Elewacja
Cztery poziomy głębi. Powierzchnie na stronie rysuje ich obramowanie; cień rzuca tylko to, co unosi się nad stroną. Głębia pokazuje, co do czego należy i co jest tymczasowe.
Elewacja mówi, jak elementy mają się do siebie. Treść leży na stronie; menu unoszą się nad elementem, który je otworzył; okna dialogowe przerywają wszystko. prfct ma cztery poziomy, a komponenty wybierają jeden z nich według swojej roli.
0. Płaski
Treść strony, elementy w tekście.
1. Wyniesiony
Karty, panele, kontrolki. Obramowanie 1 px, nigdy obramowanie razem z cieniem.
2. Pływający
Menu, popovery, podpowiedzi, listy wyboru.
3. Modalny
Okna dialogowe, panele, paleta poleceń.
Wyniesiony · karta
Obramowanie 1 px, bez cienia.
Pływający · menu
Uniesiony nad treścią, do której należy.
Modalny · okno dialogowe
Ponad wszystkim; strona czeka.
import { Button } from "@/components/ui/button"
export default function ElevationStack() {
return (
// Wide containers overlap the layers in place; narrow ones cascade them
// down the page, each one still overlapping the last.
<div className="@container w-full max-w-xl">
<div className="relative flex flex-col @md:block @md:h-72">
<div className="rounded-xl border bg-card p-5 pb-10 shadow-raised @md:absolute @md:inset-x-0 @md:top-0 @md:h-56">
<p className="text-heading-sm">Wyniesiony · karta</p>
<p className="text-sm text-muted-foreground">
Obramowanie 1 px, bez cienia.
</p>
</div>
<div className="-mt-6 ml-4 w-56 max-w-[calc(100%-1rem)] rounded-xl bg-popover p-4 shadow-floating ring-1 ring-edge @md:absolute @md:top-20 @md:left-10 @md:mt-0 @md:ml-0">
<p className="text-sm font-semibold">Pływający · menu</p>
<p className="text-xs text-muted-foreground">
Uniesiony nad treścią, do której należy.
</p>
</div>
<div className="-mt-4 ml-auto w-64 max-w-[calc(100%-2rem)] rounded-2xl bg-popover p-5 shadow-modal ring-1 ring-edge @md:absolute @md:top-32 @md:right-4 @md:mt-0">
<p className="text-sm font-semibold">Modalny · okno dialogowe</p>
<p className="mb-3 text-xs text-muted-foreground">
Ponad wszystkim; strona czeka.
</p>
<div className="flex justify-end">
<Button size="xs">Potwierdź</Button>
</div>
</div>
</div>
</div>
)
}Poziomy
Powierzchnie wyniesione rysuje samo obramowanie 1 px: krawędź albo cień, nigdy jedno i drugie. shadow-raised nie daje żadnego cienia. Pozostaje tokenem na kartach, elementach z obramowaniem i pływającym pasku bocznym, żeby motyw mógł nadać im cień w jednym miejscu, ustawiając --prfct-shadow-raised; pola i przyciski z obramowaniem go nie odczytują.
Powierzchnie pływające i modalne mają cień i obwódkę z linii włosowej ring-edge: półprzezroczysty obrys, który wyznacza krawędź na każdym tle, tam, gdzie sam cień mógłby zniknąć.
Cienie
Oba cienie używane przez komponenty, pływający i modalny, składają się z trzech warstw, od ostrego cienia kontaktowego po miękki cień rozproszony; najmniejsze stopnie skali poniżej mają jedną lub dwie. W trybie jasnym cienie przyjmują odcień skali neutralnej, więc zabarwiona szarość ustawiona w lib/tokens/palette.ts rzuca pasujący cień. Przy domyślnej skali neutralnej są po prostu ciemnoszare, a w trybie ciemnym czarne.
Tryb ciemny
Na ciemnym tle cienie są prawie niewidoczne, więc w trybie ciemnym elewację wyrażają jaśniejsze powierzchnie i krawędzie: karty mają gray-2 na stronie w gray-1, a menu, popovery i okna dialogowe przechodzą na gray-3 z jaśniejszą linią włosową wokół.
Wytyczne
- Elewacja to nie wyróżnienie. Nie dodawaj cieni, żeby coś wyglądało na ważne — do tego służą hierarchia i kolor.
- Nie nakładaj poziomów dowolnie. Powierzchnia pływająca należy do swojego wyzwalacza, a modalna — do strony. Nad powiadomieniem unoszą się tylko podpowiedzi.
- Na poziomie 1 wybieraj obramowania. Obramowanie 1 px robi dla struktury więcej niż cień i działa w każdym trybie.