"Refined Carbon" — the shared React component library and design language behind Carbon Backbone.
Dark-mode-first, data-dense but breathable, with a warm amber accent over carbon blacks and monospace numerals for accounting alignment. Documented and developed in Storybook.
pnpm install
pnpm dev # Storybook at http://localhost:6006
pnpm build # Static Storybook into ./storybook-static
pnpm typecheck # Type-check the packagesrc/
├── styles/theme.css # Design tokens — the single source of truth (Tailwind v4 @theme)
├── lib/ # cn() class merge + money/date formatters
├── components/ui/ # Components + their *.stories.tsx
├── stories/
│ ├── Introduction.mdx
│ └── foundations/ # Colors · Typography · Spacing · Radius
└── index.ts # Public barrel export
- React 19 + TypeScript
- Tailwind CSS v4 (
@themetokens, notailwind.config) - Radix UI primitives
- class-variance-authority for variants
- Storybook 8 (react-vite) with autodocs + a11y addon
Dark-mode-first, with a light theme. Toggle modes from the Theme switch in the Storybook
toolbar. In an app, dark is the default; add the .light class to a root element to switch:
<html class="light"> ... </html>Only the semantic tokens (surfaces, text, borders, accent, and the adaptive
accent/success/error/info text colors) remap — the raw palette stays fixed. Components
reference semantic tokens, so they adapt with no code changes. See the Theming block in
src/styles/theme.css.
Components never emit fixed palette utilities (text-amber-400, bg-green-500/15, …) — those
do not adapt when the theme flips and fail WCAG AA on light surfaces. Instead they use the
semantic tokens below. If you supply your own theme instead of importing
@codelittinc/carbon-design-system/styles, you must define every --color-* variable here
(with light/dark values), or the compiled components render with no color:
| Token (utility) | CSS variable | Role |
|---|---|---|
text-accent-text |
--color-accent-text |
Accent text/number, readable on the surface |
bg-accent · border-accent · ring-accent |
--color-accent |
Solid accent fills, active borders, focus rings |
bg-accent-hover |
--color-accent-hover |
Accent hover state |
bg-accent-muted |
--color-accent-muted |
Soft accent fill (badge, selected row, count pill) |
text-success-text · text-error-text · text-info-text |
--color-{success,error,info}-text |
Adaptive status text |
bg-success-soft · bg-error-soft · bg-info-soft |
--color-{success,error,info}-soft |
Soft status fills (badges, toasts) |
border-success-border · border-error-border |
--color-{success,error}-border |
Status borders (toasts) |
Each token pair (soft fill + text) is tuned to clear WCAG AA (≥4.5:1) in both themes. The
raw carbon-* foundation scale and the amber accent ramp stay fixed by design; the
theme-independent public/vendor variants of the address inputs intentionally pin their own
color scheme and do not read these tokens.
Story example copy is bilingual — English and Spanish are the only supported languages. Flip every story with the Language toggle (🌐) in the Storybook toolbar.
Built on react-i18next. The shared instance lives in
src/i18n/index.ts; each story registers its own namespace via
i18n.addResourceBundle("en" | "es", "<component>", { … }) and renders with
useTranslation("<component>"). Because components are presentational, i18n applies only to
example copy — status codes, amounts, and names are left as data.
All tokens live in src/styles/theme.css and generate the Tailwind
utilities used throughout the components — there are no hard-coded hex values in component code.
| Token group | Examples |
|---|---|
| Colors | carbon-50…950, amber-300…900, success/error/warning/info, semantic surface/text-*/border, adaptive accent-*/*-text/*-soft/*-border (see Theming) |
| Typography | font-display (Instrument Serif), font-body (DM Sans), font-mono (JetBrains Mono), .tabular-nums |
| Spacing | tightened scale px → 20 (1px → 80px) |
| Radius | sm 4px · md 6px · lg 8px · xl 12px |
Published to GitHub Packages under the @codelittinc scope. Point the scope
at the GitHub registry (once per consuming project) in an .npmrc:
@codelittinc:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}
GITHUB_TOKEN needs the read:packages scope. Then:
pnpm add @codelittinc/carbon-design-systemimport "@codelittinc/carbon-design-system/styles";
import { Button, Badge, DataTable, useToast } from "@codelittinc/carbon-design-system";Tailwind consumers: the components ship pre-built with literal utility class names, so add the package to your Tailwind sources so those classes are generated — in Tailwind v4:
@source "../node_modules/@codelittinc/carbon-design-system/dist";
Forms: Button · Input · Textarea · Checkbox · Switch · Select · MoneyInput · SearchSelect · AddressAutocomplete Overlays: Dialog · AlertDialog · DropdownMenu · Sheet · Popover · Tooltip · CommandPalette · Toast Data display: Badge · StatusBadge · DataTable · Tabs · Progress · Skeleton · Separator · ScrollArea · EmptyState · PageHeader
These components were ported from the Carbon Backbone web app as the starting point for a shared library. The originals remain in the app; this repository is the canonical home going forward.