@cellarnode/ui
v0.197.0
Published
Shared UI components, theme tokens, and chat/offer primitives for CellarNode dashboards.
Downloads
14,788
Readme
Shared React component library for CellarNode dashboards. Ships UI primitives, design tokens, chat components, offer components, a globe visualisation, and a Kanban drag-and-drop system — all typed, tree-shakeable, and tested via Storybook.
Contents
- Architecture
- Install
- Peer Dependencies
- Exports
- Theme & Design Tokens
- Development
- Writing Stories
- Make Commands
- Storybook MCP (AI Integration)
- Publishing
Architecture
src/
├── components/ UI primitives (Button, Card, Dialog, Table, Sidebar…)
├── chat/ Chat & negotiation UI (ChatShell, ChatMessageList, ConnectionBanner)
├── offer/ Offer workflow components (BeverageDetails, OrgBanner…)
├── globe/ Interactive 3-D globe visualisation (react-globe.gl)
├── hooks/ Shared hooks (useIsMobile, useToast, useKanbanDnd)
├── lib/ Utilities (cn, semantic tones, currencies, kanban transitions)
└── theme/
└── tokens.css Canonical Tailwind v4 design tokensPrimitive layers
| Layer | Package | Used for |
|-------|---------|----------|
| Radix UI | @radix-ui/* | Dialog, Dropdown, Select, Tabs, Toast… |
| Headless UI | @headlessui/react | Dropdown (Catalyst), Fieldset, Combobox |
| shadcn/ui | built on Radix | Chat & offer internal variants |
Install
pnpm add @cellarnode/uiNote: This package is public on npmjs.org (
publishConfig.access: "public", CEL-1983); installs need no registry auth. The repo.npmrcstill routes the@cellarnodescope to registry.npmjs.org and reads${NPM_TOKEN}if one is set.
Peer Dependencies
Install the peers your app uses:
# Always required
pnpm add react react-dom
# Optional — only needed when importing the specific sub-path
pnpm add motion # animations
pnpm add @dnd-kit/react @dnd-kit/dom # ./kanban-dnd
pnpm add @tanstack/react-query # chat hooks
pnpm add react-globe.gl three topojson-client world-atlas # ./globe
pnpm add @cellarnode/beverage-utils i18n-iso-countries # ./offerExports
| Import path | Contents |
|-------------|----------|
| @cellarnode/ui | All UI primitives, hooks, and utilities |
| @cellarnode/ui/theme/tokens.css | Tailwind v4 design token CSS |
| @cellarnode/ui/chat | ChatShell, ChatMessageList, ConnectionBanner, MessengerLayout, chat hooks |
| @cellarnode/ui/offer | BeverageDetails, OrgBanner, OfferStatusBadge… |
| @cellarnode/ui/kanban-dnd | KanbanDndBoard component |
| @cellarnode/ui/kanban-dnd-hooks | useDraggableCard, useDroppableColumn |
| @cellarnode/ui/globe | GlobeView component |
| @cellarnode/ui/animated-list | AnimatedList component |
Theme & Design Tokens
Import the canonical token sheet before Tailwind in your app's root CSS:
@import "@cellarnode/ui/theme/tokens.css";
@import "tailwindcss";Tokens expose semantic CSS variables (--color-background, --color-primary, --color-brand-secondary, etc.) that are automatically mapped into Tailwind utility classes.
Light/dark mode is toggled by adding the dark class to <html>.
Development
Prerequisites: Node 20+, pnpm 9+, Playwright Chromium (for browser tests).
# Install dependencies
pnpm install
# Install Playwright browser
pnpm playwright install chromium
# Start Storybook dev server
make storybook # → http://localhost:6006
# Type-check
make typecheck
# Lint
make lint
# Run tests (Storybook browser tests, headless)
make test
# Full build
make buildWriting Stories
Every component must have a .stories.tsx file co-located next to it.
import type { Meta, StoryObj } from "@storybook/react-vite";
import { Button } from "./button";
const meta = {
title: "Components/Button",
component: Button,
tags: ["autodocs"],
} satisfies Meta<typeof Button>;
export default meta;
type Story = StoryObj<typeof meta>;
export const Default: Story = {
args: { children: "Click me" },
};
export const Variants: Story = {
render: () => (
<div className="flex gap-3">
<Button color="brand">Brand</Button>
<Button outline>Outline</Button>
<Button plain>Plain</Button>
</div>
),
};Conventions
tags: ["autodocs"]→ auto-generated prop docs- Include a
Defaultstory + at least one variant story - Use
argTypesfor enum-like props (color, size, variant) - Check the A11y addon panel — fix all violations before merging
- Toggle light / dark via the Themes toolbar
- Write
playfunctions for interaction testing when behaviour is complex
Make Commands
make build Full build: lint + typecheck + compile
make clean Remove dist/
make compile Compile TypeScript to dist/
make lint Run ESLint
make typecheck TypeScript type checking (no emit)
make test Run Storybook/Vitest browser tests (headless Chromium)
make test-watch Run Vitest in watch mode
make storybook Start Storybook dev server on :6006
make build-storybook Build static Storybook to storybook-static/
make publish Manual fallback ONLY — build and publish current version to npm (not the normal path)
make release-patch Bump patch version, commit, and git tag (CI publishes on merge to main)
make release-minor Bump minor version, commit, and git tag (CI publishes on merge to main)
make release-major Bump major version, commit, and git tag (CI publishes on merge to main)Storybook MCP (AI Integration)
When Storybook is running (make storybook), the @storybook/addon-mcp addon exposes an MCP server at http://localhost:6006/mcp.
Register it with Claude Code once:
claude mcp add storybook-mcp --transport http http://localhost:6006/mcp --scope projectAvailable MCP tools:
| Tool | Description |
|------|-------------|
| get_ui_building_instructions | Guidelines for creating components and stories |
| get_story_urls | Direct browser links to every story |
Component manifest (for AI context): http://localhost:6006/manifests/components.html
Publishing
Packages are published to npm (public access — publishConfig.access: "public", see CEL-1983) via npm Trusted Publishing (OIDC) —
.github/workflows/publish.yml publishes automatically on a merge to main that changes
package.json's version. Nobody runs npm publish by hand; there is no long-lived npm token
in the publish job. Releases are cut locally via Make, then landed through a normal PR:
make release-patch # 0.2.1 → 0.2.2
make release-minor # 0.2.1 → 0.3.0
make release-major # 0.2.1 → 1.0.0Each release target: bumps version in package.json, rolls CHANGELOG.md, builds, commits, and
creates a git tag ui-vX.Y.Z — it does not publish. Push the branch, open a PR, and merging
to main triggers CI's publish job. make publish remains as an explicit manual fallback (needs
a local npm login with publish rights); it is not the normal path.
