Separator
Cienka linia, która dzieli treść na grupy — poziomo między sekcjami, pionowo między elementami w jednym wierszu.
prfct
Design system dla Next.js, zbudowany na shadcn.
import { Separator } from "@/components/ui/separator"
export default function SeparatorDemo() {
return (
<div className="w-full max-w-80">
<div className="flex flex-col gap-1">
<p className="text-sm font-semibold text-foreground">prfct</p>
<p className="text-sm text-muted-foreground">
Design system dla Next.js, zbudowany na shadcn.
</p>
</div>
<Separator className="my-4" />
<div className="flex h-5 items-center gap-4 text-sm text-muted-foreground">
<span>Dokumentacja</span>
<Separator orientation="vertical" />
<span>Komponenty</span>
<Separator orientation="vertical" />
<span>Motywy</span>
</div>
</div>
)
}Instalacja
$ pnpm dlx shadcn@latest add https://www.prfct.dev/r/separator.jsonUżycie
import { Separator } from "@/components/ui/separator"<Separator />
<Separator orientation="vertical" />Separator to linia o grubości 1 px w kolorze tokenu border. Separatory poziome wypełniają szerokość kontenera, a pionowe rozciągają się na wysokość swojego wiersza flex — nadaj więc wierszowi wysokość (h-5), a separatory się do niej dopasują.
Przykłady
Grupy w pasku narzędzi
Pionowe separatory dzielą powiązane kontrolki na grupy bez otaczania ich ramkami. Gdy separator ma być niższy niż jego wiersz, ustaw mu wysokość i wyrównaj go klasą data-vertical:self-center — wariant jest potrzebny, żeby nadpisać domyślne rozciąganie.
import {
AlignCenterIcon,
AlignLeftIcon,
AlignRightIcon,
BoldIcon,
ItalicIcon,
LinkIcon,
UnderlineIcon,
} from "lucide-react"
import { Button } from "@/components/ui/button"
import { Separator } from "@/components/ui/separator"
const groups = [
[
{ label: "Pogrubienie", icon: BoldIcon },
{ label: "Kursywa", icon: ItalicIcon },
{ label: "Podkreślenie", icon: UnderlineIcon },
],
[
{ label: "Wyrównaj do lewej", icon: AlignLeftIcon },
{ label: "Wyśrodkuj", icon: AlignCenterIcon },
{ label: "Wyrównaj do prawej", icon: AlignRightIcon },
],
[{ label: "Wstaw link", icon: LinkIcon }],
]
export default function SeparatorToolbar() {
return (
<div
role="group"
aria-label="Formatowanie tekstu"
className="flex h-11 items-center gap-1 rounded-xl border bg-card px-1.5 shadow-raised"
>
{groups.map((group, index) => (
<div key={index} className="flex items-center gap-1">
{index > 0 && (
<Separator
orientation="vertical"
className="mx-1 h-5 data-vertical:self-center"
/>
)}
{group.map(({ label, icon: Icon }) => (
<Button
key={label}
variant="ghost"
size="icon-sm"
aria-label={label}
>
<Icon />
</Button>
))}
</div>
))}
</div>
)
}Listy
Między wierszami listy albo panelu ustawień separatory pełnią rolę obramowań, nie dublując przy tym krawędzi kontenera.
import { Fragment } from "react"
import { Separator } from "@/components/ui/separator"
import { Switch } from "@/components/ui/switch"
const settings = [
{
id: "mentions",
label: "Wzmianki",
description: "Gdy ktoś cię oznaczy przez @.",
},
{
id: "replies",
label: "Odpowiedzi",
description: "Odpowiedzi w obserwowanych wątkach.",
},
{
id: "digest",
label: "Cotygodniowe podsumowanie",
description: "Podsumowanie w każdy poniedziałek.",
},
]
export default function SeparatorList() {
return (
<div className="w-full max-w-sm rounded-xl border bg-card shadow-raised">
{settings.map((setting, index) => (
<Fragment key={setting.id}>
{index > 0 && <Separator />}
<div className="flex items-center justify-between gap-6 px-4 py-3.5">
<label htmlFor={setting.id} className="flex flex-col gap-0.5">
<span className="text-sm font-medium text-foreground">
{setting.label}
</span>
<span className="text-body-xs text-muted-foreground">
{setting.description}
</span>
</label>
<Switch id={setting.id} defaultChecked={index !== 2} />
</div>
</Fragment>
))}
</div>
)
}Z etykietą
Aby wstawić lub między alternatywami, użyj FieldSeparator. Składa się z dwóch separatorów wokół etykiety i nie potrzebuje tła, więc dobrze wygląda na każdej powierzchni.
import { Button } from "@/components/ui/button"
import {
Field,
FieldGroup,
FieldLabel,
FieldSeparator,
} from "@/components/ui/field"
import { Input } from "@/components/ui/input"
export default function SeparatorWithLabel() {
return (
<FieldGroup className="w-full max-w-72">
<Button variant="outline" className="w-full">
Kontynuuj z GitHubem
</Button>
<FieldSeparator>lub</FieldSeparator>
<Field>
<FieldLabel htmlFor="separator-email">Służbowy adres e-mail</FieldLabel>
<Input
id="separator-email"
type="email"
placeholder="you@company.com"
/>
</Field>
<Button className="w-full">Kontynuuj z adresem e-mail</Button>
</FieldGroup>
)
}Dekoracyjny
Separatory są domyślnie semantyczne. Gdy separator nadaje jedynie rytm — na przykład między metadanymi w jednym wierszu — oznacz go jako decorative, żeby czytniki ekranu go nie odczytywały.
Projektowanie, w którym nie ma już czego odjąć
import { Avatar, AvatarFallback } from "@/components/ui/avatar"
import { Separator } from "@/components/ui/separator"
export default function SeparatorDecorative() {
return (
<article className="flex w-full max-w-md flex-col gap-3">
<h3 className="text-heading-sm text-foreground">
Projektowanie, w którym nie ma już czego odjąć
</h3>
<div className="flex h-5 items-center gap-3 text-body-xs text-muted-foreground">
<span className="flex items-center gap-2">
<Avatar size="xs">
<AvatarFallback>AK</AvatarFallback>
</Avatar>
Ana Kowalska
</span>
{/* Purely visual dividers: hidden from assistive technology. */}
<Separator
orientation="vertical"
decorative
className="h-3.5 data-vertical:self-center"
/>
<time dateTime="2026-09-18">18 września 2026</time>
<Separator
orientation="vertical"
decorative
className="h-3.5 data-vertical:self-center"
/>
<span>6 min czytania</span>
</div>
</article>
)
}<Separator orientation="vertical" decorative />Wytyczne
Kiedy używać
- Do podziału powierzchni na grupy, których związek nie wynika już z odstępów ani nagłówków.
- Między grupami kontrolek w pasku narzędzi, sekcjami menu i wierszami listy.
- Między metadanymi w jednym wierszu, gdzie przecinki lub punktory wprowadzałyby szum.
Kiedy nie używać
- Tam, gdzie grupy rozdzieliłaby sama pusta przestrzeń. Odstęp to cichsze narzędzie — sięgaj po niego w pierwszej kolejności.
- Jako krawędź powierzchni — karty, okna dialogowe i tabele same rysują swoje obramowania.
- Do oddzielania sekcji strony, które mają nagłówki — to nagłówek jest separatorem.
Najpierw odstęp, potem linia
Układy prfct czerpią strukturę ze skali odstępów. Dodaj separator tylko wtedy, gdy grupowanie samym odstępem wymagałoby go tak dużo, że układ by się rozsypał, albo gdy elementy leżą zbyt gęsto, by rozdzielić je w inny sposób.
Trzymaj się tokenu border
Separatory używają bg-border — subtelnego koloru strukturalnego. Nie przyciemniaj ich, żeby coś wyróżnić — jeśli podział ma być mocniejszy, prawdopodobnie potrzebuje raczej nagłówka albo większego odstępu.
Dostępność
Separator w prfct renderuje <div role="separator"> z aria-orientation, dzięki czemu technologie wspomagające mogą zasygnalizować granicę między grupami. Nie przyjmuje fokusu i nie obsługuje klawiatury.
- Semantyczny czy dekoracyjny. Zostaw domyślną rolę, gdy separator wyznacza rzeczywistą granicę między grupami treści. Użyj
decorative, gdy jest czysto wizualny: renderuje wtedyrole="none"i pomijaaria-orientation, którego ta rola nie może mieć. - Kontrast elementów nietekstowych. Token
borderjest celowo subtelny i nie musi spełniać progu 3:1 — separator nigdy sam nie przekazuje informacji. Nie traktuj go jako jedynego wskaźnika zmiany stanu.
Dokumentacja API
Separator
Renderuje <div>. Przyjmuje wszystkie propsy komponentu Separator z Base UI.