Skip to content

[PLAN] Widget showcase in storybook #252

Open

Description

@goodbounties-nanoclaw-agent

Plans execution for #250 (Olivia / 0xOlivanode, "[Feature] Widget showcase in storybook"). Preserves #250's content unchanged.

Approved by Olivia (Bounty Lead) on 2026-10-14, contingent on the six-point revision below landing — it has. Executed under job-gw250-exec; PR #253 opened.

Reference files

GoodDollar/GoodWidget (verified against main @ 291142f)

Reference pattern (already aligned, not touched by this plan):

  • examples/storybook/src/stories/streaming-widget/{StreamingWidget.stories.tsx, StreamingWidgetThemeOverrides.stories.tsx, StreamingWidgetQA.stories.tsx, StreamingWidget.mdx}
  • examples/storybook/src/stories/staking-migration-widget/{...same 4 files...}

Shared Storybook helpers to reuse as-is:

  • examples/storybook/src/stories/helpers/themeOverridePresets.ts — brand preset system (BRAND_PRESET_OPTIONS, brandPresetOverrides), widget-agnostic
  • examples/storybook/src/stories/helpers/withDefaultPreset.tsx — Theme overrides decorator
  • examples/storybook/src/stories/docs/DocsLayout.tsx — DocsPage/DocsSection/DocsCard/DocsGrid/DocsCallout/DocsList, used by every MDX and Theme overrides file

Per-widget targets (current → target state, itemized in Execution plan below). Revised: new Theme overrides files in this plan wire controls only against primitive targets (dark_Card/light_Card, dark_Button/light_Button from packages/ui) — the widget-specific named targets noted below already exist in each widget's own source (pre-dating this bounty) but do not get dedicated story controls this round; that finer-grained coverage is a follow-up, not a gap:

  • citizen-claim-widget/{CitizenClaimWidgetShowcase.stories.tsx, CitizenClaimWidgetQA.stories.tsx, CitizenClaimWidget.mdx} + packages/citizen-claim-widget/src/CitizenClaimWidget.tsx (existing named theme targets, not newly created, not individually exposed this round: ClaimCard, ClaimActionGlow, ClaimActionRing, ClaimActionInner, TokenAmountText)
  • goodreserve-widget/GoodReserveWidget.stories.tsx (single flat file, 22 stories, no MDX yet) + packages/goodreserve-widget/src/ReserveSwapView.tsx (existing named theme targets, not newly created, not individually exposed this round: ReserveSwapShell, ReserveAmountCard, ReserveSurface, ReserveSurfaceInner, ReserveDetailsTable, ReserveTokenBadge, ReserveSwapDirectionButton, ReserveSettingsButton, ReserveSuccessIcon, ReserveConfirmToBadge)
  • governance-widget/{GovernanceWidgetShowcase.stories.tsx, GovernanceWidgetQA.stories.tsx, GovernanceWidgetThemeOverrides.stories.tsx (already exists, reference only), GovernanceOnboarding.stories.tsx, GovernanceWidget.mdx}
  • ai-credits-widget/{AiCreditsWidgetShowcase.stories.tsx, AiCreditsWidgetQA.stories.tsx, AiCreditsWidget.mdx} + packages/ai-credits-widget/src/components/theme/cards.ts (existing named theme targets, not newly created, not individually exposed this round: AiCreditsStatusNotice, BonusBadgeFrame)
  • superfluid-campaign-widget/{SuperfluidCampaignWidget.stories.tsx, SuperfluidCampaignWidgetQA.stories.tsx, SuperfluidCampaignWidgetApiContracts.stories.tsx, SuperfluidCampaignWidget.mdx} — has no named theme-component module at all (unlike the three above, there is no pre-existing shared.tsx-style target to point at); this is a real design-system gap, not just reduced story coverage this round — see New components / gaps logging below.
  • gooddata-widget/GoodDataWidgetQA.stories.tsx (no MDX yet) + packages/gooddata-widget/src/{GoodDataWidget.tsx, dashboards/aiCredits/AiCreditsDashboard.tsx, dashboards/registry.ts}

No-op risk check (resolves Olivia's PR #73 concern), confirmed via packages/ui/src/presets.ts: ClaimCard, ClaimActionButton, and ClaimActionGlow already have dedicated light_*/dark_* presets of their own, so a plain dark_Card/dark_Button override is a no-op against CitizenClaimWidget's default/most-prominent claim surface, which renders through those named components instead — see that widget's Required states entry below for how the new Theme overrides file accounts for this. ReserveSwapView's family (GoodReserveWidget), AiCreditsStatusNotice/BonusBadgeFrame (AiCreditsWidget), and SuperfluidCampaignWidget (no named components at all) have no dedicated presets, so they correctly fall back to/cascade from Card's and Button's own theme — dark_Card/dark_Button overrides apply and visibly change those widgets as expected.

dark_/light_ pairing (resolves Olivia's second PR #73 concern): every new Theme overrides file in this plan wires a matching light_* control for every dark_* control it wires. Both existing reference files were re-checked and confirmed to only wire dark_* controls as live controls — StreamingWidgetThemeOverrides.stories.tsx (dark_Button/dark_StreamRow/dark_BalanceCard) and StakingMigrationWidgetThemeOverrides.stories.tsx (dark_ClaimCard/dark_ClaimActionGlow/dark_ClaimActionRing); light_* names appear only inside their documentation callout text, never as an actual wired control. New files in this bounty deliberately deviate from copying that part of the pattern. The two existing files' own light/dark gap is logged (not fixed here) under "[BountyPrep] Storybook: missing primitives and design system gaps" — see New components / gaps logging below.

Playwright specs needing hardcoded story-id updates (tests/widgets/**/*.spec.ts, testDir confirmed in playwright.config.ts):

  • tests/widgets/governance-widget/onboarding.spec.ts — 8 refs to widgets-governanceonboarding--* (title moves to the QA namespace)
  • tests/widgets/superfluid-campaign-widget/states.spec.ts — 2 refs to widgets-superfluidcampaignwidget-api-contracts--* (title moves to QA)
  • tests/widgets/gooddata-widget/states.spec.ts — 5 refs to qa-aicreditsdashboard-runtime-fixtures--* (title renames to qa-gooddatawidget-runtime-fixtures--*)
  • tests/widgets/goodreserve-widget/states.spec.ts — 16 refs to widgets-goodreservewidget--* (file splits into Showcase/QA titles)
  • tests/widgets/ai-credits-widget/states.spec.ts — verified no spec references the Showcase MockBackend story id directly, so moving it to QA needs no spec edit; re-confirm during execution in case a new QA id collides with an existing fixture name.

GoodDollar/GoodProtocol

  • releases/deployment.json (repo root) — per-environment contract deployment map, 28 environment keys total. Relevant entries for the Celo-track environments these widgets actually use:
    • development-celo: GoodDaoHouses (+FlowSplitter/PoolId/Pool), MentoReserve, GoodDollarStaking, Identity, UBIScheme, ClaimersDistribution
    • staging-celo: MentoReserve, GoodDollarStaking, Identity, UBIScheme, ClaimersDistribution — no GoodDaoHouses
    • production-celo: MentoReserve, Identity, UBIScheme — no GoodDaoHouses, no GoodDollarStaking
    • No Celo environment has Superfluid contracts — streaming-widget/superfluid-campaign-widget depend on the Superfluid SDK/subgraph, not a GoodProtocol Celo deployment entry
    • ai-credits-widget and gooddata-widget: no matching contract entries at all anywhere in the file — both are off-chain/API-backed, not gated by this file
    • Environment options rule (revised): every Showcase environment control offers development/production only, never staging — even on widgets where a staging-celo entry exists for the relevant contract (e.g. MentoReserve, Identity, UBIScheme all have staging-celo entries, but staging is never offered as a selectable option). An environment is only offered if both (a) the widget's contract/SDK actually supports that value, and (b) the contract is deployed per this file for that environment.
    • Revised further — a control must offer a genuine choice and the widget must already expose the prop: GoodReserveWidget has no environment prop anywhere in its source (confirmed via grep — zero matches), so no control is added for it; adding one would require a packages/goodreserve-widget code change, which this bounty does not make (see Required states below — logged as a gap instead). GovernanceWidget's only deployed environment for GoodDaoHouses is development-celo, so a single-value environment control is a pointless UI element — its control is dropped in favor of a static "development only" note in GovernanceWidget.mdx. CitizenClaimWidget already has an environment prop today (confirmed via grep: packages/citizen-claim-widget/src/CitizenClaimWidget.tsx), and Identity/UBIScheme are deployed on both development-celo and production-celo, so it remains the only widget that gets a genuine development/production Showcase control.

Required states, flows, and behaviors

Restates #250's per-widget breakdown against the verified current repo state; bolded notes are corrections/refinements found during this scan.

  1. CitizenClaimWidget — Showcase/QA split already correct, no changes there. Add a Theme overrides file wiring controls against the primitive dark_Card/dark_Button/light_Card/light_Button targets (not the widget's existing ClaimCard/ClaimActionGlow/ClaimActionRing/ClaimActionInner/TokenAmountText named targets — see Reference files above), following StreamingWidget's pattern for structure only. No-op risk, confirmed and accounted for: packages/ui/src/presets.ts already defines dedicated ClaimCard/ClaimActionButton/ClaimActionGlow presets, so a dark_Card/dark_Button override is a no-op against the default claim-tab surface, which renders through those named components, not the primitives. The new story instead demonstrates the override against confirmed plain-primitive surfaces that are actually reachable and do fall back to Card/Button's theme: the plain <Button> on the identity-verification step (CitizenClaimWidget.tsx ~line 401) and the plain <Card> on the Invite Rewards/News tab placeholder (~line 625) — and visibly changes when toggled, not just compiles. Add an environment control to Showcase: Identity + UBIScheme are deployed on development-celo and production-celo (staging is never offered, per the revised environments rule), so offer development/production — currently the story helper hardcodes environment: 'development' with no control at all.
  2. GoodReserveWidget — single flat file (title: 'Widgets/GoodReserveWidget', no /Showcase suffix) must split. 19 mocked/fixture stories (NoProvider, SdkInitializing, UnsupportedChain, IdleBuy, AmountEditing, QuoteLoading, QuoteReadyBuy, QuoteReadyBuyLightTheme, QuoteReadySell, QuoteReadyXdc, QuoteError, QuoteRefreshing, InsufficientBalance, SlippageSelection, ConfirmDialog, ApprovalPending, SwapPending, SwapSuccess, SwapError) move to QA/GoodReserveWidget/Runtime Fixtures unchanged in behavior (title/file move only). 3 live stories (Interactive, InjectedWallet, LiveWallet) move to Widgets/GoodReserveWidget/Showcase. New Theme overrides file wiring controls against the primitive dark_Card/dark_Button/light_Card/light_Button targets (not the widget's existing 9 ReserveSwapView named targets, which have no dedicated presets and correctly cascade from Card/Button's theme — see Reference files above). No MDX exists today — net new. Revised: no environment control, and no packages/ edit. The widget has no environment prop anywhere in its source (confirmed via grep — zero matches), so per this plan's own rule (a control is only added where the widget's prop already supports the value) it's unsupported; adding one would require modifying packages/goodreserve-widget, which is out of scope for this bounty. packages/goodreserve-widget is not touched at all. Log "GoodReserveWidget has no environment prop" in "[BountyPrep] Storybook: missing primitives and design system gaps" instead of building it here.
  3. GovernanceWidget — GovernanceOnboarding.stories.tsx (currently title: 'Widgets/GovernanceOnboarding', 15 stories, all mocked/deterministic step-flow fixtures, wraps the distinct GovernanceOnboardingWidget internal-flow component, not the top-level widget) moves into the QA namespace, as originally planned. Revised per maintainer decision (overrides this plan's earlier Demo finding): Demo, Injected Wallet, and Custodial Wallet all stay in Showcase. Demo is genuinely mocked (static adapterFactory state, no provider or contract) and would move to QA under the plain mocked/live rule, but Laurence has made an explicit maintainer-policy exception keeping it in Showcase alongside the two wallet stories — this is not a reclassification of Demo as live, it's a deliberate, logged exception to the "mocks go to QA" rule. Custodial Wallet (createCustodialEip1193Provider() against the same real dev-celo GoodDaoHouses contract as InjectedWallet) also stays, and remains hidden from the Storybook sidebar for lack of a "dev" tag — that's existing behavior, left as-is, not something this bounty fixes. Theme overrides file already exists, no new file needed — just confirm the onboarding move doesn't orphan a reference inside it. Revised: no environment control. GoodDaoHouses is deployed on development-celo only, so an environment control here would offer a single, unchangeable option — a pointless UI element. Showcase gets no environment-switcher control (remove it if one exists today; do not add one if it doesn't); instead, add a plain note to GovernanceWidget.mdx stating the widget currently only operates against the development-celo deployment.
  4. AiCreditsWidget — MockBackend ("Mock Backend (browser wallet)") moves from Showcase to QA as a new fixture story (no existing QA equivalent to merge into — this relocates the only copy). Add a Theme overrides file wiring controls against the primitive dark_Card/dark_Button/light_Card/light_Button targets (not the widget's existing AiCreditsStatusNotice/BonusBadgeFrame named targets, which have no dedicated presets and correctly cascade from Card/Button's theme — see Reference files above, confirmed via packages/ui/src/presets.ts). No GoodProtocol contract dependency (off-chain/API-backed per deployment.json) — no environment control needed unless execution finds a real backend-environment concept the widget already exposes; if none exists, leave as-is rather than inventing one, consistent with [Feature] Widget showcase in storybook #250's "most widgets support development/production only" being conditional on the widget actually having that axis.
  5. SuperfluidCampaignWidget — SuperfluidCampaignWidgetApiContracts.stories.tsx (currently title: 'Widgets/SuperfluidCampaignWidget/API Contracts', both stories are Playwright response-interception contract tests) moves to QA/SuperfluidCampaignWidget/API Contracts. New Theme overrides file wiring controls against the primitive dark_Card/dark_Button/light_Card/light_Button targets only, confirmed to cascade correctly since the widget has no named theme-component module at all — no new shared.tsx named-component module is created for this bounty (revised: dropped the earlier CampaignHeader/RewardPoolSection/LeaderboardView/ActionCard extraction). This leaves the widget with no granular theme-targetable sub-components, unlike its siblings that already have one — log that gap in "[BountyPrep] Storybook: missing primitives and design system gaps" rather than building it here. No GoodProtocol contract dependency on Celo — no environment control.
  6. GoodData widget — QA title renames from QA/AiCreditsDashboard/Runtime Fixtures to QA/GoodDataWidget/Runtime Fixtures (matches the actual package name @goodwidget/gooddata-widget; AiCreditsDashboard is just the one dashboard currently registered inside the generic GoodDataWidget shell). Add a new Widgets/GoodDataWidget/Showcase entry built on the real aiCredits connector's live data-fetch mode (paralleling the existing Live/LiveUnavailable QA fixture pair, but using the real connector instead of mocks) — this widget's "live" means live API data, not a wallet connection, matching how SuperfluidCampaignWidget's live stories work. No MDX exists today — net new. No GoodProtocol contract dependency — no environment control. New Theme overrides file, scoped to Button only: add GoodDataWidgetThemeOverrides.stories.tsx wiring controls against the primitive dark_Button/light_Button targets only — confirmed via grep -rln "Card" packages/gooddata-widget/src (zero matches) that GoodDataWidget renders Button (pagination and data-source-toggle controls) but never renders Card anywhere in its source, so a dark_Card/light_Card control would be a no-op; the file includes a short note explaining the Card exemption, consistent with the no-op acceptance criterion below rather than a silent omission. Vercel/CORS verification (resolves Olivia's live-connector concern): confirmed live, via a direct request to the aiCredits connector's backing Cloudflare Worker (https://gooddollar-antseed-integration.goodworker.workers.dev) with a simulated Vercel-preview Origin header, that it responds with Access-Control-Allow-Origin: * — the connector's browser fetch will succeed from a Vercel preview deployment, not just locally. The live-connector Showcase approach can proceed as planned; no workaround needed.
  7. ClaimWidget Theme Demo / StreamingWidget — no changes (per [Feature] Widget showcase in storybook #250). StakingMigrationWidget — re-checked under the revised no-staging rule, definitive answer: stays out of scope, unchanged. Verified live against packages/staking-migration-widget/src/StakingMigrationWidget.tsx: the widget has no environment prop or concept anywhere in its source (confirmed via grep — zero matches for "environment"); it hardcodes a Celo→Fuse chain switch (actions.switchToFuse()) and exposes only migrationApiBaseUrl as its external-config axis, which is an API endpoint, not a GoodProtocol Celo per-environment contract deployment. This is architecturally different from GoodReserveWidget's gap: GoodReserveWidget is missing an environment prop for a contract (MentoReserve) that genuinely varies by GoodProtocol Celo environment, so adding one is an identified widget-code-change dependency; StakingMigrationWidget's chain (Fuse) and axis (migrationApiBaseUrl) sit entirely outside the Celo-track deployment.json gating this plan uses, so there is no missing environment axis to add — it was never applicable, and the staging-exclusion rule change doesn't affect that conclusion.

Confirmed: zero packages/ edits anywhere in this bounty. With GoodReserveWidget's environment control dropped (item 2) and GovernanceWidget's dropped (item 3), CitizenClaimWidget is the only widget retaining a genuine environment control, and packages/citizen-claim-widget already has the environment prop today (confirmed via grep), so wiring its Showcase control needs no widget-code change either. No item in this plan requires modifying packages/goodreserve-widget, packages/citizen-claim-widget, packages/governance-widget, packages/ai-credits-widget, packages/superfluid-campaign-widget, packages/gooddata-widget, or packages/ui — every change in this plan is confined to examples/storybook/ (new/moved story and MDX files) and tests/widgets/ (story-id updates).

New components to create (package placement)

  • Environment-switcher control (new). No existing pattern anywhere in examples/storybook/src/stories/helpers/ exposes environment as a Storybook arg — the story helper currently hardcodes it internally (citizenClaimWidgetStories.tsx:190). Revised scope: CitizenClaimWidget is the only widget that gets this control — GoodReserveWidget has no environment prop to wire it to, and GovernanceWidget's single deployed value makes a control pointless (see Required states above). Needs: a shared environment argType/options source, fixed to development/production only (staging is never an option, revised rule — see Reference files above). Placement: new file under examples/storybook/src/stories/helpers/ (e.g. environmentOptions.ts), not packages/ui. This is Storybook-only dev tooling for selecting which GoodWidgetProvider environment= value a preview uses — never shipped to a widget consumer, so it does not belong in the reusable runtime design-system package.
  • Theme overrides scaffolding — no new shared component needed. Revised: no new named theme-target components are created in any widget package for this bounty. Every widget already supports the primitive dark_Card/dark_Button/light_Card/light_Button theme targets from packages/ui; the five new Theme overrides files in this plan (CitizenClaimWidget, GoodReserveWidget, AiCreditsWidget, SuperfluidCampaignWidget, GoodDataWidget) wire controls against those primitives only — each dark_* control paired with a matching light_* control, which deliberately deviates from the existing reference files' dark-only wiring (see Reference files above) — following the CodeBlock/DocsCallout copy-adapt pattern (Streaming, Governance) for structure but not for widget-specific named targets. GoodDataWidget's file is Button-only (no Card control — the widget renders no Card anywhere in its source, confirmed via grep). Finer per-widget named-target extraction (CitizenClaimWidget's ClaimCard family, GoodReserveWidget's ReserveSwapView family, AiCreditsWidget's AiCreditsStatusNotice/BonusBadgeFrame, and a SuperfluidCampaignWidget shared.tsx) is explicitly deferred to a follow-up, not built here.
  • No new packages/ui primitives, and no new widget-package named theme-target components, are created for anything in this plan — nothing here is blocked on a missing design-system primitive, and no new named theme targets are introduced. Log gaps surfaced during execution — including SuperfluidCampaignWidget's lack of any named theme-component module (it alone, unlike its siblings, has no pre-existing shared.tsx-style target to fall back on even for a future pass), GoodReserveWidget's missing environment prop (the widget-code change this bounty deliberately does not make), the existing StreamingWidgetThemeOverrides.stories.tsx/StakingMigrationWidgetThemeOverrides.stories.tsx files' own dark-only wiring (pre-dating this bounty, same class of gap as PR Storybook polish: interactive theming controls for widgets (#64) #73's finding, not fixed as part of this plan since neither file is otherwise touched), and any other widget where a story had been relying on a named target that no longer gets built this round — in "[BountyPrep] Storybook: missing primitives and design system gaps" per [Feature] Widget showcase in storybook #250's explicit out-of-scope instruction; do not build any of it here.

Execution plan

  1. CitizenClaimWidget: add CitizenClaimWidgetThemeOverrides.stories.tsx (title: 'Widgets/CitizenClaimWidget/Theme overrides') wiring paired dark_Card/light_Card/dark_Button/light_Button controls against the confirmed plain-primitive surfaces (identity-verification <Button>, Invite Rewards/News tab <Card>), following the StreamingWidget pattern for file/title/docs structure only — not against ClaimCard/ClaimActionButton/ClaimActionGlow, which already have dedicated presets and would make the override a no-op; wire the new environment control (development/production, no staging) on Showcase only; update CitizenClaimWidget.mdx with a Theme overrides section embedding the new Playground story.
  2. GoodReserveWidget: split GoodReserveWidget.stories.tsx into GoodReserveWidgetShowcase.stories.tsx (Interactive/InjectedWallet/LiveWallet, title: 'Widgets/GoodReserveWidget/Showcase', no environment control — widget has no environment prop, packages/goodreserve-widget is not touched) and GoodReserveWidgetQA.stories.tsx (19 fixture stories, title: 'QA/GoodReserveWidget/Runtime Fixtures', mockState-driven, behavior unchanged); add GoodReserveWidgetThemeOverrides.stories.tsx wiring paired dark_Card/light_Card/dark_Button/light_Button controls; create GoodReserveWidget.mdx (net new, following the reference MDX shape); log "GoodReserveWidget has no environment prop" in "[BountyPrep] Storybook: missing primitives and design system gaps"; update the 16 story-id references in tests/widgets/goodreserve-widget/states.spec.ts.
  3. GovernanceWidget: move GovernanceOnboarding.stories.tsx into the QA namespace (e.g. title: 'QA/GovernanceWidget/Onboarding'); leave GovernanceWidgetShowcase.stories.tsx untouched aside from removing its environment control (if present) — Demo, InjectedWallet, and CustodialWallet all stay (maintainer policy exception for Demo, confirmed genuinely live for the two wallet stories; CustodialWallet's missing "dev" sidebar tag is pre-existing and left as-is); add a "development only" note to GovernanceWidget.mdx in place of the dropped control; update the 8 story-id references in tests/widgets/governance-widget/onboarding.spec.ts.
  4. AiCreditsWidget: move MockBackend out of AiCreditsWidgetShowcase.stories.tsx into AiCreditsWidgetQA.stories.tsx as a new fixture story; add AiCreditsWidgetThemeOverrides.stories.tsx wiring paired dark_Card/light_Card/dark_Button/light_Button controls; update AiCreditsWidget.mdx; re-run tests/widgets/ai-credits-widget/states.spec.ts to confirm the move introduces no id collisions (no pre-existing reference to update, per the Reference files section above).
  5. SuperfluidCampaignWidget: move SuperfluidCampaignWidgetApiContracts.stories.tsx into the QA namespace (title: 'QA/SuperfluidCampaignWidget/API Contracts'); add SuperfluidCampaignWidgetThemeOverrides.stories.tsx wiring paired dark_Card/light_Card/dark_Button/light_Button controls only (no new shared.tsx named-component module this round — log the gap per New components above); update the 2 story-id references in tests/widgets/superfluid-campaign-widget/states.spec.ts.
  6. GoodData widget: rename GoodDataWidgetQA.stories.tsx's title from QA/AiCreditsDashboard/Runtime Fixtures to QA/GoodDataWidget/Runtime Fixtures; add GoodDataWidgetShowcase.stories.tsx (title: 'Widgets/GoodDataWidget/Showcase') built on the real aiCredits connector (Vercel/CORS compatibility confirmed, see Required states above); add GoodDataWidgetThemeOverrides.stories.tsx wiring paired dark_Button/light_Button controls only (no Card control — widget renders no Card, confirmed via grep — file notes the exemption); create GoodDataWidget.mdx (net new); update the 5 story-id references in tests/widgets/gooddata-widget/states.spec.ts.
  7. Run the full Playwright suite (tests/widgets/**/*.spec.ts) after all moves land; fix any remaining story-id breakage beyond what's listed above — the per-widget lists above are what's been verified via static grep so far, a full run is the final check, not a substitute for it.
  8. Manual QA: load the live Storybook preview locally; verify CitizenClaimWidget's Showcase environment control offers development/production only, never staging; verify GoodReserveWidget's and GovernanceWidget's Showcase stories have no environment control at all; verify no QA/<Name> story exposes an environment-switcher control; verify every Widgets/<Name> MDX page renders its "How to mount it" and "Theme overrides" sections correctly; verify no new Theme overrides file references a widget-specific named theme target (primitives only); toggle every wired control in every new Theme overrides story (both dark_* and its paired light_*) and confirm the rendered widget visibly changes — not just that the story compiles; verify GoodDataWidget's Showcase loads real aiCredits data on the deployed Vercel preview, not only locally.
  9. Log any design-system primitive or named-theme-target gap found during execution — including SuperfluidCampaignWidget's missing shared.tsx-style module, GoodReserveWidget's missing environment prop, and the existing StreamingWidget/StakingMigrationWidget Theme overrides files' dark-only wiring — in "[BountyPrep] Storybook: missing primitives and design system gaps" (do not build it here); leave "[BountyPrep] Storybook: live deployment review" for Olivia's own UX/docs pass.

Acceptance criteria

(Carried forward from #250's own checklist, which already enumerates these precisely — repeated here as this sub-issue's tracked checklist.)

  • Every widget with a live, integratable component follows the Widgets/<Name>/Showcase + Widgets/<Name>/Theme overrides + QA/<Name>/Runtime Fixtures structure (StreamingWidget / StakingMigrationWidget pattern).
  • ClaimWidget Theme Demo is left as a Showcase + Theme overrides only (no QA section added).
  • Every Widgets/<Name> entry has an MDX docs page with a "How to mount it" snippet and a "Theme overrides" section embedding the Playground story.
  • New Theme overrides playgrounds follow the existing *ThemeOverrides.stories.tsx pattern (flat color controls, live code snippet, reference callout) — no new pattern introduced.
  • Environment controls appear only where the widget both has a working environment prop and the environment list would offer a genuine choice (more than one deployed value) — CitizenClaimWidget's Showcase control offers development/production only (never staging); GoodReserveWidget and GovernanceWidget get no environment control (no prop, and single-value, respectively — see Required states above); QA/<Name> stories remain deterministic with no environment switching anywhere.
  • CitizenClaimWidget gets a Theme overrides playground with paired dark_*/light_* controls wired against primitive (Card/Button) targets only, demonstrated on surfaces confirmed to actually render the plain primitive (not ClaimCard/ClaimActionButton, which have dedicated presets and would make the override a no-op).
  • GoodReserveWidget is fully split: mocked/fixture states under QA/GoodReserveWidget/Runtime Fixtures, live stories under Widgets/GoodReserveWidget/Showcase with no environment control, plus a new Theme overrides file with paired dark_*/light_* controls wired against primitive targets only. packages/goodreserve-widget is not modified.
  • GovernanceWidget's GovernanceOnboarding (internal flow) moves under QA/GovernanceWidget; the Showcase file's Demo, InjectedWallet, and CustodialWallet stories all stay as-is (maintainer policy exception, not a mocked/live reclassification — see Required states above); Showcase has no environment control, replaced by a "development only" note in GovernanceWidget.mdx.
  • AiCreditsWidget's Mock Backend story moves to QA; Theme overrides file + paired dark_*/light_* controls added, wired against primitive targets only.
  • SuperfluidCampaignWidget gets a Theme overrides file + paired dark_*/light_* controls wired against primitive targets only (no new shared.tsx named-component module); API Contracts story file is moved/renamed under the QA section; the missing named-theme-target gap is logged, not built.
  • GoodData widget gets a Widgets/GoodDataWidget/Showcase entry (live aiCredits connector, CORS-verified to work from a Vercel preview deployment) and a Theme overrides file scoped to paired dark_Button/light_Button controls only (no Card control — the widget renders no Card anywhere in its source); its QA path naming is aligned with the widget's actual package name (no more AiCreditsDashboard naming mismatch).
  • No wired Theme overrides control is a no-op: review found this is NOT fully met — see feat(storybook): showcase all GoodWidget widgets with QA fixtures and theme overrides #253's review comment (2026-10-21): AiCreditsHero, ReserveSwapShell/ReserveAmountCard, and SuperfluidCampaignWidget's outer Card hardcode their own background tokens, so the background half of the dark_Card/light_Card control is a no-op on those three (border half works). Tracked as a fix item in the follow-up [GoodBounty] issue.
  • Every dark_* control wired in a new Theme overrides file has a matching wired light_* control (not just documentation text referencing it) — a deliberate improvement over the existing StreamingWidget/StakingMigrationWidget reference files, which wire dark_* only.
  • Nothing under packages/ is modified anywhere in this bounty — confirmed no plan item implies a widget-source code change.
  • All existing Playwright specs under tests/widgets/**/*.spec.ts pass; any spec referencing a story id that moved/changed as part of this restructuring is updated to the new id.
  • No new design-system primitives/components and no new widget-package named theme targets are introduced; any gaps found (including SuperfluidCampaignWidget's missing named-theme-component module, GoodReserveWidget's missing environment prop, and the existing reference files' dark-only wiring) are logged in "[BountyPrep] Storybook: missing primitives and design system gaps" ([BountyPrep] Storybook: missing primitives and design system gaps #254), not built here.
  • Bounty Lead sign-off on the resulting preview deployment — Olivia's review complete 2026-10-21 (see feat(storybook): showcase all GoodWidget widgets with QA fixtures and theme overrides #253), follow-up items tracked in a new [GoodBounty] issue.

Human-reviewer checklist

  • Every widget's Showcase/Theme overrides/QA split matches the StreamingWidget/StakingMigrationWidget reference pattern exactly (file naming, title strings, tags).
  • GovernanceWidget's Showcase stories confirmed unchanged at merge: Demo staying in Showcase is a deliberate maintainer policy exception (not a live/mocked reclassification), InjectedWallet/CustodialWallet stay as confirmed-live, and CustodialWallet's hidden-sidebar behavior (missing "dev" tag) is intentionally left alone — verify none of this drifted during implementation.
  • Each widget's Showcase environment-control options re-checked against the live releases/deployment.json at merge time, in case it changed since this plan was drafted — and confirm no control offers staging/staging-celo anywhere. Confirm GoodReserveWidget and GovernanceWidget still have no environment control (re-check this wasn't silently reintroduced).
  • No QA story anywhere exposes an environment-switcher control.
  • Confirm zero diffs under any packages/ directory in the final PR — this bounty is storybook-and-tests only. If a reviewer finds a packages/ diff, it should be flagged, not merged as-is.
  • All Playwright specs pass with updated story ids; no hardcoded id missed.
  • No new Theme overrides file in this bounty references a widget-specific named theme target (e.g. ClaimCard, ReserveSwapShell, AiCreditsStatusNotice, or a new SuperfluidCampaignWidget component) — every new file targets only the primitive Card/Button.
  • Every wired control in every new Theme overrides story was actually exercised and confirmed to visibly change the rendered widget (not just reviewed for code shape) — spot-check at least one dark_*/light_* pair per widget, per the no-op finding from PR Storybook polish: interactive theming controls for widgets (#64) #73. Partially failed on first pass — see acceptance criteria above and the follow-up [GoodBounty] issue.
  • Every dark_* control has a matching wired light_* control in each new Theme overrides file — confirm neither is present only in documentation text.
  • GoodDataWidget's Theme overrides file is Button-only with no Card control, and its exemption note is present and accurate (re-confirm the widget still renders no Card before merge, in case execution added one).
  • GoodDataWidget's live aiCredits Showcase story is checked against the actual deployed Vercel preview URL, not just a local dev server.
  • No new packages/ui primitives and no new widget-package named theme-target components introduced anywhere; any gaps found (including SuperfluidCampaignWidget's missing shared.tsx-style module, GoodReserveWidget's missing environment prop, and the existing reference files' dark-only wiring) are filed in "[BountyPrep] Storybook: missing primitives and design system gaps" ([BountyPrep] Storybook: missing primitives and design system gaps #254), not built inline.
  • StakingMigrationWidget's out-of-scope status reconfirmed at merge: no environment prop/concept added, still gated only on migrationApiBaseUrl and its hardcoded Fuse chain.
  • MDX docs for every Widgets/<Name> entry reviewed for accuracy of the "How to mount it" snippet against the actual current widget API.
  • Olivia's live-preview UX/docs pass (tracked separately in "[BountyPrep] Storybook: live deployment review") is linked but not treated as a blocking condition for this PR's own merge.

Plans #250. Executed as PR #253. Follow-up fixes tracked in a dedicated [GoodBounty] issue per Olivia's 2026-10-21 review.

Activity

  1. changed the title [-][DRAFT][PLAN] Widget showcase in storybook[/-] [+][PLAN] Widget showcase in storybook[/+] on Oct 21, 2026
  2. moved this from Prepare AI Task to In Progress in GoodBountieson Oct 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions