import UI from "#components/ui"; import React, { useCallback } from "react"; import type { DetailsProps } from "./details.types"; /** * Details - A progressive disclosure component using native HTML `
` element. * * This component wraps the native `
` and `` elements to provide * an accessible, semantic way to show and hide content. It supports accordion behavior * through the `name` attribute and includes proper keyboard navigation out of the box. * * ## Key Features: * - **Semantic HTML**: Uses native `
` for built-in accessibility * - **Keyboard Support**: Space/Enter to toggle, fully accessible by default * - **Accordion Mode**: Group multiple details with `name` for exclusive expansion * - **Customizable**: Supports icons, custom styles, and event handlers * * ## Accessibility: * - ✅ WCAG 2.1 AA compliant using semantic HTML * - ✅ Native keyboard support (Space, Enter) * - ✅ Screen reader compatible (announced as "disclosure" or "expandable") * - ✅ Focus indicators automatically applied via CSS * - ✅ `aria-expanded` managed automatically by browser * * @example * ```tsx * // Basic usage *
*

Hidden content here

*
* ``` * * @example * ```tsx * // With icon and custom styling *
} * classes="custom-details" * onToggle={(e) => console.log('Open:', e.currentTarget.open)} * > *

Ships within 2-3 business days

*
* ``` * * @example * ```tsx * // Accordion mode - only one open at a time *
Answer 1
*
Answer 2
*
Answer 3
* ``` */ export const Details = React.forwardRef( ( { summary, icon, styles, classes, ariaLabel, name, open, onPointerDown, onToggle, children, ...props }, ref ) => { // Memoize callbacks to prevent unnecessary re-renders of child components const handlePointerDown = useCallback( (e: React.PointerEvent) => { onPointerDown?.(e as React.PointerEvent); }, [onPointerDown] ); const handleToggle = useCallback( (e: React.SyntheticEvent) => { onToggle?.(e); }, [onToggle] ); return ( {icon} {summary} {children} ); } ); Details.displayName = "Details"; export default Details;