UNPKG

@base-ui/react

Version:

Base UI is a library of headless ('unstyled') React components and low-level hooks. You gain complete control over your app's CSS and accessibility features.

122 lines (121 loc) 3.91 kB
'use client'; import * as React from 'react'; import { useIsoLayoutEffect } from '@base-ui/utils/useIsoLayoutEffect'; import { warn } from '@base-ui/utils/warn'; import { resolveStyle } from "../../utils/resolveStyle.js"; import { useCollapsibleRootContext } from "../../collapsible/root/CollapsibleRootContext.js"; import { useCollapsiblePanel } from "../../collapsible/panel/useCollapsiblePanel.js"; import { useAccordionRootContext } from "../root/AccordionRootContext.js"; import { useAccordionItemContext } from "../item/AccordionItemContext.js"; import { accordionStateAttributesMapping } from "../item/stateAttributesMapping.js"; import { AccordionPanelCssVars } from "./AccordionPanelCssVars.js"; import { useRenderElement } from "../../internals/useRenderElement.js"; /** * A collapsible panel with the accordion item contents. * Renders a `<div>` element. * * Documentation: [Base UI Accordion](https://base-ui.com/react/components/accordion) */ export const AccordionPanel = /*#__PURE__*/React.forwardRef(function AccordionPanel(componentProps, forwardedRef) { const { className, hiddenUntilFound: hiddenUntilFoundProp, keepMounted: keepMountedProp, id: idProp, render, style, ...elementProps } = componentProps; const { hiddenUntilFound: contextHiddenUntilFound, keepMounted: contextKeepMounted } = useAccordionRootContext(); const { mounted, onOpenChange, open, panelId, setMounted, setOpen, setPanelIdState, transitionStatus } = useCollapsibleRootContext(); const hiddenUntilFound = hiddenUntilFoundProp ?? contextHiddenUntilFound; const keepMounted = keepMountedProp ?? contextKeepMounted; if (process.env.NODE_ENV !== 'production') { // eslint-disable-next-line react-hooks/rules-of-hooks useIsoLayoutEffect(() => { if (keepMountedProp === false && hiddenUntilFound) { warn('The `keepMounted={false}` prop on an `Accordion.Panel` is ignored when `hiddenUntilFound` is enabled on the panel or root, since the panel must remain mounted while closed.'); } }, [hiddenUntilFound, keepMountedProp]); } useIsoLayoutEffect(() => { if (idProp) { setPanelIdState(idProp); return () => { setPanelIdState(undefined); }; } return undefined; }, [idProp, setPanelIdState]); const { height, props, ref, shouldPreventOpenAnimation, shouldRender, transitionStatus: panelTransitionStatus, width } = useCollapsiblePanel({ externalRef: forwardedRef, hiddenUntilFound, id: idProp ?? panelId, keepMounted, mounted, onOpenChange, open, setMounted, setOpen, transitionStatus }); const { state, triggerId } = useAccordionItemContext(); const panelState = { ...state, transitionStatus: panelTransitionStatus }; const resolvedStyle = resolveStyle(style, panelState); const element = useRenderElement('div', { ...componentProps, style: undefined }, { state: panelState, ref, props: [props, { 'aria-labelledby': triggerId, role: 'region', style: { [AccordionPanelCssVars.accordionPanelHeight]: height === undefined ? 'auto' : `${height}px`, [AccordionPanelCssVars.accordionPanelWidth]: width === undefined ? 'auto' : `${width}px` } }, elementProps, resolvedStyle ? { style: resolvedStyle } : undefined, // Resolve the public `style` prop so temporary `animationName: 'none'` // can still win after user's inline styles have been merged. shouldPreventOpenAnimation ? { style: { animationName: 'none' } } : undefined], stateAttributesMapping: accordionStateAttributesMapping }); if (!shouldRender) { return null; } return element; }); if (process.env.NODE_ENV !== "production") AccordionPanel.displayName = "AccordionPanel";