# Pattern fill

Six hatch patterns as SVG `<defs>`, in the card's colour so they read over any series colour: diagonal, the other diagonal, horizontal, vertical, dots and a cross-hatch. Draw a shape's colour first, then the same shape again with `fill={patternFor(index, id)}` over it, so series are told apart by pattern as well as colour.

- Registry name: `pattern-fill` (`@candor/pattern-fill`)
- Tier: Pro. Installing it needs a Pro, Premium or Team licence key: the person runs `npx candor-ui key <key>` themselves; never ask for the key in chat or write it to a file.
- Docs: https://candor.themethodic.com/docs/pattern-fill

## Install

```bash
npx candor-ui add pattern-fill
```

Run `npx candor-ui@latest init` once first (https://candor.themethodic.com/get-started.md). Without the CLI: `npx shadcn@latest add @candor/pattern-fill`.
It brings in: tokens.

## Example

```tsx
"use client"

import { BarChart } from "@/components/candor/bar-chart"
import type { Series } from "@/lib/candor/data"

// Patterns show by themselves under the high-contrast theme; `always` shows them here in every theme.
const runs: Series[] = [
  { id: "passed", label: "Passed", values: [212, 148, 96, 74] },
  { id: "failed", label: "Failed", values: [3, 0, 5, 1] },
  { id: "skipped", label: "Skipped", values: [12, 30, 8, null] },
]

export default function Example() {
  return <BarChart className="max-w-xl" title="Tests by repository" subtitle="Patterns always on" categories={["api", "web", "billing", "workers"]} series={runs} patterns="always" />
}
```

## <ChartPatterns>

Props:

- `id?: string | undefined` (default `"cd-pattern"`): The prefix of the patterns' ids, unique on the page; pass the same to `patternFor`. Defaults to `cd-pattern`.

## Functions

### markerIsStroke

```ts
markerIsStroke(index: number)
```

Whether the nth marker is drawn as lines (the plus and the cross) rather than a filled shape.

### patternFor

```ts
patternFor(index: number, prefix = "cd-pattern")
```

The fill that draws the nth series' pattern, `url(#…)`, for a shape drawn over the series' colour. `prefix` is the `id` given to the `ChartPatterns` in the same document; left out, it is `cd-pattern`.

### markerPath

```ts
markerPath(index: number, x: number, y: number, r: number)
```

The nth series' marker for a line chart, as a path centred on (x, y) with radius r: a circle, a square, a triangle, a diamond, a plus and a cross, so lines are told apart by their points as well as their colour.

### patternStyle

```ts
patternStyle(index: number)
```

The nth pattern as CSS, for a shape drawn in HTML rather than SVG: a `backgroundImage` (and `backgroundSize` for the dots) to lay over the series' colour. The same six as `ChartPatterns`, in the same order. It is for the high-contrast theme only: forced colours drop an HTML background image and colour, so a shape that has to survive them is drawn in SVG with `ChartPatterns` and `patternFor`, as `ShareBar`'s are.

### useChartPatterns

```ts
useChartPatterns(mode: ChartPatternMode, ref: React.RefObject<Element | null>)
```

Whether series patterns show for an element: always or never by `mode`, and with `auto` while the nearest `data-theme` above it is `hc` or the system is in forced colours. Watches both, so switching theme switches the patterns. False until mounted (on the server the default themes need none).

## Values

### PATTERN_COUNT

How many distinct patterns there are; the seventh series takes the first again.

```ts
const PATTERN_COUNT: 6
```

## Types

### ChartPatternMode

When series patterns show: `auto` under the high-contrast theme (`data-theme="hc"` on an ancestor) and in forced colours, `always` everywhere, `never` not at all. The default themes look the same with `auto` as without patterns.

```ts
"auto" | "always" | "never"
```

## Rules for using Candor UI

- Components take plain typed data. Never pass model output as HTML or render it as a link; messages are typed blocks.
- A control that can't be used says why: wrap it in `<Locked reason="…">`, don't just disable it.
- Don't show a value you don't have: leave it out (it renders as —) rather than guess. An estimate is labelled as one.
- Nothing is pre-selected in a decision a person makes, and the agent is named from your app's data, never from model output.
- Your app's words go in `LocaleProvider`: its fixed strings in `strings`, its nouns in `nouns`; entity kinds and agent roles in `EntityKindsProvider` and `AgentRolesProvider`.
