Kompozycja
Jak łączą się komponenty prfct — części, prop render, atrybuty data do stylowania i zasady, dzięki którym własne modyfikacje da się utrzymać.
Komponenty prfct to małe części, które składa się w całość, a nie konfigurowalne monolity. Okno dialogowe to Dialog, DialogTrigger, DialogContent i DialogHeader — każda z tych części to cienkie, ostylowane opakowanie, które przeczytasz w minutę.
Części zamiast propsów
<Card>
<CardHeader>
<CardTitle>Team members</CardTitle>
<CardDescription>Invite people to collaborate.</CardDescription>
<CardAction>
<Button size="sm">Invite</Button>
</CardAction>
</CardHeader>
<CardContent>…</CardContent>
<CardFooter>…</CardFooter>
</Card>Dzięki częściom API pozostaje małe, a każdy element możesz przestawić, pominąć lub opakować — komponent nie musi dostawać nowego propa na każdą okoliczność.
Prop render
Komponenty Base UI renderują rozsądny element domyślny. Żeby wyrenderować coś innego — własny komponent albo link routera — przekaż to w render. Zachowanie, dostępność i style zostaną z nim scalone.
<DialogTrigger render={<Button variant="outline" />}>Edit profile</DialogTrigger>
<BreadcrumbLink render={<Link href="/projects" />}>Projects</BreadcrumbLink>asChild, a Base UI — render. Gdy prymityw przycisku renderuje element, który nie jest przyciskiem, ustaw nativeButton={false} — Base UI doda wtedy do niego role="button" i aktywację z klawiatury.Linki, które wyglądają jak przyciski
Nawigacja należy do linku, nawet jeśli wygląda on jak przycisk. Nie renderuj Button jako linku — Base UI oznaczyłby go jako przycisk. Zamiast tego nałóż buttonVariants na link:
import { buttonVariants } from "@/components/ui/button"
<Link href="/pricing" className={buttonVariants({ variant: "outline" })}>
See pricing
</Link>Stylowanie atrybutami data
Każda część ma atrybut data-slot, a części interaktywne udostępniają swój stan w atrybutach data (data-open, data-checked, data-disabled, data-highlighted…). Możesz się do nich odwołać w stylach rodzica, nie dotykając samego komponentu:
<Field className="*:data-[slot=field-description]:text-xs">…</Field>
<SelectItem className="data-highlighted:bg-brand-3">…</SelectItem>Dostosowywanie
Sięgaj po te sposoby w podanej kolejności:
- Warianty i rozmiary.
variant="outline",size="sm". - Układ przez
className. Szerokość, marginesy, wyrównanie — o układzie decyduje rodzic. - Nowy wariant. Jeśli potrzebujesz nowego wyglądu, dodaj go do definicji
cvakomponentu — wtedy jest wspólny, udokumentowany i spójny. - Edytuj kod źródłowy. To twój kod. Zachowaj tokeny, style fokusu i atrybuty
data-slot.
Łączenie klas
cn() łączy nazwy klas i rozwiązuje konflikty Tailwinda, więc className przekazany do komponentu w przewidywalny sposób nadpisuje jego ustawienia domyślne. cn() w prfct zna własne tokeny systemu — text-heading-md, shadow-floating, duration-fast — które ogólne narzędzie do łączenia klas źle by sklasyfikowało i po cichu odrzuciło.
import { cn } from "@/lib/utils"
cn("text-heading-md text-foreground", "text-muted-foreground")
// → "text-heading-md text-muted-foreground"