Przejdź do treści

Accordion

Stabilny

Stos nagłówków, z których każdy odsłania sekcję treści — stopniowe ujawnianie informacji drugorzędnych.

Anatomia

  1. 1WyzwalaczPrzycisk w nagłówku, który nazywa sekcję. Przełącza ją kliknięcie w dowolnym miejscu wiersza.
  2. 2ElementJedna sekcja: wyzwalacz i jego panel. Elementy są rozdzielone cienkimi liniami.
  3. 3IkonaWskazuje w dół, gdy sekcja jest zamknięta, a po jej otwarciu odwraca się.
  4. 4PanelTreść sekcji. Przy otwieraniu i zamykaniu animuje swoją wysokość, a zamknięty jest pomijany przy przechodzeniu klawiszem Tab.

Instalacja

$ pnpm dlx shadcn@latest add https://www.prfct.dev/r/accordion.json

Użycie

import {
  Accordion,
  AccordionContent,
  AccordionItem,
  AccordionTrigger,
} from "@/components/ui/accordion"
<Accordion defaultValue={["shipping"]}>
  <AccordionItem value="shipping">
    <AccordionTrigger>How long does shipping take?</AccordionTrigger>
    <AccordionContent>Orders ship within one business day.</AccordionContent>
  </AccordionItem>
</Accordion>

defaultValuevalue to zawsze tablice wartości elementów — nawet wtedy, gdy otwarty może być tylko jeden element. Nadaj każdemu elementowi stałą wartość value, żeby jego stan przetrwał ponowne renderowanie i dało się nim sterować.

Przykłady

FAQ

Klasyczne zastosowanie: wiele pytań, z których każdego czytelnika dotyczy tylko kilka. Domyślnie otwarty jest jeden element naraz, więc lista pozostaje krótka i łatwa do przejrzenia, gdy ktoś przechodzi od jednej odpowiedzi do drugiej.

Najczęściej zadawane pytania

Wszystko o planach, rozliczeniach i twoich danych.

Wiele otwartych sekcji

Ustaw multiple, gdy trzeba porównywać sekcje albo pracować w kilku naraz — przy filtrach, ustawieniach czy pogrupowanych opcjach formularza. Tutaj dwie grupy filtrów są otwarte od początku.

Z ikonami i podsumowaniami

Wyzwalacze przyjmują dowolne elementy liniowe. Ikona na początku i jednowierszowe podsumowanie pozwalają ocenić, czy warto otworzyć sekcję — bez jej otwierania. Dodaj wcięcie panelu (classNameAccordionContent stylizuje jego wewnętrzny kontener), żeby tekst panelu był wyrównany do tytułu.

Wyłączony element

Wyłącz element, który istnieje, ale jest niedostępny, i wyjaśnij powód w jego etykiecie. Wyzwalacz pozostaje widoczny, czytniki ekranu odczytują go jako wyłączony i nie da się go przełączyć.

Tryb kontrolowany

Kontroluj value, aby otwierać sekcje z zewnątrz — na potrzeby przycisku Rozwiń wszystkie, linków prowadzących prosto do sekcji czy przywracania tego, co ktoś miał wcześniej otwarte. onValueChange otrzymuje nową tablicę wartości otwartych elementów.

Rozwinięte: 1 z 3

const [value, setValue] = React.useState<string[]>(["install"])

<Accordion multiple value={value} onValueChange={setValue}>

</Accordion>

Ruch

Panele animują swoją rzeczywistą wysokość z czasem trwania base i krzywą przejścia standard, a ich treść płynnie się pojawia w tym samym rytmie; strzałka obraca się synchronicznie. Nic nie jest skalowane ani przycinane, więc tekst nigdy się nie rozmywa. Przy prefers-reduced-motion sekcje otwierają się natychmiast.

Wytyczne

Kiedy używać

  • Aby skrócić długie strony, których sekcje dotyczą tylko części czytelników: FAQ, szczegóły produktu, informacje o wersji.
  • Aby pogrupować powiązane ustawienia lub filtry, do których wraca się wybiórczo.
  • Na małych ekranach — żeby treść drugorzędna była w zasięgu jednego dotknięcia, zamiast zajmować miejsce, które trzeba przewinąć.

Kiedy nie używać

  • Do treści, której potrzebuje każdy. Ukrycie jej kosztuje dodatkowe kliknięcie i utrudnia jej znalezienie — po prostu ją pokaż.
  • Do pojedynczego obszaru, który można pokazać lub ukryć — użyj komponentu Collapsible.
  • Do przełączania między widokami tych samych danych — użyj komponentu Tabs.
  • Do nawigacji — użyj komponentu Sidebar lub Navigation Menu.

Pisz wyzwalacze łatwe do przejrzenia

Wyzwalacze są nagłówkami. Pisz je krótko, zaczynaj od słowa kluczowego i dbaj, żeby ich zakresy się nie pokrywały — wtedy od razu widać, pod którym kryje się odpowiedź. W FAQ formułuj je jako pytania, które zadałby czytelnik.

Dobrze.Krótkie, konkretne nagłówki, które zapowiadają zawartość sekcji.

Źle.Ogólnikowe etykiety zmuszają do otwierania każdej sekcji, żeby cokolwiek znaleźć.

Zachowaj płaską strukturę

Nie zagnieżdżaj akordeonów. Drugi poziom ukrywa treść za dwoma kliknięciami i utrudnia śledzenie, co jest otwarte, a co zamknięte. Jeśli treść wymaga hierarchii, daj jej osobną stronę.

Nie ukrywaj tego, co kluczowe dla zadania

Ceny, błędy, pola wymagane i wszystko, co może zmienić decyzję, muszą pozostać widoczne. Akordeon służy do treści pomocniczych — jeśli po zwinięciu sekcji ktoś mógłby przeoczyć coś ważnego, ta treść nie powinna się w nim znaleźć.

Dostępność

Każdy wyzwalacz to <button> wewnątrz <h3>, z atrybutem aria-expanded oraz aria-controls, który wskazuje jego panel. Panele mają role="region", a ich etykietą jest wyzwalacz, więc czytnik ekranu informuje, w której sekcji znajduje się użytkownik.

KlawiszDziałanie
Tab
Przenosi fokus na następny wyzwalacz albo do elementów otwartego panelu, które mogą przyjąć fokus.
ShiftTab
Przenosi fokus na poprzedni wyzwalacz lub poprzedni element, który może przyjąć fokus.
EnterSpacja
Rozwija lub zwija sekcję, na której jest fokus.
  • Bez nawigacji strzałkami. Zgodnie z aktualizacją WAI-ARIA Authoring Practices z 2025 roku nagłówki akordeonu są zwykłymi elementami kolejności tabulacji; komponent nie przechwytuje klawiszy strzałek.
  • Poziom nagłówka. Wyzwalacze są umieszczone w <h3>. Jeśli to zaburza strukturę nagłówków twojej strony, zmień render elementu AccordionPrimitive.Header w swojej kopii komponentu (na przykład render={<h2 />}).
  • Wyszukiwanie na stronie. Ustaw hiddenUntilFound na elemencie głównym (lub na panelu), a wbudowane wyszukiwanie przeglądarki przeszuka zamknięte sekcje i otworzy tę, w której znajdzie dopasowanie.
  • Wyłączone elementy pozostają w kolejności odczytu i są ogłaszane jako wyłączone, więc użytkownik wie, że taka sekcja istnieje.

Dokumentacja API

Accordion

Grupuje elementy i zarządza tym, które z nich są otwarte. Renderuje <div>. Przyjmuje wszystkie propsy Accordion.Root z Base UI.

PropTypDomyślnie
defaultValue

Wartości elementów otwartych przy pierwszym renderowaniu (tryb niekontrolowany).

any[]Brak wartości domyślnej
value

Wartości otwartych elementów (tryb kontrolowany). Używaj razem z onValueChange.

any[]Brak wartości domyślnej
onValueChange

Wywoływana z nową tablicą wartości otwartych elementów, gdy któryś element zostanie przełączony.

(value: any[], details) => voidBrak wartości domyślnej
multiple

Pozwala otworzyć więcej niż jeden element jednocześnie.

booleanfalse
disabled

Wyłącza wszystkie elementy.

booleanfalse
hiddenUntilFound

Zostawia zamknięte panele w DOM z hidden="until-found", żeby wyszukiwanie na stronie mogło je odsłonić.

booleanfalse
keepMounted

Zostawia zamknięte panele w DOM. Ignorowany, gdy ustawiono hiddenUntilFound.

booleanfalse

AccordionItem

Jeden nagłówek i jego panel. Renderuje <div>.

PropTypDomyślnie
value

Identyfikuje element w value i defaultValue. Jeśli go pominiesz, zostanie wygenerowany — ustawiaj go zawsze, gdy sterujesz akordeonem.

anyBrak wartości domyślnej
disabled

Uniemożliwia przełączanie elementu.

booleanfalse
onOpenChange

Wywoływana, gdy ten element się otwiera lub zamyka.

(open: boolean, details) => voidBrak wartości domyślnej

AccordionTrigger

Przycisk, który przełącza swój element, opakowany w <h3>. Zawiera obracającą się strzałkę. Przyjmuje wszystkie propsy Accordion.Trigger z Base UI.

AccordionContent

Zwijany panel. className trafia do wewnętrznego kontenera treści (padding, typografia), a zewnętrzny panel odpowiada za animację wysokości. Przyjmuje wszystkie propsy Accordion.Panel z Base UI, w tym hiddenUntilFoundkeepMounted.