Accordion
Secciones desplegables que abren primero y dejan que sus líneas las sigan.
Same-day delivery in Guatemala City for orders before noon.
Two to four business days anywhere else in the country.
Free over Q500.
Instalación
$ pnpm dlx shadcn@latest add @ssntl/accordionUso
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion"
<Accordion type="single" collapsible>
<AccordionItem value="envios">
<AccordionTrigger>Envíos</AccordionTrigger>
<AccordionContent><p>Entrega el mismo día…</p></AccordionContent>
</AccordionItem>
</Accordion>Reglas
Lo que este componente espera de ti, tal como se instala en components/ui/accordion.md junto al código. El archivo completo agrega cuándo usarlo, teclado, los fundamentos de UI que aplica y cada regla compartida (en inglés).
## Reglas de Accordion
- **Continuidad y superposición.** El panel abre primero (220ms) y cada línea entra 40ms después de la anterior.
- Cerrar es más rápido y de una vez, porque salir pide menos atención que llegar.
- Los encabezados son botones reales dentro de encabezados; las flechas se mueven entre ellos (Radix).
- El chevron gira con `--ease-in-out`; con movimiento reducido nada se mueve y el contenido simplemente aparece.Código
"use client"
import * as React from "react"
import { ChevronDown } from "lucide-react"
import { Accordion as AccordionPrimitive } from "radix-ui"
import { cn } from "@/lib/utils"
// Disclosure sections (Radix Accordion): arrow keys move between headers,
// Enter and Space open them, and each header is a real button in a heading.
// Follow through & overlap: the panel opens first (collapsible), then its rows
// lift in 40ms apart (follow-through), so the motion settles; closing is
// faster and all at once. Both turn off under reduced motion.
const Accordion = AccordionPrimitive.Root
function AccordionItem({
className,
...props
}: React.ComponentProps<typeof AccordionPrimitive.Item>) {
return (
<AccordionPrimitive.Item
data-slot="accordion-item"
className={cn("not-first:border-t not-first:border-border", className)}
{...props}
/>
)
}
function AccordionTrigger({
className,
children,
...props
}: React.ComponentProps<typeof AccordionPrimitive.Trigger>) {
return (
<AccordionPrimitive.Header className="flex">
<AccordionPrimitive.Trigger
data-slot="accordion-trigger"
className={cn(
"group flex min-h-14 flex-1 cursor-pointer items-center justify-between gap-4 rounded-xs py-3 text-start text-label",
"focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring",
className
)}
{...props}
>
{children}
<ChevronDown
aria-hidden
strokeWidth={1.6}
className="size-5 shrink-0 opacity-80 transition-[rotate] duration-(--duration-menu) ease-in-out group-data-[state=open]:rotate-180 motion-reduce:transition-none"
/>
</AccordionPrimitive.Trigger>
</AccordionPrimitive.Header>
)
}
function AccordionContent({
className,
children,
...props
}: React.ComponentProps<typeof AccordionPrimitive.Content>) {
return (
<AccordionPrimitive.Content
data-slot="accordion-content"
className="collapsible"
{...props}
>
<div
className={cn(
"grid follow-through gap-2 pb-4 text-body text-muted-foreground",
className
)}
>
{children}
</div>
</AccordionPrimitive.Content>
)
}
export { Accordion, AccordionContent, AccordionItem, AccordionTrigger }