diff --git a/ui/src/components/icons/InfoIcon.tsx b/ui/src/components/icons/InfoIcon.tsx new file mode 100644 index 00000000..cfc1115f --- /dev/null +++ b/ui/src/components/icons/InfoIcon.tsx @@ -0,0 +1,9 @@ +import React from 'react'; + +export default function InfoIcon(props: React.SVGProps) { + return ( + + + + ); +} diff --git a/ui/src/components/icons/ZapIcon.tsx b/ui/src/components/icons/ZapIcon.tsx new file mode 100644 index 00000000..862e3d68 --- /dev/null +++ b/ui/src/components/icons/ZapIcon.tsx @@ -0,0 +1,9 @@ +import React from 'react'; + +export default function ZapIcon(props: React.SVGProps) { + return ( + + + + ); +} diff --git a/ui/src/permissions/PermissionsDialog.tsx b/ui/src/permissions/PermissionsDialog.tsx new file mode 100644 index 00000000..968290fa --- /dev/null +++ b/ui/src/permissions/PermissionsDialog.tsx @@ -0,0 +1,2 @@ +import React from 'react'; + diff --git a/ui/src/permissions/WarningBanner.tsx b/ui/src/permissions/WarningBanner.tsx new file mode 100644 index 00000000..c9643fc2 --- /dev/null +++ b/ui/src/permissions/WarningBanner.tsx @@ -0,0 +1,24 @@ +import InfoIcon from '@/components/icons/InfoIcon'; +import ZapIcon from '@/components/icons/ZapIcon'; +import React from 'react'; + +interface WarningBannerProps { + /** + * The number of permissions that may allow root system or identity access. + */ + count: number; +} + +/** + * A warning banner that conditionally appears at the bottom of the + * permissions dialog when the agent requests sensitive permissions. + */ +export default function WarningBanner({ count }: WarningBannerProps) { + return ( +
+ +
{count} permissions may allow root system or identity access
+ +
+ ); +} diff --git a/ui/src/stories/Button.stories.ts b/ui/src/stories/Button.stories.ts deleted file mode 100644 index bb3e5c10..00000000 --- a/ui/src/stories/Button.stories.ts +++ /dev/null @@ -1,47 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react'; - -import { Button } from './Button'; - -// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export -const meta: Meta = { - title: 'Example/Button', - component: Button, - // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs - tags: ['autodocs'], - // More on argTypes: https://storybook.js.org/docs/react/api/argtypes - argTypes: { - backgroundColor: { control: 'color' }, - }, -}; - -export default meta; -type Story = StoryObj; - -// More on component templates: https://storybook.js.org/docs/react/writing-stories/introduction#using-args -export const Primary: Story = { - // More on args: https://storybook.js.org/docs/react/writing-stories/args - args: { - primary: true, - label: 'Button', - }, -}; - -export const Secondary: Story = { - args: { - label: 'Button', - }, -}; - -export const Large: Story = { - args: { - size: 'large', - label: 'Button', - }, -}; - -export const Small: Story = { - args: { - size: 'small', - label: 'Button', - }, -}; diff --git a/ui/src/stories/Button.tsx b/ui/src/stories/Button.tsx deleted file mode 100644 index c33be6ec..00000000 --- a/ui/src/stories/Button.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import React from 'react'; -import './button.css'; - -interface ButtonProps { - /** - * Is this the principal call to action on the page? - */ - primary?: boolean; - /** - * What background color to use - */ - backgroundColor?: string; - /** - * How large should the button be? - */ - size?: 'small' | 'medium' | 'large'; - /** - * Button contents - */ - label: string; - /** - * Optional click handler - */ - onClick?: () => void; -} - -/** - * Primary UI component for user interaction - */ -export const Button = ({ - primary = false, - size = 'medium', - backgroundColor, - label, - ...props -}: ButtonProps) => { - const mode = primary ? 'storybook-button--primary' : 'storybook-button--secondary'; - return ( - - ); -}; diff --git a/ui/src/stories/Header.stories.ts b/ui/src/stories/Header.stories.ts deleted file mode 100644 index a68af827..00000000 --- a/ui/src/stories/Header.stories.ts +++ /dev/null @@ -1,26 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react'; -import { Header } from './Header'; - -const meta: Meta = { - title: 'Example/Header', - component: Header, - // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs - tags: ['autodocs'], - parameters: { - // More on Story layout: https://storybook.js.org/docs/react/configure/story-layout - layout: 'fullscreen', - }, -}; - -export default meta; -type Story = StoryObj; - -export const LoggedIn: Story = { - args: { - user: { - name: 'Jane Doe', - }, - }, -}; - -export const LoggedOut: Story = {}; diff --git a/ui/src/stories/Header.tsx b/ui/src/stories/Header.tsx deleted file mode 100644 index 01504601..00000000 --- a/ui/src/stories/Header.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import React from 'react'; - -import { Button } from './Button'; -import './header.css'; - -type User = { - name: string; -}; - -interface HeaderProps { - user?: User; - onLogin: () => void; - onLogout: () => void; - onCreateAccount: () => void; -} - -export const Header = ({ user, onLogin, onLogout, onCreateAccount }: HeaderProps) => ( -
-
-
- - - - - - - -

Acme

-
-
- {user ? ( - <> - - Welcome, {user.name}! - -
-
-
-); diff --git a/ui/src/stories/Introduction.mdx b/ui/src/stories/Introduction.mdx deleted file mode 100644 index ff7fc71f..00000000 --- a/ui/src/stories/Introduction.mdx +++ /dev/null @@ -1,213 +0,0 @@ -import { Meta } from '@storybook/blocks'; -import Code from './assets/code-brackets.svg'; -import Colors from './assets/colors.svg'; -import Comments from './assets/comments.svg'; -import Direction from './assets/direction.svg'; -import Flow from './assets/flow.svg'; -import Plugin from './assets/plugin.svg'; -import Repo from './assets/repo.svg'; -import StackAlt from './assets/stackalt.svg'; - - - - - -# Welcome to Storybook - -Storybook helps you build UI components in isolation from your app's business logic, data, and context. -That makes it easy to develop hard-to-reach states. Save these UI states as **stories** to revisit during development, testing, or QA. - -Browse example stories now by navigating to them in the sidebar. -View their code in the `stories` directory to learn how they work. -We recommend building UIs with a [**component-driven**](https://componentdriven.org) process starting with atomic components and ending with pages. - -
Configure
- - - -
Learn
- - - -
- TipEdit the Markdown in{' '} - stories/Introduction.stories.mdx -
diff --git a/ui/src/stories/Page.stories.ts b/ui/src/stories/Page.stories.ts deleted file mode 100644 index 52c4cb40..00000000 --- a/ui/src/stories/Page.stories.ts +++ /dev/null @@ -1,29 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react'; -import { within, userEvent } from '@storybook/testing-library'; - -import { Page } from './Page'; - -const meta: Meta = { - title: 'Example/Page', - component: Page, - parameters: { - // More on Story layout: https://storybook.js.org/docs/react/configure/story-layout - layout: 'fullscreen', - }, -}; - -export default meta; -type Story = StoryObj; - -export const LoggedOut: Story = {}; - -// More on interaction testing: https://storybook.js.org/docs/react/writing-tests/interaction-testing -export const LoggedIn: Story = { - play: async ({ canvasElement }) => { - const canvas = within(canvasElement); - const loginButton = await canvas.getByRole('button', { - name: /Log in/i, - }); - await userEvent.click(loginButton); - }, -}; diff --git a/ui/src/stories/Page.tsx b/ui/src/stories/Page.tsx deleted file mode 100644 index 994d8908..00000000 --- a/ui/src/stories/Page.tsx +++ /dev/null @@ -1,73 +0,0 @@ -import React from 'react'; - -import { Header } from './Header'; -import './page.css'; - -type User = { - name: string; -}; - -export const Page: React.FC = () => { - const [user, setUser] = React.useState(); - - return ( -
-
setUser({ name: 'Jane Doe' })} - onLogout={() => setUser(undefined)} - onCreateAccount={() => setUser({ name: 'Jane Doe' })} - /> - -
-

Pages in Storybook

-

- We recommend building UIs with a{' '} - - component-driven - {' '} - process starting with atomic components and ending with pages. -

-

- Render pages with mock data. This makes it easy to build and review page states without - needing to navigate to them in your app. Here are some handy patterns for managing page - data in Storybook: -

-
    -
  • - Use a higher-level connected component. Storybook helps you compose such data from the - "args" of child component stories -
  • -
  • - Assemble data in the page component from your services. You can mock these services out - using Storybook. -
  • -
-

- Get a guided tutorial on component-driven development at{' '} - - Storybook tutorials - - . Read more in the{' '} - - docs - - . -

-
- Tip Adjust the width of the canvas with the{' '} - - - - - - Viewports addon in the toolbar -
-
-
- ); -}; diff --git a/ui/src/stories/WarningBanner.stories.ts b/ui/src/stories/WarningBanner.stories.ts new file mode 100644 index 00000000..6f0be1c9 --- /dev/null +++ b/ui/src/stories/WarningBanner.stories.ts @@ -0,0 +1,21 @@ +import WarningBanner from '@/permissions/WarningBanner'; +import type { Meta, StoryObj } from '@storybook/react'; + +const meta: Meta = { + title: 'Permissions/WarningBanner', + tags: ['autodocs'], + component: WarningBanner, + + parameters: { + layout: 'centered', + }, +}; + +export default meta; +type Story = StoryObj; + +export const Three: Story = { + args: { + count: 3, + }, +}; diff --git a/ui/src/stories/assets/code-brackets.svg b/ui/src/stories/assets/code-brackets.svg deleted file mode 100644 index 73de9477..00000000 --- a/ui/src/stories/assets/code-brackets.svg +++ /dev/null @@ -1 +0,0 @@ -illustration/code-brackets \ No newline at end of file diff --git a/ui/src/stories/assets/colors.svg b/ui/src/stories/assets/colors.svg deleted file mode 100644 index 17d58d51..00000000 --- a/ui/src/stories/assets/colors.svg +++ /dev/null @@ -1 +0,0 @@ -illustration/colors \ No newline at end of file diff --git a/ui/src/stories/assets/comments.svg b/ui/src/stories/assets/comments.svg deleted file mode 100644 index 6493a139..00000000 --- a/ui/src/stories/assets/comments.svg +++ /dev/null @@ -1 +0,0 @@ -illustration/comments \ No newline at end of file diff --git a/ui/src/stories/assets/direction.svg b/ui/src/stories/assets/direction.svg deleted file mode 100644 index 65676ac2..00000000 --- a/ui/src/stories/assets/direction.svg +++ /dev/null @@ -1 +0,0 @@ -illustration/direction \ No newline at end of file diff --git a/ui/src/stories/assets/flow.svg b/ui/src/stories/assets/flow.svg deleted file mode 100644 index 8ac27db4..00000000 --- a/ui/src/stories/assets/flow.svg +++ /dev/null @@ -1 +0,0 @@ -illustration/flow \ No newline at end of file diff --git a/ui/src/stories/assets/plugin.svg b/ui/src/stories/assets/plugin.svg deleted file mode 100644 index 29e5c690..00000000 --- a/ui/src/stories/assets/plugin.svg +++ /dev/null @@ -1 +0,0 @@ -illustration/plugin \ No newline at end of file diff --git a/ui/src/stories/assets/repo.svg b/ui/src/stories/assets/repo.svg deleted file mode 100644 index f386ee90..00000000 --- a/ui/src/stories/assets/repo.svg +++ /dev/null @@ -1 +0,0 @@ -illustration/repo \ No newline at end of file diff --git a/ui/src/stories/assets/stackalt.svg b/ui/src/stories/assets/stackalt.svg deleted file mode 100644 index 9b7ad274..00000000 --- a/ui/src/stories/assets/stackalt.svg +++ /dev/null @@ -1 +0,0 @@ -illustration/stackalt \ No newline at end of file diff --git a/ui/src/stories/button.css b/ui/src/stories/button.css deleted file mode 100644 index dc91dc76..00000000 --- a/ui/src/stories/button.css +++ /dev/null @@ -1,30 +0,0 @@ -.storybook-button { - font-family: 'Nunito Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; - font-weight: 700; - border: 0; - border-radius: 3em; - cursor: pointer; - display: inline-block; - line-height: 1; -} -.storybook-button--primary { - color: white; - background-color: #1ea7fd; -} -.storybook-button--secondary { - color: #333; - background-color: transparent; - box-shadow: rgba(0, 0, 0, 0.15) 0px 0px 0px 1px inset; -} -.storybook-button--small { - font-size: 12px; - padding: 10px 16px; -} -.storybook-button--medium { - font-size: 14px; - padding: 11px 20px; -} -.storybook-button--large { - font-size: 16px; - padding: 12px 24px; -} diff --git a/ui/src/stories/header.css b/ui/src/stories/header.css deleted file mode 100644 index d9a70528..00000000 --- a/ui/src/stories/header.css +++ /dev/null @@ -1,32 +0,0 @@ -.storybook-header { - font-family: 'Nunito Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; - border-bottom: 1px solid rgba(0, 0, 0, 0.1); - padding: 15px 20px; - display: flex; - align-items: center; - justify-content: space-between; -} - -.storybook-header svg { - display: inline-block; - vertical-align: top; -} - -.storybook-header h1 { - font-weight: 700; - font-size: 20px; - line-height: 1; - margin: 6px 0 6px 10px; - display: inline-block; - vertical-align: top; -} - -.storybook-header button + button { - margin-left: 10px; -} - -.storybook-header .welcome { - color: #333; - font-size: 14px; - margin-right: 10px; -} diff --git a/ui/src/stories/page.css b/ui/src/stories/page.css deleted file mode 100644 index 098dad11..00000000 --- a/ui/src/stories/page.css +++ /dev/null @@ -1,69 +0,0 @@ -.storybook-page { - font-family: 'Nunito Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; - font-size: 14px; - line-height: 24px; - padding: 48px 20px; - margin: 0 auto; - max-width: 600px; - color: #333; -} - -.storybook-page h2 { - font-weight: 700; - font-size: 32px; - line-height: 1; - margin: 0 0 4px; - display: inline-block; - vertical-align: top; -} - -.storybook-page p { - margin: 1em 0; -} - -.storybook-page a { - text-decoration: none; - color: #1ea7fd; -} - -.storybook-page ul { - padding-left: 30px; - margin: 1em 0; -} - -.storybook-page li { - margin-bottom: 8px; -} - -.storybook-page .tip { - display: inline-block; - border-radius: 1em; - font-size: 11px; - line-height: 12px; - font-weight: 700; - background: #e7fdd8; - color: #66bf3c; - padding: 4px 12px; - margin-right: 10px; - vertical-align: top; -} - -.storybook-page .tip-wrapper { - font-size: 13px; - line-height: 20px; - margin-top: 40px; - margin-bottom: 40px; -} - -.storybook-page .tip-wrapper svg { - display: inline-block; - height: 12px; - width: 12px; - margin-right: 4px; - vertical-align: top; - margin-top: 3px; -} - -.storybook-page .tip-wrapper svg path { - fill: #1ea7fd; -}