Tutorials

React tutorial

Typed function components, one file each, controlled with the standard value + onChange pattern — everything works the way React already does.

What you'll build

A small contact form — labelled input, submit button, controlled state, real keyboard and screen-reader behaviour — first bare, then styled, in about 10 minutes.

Before you start

You need git, Node 22 or later, and pnpm 10 or later. Any React 18+ project works — Next.js, Vite, or plain React.

Step 1 — Get the code

git clone https://github.com/LilyDesignSystem/lily-design-system-react-headless
cd lily-design-system-react-headless
pnpm install
pnpm test        # vitest + @testing-library/react
pnpm run storybook   # browse all 490 components

Components are flat files in components/Button.tsx, TextInput.tsx — each with its test, story, and docs alongside. Copy the files you need into your app, or vendor the repo and import from it.

Step 2 — Your 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 override), className, and any extra attribute spreads onto the root element.

Step 3 — Compose a small form

import { useState } from "react";
import Form from ".../components/Form";
import Field from ".../components/Field";
import Label from ".../components/Label";
import TextInput from ".../components/TextInput";
import Button from ".../components/Button";

export function ContactForm() {
  const [name, setName] = useState("");
  return (
    <Form onSubmit={handleSubmit}>
      <Field>
        <Label htmlFor="name">Full name</Label>
        <TextInput id="name" label="Full name" value={name} onChange={setName} required />
      </Field>
      <Button type="submit">Save</Button>
    </Form>
  );
}

Check your work: run the app and the form looks plain — exactly as intended: styling is still ahead. Press Tab: focus moves through every control, the label is announced, and submit works. The behaviour is done; the look is yours, and it's next.

Step 4 — Style it

Everything above renders as pure structure, ready for your styles. Style the hooks — .button, .text-input, .label, .field — in your stylesheet, layer Tailwind utilities via className, or link a ready-made theme:

<link rel="stylesheet" href="/themes/united-states-web-design-system.css" />

Step 5 — See it all working

The Next.js example app is the full catalog styled and demoed, with Playwright e2e and an axe-core baseline:

git clone https://github.com/LilyDesignSystem/lily-design-system-react-next-examples
cd lily-design-system-react-next-examples
pnpm install && pnpm run dev

Next steps

Questions along the way? The help page is full of answers — and if a step could be clearer, tell us and we'll gladly improve the tutorial.