aperia-ds5
v0.1.4
Published
Aperia design system — UI component library built on React 19, Tailwind CSS v4, and shadcn/ui.
Readme
aperia-ds5
Aperia design system — UI component library built on React 19, Tailwind CSS v4, and shadcn/ui.
Tech Stack
| | | |---|---| | React 19 | UI runtime | | Tailwind CSS v4 | Styling | | shadcn/ui | Component primitives | | Storybook 10 | Component development and documentation | | tsup | Library build | | Figma Code Connect | Figma ↔ code mappings |
Contributing (working inside this repo)
Requirements: Node.js 20+, npm 10+
npm install # installs deps and builds dist/ via prepare
npm run dev # start Storybook at http://localhost:6006Scripts
| Script | Description |
|---|---|
| npm run dev | Storybook dev server |
| npm run build:lib | Compile library → dist/ (ESM + types) |
| npm run build:storybook | Build Storybook for static deployment |
| npm run lint | ESLint |
| npm run format | Prettier |
| npm run typecheck | TypeScript check (no emit) |
| npm run cc:publish | Publish all Code Connect mappings to Figma |
| npm run generate:icons | Regenerate icon Code Connect from Figma (needs FIGMA_ACCESS_TOKEN in .env.local) |
| npm run publish:icons | Publish icon Code Connect mappings to Figma |
Adding a new component
- Scaffold with the
shadcnCLI - Move into
components/ui/<name>/<name>.tsx - Re-export from
components/ui/index.ts - Run
npm run build:lib - Optionally add
<name>.figma.tsxalongside it for Code Connect
Design tokens
All tokens are CSS custom properties defined directly in styles/base.css (:root for light, .dark for dark mode). Edit that file and run npm run build:lib — no token pipeline or code generation needed.
Figma Code Connect
.figma.tsx files live next to their component in components/ui/<name>/. They import the component from the local relative path and use the imports option to show the correct npm import to designers in Dev Mode.
npm run cc:publish # publish all mappings
npm run publish:icons # publish icons only
npm run generate:icons # regenerate icon mappings from FigmaUsing aperia-ds5 in a project
1. Install
npm install aperia-ds5For local development against an unpublished build:
// package.json
"aperia-ds5": "file:../aperia-ds5"Running npm install will trigger prepare and build dist/ automatically.
2. Set up globals.css
@import "tailwindcss";
@import "aperia-ds5/base.css";
/* Tell Tailwind to scan DS5 components for utility classes.
Path is relative to this file:
globals.css in app/ → ../node_modules/aperia-ds5/dist
globals.css at root → ./node_modules/aperia-ds5/dist */
@source "../node_modules/aperia-ds5/dist";base.css bundles everything in one import: design tokens, animations, Tailwind theme bridge, dark mode, Radix UI state variants, and base element styles.
3. Add ThemeProvider
import { ThemeProvider } from "aperia-ds5/theme-provider"
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en" suppressHydrationWarning>
<body>
<ThemeProvider>{children}</ThemeProvider>
</body>
</html>
)
}4. Import components
import { Button, Badge, Card, Input } from "aperia-ds5"
import { cn } from "aperia-ds5/utils"Package exports
| Import | Contents |
|---|---|
| aperia-ds5 | All UI components |
| aperia-ds5/utils | cn() (clsx + tailwind-merge) |
| aperia-ds5/theme-provider | ThemeProvider |
| aperia-ds5/base.css | Styles, tokens, and Tailwind config |
Theming
aperia-ds5 ships a zinc/shadcn default palette. Every color, radius, and chart color is a plain CSS custom property — override any of them in your globals.css after the import.
How it works
base.css defines tokens at two layers:
| Layer | What it does |
|---|---|
| :root { --primary: … } | Actual token values — override these |
| @theme inline { --color-primary: var(--primary) } | Bridges tokens into Tailwind utilities (bg-primary, text-foreground, …) |
Overriding a :root token flows through automatically to every component that uses the matching utility.
Quick start — brand color only
@import "tailwindcss";
@import "aperia-ds5/base.css";
@source "../node_modules/aperia-ds5/dist";
@theme inline {
--color-primary: #218800;
--color-primary-foreground: oklch(0.985 0 0);
}Skip
:rootwhen you only need light mode and don't need dark mode to differ.
With dark mode support
@import "tailwindcss";
@import "aperia-ds5/base.css";
@source "../node_modules/aperia-ds5/dist";
:root {
--primary: oklch(0.5 0.22 142);
--primary-foreground: oklch(0.98 0 0);
--ring: oklch(0.5 0.22 142);
}
.dark {
--primary: oklch(0.65 0.18 142);
--primary-foreground: oklch(0.141 0 0);
}
@theme inline {
--color-primary: var(--primary);
--color-primary-foreground: var(--primary-foreground);
--color-ring: var(--ring);
}Token reference
All overridable tokens and their defaults:
:root {
/* Surfaces */
--background: oklch(1 0 0);
--foreground: oklch(0.141 0.005 285.823);
--card: oklch(1 0 0);
--card-foreground: oklch(0.141 0.005 285.823);
--popover: oklch(1 0 0);
--popover-foreground: oklch(0.141 0.005 285.823);
/* Brand */
--primary: oklch(0.21 0.006 285.885);
--primary-foreground: oklch(0.985 0 0);
/* Secondary / muted / accent */
--secondary: oklch(0.967 0.001 286.375);
--secondary-foreground: oklch(0.21 0.006 285.885);
--muted: oklch(0.967 0.001 286.375);
--muted-foreground: oklch(0.552 0.016 285.938);
--accent: oklch(0.967 0.001 286.375);
--accent-foreground: oklch(0.21 0.006 285.885);
/* Destructive */
--destructive: oklch(0.577 0.245 27.325);
--destructive-foreground: oklch(0.985 0 0);
/* Chrome */
--border: oklch(0.92 0.004 286.32);
--input: oklch(0.92 0.004 286.32);
--ring: oklch(0.705 0.015 286.067);
--radius: 0.625rem;
/* Sidebar */
--sidebar: oklch(0.985 0.002 247.839);
--sidebar-foreground: oklch(0.141 0.005 285.823);
--sidebar-primary: oklch(0.21 0.006 285.885);
--sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-accent: oklch(0.967 0.001 286.375);
--sidebar-accent-foreground: oklch(0.21 0.006 285.885);
--sidebar-border: oklch(0.92 0.004 286.32);
--sidebar-ring: oklch(0.705 0.015 286.067);
/* Charts */
--chart-1: oklch(0.646 0.222 41.116);
--chart-2: oklch(0.6 0.118 184.704);
--chart-3: oklch(0.398 0.07 227.392);
--chart-4: oklch(0.828 0.189 84.429);
--chart-5: oklch(0.769 0.188 70.08);
}