flora

plants of a particular region or time

react components for binary garden

componentsiconsgithub
terminalsh
npm i @binarygarden/flora
app/layout.tsxtsx
import '@binarygarden/flora/styles.css';import { ProductScope } from '@binarygarden/flora/theme';export default function Layout({ children }) {  // one hue. that's the whole theme.  return <ProductScope hue={330}>{children}</ProductScope>;}
the design

one hue is the whole theme.

every binary garden site and product is built from the same components, type, spacing and motion. our own sites, like the trunk and this one, are black and white. each product we make for others adds one color. the rules below make that work.

color

neutrals · light

oklch hue 150 at chroma 0.004 — a trace of chlorophyll, so black and white read as paper and soil rather than #000 and #fff.

--bg-1
page / raised surface
--bg-2
sunken surface
--bg-3
tracks, disabled
--fg-1
body text
--fg-2
muted text, labels
--fg-3
faint text
--line-1
resting borders
--line-2
strong borders
neutrals · dark

data-theme='dark' on <html>. the same hue with inverted lightness; borders replace shadows.

--bg-1
page / raised surface
--bg-2
sunken surface
--bg-3
tracks, disabled
--fg-1
body text
--fg-2
muted text, labels
--fg-3
faint text
--line-1
resting borders
--line-2
strong borders
accent · one knob

--product-hue is the only thing that changes between products. the trunk sets none, so the accent is just the text colour: black in light mode, white in dark.

no scope · the trunk
accent
hue 60
accent
hue 150
accent
hue 200
accent
hue 330
accent
semantic

status only, never decorative. a semantic colour on a button that isn't reporting state is a bug.

--ok
oklch(0.62 0.15 150)
--warn
oklch(0.72 0.15 75)
--danger
oklch(0.58 0.19 25)
--info
oklch(0.6 0.13 240)

type

display

hanken grotesk, medium, tracking -0.03em, leading 1.05. text-wrap: balance on headings.

open source, for humans.
headings & body

one family. hierarchy comes from size, weight and tracking — never from a second face.

h1 · 36 / 1.2
h2 · 22 / 1.2
lg · 18 / 1.5
body · 15 / 1.5 — paragraphs get text-wrap: pretty.
small · 13 / 1.5
scale

11 → 88 in 11 steps.

tokenpxspecimen
--text-2xs11binary garden
--text-xs12binary garden
--text-sm13binary garden
--text-md15binary garden
--text-lg18binary garden
--text-xl22binary garden
--text-2xl28binary garden
--text-3xl36binary garden
--text-4xl48binary garden
--text-5xl64binary garden
--text-6xl88binary garden
line length

lines of 45–75 characters read best, so headings and paragraphs cap their width in ch. the bigger the text, the shorter the line.

textmax-width
display (hero headline)16ch
h124ch
hero subtitle48ch
lead paragraph (lg)60ch
body and small paragraphs68ch

this paragraph stops at 68ch however wide the window gets. below that it wraps with its container like any other text. code, tables, labels and one-line ui text like buttons and nav are not capped.

labels & code

labels are lowercase at +0.02em tracking and use --fg-2, not --fg-3, on the page background. code uses the system mono stack.

a label · 12 / 500 / +0.02em
ts
const hue = 330; // the whole theme

spacing & shape

scale

4px base. components use 1–6; sections use 20–24 of vertical space.

--space-1
4
--space-2
8
--space-3
12
--space-4
16
--space-5
20
--space-6
24
--space-8
32
--space-10
40
--space-12
48
--space-16
64
--space-20
80
--space-24
96
--space-32
128
control heights

32 / 40 / 48. every control in the system lands on one of these.

radius & shadow

soft, not round — the radius grows with the box. shadows appear only on things that float; resting cards use a border.

tokenpxused forspecimen
--radius-xs4badges, focus
--radius-sm6controls
--radius-md8cards, code
--radius-lg12tiles, dialogs, palette
--radius-full999tags, switches
--shadow-sm
--shadow-md
--shadow-lg

motion

easing

ease-out for most things; the spring is for entrances only, because it overshoots. reduced motion zeroes every duration.

tokencurveused for
--ease-outcubic-bezier(0.2, 0.8, 0.2, 1)state changes, 120–200ms
--ease-in-outcubic-bezier(0.65, 0, 0.35, 1)symmetric moves
--ease-springcubic-bezier(0.34, 1.4, 0.64, 1)entrances only — it overshoots
hover · press · reveal

buttons lift 1px on hover, cards 2px with a shadow. press scales to .98. reveals rise 12px and fade, staggered 60ms.

hover me

lift 1px + shadow

press me

scale .98

revealed

rise 12px + fade

focus

a 2px accent ring offset by the page colour. inputs get a 3px soft-accent halo instead. tab through these.

brand

mark

the five-petal flower: black on light, white on dark, never recoloured or tinted with a product hue. minimum 20px. the name is set beside it in hanken grotesk 500 at -0.01em.

binary garden
voice

terse, technical, lowercase. say the thing.

donot
open source, for humans.Powerful, Seamless Open Source!
read the docsLearn More
publishGet Started Now
v1.2 · 14 contributorsVersion 1.2 (14 contributors!)
publishedWe published your changes 🎉