@whiskeyjack-net/design-system
v0.25.0
Published
Tauri-first design system and design language: thumb-first components, Metro-style pivot navigation, and a CSS-variable token pipeline for offline-first personal apps.
Maintainers
Readme
Whiskeyjack Design System
A Tauri-first design system and design language: thumb-first components with Metro-style pivot navigation, built for small, offline-first personal apps that ship one web codebase to desktop and mobile via Tauri. Every component was hardened across a family of real, shipping apps before extraction.
This README documents the published artifact (@whiskeyjack-net/design-system,
staged via npm run build:package). Inside the monorepo, apps consume the
workspace source export as @whiskeyjack/design-system – see CLAUDE.md.
Install
npm install @whiskeyjack-net/design-systemRequires react 18+, react-dom 18+, and tailwindcss 3.4+ as peers.
Setup
- Import the token CSS once (order matters), then your Tailwind entry:
/* index.css */
@import '@whiskeyjack-net/design-system/css'; /* token variables */
@import '@whiskeyjack-net/design-system/css/utilities'; /* shared utilities */
@tailwind base;
@tailwind components;
@tailwind utilities;- Consume the Tailwind preset, and scan the package so the components' classes are generated:
// tailwind.config.js
import preset from '@whiskeyjack-net/design-system/tailwind-preset'
export default {
presets: [preset],
content: [
'./index.html',
'./src/**/*.{js,ts,jsx,tsx}',
'./node_modules/@whiskeyjack-net/design-system/dist/index.js',
],
}- Use the components:
import { Button, Card, TabBar } from '@whiskeyjack-net/design-system'
<Button variant="accent">Check in</Button>Exports
| Subpath | Contents |
|---------|----------|
| . | React components, hooks, cn(), accent utilities |
| ./css | Token CSS variables |
| ./css/utilities | Shared utility classes (safe areas, scrollbar, fade masks) |
| ./themes/* | Per-app accent theme CSS |
| ./tokens | Tokens as a JS module |
| ./tailwind-preset | The Tailwind preset (token colors, fonts, radius/shadow, layout-gate variants) |
Two ways to consume the components
- Install (above) – import from the package (
import { Button } from '@whiskeyjack-net/design-system'). Fastest; you track the package version. - Registry (copy-into-repo) – pull a component's source into your own repo
and own the code (the shadcn model, which fits this system's CVA/
cn()DNA). Either way you still install the package for the tokens, Tailwind preset, and CSS – the registry ships only the components.
Registry
The registry is live at https://whiskeyjack.net/r/ – 44 items (28
components, 11 hooks, 5 utilities), each carrying a title, description,
categories, and install-time usage notes.
Register the namespace once, then add items by name:
npx shadcn@latest registry add @whiskeyjack=https://whiskeyjack.net/r/{name}.json
npx shadcn@latest add @whiskeyjack/confirm-buttonOr put it straight in your components.json (apps scaffolded with
npm create whiskeyjack@latest already have this):
{
"registries": {
"@whiskeyjack": "https://whiskeyjack.net/r/{name}.json"
}
}Browse what is available with npx shadcn@latest search @whiskeyjack, or fetch
the catalog directly at
https://whiskeyjack.net/r/registry.json.
A single item URL also works without registering anything:
npx shadcn@latest add https://whiskeyjack.net/r/confirm-button.jsonAdding a component pulls its full dependency closure – confirm-button brings
button, announce, use-input-type, and utils. The copied source compiles
against a @/* path alias plus the item's npm dependencies
(class-variance-authority, clsx, tailwind-merge), and the token/utility
CSS from the installed package.
Generated by npm run build:registry into registry/: registry.json (the
catalog, plus an index.json duplicate at the path this registry first
published) and registry/r/<name>.json per item. Descriptive metadata comes
from components.manifest.json; relative imports are rewritten to @/ aliases
(@/components/ui/*, @/hooks/*, @/lib/*).
Theming & accent
The headline theming feature: retint the entire UI from a single accent color, with a readable foreground chosen for you.
Runtime accent (one line, no build step)
import { applyAccentColor, clearAccentColor } from '@whiskeyjack-net/design-system'
applyAccentColor('#e66767') // derive the full accent scale (50→700) from one
// hex and apply it to the --color-accent-* vars
clearAccentColor() // revert to the theme defaultapplyAccentColor(hex) does two things from that single hex:
- Generates the scale – lighter stops mix toward white, darker toward black – so you never hand-pick six values.
- Auto-contrast foreground (WCAG) – it measures the accent's relative
luminance and sets
--color-accent-foregroundto white or near-black so text and icons on the accent stay legible (≥3:1). It flips to dark once the accent is light enough that white would fail. This is why an accent Button's label is always readable, whatever color you throw at it.
Use it for a user-customizable accent, or to match a desktop OS accent (the
@whiskeyjack-net/tauri pack calls it with the system color). applyAccentForeground()
recomputes just the foreground from the current --color-accent-500.
Static per-app theme (no first-frame flash)
If the accent is fixed per app and you want it in the initial CSS (no JS on
first paint), override the accent variables in a :root block, loaded after the
token CSS:
/* your-theme.css – loaded after '@whiskeyjack-net/design-system/css' */
:root {
--color-accent-50: #fff9e0;
--color-accent-100: #fff3c1;
--color-accent-400: #ffd54f;
--color-accent-500: #ffc312;
--color-accent-600: #e0ab00;
--color-accent-700: #b88d00;
/* Foreground: pick #ffffff for a dark accent, #1d1d1d for a light one
(luminance > 0.30), plus the alpha steps. */
--color-accent-foreground: #1d1d1d;
--color-accent-foreground-icon: #1d1d1d;
}To generate that block from one hex instead of hand-authoring it, call
applyAccentColor(hex) once in a scratch page and copy the resulting
--color-accent-* inline styles off <html> – same math, precomputed. (The
in-repo apps keep hand-tuned stops in tokens/themes/{app}.json; external
consumers don't need that build step – the runtime call or this static block
covers it.)
License
MIT
