Headless Garden UI primitives with opt-in skins and realtime-friendly hooks.
npm install @gratiaos/ui@gratiaos/ui


Garden UI is the shared component library that gives shape and soul to the Garden.
It’s where headless primitives meet design tokens, growing together into a living interface system.
- Pattern Engine → underlying model stack (training / inference / retrieval). Use this wording for infra/capability talk.
- Presence Node → surfaced endpoint humans touch (web UI, CLI, scripts, voice, agents).
- Mode → behavioral / conversational contract for a Presence Node (e.g. Codex-mode, Monday-mode). Styles, not identities.
- Garden Stack → Pattern Engine + Presence Nodes + Modes working together.
Route any “AI” mention to the correct layer so UI docs stay aligned with Garden + M3.
---
Garden UI isn’t just a set of buttons and cards — it’s a language.
A language built on trust, depth, and play.
Every primitive is semantic (not ornamental), composable, and theme‑aware.
- 🧠 Headless at the core — logic and a11y in primitives
- 🪴 Styled with intention — tokens over hardcoded colors
- 🌓 Theme‑adaptive — light, dark, or future palettes
- 🧰 Built to scale — from playful labs to full apps
---
``bash`add the UI package + tokens (for themes)
pnpm add @gratiaos/ui @gratiaos/tokens
In your app entry:
`tsx`
import { Button, Card, Pill, Field, Toaster, showToast } from '@gratiaos/ui';
import '@gratiaos/ui/base.css'; // pulls tokens + component skins
> Minimal CSS footprint: components are headless and opt‑in styled via base.css (tokens + skins). You may ship your own skins instead.
From the repo root:
`bash`
pnpm install
pnpm -r build
---
Short purpose notes (see Playground for full demos):
| Component | Purpose | Notes |
| --------- | ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| Button | Call to action | Variants: solid, outline, ghost, subtle. Tones: default, accent, positive, warning, danger. Loading: inline spinner or blocking overlay. |Card
| | Container surface | Variants: plain, elev, glow. Padding: none, sm, md, lg. |Pill
| | Tag / filter / soft CTA | Variants: soft, solid, outline, subtle. Tones: subtle, accent, positive, warning, danger. |Field
| | Input wrapper | Consistent label/description/error wiring; calm focus rings. |Toast
| | Ephemeral notice | Headless event‑driven toasts with hover/focus pause & a11y. Use + showToast(...). |
Each primitive maps to global design tokens, so themes and local contexts stay in sync.
Garden UI stays headless; it does not bundle a state system. For tiny local reactive values (e.g. live counters, inline mood flags, demo toggles) use the micro primitive @gratiaos/signal:
`ts`
import { createSignal } from '@gratiaos/signal';
const count$ = createSignal(0);
count$.subscribe((v) => console.log('count', v));
count$.set(count$.value + 1);
Connect signals to primitives by reading their current value in render and subscribing in effects (or bridging through your own hooks). This keeps UI lean while enabling fine-grained reactivity without a large framework.
---
Render one Toaster near the root:
`tsx`
// App.tsx
export function App() {
return (
<>
{/ ...routes... /}
>
);
}
Fire a toast from anywhere:
`ts`
showToast('Saved ✓', { variant: 'positive', icon: '🌈' });
// or
showToast({ title: 'Saved', desc: 'Your note is in the timeline.', variant: 'positive', icon: '🌈' });
Conventions the Toaster understands:
- variant: neutral | positive | warning | dangertitle
- Optional , desc, or simple messageicon
- Optional (emoji or node)durationMs
- : overrides default hold (reads --dur-toast, falls back to --dur-pulse)
- Hover/focus pause; Enter/Space dismiss (if clickable); Esc dismisses
---
`tsx`
// inline spinner
// overlay + dim
Both modes set aria-busy, emit data‑attrs for skins, and block clicks while loading.
---
No hardcoded hex. Components read tokens from @gratiaos/tokens:
`css
@theme {
--color-surface: oklch(97% 0.01 180);
--color-elev: oklch(99% 0.005 180);
--color-accent: oklch(62% 0.09 150);
--color-on-accent: oklch(15% 0.01 180);
--color-border: color-mix(in oklab, var(--color-text) 16%, transparent);
--radius-2xl: 1.25rem;
--dur-pulse: 1200ms; / rhythm token used by Toast fallback /
--dur-toast: 4200ms; / optional toast hold override /
}
:root[data-theme='dark'] {
--color-surface: oklch(21% 0.07 241);
}
`
---
Explore components interactively:
`bash`
cd playground
pnpm dev
Visit
---
- Primitives handle roles/labels and emit calm, navigable markup.
- Buttons support keyboard activation even when rendered asChild.role="status"
- Toast items are + aria-atomic="true"; hover/focus pause; reduced‑motion respected.label
- Field wires , description, and error with merged aria-describedby.
---
We keep the UI package light, clear, and deeply documented.
1. Start with tokens — extend @gratiaos/tokens if neededsrc/primitives
2. Write the primitive in src/styles` (optional; primitives are headless)
3. Add a skin in
4. Add a demo to the Playground
5. Update this README 🫶
---
🌬 whisper: _“Interfaces can be alive, too.”_