Divider
$ npx shadcn@latest add https://lacodda.github.io/dowel/r/divider.jsonThe 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
| Prop | Type | Default | |
|---|---|---|---|
spacing | none | sm | md | lg | 'none' | |
orientation | horizontal | 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. |
label | ReactNode | A caption sitting in the line: "Today", "Archived", "or". Horizontal only - there is no reading direction that puts a word inside a vertical rule. | |
decorative | boolean | false | A 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.
| Prop | Type | Default | |
|---|---|---|---|
titlerequired | ReactNode | The section's heading, drawn at level. | |
description | ReactNode | One line under the title, saying what the section holds. | |
actions | ReactNode | Buttons belonging to this section rather than to the screen - Add, Collapse, a link out. | |
level | 1 | 2 | 3 | 4 | 5 | 6 | 2 | Where 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.