@brite-nites/design-system
v0.5.2
Published
BriteBase Design System — React primitives + Tailwind v4 tokens for Brite-Nites apps.
Downloads
507
Readme
@brite-nites/design-system
The Brite Design System — React 19 + Tailwind v4 primitives and tokens shared across Brite-Nites apps (brite-supply-commerce, brite-lms, brite-labs, brite-roster, lseo-tool, email-infrastructure-orchestration-platform, brite-pim, brite-base).
Live sandbox — browse every primitive, web-section, and dashboard-card block: https://brite-design-system-sandbox.vercel.app
History — this repo previously hosted a private shadcn-registry + Storybook architecture targeting multi-brand theming. That structure is preserved on the
legacy/storybook-registrybranch (and thev0-storybook-registrytag). The current main branch is a fresh flat npm package per Phase 2 of the cross-repo migration plan.
Status
Published on public npm. Tokens, primitives, and fonts are ported and shipping; consumers npm install with no auth. A live Sandbox app previews the entire system, and CI builds + typechecks every PR.
| Slice | Status |
|---|---|
| Tokens (/styles) | ✅ Shipped |
| Lib (cn + hooks) | ✅ Shipped |
| Build pipeline (tsup + tsc) | ✅ Shipped |
| Public-npm publish workflow | ✅ Shipped |
| CI — build + typecheck on PRs | ✅ Shipped |
| 56 shadcn primitives (/ui) | ✅ Ported |
| 42 Brite* primitives (/primitives) | ✅ Ported |
| Fonts (Geist Sans / Mono, Magda) | ✅ Shipped |
| Sandbox app (live preview) | ✅ Live — brite-design-system-sandbox.vercel.app |
| Sandbox scaffold CLI (@brite-nites/create-sandbox) | Available |
Install (consumers)
Published on public npm, scope @brite-nites — no registry config or auth token needed.
npm install @brite-nites/design-systemAny package manager works — pnpm add, yarn add, or bun add resolve it the same way, with no .npmrc and no token.
In a Next.js App Router + Tailwind v4 project, add to src/app/globals.css:
@import "tailwindcss";
@import "tw-animate-css";
@import "@brite-nites/design-system/styles";tw-animate-css is a required peer dependency — the open/close animations on dialogs, sheets, popovers, selects, and tooltips are animate-in / animate-out utilities that it provides. Without its @import (after @import "tailwindcss";) those components render with no transitions and no error.
…or import slices individually if you only want some of the layers:
@import "@brite-nites/design-system/styles/tokens"; /* CSS vars + @theme block */
@import "@brite-nites/design-system/styles/components"; /* .btn-*, scrollbars, animations */Then in TS:
import { cn, useIsMobile } from "@brite-nites/design-system/lib";
import { Button } from "@brite-nites/design-system/ui";
import { BriteTable } from "@brite-nites/design-system/primitives";Peer dependencies
Since 0.3.1 the peers are split into required (declared) and subpath
(documented) — ADR-0002 for the split, ADR-0003 for why the twelve are not
declared: GitHub Packages strips peerDependenciesMeta from the metadata it
serves, so declaring them at all forces every consumer to install all twelve
and hard-fails installs on any version drift.
Required — the only declared peers; every consumer installs these seven:
react, react-dom, next, tailwindcss, radix-ui,
@phosphor-icons/react, tw-animate-css.
(tw-animate-css has zero JS imports — it is the CSS animation layer @imported
in globals.css per the Install section. Required, not dead weight.)
Subpath peers — your package manager will NOT install these and never checks their versions. Install one only when you import a subpath that needs it. The ranges are what the design system is verified against — staying inside them is on you:
| Subpath export | Install to use it |
|---|---|
| /ui/chart | recharts (^2.15.0 \|\| ^3.0.0) |
| /ui/calendar | react-day-picker |
| /primitives/brite-calendar | react-day-picker, date-fns |
| /primitives/property-field | date-fns |
| /ui/form | react-hook-form |
| /primitives/brite-form-dialog | react-hook-form |
| /ui/command | cmdk |
| /ui/drawer | vaul |
| /ui/input-otp | input-otp |
| /ui/sonner | sonner, next-themes |
| /ui/carousel | embla-carousel-react |
| /ui/resizable | react-resizable-panels |
| /ui/combobox | @base-ui/react |
Importing a subpath without its peer installed fails at build/import time with a
module-not-found error naming the package — install the row above and it
resolves. This table is enforced by check:peers in CI.
Two sharp edges:
- Barrel imports need everything.
/ui,/primitives, and the root barrel statically re-export every component, so importing a barrel pulls every subpath peer into your module graph. To stay peer-light, import per component (@brite-nites/design-system/ui/button). - The seven required peers still hard-fail npm installs on version
conflicts. If e.g. your tree pins
radix-uiornextoutside our range,npm installraises ERESOLVE. The twelve subpath peers can't conflict at install time — but that also means nothing warns you when your installed version drifts outside the table's verified range.
Fonts
The design system uses Geist Sans, Geist Mono, and Magda Clean (eyebrow). The package ships Magda Clean as a binary; Geist Sans/Mono are configured by the consumer through next/font/google so Next.js can apply build-time subsetting + preload hints.
1. Import Magda CSS in globals.css
@import "tailwindcss";
@import "@brite-nites/design-system/styles";
@import "@brite-nites/design-system/fonts/magda";This declares the @font-face for Magda Clean (woff2 ships in dist/fonts/) and sets the --font-magda variable that the package's @theme block maps to --font-eyebrow.
2. Configure Geist Sans/Mono in your layout
// src/app/layout.tsx
import { Geist, Geist_Mono } from "next/font/google";
const geistSans = Geist({ variable: "--font-geist-sans", subsets: ["latin"] });
const geistMono = Geist_Mono({ variable: "--font-geist-mono", subsets: ["latin"] });
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body className={`${geistSans.variable} ${geistMono.variable} antialiased`}>
{children}
</body>
</html>
);
}The variable names --font-geist-sans and --font-geist-mono are what the package's @theme block maps to font-sans and font-mono Tailwind keywords.
Develop
pnpm install
pnpm dev # tsup --watch
pnpm build # tsup + post-build copy of /styles + /fonts into dist/
pnpm typecheck # tsc --noEmitRelease
Cut a tag matching v* (e.g. v0.1.0) — the .github/workflows/publish.yml workflow builds and publishes to GitHub Packages.
# bump version in package.json
git commit -am "release: v0.1.0"
git tag v0.1.0
git push origin main --tagsRepo layout
brite-design-system/
├── src/
│ ├── index.ts # root barrel (re-exports lib + ui + primitives)
│ ├── lib/ # cn() + framework-agnostic hooks
│ ├── ui/ # shadcn primitives (new-york style, neutral base)
│ ├── primitives/ # Brite* primitives composed from shadcn + base-ui
│ ├── fonts/ # next/font/local loaders + woff2 binaries
│ └── styles/
│ ├── tokens.css # :root + .dark + @theme inline (Layer 1 + Layer 2)
│ ├── components.css # .btn-*, .scrollbar-*, animations, base resets
│ └── index.css # entry — @imports both
├── scripts/copy-static.mjs # post-build: mirror /styles + /fonts into dist/
├── .github/workflows/publish.yml # tag-triggered GitHub Packages publish
├── tsup.config.ts # multi-entry ESM + dts
├── tsconfig.json
└── package.jsonMigration & consumer compat
- React 19 required (peer dep
^19) - Next.js 15.5+ or 16 required (peer dep
^15.5 || ^16) - Tailwind v4 required (peer dep
^4). Will not work with v3 — consumers must finish v4 migration first. - shadcn style:
new-york— consumers ondefault/base-nova/radix-mirawill see subtle layout drift; recommended to migrate consumer tonew-york. See Phase 5b in the cross-repo migration plan.
License
Internal — UNLICENSED. Not for public distribution.
