Przejdź do głównej zawartości

Button

Techniczny: DraftAkceptacja: Draft

Materiał odziedziczony z PoC. Działający przykład pokazuje stan kodu, nie zatwierdzenie nowej identyfikacji. Rozstrzygnięcia warsztatów mają pierwszeństwo.

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 LinkButton tylko jeśli wizualnie musi wyglądać jak przycisk, np. CTA w karcie). Nie dawaj też dwóch primary obok siebie — hierarchia akcji ginie.

NazwaTypWymaganyDomyślnieOpis
variant'primary' | 'secondary' | 'ghost' | 'destructive'nie'primary'Wariant wizualny.
size'sm' | 'md' | 'lg'nie'md'Rozmiar (padding + typografia).
focusableWhenDisabledbooleanniefalsePozostawia disabled w kolejności fokusu; Base UI blokuje akcję i ustawia aria-disabled.

Button używa Base UI i domyślnie ma type="button". Wysłanie formularza wymaga type="submit". focusableWhenDisabled zachowuje fokusowalność, ale nadal blokuje akcję. Nie wystawiamy polimorficznego render.

LinkButton importujemy z @polisoteka/design-ui/button; cel podajemy w href. Współdzieli warianty wizualne, nie zachowanie przycisku.

NazwaTypWymaganyDomyślnieOpis
variant'primary' | 'secondary' | 'ghost' | 'destructive'nie'primary'Wspólna skala stylu Button; destructive nie służy zwykłej nawigacji.
size'sm' | 'md' | 'lg'nie'md'Wspólny rozmiar tokenowy.

Zapewnione przez komponent:

  • Renderuje natywny <button> (rola i klawiaturowa obsługa za darmo) — mechanikę zapewnia Base UI. LinkButton zachowuje natywną rolę odsyłacza.
  • :focus-visible widoczny, kolor z tokenu focus.ring.
  • Stan disabled: cursor-not-allowed i BRAK reakcji na wskaźnik — reguły hover:/active: mają warunek not-disabled:not-data-disabled:, więc wyłączony przycisk nie zmienia tła pod kursorem. Bez tego warunku wyłączony przycisk udawał aktywny (zmierzone w Chromium: rgb(39, 74, 116) → rgb(26, 53, 86)). Nie używamy pointer-events-none: ta klasa zdejmuje obsługę wskaźnika, więc unieważniałaby samo cursor-not-allowed.

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/src/artifact.ts), ale jeśli nadpiszesz className kolorem spoza tokenów, kontrast przestaje być gwarantowany.
  • Input — formularze zwykle łączą Button z Field/Input.
  • Card — CardFooter typowo zawiera Button.
  • Fundamenty → Kolor — pochodzenie brand.primary/status.danger.

@todo(button): wykonać poniższy brief, przedstawić rezultat i dowody odbioru. Usunięcie znacznika nie jest wykonaniem zadania.

  • Zakres: Zachowaj działające API i demo; uzupełnij mikrocopy, wszystkie stany i mapę wartości do tokenów, test regresji na szablonie.
  • Konwencja: najpierw reguła lub gotowe zastosowanie, potem przykład i kontrprzykład, następnie granice oraz sposób sprawdzenia. Nie zastępuj materiału opisem planu jego przygotowania.
  • Źródła: platforma marki; zaakceptowane decyzje warsztatów. Zastane demo lub deklaracja PoC nie zatwierdzają nowej reguły.
  • Powiązania: Tokeny i zależności, Mikrocopy i komunikaty operacyjne.
  • Granica swobody: możesz redagować i pokazywać istniejące ustalenia. Nową obietnicę, wybór wizualny, dane firmy i twierdzenie produktowe przedstaw do decyzji; nie uzupełniaj z pamięci.

Sprawdź rzeczywisty render i użycie wspólnego kodu, desktop/mobile, jasny/ciemny tryb oraz właściwe konteksty portali. Bramka techniczna: pnpm design:check; przed wydaniem także pnpm design:audit. Sam opis ani zielony test innego demo nie jest dowodem odbioru tego elementu.