Skip to content

Divider

Terminal window
$ npx shadcn@latest add https://lacodda.github.io/dowel/r/divider.json
See it liveA plain rule, a captioned break, a vertical rule in a row of controls, and a section heading with its own actions.→

The set already had four separators — in the menu, the select, the context menu and the action bar — and each was written inside the thing it divided, so a screen that wanted a rule between two sections had nothing and reached for a bare <hr> or a div with a background.

<SectionHeader title={t('versions')} description={t('versions.hint')} actions={<Button>{t('add')}</Button>} />
<VersionList />
<Divider label={t('archived')} spacing="lg" />
<ArchivedList />

A rule is a claim, and decorative withdraws it. A boundary between sections carries role="separator", which is what tells a reader the content after it is a different thing. A rule that is only drawing — a hairline inside a card, a tick between two numbers — should not be announced at all, and a reader hearing “separator” six times in one row is being read the styling.

It is not Base UI’s Separator, which was the obvious dependency and does not do the one thing this is for: it renders a div with aria-orientation and no role, so nothing is announced as a separator at all. That was measured by rendering it, not read off the documentation.

A vertical rule stretches, it does not fill. h-full in a flex row of buttons resolves to zero — a rule that is in the markup and invisible on the screen — so this one is self-stretch.

Spacing follows the axis. md is my-4 on a horizontal rule and mx-4 on a vertical one; the same step on the wrong axis is the bug that pair prevents. The default is none, because the common case is a rule inside something already padded.

A caption in the line. label makes the rule a captioned break: the rule runs to the word, the word sits in it, and the rule continues. It is a heading for a run of content that does not deserve one — “Today”, “Archived”, “or”. Horizontal only; there is no reading direction that puts a word inside a vertical rule.

SectionHeader is an h2. PageHeader holds the screen’s h1 and a section is one level inside it, so a reader moving by heading walks the screen’s actual structure. It is the between-size heading the products kept writing by hand: above SectionLabel’s uppercase caption and below the page’s title.

Props

Read from the types in ui/divider.tsx, the file a product copies - so the description of each prop is also what an editor shows over it there.

Divider

PropTypeDefault
spacingnone | sm | md | lg'none'
orientationhorizontal | vertical'horizontal'Declared here rather than taken from the variants: cva types a variant as nullable, and aria-orientation is not - a null passed through would be a type error at the call site and an attribute React drops.
labelReactNodeA caption sitting in the line: "Today", "Archived", "or". Horizontal only - there is no reading direction that puts a word inside a vertical rule.
decorativebooleanfalseA rule that is styling rather than structure. Taken out of the accessibility tree, so a reader is not told about it.

And every prop of React's HTMLAttributes<HTMLDivElement> except children, passed on.

SectionHeader

The heading over a part of a screen, with what belongs to that part at the far end of the same row.

PropTypeDefault
titlerequiredReactNodeThe section's heading, drawn at level.
descriptionReactNodeOne line under the title, saying what the section holds.
actionsReactNodeButtons belonging to this section rather than to the screen - Add, Collapse, a link out.
level1 | 2 | 3 | 4 | 5 | 62Where the section stands in the outline: 2 by default.

And every prop of React's HTMLAttributes<HTMLDivElement> except title, passed on.

Accessibility

The examples on the stand, through axe 4.14.0 in a browser, in both themes, against WCAG 2.2 A and AA and axe's best practices: 16 rules applied and passed, and none failed. The accessibility report has every item.

History

Each release that changed ui/divider.tsx - the file a product copies - newest first.

  1. v0.41.0
    • docs read every props table from the component's types ee3b159
  2. v0.38.0
    • feat a heading stands at the level the page gives it 101c183
  3. v0.33.0
    • feat one caption utility and the compact rail width 88a3fee
  4. v0.29.0
    • feat a rule that says whether it means anything 6494aa8