Skip to content
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Canvas, Meta } from '@storybook/blocks';
import { Canvas, Meta, Source } from '@storybook/blocks';
import * as ShowcaseStories from './CitizenClaimWidgetShowcase.stories';
import { DocsCallout, DocsCard, DocsGrid, DocsPage, DocsSection } from '../docs/DocsLayout';

Expand All @@ -11,11 +11,35 @@ import { DocsCallout, DocsCard, DocsGrid, DocsPage, DocsSection } from '../docs/
>
<DocsSection
title="Manual wallet showcase"
description="Use this story when reviewing the widget in a browser that has an injected wallet available."
description="Use this story when reviewing the widget in a browser that has an injected wallet available. Use the Controls panel below the canvas to preview `defaultTheme` and a sample `themeOverrides` brand preset."
>
<Canvas of={ShowcaseStories.InjectedWallet} />
</DocsSection>

<DocsSection
title="How to mount it"
description="Keep the host contract narrow. The widget expects a provider and optional theming inputs."
>
<Source
dark
language="tsx"
code={`import { CitizenClaimWidget } from '@goodwidget/citizen-claim-widget'
import { MiniAppShell } from '@goodwidget/ui'

export function ClaimPanel({ provider }: { provider?: unknown }) {
return (
<MiniAppShell title="GoodDollar">
<CitizenClaimWidget
provider={provider}
environment="production"
defaultTheme="dark"
/>
</MiniAppShell>
)
}`}
/>
</DocsSection>

<DocsSection
title="QA coverage"
description="Use the QA demo when you need reproducible custodial state, Playwright screenshots, or fixture-driven debugging. Keep this page focused on the product-facing integration flow."
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,41 @@
import type { Meta, StoryObj } from '@storybook/react'
import { CitizenClaimWidget } from '@goodwidget/citizen-claim-widget'
import { CustodialLocalFixtureStory } from '../helpers/citizenClaimWidgetStories'
import { BRAND_PRESET_OPTIONS, brandPresetOverrides, type BrandPreset } from '../helpers/themeOverridePresets'

const meta: Meta<typeof CitizenClaimWidget> = {
interface CitizenClaimWidgetQAArgs {
defaultTheme: 'light' | 'dark'
brandPreset: BrandPreset
}

const meta: Meta<CitizenClaimWidgetQAArgs> = {
title: 'QA/CitizenClaimWidget/Runtime Fixtures',
component: CitizenClaimWidget,
tags: ['autodocs', 'qa'],
parameters: { layout: 'padded' },
argTypes: {
defaultTheme: {
control: 'radio',
options: ['dark', 'light'],
description: 'Base theme applied via the widget’s own defaultTheme prop.',
},
brandPreset: {
control: 'select',
options: BRAND_PRESET_OPTIONS,
description: 'Sample host-branding themeOverrides preset.',
},
},
args: {
defaultTheme: 'dark',
brandPreset: 'None',
},
}

export default meta
type Story = StoryObj<typeof meta>
type Story = StoryObj<CitizenClaimWidgetQAArgs>

export const CustodialLocalFixture: Story = {
render: () => <CustodialLocalFixtureStory />,
render: ({ defaultTheme, brandPreset }) => (
<CustodialLocalFixtureStory defaultTheme={defaultTheme} themeOverrides={brandPresetOverrides(brandPreset)} />
),
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,41 @@
import type { Meta, StoryObj } from '@storybook/react'
import { CitizenClaimWidget } from '@goodwidget/citizen-claim-widget'
import { InjectedWalletStory } from '../helpers/citizenClaimWidgetStories'
import { BRAND_PRESET_OPTIONS, brandPresetOverrides, type BrandPreset } from '../helpers/themeOverridePresets'

const meta: Meta<typeof CitizenClaimWidget> = {
interface CitizenClaimWidgetStoryArgs {
defaultTheme: 'light' | 'dark'
brandPreset: BrandPreset
}

const meta: Meta<CitizenClaimWidgetStoryArgs> = {
title: 'Widgets/CitizenClaimWidget/Showcase',
component: CitizenClaimWidget,
tags: ['integrator', 'manual', 'showcase'],
parameters: { layout: 'padded' },
argTypes: {
defaultTheme: {
control: 'radio',
options: ['dark', 'light'],
description: 'Base theme applied via the widget’s own defaultTheme prop.',
},
brandPreset: {
control: 'select',
options: BRAND_PRESET_OPTIONS,
description: 'Sample host-branding themeOverrides preset.',
},
},
args: {
defaultTheme: 'dark',
brandPreset: 'None',
},
}

export default meta
type Story = StoryObj<typeof meta>
type Story = StoryObj<CitizenClaimWidgetStoryArgs>

export const InjectedWallet: Story = {
render: () => <InjectedWalletStory />,
render: ({ defaultTheme, brandPreset }) => (
<InjectedWalletStory defaultTheme={defaultTheme} themeOverrides={brandPresetOverrides(brandPreset)} />
),
}
58 changes: 45 additions & 13 deletions examples/storybook/src/stories/claim-widget/ClaimWidget.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@
*/
import type { Meta, StoryObj } from '@storybook/react'
import { ClaimWidget } from '@goodwidget/claim-widget-theme-demo'
import {
ClaimWidgetStoryCanvas,
cobaltOverrides,
tealOverrides,
} from '../helpers/claimWidgetStories'
import { ClaimWidgetStoryCanvas } from '../helpers/claimWidgetStories'
import { BRAND_PRESET_OPTIONS, brandPresetOverrides, type BrandPreset } from '../helpers/themeOverridePresets'

const meta: Meta<typeof ClaimWidget> = {
interface ClaimWidgetStoryArgs {
defaultTheme: 'light' | 'dark'
brandPreset: BrandPreset
}

const meta: Meta<ClaimWidgetStoryArgs> = {
title: 'Widgets/ClaimWidget Theme Demo/Showcase',
component: ClaimWidget,
tags: ['integrator', 'showcase'],
Expand All @@ -22,33 +24,63 @@ const meta: Meta<typeof ClaimWidget> = {
disableProvider: true,
useShell: false,
},
argTypes: {
defaultTheme: {
control: 'radio',
options: ['dark', 'light'],
description: 'Base theme applied via the widget’s own defaultTheme prop.',
},
brandPreset: {
control: 'select',
options: BRAND_PRESET_OPTIONS,
description: 'Sample host-branding themeOverrides preset.',
},
},
}
export default meta

type Story = StoryObj<typeof ClaimWidget>
type Story = StoryObj<ClaimWidgetStoryArgs>

export const Default: Story = {
render: () => <ClaimWidgetStoryCanvas dataTestId="ClaimWidget-default" />,
args: { defaultTheme: 'dark', brandPreset: 'None' },
render: ({ defaultTheme, brandPreset }) => (
<ClaimWidgetStoryCanvas
dataTestId="ClaimWidget-default"
defaultTheme={defaultTheme}
themeOverrides={brandPresetOverrides(brandPreset)}
/>
),
}

export const LightTheme: Story = {
render: () => <ClaimWidgetStoryCanvas dataTestId="ClaimWidget-light" defaultTheme="light" />,
args: { defaultTheme: 'light', brandPreset: 'None' },
render: ({ defaultTheme, brandPreset }) => (
<ClaimWidgetStoryCanvas
dataTestId="ClaimWidget-light"
defaultTheme={defaultTheme}
themeOverrides={brandPresetOverrides(brandPreset)}
/>
),
}

export const CobaltBrand: Story = {
render: () => (
args: { defaultTheme: 'dark', brandPreset: 'Cobalt' },
render: ({ defaultTheme, brandPreset }) => (
<ClaimWidgetStoryCanvas
dataTestId="ClaimWidget-cobalt"
themeOverrides={cobaltOverrides}
defaultTheme={defaultTheme}
themeOverrides={brandPresetOverrides(brandPreset)}
/>
),
}

export const TealBrand: Story = {
render: () => (
args: { defaultTheme: 'dark', brandPreset: 'Teal' },
render: ({ defaultTheme, brandPreset }) => (
<ClaimWidgetStoryCanvas
dataTestId="ClaimWidget-teal"
themeOverrides={tealOverrides}
defaultTheme={defaultTheme}
themeOverrides={brandPresetOverrides(brandPreset)}
/>
),
}
23 changes: 22 additions & 1 deletion examples/storybook/src/stories/design-system/Card.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,18 @@ const meta: Meta<typeof Card> = {
component: Card,
tags: ['autodocs', 'showcase'],
parameters: { layout: 'padded' },
argTypes: {
elevated: { control: 'boolean', description: 'Applies the elevated shadow variant' },
outlined: { control: 'boolean', description: 'Applies the outlined border variant' },
backgroundColor: { control: 'color', description: 'Inline background color override' },
borderColor: { control: 'color', description: 'Inline border color override' },
},
}
export default meta
type Story = StoryObj<typeof Card>

/** Default Card using base theme values. */
/** Default Card using base theme values. Fixed reference story — the Controls panel is
* inert here; use "Controllable" below to drive props live. */
export const Default: Story = {
render: () => (
<Card data-testid="Card-default" style={{ width: 320 }}>
Expand Down Expand Up @@ -59,3 +66,17 @@ export const InlineStyled: Story = {
</Card>
),
}

/** Controllable instance — edit args in the Controls panel. */
export const Controllable: Story = {
args: {
elevated: true,
outlined: false,
},
render: (args) => (
<Card data-testid="Card-controllable" style={{ width: 320 }} {...args}>
<Heading level={5}>Controllable Card</Heading>
<Text>Use the Controls panel to toggle variants and colors.</Text>
</Card>
),
}
38 changes: 37 additions & 1 deletion examples/storybook/src/stories/design-system/Drawer.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,19 @@ const meta: Meta = {
title: 'Design System/Primitives/Drawer',
tags: ['autodocs', 'showcase'],
parameters: { layout: 'padded' },
argTypes: {
height: {
control: 'radio',
options: ['half', 'full'],
description: 'How much of the viewport the Drawer covers when open',
},
},
}
export default meta
type Story = StoryObj

/** Controlled Drawer triggered by a button. */
/** Controlled Drawer triggered by a button. Fixed reference story (has an interaction
* test) — the Controls panel is inert here; use "Controllable" below to drive props live. */
export const Default: Story = {
render: () => {
// eslint-disable-next-line react-hooks/rules-of-hooks
Expand Down Expand Up @@ -49,3 +57,31 @@ export const Default: Story = {
await expect(await screen.findByRole('button', { name: /close/i })).toBeVisible()
},
}

/** Controllable instance — edit the `height` arg, then click "Open Drawer". */
export const Controllable: Story = {
args: {
height: 'half',
},
render: ({ height }: { height?: 'half' | 'full' }) => {
// eslint-disable-next-line react-hooks/rules-of-hooks
const [open, setOpen] = useState(false)
return (
<Card data-testid="Drawer-controllable-trigger" style={{ width: 320 }}>
<Heading level={5}>Trigger</Heading>
<Text>A Drawer slides up from the bottom and overlays the content.</Text>
<Button fullWidth onPress={() => setOpen(true)}>
<ButtonText>Open Drawer</ButtonText>
</Button>
<Drawer open={open} onClose={() => setOpen(false)} height={height}>
<YStack gap="$4">
<Text>Drawer content. Close via the button below or tap outside.</Text>
<Button fullWidth onPress={() => setOpen(false)}>
<ButtonText>Close</ButtonText>
</Button>
</YStack>
</Drawer>
</Card>
)
},
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,16 @@ const meta: Meta<typeof GlowCard> = {
component: GlowCard,
tags: ['autodocs', 'showcase'],
parameters: { layout: 'padded' },
argTypes: {
elevated: { control: 'boolean', description: 'Applies the elevated shadow variant' },
outlined: { control: 'boolean', description: 'Applies the outlined border variant' },
},
}
export default meta
type Story = StoryObj<typeof GlowCard>

/** Default GlowCard with theme-driven glow colour. */
/** Default GlowCard with theme-driven glow colour. Fixed reference story — the Controls
* panel is inert here; use "Controllable" below to drive props live. */
export const Default: Story = {
render: () => (
<GlowCard data-testid="GlowCard-default" style={{ width: 320 }}>
Expand All @@ -29,3 +34,17 @@ export const Default: Story = {
</GlowCard>
),
}

/** Controllable instance — edit args in the Controls panel. */
export const Controllable: Story = {
args: {
elevated: true,
outlined: false,
},
render: (args) => (
<GlowCard data-testid="GlowCard-controllable" style={{ width: 320 }} {...args}>
<Heading level={4}>Controllable GlowCard</Heading>
<Text>Use the Controls panel to toggle variants.</Text>
</GlowCard>
),
}
Loading