Skip to content

Storybook polish: interactive theming controls for widgets (#64)#73

Open
Godbrand0 wants to merge 12 commits into
GoodDollar:mainfrom
Godbrand0:feat/storybook-controls-polish
Open

Storybook polish: interactive theming controls for widgets (#64)#73
Godbrand0 wants to merge 12 commits into
GoodDollar:mainfrom
Godbrand0:feat/storybook-controls-polish

Conversation

@Godbrand0

@Godbrand0 Godbrand0 commented Jul 1, 2026

Copy link
Copy Markdown

Summary

Part of #64 (Polish storybook interaction and presentation) — not closing it, since the issue's Definition of Done has three items and this PR intentionally covers a scoped subset (see below). Focuses on the "controls" and "documentation" parts of the DoD:

  • Wires up Storybook argTypes controls for defaultTheme and themeOverrides (via a shared "brand preset" select: None/Cobalt/Teal) across all four widget showcase stories — StreamingWidget, CitizenClaimWidget, StakingMigrationWidget, and ClaimWidget Theme Demo — so integrators can flip theme/branding live in the Controls panel instead of editing story code.
  • Extends the same controls to every QA fixture story across these four widgets (20 StreamingWidget states, 1 CitizenClaimWidget state, 8 StakingMigrationWidget states), matching the DoD's literal "all stories are accompanied with controls" wording. QA determinism for Playwright is unaffected — automated tests navigate directly to story IDs without touching the Controls panel, so the fixed default args (dark theme, no brand preset) still apply during test runs.
  • Extracts the cobalt/teal override presets (previously local to claimWidgetStories.tsx) into a shared themeOverridePresets.ts helper reused by all widgets, with both dark_* and light_* variants for every named component theme (per review feedback — the first pass was dark-only and silently did nothing in light mode).
  • Adds argTypes + a Controllable story to the Card, GlowCard, Stepper, and Drawer design-system primitives, following the existing TokenAmount pattern.
  • Adds "How to mount it" integration code snippets to CitizenClaimWidget.mdx and StakingMigrationWidget.mdx to match ClaimWidget.mdx's existing depth, plus a one-line pointer to the new controls on all three widget docs pages.
  • Fixes two bugs caught during manual visual verification: the Stepper Controllable story's activeStepId control only auto-scrolled the list without changing which step rendered as active, and the brandPreset control was a no-op on StreamingWidget because its card surfaces use different named theme keys than the Claim-family widgets.
  • Cleans up now-dead goodWidgetProvider parameter blocks across the touched story files — .storybook/preview.tsx on main no longer reads that parameter at all (the global provider/shell decorator was removed upstream since every widget already wraps its own provider), so this was leftover config with nothing consuming it. Also resolves the specific ClaimWidget.stories.tsx TS2353 flagged in review — that block was placed outside parameters and never worked even before the decorator was removed.

Explicitly out of scope for this PR (per maintainer guidance in review): ai-credits-widget, governance-widget, and goodreserve-widget landed on main after this branch started and are not touched here. Also out of scope: the broader "human eye review" pass across every QA state for correctness, beyond the two bugs already found and fixed above.

Rebased onto current main (3620f63) to pick up the preview.tsx decorator removal and the new widget packages; the only conflict was in citizenClaimWidgetStories.tsx, where main had already refactored the story shell — the theme-prop threading was re-applied to the new shape rather than mechanically resolved.

Test plan

  • pnpm install + full workspace pnpm build (13/13) + pnpm build-storybook succeed post-rebase
  • npx tsc --noEmit in examples/storybook shows no errors in any file this PR touches (remaining errors are pre-existing, in ai-credits-widget/goodreserve-widget story files and a tamagui/@types/node issue, unrelated to this change)
  • Manually verified in a running Storybook that defaultTheme and brandPreset controls visibly change each widget's rendering in both dark and light mode, and that Card/Stepper/Drawer controls visibly change their primitives
  • pnpm test:demo (Playwright) — 33/35 passed; the 2 failures in staking-migration-widget/states.spec.ts (ReadyStory/MigratingStory) predate this PR and are still being investigated separately (not attributed to this change)

@Godbrand0
Godbrand0 requested review from a team and L03TJ3 July 1, 2026 09:45
@L03TJ3
L03TJ3 requested review from a team and 0xOlivanode and removed request for a team July 6, 2026 07:36
@L03TJ3 L03TJ3 moved this to In Review in GoodBounties Jul 7, 2026

@0xOlivanode 0xOlivanode left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code itself is solid, the Stepper activeStepId fix is a real and correctly implemented fix, the cobalt/teal preset extraction preserves every value exactly, and the theme prop threading across all the QA/Showcase files is consistent throughout.

Requesting changes on process, not code:

This PR's description says "closes #64", but it's explicitly framed as a "first increment" and its own test plan lists remaining DoD items as follow-up work. Checking issue #64 directly, its Definition of Done has 3 items, and this PR only partially covers them:

  • "All stories are accompanied with controls": this PR covers 4 widgets (StreamingWidget, CitizenClaimWidget, StakingMigrationWidget, ClaimWidget Theme Demo), but the repo has 6 widget areas with story files. ai-credits-widget and governance-widget both have QA + Showcase stories that aren't touched here.
  • "All stories reviewed for clear guiding text": explicitly deferred per the PR's own test plan.
  • "Component-level issues resolved or documented": partially done (the Stepper fix), no broader sweep.

Since this is tagged as a bounty issue, merging with "closes #64" as-is will auto-close the tracking issue before its DoD is actually met. Can we change this to "part of #64" and open a follow-up issue for the remaining scope (ai-credits-widget, governance-widget, and the human-eye review pass), or confirm with whoever manages the bounty that partial closure here is intentional?

Small nit: the PR description says "no QA fixture stories were touched", the three *QA.stories.tsx files were edited (just to add the new controls, no data-testid changes), so the underlying claim about stable test IDs holds, but the wording overstates it slightly.

dark_SetStreamFormCard: { borderColor: '#00A884', shadowColor: 'rgba(0,168,132,0.65)' },
},
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Every entry here is a dark_* key, there's no light_* equivalent for any of these (ClaimCard, StreamRow, PoolRow, BalanceCard, etc).

Since the QA/Showcase stories now expose defaultTheme and brandPreset as independent controls, selecting defaultTheme: light + a brand preset will apply the top-level tokens.color.primary globally, but none of the component-specific border/shadow/glow overrides will render, since those only exist for dark. That's the part that actually makes the preset visually "brand," so in light mode it'll look like the preset silently isn't working.

Is that intentional (presets are meant as dark-mode demos only), or should light variants be added here too?

@github-project-automation github-project-automation Bot moved this from In Review to In Progress in GoodBounties Jul 8, 2026
@L03TJ3

L03TJ3 commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

@0xOlivanode the note on 'auto-closing', this is turned off in the repo so does not affect anything.
I manage closing issues manually for tracking purposes.

Godbrand0 added a commit to Godbrand0/GoodWidget that referenced this pull request Jul 9, 2026
…ow key

Addresses PR GoodDollar#73 review comment: every brandPreset override was dark_*
only, so selecting defaultTheme: light left only the top-level
tokens.color.primary applied globally, while every component-specific
border/shadow/glow override silently did nothing — the preset looked
broken in light mode.

Adds a light_* counterpart for every dark_* entry, using field values
appropriate for light mode (much lower shadow opacity, matching the
base design preset's light_Card/light_Toast/etc precedent in
packages/ui/src/presets.ts; darker/more saturated text color for
contrast on a light background instead of the pastel dark-mode shade).
ClaimActionInner stays dark-only, matching the base preset's own
precedent of never defining a light variant for it.

Also fixes dark_ClaimActionGlow, which used the wrong field name
(primary instead of backgroundColor) — CircularActionButton.tsx reads
$backgroundColor for the glow's resting fill and $primaryLight only for
its hover state, so the old key silently did nothing.
@Godbrand0

Godbrand0 commented Jul 9, 2026

Copy link
Copy Markdown
Author

hello @L03TJ3 , so should i change the pr name to "closes part of 64" or i should leave it as is. will the other issues be created or should i work on them myself??

@L03TJ3

L03TJ3 commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Thats review feedback so should be followed up on in this PR

once done, you request review from @0xOlivanode

@Godbrand0

@Godbrand0
Godbrand0 requested a review from 0xOlivanode July 10, 2026 05:44
@L03TJ3 L03TJ3 moved this from In Progress to In Review in GoodBounties Jul 13, 2026

@0xOlivanode 0xOlivanode left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the fast turnaround on the light_* fix. I pulled the branch and went through it in depth. The review-response commit fully checks out:

Every dark_* key now has a light_* counterpart, with ClaimActionInner intentionally excepted, matching the base preset's own precedent in packages/ui/src/presets.ts.
Verified against CircularActionButton.tsx that the glow reads $backgroundColor / $glowOpacity, so the old primary key was indeed dead. Nice catch; that was a pre-existing latent bug, and the new light values follow the base preset's light_ClaimActionGlow convention.
pnpm install --frozen-lockfile, full workspace build (9/9), and build-storybook all pass on the branch. test:demo gives 33/35 with only the two already-noted staking-migration failures.
Re-verified QA determinism directly: zero data-testid changes across the branch, no story export renames, and all three widgets internally default to 'dark', so the now-explicit QA args are behavior-identical for the test runner.

Requesting changes on three items:

Rebase required, the branch no longer merges into main. There's a content conflict in examples/storybook/src/stories/helpers/citizenClaimWidgetStories.tsx: main has since refactored that story shell (the WidgetTabs wrapper was removed and the widget now mounts directly), so the themeOverrides threading needs to be re-applied to the new component shape rather than mechanically conflict-resolved.

Post-rebase, main now has three additional widget story areas with no controls: ai-credits-widget (Showcase + QA + MDX), governance-widget, and goodreserve-widget. @L03TJ3, per the DoD's "all stories are accompanied with controls," should these be extended in this PR after the rebase, or split into a follow-up issue? Either works; it just needs an explicit call so the bounty scope is unambiguous.

One small fix while you're in ClaimWidget.stories.tsx, see inline comment: goodWidgetProvider is placed at the meta top level, but the decorator reads it from parameters, so it's currently a silent no-op. Pre-existing, but this PR already edits that meta object.

Non-blocking: the PR description still says "no QA fixture stories were touched," which 4112317 made outdated, so worth a quick edit. Separately, the two failing staking-migration tests (ready summary / migrating timeline) reproduce outside the sandbox on a normal connection too, so the sandbox-network explanation doesn't fully cover them. I'm following up on whether they also fail on main; not attributing them to this PR for now since the specs predate it.

} from '../helpers/claimWidgetStories'
import { ClaimWidgetStoryCanvas } from '../helpers/claimWidgetStories'
import { BRAND_PRESET_OPTIONS, brandPresetOverrides, type BrandPreset } from '../helpers/themeOverridePresets'

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

goodWidgetProvider here sits at the top level of meta, but the decorator in .storybook/preview.tsx reads context.parameters.goodWidgetProvider, so disableProvider: true, useShell: false never actually applies to these stories. Moving it inside parameters (as every other story file does) makes it functional and also clears the TS2353 error on this file.

@github-project-automation github-project-automation Bot moved this from In Review to In Progress in GoodBounties Jul 13, 2026
@L03TJ3

L03TJ3 commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

@Godbrand0 @0xOlivanode
we are working async, so its okay to not keep updating stories as we push new updates to widgets.
keep the updates to the stories you currently targetted

Only thing that should be left/kept in place is the removal of miniapp-shell and goodwidget provider in preview.tsx

Godbrand0 added a commit to Godbrand0/GoodWidget that referenced this pull request Jul 13, 2026
…ow key

Addresses PR GoodDollar#73 review comment: every brandPreset override was dark_*
only, so selecting defaultTheme: light left only the top-level
tokens.color.primary applied globally, while every component-specific
border/shadow/glow override silently did nothing — the preset looked
broken in light mode.

Adds a light_* counterpart for every dark_* entry, using field values
appropriate for light mode (much lower shadow opacity, matching the
base design preset's light_Card/light_Toast/etc precedent in
packages/ui/src/presets.ts; darker/more saturated text color for
contrast on a light background instead of the pastel dark-mode shade).
ClaimActionInner stays dark-only, matching the base preset's own
precedent of never defining a light variant for it.

Also fixes dark_ClaimActionGlow, which used the wrong field name
(primary instead of backgroundColor) — CircularActionButton.tsx reads
$backgroundColor for the glow's resting fill and $primaryLight only for
its hover state, so the old key silently did nothing.
@Godbrand0
Godbrand0 force-pushed the feat/storybook-controls-polish branch from 947c695 to 9059962 Compare July 13, 2026 17:25
Godbrand0 added a commit to Godbrand0/GoodWidget that referenced this pull request Jul 13, 2026
Addresses PR GoodDollar#73 review comment: main removed the global GoodWidgetProvider/
MiniAppShell decorator from .storybook/preview.tsx entirely (every widget
already wraps its own provider internally, so the outer one was redundant).
That decorator was the only thing reading context.parameters.goodWidgetProvider,
so every remaining goodWidgetProvider parameter block in the touched story
files is now dead configuration with nothing left to consume it.

Removes it from the five files this PR touches (ClaimWidget, StreamingWidget
Showcase/QA, StakingMigrationWidget Showcase/QA). This also resolves the
specific nit about ClaimWidget.stories.tsx: that block was placed at the
meta top level instead of inside `parameters` and was already a no-op before
this rebase — deleting it (rather than moving it) is correct now since
there's no decorator left to read it either way.
@Godbrand0
Godbrand0 requested a review from 0xOlivanode July 13, 2026 17:31
@L03TJ3 L03TJ3 linked an issue Jul 14, 2026 that may be closed by this pull request
8 tasks
@L03TJ3 L03TJ3 moved this from In Progress to In Review in GoodBounties Jul 14, 2026

@L03TJ3 L03TJ3 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a good demonstration of the requested controls and I find it relatively 'lazy' for lack of a better word.
I also don't see anything done towards 'clear and concise showcase ... write new widgets

the basics work. sure.
Note this section of the original issue:
The main structure as-is now setup should be kept. This boutny is about about polishing the content, the way widgets or components are demonstrated, including guiding documentation and code examples). And besides having an interactive demo functionality, it should also be interactive by being able to play with the design-system and override as we promote: 'almost all UI aspects of a given widget'. This requires clear mapping of exposed styling variables and making it configurable/overridable through storybooks native controls feature.

Then my AI review:
For StreamingWidget, the current control offers only:

  • defaultTheme
  • brandPreset: None / Cobalt / Teal

That is a fixed bundle of overrides. It cannot answer “make only primary buttons purple,” for example.

The underlying API can do it:

<StreamingWidget
  themeOverrides={{
    themes: {
      dark_Button: {
        background: '#7C3AED',
        backgroundHover: '#6D28D9',
        backgroundPress: '#5B21B6',
        backgroundFocus: '#6D28D9',
        textColor: '#FFFFFF',
      },
    },
  }}
/>

Button is a public named theme target, and StreamingWidget uses it for its primary actions. But no StreamingWidget story or guide exposes or explains that target. The current presets only override a selection of card surfaces (dark_StreamRow, dark_PoolRow, etc.), not dark_Button.

For the ClaimWidget theme demo, the API is similarly capable of targeted overrides:

  • dark_ClaimCard
  • dark_ClaimActionGlow — use backgroundColor / glowOpacity
  • dark_ClaimActionRing — use primary / primaryLight
  • dark_ClaimActionInner
  • dark_TokenAmountText
  • dark_Button

But the current “Theming and Overrides” experience does not make those targets discoverable, structured, or interactively editable. Worse, the supposedly canonical playground still shows stale glow fields (primary) where the actual component uses backgroundColor and glowOpacity; the new shared preset fixed that elsewhere. See ThemePlayground.stories.tsx and ThemingAndOverrides.mdx.

So I’d frame it this way:

  • You should not necessarily expect a color picker for every internal style value.
  • You should expect a Storybook “advanced overrides” path that demonstrates the supported public contract per widget.
  • It should show the target names, which semantic fields they accept, light/dark counterparts, a live editable example (structured controls or an object/JSON control), and copy-paste code that matches the live result.
  • QA fixtures should stay deterministic. This belongs primarily in Showcase/Integrator stories, not by putting two broad controls on every QA state.

Today, this PR demonstrates “choose one of two brands,” not “almost all UI aspects are overridable.” That is materially below issue #64’s stated goal.

@github-project-automation github-project-automation Bot moved this from In Review to In Progress in GoodBounties Jul 15, 2026
…tories

Adds interactive Storybook controls for defaultTheme and themeOverrides
across all four widget showcase stories (StreamingWidget, CitizenClaimWidget,
StakingMigrationWidget, ClaimWidget) plus the Card/GlowCard/Stepper/Drawer
design-system primitives, so integrators can experiment with theming live
in the Controls panel instead of editing story code. Extracts the cobalt/teal
brand override presets into a shared helper reused across widgets.
CitizenClaimWidget.mdx and StakingMigrationWidget.mdx were missing the
"How to mount it" code snippet that ClaimWidget.mdx already has, so
integrators had no copy-paste starting point for those two widgets.
Adds the same Source block pattern to both, and adds a one-line note
to all three widget docs pages (CitizenClaimWidget, StakingMigrationWidget,
StreamingWidget) pointing at the new defaultTheme/themeOverrides Storybook
controls added in this branch.
Found during manual visual verification of issue GoodDollar#64 (each control must
visibly change what renders): the Stepper Controllable story passed a
static STEPS array with hardcoded per-step `status` values, so moving the
`activeStepId` control only auto-scrolled the list — the blue "active"
highlight stayed pinned to whichever step had status:'active' in the
array (always "Submit migration"), regardless of the selected control
value. Now recomputes each step's status relative to the chosen
activeStepId so the control drives a real state change.
Found during manual verification: StreamingWidget's card surfaces use
their own named Tamagui theme keys (StreamRow, PoolRow, BalanceCard,
EmptyStateCard, ErrorStateCard, SetStreamFormCard — see
packages/streaming-widget/src/components/shared.tsx), none of which
overlap with the Claim-family keys (ClaimCard, ClaimActionGlow, etc.)
the shared cobalt/teal presets originally targeted. So toggling
brandPreset on the StreamingWidget showcase story changed nothing.

Adds matching border/shadow overrides for StreamingWidget's card names
to both presets so the control has a real effect there too.

StakingMigrationWidget already reuses the ClaimCard/StreakCard names
(packages/staking-migration-widget/src/migrationWidgetComponents.ts),
so it was already covered — it just isn't visible on the "no wallet"
fallback screen, since that screen renders plain text with no themed
Card at all.
The Controls panel is auto-generated for every story of a component,
so it appears (and looks interactive) on Default/WithAction-style
stories too — but their render functions use fixed hardcoded props
so those stories stay stable for other docs pages and Playwright
screenshot tests. Only the "Controllable" story actually reads args.
This was confusing during manual verification, so each Default story
across Card/GlowCard/Stepper/Drawer now says so explicitly.
… fallback

Found during manual verification: InjectedWalletStory threaded
themeOverrides through to StreamingWidgetStoryShell (the "wallet
connected" path) but not to PreviewStoryShell (the "no wallet"
fallback path, which most reviewers hit since they don't have a
matching injected wallet). So brandPreset silently did nothing on
the common case of that story. PreviewStoryShell and its underlying
StreamingWidgetPreview call now also receive themeOverrides.
…re stories

Per issue GoodDollar#64's literal DoD ("all stories are accompanied with controls"),
the QA runtime-fixture stories previously had zero controls. Threads
defaultTheme/themeOverrides through every QA helper function across all
three widgets (20 StreamingWidget states, 1 CitizenClaimWidget state, 8
StakingMigrationWidget states) and wires matching argTypes into each QA
story file, following the same pattern already used on the Showcase
stories.

QA determinism for Playwright is unaffected: automated tests navigate
directly to story IDs without touching the Controls panel, so the fixed
default args (dark theme, no brand preset) still apply during test runs.
A human reviewer gets the same live override on top when browsing QA
stories manually.

LightThemePopulated/LightThemeReady keep their hardcoded defaultTheme="light"
mount (that's the point of those specific stories) but now also accept the
brandPreset control on top.
…ow key

Addresses PR GoodDollar#73 review comment: every brandPreset override was dark_*
only, so selecting defaultTheme: light left only the top-level
tokens.color.primary applied globally, while every component-specific
border/shadow/glow override silently did nothing — the preset looked
broken in light mode.

Adds a light_* counterpart for every dark_* entry, using field values
appropriate for light mode (much lower shadow opacity, matching the
base design preset's light_Card/light_Toast/etc precedent in
packages/ui/src/presets.ts; darker/more saturated text color for
contrast on a light background instead of the pastel dark-mode shade).
ClaimActionInner stays dark-only, matching the base preset's own
precedent of never defining a light variant for it.

Also fixes dark_ClaimActionGlow, which used the wrong field name
(primary instead of backgroundColor) — CircularActionButton.tsx reads
$backgroundColor for the glow's resting fill and $primaryLight only for
its hover state, so the old key silently did nothing.
Addresses PR GoodDollar#73 review comment: main removed the global GoodWidgetProvider/
MiniAppShell decorator from .storybook/preview.tsx entirely (every widget
already wraps its own provider internally, so the outer one was redundant).
That decorator was the only thing reading context.parameters.goodWidgetProvider,
so every remaining goodWidgetProvider parameter block in the touched story
files is now dead configuration with nothing left to consume it.

Removes it from the five files this PR touches (ClaimWidget, StreamingWidget
Showcase/QA, StakingMigrationWidget Showcase/QA). This also resolves the
specific nit about ClaimWidget.stories.tsx: that block was placed at the
meta top level instead of inside `parameters` and was already a no-op before
this rebase — deleting it (rather than moving it) is correct now since
there's no decorator left to read it either way.
@Godbrand0
Godbrand0 force-pushed the feat/storybook-controls-polish branch from 9059962 to bc797f4 Compare July 16, 2026 12:55
…ix brand preset Button/glow gaps

Addresses L03TJ3's review on PR GoodDollar#73: the existing brandPreset control (None/
Cobalt/Teal) only demonstrated picking from two curated palettes across a
handful of hardcoded card targets, not "almost all UI aspects" being
overridable as issue GoodDollar#64 asks for.

- New Widgets/StreamingWidget/Advanced Overrides story: live color-picker
  controls (always visible, no collapsed JSON tree to expand) mapped to real
  themeOverrides.themes fields (dark_Button + dark_StreamRow/dark_BalanceCard
  from the rendered fixture), with a code snippet generated from the live arg
  values so it can never drift from what's rendered. Reference list for the
  remaining Card-derived targets (PoolRow, EmptyStateCard, ErrorStateCard,
  SetStreamFormCard) that share the same field shape.
- Fixed dark_ClaimActionGlow using stale primary/primaryLight fields in
  ThemePlayground.stories.tsx (the component reads $backgroundColor, not
  $primary — same bug class already fixed in themeOverridePresets.ts).
- Fixed cobaltOverrides/tealOverrides never touching dark_Button/light_Button:
  manually verified the InjectedWallet story's wallet-not-connected fallback
  (WalletGate.tsx) renders an EmptyStateCard + a Button-themed "Connect
  Wallet" action, so previously only a subtle card border tint changed
  between presets while the one loud, obviously-colored element never did.
  This also fixes the same gap for ClaimWidget/StakingMigrationWidget, which
  share the base Button theme.

One widget scoped first (per plan) to validate the pattern before
replicating to ClaimWidget and StakingMigrationWidget.
@Godbrand0

Copy link
Copy Markdown
Author

@L03TJ3 pushed a first pass at the "advanced overrides" pattern, scoped to one widget (StreamingWidget) before replicating it elsewhere, to get sign-off on the shape first.

New story: Widgets/StreamingWidget/Advanced Overrides → Playground

  • Individual color-picker controls mapped to real themeOverrides.themes fields (dark_Button + the two Card-derived targets shown in the fixture: dark_StreamRow, dark_BalanceCard) — all visible as flat rows in the Controls panel, no collapsed JSON tree to expand.
  • The code snippet above the widget is generated from the live arg values (not hardcoded), so it can't drift from what's actually rendered, the same class of bug you caught in ThemePlayground.stories.tsx (also fixed in this push: dark_ClaimActionGlow was using stale primary/primaryLight fields there; the component reads $backgroundColor).
  • A reference list for the remaining Card-derived targets (PoolRow, EmptyStateCard, ErrorStateCard, SetStreamFormCard) that share the same field shape but aren't individually wired to a control, to keep the control count reasonable.

Questions before I replicate this to ClaimWidget and StakingMigrationWidget:

  1. Does this satisfy "almost all UI aspects... configurable/overridable through storybook's native controls," or do you want full per-target coverage (all 7 StreamingWidget targets individually control-wired, not just the 3 shown live)?
  2. Individual color controls vs. a single JSON/object control — any preference now that you can compare it live?
  3. Should this live under each widget's own Showcase folder (as done here) or be consolidated into ThemePlayground.stories.tsx alongside the ClaimWidget override layers?

@Godbrand0
Godbrand0 requested a review from L03TJ3 July 16, 2026 15:52
@L03TJ3

L03TJ3 commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

I think its the right direction yes. some comments:

  • Can we disable 'saving' state (at the bottom after making changes). the stories should always load with default state

  • Can playground be used like docs? so that you have the playground but around it more docs-style guide/documentation.
    if not, at least see if you can apply some formatting/styling aligned with docs pages. the guiding text currently reads a bit off.

  • Advanced Overrides > Can be renamed to Theme overrides

  • Expand the how it works section and include all overridable paths (they don't have to be supported by controls, but should be clear). If that is supposed to be the header at the top: not really clear.

-- Also, maybe add text to how it works: 'Play around with some of the theme overrides using the controls below (you maybe have to activate controls top-right). The code here can later be copied and directly used in your own dapp. See the .... section for additional overridable styles' <-- Something along those lines, whatever makes sense

  • flat rows is fine, I think clear enough. and yes. should a couple of high target/impact controls that change default brand visually. we don't have to go into the depth of everything in storybook.

…and StakingMigrationWidget

Follow-up to L03TJ3's sign-off on the StreamingWidget pattern
("I think its the right direction yes"), replicating it to the other two
widgets and applying their requested refinements across all three:

- New Widgets/ClaimWidget Theme Demo/Theme overrides and Widgets/
  StakingMigrationWidget/Theme overrides playgrounds, same shape as
  StreamingWidget's: flat always-visible color controls for a couple of
  high-impact targets per widget, a live code snippet, and a reference
  callout listing every overridable path (controlled or not).
  - ClaimWidget: dark_Button, dark_ClaimActionGlow, dark_ClaimActionRing,
    dark_ClaimCard (it defines its own local ClaimActionGlow/Ring/Inner,
    same shape as the shared CircularActionButton).
  - StakingMigrationWidget: dark_ClaimCard, dark_ClaimActionGlow,
    dark_ClaimActionRing (no dark_Button control — this widget has no plain
    Button usage, only the shared circular action button).
- Renamed "Advanced Overrides" -> "Theme overrides" everywhere per feedback.
- preview.tsx: parameters.controls.disableSaveFromUI = true globally, so
  editing any control (including the existing brandPreset/defaultTheme ones)
  no longer shows Storybook's "Update story / Create new story" save bar.
- Each widget's .mdx docs page gets a new "Theme overrides" DocsSection
  embedding the Playground story via Canvas, using the intro copy L03TJ3
  suggested. The header/description lives only in the docs page (not
  duplicated inside the story itself) to avoid the doubled heading that
  showed up when both had it.
- Centered the code snippet + reference callout (maxWidth 560, margin auto)
  so they align with the widget preview below them instead of stretching
  full-bleed while the widget stays narrow and centered.
…ior commit

These belonged in the previous commit (theme-overrides playground
replication) but were dropped by a staging mistake: a failed git add on a
stale path aborted the whole add call.

- preview.tsx: parameters.controls.disableSaveFromUI = true.
- Each widget's .mdx docs page: new "Theme overrides" DocsSection embedding
  its Playground story via Canvas.
@Godbrand0

Copy link
Copy Markdown
Author

@L03TJ3 pushed the refinements you asked for, plus replicated the pattern to the other two widgets.

StreamingWidget refinements (all five points addressed):

  • disableSaveFromUI: true set globally in .storybook/preview.tsx — the "Update story / Create new story / Reset" bar no longer shows on any control edit, including the existing brandPreset/defaultTheme controls.
  • Renamed "Advanced Overrides" → "Theme overrides" everywhere.
  • Restyled the guiding text using the same DocsSection/DocsCallout/DocsList building blocks the docs pages already use (ThemingAndOverrides.mdx, etc.), rather than a separate visual language.
  • "How it works" now documents every overridable path on the widget (not just the ones wired to a live control), split into "wired to the controls above" vs. reference-only.
  • Added the intro copy you suggested, adapted slightly.
  • Kept the control depth as-is per your note — flat rows, a couple of high-impact targets, not full per-field coverage.

Replicated to the other two widgets, same shape:

  • Widgets/ClaimWidget Theme Demo/Theme overrides — controls for dark_Button, dark_ClaimActionGlow, dark_ClaimActionRing, dark_ClaimCard. (This widget defines its own local ClaimActionGlow/Ring/Inner — same field shape as the shared CircularActionButton, just not imported from it.)
  • Widgets/StakingMigrationWidget/Theme overrides — controls for dark_ClaimCard, dark_ClaimActionGlow, dark_ClaimActionRing. No dark_Button control here — this widget has no plain Button usage anywhere, only the shared circular action button.

Docs integration: each widget's .mdx docs page gets a new "Theme overrides" section embedding the Playground story via <Canvas>, right where "Manual wallet showcase" already lives. The header/description lives only in the docs page now — we tried it in both places first and it visibly duplicated on the Docs tab, so it's single-sourced there; the standalone Playground story pages show just the controls/code/widget.

Everything typechecks and pnpm build-storybook passes across all three. Let us know if the pattern reads right now or if anything else needs adjusting before we consider this settled.

@vercel

vercel Bot commented Jul 16, 2026

Copy link
Copy Markdown

Deployment failed with the following error:

The provided GitHub repository does not contain the requested branch or commit reference. Please ensure the repository is not empty.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

[GoodBounty]: Polish storybook interaction and presentation

3 participants