Grove
Parchment, forest ink and emerald buttons lettered in mint, with a pastel card for every feature.
- Light by default
- 35 colours · 14 type steps
- Inspired by lattice.com
The same generated app in every design. Scroll inside the window to see the whole page.
What it is
Grove sets your product on warm parchment and writes it in deep forest ink. Buttons are built like keys: emerald lettered in mint under a soft top sheen, with a white top highlight, a darker green edge and a forest tinted drop, and they lift on hover and sink on press. Every section opens with a mint pill label, and each feature gets its own pastel card (mint, butter, lavender, sage, petal, meadow), so the page reads like a tray of labelled specimens. One aurora panel holds the product picture, and dark mode turns the page into a forest at night with a jade and indigo glow.
Maintained by @agentic-studio in the open registry.
Best for
People and HR tools, team software, education, health and wellbeing apps: products that should feel calm, human and safe to trust. It shines when the product has several modules, because each one can own a pastel.
Trade-offs
- The pastel cards need a plan. Give each module one colour and keep it everywhere; six random pastels look like a sweet shop.
- Parchment and white sit close in tone, so depth does the separating. Strip the green tinted shadows and a dense admin screen goes flat.
- The emerald button with mint lettering is a strong brand signal. A product with its own brand colour will fight it.
Tokens
Generated from this design’s design.yaml, and shipped as CSS variables plus a Tailwind theme. Templates may use these names and nothing else.
Colours
Every colour token in design.yaml, grouped the way the system documents them. These are the light palette's values. The dark palette uses the same names with its own values, and tokens.css ships both.
Brand and accent
accent
#046645
accent-1
#046645
accent-2
#624ee5
accent-3
#b8740f
accent-4
#b8337a
accent-5
#0a8a8f
accent-6
#7b8f00
accent-hover
#03573b
accent-soft
#cdface
primary
#046645
Surface
canvas
#f7f6f2
hairline
rgb(0 31 31 / 0.1)
surface-card
#efeee7
surface-dark
#001f1f
surface-dark-elevated
#0a2e2c
surface-soft
#f2f1eb
surface-solid
#ffffff
surface-strong
#e4e3da
Text
body
#455252
body-strong
#1b3535
ink
#001f1f
muted
#526666
muted-soft
#7d8a8a
on-accent
#cdface
on-dark
#f7f6f2
on-primary
#cdface
Semantic
error
#a82e25
success
#2f6b1c
warning
#8a5a0f
Other
danger
#a82e25
danger-soft
#fce9e4
error-soft
#fce9e4
primary-hover
#03573b
success-soft
#e3f5d6
warning-soft
#fff3c2
Type scale
Each token rendered at its real size, weight, line height and tracking. Specimens fall back to this site's typeface when the design's own face is not installed locally, so read the numbers, not the letterforms.
Ship faster
- Token
- display-xl
- Values
- 4.5rem · 72px · 500 · lh 0.9 · ls -0.024em
Ship faster
- Token
- display-lg
- Values
- 3.5rem · 56px · 500 · lh 0.95 · ls -0.024em
Ship faster
- Token
- display-md
- Values
- 2.9375rem · 47px · 500 · lh 1 · ls -0.024em
Ship faster
- Token
- display-sm
- Values
- 2.25rem · 36px · 500 · lh 1.05 · ls -0.024em
Ship faster
- Token
- title-lg
- Values
- 1.375rem · 22px · 500 · lh 1.1 · ls -0.024em
Ship faster
- Token
- body-lg
- Values
- 1.1875rem · 19px · 400 · lh 1.4 · ls 0
Ship faster
- Token
- title-md
- Values
- 1.1875rem · 19px · 500 · lh 1.25 · ls -0.01em
Ship faster
- Token
- body-md
- Values
- 1rem · 16px · 400 · lh 1.45 · ls 0
Ship faster
- Token
- title-sm
- Values
- 1rem · 16px · 500 · lh 1.3 · ls -0.005em
Ship faster
- Token
- body-sm
- Values
- 0.875rem · 14px · 400 · lh 1.4 · ls 0
Ship faster
- Token
- button
- Values
- 0.875rem · 14px · 500 · lh 1 · ls 0
Ship faster
- Token
- nav-link
- Values
- 0.875rem · 14px · 500 · lh 1.3 · ls 0
Ship faster
- Token
- caption
- Values
- 0.8125rem · 13px · 400 · lh 1.35 · ls 0
SHIP FASTER
- Token
- caption-uppercase
- Values
- 0.6875rem · 11px · 500 · lh 1.3 · ls 0.08em
Typefaces
The families the generated Tailwind theme points at. A licensed face is named here even when the substitute below is what actually renders.
- DisplayFigtree, ui-sans-serif, system-ui, sans-serif
- BodyFigtree, ui-sans-serif, system-ui, sans-serif
- MonoDM Mono, ui-monospace, SFMono-Regular, Menlo, monospace
Spacing scale
Drawn at true size. These are the only gaps and paddings a generated repo is allowed to use.
- xxs0.25rem · 4px
- xs0.5rem · 8px
- sm0.75rem · 12px
- md1rem · 16px
- lg1.5rem · 24px
- xl1.75rem · 28px
- xxl3rem · 48px
- section4.5rem · 72px
Radius scale
Sample shapes at true corner radius. Buttons and inputs sit at the small end of this scale, feature cards at the large end.
- xs0.4375rem · 7px
- sm0.75rem · 12px
- md0.875rem · 14px
- lg1.375rem · 22px
- xl1.8rem · 29px
- full9999px
- pill9999px
Elevation
Shadow tokens on a neutral card, at true blur and spread.
- insetinset 0 1px 0 0 rgb(255 255 255 / 0.9)
- lift0 0 0 1px #001f1f0a, 0 1px 2px 0 #0434260d, 0 4px 8px -2px #0434260f, 0 12px 24px -8px #0434261a, 0 28px 48px -20px #04342629
- overlayinset 0 1px 0 0 #ffffffe6, 0 0 0 1px #001f1f0a, 0 2px 4px -1px #0434260f, 0 12px 24px -6px #0434261f, 0 28px 56px -14px #0434262e
- ring0 0 0 3px rgb(4 102 69 / 0.2)
- softinset 0 1px 0 0 #ffffffe6, 0 0 0 1px #001f1f0d, 0 1px 2px 0 #0434260d, 0 4px 8px -3px #0434260f, 0 12px 24px -12px #0434261f
- xs0 1px 1px 0 #0434260f, 0 1px 3px -1px #04342614
DESIGN.md
Ships in your repo as DESIGN.md. The designer agent reads it before it may introduce a new visual pattern. This is the briefing, not a page about the briefing.
Grove is a botanical field journal: parchment pages, forest ink, emerald buttons lettered in mint and a pastel specimen card for every module. Everything tactile is built like a key: a top highlight, a crisp edge and a soft drop tinted green, lifting on hover and sinking on press. Headings, buttons and labels are Figtree 500 and text is Figtree 400. Dark mode is the same forest at night.
Read this before you add a screen, a component or a colour. The tokens live in
src/app/globals.css, the faces in src/app/fonts.ts, the kit in
src/components/ui/.
At a glance
| Theme | Light native on #f7f6f2 parchment with white cards. Dark is the forest at night (#061e1c) with mint buttons lettered in forest. |
| Type | Figtree for everything: 500 for headings, buttons and labels, 400 for text, display sizes tracked at -0.024em. DM Mono only for code, keys, shortcuts and ids. |
| Colour | Forest ink (#001f1f), emerald (#046645) lettered in mint (#cdface), six specimen pastels for features, and an aurora of lime, aqua, periwinkle and sky used once. |
| Shape | Rounded: 7px on small parts, 12px on controls, 14px on cards, 22px on dialogs and the product window, 29px on specimen cards. Pills for badges, tabs, labels and switches. |
| Depth | A layered depth system tinted green, never grey: xs, soft, lift and overlay drops, a white top highlight, and key-like buttons with a soft top sheen and a darker base edge that lift 1px on hover and sink 1px on press. Fields sit slightly into the paper. Dark uses deeper black drops with a faint mint rim, and no coloured glow under buttons. |
| Signature | The emerald key button with a mint label on a soft green drop, the aurora panel around the product window, and a tray of six pastel specimen cards under mint pill labels. |
Principles
- Parchment page, white cards. Content lifts onto paper, never the other way round.
- Emerald and meadow travel together: an emerald fill carries a mint label, a meadow fill carries an emerald or ink label.
- One module, one pastel. Keep the pairing on every page it appears.
- Two weights: Figtree 500 for headings, buttons and labels, 400 for text.
- Depth is tactile and tinted: raised things lift on green shadows with a top highlight, fields and tracks sit into the paper, and a press always sinks.
Colour
Palette
| Token | Light | Dark | Role |
|---|---|---|---|
canvas (--background) | #f7f6f2 | #061e1c | The page floor |
surface-soft | #f2f1eb | #0a2421 | Section bands, sidebars, table heads |
surface-card (--muted) | #efeee7 | #12312e | Tinted fills: inactive tabs, hover rows, code |
surface-strong | #e4e3da | #1b3f3b | Pressed fills, progress tracks |
surface-solid (--popover) | #ffffff | #102e2b | Menus, selects, toasts: always opaque |
card | #ffffff | #0c2826 | The card fill |
surface-dark | #001f1f | #011413 | The inverted panel |
hairline (--border) | rgb(0 31 31 / 0.1) | rgb(205 250 206 / 0.12) | Every border and divider |
ink (--foreground) | #001f1f | #f1f0e9 | Headings and primary text |
body-strong | #1b3535 | #dde5e0 | Emphasised body text |
body | #455252 | #c3cfca | Running text |
muted (--muted-foreground) | #526666 | #98aca7 | Secondary text, captions |
muted-soft | #7d8a8a | #6f8a85 | Placeholders, disabled text, icons at rest |
primary | #046645 | #cdface | The action colour |
accent (--accent-fill) | #046645 | #86e0aa | The saturated accent: links, the accent badge |
accent-soft | #cdface | #0f3b2f | The tint an accent label sits on |
danger (--destructive) | #a82e25 | #f28b7d | Destructive actions and errors |
success, warning and error each come with a -soft tint for the back of a
badge or an alert: #2f6b1c, #8a5a0f and #a82e25 in light, #9bdc7f, #f2c35f and
#ff9a8a in dark.
Grove's own variables, read by the landing hooks and the kit: --specimen-1
(#e4f7f9 light, #0d2d32 dark), --specimen-2 (#fff3c2 light, #2c2710 dark),
--specimen-3 (#e1e1fa light, #1e1f3d dark), --specimen-4 (#eff5ce light,
#222a12 dark), --specimen-5 (#fde5ff light, #2e1a33 dark), --specimen-6
(#dcf7dd light, #10301e dark), --specimen-deep (rgb(0 31 31 / 0.07) light,
rgb(241 240 233 / 0.08) dark), --halo-1 (#cbfd74 light, rgb(79 211 154 /
0.3) dark), --halo-2 (#6ee6f3 light, rgb(110 230 243 / 0.3) dark),
--halo-3 (#dfe4ff light, rgb(150 160 255 / 0.26) dark), --halo-4 (#b9e9f4
light, rgb(100 190 230 / 0.24) dark), --raised (#ffffff light, #15392f
dark), --primary-edge (#03543a light, #a8e8b2 dark), --button-highlight
(inset 0 1px 0 0 rgb(255 255 255 / 0.24) light, inset 0 1px 0 0 rgb(255 255
255 / 0.65) dark), --button-shadow (inset 0 1px 0 0 rgb(255 255 255 / 0.22),
0 0 0 1px #03543a, 0 1px 0 1px #023d2a, 0 2px 3px 0 rgb(0 31 31 / 0.18), 0 6px
14px -6px rgb(0 41 28 / 0.4) light, inset 0 1px 0 0 rgb(255 255 255 / 0.7),
inset 0 -1px 0 0 rgb(4 102 69 / 0.18), 0 0 0 1px #8fd6a4, 0 1px 0 1px #4d9a6c, 0
2px 3px 0 rgb(0 0 0 / 0.45), 0 8px 18px -6px rgb(0 0 0 / 0.6) dark),
--button-shadow-hover (inset 0 1px 0 0 rgb(255 255 255 / 0.26), 0 0 0 1px
#03543a, 0 1px 0 1px #023d2a, 0 4px 6px -1px rgb(0 31 31 / 0.18), 0 12px 22px
-8px rgb(0 41 28 / 0.45) light, inset 0 1px 0 0 rgb(255 255 255 / 0.75), inset
0 -1px 0 0 rgb(4 102 69 / 0.18), 0 0 0 1px #8fd6a4, 0 1px 0 1px #4d9a6c, 0 4px
6px -1px rgb(0 0 0 / 0.5), 0 14px 26px -8px rgb(0 0 0 / 0.65) dark),
--button-shadow-active (inset 0 2px 3px 0 rgb(0 31 31 / 0.35), inset 0 0 0
1px rgb(0 31 31 / 0.15), 0 0 0 1px #03543a, 0 1px 1px 0 rgb(0 31 31 / 0.12)
light, inset 0 2px 3px 0 rgb(4 102 69 / 0.35), 0 0 0 1px #8fd6a4, 0 1px 1px 0
rgb(0 0 0 / 0.4) dark), --button-soft-highlight (inset 0 -1px 0 0 rgb(0 31
31 / 0.04) light, inset 0 1px 0 0 rgb(205 250 206 / 0.1) dark),
--button-soft-press (inset 0 1px 2px 0 rgb(0 31 31 / 0.1) light, inset 0
1px 2px 0 rgb(0 0 0 / 0.35) dark), --button-soft-shadow (inset 0 1px 0 0
rgb(255 255 255 / 1), 0 1px 0 0 rgb(0 31 31 / 0.1), 0 2px 3px -1px rgb(0 31 31 /
0.08), 0 6px 14px -6px rgb(0 41 28 / 0.18) light, inset 0 1px 0 0 rgb(205 250
206 / 0.12), 0 1px 0 0 rgb(0 0 0 / 0.5), 0 2px 3px 0 rgb(0 0 0 / 0.35), 0 8px
18px -6px rgb(0 0 0 / 0.55) dark), --button-soft-shadow-hover (inset 0 1px 0
0 rgb(255 255 255 / 1), 0 1px 0 0 rgb(0 31 31 / 0.12), 0 4px 6px -2px rgb(0 31
31 / 0.1), 0 12px 22px -8px rgb(0 41 28 / 0.22) light, inset 0 1px 0 0 rgb(205
250 206 / 0.16), 0 1px 0 0 rgb(0 0 0 / 0.5), 0 4px 6px -1px rgb(0 0 0 / 0.4), 0
14px 26px -8px rgb(0 0 0 / 0.6) dark), --button-soft-shadow-active (inset 0
2px 3px 0 rgb(0 31 31 / 0.1), 0 0 0 0 rgb(0 31 31 / 0) light, inset 0 2px 3px
0 rgb(0 0 0 / 0.35), 0 0 0 0 rgb(0 0 0 / 0) dark), --button-danger-shadow
(inset 0 1px 0 0 rgb(255 255 255 / 0.22), 0 0 0 1px #8f261f, 0 1px 0 1px
#6e1c17, 0 2px 3px 0 rgb(0 31 31 / 0.18), 0 6px 14px -6px rgb(74 18 14 / 0.4)
light, inset 0 1px 0 0 rgb(255 255 255 / 0.55), 0 0 0 1px #de7466, 0 1px 0 1px
#aa4e42, 0 2px 3px 0 rgb(0 0 0 / 0.45), 0 8px 18px -6px rgb(0 0 0 / 0.6) dark),
--button-danger-shadow-hover (inset 0 1px 0 0 rgb(255 255 255 / 0.26), 0 0 0
1px #8f261f, 0 1px 0 1px #6e1c17, 0 4px 6px -1px rgb(0 31 31 / 0.18), 0 12px
22px -8px rgb(74 18 14 / 0.45) light, inset 0 1px 0 0 rgb(255 255 255 / 0.6),
0 0 0 1px #de7466, 0 1px 0 1px #aa4e42, 0 4px 6px -1px rgb(0 0 0 / 0.5), 0 14px
26px -8px rgb(0 0 0 / 0.65) dark), --button-danger-shadow-active (inset 0
2px 3px 0 rgb(0 31 31 / 0.35), inset 0 0 0 1px rgb(0 31 31 / 0.15), 0 0 0 1px
#8f261f, 0 1px 1px 0 rgb(0 31 31 / 0.12) light, inset 0 2px 3px 0 rgb(0 0 0 /
0.3), 0 0 0 1px #de7466, 0 1px 1px 0 rgb(0 0 0 / 0.4) dark), --field-shadow
(inset 0 1px 2px 0 #001f1f0f, 0 1px 0 0 #ffffffbf light, inset 0 1px 2px 0
#0000004c, 0 1px 0 0 #cdface0d dark), --focus-glow (rgb(134 224 170 / 0.5)
light, rgb(134 224 170 / 0.28) dark), --control-border (rgb(0 31 31 / 0.3)
light, rgb(205 250 206 / 0.3) dark), --control-checked-shadow (inset 0 1px
0 0 #ffffff3d, 0 1px 2px 0 #0466454c light, inset 0 1px 0 0 #ffffffa6, 0 1px
2px 0 #00000073 dark), --track-inset (inset 0 1px 2px 0 rgb(0 31 31 / 0.1)
light, inset 0 1px 2px 0 rgb(0 0 0 / 0.4) dark), --thumb-shadow (0 0 0
0.5px #001f1f14, 0 1px 2px 0 #04342633, 0 2px 5px -1px #04342629 light, 0 0 0
0.5px #0000004c, 0 1px 2px 0 #00000080, 0 2px 6px -1px #00000066 dark),
--segment-raised (inset 0 -1px 0 0 #001f1f0a, 0 0 0 1px #001f1f0f, 0 1px 2px
0 #04342614, 0 3px 8px -3px #0434261f light, inset 0 1px 0 0 #cdface1a, 0 0 0
1px #cdface14, 0 1px 2px 0 #00000066, 0 3px 8px -3px #00000073 dark),
--kbd-shadow (inset 0 -1.5px 0 0 #001f1f1a, 0 1px 1px 0 #04342614 light,
inset 0 -1.5px 0 0 #00000059, inset 0 1px 0 0 #cdface14, 0 1px 1px 0 #00000066
dark), --dark-surface-shadow (inset 0 1px 0 0 #cdface17, 0 0 0 1px #001f1f0a,
0 1px 2px 0 #0434260d, 0 4px 8px -2px #0434260f, 0 12px 24px -8px #0434261a, 0
28px 48px -20px #04342629 light, inset 0 1px 0 0 #cdface17, 0 0 0 1px
#cdface12, 0 2px 4px -1px #00000066, 0 12px 24px -8px #00000073, 0 32px 56px
-20px #00000099 dark), --specimen-shadow (inset 0 1px 0 0 #ffffff99, 0 0 0
1px #001f1f0a, 0 1px 2px 0 #0434260a, 0 12px 24px -14px #04342633 light, inset
0 1px 0 0 #f1f0e90f, 0 0 0 1px #cdface0d, 0 14px 28px -14px #00000099 dark),
--field (#ffffff light, #0a2321 dark), --segment-track (#eceae2 light,
#081f1d dark), --button-sheen (linear-gradient(rgb(255 255 255 / 0.14) 0%,
rgb(255 255 255 / 0.03) 55%, rgb(0 31 31 / 0.06) 100%) light,
linear-gradient(rgb(255 255 255 / 0.4) 0%, rgb(255 255 255 / 0) 60%, rgb(0 31
31 / 0.05) 100%) dark), --button-sheen-hover (linear-gradient(rgb(255 255
255 / 0.2) 0%, rgb(255 255 255 / 0.06) 55%, rgb(0 31 31 / 0.04) 100%) light,
linear-gradient(rgb(255 255 255 / 0.5) 0%, rgb(255 255 255 / 0.05) 60%, rgb(0
31 31 / 0.04) 100%) dark), --button-sheen-active (linear-gradient(rgb(0 31
31 / 0.14) 0%, rgb(0 31 31 / 0) 45%) light, linear-gradient(rgb(0 31 31 /
0.16) 0%, rgb(0 31 31 / 0) 50%) dark), --button-soft-sheen
(linear-gradient(rgb(0 31 31 / 0) 30%, rgb(0 31 31 / 0.035) 100%) light,
linear-gradient(rgb(205 250 206 / 0.06) 0%, rgb(205 250 206 / 0) 70%) dark),
--button-soft-sheen-active (linear-gradient(rgb(0 31 31 / 0.06) 0%, rgb(0 31
31 / 0.03) 100%) light, linear-gradient(rgb(0 0 0 / 0.18) 0%, rgb(0 0 0 /
0.08) 100%) dark), --button-soft-edge (rgb(0 31 31 / 0.16) light, rgb(205
250 206 / 0.16) dark), --button-soft-edge-hover (rgb(0 31 31 / 0.26) light,
rgb(205 250 206 / 0.26) dark), --plan-halo (rgb(4 102 69 / 0.1) light,
rgb(134 224 170 / 0.12) dark).
How colour is used
- Emerald (
bg-primary) is the one action fill per view, always lettered in mint. At night it flips to mint lettered in forest. - Meadow (
bg-accent-soft) fills eyebrow pills, active sidebar items, avatar fallbacks, info alerts and the focus glow. It is never a text colour on a light ground. - Text steps from forest ink headings to slate body (#455252) and lichen muted copy (#526666).
- The six specimen pastels (mint, butter, lavender, sage, petal, meadow) belong to feature cards, showcase panels and quote cards. They never span the page width.
- Green, amber and brick mark status only, each on its own soft tint.
Charts
accent-1 to accent-6 (also chart-1 to chart-6) are six series colours
ordered so neighbours stay distinguishable. Six series lead with emerald, then
violet, amber, berry, teal and olive (jade, lilac, gold, pink, aqua and lime at
night). Chart colours never fill a surface or a button. Assign them in order;
never let colour be the only way to tell two series apart.
Dark mode
The palette is declared twice in src/app/globals.css: light on :root, dark
under @media (prefers-color-scheme: dark) and again on .dark, where the
class wins in both directions. @theme inline points every utility at those
variables, so bg-canvas is one class that follows the mode.
src/lib/design.ts sets the theme a first visit opens in: light here, because
Grove is drawn in light first. The theme menu in the header offers light, dark
and system and remembers the choice.
Type
Faces
- Figtree (
font-display,font-body): headings and display type; running text and interface copy. - DM Mono (
font-mono): code, ids and tabular labels (weights 400, 500).
Figtree is a geometric sans with humanist warmth: round bowls, a double-storey a and open shapes, so one family sets headings at 500 and text at 400. DM Mono is round in the same way, so code and keys still feel like the same product.
Every face loads through next/font/google in src/app/fonts.ts: downloaded at
build time and served from this app. Change a face there and here, together.
Scale
| Token | Size | Line | Tracking | Weight | Use |
|---|---|---|---|---|---|
text-display-xl | 72px | 0.9 | -0.024em | 500 | The hero headline, desktop |
text-display-lg | 56px | 0.95 | -0.024em | 500 | The hero headline, tablet |
text-display-md | 47px | 1 | -0.024em | 500 | Section headlines, the hero on phones |
text-display-sm | 36px | 1.05 | -0.024em | 500 | Section headlines on phones, big numbers |
text-title-lg | 22px | 1.1 | -0.024em | 500 | Page titles in the app |
text-title-md | 19px | 1.25 | -0.01em | 500 | Card titles |
text-title-sm | 16px | 1.3 | -0.005em | 500 | Small headings, table titles |
text-body-lg | 19px | 1.4 | 0 | 400 | Lead paragraphs |
text-body-md | 16px | 1.45 | 0 | 400 | Running text |
text-body-sm | 14px | 1.4 | 0 | 400 | Interface copy, table cells |
text-caption | 13px | 1.35 | 0 | 400 | Metadata, helper text |
text-caption-uppercase | 11px | 1.3 | 0.08em | 500 | Eyebrows above headings |
text-button | 14px | 1 | 0 | 500 | Buttons |
text-nav-link | 14px | 1.3 | 0 | 500 | Header and footer links |
Rules: one h1 per page. Display sizes are for marketing pages; the app tops
out at text-title-lg. Display steps run 72, 56, 47 and 36px at -0.024em with
tight leading (0.9 to 1.05); titles run 22, 19 and 16px, and body text is 16px
at 1.45. Caps appear only at 11px with 0.08em tracking: table heads, menu
labels, footer titles and the logo strip title. Eyebrow pills, buttons and nav
links stay in sentence case.
Space and layout
- Spacing tokens:
xxs4px,xs8px,sm12px,md16px,lg24px,xl28px,xxl48px,section72px (the gap between landing sections). - Content sits in
max-w-content(1280px) withpx-mdon phones andpx-lgfromsmup. Reading text stops atmax-w-measure(672px). - Spacing steps are 4, 8, 12, 16, 24, 28 and 48px, with 72px between sections.
- Compact but airy: gaps inside components are 8 to 12px and cards pad 24 to 28px.
- Sections are split by space, not colour bands. Pastels sit on contained cards and panels, never across the full width.
Shape and depth
| Token | Value | Where |
|---|---|---|
rounded-xs | 7px | Breadcrumb, Checkbox, DropdownMenu, Kbd, Select, Tooltip, the landing page |
rounded-sm | 12px | Accordion, Button, Input, Tabs, Toaster, the landing page |
rounded-md | 14px | Alert, Card, DropdownMenu, Popover, Select, Skeleton, Toaster, the landing page |
rounded-lg | 22px | AlertDialog, Dialog, the landing page |
rounded-xl | 28.8px | The landing page |
rounded-pill | 9999px | Badge, Button, Dialog, Progress, Sheet, Switch, Tabs, the landing page |
rounded-full | 9999px | Accordion, Avatar, RadioGroup, Switch |
Radii are 7px on checkboxes, keys, menu items and tooltips, 12px on buttons and
fields, 14px on cards, menus and alerts, 22px on dialogs and the product window,
and 29px on specimen cards, showcase panels and the closing panel. Borders are
1px forest ink at 10%, never grey; fields use ink at 22% and raised keys 16%.
Every drop is layered and tinted deep green: xs under small controls, soft
under cards, lift under the product window, showcase cards and the highlighted
plan, overlay under menus and dialogs, and inset is the white top highlight
that soft and overlay already carry. Buttons read their own set:
--button-sheen (a soft top sheen over the fill, brighter on hover, an inner
shade on press), --button-shadow (a white top highlight, a darker green edge
and base and a forest tinted drop), --button-shadow-hover (more lift),
--button-shadow-active (base and drop fold into an inner shadow), and the
--button-soft-* family (edge, sheen and shadows) for secondary and outline.
Fields, tracks and unchecked controls sit into the paper on --field-shadow and
--track-inset. Dark surfaces (the dark card, tooltips, the closing panel) use
--dark-surface-shadow: a faint mint rim over the lift. Dark mode uses deeper
black drops with the same mint rim.
Components
Every component lives in src/components/ui/ and is written against the tokens
above. Import from there; never restyle a kit component inline to make a
one-off.
| Component | In Grove |
|---|---|
Button | 12px corners, Figtree 500, sentence case, built like a key. Primary is emerald with a mint label under a soft top sheen, with a white top highlight, a darker green edge and base and a forest tinted drop (a mint key lettered in forest at night, on a green edge and a black drop, never a glow). Secondary and outline are white raised keys: a 16% ink edge, a base line under it and a faint fade toward parchment; secondary letters in emerald, outline in ink. Danger is brick built like primary; ghost fills with ink at 5% and sinks on press; link is ink with a 2px emerald underline on hover. Hover lifts 1px as the sheen brightens and the drop deepens. A press sinks 1px: base and drop fold into an inner shadow and the face darkens. Transitions run only when motion is allowed, and focus is a 2px emerald ring with a 2px gap. Sizes are 32, 40 and 44px tall. |
Badge | A 22px pill with a 13px label at 500, a hairline in its own tint and a faint top sheen. Accent is meadow with emerald text; neutral, success, warning and danger use their soft fills. Uppercase is 11px caps, and accent plus uppercase is the mint category pill with an ink line. |
Card | White on parchment with 14px corners and no border, on a layered soft shadow tinted green whose 1px ring is the edge, with a white top highlight. Soft and outline carry a hairline, strong sits into the page, and dark runs from elevated forest to deep forest with a mint rim on the lift shadow. Titles are forest ink at 19px and 500 (parchment on the dark tone), and padding runs 16 to 28px. |
Input, Textarea, Select | White 40px fields with 12px corners set slightly into the paper: a 1px ink line at 22%, a soft inner shadow and a white lip below. At night fields sit a shade below the card. Hover firms the line; focus turns it emerald with a 3px mint glow; invalid turns it brick. Textareas start at 96px. Select content is a white 14px menu on the overlay shadow whose highlighted item is meadow and whose check is emerald. |
Checkbox, RadioGroup, Switch | 18px controls with a 1px ink line at 30% and a soft inner shadow on white. Checked is emerald with a darker edge, a top highlight and a mint check or a raised mint dot (mint with forest at night); focus adds the mint glow. The switch is a 44 by 24px pill (36 by 20px small) whose track sits into the paper; the thumb is raised on its own shadow, light when off and mint on an emerald track when on. |
Tabs | Default tabs are a segmented control: a pill track set into the paper with a hairline (pale by day, a deep sunken green at night), and the active tab is a white pill raised on a green tinted shadow. Line tabs sit on a hairline and mark the active tab with a 2px emerald bar. |
Accordion | Rows split by hairlines with 16px ink triggers that turn emerald on hover. The chevron sits in a 28px meadow disc that turns emerald with a mint chevron when open. |
Dialog, AlertDialog, Sheet | A forest scrim at 40% with a 4px blur. Panels are white with 22px corners, a hairline, a top highlight and the overlay shadow; dialogs pad 28px and close on a 32px ghost pill, and sheets round only their inner edge. Alert dialogs pair a raised outline cancel with a primary or danger action. |
DropdownMenu, Popover, Select content, Tooltip | White panels with 14px corners, a hairline, a top highlight and the layered overlay shadow. Items have 7px corners and highlight to meadow; labels are 11px caps, shortcuts are DM Mono and checks are emerald. Tooltips are forest ink with parchment text, 7px corners, a mint rim and the lift shadow. |
Table | A 40px header in 11px caps on a soft band, hairlines between rows and a faint meadow hover. Selected rows take a deeper meadow tint and numbers are tabular; right-align number columns and set ids in font-mono. |
Alert | 14px corners, a hairline in the status tint, a top sheen and an icon on the left. Info is meadow with an emerald icon; success, warning and danger use their soft fills with the status colour on the icon. |
Avatar, Progress, Skeleton, Spinner, Separator, Kbd, Breadcrumb, Pagination, Field, Label, Toaster | Avatars are circles in a 2px card ring with meadow fallbacks and emerald initials. Progress is an 8px pill track set into the paper with a rounded emerald fill; skeletons pulse on a pale surface; spinners turn in the current colour. Separators are ink hairlines at 10%. Kbd is a DM Mono keycap on the raised surface with a pressed bottom edge. Breadcrumbs split on small chevrons. Pagination uses pill buttons with the same press: the current page is the raised outline pill. Labels are 14px at 500 in ink, helpers 13px in lichen. Toasts are white 14px cards on the overlay shadow that show status in the icon, with a small emerald action. |
The landing page
The landing page is the same in every design; the design decides how it looks.
Its sections carry data-slot hooks (listed at the top of
src/components/marketing/section-heading.tsx) that globals.css may style.
Grove styles these:
hero-backdrop: no wash and no grid, so the hero is quiet parchment.hero: from 64rem the copy splits like a journal page: headline and buttons on the left, the lead on the right at 22px in ink, its last line on the headline's last baseline.hero-eyebrow: the mint pill with a 1px ink line and a tiny lift; a trailing arrow sits in a forest disc and nudges 2px on hover.hero-actions: the emerald key button and, beside it, the white paper key with an emerald label; both lift 1px on hover and sink 1px on press.hero-visual: the aurora panel (lime, aqua, periwinkle, sky) with 44px corners and a wide field of colour beside the window; at night it is a jade, teal and indigo glow.product-preview: an 8px white frame, 22px corners and the lift shadow;product-preview-barturns soft parchment.section-eyebrow: every section opens with the mint pill in 13px sentence case, placed by its heading's own alignment.section-titleandsection-heading: balanced headings with 14px between pill, heading and lead;section-descriptionkeeps a 38rem measure.feature-card: pastel specimen cards in a fixed order (mint, butter, lavender, sage, petal, meadow) with 29px corners, a white top highlight, a faint ring and a soft green drop, and no hover lift;feature-iconis a 44px raised white chip with an emerald icon.showcase-visual: each picture sits on a mint, lavender or butter stage on the specimen shadow, with a white card floating on the lift shadow.step-marker: the raised emerald disc with a mint numeral sits in a 6px meadow halo with a hairline, like a seed.stat-gridandstat: separate white 14px cards on the soft shadow with a top highlight;stat-valueuses tabular numbers and grows to 47px on wide screens.testimonial: quotes always sit on lavender cards with 14px corners on the specimen shadow.sectionpricing: the highlighted plan has an emerald edge in a faint 4px green halo, on the lift shadow.faq: questions are white 14px cards on the soft shadow stacked 8px apart; the chevron sits in a meadow disc that turns into a raised emerald disc when open.cta-panel: the forest at night with 29px corners, a mint rim and the page's green tinted lift, a jade, aqua and indigo glow rising from the bottom edge, and the mint key button beside the soft raised one.site-nav: links in slate that turn ink on hover; the current page gets a 2px emerald underline.brand-mark: a leaf, round on three corners and tight on one.logo-cloudandlogo: the strip keeps 48px of parchment under the aurora panel; wordmarks in lichen at 500, spread 56px apart; image logos go grey at 70%.
Everything else is type, space and the kit.
Signed-in screens
The dashboard sits on parchment with a deeper parchment sidebar whose active item is a raised pale pill with a hairline and ink text; white cards rest on the soft shadow, and the small actions in them are the same raised keys as the landing page.
Sign-in is one white card with 14px corners centred on parchment, with white fields set into the paper, a full-width emerald key submit, a raised white provider button and a hairline divider.
Do and don't
Do
- Put every page on parchment (
bg-canvas) and lift content onto white cards (bg-card). - Pair emerald and meadow: an emerald fill carries a mint label, a meadow fill carries an emerald or ink label.
- Give each product module one pastel (mint, butter, lavender, sage, petal, meadow) and keep that pairing on every page.
- Open every landing section with the mint pill eyebrow, then the 47px heading, then the lead.
- Set headings, buttons and labels in Figtree 500 and text in 400, and track display sizes at -0.024em.
- Lift cards with the forest-tinted shadow and let its 1px ring stand in for a border.
- Keep the aurora to the hero picture and the closing panel, and let depth do the rest: raised things on green tinted shadows, fields and tracks set into the paper.
- Keep one emerald button per view; the second action is the soft raised button (secondary on the landing page, outline in the app).
Don't
- Don't use pure black or pure white for text. Ink is forest #001f1f; light text is parchment.
- Don't paint a full-width section in a pastel. Pastels live on contained cards and panels only.
- Don't use sharp corners. Nothing interactive goes under 7px.
- Don't add a new accent colour or use a chart colour for a surface or a button.
- Don't use grey or black drops on parchment, and don't stack heavy single shadows. Depth is layered, soft and tinted green.
- Don't repeat the aurora as a pattern or put it behind body text.
- Don't set buttons, nav links or eyebrow pills in mono or all caps. Caps are for 11px labels only.
- Don't use meadow as a text colour on light grounds (1.1:1). It is a fill, or a label on emerald.
Working in this design
Pasting from shadcn/ui. The token layer carries shadcn's variable names, so
most snippets render unmodified. Two utility names mean something else here:
bg-muted becomes bg-surface-card, and bg-accent / text-accent-foreground
(a hover surface upstream) become bg-surface-card / text-ink. Here muted
is a text colour and accent is the saturated accent.
Adding a token. Add it to all three palette blocks in globals.css (light,
the dark media query, .dark), map it in @theme inline, and document it in
the palette table above. Check contrast in both modes.
Adding a component. Check the kit first: most needs are a variant of
Button, Card or Badge, or a composition on the page. A new component gets
its own file in src/components/ui/, token classes only, a data-slot, and a
row in the Components table here. The designer subagent owns this.
Build a repo in Grove
The builder opens with Grove picked. Pick your batteries and the design is applied to every template before the zip is built.
