Divider

A rule between content groups.

Primitives Divider.jsx Divider.d.ts Divider.md

Playground

Change a prop and watch it. The code below follows along.

Install and import

Divider is in @dovetail-ds/react. Install it with React, if you haven't:

npm install @dovetail-ds/react react react-dom
import { Divider } from "@dovetail-ds/react";

Import @dovetail-ds/react/styles.css once at your app's root, then your theme after it. Setup covers the stylesheets, fonts and dark mode.

Guidelines

A rule between content groups.

Use it when

  • Separating sections inside a card or menu where whitespace alone is ambiguous.
  • Splitting alternative paths, with label="or".

Don't use it when

  • Space would do the job. Reach for Stack with a larger gap first; a divider is visual debt.
  • Between every row of a list. Use one border on the container instead.

Example

<Divider />
<Divider label="or" />
<Divider orientation="vertical" />

Accessibility

Renders role="separator", with aria-orientation on the vertical variant.

Tokens

--dt-border-subtle by default; --dt-border-default and --dt-border-strong via tone.

Props

The typed contract, from Divider.d.ts.

import * as React from "react";

/** Rule between content groups. Optional centred label. */
export interface DividerProps extends React.HTMLAttributes<HTMLDivElement> {
  /** @default "horizontal" */
  orientation?: "horizontal" | "vertical";
  /** Centred label, horizontal only, e.g. "or" */
  label?: string;
  /** @default "subtle" */
  tone?: "subtle" | "default" | "strong";
}

export declare function Divider(props: DividerProps): React.JSX.Element;

Tokens it reads

Every custom property Divider.jsx resolves, read from the source: 9 semantic. Component tier first, because that is the one to reach for.

  • semantic Shared roles. Override one and everything using that role moves with it.
TokenTierDeclared as
--dt-border-defaultsemanticvar(--dt-color-neutral-200)
--dt-border-strongsemanticvar(--dt-color-neutral-400)
--dt-border-subtlesemanticvar(--dt-color-neutral-100)
--dt-border-width-defaultsemanticvar(--dt-dim-hair)
--dt-space-inline-smsemanticvar(--dt-dim-3)
--dt-text-label-sm-familysemanticvar(--dt-font-family-secondary)
--dt-text-label-sm-sizesemanticvar(--dt-font-size-xs)
--dt-text-label-sm-weightsemanticvar(--dt-font-weight-medium)
--dt-text-tertiarysemanticvar(--dt-color-neutral-500)

Source

React only, no dependencies, every value a token.

import React from "react";

export function Divider({ orientation = "horizontal", label, tone = "subtle", style, ...rest }) {
  const color = tone === "strong" ? "var(--dt-border-strong)" : tone === "default" ? "var(--dt-border-default)" : "var(--dt-border-subtle)";
  if (orientation === "vertical") {
    return <div role="separator" aria-orientation="vertical" style={{ width: "var(--dt-border-width-default)", alignSelf: "stretch", background: color, ...style }} {...rest} />;
  }
  if (label) {
    return (
      <div role="separator" style={{ display: "flex", alignItems: "center", gap: "var(--dt-space-inline-sm)", ...style }} {...rest}>
        <span style={{ height: "var(--dt-border-width-default)", background: color, flex: 1 }} />
        <span style={{ fontFamily: "var(--dt-text-label-sm-family)", fontSize: "var(--dt-text-label-sm-size)", fontWeight: "var(--dt-text-label-sm-weight)", color: "var(--dt-text-tertiary)" }}>{label}</span>
        <span style={{ height: "var(--dt-border-width-default)", background: color, flex: 1 }} />
      </div>
    );
  }
  return <div role="separator" style={{ height: "var(--dt-border-width-default)", background: color, width: "100%", ...style }} {...rest} />;
}

In context

Divider also appears on the primitives reference cards, alongside the rest of its family.