import type { ReactNode } from "react"; export type AccordionHeadingLevel = 2 | 3 | 4 | 5 | 6; export type AccordionItem = { content: ReactNode; isDisabled?: boolean; key: string; label: ReactNode; }; export type AccordionProps = { className?: string; /** **Initial** only. Charcuterie owns it from then on. */ expandedKeys?: string[]; /** * The heading level the triggers sit at. An accordion inside a * `Card` that already has an `

` needs `3`, and getting this * wrong is a document-outline break that no gate here can see — * it depends entirely on the page. */ headingLevel?: AccordionHeadingLevel; /** * Several sections open at once. The default is **exclusive**, * because that is what every one of the fleet's disclosure groups * does today. */ isMultiple?: boolean; items: AccordionItem[]; onChange?: (expandedKeys: string[]) => void; }; /** * Eleven sites in the fleet, and the plan called it "nearly free * once `Tabs` exists". It is — the exclusive mode is * `VisibilityGroup` and nothing else — but the reason it is worth * shipping is not the saving. * * ### The two-owners bug, live, in the app this milestone migrates * * mux-magic's `JobStepsDisclosure` is built on `
`, and * `
` **owns `open`**. It also wants the state in a Jotai * atom so a job can be expanded from elsewhere. Reconciling the two * takes three separate mechanisms: * * ```tsx * const detailsRef = useRef(null) * const skipNextToggleRef = useRef(isOpen) * * useEffect(() => { * if (detailsRef.current) detailsRef.current.open = isOpen * }, [isOpen]) * * const handleToggle = (event) => { * if (skipNextToggleRef.current) { * skipNextToggleRef.current = false * return // ← swallow the toggle our own write just fired * } * setStepsOpen(…) * } * ``` * * That is the Radix argument from `Popover` pointed at the platform: * a ref to reach past React, an effect to push state into the DOM, * and a guard to stop the DOM's echo coming back. Every one of the * three exists only because two things hold one fact. * * So this is a `