defuss-shadcn / Primitives / separator
SeparatorATM
Visually or semantically separates content. Built on the native <hr> element with support for vertical orientation and labeled separators. No JavaScript required.
On this page (15)
§With text
Text inside the separator sits on the line - the lines draw themselves left and right of it. Meaningful text keeps role="separator" off, so screen readers read it.
§Side by side
data-orientation="vertical" in a flex row: the text sits on a vertical line between the two blocks (DaisyUI calls this divider-horizontal - it divides horizontally placed items).
§Responsive
data-orientation-lg="vertical": stacked with a horizontal line on small screens, side by side with a vertical one from 64rem - the parent switches to a row at the same width. Try the device sizes in the toolbar.
§Colors
data-variant colors the line (the text stays muted): neutral, primary, secondary, accent, info, success, warning and destructive (alias error). Secondary and accent take the theme's chart colors - its --secondary / --accent are pale surfaces; success, warning and info are fixed colors.
§Text position
data-align="start" or "end" moves the text to the start or end of the line (default: centered).
§Sizes
data-size sets the thickness: sm 1px (the default), md 2px, lg 4px, xl 8px - with or without text.
§Gaps
data-gap sets the space between the text and the lines: none, sm, md (the default), lg, xl. For space around a separator, use the margin utilities (my-4, my-8 …).
§With Label
The older wrapper form - two separators around a span - still works; text inside the separator itself (above) is simpler.
Vertical separators between menu items with descriptions.
§Decorative
Ornamental section breaks in running text - a text separator with a glyph (✦ ✦ ✦, ❦) and aria-hidden, so assistive technology never reads the ornament, or a bare glyph without its lines (data-line='none': ⁂) - and a short accent rule closing the chapter, an <hr> with role='none' (no separator semantics).
§CSS view file
/* -- Separator component ---------------------------------------- */@layer components { /* One element, three looks: - empty: a plain line (1px, --border) - horizontal, or vertical with data-orientation="vertical" (inside a flex row) - with text inside: the text sits ON the line - two pseudo-element lines left and right of it (above and below when vertical) Knobs: data-variant (line color), data-size (thickness), data-gap (space between text and lines), data-align="start|end" (text position), data-orientation-md / -lg="vertical" (switch to a vertical line from 48 / 64rem). --_line / --_thick / --_gap are private. */ .separator { --_line: var(--border); --_thick: 1px; --_gap: 0.75rem; border: none; margin: 0; flex-shrink: 0; background: var(--_line); /* Horizontal (default) */ height: var(--_thick); width: 100%; /* Vertical */ &[data-orientation="vertical"] { height: auto; width: var(--_thick); align-self: stretch; } /* Decorative - hidden from assistive technology */ &[aria-hidden="true"], &[role="none"] { /* No visual change - purely semantic */ } /* -- Text on the line ------------------------------------ */ &:not(:empty) { display: flex; align-items: center; gap: var(--_gap); height: auto; background: none; font-size: 0.75rem; font-weight: 500; line-height: 1.25rem; letter-spacing: 0.02em; color: var(--muted-foreground); white-space: nowrap; &::before, &::after { content: ''; flex: 1 1 0; height: var(--_thick); background: var(--_line); } /* text position along the line */ &[data-align="start"]::before { display: none; } &[data-align="end"]::after { display: none; } /* a bare glyph - an asterism, a dinkus, a fleuron - without the lines. VERIFIED: (separator.e2e "data-line=none") no pseudo lines, centred */ &[data-line="none"] { justify-content: center; &::before, &::after { display: none; } } &[data-orientation="vertical"] { flex-direction: column; width: auto; align-self: stretch; &::before, &::after { width: var(--_thick); height: auto; min-height: 0.5rem; } } } /* -- Colors (the line; the text stays muted) -------------- */ &[data-variant="neutral"] { --_line: var(--foreground); } &[data-variant="primary"] { --_line: var(--primary); } /* the tweakcn --secondary / --accent are pale surfaces, too faint for a line: the theme's vivid chart colors instead (like the status dot) */ &[data-variant="secondary"] { --_line: var(--chart-2); } &[data-variant="accent"] { --_line: var(--chart-4); } &[data-variant="destructive"], &[data-variant="error"] { --_line: var(--destructive); } /* success / warning / info: literals - the token set has no such pairs */ &[data-variant="success"] { --_line: #16a34a; } &[data-variant="warning"] { --_line: #f59e0b; } &[data-variant="info"] { --_line: #0ea5e9; } /* -- Thickness -------------------------------------------- */ &[data-size="sm"] { --_thick: 1px; } &[data-size="md"] { --_thick: 2px; } &[data-size="lg"] { --_thick: 4px; } &[data-size="xl"] { --_thick: 8px; } /* -- Gap between the text and the lines ------------------- */ &[data-gap="none"] { --_gap: 0; } &[data-gap="sm"] { --_gap: 0.375rem; } &[data-gap="md"] { --_gap: 0.75rem; } &[data-gap="lg"] { --_gap: 1.5rem; } &[data-gap="xl"] { --_gap: 2.5rem; } /* -- Responsive: a vertical line from a breakpoint up (DaisyUI's lg:divider-horizontal). The PARENT must turn into a row at the same width - the separator only follows it. */ @media (min-width: 48rem) { &[data-orientation-md="vertical"] { height: auto; width: var(--_thick); align-self: stretch; &:not(:empty) { flex-direction: column; width: auto; &::before, &::after { width: var(--_thick); height: auto; min-height: 0.5rem; } } } } @media (min-width: 64rem) { &[data-orientation-lg="vertical"] { height: auto; width: var(--_thick); align-self: stretch; &:not(:empty) { flex-direction: column; width: auto; &::before, &::after { width: var(--_thick); height: auto; min-height: 0.5rem; } } } } } /* -- Labeled separator (the older wrapper form) -------------- Still supported; text inside .separator itself is the simpler form. */ .separator-label { display: flex; align-items: center; gap: 0.75rem; & .separator { flex: 1; } & span { font-size: 0.75rem; font-weight: 500; color: var(--muted-foreground); text-transform: uppercase; letter-spacing: 0.05em; white-space: nowrap; flex-shrink: 0; } } /* -- Accessibility ----------------------------------------- */ @media (forced-colors: active) { /* system colors would erase the line (a background) - keep it */ .separator { forced-color-adjust: none; --_line: CanvasText; color: CanvasText; } } @media (prefers-contrast: more) { .separator:not([data-variant]) { --_line: var(--foreground); } .separator:not([data-size]) { --_thick: 2px; } }}Comments, ideas or improvements? Edit this page's source on GitHub