Primitives Layout and display
Separator
A native <hr> between blocks, or role="separator" with a vertical orientation between inline items. The browser exposes both as separators; the package draws the line and writes down when a separator should be silent. Tier 0.
- Tier
- 0 · Native
- Behavior JS
- 0 B brotli · 0 B gzip ·
fixtures/· methodresults.json (native-only) - Platform features
<hr>,role="separator",aria-orientation- Shared listeners
- none
- Per-instance listeners
- none
- Lazy state
- none
- Native base
<hr>, role="separator"
On this page
Example
The first topic ends here.
A second topic starts after the rule.
<p>The first topic ends here.</p>
<hr data-slean="separator" />
<p>A second topic starts after the rule.</p>
<nav aria-label="Separator example" class="links">
<a href="/primitives">Primitives</a>
<div role="separator" aria-orientation="vertical" data-slean="separator"></div>
<a href="/table">Table</a>
<div role="separator" aria-orientation="vertical" data-slean="separator"></div>
<a href="/styling">Styling</a>
</nav><script lang="ts">
import '@svelte-lean/styles/separator.css';
</script>
<p>The first topic ends here.</p>
<hr data-slean="separator" />
<p>A second topic starts after the rule.</p>
<nav aria-label="Separator example" class="links">
<a href="/primitives">Primitives</a>
<div role="separator" aria-orientation="vertical" data-slean="separator"></div>
<a href="/table">Table</a>
<div role="separator" aria-orientation="vertical" data-slean="separator"></div>
<a href="/styling">Styling</a>
</nav>
<style>
.links {
display: flex;
align-items: center;
}
</style>Why this implementation exists
<hr> is a separator for assistive technology and a thematic break in the document; the browser draws it with an inset border that the stylesheet replaces with a one-pixel line. Between inline items there is no element for a vertical line, so the ARIA role takes its place, with the orientation set because the role defaults to horizontal.
The decision that matters is whether a separator is announced at all. Most lines in an interface only draw a boundary that the structure already makes, and hearing "separator" between every pair of links adds nothing. The contract names the two forms and how to silence one.
The browser owns
- the separator role of <hr> and its horizontal orientation
- the vertical orientation announced from aria-orientation
- leaving a decorative separator out of the accessibility tree (aria-hidden)
Svelte Lean owns
- separator.css: the one-pixel border, the spacing, the vertical line that fills its row
- the contract: when a separator is announced and when it is decorative
- documentation
Usage
The markup needs no package. Install @svelte-lean/styles for the stylesheet; @svelte-lean/primitives adds the typed contract and nothing at runtime.
npm install @svelte-lean/stylespnpm add @svelte-lean/stylesyarn add @svelte-lean/stylesbun add @svelte-lean/stylesimport '@svelte-lean/styles/separator.css';Use <hr> between blocks that change topic. Use the vertical form between items in a row, inside a flex container: the line takes the row’s height. In running text it is one line of text tall.
For a decorative line add aria-hidden="true". On an <hr>, role="none" has the same effect, but it cannot carry aria-orientation, so the vertical form uses aria-hidden.
Anatomy
| Part | Element | data-slean-part | Required | Notes |
|---|---|---|---|---|
| root | <hr data-slean="separator"> | – | yes | Horizontal, between blocks. aria-hidden="true" when decorative. |
| vertical | <div role="separator" aria-orientation="vertical"> | – | no | Between inline items. The styles read aria-orientation. |
Runtime profile
Tier 0: the separator has no behavior module, the Vite plugin maps separator to no module, and the native-only fixture proves the path ships no Svelte Lean JavaScript.
Accessibility contract
<hr>is exposed as a horizontal separator; the vertical form as a vertical separator fromaria-orientation.- A static separator is not focusable and has no name.
- A decorative separator with
aria-hidden="true"is not in the accessibility tree. - A focusable separator with a value is a window splitter, which this primitive is not.
Keyboard
| Key | When | Result |
|---|---|---|
| Tab | anywhere | Passes the separator by: a static separator is not focusable (native) |
Platform features
| Feature | Baseline | Outside the target |
|---|---|---|
<hr>, role="separator", aria-orientation | Widely available | Not applicable within the support policy |
Without JavaScript
Fully functional.
Server rendering
Static HTML.
Before hydration
Nothing is attached.
Styling
separator.css removes the inset border of <hr>, draws a one-pixel border in the border token, sets the spacing, and turns an element with aria-orientation="vertical" into a line that fills its flex row. The tokens it reads:
| Token | Default (light) | Applies to |
|---|---|---|
--slean-space-4 | 1rem | margin-block |
--slean-border | var(--slean-neutral-6) | border-block-start, border-inline-start |
--slean-space-2 | 0.5rem | margin-inline |
State selectors the stylesheet targets, all from the platform or ARIA: [aria-orientation="vertical"].
Compatibility notes
Everything here is widely available.
Examples
Decorative separators
A line that repeats a boundary the content already has is decoration. Add aria-hidden="true" so it is not announced, or draw it as a border in the application's
CSS with no element at all.
<!-- The names already read as separate items; the line only draws that boundary. -->
<p class="byline">
<span>Amara Okafor</span>
<span role="separator" aria-orientation="vertical" data-slean="separator" aria-hidden="true"></span>
<span>Design team</span>
</p>
<!-- The same line in the application's CSS, with no element. -->
<style>
.byline > span + span {
border-inline-start: 1px solid var(--slean-border);
padding-inline-start: 0.5rem;
}
</style>Testing
apps/playground/tests/primitives/display.spec.tsPlaywright: open state, exclusive groups, stretched links, roles and names, carousel scrolling, axepackages/styles/testsstatic checks of the stylesheet (layers, tokens, specificity, dark parity)
Source
packages/primitives/src/separator/contract.mdthe contract in prose: semantics, keyboard, focus, ARIA, SSR, JS-disabled behaviorpackages/primitives/src/separator/contract.tstyped constants: name, tier, base, parts, options, eventspackages/styles/css/separator.cssthe optional stylesheet