diff --git a/ui/.storybook/main.ts b/ui/.storybook/main.ts index 602c7d48..a228152d 100644 --- a/ui/.storybook/main.ts +++ b/ui/.storybook/main.ts @@ -1,6 +1,6 @@ import type { StorybookConfig } from '@storybook/react-vite'; const config: StorybookConfig = { - stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'], + stories: ['../src/**/*.stories.@(js|jsx|ts|tsx)'], addons: [ '@storybook/addon-links', '@storybook/addon-essentials', diff --git a/ui/src/components/icons/ZapIcon.tsx b/ui/src/components/icons/ZapIcon.tsx index 862e3d68..f3e6bf5a 100644 --- a/ui/src/components/icons/ZapIcon.tsx +++ b/ui/src/components/icons/ZapIcon.tsx @@ -1,9 +1,21 @@ import React from 'react'; -export default function ZapIcon(props: React.SVGProps) { +type ZapIconProps = React.SVGProps & { + /** + * (optional) The color of the icon. + * Defaults to `white`. + */ + color?: string; +}; + +export default function ZapIcon(props: ZapIconProps) { return ( - + ); } diff --git a/ui/src/permissions/PermissionsDialog.tsx b/ui/src/permissions/PermissionsDialog.tsx index 968290fa..ab3cecd8 100644 --- a/ui/src/permissions/PermissionsDialog.tsx +++ b/ui/src/permissions/PermissionsDialog.tsx @@ -1,2 +1,5 @@ import React from 'react'; +export default function PermissionsDialog() { + return
PermissionsDialog
; +} diff --git a/ui/src/permissions/SummaryRow.tsx b/ui/src/permissions/SummaryRow.tsx new file mode 100644 index 00000000..6b8f48e6 --- /dev/null +++ b/ui/src/permissions/SummaryRow.tsx @@ -0,0 +1,45 @@ +import { Adjust } from '@/components/icons/Adjust'; +import ZapIcon from '@/components/icons/ZapIcon'; +import React from 'react'; + +interface SummaryRowProps { + /** + * A description of the requested permission. + * Example: "Read your contacts" + */ + description: string; + /** + * An optional warning message to display. + */ + warning: string | null; + /** + * TODO: pass in the permission object and use + * a helper function to determine which icon based on the metadata. + */ + // icon: string; +} + +/** + * A row summarizing a requested permission. + * It has the description of the permission and an optional warning icon. + */ +export default function SummaryRow({ description, warning }: SummaryRowProps) { + return ( +
+
+
+ {/* TODO: placeholder icon */} + +
+
+ {description} +
+
+ {warning ? ( +
+ +
+ ) : null} +
+ ) +} diff --git a/ui/src/permissions/WarningBanner.tsx b/ui/src/permissions/WarningBanner.tsx index c9643fc2..30256f22 100644 --- a/ui/src/permissions/WarningBanner.tsx +++ b/ui/src/permissions/WarningBanner.tsx @@ -1,21 +1,26 @@ +import React from 'react'; +import { noop } from 'lodash'; 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; + /** + * Optional click handler for the banner. + */ + onClick?: () => void; } /** * 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) { +export default function WarningBanner({ count, onClick = noop }: WarningBannerProps) { return ( -
+
{count} permissions may allow root system or identity access
diff --git a/ui/src/stories/SummaryRow.stories.tsx b/ui/src/stories/SummaryRow.stories.tsx new file mode 100644 index 00000000..4217f553 --- /dev/null +++ b/ui/src/stories/SummaryRow.stories.tsx @@ -0,0 +1,29 @@ +import SummaryRow from '@/permissions/SummaryRow'; +import type { Meta, StoryObj } from '@storybook/react'; + +const meta: Meta = { + title: 'Permissions/SummaryRow', + tags: ['autodocs'], + component: SummaryRow, + + parameters: { + layout: 'centered', + }, +}; + +export default meta; +type Story = StoryObj; + +export const HasWarning: Story = { + args: { + description: 'Access network keys or passwords', + warning: 'This permission is dangerous', + }, +}; + +export const NoWarning: Story = { + args: { + description: 'Send notifications', + warning: null, + }, +};