React tutorial
Typed function components, ae file ilkane, controllit wi the standard
value + onChange pattern — aathing wirks the wey React aareadies does.
Whit ye'll big
A wee contact form — labelled input, submit button, controllit state, real keyboard an screen-reader behaviour — first bare, then styled, in aboot 10 minutes.
Afore ye stairt
Ye need git, Node 22 or later, an pnpm 10 or later. Onie React 18+ project wirks — Next.js, Vite, or plain React.
Step 1 — Git the code
git clone https://github.com/LilyDesignSystem/lily-design-system
cd lily-design-system/lily-design-system-react-headless
pnpm install
pnpm test # vitest + @testing-library/react
pnpm run storybook # browse all 571 components
The components are flat files in components/ —
Button.tsx, TextInput.tsx — ilkane wi its test, story, an docs alangside. Copy the files ye need intae yer app, or vendor the repo an import frae it.
Step 2 — Yer first component
import Button from "lily-design-system-react-headless/components/Button";
export function SaveBar() {
return <Button onClick={save}>Save</Button>;
}
Renders <button class="button" type="button">. Props:
type, disabled, pressed (renders
aria-pressed), label (an
aria-label owerride), className, an onie extra attribute spreids ontae the root element.
Step 3 — Compose a wee form
import { useState } from "react";
import Form from ".../components/Form";
import Field from ".../components/Field";
import TextInput from ".../components/TextInput";
import Button from ".../components/Button";
export function ContactForm() {
const [name, setName] = useState("");
return (
<Form label="Contact form" onSubmit={handleSubmit}>
<Field label="Full name" required>
<TextInput id="name" label="Full name" value={name} onChange={setName} required />
</Field>
<Button type="submit">Save</Button>
</Form>
);
}
Field taks the visible label as its ain prop raither than a nestit label component — pass it ance, on
Field, an TextInputon
label supplies the accessible name.
Verified 2026-08-29: an earlier draft nestit a separate Label inside Field, which renders
twa labels (ane empty) because Field aareadies renders its ain frae the label prop — catcht bi compilin the exact snippet. The
contact-form composed route
is the same pattern, exercised bi real e2e an axe tests.
Step 4 — Style it
Aathing abune renders as pure structure, ready for yer styles. Style the hooks — .button,
.text-input, .label, .field — in yer stylesheet, layer Tailwind utilities through className, or link a ready-made theme:
<link rel="stylesheet" href="/themes/united-states-web-design-system.css" />
Step 5 — See it aw wirkin
The Next.js example app is the full catalog styled an demoed, wi Playwright e2e an an axe-core baseline:
git clone https://github.com/LilyDesignSystem/lily-design-system
cd lily-design-system/lily-design-system-react-next-examples
pnpm install && pnpm run dev
Neist steps
- Theming — runtime switchin wi the React theme-picker helper.
- Preference helpers — leid an text size.
- Component catalog — props, ARIA, an keyboard per component.
Questions alang the wey? The help page is fu o answers — an if a step could be clearer, tell us an we'll gladly improve the tutorial.