Separator
A 1px hairline in the border colour that splits groups inside a menu, a toolbar or a rail. It never carries meaning on its own.
Playground
Change the controls to try each prop. The code under the preview updates as you go and lists only the props you changed; copy it into your page.
import { Separator } from '@/ui/separator';<Separator />Horizontal
Between groups of menu items, and above a destructive item. It takes the width of its parent.
import { Separator } from '@/ui/separator';
export default function SeparatorHorizontal() {
return (
<div className="flex w-56 flex-col rounded-large bg-surface p-050 text-body font-medium text-text shadow-control">
<div className="px-100 py-050">Open record</div>
<div className="px-100 py-050">Copy link</div>
<Separator className="my-050" />
<div className="px-100 py-050 text-danger">Delete</div>
</div>
);
}Vertical
Inset
Between toolbar groups. inset makes it 20px tall, centred on the 28px controls, instead of the full height of the bar.
import { FunnelSimpleIcon } from '@phosphor-icons/react';
import { Button } from '@/ui/button';
import { Separator } from '@/ui/separator';
export default function SeparatorVertical() {
return (
<div className="flex h-11 items-center gap-100 rounded-large bg-surface px-100 shadow-control">
<Button variant="ghost">
<FunnelSimpleIcon />
Filter
</Button>
<Button variant="ghost">Sort</Button>
<Separator orientation="vertical" inset />
<Button variant="ghost">Display</Button>
</div>
);
}Full height
Without inset, a vertical separator takes the height of its parent, here two stacked figures.
import { Separator } from '@/ui/separator';
export default function SeparatorFullHeight() {
return (
<div className="flex h-16 items-center gap-200 text-body text-text">
<div className="flex flex-col">
<span className="text-body-small font-medium text-text-subtle">Open jobs</span>
<span className="font-semibold">12</span>
</div>
<Separator orientation="vertical" />
<div className="flex flex-col">
<span className="text-body-small font-medium text-text-subtle">CVs sent this week</span>
<span className="font-semibold">34</span>
</div>
</div>
);
}In a rail
Between sections of the details rail, at the full width of the section.
- Company
- Halcyon Bank
- Stage
- CV sent
- Owner
- Maya Chen
import { Separator } from '@/ui/separator';
const sections = [
['Company', 'Halcyon Bank'],
['Stage', 'CV sent'],
['Owner', 'Maya Chen'],
];
export default function SeparatorRail() {
return (
<div className="flex w-72 flex-col gap-150 rounded-xlarge bg-surface px-200 py-150 shadow-control">
{sections.map(([label, value], i) => (
<div key={label} className="flex flex-col gap-150">
{i > 0 && <Separator />}
<dl className="flex flex-col gap-025">
<dt className="text-body-small font-medium text-text-subtle">{label}</dt>
<dd className="text-body text-text">{value}</dd>
</dl>
</div>
))}
</div>
);
}Needs you list
The list on Home of what is waiting on you today, and the sections of the morning brief. Every row is one thing, with the one action that clears it.
Task row and task form
A Task is a row: what to do, who it is about and when it is due, with one way to complete it. A new Task is a draft row in the Tasks table, never a dialog.