Separator
A hairline rule for separating sibling content — the visual analogue of <hr>. Horizontal by default, vertical when stretched between flex / grid children. Decorative by default so it stays out of the accessibility tree; flip decorative={false} to announce a semantic break with role="separator" and the matching aria-orientation.
The journeyThree ways to see what you built
Step 1Step 2Step 3
Last block is a semantic separator (role="separator").
Installation
npx shadcn@latest add https://craftbits.dev/r/separator.jsonUsage
import { Separator } from "@craft-bits/core";
<Separator />Stretch a vertical rule between inline siblings inside a flex row:
<div className="flex h-5 items-center gap-4">
<span>Step 1</span>
<Separator orientation="vertical" />
<span>Step 2</span>
</div>Announce the break to assistive tech when the rule separates groups of content:
<Separator decorative={false} />Understanding the component
- Hairline rule, not a heading. Separator renders a
1pxfilled<div>painted with--cb-border-muted. Pair it with a heading underneath when you need an a11y landmark; keep it on its own when the break is purely visual. - Orientation drives sizing.
horizontal(default) setsh-px w-fullso the rule fills the row.verticalsetsh-full w-px self-stretchso the rule grows to its flex / grid track height — pin a height on the parent for the rule to land. - Decorative is the safe default.
decorativerendersrole="none"and skipsaria-orientation, matching<hr aria-hidden>.decorative={false}exposesrole="separator"plusaria-orientation="vertical"when the orientation is vertical; horizontal is the WAI-ARIA implicit default so the attribute is omitted. - Data hooks. The root carries
data-cb-separator,data-orientation, anddata-decorativeso consumers can target nested regions without re-deriving props. - No motion. The component is fully static — reduced-motion respect is the responsibility of the surrounding layout.
Variants
Horizontal (default)
<Separator />Vertical
<div className="flex h-5 items-center gap-4">
<span>Step 1</span>
<Separator orientation="vertical" />
<span>Step 2</span>
</div>Announced (non-decorative)
<Separator decorative={false} />Props
| Prop | Type | Default | Description |
|---|---|---|---|
orientation | 'horizontal' | 'vertical' | 'horizontal' | Layout axis. horizontal sets h-px w-full; vertical sets h-full w-px self-stretch. |
decorative | boolean | true | When true, renders role="none" and omits aria-orientation. When false, renders role="separator" and exposes aria-orientation on the vertical variant. |
className | string | — | Merged onto the rendered <div> via cn(). |
...rest | HTMLAttributes<HTMLDivElement> | — | Any other <div> attribute. |
Accessibility
- Decorative separators render
role="none"and are never announced to assistive tech — the WAI-ARIA pattern for purely-visual breaks. - Non-decorative separators render
role="separator". The horizontal orientation matches the ARIA default, soaria-orientationis omitted; the vertical orientation explicitly setsaria-orientation="vertical". - Colour contrast: the rule paints with
--cb-border-muted, which clears the WCAG3:1UI-component contrast threshold on the default--cb-bgand--cb-bg-elevatedsurfaces. - No motion. Reduced-motion respect is the responsibility of the surrounding content.
Credits
- Extracted from:
algoflashcards(src/platform/ui/separator.tsx). The original wrappedradix-ui'sSeparator.Rootto inherit the same ARIA semantics. craft-bits drops the Radix dependency in favour of a direct DOM render — the role / orientation logic is small enough that the runtime cost outweighs the peer-dep cost — and swaps the rawbg-borderTailwind class for the cb-token-drivenbg-cb-border-muted.