nostalgia-ui
uiretro-accordionsource: ok · hit
RetroAccordion
A Mac OS 9 styled accordion with disclosure triangle, bevel separator, and collapse animation, built on Radix UI Accordion.
npx shadcn add "https://nostalgia-ui.com/r/retro-accordion.json"free
Visual style
retro
Interaction
accordion
Tags auto-generated by rules on 9/24/2026 — empty means no evidence, not lack of support.
Dependencies
Bundle weight · lightui-primitives@radix-ui/react-accordion
Registry dependencies
https://nostalgia-ui.com/r/nostalgia-theme.json
Files1 · source cached 10/15/2026, 7:39:54 AM
registry/new-york/ui/retro-accordion.tsx
"use client"
import * as React from "react"
import * as AccordionPrimitive from "@radix-ui/react-accordion"
import { cn } from "@/lib/utils"
/* ------------------------------------------------------------------ */
/* RetroAccordion (root) */
/* ------------------------------------------------------------------ */
function RetroAccordion(
{
className,
...props
}: React.ComponentProps<typeof AccordionPrimitive.Root>,
ref: React.ForwardedRef<HTMLDivElement>
) {
return (
<AccordionPrimitive.Root
ref={ref}
className={cn("flex flex-col", className)}
{...props}
/>
)
}
const ForwardedRetroAccordion = React.forwardRef(RetroAccordion)
ForwardedRetroAccordion.displayName = "RetroAccordion"
/* ------------------------------------------------------------------ */
/* RetroAccordionItem */
/* ------------------------------------------------------------------ */
function RetroAccordionItem(
{
className,
...props
}: React.ComponentProps<typeof AccordionPrimitive.Item>,
ref: React.ForwardedRef<HTMLDivElement>
) {
return (
<AccordionPrimitive.Item
ref={ref}
className={cn(
/* Bevel separator: 1px dark + 1px light */
"border-b border-b-[var(--os9-gray-700)]",
"shadow-[0_1px_0_var(--os9-white)]",
className
)}
{...props}
/>
)
}
const ForwardedRetroAccordionItem = React.forwardRef(RetroAccordionItem)
ForwardedRetroAccordionItem.displayName = "RetroAccordionItem"
/* ------------------------------------------------------------------ */
/* RetroAccordionTrigger */
/* ------------------------------------------------------------------ */
function RetroAccordionTrigger(
{
className,
children,
...props
}: React.ComponentProps<typeof AccordionPrimitive.Trigger>,
ref: React.ForwardedRef<HTMLButtonElement>
) {
return (
<AccordionPrimitive.Header className="flex">
<AccordionPrimitive.Trigger
ref={ref}
className={cn(
"group/accordion-trigger",
"flex w-full flex-row items-center justify-between",
"py-[6px]",
"cursor-pointer select-none",
"font-[family-name:var(--os9-font-heading)] text-[12px] tracking-[0.42px]",
"text-os9-black",
"hover:bg-[var(--os9-lavender)]",
"focus-visible:os9-focus-ring",
"transition-none",
"[&>svg]:shrink-0",
className
)}
{...props}
>
<span className="flex items-center gap-[6px]">
{/* Disclosure triangle */}
<svg
width="8"
height="8"
viewBox="0 0 8 8"
fill="currentColor"
aria-hidden="true"
className={cn(
"transition-transform duration-150",
/* Scoped to this trigger so nested accordions rotate independently */
"group-data-[state=open]/accordion-trigger:rotate-90"
)}
>
<polygon points="1,0 7,4 1,8" />
</svg>
{children}
</span>
</AccordionPrimitive.Trigger>
</AccordionPrimitive.Header>
)
}
const ForwardedRetroAccordionTrigger = React.forwardRef(RetroAccordionTrigger)
ForwardedRetroAccordionTrigger.displayName = "RetroAccordionTrigger"
/* ------------------------------------------------------------------ */
/* RetroAccordionContent */
/* ------------------------------------------------------------------ */
function RetroAccordionContent(
{
className,
children,
...props
}: React.ComponentProps<typeof AccordionPrimitive.Content>,
ref: React.ForwardedRef<HTMLDivElement>
) {
return (
<AccordionPrimitive.Content
ref={ref}
className={cn(
"overflow-hidden",
"font-[family-name:var(--os9-font-sans)] text-[10px]",
"text-os9-black",
/* Collapse/expand animation via data-state */
"data-[state=open]:animate-accordion-down",
"data-[state=closed]:animate-accordion-up",
className
)}
{...props}
>
<div className="pb-[8px] pl-[16px] pr-0 pt-0">{children}</div>
</AccordionPrimitive.Content>
)
}
const ForwardedRetroAccordionContent = React.forwardRef(RetroAccordionContent)
ForwardedRetroAccordionContent.displayName = "RetroAccordionContent"
/* ------------------------------------------------------------------ */
/* Exports */
/* ------------------------------------------------------------------ */
export {
ForwardedRetroAccordion as RetroAccordion,
ForwardedRetroAccordionItem as RetroAccordionItem,
ForwardedRetroAccordionTrigger as RetroAccordionTrigger,
ForwardedRetroAccordionContent as RetroAccordionContent,
}