Skip to main content

@bloom/ui

Shared Bloom UI, extracted from bloom-web (#481): the eight shadcn new-york primitives (avatar, badge, button, card, dropdown-menu, input, skeleton, textarea), the BloomMark glyph, ThemeProvider/useTheme/ThemeToggle, and the cn class helper.

Source-only package: consumers compile src/ with their own bundler (Vite). To wire an app up:

  1. Depend on @bloom/ui (workspace:*) and add @bloom/config/tailwind-preset.js to the app's Tailwind presets.
  2. Add ../../packages/ui/src/**/*.{ts,tsx} to the app's Tailwind content globs.
  3. @import "@bloom/ui/tokens.css"; at the top of the app's Tailwind entry CSS.
  4. Mount <ThemeProvider storageKey="..."> - the localStorage key is a prop so each app keeps its own theme preference.

Storybook

The component workbench (M28) lives in this package - Storybook 10, Vite builder, wired to the shared Tailwind preset + tokens.css so stories render with real theming, with a light/dark toolbar toggle (@storybook/addon-themes) plus the docs and a11y addons.

  • pnpm -F @bloom/ui storybook - dev server on port 6006.
  • pnpm -F @bloom/ui build-storybook - static build to storybook-static/ (built in CI as a non-deploying check).

Stories live in stories/ (not src/) so consumer apps' Tailwind content globs, which scan packages/ui/src/**, never pick up story-only classes.

Chromatic (visual regression)

Every PR publishes this Storybook to Chromatic via .github/workflows/chromatic.yml (M28-4), which snapshots stories and diffs them against the accepted baselines.

One-time setup (until then the workflow is a clean no-op and CI stays green):

  1. Sign in at chromatic.com with the hidden-claw GitHub org and create a project for hidden-claw/bloom-ai.
  2. Copy the project token from the project's Manage → Configure page.
  3. Add it as the CHROMATIC_PROJECT_TOKEN repository secret (Settings → Secrets and variables → Actions).

Reviewing diffs (accept-baseline flow): a visual change never hard-fails PR CI - it shows up as the Chromatic "UI Tests" check on the PR ("X changes must be accepted"). The reviewer opens the check's Chromatic build, compares each snapshot against the baseline, and accepts (intended change - the snapshot becomes the new baseline) or denies (regression - fix the code and push again) each diff. There is no auto-accept in CI; baselines only move when a human accepts them in the Chromatic UI. Pushes to main run strict (a leftover unaccepted diff fails there), since all diffs should have been accepted during PR review.

TurboSnap (onlyChanged: true) traces each PR's changed files through the Vite dependency graph and only snapshots the affected stories, so PRs that don't touch @bloom/ui (or its Storybook config) skip snapshotting entirely and cost nothing.