Skip to content

feat(badge): Badge primitive (shadcn v4) + gallery showcase#49

Merged
SiphoChris merged 10 commits into
mainfrom
feat/flutterbits-badge
Jun 15, 2026
Merged

feat(badge): Badge primitive (shadcn v4) + gallery showcase#49
SiphoChris merged 10 commits into
mainfrom
feat/flutterbits-badge

Conversation

@SiphoChris

Copy link
Copy Markdown
Owner

Badge — the third flutterbits primitive

Ships Badge at apps/gallery/lib/components/ui/badge.dart — a Material-free, themeable, shadcn-v4-faithful variant pill. It's the canonical shape for a variant-based, non-interactive, single-box primitive: Button's variant discipline (typed enum + exhaustive switch + record palette) without Button's interaction-state machine, and Card's non-interactive stance without Card's composition.

shadcn v4 class mapping

Authoritative base (new-york-v4): inline-flex w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-full border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap [&>svg]:size-3.

shadcn flutterbits
rounded-full / overflow-hidden .roundedFull / .clip()
border border-transparent + outline border-border every variant .border(1, color:) — transparent Color(0x00000000) (filled) / c.border (outline)
px-2 py-0.5 text-xs font-medium gap-1 .px(2).py(0.5).textSize(FwFontSize.xs.px).weight(FwFontWeight.medium) + FwRow(gap:1)
[&>svg]:size-3 IconTheme.merge(size:12) (pins icon size independent of text size)
default→primary / secondary / destructive / outline BadgeVariant {primary, secondary, destructive, outline}

Design decisions

  • Non-interactive (StatelessWidget). shadcn's default badge is a <span>; its hover states are [a&]: (link-only). Clickability is composed by wrapping — documented, consistent with Card.
  • defaultprimary (Dart reserved word), every other shadcn name verbatim. No size enum (shadcn's Badge has one size).
  • Faithful-token deviations (documented in the class doc, matching Button): destructive foreground uses the destructiveForeground token, not a literal text-white (AGENTS.md §3.1 bans color literals except transparent; ≈ white in the stock theme and it reskins); the dark:bg-destructive/60 refinement is dropped in favor of the flat destructive token both brightnesses.
  • Sizes to its content (w-fit) — documented behavior in a stretch parent (wrap in Align/FwRow).
  • semanticLabel replaces child semantics via Semantics(excludeSemantics: true) — verified empirically (without it a text child double-announces). Icon-only badges must pass it.

Tests

  • 9 behavior tests: per-variant fill tokens, outline transparent-fill + visible border-token border, foreground token (destructive→destructiveForeground), icon slots (gap-1 horizontal Flex, mainAxisSize.min), semanticLabel replacement for both icon-only and text children (no double-announce), RTL composition, theme reskin (dark token present, light absent).
  • Golden grid (badge_golden_test.dart) — all 4 variants + icon slots, light / dark / RTL.
  • Rendered in apps/gallery (Badges section) + smoke-tested.

Goldens are provisional (generated on Windows). They will be re-baselined from the CI Linux gallery-golden-failures artifact once this PR's gallery job runs (the Button/Card precedent — Windows AA differs from CI Linux).

Also

  • Charter §8 sequencing note records Badge shipped (no-drift).
  • .gitignore: generalized the golden-failure-artifact rule to **/test/**/failures/ so it covers every package/app test tree (it previously only matched a root-level test/).

Executed via superpowers subagent-driven-development (implementer + spec-review + code-quality-review; review findings triaged and applied — excludeSemantics, foreground/border/Flex test guards).

🤖 Generated with Claude Code

Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com

@vercel

vercel Bot commented Jun 15, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
flutterbits Ready Ready Preview, Comment Jun 15, 2026 11:33am

@SiphoChris SiphoChris merged commit 16de440 into main Jun 15, 2026
8 checks passed
@SiphoChris SiphoChris deleted the feat/flutterbits-badge branch June 15, 2026 11:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant