Przejdź do głównej zawartości

Button

Draft

Wszystkie warianty × rozmiary naraz, w izolowanym podglądzie (przydatne przy sprawdzaniu kontrastu na żywo w innej marce/trybie):

Otwórz w nowej karcie ↗
Warianty
import { Button } from "@polisoteka-design/ui";

export function ButtonVariants() {
  return (
    <div className="flex flex-wrap gap-inline-sm">
      <Button variant="primary">Primary</Button>
      <Button variant="secondary">Secondary</Button>
      <Button variant="ghost">Ghost</Button>
      <Button variant="destructive">Destructive</Button>
    </div>
  );
}

export default ButtonVariants;
Rozmiary
import { Button } from "@polisoteka-design/ui";

export function ButtonSizes() {
  return (
    <div className="flex flex-wrap items-center gap-inline-sm">
      <Button size="sm">Small</Button>
      <Button size="md">Medium</Button>
      <Button size="lg">Large</Button>
    </div>
  );
}

export default ButtonSizes;

Używaj Button, gdy akcja coś ZMIENIA (zapisuje, wysyła, usuwa, uruchamia proces) — jeden primary na widok/formularz dla akcji głównej, secondary/ghost dla akcji pobocznych, destructive wyłącznie dla akcji nieodwracalnych lub kosztownych do cofnięcia.

Nie używaj Button, gdy element tylko NAWIGUJE do innej strony bez efektu ubocznego — to zwykły link (<a> ze stylem linku, albo Button asChild tylko jeśli wizualnie musi wyglądać jak przycisk, np. CTA w karcie). Nie dawaj też dwóch primary obok siebie — hierarchia akcji ginie.

@todo(S-WYWIAD): mikrocopy przycisków (czasownik + rezultat, np. „Zapisz zmiany” nie „OK”; jak formułować destructive — potwierdzenie w treści przycisku vs. osobny dialog) — powstanie w wywiadzie z Human, bez kopiowania z company/brand/ na skróty.

NazwaTypWymaganyDomyślnieOpis
variant'primary' | 'secondary' | 'ghost' | 'destructive'nie'primary'Wariant wizualny.
size'sm' | 'md' | 'lg'nie'md'Rozmiar (padding + typografia).
asChildbooleanniefalseRenderuje klasy/warianty na przekazanym dziecku (Radix Slot) zamiast <button>.

Zapewnione przez komponent:

  • Renderuje natywny <button> (rola i klawiaturowa obsługa za darmo) — asChild przenosi te same klasy na dowolny element przez Radix Slot.
  • :focus-visible widoczny, kolor z tokenu focus.ring.
  • Stan disabled: pointer-events-none + cursor-not-allowed, więc nie wygląda na klikalny.

Sprawdź przy użyciu:

  • Accessible name pochodzi z children (tekst) albo aria-label — jeśli przycisk niesie tylko ikonę, aria-label jest wymagany.
  • Kontrast tekst/tło każdego wariantu jest zweryfikowany na poziomie tokenów (tokens/check.mjs), ale jeśli nadpiszesz className kolorem spoza tokenów, kontrast przestaje być gwarantowany.
  • Input — formularze zwykle łączą Button z Field/Input.
  • CardCardFooter typowo zawiera Button.
  • Fundamenty → Kolor — pochodzenie brand.primary/status.danger.