You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Should the scaffold feature gallery use a design system rather than hand-rolled inline Tailwind on every demo, and if so, built on what?
Decision
Yes. Adopt a lightweight design system in the gallery built on @webjsdev/ui's tier-1 class helpers (buttonClass, cardClass, inputClass, badgeClass, etc.), not on hand-rolled per-demo class strings and not on wrapping components. The gallery keeps looking mostly the same (same design tokens, same neutral palette); this is a consistency + variants refactor plus an architecture cleanup, not a redesign.
Why (rationale)
The drift is real and measurable. ~18 gallery files hand-roll button styling with slightly different class strings; card panels, inputs, and badges repeat too. That drift is exactly how the cursor-pointer gap (fix: add cursor-pointer to the gallery streaming demo button #1057) happened: one of 18 hand-styled buttons was missed.
@webjsdev/ui already solves it, and the gallery is half-adopted. The gallery already uses the shadcn-standard design tokens (--color-primary, --color-card). It just does not use the buttonClass({ variant, size }) / cardClass() / inputClass() / badgeClass() helpers (button variants default/destructive/outline/secondary/ghost/link; sizes xs/sm/lg/icon...).
The primitives are CLASS HELPERS, not wrapping components. You spread the classes onto a native element: <button class=${buttonClass({ variant: 'outline', size: 'sm' })} @click=...>. So adopting them:
adds NO indirection and keeps each demo's concept (server action, streaming, slots) fully readable, unlike a <ui-button> wrapper;
dogfoods @webjsdev/ui in WebJs's PRIMARY teaching surface (a strong signal that the framework uses its own kit) and teaches agents and humans the right pattern for growing the scaffold.
Scope (deliberately bounded)
Adopt the HIGH-REPETITION primitives only: button (~18 files), card/panel, input/textarea, badge. That is where the drift lives.
Leave one-off LAYOUT (grids, section wrappers, the gallery index cards) as inline Tailwind. Those are not design-system primitives; forcing them into helpers would obscure, not clarify.
Shadow-DOM demos (for example reactive-meter) keep their scoped static styles; buttonClass is a light-DOM Tailwind helper, so light-DOM primitives are the system and shadow demos stay a deliberate exception (a couple of them).
Ship the tier-1 class helpers under the scaffold's components/ui/ (the scaffold already pre-initializes for webjs ui add), so a scaffolded app STARTS with a design system.
Keep it visually "mostly how it looks now": same tokens, same palette. Consistency + variants, not a new look.
Alternatives considered and rejected
Full @webjsdev/ui wrapping components for every demo. Rejected: adds an indirection layer that obscures the WebJs concept each demo is meant to teach. The class-helper form gives the design system with none of that cost.
A global CSS base rule (button:not(:disabled) { cursor: pointer }). Rejected earlier (see fix: add cursor-pointer to the gallery streaming demo button #1057 discussion): un-Tailwind-idiomatic, inconsistent with a codebase that does per-element utilities, and it only addresses the cursor symptom, not the broader styling drift.
A bespoke gallery-only style helper (lib/ui.ts). Rejected in favor of dogfooding @webjsdev/ui, so the gallery teaches the real kit rather than a one-off.
Non-goals / guardrails
@webjsdev/ui stays OPT-OUT (the helpers are removable class functions; defaults, not lock-in).
Do NOT pull in all 40 registry components, only the handful the gallery repeats.
Not a redesign: the visual result should be recognizably the same gallery.
Follow-up
The implementation is separate, actionable tracked work (filed via the webjs-file-issue skill), with the scoped primitive list above as its spec.
Question
Should the scaffold feature gallery use a design system rather than hand-rolled inline Tailwind on every demo, and if so, built on what?
Decision
Yes. Adopt a lightweight design system in the gallery built on
@webjsdev/ui's tier-1 class helpers (buttonClass,cardClass,inputClass,badgeClass, etc.), not on hand-rolled per-demo class strings and not on wrapping components. The gallery keeps looking mostly the same (same design tokens, same neutral palette); this is a consistency + variants refactor plus an architecture cleanup, not a redesign.Why (rationale)
cursor-pointergap (fix: add cursor-pointer to the gallery streaming demo button #1057) happened: one of 18 hand-styled buttons was missed.@webjsdev/uialready solves it, and the gallery is half-adopted. The gallery already uses the shadcn-standard design tokens (--color-primary,--color-card). It just does not use thebuttonClass({ variant, size })/cardClass()/inputClass()/badgeClass()helpers (button variants default/destructive/outline/secondary/ghost/link; sizes xs/sm/lg/icon...).<button class=${buttonClass({ variant: 'outline', size: 'sm' })} @click=...>. So adopting them:<ui-button>wrapper;buttonClassputscursor-pointeron the base and handlesdisabled:pointer-events-none;@webjsdev/uiin WebJs's PRIMARY teaching surface (a strong signal that the framework uses its own kit) and teaches agents and humans the right pattern for growing the scaffold.Scope (deliberately bounded)
reactive-meter) keep their scopedstatic styles;buttonClassis a light-DOM Tailwind helper, so light-DOM primitives are the system and shadow demos stay a deliberate exception (a couple of them).components/ui/(the scaffold already pre-initializes forwebjs ui add), so a scaffolded app STARTS with a design system.Alternatives considered and rejected
@webjsdev/uiwrapping components for every demo. Rejected: adds an indirection layer that obscures the WebJs concept each demo is meant to teach. The class-helper form gives the design system with none of that cost.button:not(:disabled) { cursor: pointer }). Rejected earlier (see fix: add cursor-pointer to the gallery streaming demo button #1057 discussion): un-Tailwind-idiomatic, inconsistent with a codebase that does per-element utilities, and it only addresses the cursor symptom, not the broader styling drift.lib/ui.ts). Rejected in favor of dogfooding@webjsdev/ui, so the gallery teaches the real kit rather than a one-off.Non-goals / guardrails
@webjsdev/uistays OPT-OUT (the helpers are removable class functions; defaults, not lock-in).Follow-up
The implementation is separate, actionable tracked work (filed via the
webjs-file-issueskill), with the scoped primitive list above as its spec.