Grove

A design system for Twig — token-driven, accessible, and built for product teams. This site uses the brand intent on <html> so colours follow Grove semantic tokens (sprout active surfaces and pebble neutrals). React sources live under packages/grove/src in four layers (seeds → sprouts → branches → canopies). Everything is exported from @twig/grove.

Getting started

Import @twig/grove/css for the global reset, design tokens, typography utilities, and UI styles in one file. For smaller bundles, load granular sheets (for example @twig/grove/css/button) instead of the full bundle.

// globals.css
@import '@twig/grove/css';      /* reset + tokens + typography + UI */
@import '@twig/utils/css';      /* utility classes */
// layout.tsx — brand intent drives semantic colours site-wide
<html data-theme="light" data-intent="brand">
  ...
</html>

Component library

Each tier builds on the last. Import components by name from @twig/grove; source files are grouped by tier only for maintenance — there is no separate subpath import.

Seeds

Primitive controls — buttons, inputs, chips, links.

packages/grove/src/seeds

Exported: Badge, Button, Checkbox, Chip, Input, Link, ProgressBar, Radio, Select, Toggle

Open button docs →

Sprouts

Composed patterns built from seeds — labelled fields and grouped inputs.

packages/grove/src/sprouts

Exported: AmountInput, CheckboxGroup, FormField, RadioGroup, SearchInput, ToggleRow

Open form field docs →

Branches

Product-shaped composites — rows and cards for money workflows.

packages/grove/src/branches

Exported: ExpenseRow, GoalCard, InsightCard, TransactionRow

Open goal card docs →

Canopies

Layout shells that wrap flows — tab chrome and sheets.

packages/grove/src/canopies

Exported: SheetLayout, TabLayout

Open tab layout docs →

Token architecture

Grove uses a three-tier token hierarchy. Primitive values live in units.json and themes.json, semantic intent tokens map onto those primitives, and component tokens reference the semantic layer. This means swapping an intent changes colours everywhere that intent is applied.

units.json         → --units-4: 4px
themes.json        → --sprout-500: #6ba53d
intent.json        → --surface-active-strong: var(--sprout-400)
components.json    → --sprouts-button-color-primary-surface-default: var(--surface-active-strong)