fine-design
Health Warn
- License — License: MIT
- Description — Repository has a description
- Active repo — Last push 0 days ago
- Low visibility — Only 6 GitHub stars
Code Pass
- Code scan — Scanned 12 files during light audit, no dangerous patterns found
Permissions Pass
- Permissions — No dangerous permissions requested
No AI report is available for this listing yet.
React design system on Base UI, Tailwind v4 and Motion, shipped as a shadcn registry: 42 components, 7 blocks, three themes, and a Claude Code plugin. MIT.
███████╗██╗███╗ ██╗███████╗
██╔════╝██║████╗ ██║██╔════╝
█████╗ ██║██╔██╗ ██║█████╗
██╔══╝ ██║██║╚██╗██║██╔══╝
██║ ██║██║ ╚████║███████╗
╚═╝ ╚═╝╚═╝ ╚═══╝╚══════╝

React design system: Base UI primitives, Tailwind CSS v4 tokens, Motion springs, distributed as a shadcn registry.
Live site: https://fine-design.qeqx.chatgpt.site

┌─ status ──────────────────────────────────────────────────────────────┐
│ built 3 presets · 42 components · 7 blocks · docs site · tests │
│ live shadcn registry · llms.txt · agent plugin │
└───────────────────────────────────────────────────────────────────────┘
How it fits together
scripts/presets/*.mjs ──▶ scripts/tokens.mjs ──▶ styles/fine.css (Ledger) ─┐
appearance: one file OKLCH math, contrast styles/presets/<n>.css ├─▶ components/ui/*.tsx ──▶ registry.json ──▶ public/r/*.json
per preset (values gate per preset, styles/presets.css │ Base UI + cva + Motion shadcn build npx shadcn add
only) fails on any AA miss styles/tokens.json │ tiers; tokens only <site>/r/<name>.json
lib/motion.ts ───────────┘
Behavior (Base UI roles, keyboard, focus, validation, motion tiers, reduced motion) lives in the components and is the same in every preset. Appearance (colors, fonts, weights, radii, type scale, control sizes, padding, border width, shadows) lives in presets.
Agents: read AGENTS.md (using and changing the system) and /llms.txt on the docs site (per-item index), or install the plugin below.
Use with agents
- Claude Code:
/plugin marketplace add anon5376/fine-design, then/plugin install fine-design@fine-design. Adds thefine-designskill and the shadcn MCP server (search, view, add). - Codex and other agents: copy
plugin/skills/fine-designinto the agent's skills directory (Codex:~/.codex/skills/fine-design/). - Any project: add the namespace to
components.json, thennpx shadcn@latest add @fine/button. For agent tools, runnpx shadcn@latest mcp.
"registries": { "@fine": "https://fine-design.qeqx.chatgpt.site/r/{name}.json" }
https://fine-design.qeqx.chatgpt.site/llms.txt is the per-item index for agents.
Install from the registry
Install a theme once, then components. Components never re-skin a project.
npx shadcn@latest add https://fine-design.qeqx.chatgpt.site/r/theme-ledger.json # or theme-folio, theme-poster
npx shadcn@latest add https://fine-design.qeqx.chatgpt.site/r/button.json
- Every component depends on
fine-base: the Tailwind mappings, thefigures,figure-fit,focus-ringandborder-lineutilities, keyframes, and Ledger defaults in a cascade layer. Your:rootand any installed theme win over those defaults, so a component added later does not change your look. A component installed without a theme renders in Ledger. - A theme writes values only (colors, fonts, weights, radii, type scale, control sizes, padding, border width, shadows) to
:root,.light,.darkand the OS dark query. A second theme replaces the first.fine-themeis an alias oftheme-ledger. It keeps Tailwind's own palette. - Load the fonts listed in the theme item's
meta.fontswith next/font, passing an entry'saxesorweights(asaxesandweight) when it lists them: Folio's Newsreader and Poster's Bricolage Grotesque listopsz. Ledger needs Geist as--font-geist-sansand--font-geist-mono. - Project needs React 19, Tailwind v4 and the default
components.jsonaliases. Aftershadcn init, add--overwriteso Fine'sbuttonandutilsreplace init's. - Items reference each other by absolute URL, taken from
REGISTRY_URLat build time (defaulthttp://localhost:4319). For a deploy:REGISTRY_URL=https://<host> npm run build. - Every docs page shows its install line.
/r/registry.jsonindexes all 58 items: 42 ui, 7 blocks, 4 lib,fine-base, and 4 theme items (theme-ledger,theme-folio,theme-poster,fine-theme).
Develop
npm install
npm run dev # docs on port 4318
npm run tokens # regenerate CSS, JSON, motion for every preset; exits 1 on a contrast, accent/danger hue or gamut failure
npm run registry:build # registry.json + public/llms.txt, then shadcn build → public/r/*.json (58 items)
npm run build # tokens → registry:build → static site in out/
npm run serve # serve out/ on PORT (default 4319)
npm run typecheck
npm run check:snippets # typecheck every copyable docs snippet
npm test # Playwright: keyboard, motion, axe; needs a build, uses installed Chrome
npm run verify # build → typecheck → snippets → Playwright
npm run verify:install # install theme-folio, select and dialog into a fresh Next app, then fine-base alone, and check both; needs network and a prior build
node scripts/screenshots.mts [states] # every page at 375/1440, light/dark → screenshots/
node scripts/motion-tour.mts # motion video tour → screenshots/motion/ (needs ffmpeg)
node scripts/showcase-video.mts # 1080p60 promo reel of /showcase → screenshots/x/ (needs ffmpeg)
node scripts/render-film.mts # deterministic launch film of /film (virtual clock, 1080p60) → screenshots/x/fine-film.mp4; --path /film/v03/ renders the 0.3 film → fine-0.3.mp4; --from/--to/--stills for partials (build first; needs ffmpeg)
node scripts/launch-assets.mts all # README and listing assets: docs/demo.gif, themes.png, social-preview.png, plugin icon; or gif|themes|preview|icon, --out <dir> (build first; needs ffmpeg and the film for the gif)
Presets
┌─ behavior (same everywhere) ───────────┐ ┌─ appearance (a preset) ─────────────────────────────────┐
│ Base UI roles · keyboard · focus │ │ colors fonts weights radii type scale │
│ validation · motion tiers · reduced │ │ control sizes padding border width shadows │
│ motion · contrast gate · token-only │ │ ledger · folio · poster (scripts/presets/<name>.mjs) │
│ styling │ │ │
└────────────────────────────────────────┘ └─────────────────────────────────────────────────────────┘

Ledger, Folio and Poster, left to right: the same components on the same page, only the preset differs.
| Preset | Direction | Take it for |
|---|---|---|
| Ledger | Achromatic, dense, flat at rest, ink chrome with one cobalt accent | Dashboards, admin and finance tools |
| Folio | Editorial, set for reading: warm paper, serif titles, one quiet aubergine accent | Docs, publications, content-led pages |
| Poster | Loud, large type, strong contrast: a flat hot magenta for the main action and the accent, hard shadows | Launches, campaigns, marketing pages |
The table states each preset's intent. Exact values are in scripts/presets/<name>.mjs and styles/tokens.json.
- Components use semantic and preset utilities only:
bg-primary,text-muted-foreground,border-line,rounded-control,h-control-md,px-pad-field-md,font-label. The token contract table is in AGENTS.md. The docs site removes Tailwind's default palette, sobg-blue-500does not exist there (an installed project keeps its palette). - Switching: in a project, install the other theme. In the docs, the Preset select in the sidebar sets
data-preseton<html>; no attribute means Ledger. - Dark mode:
.darkor.lighton<html>(or any subtree). Without either class, the OS setting decides. - Making a preset: copy
scripts/presets/ledger.mjstoscripts/presets/<name>.mjs, add its font loaders tosite/presets.ts, runnpm run tokens. Every text/background pair must pass WCAG AA (4.5:1 text, 3:1 UI), every color must fit in sRGB, and the accent (and a chromatic primary) must sit 40 degrees or more from danger in hue so it never reads as an error, or the script fails.npm run buildthen producestheme-<name>. - Before building a new site or screen, settle the direction (audience, content, typography, palette, composition, imagery, interaction character), pick the closest preset or derive one, then build with Fine components. A small edit inside an existing screen follows that screen.
- Ledger's rules: ink chrome,
accent(cobalt) on the main data element only,figures(Geist Mono, tabular digits) on money, counts, IDs and addresses, no shadows on things at rest, no taglines or secondary labels. - Forms show a hint under any input with a rule or a format:
FieldDescriptioninsideField, linked to the input througharia-describedby.
Motion
tier enter spring exit tween moves
────────── ──────────────────────────── ────────── ─────────────────────────────
fast 80ms · bounce 0 60ms hover, focus, highlights, tooltips
moderate 160ms · bounce 0 120ms popup enters (select, combobox, menu, popover), drawers, indicators
slow 240ms · bounce 0.12 160ms dialogs, command palette
expressive 420ms · bounce 0.28 (≈810ms) 160ms toasts: feedback arriving, the one visible overshoot
Enter on spring.<tier>, exit on spring.<tier>.exit (lib/motion.ts); expressive is RareUI's visual duration (the CSS curve runs the full ≈810ms settle) and exits on slow's tween, and popups leave on fast's exit. CSS uses duration-(--duration-<tier>) with ease-spring-<tier> to enter and duration-<tier>-exit with ease-exit to leave. Every other transition defaults to --ease-enter, and Motion tweens take easing.enter and easing.exit. Lists, menus and nav share one hover highlight that glides between items (useFluidHover + <FluidHighlight> in lib/fluid-hover.tsx). Prefer transform and opacity; width is animated only where the size is the information (progress fill, switch thumb, highlight, a figure gaining a digit, slider position). Wrap apps in <MotionConfig reducedMotion="user">; with reduced motion on, movement is dropped and fades remain.
Fine's own animations (original, not borrowed) animate only a change the user needs to notice, on the same tiers, with no loops and no entrance on page load. Reduced motion keeps at most a fade, and the final value or name is in the accessibility tree on the click.
animation where tier reduced motion
────────────────── ─────────────────────── ──────────────────────────── ───────────────────
digit roll AnimatedNumber, pricing moderate (exit 120ms tween) fade only
tag removal TagList + Tag fast exit; siblings moderate fade, siblings jump
slider track press Slider moderate (CSS) jump
avatar image fade Avatar fast fade kept
theme crossfade docs ThemeToggle moderate (view transition) instant
Still static: Alert, Badge, the Navbar wordmark, a Tag outside a TagList, and slider drag and keyboard steps (a drag must track the pointer exactly).
Layout
fine-design/
├─ components/
│ ├─ ui/ one file per component (installed to the same path)
│ └─ blocks/ compositions of components/ui only: auth-form · hero ·
│ feature-grid · pricing · faq · footer · dashboard-shell
├─ lib/ utils (cn) · popup · fluid-hover · motion (generated)
├─ styles/ fine.css · presets/<name>.css · presets.css · tokens.json (generated)
├─ scripts/ tokens · presets/<name>.mjs · registry · verify-install · check-snippets · serve · screenshots · motion-tour · launch-assets
├─ site/ docs-only code: nav, examples/<slug>.tsx, presets.ts, preset-switch, chrome
├─ app/ docs routes: /tokens · /components/[slug] · /blocks/[slug]
├─ tests/ keyboard · motion · a11y · layout (233 Playwright tests, against out/)
├─ plugin/ Claude Code plugin: skills/fine-design (also usable in Codex) + .mcp.json
├─ .claude-plugin/ marketplace.json for `/plugin marketplace add`
└─ registry.json · public/r/ · public/llms.txt generated by registry:build
Adding a component
- Write
components/ui/<name>.tsx: Base UI primitive underneath,cvaforvariant/size, semantic and preset utilities only,focus-visible:focus-ring. - Motion, if any, comes from a source animation mapped onto
spring.<tier>, or is the one change the user needs to notice. Static is fine. - Add
site/examples/<name>.tsx. Each exported function is one live example, and its source is the copyable code. - Add the entry to
site/nav.ts, and its category and one-line description toUIinscripts/registry.mjs(the build fails if either is missing). - Run
npm run typecheck && npm run check:snippets && npm run build && npm test.
Credits
Full notices and licenses: THIRD-PARTY-NOTICES.md. Fine itself is MIT.
| From | License | Used for |
|---|---|---|
| Fluid Functionalism | MIT | motion tiers, hover highlight, button press geometry, spinner, icon stroke hover |
| Rare UI | MIT + Commons Clause + Attribution | expressive tier: the FAQ reply bubble's SEND spring (visualDuration 0.42, bounce 0.28); the hero's falling-slips moment takes its idea from Gravity Letters (idea only, no code) |
| easyui | MIT | Pagination active-page slide: SlidePagination's shared-layoutId technique, rewritten onto our tokens |
| taste-skill | MIT | art direction: the Ledger preset's "achromatic ledger" style (ink chrome, mono figures, 6/8 radius) |
| Base UI | MIT | primitives |
The digit roll, tag removal, slider glide, avatar fade and theme crossfade are Fine's own and have no source to credit.
Reviews (0)
Sign in to leave a review.
Leave a reviewNo results found