Dot Field
betaA wide field of dithered dots, with bands of theme color that wind across it, as art behind a hero or a section title.
Built from Motion Timing.
Preview
behind a headline
Signal through the noise.
three bands, another seed
narrow container
Install
1. Add the registry to
components.json, once per app. Without it, the shadcn CLI looks up@txbrendanin a public list that txbrendan/ui does not control.npx shadcn@latest registry add "@txbrendan=https://txbrendan.dev/r/{name}.json"2. Add the theme, once per app. It replaces your color tokens with ones checked for contrast.
npx shadcn@latest add @txbrendan/theme3. Add the website component. It also adds every component it uses. Its own files go in your
componentsfolder, and they are yours to edit.npx shadcn@latest add @txbrendan/dot-field
Use it for
- Art for a landing page, like the band behind a hero, a section title, or a call to action.
- Put a short Headline inside it as children. It sits in the middle of the field.
- Pass `bands` to pick the colors, as theme colors like `var(--chart-1)`. Later bands draw on top.
- Pass `seed` for another shape. The same seed always draws the same field.
- Pair it with Dither, so the charts and buttons on the page share its dotted look.
Avoid it for
- Long text over the field. The dots behind it make it hard to read. Keep it to a short headline.
- Raw colors in `bands`. Use theme colors, so the field follows light and dark.
- Information. The field is art, so it says nothing a screen reader needs, unless you name it.
Props
- bands
Each band's color, as a theme color. Later bands draw over earlier ones.
readonly string[] · default ["var(--chart-4)", "var(--chart-2)"]
- seed
Picks the shape of the bands.
number · default 1
- size
Height: 5, 8, or 12 times --control-h-md, so density scales it.
"sm" | "md" | "lg" · default "md"
- aria-label
Names the field as an image. Left out, screen readers skip it.
string
- children
Content over the field, like a Headline. It sits in the middle.
ReactNode
- className
Extra classes on the root. Later classes win, so className='h-64' sets the height.
string
| Prop | Type | Default | What it does |
|---|---|---|---|
| bands | readonly string[] | ["var(--chart-4)", "var(--chart-2)"] | Each band's color, as a theme color. Later bands draw over earlier ones. |
| seed | number | 1 | Picks the shape of the bands. |
| size | "sm" | "md" | "lg" | "md" | Height: 5, 8, or 12 times --control-h-md, so density scales it. |
| aria-label | string | - | Names the field as an image. Left out, screen readers skip it. |
| children | ReactNode | - | Content over the field, like a Headline. It sits in the middle. |
| className | string | - | Extra classes on the root. Later classes win, so className='h-64' sets the height. |
Accessibility
- The field is decoration, hidden from screen readers. Pass aria-label to name it as an image instead.
- The name sits on the canvas, so a Headline in children stays a real heading.
- When the field first comes on screen, its dots grow in one at a time, sweeping in from the left, over 60% of --motion-pulse-duration. After that, nothing moves.
- With reduced motion or motion off, the pulse is 0s, so every dot shows at once. A print shows every dot.
Examples
Art on its own
<DotField />Behind a headline
<DotField size="lg" bands={["var(--chart-1)", "var(--chart-2)"]}>
<Headline texture="dither" title="Signal through" muted="the noise." />
</DotField>