--primitiv-divider-color--primitiv-divider-thickness--primitiv-divider-spacingA separator between content sections — a <span role="separator"> whose aria-orientation drives a horizontal or vertical rule.
Preview
import { Divider } from "@/components/ui/divider";
<Divider orientation="horizontal" />import { Divider } from "@primitiv-ui/react";
<Divider orientation="horizontal" />Density is set by a data-density ancestor — the Context system, not a Divider prop.
npx primitiv add dividerpnpm dlx primitiv add divideryarn dlx primitiv add dividerbunx primitiv add dividerImport
import { Divider } from "@/components/ui/divider";Copied into your project as .primitiv-divider — you own the file afterwards, so upgrades are opt-in.
Headless mode installs the npm package instead: @primitiv-ui/react
Extends HTMLSpanElement — every native attribute of that element is accepted and forwarded.
| Prop | Type | Default | From | Description |
|---|---|---|---|---|
| orientation | "horizontal" | "vertical" | "horizontal" | headless | Axis the separator runs along. Sets aria-orientation on the rendered
<span role="separator"> so screen readers announce the correct
orientation. Use "horizontal" for row-dividing rules and
"vertical" for column-dividing rules. |
--primitiv-divider-color--primitiv-divider-thickness--primitiv-divider-spacing<span role="separator">, so assistive tech announces it as a boundary between content groups rather than as decoration.orientation sets aria-orientation on that element — "horizontal" (the default) or "vertical" — so the announced axis matches what is drawn.aria-hidden="true". A separator whose meaning is already carried by the surrounding structure is noise in the accessibility tree, and hiding it is the right call there.The default: a full-width hairline that spans its container and reads as a real role="separator" to assistive tech. Note the breathing room around it is the container's gap, not the rule — Divider reserves no separation of its own (see below).
import { Divider } from "@/components/ui/divider";import { Stack } from "@/components/ui/stack";
<Stack gap="lg"> <section>{/* ... */}</section> <Divider /> <section>{/* ... */}</section></Stack>import { Divider } from "@primitiv-ui/react";
<div style={{ display: "flex", flexDirection: "column", gap: "1rem" }}> <section>{/* ... */}</section> <Divider /> <section>{/* ... */}</section></div>orientation="vertical" sets aria-orientation and turns the rule 90°. A vertical divider takes its height from the flex row it sits in — a flex item stretches to the row's cross-axis by default — so a plain block or column gives it no height to span. Ideal between inline metadata or toolbar groups.
import { Divider } from "@/components/ui/divider";import { Stack } from "@/components/ui/stack";
<Stack direction="row" gap="md"> <span>Overview</span> <Divider orientation="vertical" /> <span>Pricing</span> <Divider orientation="vertical" /> <span>Docs</span></Stack>import { Divider } from "@primitiv-ui/react";
<div style={{ display: "flex", gap: "1rem" }}> <span>Overview</span> <Divider orientation="vertical" /> <span>Pricing</span> <Divider orientation="vertical" /> <span>Docs</span></div>Divider ships no margin by default — separation is the container's job. A gap-based container already spaces its children, and a margin baked into the rule would double that, could never reach 0, and could not track data-density. When a plain block-flow context has no gap of its own, give the rule its own margin: the styled surface exposes --primitiv-divider-spacing for exactly this, and in headless — where no styles ship at all — you set the margin directly.
Above the rule.
Below the rule.
import { Divider } from "@/components/ui/divider";
{/* Plain block flow — no container gap, so the rule reserves its own. */}<article> <p>{/* ... */}</p> <Divider style={{ "--primitiv-divider-spacing": "var(--primitiv-space-space-16)" }} /> <p>{/* ... */}</p></article>import { Divider } from "@primitiv-ui/react";
{/* Plain block flow — no container gap, so the rule reserves its own. */}<article> <p>{/* ... */}</p> <Divider style={{ marginBlock: "1rem" }} /> <p>{/* ... */}</p></article>Left to itself, a Divider announces as a separator. When the rule is purely visual — the surrounding structure already groups the content — pass aria-hidden="true" to drop it from the accessibility tree so a screen reader is not told about a line that carries no meaning. Keep the semantic form when the divider genuinely separates distinct groups, like sections of a menu.
import { Divider } from "@/components/ui/divider";
{/* Semantic: a real boundary between content groups. */}<Divider />
{/* Decorative: purely visual, hidden from assistive tech. */}<Divider aria-hidden="true" />import { Divider } from "@primitiv-ui/react";
{/* Semantic: a real boundary between content groups. */}<Divider />
{/* Decorative: purely visual, hidden from assistive tech. */}<Divider aria-hidden="true" />