diff --git a/docs/reference/generated/accordion-panel.json b/docs/reference/generated/accordion-panel.json index 24ee5bbbbdb..2fd4e036607 100644 --- a/docs/reference/generated/accordion-panel.json +++ b/docs/reference/generated/accordion-panel.json @@ -39,6 +39,9 @@ "data-disabled": { "description": "Present when the accordion item is disabled." }, + "data-hidden": { + "description": "Present when the panel is hidden." + }, "data-index": { "description": "Indicates the index of the accordion item.", "type": "number" diff --git a/docs/reference/generated/collapsible-panel.json b/docs/reference/generated/collapsible-panel.json index c1595a4c0cd..f5efeb1b195 100644 --- a/docs/reference/generated/collapsible-panel.json +++ b/docs/reference/generated/collapsible-panel.json @@ -36,6 +36,9 @@ "data-closed": { "description": "Present when the collapsible panel is closed." }, + "data-hidden": { + "description": "Present when the panel is hidden." + }, "data-starting-style": { "description": "Present when the panel is animating in." }, diff --git a/packages/react/src/accordion/panel/AccordionPanel.tsx b/packages/react/src/accordion/panel/AccordionPanel.tsx index a792309be61..d2aec21716e 100644 --- a/packages/react/src/accordion/panel/AccordionPanel.tsx +++ b/packages/react/src/accordion/panel/AccordionPanel.tsx @@ -14,6 +14,23 @@ import { AccordionPanelCssVars } from './AccordionPanelCssVars'; import { useOpenChangeComplete } from '../../utils/useOpenChangeComplete'; import { useRenderElement } from '../../utils/useRenderElement'; import type { TransitionStatus } from '../../utils/useTransitionStatus'; +import type { StateAttributesMapping } from '../../utils/getStateAttributesProps'; +import { AccordionPanelDataAttributes } from './AccordionPanelDataAttributes'; + +const stateAttributesMapping: StateAttributesMapping = { + ...accordionStateAttributesMapping, + open: (open) => { + const hidden = !open; + const itemMapping = accordionStateAttributesMapping.open?.(open) ?? {}; + if (hidden) { + return { + ...itemMapping, + [AccordionPanelDataAttributes.hidden]: '', + }; + } + return itemMapping; + }, +}; /** * A collapsible panel with the accordion item contents. @@ -153,7 +170,7 @@ export const AccordionPanel = React.forwardRef(function AccordionPanel( }, elementProps, ], - stateAttributesMapping: accordionStateAttributesMapping, + stateAttributesMapping, }); const shouldRender = keepMounted || hiddenUntilFound || (!keepMounted && mounted); diff --git a/packages/react/src/accordion/panel/AccordionPanelDataAttributes.ts b/packages/react/src/accordion/panel/AccordionPanelDataAttributes.ts index 21f5fd2a1e9..3bd946447bc 100644 --- a/packages/react/src/accordion/panel/AccordionPanelDataAttributes.ts +++ b/packages/react/src/accordion/panel/AccordionPanelDataAttributes.ts @@ -26,4 +26,8 @@ export enum AccordionPanelDataAttributes { * Present when the panel is animating out. */ endingStyle = TransitionStatusDataAttributes.endingStyle, + /** + * Present when the panel is hidden. + */ + hidden = 'data-hidden', } diff --git a/packages/react/src/collapsible/panel/CollapsiblePanel.tsx b/packages/react/src/collapsible/panel/CollapsiblePanel.tsx index 7450f5f1462..bdf225a1976 100644 --- a/packages/react/src/collapsible/panel/CollapsiblePanel.tsx +++ b/packages/react/src/collapsible/panel/CollapsiblePanel.tsx @@ -6,12 +6,18 @@ import { BaseUIComponentProps } from '../../utils/types'; import { useRenderElement } from '../../utils/useRenderElement'; import { useCollapsibleRootContext } from '../root/CollapsibleRootContext'; import type { CollapsibleRoot } from '../root/CollapsibleRoot'; -import { collapsibleStateAttributesMapping } from '../root/stateAttributesMapping'; +import { transitionStatusMapping } from '../../utils/stateAttributesMapping'; +import { panelOpenStateMapping } from '../../utils/collapsibleOpenStateMapping'; import { useCollapsiblePanel } from './useCollapsiblePanel'; import { CollapsiblePanelCssVars } from './CollapsiblePanelCssVars'; import { useOpenChangeComplete } from '../../utils/useOpenChangeComplete'; import type { TransitionStatus } from '../../utils/useTransitionStatus'; +import type { StateAttributesMapping } from '../../utils/getStateAttributesProps'; +const stateAttributesMapping: StateAttributesMapping = { + ...panelOpenStateMapping, + ...transitionStatusMapping, +}; /** * A panel with the collapsible contents. * Renders a `
` element. @@ -144,7 +150,7 @@ export const CollapsiblePanel = React.forwardRef(function CollapsiblePanel( }, elementProps, ], - stateAttributesMapping: collapsibleStateAttributesMapping, + stateAttributesMapping, }); const shouldRender = keepMounted || hiddenUntilFound || (!keepMounted && mounted); diff --git a/packages/react/src/collapsible/panel/CollapsiblePanelDataAttributes.ts b/packages/react/src/collapsible/panel/CollapsiblePanelDataAttributes.ts index d081ee87c7c..b8328926b91 100644 --- a/packages/react/src/collapsible/panel/CollapsiblePanelDataAttributes.ts +++ b/packages/react/src/collapsible/panel/CollapsiblePanelDataAttributes.ts @@ -17,4 +17,8 @@ export enum CollapsiblePanelDataAttributes { * Present when the panel is animating out. */ endingStyle = TransitionStatusDataAttributes.endingStyle, + /** + * Present when the panel is hidden. + */ + hidden = 'data-hidden' } diff --git a/packages/react/src/utils/collapsibleOpenStateMapping.ts b/packages/react/src/utils/collapsibleOpenStateMapping.ts index df22f2c525b..641b2337edf 100644 --- a/packages/react/src/utils/collapsibleOpenStateMapping.ts +++ b/packages/react/src/utils/collapsibleOpenStateMapping.ts @@ -33,3 +33,21 @@ export const collapsibleOpenStateMapping = { } satisfies StateAttributesMapping<{ open: boolean; }>; + +export const panelOpenStateMapping = { + open: (open) => { + const panelHidden = !open; + const collapsibleStateMapping = collapsibleOpenStateMapping.open(open); + + if (panelHidden) { + return { + ...collapsibleStateMapping, + [CollapsiblePanelDataAttributes.hidden]: '', + }; + } + + return collapsibleStateMapping; + }, +} satisfies StateAttributesMapping<{ + open: boolean; +}>;