# Separator

A rule, in the three weights a monochrome page needs — with words in it when the break has something to say.

- Group: Display
- Import: `import { Separator } from '@misoto22/folio'`
- Page: https://ui.misoto22.com/components/separator/

## When to reach for it

Hairline between rows, edge between blocks, hard under a masthead. label puts words in the break: "or continue with", "Older".

## Anatomy

- **Rule** (required) — One <div>. A pixel on its cross axis and 100% on its main axis, so it takes the width — or the height — of whatever contains it, and nothing else.
- **Ink** (required) — The only thing weight changes: --rule inside a block, --rule-2 between blocks, --rule-hard under a masthead. The hard one is not a darker grey, it is --ink itself.
- **Label** — label, horizontal only. It changes the construction rather than the styling: the rule is drawn TWICE, one aria-hidden piece either side of the words in mono-meta at --ink-3-aa, and the gap between them is a gap.

## Best practices

### Do

- Give a vertical separator a height. It is h-full, which against a parent with no height of its own resolves to zero — the element renders, occupies nothing, and reads as a component that failed to load.
- Pass decorative={false} when the rule is the only thing dividing two sections a screen reader should hear as distinct: that is what swaps role="none" for role="separator" and sets aria-orientation with it.
- Use label rather than building "or continue with" out of two Separators and a span. The two rules are drawn for you and neither of them needs to know the ground it is on.

### Don’t

- Do not pick the weight by eye. The three are ordered, so a hard rule between two table rows tells the reader the table ended there.
- Do not hand-tune a fourth grey through className. Three named weights are the whole set, and the names exist because a monochrome page drifts into five slightly different rules the moment one of them is chosen by feel.
- Do not lay the label over a single rule with a background colour to punch a hole in it. That version has to be told the ground it is sitting on, and a --paper notch on a --stone card reads as a rendering bug.

## Accessibility

- role="none" by default. A rule that only groups things visually must not be announced.
- With a label, the words are the content and the two rules are aria-hidden decoration — so decorative no longer applies, and nothing announces a separator over the top of the text.
- A label on a vertical rule is ignored rather than silently redrawn as a horizontal bar: there is no sensible place for words inside a one-pixel column.

## Separator

A rule, with or without words in it. In a monochrome system the rule does the work colour would otherwise do, so it has three weights rather than one: hairline between rows, edge between blocks, hard under a masthead. Picking by name keeps a page from drifting into five hand-tuned greys. **On the label.** "or continue with" was two Separators and a span at every call site, and the usual one-element version — text laid over a single rule with a background to punch a hole in it — needs to know the ground it is sitting on. Get that wrong and the notch is `--paper` on a card that is `--stone`, which reads as a rendering bug. So there is no ground: the rule is drawn twice, one piece either side of the label, and the gap is a gap. It is correct on any surface without being told which one it is on.

### Props

- `orientation` — `'horizontal' | 'vertical'` default `'horizontal'`.
- `weight` — `'hairline' | 'edge' | 'hard'` default `'hairline'`. `hairline` divides rows inside one block; `edge` divides one block from the next.
- `decorative` — `boolean` default `true`. A rule that only groups things visually is decoration and must not be announced. Set `false` when the rule genuinely separates two sections a screen reader should hear as distinct.
- `label` — `ReactNode`. Words in the break — "or continue with", "Older". Horizontal only, and it changes the construction rather than the styling: see the note on the component. `decorative` no longer applies, because the label is content and the two rules beside it are decoration either way.

Also accepts: `HTMLAttributes<HTMLDivElement>`.

## Example — weights

```tsx
import { Separator } from '@misoto22/folio'

<div className="flex w-full flex-col gap-5">
  <div>
    <p className="m-0 mb-2 mono-meta text-(--ink-3-aa)">hairline — between rows</p>
    <Separator />
  </div>
  <div>
    <p className="m-0 mb-2 mono-meta text-(--ink-3-aa)">edge — between blocks</p>
    <Separator weight="edge" />
  </div>
  <div>
    <p className="m-0 mb-2 mono-meta text-(--ink-3-aa)">hard — under a masthead</p>
    <Separator weight="hard" />
  </div>
</div>
```

## Example — vertical needs a height

```tsx
import { Separator } from '@misoto22/folio'

<div className="flex flex-wrap items-center gap-3 text-sm text-(--ink-2)">
  <span>12 releases</span>
  <Separator orientation="vertical" className="h-4" />
  <span>0 rollbacks</span>
  <Separator orientation="vertical" className="h-4" />
  <span>99.98% uptime</span>
</div>
```

## Example — announced between sections

```tsx
import { Heading, Separator, Text } from '@misoto22/folio'

<div className="flex w-full flex-col gap-5">
  <section className="flex flex-col gap-2">
    <Heading level={3}>Installation</Heading>
    <Text size="sm">One package, and one stylesheet next to it.</Text>
  </section>
  <Separator weight="edge" decorative={false} />
  <section className="flex flex-col gap-2">
    <Heading level={3}>Upgrading</Heading>
    <Text size="sm">Minor versions add exports; they never move one.</Text>
  </section>
</div>
```

## Example — words in the rule

```tsx
import { Separator } from '@misoto22/folio'

<div className="flex w-full flex-col gap-6">
  <Separator label="or continue with" />
  <div className="rounded-(--radius-lg) bg-(--stone) p-5">
    <Separator weight="edge" label="Older" />
  </div>
</div>
```
