# Separator

> Divide related sections visually or semantically.

Source: https://www.honestui.com/docs/components/separator

```tsx
import { Separator } from "@/components/honest-ui/ui/separator"

export function SeparatorDemo() {
  return (
    <div className="max-w-72">
      <div className="space-y-1">
        <h4 className="text-sm font-medium">Honest UI</h4>
        <p className="text-sm text-muted-foreground">
          Unstyled, accessible primitives for fast product UI and design
          systems.
        </p>
      </div>
      <Separator className="my-4" />
      <div className="flex items-center gap-4 text-sm">
        <div>Blog</div>
        <Separator orientation="vertical" />
        <div>Docs</div>
        <Separator orientation="vertical" />
        <div>Source</div>
        <Separator orientation="vertical" />
        <div>Releases</div>
      </div>
    </div>
  )
}

```

## Overview [#overview]

Use Separator to mark a boundary between related regions: sections of a settings page, groups inside a toolbar or menu, stats in a row, entries in a timeline. The line says "these things belong together, but they are not the same thing" — it reinforces structure that spacing and headings have already established.

Separators work best sparingly. If a page needs a line between every pair of elements, the real problem is usually missing hierarchy, and no amount of rules will fix it. See [Don't do this](#dont-do-this).

## Anatomy [#anatomy]

A separator is a single 1 px line, horizontal by default. The Honest UI wrapper adds two props on top of Base UI: `size` controls how far the line extends (`small` for a fixed stub, `half` for half the container, `full` to span it), and `variant` picks an emphasis from the border tokens (`primary`, `secondary`, `tertiary`), so separators recede or advance with the surrounding content instead of fighting it.

## Usage guidance [#usage-guidance]

Reach for whitespace and headings first; add a separator only when the boundary genuinely improves scanning. Use a container border instead when the division belongs to an edge, such as a card's bottom edge. A vertical separator needs a flex row or another container with height to render against, because a bare vertical line has no intrinsic height.

Because emphasis is a choice, prefer `secondary` or `tertiary` variants for quiet divisions inside dense surfaces and reserve `primary` for major section breaks.

## Accessibility [#accessibility]

The component renders `<div role="separator">`, which assistive technology announces as a divider — it is semantic, not decorative. That makes it useful for marking real section boundaries in long forms and menus, where hearing "separator" helps people orient.

It renders as a plain `<div>` rather than `<hr>`, so it inherits theme colors and works anywhere without user-agent style resets. It never receives keyboard focus and has no interactive states.

If a separator is purely decorative — one visual device among several in a layout whose structure is already conveyed by headings — you can silence an individual instance with `role="presentation"` to reduce screen-reader noise. Make that call per instance; the default keeps the semantics.

There is no loading, disabled, or error state — a separator has none by nature, and the component honestly offers nothing more. Colors come from border theme tokens, so every variant adapts to dark mode automatically, and orientation uses logical properties, so lines mirror correctly in right-to-left layouts.

## Installation [#installation]


  

  
    <CliBlock commands="[&#x22;separator&#x22;]" />
  

  
    
      
        Install the following dependencies:
      

      ```bash
      npm install @base-ui-components/react
      ```

      
        Copy and paste the following code into your project.
      

      ### components/ui/separator.tsx

```tsx
import { Separator as SeparatorPrimitive } from "@base-ui-components/react/separator"

import { cn } from "@/lib/utils"

function Separator({
  className,
  orientation = "horizontal",
  size = "full",
  variant = "primary",
  ...props
}: SeparatorPrimitive.Props & {
  size?: "small" | "half" | "full"
  variant?: "primary" | "secondary" | "tertiary"
}) {
  return (
    <SeparatorPrimitive
      data-slot="separator"
      data-size={size}
      data-variant={variant}
      orientation={orientation}
      className={cn(
        "m-0 shrink-0 cursor-default border-0",
        variant === "primary" &&
          "bg-[var(--hui-color-border-base-primary)]",
        variant === "secondary" &&
          "bg-[var(--hui-color-border-base-secondary)]",
        variant === "tertiary" &&
          "bg-[var(--hui-color-border-base-tertiary)]",
        size === "small" &&
          "data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-[var(--hui-space-6)] data-[orientation=vertical]:h-[var(--hui-space-6)] data-[orientation=vertical]:w-px",
        size === "half" &&
          "data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-1/2 data-[orientation=vertical]:h-1/2 data-[orientation=vertical]:w-px",
        size === "full" &&
          "data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px",
        className
      )}
      {...props}
    />
  )
}

export { Separator }

```

      
        Update the import paths to match your project setup.
      
    
  


## Usage [#usage]

```tsx
import { Separator } from "@/components/ui/separator";
```

```tsx
<Separator />
```

Set `orientation="vertical"` inside a flex row, and reach for `size` when a full-width rule feels heavier than the division deserves.

## Don't do this [#dont-do-this]

### Separator as spacing [#separator-as-spacing]

```tsx
// Bad
<div>
  <p>First paragraph</p>
  <Separator className="my-4" />
  <p>Second paragraph</p>
  <Separator className="my-4" />
</div>
```

```tsx
// Good
<div className="space-y-4">
  <p>First paragraph</p>
  <p>Second paragraph</p>
</div>
```

Rules between everything add visual noise without adding meaning: screen readers now hear "separator" between paragraphs that were never separate sections, and sighted users scan lines instead of content. Margin and padding group through emptiness; save separators for boundaries that carry structure.

### Vertical separator without height [#vertical-separator-without-height]

```tsx
// Bad
<div>
  <span>12 files</span>
  <Separator orientation="vertical" />
  <span>4.8 MB</span>
</div>
```

```tsx
// Good
<div className="flex items-center gap-4">
  <span>12 files</span>
  <Separator orientation="vertical" />
  <span>4.8 MB</span>
</div>
```

A vertical line is 1 px wide and zero pixels tall until something stretches it, so outside a flex container it silently disappears — the division vanishes exactly where people expected it. Give the parent a flex context (and items-center alignment) so the line spans the row.

## Examples [#examples]

### Section label [#section-label]

A heading, a rule, then supporting text: the quiet way to open a settings block.

```tsx
import { Separator } from "@/components/honest-ui/ui/separator"

export function SeparatorSectionLabel() {
  return (
    <div className="w-full max-w-sm space-y-3">
      <div className="text-sm font-medium">Account</div>
      <Separator />
      <p className="text-sm text-muted-foreground">Profile, security, and billing settings.</p>
    </div>
  )
}

```

### Vertical stack [#vertical-stack]

Stats in a row separated by vertical rules, each with its own breathing room.

```tsx
import { Separator } from "@/components/honest-ui/ui/separator"

export function SeparatorVerticalStack() {
  return (
    <div className="flex h-24 items-center rounded-xl border p-4 text-sm">
      <span>12 files</span>
      <Separator orientation="vertical" className="mx-4" />
      <span>4.8 MB</span>
      <Separator orientation="vertical" className="mx-4" />
      <span>Synced</span>
    </div>
  )
}

```

### Timeline [#timeline]

Stages of a process where vertical rules mark progression without implying navigation.

```tsx
import { Separator } from "@/components/honest-ui/ui/separator"

export function SeparatorTimeline() {
  return (
    <div className="flex h-24 items-center gap-4 text-sm">
      <div>Draft</div>
      <Separator orientation="vertical" />
      <div>Review</div>
      <Separator orientation="vertical" />
      <div>Publish</div>
    </div>
  )
}

```

## API reference [#api-reference]

`Separator` forwards Base UI Separator props (`orientation`, plus native `<div>` props) and adds:

| Prop          | Values                                   | Default        |
| ------------- | ---------------------------------------- | -------------- |
| `orientation` | `"horizontal"`, `"vertical"`             | `"horizontal"` |
| `size`        | `"small"`, `"half"`, `"full"`            | `"full"`       |
| `variant`     | `"primary"`, `"secondary"`, `"tertiary"` | `"primary"`    |

The component renders a `<div role="separator">` with `data-size` and `data-variant` attributes for targeted styling. Decorative instances can opt out of the accessibility tree individually by overriding `role`. Use a heading or landmark instead when the division itself needs a semantic name.

See the [Base UI Separator API](https://base-ui.com/react/components/separator#api-reference).
