Accordion
BetaApila secciones que se expanden de a una, para contenido opcional que no todos necesitan leer.
Abrir en Figma
registry/ds/accordion.tsxEl primer lunes de febrero y de julio. Te avisamos por correo una semana antes.
import { Accordion, AccordionItem } from "@/registry/ds/accordion";
export default function AccordionBasic() {
return (
<div className="w-full max-w-xl">
<Accordion defaultValue={["1"]}>
<AccordionItem value="1" title="¿Cuándo abren las inscripciones?">
El primer lunes de febrero y de julio. Te avisamos por correo una semana antes.
</AccordionItem>
<AccordionItem value="2" title="¿Puedo cambiar de carrera?">
Sí, una vez por año, con las materias aprobadas que sean equivalentes.
</AccordionItem>
<AccordionItem value="3" title="¿Hay becas para segundo año?" disabled>
Próximamente.
</AccordionItem>
</Accordion>
</div>
);
}Cuándo usarlo
Para contenido opcional: preguntas frecuentes, detalles, condiciones. Lo que todos tienen que leer, va visible.
| Usá Accordion para… | Usá otra cosa para… |
|---|---|
| FAQs y detalles secundarios. | Contenido que todos necesitan → texto a la vista. |
| Reducir el largo de una página en mobile. | Secciones hermanas de igual peso → Tabs. |
| Pasos numerados de un proceso informativo. | Acciones destructivas: nunca escondidas en un panel cerrado. |
Estilos
Divider es el default, para documentación y configuración. Cards —con número y cápsula— es el expresivo, para FAQs de marketing.
Compará planes de estudio, duración y salida laboral de las 24 carreras.
import { Accordion, AccordionItem } from "@/registry/ds/accordion";
import { Button } from "@/registry/ds/button";
import { ArrowUpRight } from "@/registry/ds/icons";
export default function AccordionCards() {
return (
<div className="w-full max-w-xl">
<Accordion variant="cards" toggle="capsule" defaultValue={["01"]}>
<AccordionItem
value="01"
number="01"
title="Elegí tu carrera"
action={<Button variant="text" size="sm" iconRight={<ArrowUpRight />}>Ver carreras</Button>}
>
Compará planes de estudio, duración y salida laboral de las 24 carreras.
</AccordionItem>
<AccordionItem value="02" number="02" title="Completá la inscripción">
Cargá tus datos y la documentación. Te lleva unos 10 minutos.
</AccordionItem>
<AccordionItem value="03" number="03" title="Conocé el campus">
Sumate a una visita guiada o recorrelo en 360° desde tu casa.
</AccordionItem>
</Accordion>
</div>
);
}Indicador
Tres opciones; una sola por página. Al abrir, el chevron rota y el más se vuelve menos. Nunca una ✕: eso significa cerrar o borrar.
import { Accordion, AccordionItem } from "@/registry/ds/accordion";
export default function AccordionToggles() {
return (
<div className="grid w-full max-w-2xl gap-4 sm:grid-cols-3">
{(["chevron", "plus", "capsule"] as const).map((toggle) => (
<Accordion key={toggle} toggle={toggle} size="sm" accent={false}>
<AccordionItem value="a" title={toggle}>
El indicador cambia al abrir; nunca es una ✕.
</AccordionItem>
</Accordion>
))}
</div>
);
}Reglas
- Cerrado por defecto, salvo el primero si ayuda a entender el patrón.
- Se abre uno a la vez;
multiplesolo si comparar paneles tiene sentido. - Títulos que se entiendan sin abrir: la pregunta completa, no "Más información".
- Un solo nivel: nada de accordions dentro de accordions.
- El acento verde inferior es para piezas de marca; apagalo (
accent={false}) en UI de producto densa.
Medidas
| Size | Padding trigger | Título | Icono | Cápsula | Contenido |
|---|---|---|---|---|---|
sm | 14 × 16 | Text sm / Medium | 16 | 24 | Text sm |
md | 18 × 20 | Text md / Medium | 20 | 28 | Text sm |
Contenedor radius-xl (12). Cards: gap spacing-xl (12) + Elevation/xs.
Acento: 3 px abajo del item abierto. Animación de alto: duration/fast (200 ms).
Tokens por estado
| Parte | Propiedad | Token |
|---|---|---|
| Contenedor / card | Fondo | bg/elevated |
| Contenedor / divisores | Borde | border/default |
| Trigger · hover | Fondo | bg/subtle |
| Título | Color | text/default |
| Número | Color | primary/accent |
| Icono leading | Color | icon/muted |
| Chevron / más | Color | icon/subtle |
| Cápsula | Fondo / glifo | primary/solid |
| Contenido | Color | text/muted |
| Acento | Fondo | primary/solid |
| Deshabilitado | Todo el texto | text/disabled |
| Foco | Anillo interior 2 px | focus/ring |
En Figma
| Propiedad en Figma | Valores | En código | Nota |
|---|---|---|---|
| Accordion › Style | Divider · Cards | variant | — |
| Size | sm · md | size | — |
| .Accordion item › Toggle | Chevron · Plus · Capsule | toggle | En código se define una vez, en el grupo. |
| Leading | None · Icon · Number | icon · number | — |
| State | Closed · Hover · Open · Disabled | value · disabled | — |
| Title · Content | Texto | title · children | — |
| Show action | on/off | action | — |
| Accent | on/off | accent | — |
Instalación
npx shadcn@latest add https://polen.cdc.cool/r/accordion.jsonPlayground
Configurá el componente y copiá el snippet: se genera del mismo estado que renderiza el preview.
El primer lunes de febrero y de julio. Te avisamos por correo una semana antes.
variant
toggle
size
Antes del título
<Accordion defaultValue={["0"]}>
<AccordionItem value="0" title="¿Cuándo abren las inscripciones?">El primer lunes de febrero y de julio. Te avisamos por correo una semana antes.</AccordionItem>
<AccordionItem value="1" title="¿Puedo cambiar de carrera?">Sí, una vez por año, con las materias aprobadas que sean equivalentes.</AccordionItem>
<AccordionItem value="2" title="¿Hay becas para segundo año?">Sí: por promedio y por situación económica. Se piden en marzo.</AccordionItem>
</Accordion>Uso
<Accordion defaultValue={["1"]}>
<AccordionItem value="1" title="¿Cuándo abren las inscripciones?">
El primer lunes de febrero y de julio.
</AccordionItem>
</Accordion>Props
Sobre Base UI Accordion.
| Prop | Tipo | Default | Descripción |
|---|---|---|---|
Accordion · variant | "divider" | "cards" | "divider" | Estilo del grupo. |
Accordion · toggle | "chevron" | "plus" | "capsule" | "chevron" | Indicador de todos los items. |
Accordion · size | "sm" | "md" | "md" | Padding y tipografía. |
Accordion · accent | boolean | true | Barra verde bajo el item abierto. |
Accordion · multiple | boolean | false | Permite varios abiertos. |
Accordion · value / defaultValue | string[] | — | Items abiertos. |
AccordionItem · value | string | — | Identificador del item. |
AccordionItem · title | ReactNode | — | Requerido. |
AccordionItem · icon · number | ReactNode · string | — | Leading: uno u otro. |
AccordionItem · action | ReactNode | — | Un Button variant="text" al final del contenido. |
AccordionItem · disabled | boolean | false | No se puede abrir. |
Teclado
| Tecla | Qué hace |
|---|---|
| Tab | Pasa de un encabezado al siguiente (y por el contenido abierto). |
| EnterEspacio | Abre o cierra el item enfocado. |
Qué viene resuelto
- Cada encabezado es un
<button>dentro de un heading, conaria-expandedyaria-controls. - El panel cerrado no es alcanzable con teclado ni por lectores de pantalla.
- El estado no depende del color: el indicador cambia de forma.
- Sin animación con
prefers-reduced-motion.
Qué tenés que cuidar vos
- El nivel de heading de los títulos tiene que encajar en la jerarquía de la página.
- El buscador del navegador (⌘F) no encuentra texto en paneles cerrados: otra razón para no esconder contenido importante.