@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:
- Depend on
@bloom/ui(workspace:*) and add@bloom/config/tailwind-preset.jsto the app's Tailwindpresets. - Add
../../packages/ui/src/**/*.{ts,tsx}to the app's Tailwindcontentglobs. @import "@bloom/ui/tokens.css";at the top of the app's Tailwind entry CSS.- 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 tostorybook-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):
- Sign in at chromatic.com with the
hidden-clawGitHub org and create a project forhidden-claw/bloom-ai. - Copy the project token from the project's Manage → Configure page.
- Add it as the
CHROMATIC_PROJECT_TOKENrepository 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.