@hubbiparts/uikit 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,16 +1,25 @@
1
1
  {
2
2
  "name": "@hubbiparts/uikit",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
4
4
  "description": "HubbiParts React UI kit built with shadcn/ui primitives.",
5
5
  "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://gitlab.com/hubbiparts1/uikit.git"
9
+ },
6
10
  "private": false,
7
11
  "publishConfig": {
8
12
  "access": "public"
9
13
  },
10
14
  "type": "module",
11
15
  "files": [
12
- "dist"
16
+ "dist",
17
+ "bin",
18
+ "skills"
13
19
  ],
20
+ "bin": {
21
+ "hubbiparts-uikit": "./bin/hubbiparts-uikit.mjs"
22
+ },
14
23
  "main": "./dist/index.cjs",
15
24
  "module": "./dist/index.js",
16
25
  "types": "./dist/index.d.ts",
@@ -21,6 +30,7 @@
21
30
  "require": "./dist/index.cjs"
22
31
  },
23
32
  "./style.css": "./dist/style.css",
33
+ "./skill": "./skills/hubbiparts-uikit/SKILL.md",
24
34
  "./package.json": "./package.json"
25
35
  },
26
36
  "sideEffects": [
@@ -0,0 +1,149 @@
1
+ ---
2
+ name: hubbiparts-uikit
3
+ description: Installs, uses, updates and audits the @hubbiparts/uikit React component package (HubbiParts design system built on shadcn/ui + Radix + Tailwind v4). Applies whenever a project depends on @hubbiparts/uikit, when building HubbiParts/Hubbi frontend UI, when asked to "install the Hubbi UI kit", "update the uikit", "migrate local shadcn components to the kit", or when importing from '@hubbiparts/uikit'. Prefer it over the generic shadcn skill in those projects.
4
+ user-invocable: true
5
+ allowed-tools: Bash(npx hubbiparts-uikit *), Bash(npm view @hubbiparts/uikit *), Bash(npm outdated @hubbiparts/uikit)
6
+ ---
7
+
8
+ # @hubbiparts/uikit
9
+
10
+ HubbiParts' React UI kit: 61 shadcn/ui components (Radix base, `radix-nova` style), themed with HubbiParts tokens, **distributed as a compiled npm package** — not copied into the project.
11
+
12
+ That single fact changes the shadcn workflow:
13
+
14
+ | shadcn (source copy) | @hubbiparts/uikit (npm package) |
15
+ | --------------------------------------- | ----------------------------------------------------------------- |
16
+ | `npx shadcn add button` | Already shipped — just `import { Button } from '@hubbiparts/uikit'` |
17
+ | Component lives in `@/components/ui` | Component lives in `node_modules`; never edit it there |
18
+ | Update = `shadcn add --diff` | Update = bump the package version (see [maintenance.md](./rules/maintenance.md)) |
19
+ | Customize by editing the file | Compose, use variants, or contribute upstream to the kit |
20
+
21
+ ## Current Project Context
22
+
23
+ ```json
24
+ !`npx hubbiparts-uikit info --json`
25
+ ```
26
+
27
+ If the block above is empty or failed, run `npx hubbiparts-uikit info --json` yourself (the CLI ships with the package; if it is missing, the kit is not installed — see [setup.md](./rules/setup.md)).
28
+
29
+ Key fields:
30
+
31
+ - **`installedVersion` / `latestVersion` / `updateAvailable`** → whether to propose an upgrade.
32
+ - **`styleImportedIn`** → where `@hubbiparts/uikit/style.css` is imported. `null` means components render unstyled: fix that first.
33
+ - **`tailwind.major`** → `4`, `3` or `null`. Decides how project utilities reach kit tokens ([theming.md](./rules/theming.md)).
34
+ - **`isRSC`** → when `true` (Next.js App Router), any file that renders kit components with state/handlers needs `"use client"`. The bundle does not add it for you.
35
+ - **`localDuplicates`** → local shadcn copies (e.g. `src/components/ui/button.tsx`) that duplicate kit components. Migration candidates, never silently delete them.
36
+ - **`components`** → the exact catalog of the installed version. Never import a component that is not listed.
37
+ - **`packageManager`** → use it for installs (`pnpm add`, `npm install`, ...).
38
+ - **`isKitRepository`** → `true` inside the kit's own repo; then follow [contributing.md](./rules/contributing.md) instead.
39
+
40
+ ## Principles
41
+
42
+ 1. **Kit first.** Before writing any UI, check the catalog (`npx hubbiparts-uikit list`). A styled `div` that re-implements a kit component is a bug.
43
+ 2. **Compose, don't reinvent.** Settings page = `Tabs` + `Card` + `FieldGroup`. Dashboard = `Sidebar` + `Card` + `Chart` + `Table`.
44
+ 3. **Variants before classes.** `variant="outline"`, `size="sm"`. `className` is for layout (width, margin, grid placement), not for recoloring.
45
+ 4. **Semantic tokens only.** `bg-primary`, `text-muted-foreground`, `border-border`. Never `bg-blue-600` or `#1E3F9E` — the brand lives in the tokens.
46
+ 5. **One source of truth.** Missing variant or component? Add it to the kit ([contributing.md](./rules/contributing.md)) — do not fork a local copy.
47
+
48
+ ## Critical Rules
49
+
50
+ Always enforced. Details and Incorrect/Correct pairs in the linked files.
51
+
52
+ ### Setup → [setup.md](./rules/setup.md)
53
+ - Import `@hubbiparts/uikit/style.css` **once**, at the app entry, before project CSS.
54
+ - Wrap the app with `TooltipProvider` once; wrap sidebar layouts with `SidebarProvider`.
55
+ - Render `<Toaster />` once near the root; Toaster reads the theme via `next-themes` (`ThemeProvider attribute="class"`).
56
+ - Dark mode is the `.dark` class on an ancestor (usually `<html>`). No `dark:` color overrides.
57
+
58
+ ### Imports → [usage.md](./rules/usage.md)
59
+ - Always `import { X } from '@hubbiparts/uikit'`. Never deep-import `@hubbiparts/uikit/dist/...`.
60
+ - `cn` is exported by the kit: `import { cn } from '@hubbiparts/uikit'`.
61
+ - Icons are `lucide-react`, passed as components, with `data-icon="inline-start|inline-end"` inside buttons and no size classes.
62
+ - `toast()` comes from `sonner` (the kit exports only `Toaster`).
63
+
64
+ ### Composition → [usage.md](./rules/usage.md)
65
+ - Items inside their Group: `SelectItem` → `SelectGroup`/`SelectContent`, `CommandItem` → `CommandGroup`, `DropdownMenuItem` → `DropdownMenuContent`.
66
+ - Custom triggers use `asChild` (Radix base). Exception: `Combobox` is Base UI — use its own props.
67
+ - `Dialog`, `Sheet`, `Drawer`, `AlertDialog` always have a Title (`className="sr-only"` if hidden).
68
+ - Full `Card` composition: `CardHeader`/`CardTitle`/`CardDescription`/`CardContent`/`CardFooter`.
69
+ - Forms: `FieldGroup` + `Field` + `FieldLabel`; validation = `data-invalid` on `Field` + `aria-invalid` on control.
70
+ - Loading buttons: `Spinner` + `disabled`. There is no `isLoading` prop.
71
+ - `Avatar` always has `AvatarFallback`. `TabsTrigger` always inside `TabsList`.
72
+ - Callouts = `Alert`, empty states = `Empty`, placeholders = `Skeleton`, dividers = `Separator`, status = `Badge`.
73
+ - Chat UIs: `MessageScroller` + `Message` + `Bubble` + `Attachment` + `Marker`.
74
+
75
+ ### Styling → [theming.md](./rules/theming.md)
76
+ - `flex flex-col gap-*`, never `space-y-*`. `size-*` for squares. `truncate` shorthand.
77
+ - No manual `z-index` on overlays.
78
+ - Brand typography: `font-display` (Space Grotesk) for headings, `font-sans` (Inter) for UI, `font-mono` (Space Mono) for SKUs, plates, VINs, codes.
79
+ - Brand changes (colors, radius, fonts) are made **in the kit's tokens**, never by overriding classes in a consumer.
80
+
81
+ ### Maintenance → [maintenance.md](./rules/maintenance.md)
82
+ - Check `npx hubbiparts-uikit outdated` at the start of UI work; propose — don't silently perform — major/minor upgrades.
83
+ - Upgrade via the package manager, then run typecheck + tests + build + a visual check.
84
+ - Migrating local shadcn copies to the kit: one component at a time, diff behavior first, keep local customizations as composition.
85
+
86
+ ## Component Selection
87
+
88
+ | Need | Use |
89
+ | -------------------------- | ----------------------------------------------------------------------------------------- |
90
+ | Actions | `Button` (+ `ButtonGroup`), `Toggle`, `ToggleGroup` for 2–7 options |
91
+ | Form inputs | `Input`, `InputGroup`, `Textarea`, `Select`, `NativeSelect`, `Combobox`, `Checkbox`, `RadioGroup`, `Switch`, `Slider`, `InputOTP`, `Calendar` |
92
+ | Form layout | `FieldGroup`, `Field`, `FieldLabel`, `FieldDescription`, `FieldError`, `Label` |
93
+ | Data display | `Table`, `Card`, `Item`, `Badge`, `Avatar`, `Kbd`, `ChartContainer` (Recharts) |
94
+ | Navigation | `Sidebar`, `NavigationMenu`, `Menubar`, `Breadcrumb`, `Tabs`, `Pagination` |
95
+ | Overlays | `Dialog`, `Sheet`, `Drawer`, `AlertDialog`, `Popover`, `HoverCard`, `Tooltip` |
96
+ | Menus | `DropdownMenu`, `ContextMenu`, `Command` (inside `Dialog` for palettes) |
97
+ | Feedback | `Toaster` + `toast()` from sonner, `Alert`, `Progress`, `Skeleton`, `Spinner`, `Empty` |
98
+ | Layout | `Separator`, `ScrollArea`, `ResizablePanelGroup`, `Accordion`, `Collapsible`, `AspectRatio`, `Carousel` |
99
+ | Chat / conversation | `MessageScroller`, `Message`, `Bubble`, `Attachment`, `Marker` |
100
+ | Guided flows | `Questionnaire` |
101
+ | Composition-only (no file) | Data Table = `Table` + state; Date Picker = `Popover` + `Calendar`; Typography = tokens |
102
+
103
+ ## Getting a Component's API
104
+
105
+ Never guess props. The installed version is the contract:
106
+
107
+ ```bash
108
+ npx hubbiparts-uikit docs sidebar dialog # exports + TypeScript signatures of the installed version
109
+ npx hubbiparts-uikit list # every component and its exports
110
+ ```
111
+
112
+ For usage examples and behavior, the shadcn page printed by `docs` (Radix variant) applies — HubbiParts only changes tokens. When the kit signature and the shadcn page disagree, **the kit signature wins**.
113
+
114
+ ## Workflow
115
+
116
+ 1. **Context** — read the injected info (or run `npx hubbiparts-uikit info --json`).
117
+ 2. **Setup check** — `styleImportedIn` set, providers present, Tailwind bridge configured ([setup.md](./rules/setup.md)). Fix before building features.
118
+ 3. **Freshness** — if `updateAvailable`, tell the user and propose the upgrade ([maintenance.md](./rules/maintenance.md)).
119
+ 4. **Pick components** — from the catalog; confirm the API with `docs`.
120
+ 5. **Build** — compose following the Critical Rules; semantic tokens only.
121
+ 6. **Verify** — project typecheck, lint, tests, build, and look at the rendered UI (light and dark).
122
+ 7. **Gaps** — if the kit lacks something, compose it locally in a feature folder (not `components/ui`) and report it as a kit contribution candidate.
123
+
124
+ ## Quick Reference
125
+
126
+ ```bash
127
+ # Install (use the project's package manager)
128
+ npm install @hubbiparts/uikit
129
+ npx hubbiparts-uikit skill install # links this skill into .agents/skills
130
+ npx hubbiparts-uikit skill install --dir .claude/skills
131
+
132
+ # Context & catalog
133
+ npx hubbiparts-uikit info --json
134
+ npx hubbiparts-uikit list
135
+ npx hubbiparts-uikit docs button field select
136
+
137
+ # Updates
138
+ npx hubbiparts-uikit outdated
139
+ npm view @hubbiparts/uikit versions --json
140
+ npm install @hubbiparts/uikit@latest
141
+ ```
142
+
143
+ ## Detailed References
144
+
145
+ - [rules/setup.md](./rules/setup.md) — installation, CSS import, providers, dark mode, Tailwind v3/v4, Next.js/Vite
146
+ - [rules/usage.md](./rules/usage.md) — imports, composition, forms, overlays, icons, toast, Incorrect/Correct pairs
147
+ - [rules/theming.md](./rules/theming.md) — HubbiParts tokens, typography, spacing rules, using tokens in project utilities
148
+ - [rules/maintenance.md](./rules/maintenance.md) — checking versions, upgrading, migrating local shadcn copies, regression checklist
149
+ - [rules/contributing.md](./rules/contributing.md) — adding or updating components in the kit repository and releasing
@@ -0,0 +1,49 @@
1
+ # Contributing to the kit (inside the kit repository)
2
+
3
+ Applies when `info` reports `isKitRepository: true` (package name `@hubbiparts/uikit`). Here the generic **shadcn skill applies** for source edits — components live in `src/components/ui` and are managed with the shadcn CLI.
4
+
5
+ ## Branching
6
+
7
+ Never commit on protected branches (`main`, `dev`). Create `feat/<slug>` from the target branch before editing and preserve uncommitted work with `git switch -c`.
8
+
9
+ ## Adding a component
10
+
11
+ ```bash
12
+ npx shadcn@latest add <component> # writes src/components/ui/<component>.tsx
13
+ ```
14
+
15
+ Then, in the same change:
16
+
17
+ 1. Export it from `src/components/ui/index.ts` (`export * from './<component>'`).
18
+ 2. Add the slug to `publicComponentSlugs` in the same file.
19
+ 3. Add an inventory entry with a dedicated preview in `playground/src/component-inventory.ts` and `playground/src/ComponentInventory.tsx` (the test fails if any entry uses the default preview).
20
+ 4. Add stories if the component belongs to a Storybook category.
21
+ 5. If it needs a new third-party package, add it to `dependencies` **and** to `build.rollupOptions.external` in `vite.config.ts`.
22
+
23
+ ## Updating a component from upstream shadcn
24
+
25
+ Follow the shadcn skill's update flow: `npx shadcn@latest add <component> --dry-run`, then `--diff <file>`, merge preserving HubbiParts changes. Never `--overwrite` without explicit approval.
26
+
27
+ ## Changing tokens
28
+
29
+ Edit `src/index.css` only. Keep semantic names stable — renaming a variable is a breaking change for consumers.
30
+
31
+ ## Validation before release
32
+
33
+ ```bash
34
+ npm run typecheck
35
+ npm run lint
36
+ npm test
37
+ npm run build
38
+ npm run build:playground
39
+ npm publish --dry-run --access public
40
+ ```
41
+
42
+ Check the tarball contains `dist`, `bin/hubbiparts-uikit.mjs` and `skills/hubbiparts-uikit`, and that `npx hubbiparts-uikit list` reflects the new component.
43
+
44
+ ## Release
45
+
46
+ 1. Bump the version (`npm version patch|minor --no-git-tag-version`); on `0.x` use `minor` for breaking changes.
47
+ 2. Update this skill if rules, components or setup changed — it ships with the package and is what consumer agents read.
48
+ 3. Merge the MR into `main` on `gitlab.hubbi.app`. The push mirror sends `main` to `gitlab.com/hubbiparts1/uikit`, whose pipeline publishes via npm Trusted Publishing (OIDC, no token). Never publish from a local machine unless a human explicitly asks for it (it requires the npm account's 2FA/OTP).
49
+ 4. Confirm: `npm view @hubbiparts/uikit version`.
@@ -0,0 +1,74 @@
1
+ # Maintenance: keeping the kit up to date
2
+
3
+ In a consumer project, "updating components" means **updating the package version**. There is nothing to `shadcn add`.
4
+
5
+ ## Check
6
+
7
+ ```bash
8
+ npx hubbiparts-uikit outdated # installed vs latest
9
+ npx hubbiparts-uikit info --json # installedVersion, latestVersion, declaredRange
10
+ npm view @hubbiparts/uikit versions --json # full release list
11
+ ```
12
+
13
+ Do this at the start of any UI task in a consumer project. If `updateAvailable` is true, **tell the user** and propose the upgrade; do not upgrade silently inside an unrelated feature change.
14
+
15
+ ## Semver policy
16
+
17
+ The kit follows semver. While on `0.x`, a **minor** bump (`0.1 → 0.2`) may contain breaking changes; a patch is safe.
18
+
19
+ | Bump | Action |
20
+ | --------------- | ---------------------------------------------------------------------- |
21
+ | Patch | Upgrade, run the checks below. |
22
+ | Minor on `0.x` / Major | Ask the user first; read the release notes/diff of `dist/components/ui/*.d.ts` between versions; upgrade in its own branch/commit. |
23
+
24
+ Compare APIs between versions without installing:
25
+
26
+ ```bash
27
+ npm pack @hubbiparts/uikit@<old> @hubbiparts/uikit@<new> --pack-destination "$TMPDIR"
28
+ # extract both and diff package/dist/components/ui/*.d.ts
29
+ ```
30
+
31
+ ## Upgrade
32
+
33
+ ```bash
34
+ npm install @hubbiparts/uikit@latest # or a pinned version: @0.2.0
35
+ ```
36
+
37
+ Use the project's package manager. Keep the lockfile change in the same commit.
38
+
39
+ If the skill was installed with `--copy`, refresh it:
40
+
41
+ ```bash
42
+ npx hubbiparts-uikit skill install --copy
43
+ ```
44
+
45
+ Symlinked skills update automatically.
46
+
47
+ ## Regression checklist after upgrading
48
+
49
+ 1. `npx hubbiparts-uikit info --json` shows the new `installedVersion`.
50
+ 2. Project typecheck — signature changes surface here first.
51
+ 3. Project lint and tests.
52
+ 4. Project build.
53
+ 5. Visual check of the screens that use changed components, in light and dark mode.
54
+ 6. Report which components changed and what was verified. If something could not be verified (e.g. no browser available), say so.
55
+
56
+ ## Migrating local shadcn copies to the kit
57
+
58
+ `localDuplicates` lists local files such as `src/components/ui/button.tsx` whose slug exists in the kit.
59
+
60
+ 1. Ask the user before starting; migration touches many imports.
61
+ 2. One component at a time. For each:
62
+ - Diff the local file against `npx hubbiparts-uikit docs <slug>` — note custom variants, props or behavior.
63
+ - Local additions that are pure styling → drop them (the kit tokens replace them).
64
+ - Local additions that are real features (new variant, prop) → keep them as composition in a feature component, and report them as kit contribution candidates.
65
+ - Replace imports `@/components/ui/<slug>` → `@hubbiparts/uikit`.
66
+ - Delete the local file only after no import references it (`grep -r "components/ui/<slug>"`).
67
+ 3. Run the regression checklist after each component or small batch.
68
+ 4. Never delete local copies in bulk, never use `--overwrite`-style shortcuts.
69
+
70
+ ## Keeping the dependency healthy
71
+
72
+ - Pin with a caret range (`^0.1.0`) or an exact version according to the project's policy; do not use `*` or `latest` in `package.json`.
73
+ - Do not add `resolutions`/`overrides` for kit internals (Radix, sonner) unless asked; report conflicts to the kit instead.
74
+ - Duplicate React warnings mean the project resolves two React copies — check `npm ls react`; the kit only has React as a peer.
@@ -0,0 +1,90 @@
1
+ # Setup
2
+
3
+ ## Install
4
+
5
+ Use the project's package manager (`packageManager` from `info`):
6
+
7
+ ```bash
8
+ npm install @hubbiparts/uikit # or: pnpm add / yarn add / bun add
9
+ ```
10
+
11
+ Peer dependencies: `react` and `react-dom` `>=18.2 <20`. Everything else (Radix, sonner, recharts, lucide-react, next-themes, ...) is a regular dependency of the kit.
12
+
13
+ If the project also imports `lucide-react` or `sonner` directly, add them to its own `package.json` instead of relying on hoisting.
14
+
15
+ Then install the agent skill so every agent in the repo sees it:
16
+
17
+ ```bash
18
+ npx hubbiparts-uikit skill install # .agents/skills/hubbiparts-uikit (symlink)
19
+ npx hubbiparts-uikit skill install --dir .claude/skills # Claude Code layout
20
+ npx hubbiparts-uikit skill install --copy # copy instead of symlink (e.g. to commit it)
21
+ ```
22
+
23
+ The symlink points into `node_modules`, so the skill always matches the installed kit version. A copied skill must be refreshed after each upgrade.
24
+
25
+ ## Import the stylesheet once
26
+
27
+ The CSS contains the tokens, fonts, base layer and every utility the components use. Without it components render unstyled.
28
+
29
+ ```tsx
30
+ // src/main.tsx (Vite) — before the project's own CSS
31
+ import '@hubbiparts/uikit/style.css'
32
+ import './index.css'
33
+ ```
34
+
35
+ ```tsx
36
+ // app/layout.tsx (Next.js App Router)
37
+ import '@hubbiparts/uikit/style.css'
38
+ import './globals.css'
39
+ ```
40
+
41
+ **Incorrect:** importing `style.css` in several components, or importing `@hubbiparts/uikit/dist/style.css`.
42
+
43
+ ## Providers
44
+
45
+ ```tsx
46
+ import { ThemeProvider } from 'next-themes'
47
+ import { Toaster, TooltipProvider } from '@hubbiparts/uikit'
48
+
49
+ export function AppProviders({ children }: { children: React.ReactNode }) {
50
+ return (
51
+ <ThemeProvider attribute="class" defaultTheme="system" enableSystem>
52
+ <TooltipProvider>
53
+ {children}
54
+ <Toaster position="bottom-right" />
55
+ </TooltipProvider>
56
+ </ThemeProvider>
57
+ )
58
+ }
59
+ ```
60
+
61
+ - `TooltipProvider` once at the root (sidebar tooltips depend on it too).
62
+ - `Toaster` once. It reads the theme through `next-themes`; without `ThemeProvider` it falls back to `system`.
63
+ - `SidebarProvider` wraps only layouts that render a `Sidebar`.
64
+
65
+ ## Dark mode
66
+
67
+ The kit switches on the `.dark` class on an ancestor. `ThemeProvider attribute="class"` sets it on `<html>`. Do not implement dark mode with `dark:` utilities on kit components.
68
+
69
+ ## Tailwind in the consumer project
70
+
71
+ The kit CSS is precompiled; the project does **not** need Tailwind to use the components. It needs Tailwind configuration only so *its own* utilities (`bg-primary`, `font-display`, `rounded-lg`) resolve to kit tokens. See [theming.md](./theming.md#using-tokens-in-project-utilities) for the v4 and v3 snippets.
72
+
73
+ The kit already ships Tailwind's preflight. With Tailwind v3 in the project this means preflight runs twice — harmless — but do not disable the kit's base layer.
74
+
75
+ ## Next.js App Router (`isRSC: true`)
76
+
77
+ The bundle has no `"use client"` directive. Import kit components from client components:
78
+
79
+ ```tsx
80
+ 'use client'
81
+ import { Button, Dialog, DialogContent, DialogTitle, DialogTrigger } from '@hubbiparts/uikit'
82
+ ```
83
+
84
+ Server components may render purely presentational kit components (`Card`, `Badge`, `Separator`) only if they do not pass handlers; when in doubt, add `'use client'` to the file.
85
+
86
+ ## Setup verification
87
+
88
+ 1. `npx hubbiparts-uikit info --json` → `styleImportedIn` not null, `installedVersion` set.
89
+ 2. Render a `Button` and a `Dialog`: button is HubbiParts blue (`#1E3F9E` light), dialog overlays correctly.
90
+ 3. Toggle `.dark` on `<html>`: surfaces and text switch without any extra class.
@@ -0,0 +1,135 @@
1
+ # Theming & Styling
2
+
3
+ The brand is encoded in CSS variables shipped by `@hubbiparts/uikit/style.css`. Consumers **use** tokens; they never redefine the brand.
4
+
5
+ ## HubbiParts tokens
6
+
7
+ | Role | Token (use this) | Value (reference only) |
8
+ | ----------------------- | ---------------------------------------------- | ------------------------------- |
9
+ | Primary | `bg-primary` / `text-primary-foreground` | `#1E3F9E` (light), lighter in dark |
10
+ | Secondary brand blue | `--blue-400` | `#576DB5` |
11
+ | Surfaces | `bg-background`, `bg-card`, `bg-popover`, `bg-muted` | steel-blue neutrals |
12
+ | Text | `text-foreground`, `text-muted-foreground` | |
13
+ | Borders / focus | `border-border`, `border-input`, `ring-ring` | |
14
+ | Danger | `destructive` variants, `text-destructive` | |
15
+ | Charts | `var(--chart-1)` … `var(--chart-5)` | |
16
+ | Sidebar | `bg-sidebar`, `text-sidebar-foreground`, … | |
17
+ | Radius | `rounded-sm` … `rounded-2xl` (squircle-like brand radii) | `lg` = 16px |
18
+ | Fonts | `font-display`, `font-sans`, `font-mono` | Space Grotesk / Inter / Space Mono |
19
+
20
+ The hex values are for recognition only. **Never write them in code.**
21
+
22
+ ```tsx
23
+ // Correct
24
+ <span className="text-muted-foreground">Updated</span>
25
+ <Badge variant="secondary">In stock</Badge>
26
+
27
+ // Incorrect
28
+ <span className="text-[#6B7A99]">Updated</span>
29
+ <span className="bg-green-100 text-green-700">In stock</span>
30
+ ```
31
+
32
+ ## Typography
33
+
34
+ - Headings, big numbers, hero text: `font-display`.
35
+ - Interface copy, labels, tables: `font-sans` (default).
36
+ - SKUs, plates, VINs, part numbers, codes: `font-mono`.
37
+
38
+ ## Styling rules
39
+
40
+ - `className` on kit components is for **layout**: width, margin, grid/flex placement, `max-w-*`. Not for colors, font sizes or borders.
41
+ - Stacks: `flex flex-col gap-4`, never `space-y-4`. Rows: `flex items-center gap-2`.
42
+ - Squares: `size-10`, not `w-10 h-10`.
43
+ - Ellipsis: `truncate`.
44
+ - Conditional classes: `cn()` from the kit, not template-literal ternaries.
45
+ - Dark mode: tokens handle it. No `dark:bg-*` / `dark:text-*` on kit components.
46
+ - Overlays manage stacking. No `z-*` on `DialogContent`, `PopoverContent`, etc.
47
+
48
+ ## Using tokens in project utilities
49
+
50
+ The kit CSS contains only utilities the kit itself uses. For the project's own markup to use `bg-primary`, `font-display`, etc., its Tailwind must map to the kit variables.
51
+
52
+ ### Tailwind v4 (`tailwind.major === 4`)
53
+
54
+ ```css
55
+ /* src/index.css — after `@import "tailwindcss";` */
56
+ @custom-variant dark (&:is(.dark *));
57
+
58
+ @theme inline {
59
+ --color-background: var(--background);
60
+ --color-foreground: var(--foreground);
61
+ --color-card: var(--card);
62
+ --color-card-foreground: var(--card-foreground);
63
+ --color-popover: var(--popover);
64
+ --color-popover-foreground: var(--popover-foreground);
65
+ --color-primary: var(--primary);
66
+ --color-primary-foreground: var(--primary-foreground);
67
+ --color-secondary: var(--secondary);
68
+ --color-secondary-foreground: var(--secondary-foreground);
69
+ --color-muted: var(--muted);
70
+ --color-muted-foreground: var(--muted-foreground);
71
+ --color-accent: var(--accent);
72
+ --color-accent-foreground: var(--accent-foreground);
73
+ --color-destructive: var(--destructive);
74
+ --color-border: var(--border);
75
+ --color-input: var(--input);
76
+ --color-ring: var(--ring);
77
+ --font-sans: var(--font-body-family);
78
+ --font-display: var(--font-display-family);
79
+ --font-mono: var(--font-mono-family);
80
+ --radius-sm: var(--radius-sm-brand);
81
+ --radius-md: var(--radius-md-brand);
82
+ --radius-lg: var(--radius-lg-brand);
83
+ --radius-xl: var(--radius-xl-brand);
84
+ --radius-2xl: var(--radius-2xl-brand);
85
+ }
86
+ ```
87
+
88
+ ### Tailwind v3 (`tailwind.major === 3`)
89
+
90
+ ```js
91
+ // tailwind.config.js
92
+ export default {
93
+ darkMode: 'class',
94
+ theme: {
95
+ extend: {
96
+ colors: {
97
+ background: 'var(--background)',
98
+ foreground: 'var(--foreground)',
99
+ card: { DEFAULT: 'var(--card)', foreground: 'var(--card-foreground)' },
100
+ popover: { DEFAULT: 'var(--popover)', foreground: 'var(--popover-foreground)' },
101
+ primary: { DEFAULT: 'var(--primary)', foreground: 'var(--primary-foreground)' },
102
+ secondary: { DEFAULT: 'var(--secondary)', foreground: 'var(--secondary-foreground)' },
103
+ muted: { DEFAULT: 'var(--muted)', foreground: 'var(--muted-foreground)' },
104
+ accent: { DEFAULT: 'var(--accent)', foreground: 'var(--accent-foreground)' },
105
+ destructive: 'var(--destructive)',
106
+ border: 'var(--border)',
107
+ input: 'var(--input)',
108
+ ring: 'var(--ring)',
109
+ },
110
+ fontFamily: {
111
+ sans: 'var(--font-body-family)',
112
+ display: 'var(--font-display-family)',
113
+ mono: 'var(--font-mono-family)',
114
+ },
115
+ borderRadius: {
116
+ sm: 'var(--radius-sm-brand)',
117
+ md: 'var(--radius-md-brand)',
118
+ lg: 'var(--radius-lg-brand)',
119
+ xl: 'var(--radius-xl-brand)',
120
+ '2xl': 'var(--radius-2xl-brand)',
121
+ },
122
+ },
123
+ },
124
+ }
125
+ ```
126
+
127
+ Opacity modifiers (`bg-primary/50`) need `color-mix`-capable values in v3; prefer the kit's variants over opacity tricks.
128
+
129
+ ### No Tailwind (`tailwind.major === null`)
130
+
131
+ Use the variables directly in CSS modules: `color: var(--muted-foreground)`.
132
+
133
+ ## Changing the brand
134
+
135
+ Token or font changes belong in the kit's `src/index.css` and ship as a new kit version ([contributing.md](./contributing.md)). A consumer redefining `--primary` forks the design system — do it only when the user explicitly asks for a local theme, and scope it to a wrapper class, never `:root`.