Skip to content

Component inventory

Part of the design-brief package (issue #263). The reusable pieces a generated design must define, each with the behavioral requirements the visual design has to satisfy. Components reference only --ns-* theme tokens (see brand-tokens.md) so every one restyles with a theme switch.

Implementation registries

Two shared component kits implement this inventory — import from a kit rather than re-declaring .btn/.card/.tier-badge styles per page:

  • Public kit — $lib/public/ui (issue #824): Button (primary/secondary/quiet, big, ≥44px targets), Card (default/accent/muted tones), TierChip (equal-weight by construction — see Badges & tier markers), Tabs + tabs.ts (WAI-ARIA tablist, ?tab= URL-sync — logic shared with the admin kit), NudgeCard (the right-sizing nudge's success-trio shell), SectionHeading, FieldGroup (reset fieldset+legend). Consumed by home, /select (stepper + results), and /compare.
  • Admin kit — $lib/admin/ui (issue #308): the admin register — denser metrics, danger/ghost variants, tables, forms. See its index.ts header for conventions.

Buttons

  • Variants: primary (one per screen — the forward action), secondary (Previous, Start fresh), tertiary/link (dismiss, "skip to compare"), and destructive (admin only).
  • Behavior: visible hover, active, focus-visible (use --ns-color-focus as a ring — never remove outlines), and disabled states. Hit target ≥ 44px on touch. Primary uses accent/on-accent; hover uses accent-hover.
  • Hand-off buttons (configurator/resources deep links) are styled as primary-family actions, not external-link afterthoughts — they continue the journey (principle 4).

Cards

  • Persona track cards (home): title + one-line buyer-facing description; entire card clickable with a single focus outline; equal heights in a row of 1–4; must survive long track names and 2-sentence descriptions.
  • System cards (results shortlist): photo (card rendition), name, tier badge, one-line fit summary, actions. Must render acceptably with no photo (no gray placeholder box — collapse the media slot).
  • Education callout (stepper): reading-typography block visually distinct from controls; supports 1–3 short paragraphs; never collapsible.

Stepper & progress

The signature component (see the screen inventory).

  • Progress indicator: "Step N of M" text plus a visual track/fill; must scale from 5 to 20 steps without layout change; announces progress to screen readers (aria current/total).
  • Step transitions: advancing feels immediate (< 100ms perceived); optional subtle motion must respect prefers-reduced-motion.
  • Option group: radio semantics, one column; label + optional "what this means" line; selected state obvious at a glance (not just a dot — fill/border shift); re-clicking the selection clears it, so the selected state must also read as a toggle.
  • Boundaries: no Previous on step 1; final forward action reads See results.
  • Numbered step marker (home how-it-works, #977): the 1-2-3 markers match the nanawall.com/resources treatment — a large outlined ring (transparent fill, brand-colored ring + numeral), fluid clamp(2.75rem, 8vw, 3.5rem). Ring and numeral are --ns-color-accent, so each theme renders its own accent (nanawall teal · graphite amber · linen terracotta · pressroom vermillion) with no raw blue; the markup is identical across themes, only tokens differ. Numeral-on-circle is AA in every theme (accent ≥ 4.5:1 on the section background), enforced by the accent-on-surface pair in the #845 token gate.

Forms (admin register)

  • Text/number/select/textarea/toggle with persistent labels (no placeholder-as-label), inline validation on blur, error text tied via aria-describedby using the danger trio, save success/failure feedback, and dirty-state protection cues. Dense vertical rhythm — admin is a working tool.

Comparison table

  • Sticky header (system names + photos) and sticky first column (attribute names); row hover; difference highlighting (rows where values differ); right-sizing nudge attachable to a column; "??"/missing cells as em-dash, visually quieter than real values; groups of ~60 attributes by category with collapsible group headers; horizontal scroll pattern on mobile with the first column pinned. Numeric/technical values may use --ns-font-mono.

Existing primitives (MediaGallery.svelte, ResponsiveImage.svelte, VideoEmbed.svelte) the design skins, not reinvents.

  • Renditions: thumb 160w · card 480w · hero 1200w · full 2000w (AVIF/WebP/ JPEG). Design to these widths; art direction in art-direction.md.
  • Gallery: primary image + thumbnail strip, keyboard navigable, captions optional; video embeds get a poster frame, never autoplay with sound.
  • Slideshow + slideshow.ts (#976): one framed image visible at a time — the deliberate replacement for a vertical image pile. WAI-ARIA carousel (role=group + aria-roledescription, per-slide labels, polite live region for user-driven changes only); prev/next buttons + a dot position indicator; ArrowLeft/Right/Home/End cycle. Auto-advance is gated on prefers-reduced-motion and pauses on hover/focus. Graceful degradation (H5): the controls render only after hydration, so with JS or images absent the section is a single static framed image (MediaFrame theme tokens) — never dead buttons or a pile. Pure index logic lives in slideshow.ts.

Right-sizing nudge

The product's hero element (principle 2 — first-class, affirmative).

  • A card-level call-out: "recommended X, but Y satisfies your requirements for less" with the cheaper system's name, what it still satisfies, and its own action (view/compare). Uses the success trio (soft fill + border) — never warning yellow or muted gray. Must work inside the results page and attached to a comparison-table column.
  • Shipped as NudgeCard (#824/#825): variant="card" (default) is the standalone results form, rendered directly under the lead recommendation with the compare-pair pre-filled action; variant="column" is the compact comparison-column attachment (same success semantics, tighter rhythm) — consumed by the compare column crown.

Coverage warning

  • Calm honesty for partial data or an unmet requirement: warning trio, icon + short text + "verify with an advisor" action. Distinct from both the nudge (positive) and errors (danger). Never blocks interaction.

Resume banner / welcome-back card

  • Non-modal card above hero (home) or stepper (/select): state line ("3 of 14 answered" / "You completed a selection"), primary resume action, secondary start-fresh, dismiss. Must not push the hero below the fold on mobile.

Badges & tier markers

  • Tier labels (Budget / Mid / Premium / Ultra) as neutral, equal-weight badges — differentiated by label, not by escalating visual richness (principle 2: tiers are fit descriptors, not a podium).
  • Status badges (admin): published/draft/retired with success/neutral/ warning treatments.

Admin data tables

  • Dense rows, sortable headers, row actions (edit/retire), pagination or virtualized scroll for 60+ rows, empty state with a create action, bulk-select pattern, and an audit-trail row treatment (--ns-font-mono timestamps). Retired/unpublished rows visually muted but readable.

Shared interaction rules

  • Every interactive element: hover + focus-visible + active states from theme tokens; focus ring via --ns-color-focus.
  • Motion: 0.15s ease-in-out (the house idiom, --nw-transition-fast) as the default; all motion behind prefers-reduced-motion.
  • Overlays/modals (admin confirms): --ns-color-overlay scrim, focus trap, Escape closes. Public surfaces avoid modals entirely (the resume offer is a card, not a dialog).