Skip to main content
Problem 40

Extend an Accordion with Controlled Mode and Exclusive Opening

MEDIUMEXTEND
React Patterns+3
Brief

You have a working Accordion built using the compound component pattern. It renders panels that open and close when their trigger is clicked. The existing implementation is uncontrolled — it manages its own open/close state internally.

Extend the Accordion without breaking existing behavior:

  1. Exclusive mode — when the exclusive prop is set to true, opening one panel must automatically close any other open panel.
  2. Controlled mode — when activePanel and onPanelChange props are both provided, the Accordion must defer to external state instead of managing its own.
  3. Disabled panelsAccordion.Panel must accept a disabled prop. A disabled panel's trigger must be unclickable and its content must never open.

All existing tests for the default uncontrolled behavior must continue to pass.

Requirements
  • The existing uncontrolled behavior (click trigger → panel opens/closes) must not be broken.
  • When exclusive={true} is passed to Accordion, clicking a trigger closes any currently open panel before opening the new one. Clicking the already-open panel's trigger still closes it.
  • When activePanel (string | null) and onPanelChange (function) are both provided, the Accordion reads its open/close state from activePanel and calls onPanelChange(id) or onPanelChange(null) on toggle — it must not call setActivePanel internally.
  • Accordion.Panel must accept a disabled?: boolean prop. When disabled is true, the panel's trigger must have a disabled HTML attribute and clicking it must not open the panel or call any callback.
  • The data-testid attributes on existing elements must not be changed.
Examples
Example 1
Input
<Accordion exclusive>
  <Accordion.Panel id="a">...</Accordion.Panel>
  <Accordion.Panel id="b">...</Accordion.Panel>
</Accordion>
Output
Opening panel 'b' while 'a' is open → panel 'a' closes, panel 'b' opens.
Note

Exclusive mode: at most one panel is open at any time.

Example 2
Input
const [open, setOpen] = useState('a');
<Accordion activePanel={open} onPanelChange={setOpen}>
Output
Clicking panel 'b' trigger → setOpen('b') is called → Accordion re-renders with panel 'b' open.
Note

Controlled mode: the Accordion reflects external state and delegates changes upward.

Example 3
Input
<Accordion.Panel id="c" disabled>
  <Accordion.Trigger panelId="c">Section C</Accordion.Trigger>
  ...
</Accordion.Panel>
Output
Clicking the trigger has no effect. Content for panel 'c' never renders.
Note

Disabled panels are inert — their trigger is disabled and their content stays hidden.

Constraints
  • Do not modify data-testid attributes on any existing element.
  • The compound component API (Accordion, Accordion.Panel, Accordion.Trigger, Accordion.Content) must remain intact.
  • Controlled mode only activates when both activePanel and onPanelChange are provided — not just one of them.
Judge checks
  • react environment
  • react-testing-library runner
  • 10000ms judge budget
Follow-up

The current implementation only allows one panel open at a time in exclusive mode. How would you add a `multi` prop that allows any number of panels to be open simultaneously?

Hints
Console output appears after the preview logs something.