Motywy
Nadaj prfct kolory swojej marki, zabarwienie szarości, zaokrąglenie albo tryb, globalnie lub dla jednego poddrzewa, bez dotykania komponentów.
Każdy komponent prfct odczytuje kolory, zaokrąglenia i cienie ze zmiennych CSS. Dostosowanie motywu sprowadza się do zmiany tych wartości — komponentów nigdy nie trzeba edytować. Wypróbuj to na żywo w kreatorze motywów.
Te same komponenty, te same klasy — o trybie decyduje poddrzewo.
Te same komponenty, te same klasy — o trybie decyduje poddrzewo.
import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
import { Switch } from "@/components/ui/switch"
function Panel({ mode, label }: { mode: "light" | "dark"; label: string }) {
return (
<div
className={`${mode} flex flex-col gap-4 rounded-xl border bg-background p-5 text-foreground`}
>
<div className="flex items-center justify-between">
<span className="text-sm font-semibold">{label}</span>
<Badge variant="brand">Lokalny</Badge>
</div>
<p className="text-sm text-muted-foreground">
Te same komponenty, te same klasy — o trybie decyduje poddrzewo.
</p>
<div className="flex items-center justify-between">
<Switch defaultChecked aria-label={`Powiadomienia, ${label}`} />
<Button size="sm">Dalej</Button>
</div>
</div>
)
}
export default function ScopedTheme() {
return (
<div className="grid w-full max-w-2xl gap-3 sm:grid-cols-2">
<Panel mode="light" label="Jasny" />
<Panel mode="dark" label="Ciemny" />
</div>
)
}Tryb jasny i ciemny
prfct ma oba tryby. Domyślna konfiguracja używa next-themes, żeby podążać za ustawieniem systemu operacyjnego, zapamiętywać wybór i nie dopuścić do mignięcia niewłaściwego motywu:
import { ThemeProvider } from "@/components/theme-provider"
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en" suppressHydrationWarning>
<body>
<ThemeProvider>{children}</ThemeProvider>
</body>
</html>
)
}ThemeProvider przekazuje swoje propsy do next-themes i dodaje jeden własny: hotkey, pojedynczy klawisz przełączający tryb jasny i ciemny, na przykład hotkey="d". Domyślnie jest wyłączony, bo skrót z jednego klawisza musi być czymś, na co ludzie sami się decydują (WCAG 2.1.4).
Motywy lokalne
Tryby są zdefiniowane na klasach, a nie tylko na elemencie głównym, więc przełączyć się może dowolne poddrzewo:
<aside className="dark">…</aside> {/* a dark panel on a light page */}
<figure className="light">…</figure> {/* a light preview on a dark page */}Tak dokumentacja prfct pokazuje jasne i ciemne próbki obok siebie. Działa to, bo komponenty wyrażają każdą różnicę między trybami przez zmienne — żaden z nich nie używa klas dark:.
Kolory marki
prfct jest czarno-biały. Oba kolory marki są monochromatyczne, więc zaznaczone kontrolki, postęp, pierścień fokusu i linki są czarne, a w trybie ciemnym białe. Kolor pojawia się tylko tam, gdzie coś znaczy: przy statusach, w danych i tam, gdzie wprowadzi go twoja marka. Motyw daje systemowi do dwóch kolorów marki.
export const themeConfig: ThemeConfig = {
gray: neutralPresets.neutral,
brand: huePresets.blue, // or { hue: 150, chroma: 0.15, lightness: 0.55 }
brandSecondary: "mono",
}W twoim projekcie robi to kreator motywów w przeglądarce: przyjmuje wartości hex twojej marki i daje gotowy CSS do wklejenia. Odczytuje też kolor marki z adresu: /themes?brand=violet otwiera go z gotową paletą, a /themes?hue=150 z odcieniem podanym w stopniach. W repozytorium prfct pnpm tokens przebudowuje styles/tokens.css tym samym kodem.
Główny kolor marki
Kolor marki powstaje z trzech liczb: odcienia, nasycenia i jasności stopnia wypełnienia, czyli stopnia 9. Trzy opcjonalne pozwalają go dostroić: hueShift przesuwa odcień wzdłuż skali, tintBoost dodaje nasycenia stopniom od 3 do 8, a darkLightness ustawia inne wypełnienie w trybie ciemnym. Wszystkie 12 stopni jest generowanych na nowo dla obu trybów, a kontrast stopni tekstu wyliczany od początku. Główny kolor marki barwi wszystko, co pokazuje zaznaczenie lub fokus: zaznaczone kontrolki, suwaki, postęp, pierścień fokusu, linki i zaznaczony tekst (brand, ring, link, selection). Jest też pierwszą serią wykresów, chart-1.
Stopień wypełnienia jest wyliczany pod tekst, który na nim leży, a nie względem strony. Jasny kolor marki, o jasności wypełnienia powyżej około 0,65, taki jak gotowa paleta amber, wypełnia zaznaczone kontrolki z kontrastem poniżej 3:1 na bieli; stan nadal przekazują znaczek zaznaczenia i uchwyt. Z pierścieniem fokusu jest inaczej, bo nie ma on się na czym oprzeć: ring wskazuje na brand-focus, czyli wypełnienie, gdy odróżnia się ono od każdej powierzchni w stosunku 3:1, a w przeciwnym razie stopień tekstu marki, osobno w każdym trybie.
Drugi kolor marki
Drugi kolor marki, brand-secondary ze stopniami od brand-secondary-1 do brand-secondary-12, nie jest używany przez żaden komponent samodzielnie. To ty decydujesz, gdzie się pojawi: w odznace planu, w wyróżnieniu na wykresie, w ilustracji. Zachowaj go do akcentów; dwa kolory walczące o uwagę znoszą się nawzajem.
<Badge variant="brand-secondary">Pro</Badge>
<p className="text-brand-secondary-11">Included in your plan</p>Główne przyciski w kolorze marki
Główne przyciski są domyślnie czarne, więc jedynym kolorowym elementem na stronie jest ten, który coś znaczy. Jeśli twoja marka wymaga kolorowych przycisków, przypisz do niej primary. Kreator motywów zapisze to za ciebie, gdy włączysz Główne przyciski w kolorze marki.
:root,
.light,
.dark {
--primary: var(--brand-9);
--primary-foreground: var(--brand-contrast);
}Zabarwienie szarości
Skala szarości może nieść subtelny odcień. prfct ma siedem gotowych palet:
Zaokrąglenie
:root {
--radius: 0.5rem;
}Każdy stopień zaokrąglenia jest wyliczany z --radius, więc 0 daje ostry, techniczny interfejs, a 0.75rem miękki i przyjazny. Zobacz Kształt.
Nadpisywanie tokenów semantycznych
Przy jednorazowych wymaganiach nadpisuj tokeny semantyczne po arkuszu stylów prfct. Przypisuj je do stopnia skali, a nie do surowego koloru, żeby tryb ciemny dalej działał. Na przykład klasyczne niebieskie linki w poza tym monochromatycznym interfejsie:
:root,
.light,
.dark {
--link: var(--blue-11);
}