From a64950b01a8da511c2c1fa4d9dc1c9f765bf34d4 Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Tue, 3 Sep 2024 16:15:16 +0800 Subject: [PATCH 01/37] Provide Collapsible content width css var --- .../mui-base/src/Collapsible/Content/CollapsibleContent.tsx | 3 ++- .../src/Collapsible/Content/useCollapsibleContent.ts | 6 +++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/mui-base/src/Collapsible/Content/CollapsibleContent.tsx b/packages/mui-base/src/Collapsible/Content/CollapsibleContent.tsx index c258affd8..5d522d324 100644 --- a/packages/mui-base/src/Collapsible/Content/CollapsibleContent.tsx +++ b/packages/mui-base/src/Collapsible/Content/CollapsibleContent.tsx @@ -27,7 +27,7 @@ const CollapsibleContent = React.forwardRef(function CollapsibleContent( const { animated, mounted, open, contentId, setContentId, setMounted, setOpen, ownerState } = useCollapsibleContext(); - const { getRootProps, height } = useCollapsibleContent({ + const { getRootProps, height, width } = useCollapsibleContent({ animated, htmlHidden, id: contentId, @@ -48,6 +48,7 @@ const CollapsibleContent = React.forwardRef(function CollapsibleContent( ...otherProps, style: { '--collapsible-content-height': height ? `${height}px` : undefined, + '--collapsible-content-width': width ? `${width}px` : undefined, }, }, customStyleHookMapping: collapsibleStyleHookMapping, diff --git a/packages/mui-base/src/Collapsible/Content/useCollapsibleContent.ts b/packages/mui-base/src/Collapsible/Content/useCollapsibleContent.ts index 1af0eb3aa..e9e0b7324 100644 --- a/packages/mui-base/src/Collapsible/Content/useCollapsibleContent.ts +++ b/packages/mui-base/src/Collapsible/Content/useCollapsibleContent.ts @@ -52,6 +52,7 @@ export function useCollapsibleContent( const contentRef = React.useRef(null); const [height, setHeight] = React.useState(0); + const [width, setWidth] = React.useState(0); const latestAnimationNameRef = React.useRef('none'); const originalTransitionDurationStyleRef = React.useRef(); @@ -114,6 +115,7 @@ export function useCollapsibleContent( if (!isTransitioning || !(open || contextMounted)) { setHeight(rect.height); + setWidth(rect.width); } element.style.animationName = shouldCancelAnimation ? 'none' : originalAnimationName; @@ -264,8 +266,9 @@ export function useCollapsibleContent( () => ({ getRootProps, height, + width, }), - [getRootProps, height], + [getRootProps, height, width], ); } @@ -298,5 +301,6 @@ export namespace useCollapsibleContent { externalProps?: React.ComponentPropsWithRef<'button'>, ) => React.ComponentPropsWithRef<'button'>; height: number; + width: number; } } From ab49d59f2336dca8b980dee28cf711a0e367c67f Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Fri, 23 Aug 2024 00:00:26 +0800 Subject: [PATCH 02/37] New Accordion hooks and components --- docs/app/experiments/accordion.tsx | 191 +++++++++++++ docs/data/api/accordion-heading.json | 19 ++ docs/data/api/accordion-panel.json | 23 ++ docs/data/api/accordion-root.json | 30 ++ docs/data/api/accordion-section.json | 21 ++ docs/data/api/accordion-trigger.json | 19 ++ docs/data/api/use-accordion-root.json | 8 + docs/data/components/accordion/accordion.mdx | 16 ++ docs/data/pages.ts | 1 + .../accordion-heading/accordion-heading.json} | 0 .../accordion-panel/accordion-panel.json} | 0 .../accordion-root/accordion-root.json | 26 ++ .../accordion-section/accordion-section.json} | 9 - .../accordion-trigger/accordion-trigger.json} | 3 - .../checkbox-group-root.json | 24 -- .../radio-group-root/radio-group-root.json | 19 -- .../api-docs/radio-root/radio-root.json | 14 - .../use-checkbox-group-parent.json | 1 - .../use-checkbox-group-root.json | 1 - .../use-collapsible-content.json | 1 - .../use-collapsible-root.json | 1 - .../use-collapsible-trigger.json | 1 - .../use-composite-item.json | 1 - .../use-composite-list-item.json | 5 - .../use-radio-group-root.json | 1 - .../use-radio-root/use-radio-root.json | 1 - .../Heading/AccordionHeading.test.tsx | 77 ++++++ .../Accordion/Heading/AccordionHeading.tsx | 62 +++++ .../Accordion/Panel/AccordionPanel.test.tsx | 77 ++++++ .../src/Accordion/Panel/AccordionPanel.tsx | 97 +++++++ .../src/Accordion/Root/AccordionRoot.test.tsx | 16 ++ .../src/Accordion/Root/AccordionRoot.tsx | 173 ++++++++++++ .../Accordion/Root/AccordionRootContext.tsx | 22 ++ .../mui-base/src/Accordion/Root/styleHooks.ts | 0 .../src/Accordion/Root/useAccordionRoot.ts | 260 ++++++++++++++++++ .../Section/AccordionSection.test.tsx | 41 +++ .../Accordion/Section/AccordionSection.tsx | 192 +++++++++++++ .../Section/AccordionSectionContext.tsx | 24 ++ .../src/Accordion/Section/styleHooks.ts | 27 ++ .../Trigger/AccordionTrigger.test.tsx | 77 ++++++ .../Accordion/Trigger/AccordionTrigger.tsx | 78 ++++++ .../mui-base/src/Accordion/index.barrel.ts | 5 + packages/mui-base/src/Accordion/index.ts | 13 + .../Content/useCollapsibleContent.ts | 4 +- .../Trigger/useCollapsibleTrigger.ts | 6 +- packages/mui-base/src/index.ts | 1 + .../src/utils/defaultRenderFunctions.tsx | 4 + 47 files changed, 1607 insertions(+), 85 deletions(-) create mode 100644 docs/app/experiments/accordion.tsx create mode 100644 docs/data/api/accordion-heading.json create mode 100644 docs/data/api/accordion-panel.json create mode 100644 docs/data/api/accordion-root.json create mode 100644 docs/data/api/accordion-section.json create mode 100644 docs/data/api/accordion-trigger.json create mode 100644 docs/data/api/use-accordion-root.json create mode 100644 docs/data/components/accordion/accordion.mdx rename docs/{translations/api-docs/collapsible-trigger/collapsible-trigger.json => data/translations/api-docs/accordion-heading/accordion-heading.json} (100%) rename docs/{translations/api-docs/collapsible-content/collapsible-content.json => data/translations/api-docs/accordion-panel/accordion-panel.json} (100%) create mode 100644 docs/data/translations/api-docs/accordion-root/accordion-root.json rename docs/{translations/api-docs/collapsible-root/collapsible-root.json => data/translations/api-docs/accordion-section/accordion-section.json} (52%) rename docs/{translations/api-docs/radio-indicator/radio-indicator.json => data/translations/api-docs/accordion-trigger/accordion-trigger.json} (74%) delete mode 100644 docs/translations/api-docs/checkbox-group-root/checkbox-group-root.json delete mode 100644 docs/translations/api-docs/radio-group-root/radio-group-root.json delete mode 100644 docs/translations/api-docs/radio-root/radio-root.json delete mode 100644 docs/translations/api-docs/use-checkbox-group-parent/use-checkbox-group-parent.json delete mode 100644 docs/translations/api-docs/use-checkbox-group-root/use-checkbox-group-root.json delete mode 100644 docs/translations/api-docs/use-collapsible-content/use-collapsible-content.json delete mode 100644 docs/translations/api-docs/use-collapsible-root/use-collapsible-root.json delete mode 100644 docs/translations/api-docs/use-collapsible-trigger/use-collapsible-trigger.json delete mode 100644 docs/translations/api-docs/use-composite-item/use-composite-item.json delete mode 100644 docs/translations/api-docs/use-composite-list-item/use-composite-list-item.json delete mode 100644 docs/translations/api-docs/use-radio-group-root/use-radio-group-root.json delete mode 100644 docs/translations/api-docs/use-radio-root/use-radio-root.json create mode 100644 packages/mui-base/src/Accordion/Heading/AccordionHeading.test.tsx create mode 100644 packages/mui-base/src/Accordion/Heading/AccordionHeading.tsx create mode 100644 packages/mui-base/src/Accordion/Panel/AccordionPanel.test.tsx create mode 100644 packages/mui-base/src/Accordion/Panel/AccordionPanel.tsx create mode 100644 packages/mui-base/src/Accordion/Root/AccordionRoot.test.tsx create mode 100644 packages/mui-base/src/Accordion/Root/AccordionRoot.tsx create mode 100644 packages/mui-base/src/Accordion/Root/AccordionRootContext.tsx create mode 100644 packages/mui-base/src/Accordion/Root/styleHooks.ts create mode 100644 packages/mui-base/src/Accordion/Root/useAccordionRoot.ts create mode 100644 packages/mui-base/src/Accordion/Section/AccordionSection.test.tsx create mode 100644 packages/mui-base/src/Accordion/Section/AccordionSection.tsx create mode 100644 packages/mui-base/src/Accordion/Section/AccordionSectionContext.tsx create mode 100644 packages/mui-base/src/Accordion/Section/styleHooks.ts create mode 100644 packages/mui-base/src/Accordion/Trigger/AccordionTrigger.test.tsx create mode 100644 packages/mui-base/src/Accordion/Trigger/AccordionTrigger.tsx create mode 100644 packages/mui-base/src/Accordion/index.barrel.ts create mode 100644 packages/mui-base/src/Accordion/index.ts diff --git a/docs/app/experiments/accordion.tsx b/docs/app/experiments/accordion.tsx new file mode 100644 index 000000000..94e537a39 --- /dev/null +++ b/docs/app/experiments/accordion.tsx @@ -0,0 +1,191 @@ +import * as React from 'react'; +import Check from '@mui/icons-material/Check'; +import { useTheme } from '@mui/system'; +import * as Checkbox from '@base_ui/react/Checkbox'; +import * as Accordion from '@base_ui/react/Accordion'; + +export default function App() { + const [openMultiple, setOpenMultiple] = React.useState(true); + const [val, setVal] = React.useState(['one']); + return ( +
+ multiple `Accordion.Section`s can be open at the same time: + + + + + + +
+ +

Uncontrolled

+ + + + + Trigger 1 + + + This is the contents of Accordion.Panel 1 + + + + + + Trigger 2 + + + This is the contents of Accordion.Panel 2 + + + + + + + Trigger 3 + + + + This is the contents of Accordion.Panel 3 + + + + + + Trigger 4 + + + This is the contents of Accordion.Panel 4 + + + + + + Trigger 5 + + + This is the contents of Accordion.Panel 5 + + + + +
+ +

Controlled

+ + + + + Trigger 1 + + + This is the contents of Accordion.Panel 1, the value is "one" + + + + + + Trigger 2 + + + This is the contents of Accordion.Panel 2, the value is "two" + + + + + + Trigger 3 + + + This is the contents of Accordion.Panel 3, the value is "three" + + + + +
+ ); +} + +const grey = { + 100: '#E5EAF2', + 300: '#C7D0DD', + 500: '#9DA8B7', + 600: '#6B7A90', + 800: '#303740', + 900: '#1C2025', +}; + +function useIsDarkMode() { + const theme = useTheme(); + return theme.palette.mode === 'dark'; +} + +function Styles() { + // Replace this with your app logic for determining dark mode + const isDarkMode = useIsDarkMode(); + return ( + + ); +} diff --git a/docs/data/api/accordion-heading.json b/docs/data/api/accordion-heading.json new file mode 100644 index 000000000..84859add9 --- /dev/null +++ b/docs/data/api/accordion-heading.json @@ -0,0 +1,19 @@ +{ + "props": { + "className": { "type": { "name": "union", "description": "func
| string" } }, + "render": { "type": { "name": "union", "description": "element
| func" } } + }, + "name": "AccordionHeading", + "imports": [ + "import * as Accordion from '@base_ui/react/Accordion';\nconst AccordionHeading = Accordion.Heading;" + ], + "classes": [], + "spread": true, + "themeDefaultProps": true, + "muiName": "AccordionHeading", + "forwardsRefTo": "HTMLHeadingElement", + "filename": "/packages/mui-base/src/Accordion/Heading/AccordionHeading.tsx", + "inheritance": null, + "demos": "", + "cssComponent": false +} diff --git a/docs/data/api/accordion-panel.json b/docs/data/api/accordion-panel.json new file mode 100644 index 000000000..cc3d42099 --- /dev/null +++ b/docs/data/api/accordion-panel.json @@ -0,0 +1,23 @@ +{ + "props": { + "className": { "type": { "name": "union", "description": "func
| string" } }, + "htmlHidden": { + "type": { "name": "enum", "description": "'hidden'
| 'until-found'" }, + "default": "'hidden'" + }, + "render": { "type": { "name": "union", "description": "element
| func" } } + }, + "name": "AccordionPanel", + "imports": [ + "import * as Accordion from '@base_ui/react/Accordion';\nconst AccordionPanel = Accordion.Panel;" + ], + "classes": [], + "spread": true, + "themeDefaultProps": true, + "muiName": "AccordionPanel", + "forwardsRefTo": "HTMLDivElement", + "filename": "/packages/mui-base/src/Accordion/Panel/AccordionPanel.tsx", + "inheritance": null, + "demos": "", + "cssComponent": false +} diff --git a/docs/data/api/accordion-root.json b/docs/data/api/accordion-root.json new file mode 100644 index 000000000..64ea416c3 --- /dev/null +++ b/docs/data/api/accordion-root.json @@ -0,0 +1,30 @@ +{ + "props": { + "animated": { "type": { "name": "bool" }, "default": "true" }, + "className": { "type": { "name": "union", "description": "func
| string" } }, + "defaultValue": { + "type": { "name": "arrayOf", "description": "Array<number
| string>" }, + "default": "0" + }, + "disabled": { "type": { "name": "bool" }, "default": "false" }, + "onOpenChange": { "type": { "name": "func" } }, + "openMultiple": { "type": { "name": "bool" }, "default": "true" }, + "render": { "type": { "name": "union", "description": "element
| func" } }, + "value": { + "type": { "name": "arrayOf", "description": "Array<number
| string>" } + } + }, + "name": "AccordionRoot", + "imports": [ + "import * as Accordion from '@base_ui/react/Accordion';\nconst AccordionRoot = Accordion.Root;" + ], + "classes": [], + "spread": true, + "themeDefaultProps": true, + "muiName": "AccordionRoot", + "forwardsRefTo": "HTMLDivElement", + "filename": "/packages/mui-base/src/Accordion/Root/AccordionRoot.tsx", + "inheritance": null, + "demos": "", + "cssComponent": false +} diff --git a/docs/data/api/accordion-section.json b/docs/data/api/accordion-section.json new file mode 100644 index 000000000..e9f2e1d7d --- /dev/null +++ b/docs/data/api/accordion-section.json @@ -0,0 +1,21 @@ +{ + "props": { + "className": { "type": { "name": "union", "description": "func
| string" } }, + "disabled": { "type": { "name": "bool" }, "default": "false" }, + "onOpenChange": { "type": { "name": "func" } }, + "render": { "type": { "name": "union", "description": "element
| func" } } + }, + "name": "AccordionSection", + "imports": [ + "import * as Accordion from '@base_ui/react/Accordion';\nconst AccordionSection = Accordion.Section;" + ], + "classes": [], + "spread": true, + "themeDefaultProps": true, + "muiName": "AccordionSection", + "forwardsRefTo": "HTMLDivElement", + "filename": "/packages/mui-base/src/Accordion/Section/AccordionSection.tsx", + "inheritance": null, + "demos": "", + "cssComponent": false +} diff --git a/docs/data/api/accordion-trigger.json b/docs/data/api/accordion-trigger.json new file mode 100644 index 000000000..b2016c8d1 --- /dev/null +++ b/docs/data/api/accordion-trigger.json @@ -0,0 +1,19 @@ +{ + "props": { + "className": { "type": { "name": "union", "description": "func
| string" } }, + "render": { "type": { "name": "union", "description": "element
| func" } } + }, + "name": "AccordionTrigger", + "imports": [ + "import * as Accordion from '@base_ui/react/Accordion';\nconst AccordionTrigger = Accordion.Trigger;" + ], + "classes": [], + "spread": true, + "themeDefaultProps": true, + "muiName": "AccordionTrigger", + "forwardsRefTo": "HTMLButtonElement", + "filename": "/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.tsx", + "inheritance": null, + "demos": "", + "cssComponent": false +} diff --git a/docs/data/api/use-accordion-root.json b/docs/data/api/use-accordion-root.json new file mode 100644 index 000000000..53bd7e2ae --- /dev/null +++ b/docs/data/api/use-accordion-root.json @@ -0,0 +1,8 @@ +{ + "parameters": {}, + "returnValue": {}, + "name": "useAccordionRoot", + "filename": "/packages/mui-base/src/Accordion/Root/useAccordionRoot.ts", + "imports": ["import { useAccordionRoot } from '@base_ui/react/Accordion';"], + "demos": "" +} diff --git a/docs/data/components/accordion/accordion.mdx b/docs/data/components/accordion/accordion.mdx new file mode 100644 index 000000000..59558b41b --- /dev/null +++ b/docs/data/components/accordion/accordion.mdx @@ -0,0 +1,16 @@ +--- +productId: base-ui +title: React Accordion components +components: AccordionRoot, AccordionSection, AccordionHeading, AccordionTrigger, AccordionPanel +hooks: useAccordionRoot +githubLabel: 'component: accordion' +waiAria: https://www.w3.org/WAI/ARIA/apg/patterns/accordion/ +packageName: '@base_ui/react' +--- + +# Accordion + +

+ Accordion is a stacked set of interactive headings that each reveal an associated section of + content. +

diff --git a/docs/data/pages.ts b/docs/data/pages.ts index b82dc07f7..6cd2afbaf 100644 --- a/docs/data/pages.ts +++ b/docs/data/pages.ts @@ -22,6 +22,7 @@ const pages: readonly RouteMetadata[] = [ pathname: '/components', title: 'Components', children: [ + { pathname: '/components/react-accordion', title: 'Accordion' }, { pathname: '/components/react-alert-dialog', title: 'Alert Dialog' }, { pathname: '/components/react-checkbox', title: 'Checkbox' }, { pathname: '/components/react-checkbox-group', title: 'Checkbox Group' }, diff --git a/docs/translations/api-docs/collapsible-trigger/collapsible-trigger.json b/docs/data/translations/api-docs/accordion-heading/accordion-heading.json similarity index 100% rename from docs/translations/api-docs/collapsible-trigger/collapsible-trigger.json rename to docs/data/translations/api-docs/accordion-heading/accordion-heading.json diff --git a/docs/translations/api-docs/collapsible-content/collapsible-content.json b/docs/data/translations/api-docs/accordion-panel/accordion-panel.json similarity index 100% rename from docs/translations/api-docs/collapsible-content/collapsible-content.json rename to docs/data/translations/api-docs/accordion-panel/accordion-panel.json diff --git a/docs/data/translations/api-docs/accordion-root/accordion-root.json b/docs/data/translations/api-docs/accordion-root/accordion-root.json new file mode 100644 index 000000000..ceb5a5e1b --- /dev/null +++ b/docs/data/translations/api-docs/accordion-root/accordion-root.json @@ -0,0 +1,26 @@ +{ + "componentDescription": "", + "propDescriptions": { + "animated": { + "description": "If true, the component supports CSS/JS-based animations and transitions." + }, + "className": { + "description": "Class names applied to the element or a function that returns them based on the component's state." + }, + "defaultValue": { + "description": "The default value representing the currently open Accordion.Section This is the uncontrolled counterpart of value." + }, + "disabled": { "description": "If true, the component is disabled." }, + "onOpenChange": { + "description": "Callback fired when an Accordion section is opened or closed. The value representing the involved section is provided as an argument." + }, + "openMultiple": { + "description": "Whether multiple Accordion sections can be opened at the same time" + }, + "render": { "description": "A function to customize rendering of the component." }, + "value": { + "description": "The value of the currently open Accordion.Section This is the controlled counterpart of defaultValue." + } + }, + "classDescriptions": {} +} diff --git a/docs/translations/api-docs/collapsible-root/collapsible-root.json b/docs/data/translations/api-docs/accordion-section/accordion-section.json similarity index 52% rename from docs/translations/api-docs/collapsible-root/collapsible-root.json rename to docs/data/translations/api-docs/accordion-section/accordion-section.json index b45c0ae2b..121ef9081 100644 --- a/docs/translations/api-docs/collapsible-root/collapsible-root.json +++ b/docs/data/translations/api-docs/accordion-section/accordion-section.json @@ -1,20 +1,11 @@ { "componentDescription": "", "propDescriptions": { - "animated": { - "description": "If true, the component supports CSS/JS-based animations and transitions." - }, "className": { "description": "Class names applied to the element or a function that returns them based on the component's state." }, - "defaultOpen": { - "description": "If true, the Collapsible is initially open. This is the uncontrolled counterpart of open." - }, "disabled": { "description": "If true, the component is disabled." }, "onOpenChange": { "description": "Callback fired when the Collapsible is opened or closed." }, - "open": { - "description": "If true, the Collapsible is initially open. This is the controlled counterpart of defaultOpen." - }, "render": { "description": "A function to customize rendering of the component." } }, "classDescriptions": {} diff --git a/docs/translations/api-docs/radio-indicator/radio-indicator.json b/docs/data/translations/api-docs/accordion-trigger/accordion-trigger.json similarity index 74% rename from docs/translations/api-docs/radio-indicator/radio-indicator.json rename to docs/data/translations/api-docs/accordion-trigger/accordion-trigger.json index 35cfbe606..4bc12cf1e 100644 --- a/docs/translations/api-docs/radio-indicator/radio-indicator.json +++ b/docs/data/translations/api-docs/accordion-trigger/accordion-trigger.json @@ -4,9 +4,6 @@ "className": { "description": "Class names applied to the element or a function that returns them based on the component's state." }, - "keepMounted": { - "description": "Whether the component should be kept mounted when not checked." - }, "render": { "description": "A function to customize rendering of the component." } }, "classDescriptions": {} diff --git a/docs/translations/api-docs/checkbox-group-root/checkbox-group-root.json b/docs/translations/api-docs/checkbox-group-root/checkbox-group-root.json deleted file mode 100644 index b94a0873b..000000000 --- a/docs/translations/api-docs/checkbox-group-root/checkbox-group-root.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "componentDescription": "The foundation for building custom-styled checkbox groups.", - "propDescriptions": { - "allValues": { "description": "All values of the checkboxes in the group." }, - "className": { - "description": "Class names applied to the element or a function that returns them based on the component's state." - }, - "defaultValue": { - "description": "The default checked values of the checkbox group. Use when uncontrolled." - }, - "disabled": { "description": "Whether the checkbox group is disabled." }, - "onValueChange": { - "description": "A callback function that is called when the value of the checkbox group changes. Use when controlled." - }, - "preserveChildStates": { - "description": "Whether the parent checkbox should preserve its child states when checked/unchecked, leading to a tri-state checkbox group." - }, - "render": { "description": "A function to customize rendering of the component." }, - "value": { - "description": "The currently checked values of the checkbox group. Use when controlled." - } - }, - "classDescriptions": {} -} diff --git a/docs/translations/api-docs/radio-group-root/radio-group-root.json b/docs/translations/api-docs/radio-group-root/radio-group-root.json deleted file mode 100644 index bbf977c55..000000000 --- a/docs/translations/api-docs/radio-group-root/radio-group-root.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "componentDescription": "", - "propDescriptions": { - "className": { - "description": "Class names applied to the element or a function that returns them based on the component's state." - }, - "defaultValue": { - "description": "The default value of the selected radio button. Use when uncontrolled." - }, - "disabled": { "description": "Determines if the radio group is disabled." }, - "name": { "description": "The name of the radio group submitted with the form data." }, - "onValueChange": { "description": "Callback fired when the value changes." }, - "readOnly": { "description": "Determines if the radio group is readonly." }, - "render": { "description": "A function to customize rendering of the component." }, - "required": { "description": "Determines if the radio group is required." }, - "value": { "description": "The value of the selected radio button. Use when controlled." } - }, - "classDescriptions": {} -} diff --git a/docs/translations/api-docs/radio-root/radio-root.json b/docs/translations/api-docs/radio-root/radio-root.json deleted file mode 100644 index 04b7711e7..000000000 --- a/docs/translations/api-docs/radio-root/radio-root.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "componentDescription": "", - "propDescriptions": { - "className": { - "description": "Class names applied to the element or a function that returns them based on the component's state." - }, - "disabled": { "description": "Determines if the radio is disabled." }, - "readOnly": { "description": "Determines if the radio is readonly." }, - "render": { "description": "A function to customize rendering of the component." }, - "required": { "description": "Determines if the radio is required." }, - "value": { "description": "The unique identifying value of the radio in a group." } - }, - "classDescriptions": {} -} diff --git a/docs/translations/api-docs/use-checkbox-group-parent/use-checkbox-group-parent.json b/docs/translations/api-docs/use-checkbox-group-parent/use-checkbox-group-parent.json deleted file mode 100644 index e3eb65c6e..000000000 --- a/docs/translations/api-docs/use-checkbox-group-parent/use-checkbox-group-parent.json +++ /dev/null @@ -1 +0,0 @@ -{ "hookDescription": "", "parametersDescriptions": {}, "returnValueDescriptions": {} } diff --git a/docs/translations/api-docs/use-checkbox-group-root/use-checkbox-group-root.json b/docs/translations/api-docs/use-checkbox-group-root/use-checkbox-group-root.json deleted file mode 100644 index e3eb65c6e..000000000 --- a/docs/translations/api-docs/use-checkbox-group-root/use-checkbox-group-root.json +++ /dev/null @@ -1 +0,0 @@ -{ "hookDescription": "", "parametersDescriptions": {}, "returnValueDescriptions": {} } diff --git a/docs/translations/api-docs/use-collapsible-content/use-collapsible-content.json b/docs/translations/api-docs/use-collapsible-content/use-collapsible-content.json deleted file mode 100644 index e3eb65c6e..000000000 --- a/docs/translations/api-docs/use-collapsible-content/use-collapsible-content.json +++ /dev/null @@ -1 +0,0 @@ -{ "hookDescription": "", "parametersDescriptions": {}, "returnValueDescriptions": {} } diff --git a/docs/translations/api-docs/use-collapsible-root/use-collapsible-root.json b/docs/translations/api-docs/use-collapsible-root/use-collapsible-root.json deleted file mode 100644 index e3eb65c6e..000000000 --- a/docs/translations/api-docs/use-collapsible-root/use-collapsible-root.json +++ /dev/null @@ -1 +0,0 @@ -{ "hookDescription": "", "parametersDescriptions": {}, "returnValueDescriptions": {} } diff --git a/docs/translations/api-docs/use-collapsible-trigger/use-collapsible-trigger.json b/docs/translations/api-docs/use-collapsible-trigger/use-collapsible-trigger.json deleted file mode 100644 index e3eb65c6e..000000000 --- a/docs/translations/api-docs/use-collapsible-trigger/use-collapsible-trigger.json +++ /dev/null @@ -1 +0,0 @@ -{ "hookDescription": "", "parametersDescriptions": {}, "returnValueDescriptions": {} } diff --git a/docs/translations/api-docs/use-composite-item/use-composite-item.json b/docs/translations/api-docs/use-composite-item/use-composite-item.json deleted file mode 100644 index e3eb65c6e..000000000 --- a/docs/translations/api-docs/use-composite-item/use-composite-item.json +++ /dev/null @@ -1 +0,0 @@ -{ "hookDescription": "", "parametersDescriptions": {}, "returnValueDescriptions": {} } diff --git a/docs/translations/api-docs/use-composite-list-item/use-composite-list-item.json b/docs/translations/api-docs/use-composite-list-item/use-composite-list-item.json deleted file mode 100644 index 6b0431979..000000000 --- a/docs/translations/api-docs/use-composite-list-item/use-composite-list-item.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "hookDescription": "Used to register a list item and its index (DOM position) in the\n`CompositeList`.", - "parametersDescriptions": {}, - "returnValueDescriptions": {} -} diff --git a/docs/translations/api-docs/use-radio-group-root/use-radio-group-root.json b/docs/translations/api-docs/use-radio-group-root/use-radio-group-root.json deleted file mode 100644 index e3eb65c6e..000000000 --- a/docs/translations/api-docs/use-radio-group-root/use-radio-group-root.json +++ /dev/null @@ -1 +0,0 @@ -{ "hookDescription": "", "parametersDescriptions": {}, "returnValueDescriptions": {} } diff --git a/docs/translations/api-docs/use-radio-root/use-radio-root.json b/docs/translations/api-docs/use-radio-root/use-radio-root.json deleted file mode 100644 index e3eb65c6e..000000000 --- a/docs/translations/api-docs/use-radio-root/use-radio-root.json +++ /dev/null @@ -1 +0,0 @@ -{ "hookDescription": "", "parametersDescriptions": {}, "returnValueDescriptions": {} } diff --git a/packages/mui-base/src/Accordion/Heading/AccordionHeading.test.tsx b/packages/mui-base/src/Accordion/Heading/AccordionHeading.test.tsx new file mode 100644 index 000000000..6a219aa06 --- /dev/null +++ b/packages/mui-base/src/Accordion/Heading/AccordionHeading.test.tsx @@ -0,0 +1,77 @@ +import * as React from 'react'; +// import { expect } from 'chai'; +// import { spy } from 'sinon'; +import { createRenderer /* , act */ } from '@mui/internal-test-utils'; +import * as Accordion from '@base_ui/react/Accordion'; +import * as Collapsible from '@base_ui/react/Collapsible'; +import { describeConformance } from '../../../test/describeConformance'; + +const { AccordionRootContext, AccordionSectionContext } = Accordion; + +const { CollapsibleContext } = Collapsible; + +const accordionRootContextValue: Accordion.Root.Context = { + accordionSectionRefs: { current: [] }, + animated: false, + direction: 'ltr', + disabled: false, + handleOpenChange() {}, + orientation: 'vertical', + ownerState: { + value: [0], + disabled: false, + orientation: 'vertical', + }, + value: [0], +}; + +const accordionSectionContextValue: Accordion.Section.Context = { + open: true, + ownerState: { + value: [0], + disabled: false, + index: 0, + open: true, + orientation: 'vertical', + transitionStatus: undefined, + }, +}; + +const collapsibleContextValue: Collapsible.Root.Context = { + animated: false, + contentId: ':content:', + disabled: false, + mounted: true, + open: true, + setContentId() {}, + setMounted() {}, + setOpen() {}, + transitionStatus: undefined, + ownerState: { + open: true, + disabled: false, + transitionStatus: undefined, + }, +}; + +describe('', () => { + const { render } = createRenderer(); + + describeConformance(, () => ({ + inheritComponent: 'h3', + render: (node) => { + const { container, ...other } = render( + + + + {node} + + + , + ); + + return { container, ...other }; + }, + refInstanceof: window.HTMLHeadingElement, + })); +}); diff --git a/packages/mui-base/src/Accordion/Heading/AccordionHeading.tsx b/packages/mui-base/src/Accordion/Heading/AccordionHeading.tsx new file mode 100644 index 000000000..4bae16fd5 --- /dev/null +++ b/packages/mui-base/src/Accordion/Heading/AccordionHeading.tsx @@ -0,0 +1,62 @@ +'use client'; +import * as React from 'react'; +import PropTypes from 'prop-types'; +import { BaseUIComponentProps } from '../../utils/types'; +import { useComponentRenderer } from '../../utils/useComponentRenderer'; +import type { AccordionSection } from '../Section/AccordionSection'; +import { useAccordionSectionContext } from '../Section/AccordionSectionContext'; +import { accordionStyleHookMapping } from '../Section/styleHooks'; +/** + * + * Demos: + * + * - [Accordion](https://base-ui.netlify.app/components/react-accordion/) + * + * API: + * + * - [AccordionHeading API](https://base-ui.netlify.app/components/react-accordion/#api-reference-AccordionHeading) + */ +const AccordionHeading = React.forwardRef(function AccordionHeading( + props: AccordionHeading.Props, + forwardedRef: React.ForwardedRef, +) { + const { render, className, ...otherProps } = props; + + const { ownerState } = useAccordionSectionContext(); + + const { renderElement } = useComponentRenderer({ + render: render ?? 'h3', + ownerState, + className, + ref: forwardedRef, + extraProps: otherProps, + customStyleHookMapping: accordionStyleHookMapping, + }); + + return renderElement(); +}); + +AccordionHeading.propTypes /* remove-proptypes */ = { + // ┌────────────────────────────── Warning ──────────────────────────────┐ + // │ These PropTypes are generated from the TypeScript type definitions. │ + // │ To update them, edit the TypeScript types and run `pnpm proptypes`. │ + // └─────────────────────────────────────────────────────────────────────┘ + /** + * @ignore + */ + children: PropTypes.node, + /** + * Class names applied to the element or a function that returns them based on the component's state. + */ + className: PropTypes.oneOfType([PropTypes.func, PropTypes.string]), + /** + * A function to customize rendering of the component. + */ + render: PropTypes.oneOfType([PropTypes.element, PropTypes.func]), +} as any; + +export { AccordionHeading }; + +export namespace AccordionHeading { + export interface Props extends BaseUIComponentProps<'h3', AccordionSection.OwnerState> {} +} diff --git a/packages/mui-base/src/Accordion/Panel/AccordionPanel.test.tsx b/packages/mui-base/src/Accordion/Panel/AccordionPanel.test.tsx new file mode 100644 index 000000000..f03b91751 --- /dev/null +++ b/packages/mui-base/src/Accordion/Panel/AccordionPanel.test.tsx @@ -0,0 +1,77 @@ +import * as React from 'react'; +// import { expect } from 'chai'; +// import { spy } from 'sinon'; +import { createRenderer /* , act */ } from '@mui/internal-test-utils'; +import * as Accordion from '@base_ui/react/Accordion'; +import * as Collapsible from '@base_ui/react/Collapsible'; +import { describeConformance } from '../../../test/describeConformance'; + +const { AccordionRootContext, AccordionSectionContext } = Accordion; + +const { CollapsibleContext } = Collapsible; + +const accordionRootContextValue: Accordion.Root.Context = { + accordionSectionRefs: { current: [] }, + animated: false, + direction: 'ltr', + disabled: false, + handleOpenChange() {}, + orientation: 'vertical', + ownerState: { + value: [0], + disabled: false, + orientation: 'vertical', + }, + value: [0], +}; + +const accordionSectionContextValue: Accordion.Section.Context = { + open: true, + ownerState: { + value: [0], + disabled: false, + index: 0, + open: true, + orientation: 'vertical', + transitionStatus: undefined, + }, +}; + +const collapsibleContextValue: Collapsible.Root.Context = { + animated: false, + contentId: ':content:', + disabled: false, + mounted: true, + open: true, + setContentId() {}, + setMounted() {}, + setOpen() {}, + transitionStatus: undefined, + ownerState: { + open: true, + disabled: false, + transitionStatus: undefined, + }, +}; + +describe('', () => { + const { render } = createRenderer(); + + describeConformance(, () => ({ + inheritComponent: 'div', + render: (node) => { + const { container, ...other } = render( + + + + {node} + + + , + ); + + return { container, ...other }; + }, + refInstanceof: window.HTMLDivElement, + })); +}); diff --git a/packages/mui-base/src/Accordion/Panel/AccordionPanel.tsx b/packages/mui-base/src/Accordion/Panel/AccordionPanel.tsx new file mode 100644 index 000000000..795e8ea02 --- /dev/null +++ b/packages/mui-base/src/Accordion/Panel/AccordionPanel.tsx @@ -0,0 +1,97 @@ +'use client'; +import * as React from 'react'; +import PropTypes from 'prop-types'; +import { BaseUIComponentProps } from '../../utils/types'; +import { useComponentRenderer } from '../../utils/useComponentRenderer'; +import { useCollapsibleContext } from '../../Collapsible/Root/CollapsibleContext'; +import { useCollapsibleContent } from '../../Collapsible/Content/useCollapsibleContent'; +import { useAccordionRootContext } from '../Root/AccordionRootContext'; +import type { AccordionSection } from '../Section/AccordionSection'; +import { useAccordionSectionContext } from '../Section/AccordionSectionContext'; +import { accordionStyleHookMapping } from '../Section/styleHooks'; +/** + * + * Demos: + * + * - [Accordion](https://base-ui.netlify.app/components/react-accordion/) + * + * API: + * + * - [AccordionPanel API](https://base-ui.netlify.app/components/react-accordion/#api-reference-AccordionPanel) + */ +const AccordionPanel = React.forwardRef(function AccordionPanel( + props: AccordionPanel.Props, + forwardedRef: React.ForwardedRef, +) { + const { className, htmlHidden: htmlHiddenProp, render, ...otherProps } = props; + + const { animated, mounted, open, contentId, setContentId, setMounted, setOpen } = + useCollapsibleContext(); + + const { htmlHidden } = useAccordionRootContext(); + + const { getRootProps, height, width } = useCollapsibleContent({ + animated, + htmlHidden: htmlHiddenProp || htmlHidden, + id: contentId, + mounted, + open, + ref: forwardedRef, + setContentId, + setMounted, + setOpen, + }); + + const { ownerState, triggerId } = useAccordionSectionContext(); + + const { renderElement } = useComponentRenderer({ + propGetter: getRootProps, + render: render ?? 'div', + ownerState, + className, + extraProps: { + ...otherProps, + 'aria-labelledby': triggerId, + role: 'region', + style: { + '--accordion-content-height': height ? `${height}px` : undefined, + '--accordion-content-width': width ? `${width}px` : undefined, + }, + }, + customStyleHookMapping: accordionStyleHookMapping, + }); + + return renderElement(); +}); + +AccordionPanel.propTypes /* remove-proptypes */ = { + // ┌────────────────────────────── Warning ──────────────────────────────┐ + // │ These PropTypes are generated from the TypeScript type definitions. │ + // │ To update them, edit the TypeScript types and run `pnpm proptypes`. │ + // └─────────────────────────────────────────────────────────────────────┘ + /** + * @ignore + */ + children: PropTypes.node, + /** + * Class names applied to the element or a function that returns them based on the component's state. + */ + className: PropTypes.oneOfType([PropTypes.func, PropTypes.string]), + /** + * The hidden state when closed + * @default 'hidden' + */ + htmlHidden: PropTypes.oneOf(['hidden', 'until-found']), + /** + * A function to customize rendering of the component. + */ + render: PropTypes.oneOfType([PropTypes.element, PropTypes.func]), +} as any; + +export { AccordionPanel }; + +export namespace AccordionPanel { + export interface Props + extends BaseUIComponentProps<'div', AccordionSection.OwnerState>, + Pick {} +} diff --git a/packages/mui-base/src/Accordion/Root/AccordionRoot.test.tsx b/packages/mui-base/src/Accordion/Root/AccordionRoot.test.tsx new file mode 100644 index 000000000..6597bf2e1 --- /dev/null +++ b/packages/mui-base/src/Accordion/Root/AccordionRoot.test.tsx @@ -0,0 +1,16 @@ +import * as React from 'react'; +// import { expect } from 'chai'; +// import { spy } from 'sinon'; +import { createRenderer /* , act */ } from '@mui/internal-test-utils'; +import * as Accordion from '@base_ui/react/Accordion'; +import { describeConformance } from '../../../test/describeConformance'; + +describe('', () => { + const { render } = createRenderer(); + + describeConformance(, () => ({ + inheritComponent: 'div', + render, + refInstanceof: window.HTMLDivElement, + })); +}); diff --git a/packages/mui-base/src/Accordion/Root/AccordionRoot.tsx b/packages/mui-base/src/Accordion/Root/AccordionRoot.tsx new file mode 100644 index 000000000..660bc6bd5 --- /dev/null +++ b/packages/mui-base/src/Accordion/Root/AccordionRoot.tsx @@ -0,0 +1,173 @@ +'use client'; +import * as React from 'react'; +import PropTypes from 'prop-types'; +import { BaseUIComponentProps } from '../../utils/types'; +import { useComponentRenderer } from '../../utils/useComponentRenderer'; +import type { useCollapsibleContent } from '../../Collapsible/Content/useCollapsibleContent'; +import { CompositeList } from '../../Composite/List/CompositeList'; +import { useAccordionRoot } from './useAccordionRoot'; +import { AccordionRootContext } from './AccordionRootContext'; +/** + * + * Demos: + * + * - [Accordion](https://base-ui.netlify.app/components/react-accordion/) + * + * API: + * + * - [AccordionRoot API](https://base-ui.netlify.app/components/react-accordion/#api-reference-AccordionRoot) + */ +const AccordionRoot = React.forwardRef(function AccordionRoot( + props: AccordionRoot.Props, + forwardedRef: React.ForwardedRef, +) { + const { + animated, + className, + direction, + disabled = false, + htmlHidden, + onOpenChange, + openMultiple = true, + orientation, + value, + defaultValue, + render, + ...otherProps + } = props; + + const { getRootProps, ...accordion } = useAccordionRoot({ + animated, + direction, + disabled, + defaultValue, + orientation, + onOpenChange, + openMultiple, + value, + }); + + const ownerState: AccordionRoot.OwnerState = React.useMemo( + () => ({ + value: accordion.value, + disabled: accordion.disabled, + orientation: accordion.orientation, + // transitionStatus: accordion.transitionStatus, + }), + [accordion.value, accordion.disabled, accordion.orientation], + ); + + const contextValue: AccordionRoot.Context = React.useMemo( + () => ({ + ...accordion, + htmlHidden, + ownerState, + }), + [accordion, htmlHidden, ownerState], + ); + + const { renderElement } = useComponentRenderer({ + propGetter: getRootProps, + render: render ?? 'div', + className, + ownerState, + ref: forwardedRef, + extraProps: otherProps, + customStyleHookMapping: { + disabled: (isDisabled) => { + if (isDisabled) { + return { 'data-disabled': '' }; + } + return null; + }, + value: () => null, + }, + }); + + return ( + + {renderElement()} + + ); +}); + +AccordionRoot.propTypes /* remove-proptypes */ = { + // ┌────────────────────────────── Warning ──────────────────────────────┐ + // │ These PropTypes are generated from the TypeScript type definitions. │ + // │ To update them, edit the TypeScript types and run `pnpm proptypes`. │ + // └─────────────────────────────────────────────────────────────────────┘ + /** + * If `true`, the component supports CSS/JS-based animations and transitions. + * @default true + */ + animated: PropTypes.bool, + /** + * Class names applied to the element or a function that returns them based on the component's state. + */ + className: PropTypes.oneOfType([PropTypes.func, PropTypes.string]), + /** + * The default value representing the currently open `Accordion.Section` + * This is the uncontrolled counterpart of `value`. + * @default 0 + */ + defaultValue: PropTypes.arrayOf( + PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired, + ), + /** + * @default 'ltr' + */ + direction: PropTypes.oneOf(['ltr', 'rtl']), + /** + * If `true`, the component is disabled. + * @default false + */ + disabled: PropTypes.bool, + /** + * @ignore + */ + htmlHidden: PropTypes.oneOf(['hidden', 'until-found']), + /** + * Callback fired when an Accordion section is opened or closed. + * The value representing the involved section is provided as an argument. + */ + onOpenChange: PropTypes.func, + /** + * Whether multiple Accordion sections can be opened at the same time + * @default true + */ + openMultiple: PropTypes.bool, + /** + * @default 'vertical' + */ + orientation: PropTypes.oneOf(['horizontal', 'vertical']), + /** + * A function to customize rendering of the component. + */ + render: PropTypes.oneOfType([PropTypes.element, PropTypes.func]), + /** + * The value of the currently open `Accordion.Section` + * This is the controlled counterpart of `defaultValue`. + */ + value: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired), +} as any; + +export { AccordionRoot }; + +export namespace AccordionRoot { + export interface Context extends Omit { + ownerState: OwnerState; + htmlHidden?: useCollapsibleContent.HtmlHiddenType; + } + + export interface OwnerState { + value: useAccordionRoot.Value; + disabled: boolean; + orientation: useAccordionRoot.Orientation; + } + + export interface Props + extends useAccordionRoot.Parameters, + BaseUIComponentProps { + htmlHidden?: useCollapsibleContent.HtmlHiddenType; + } +} diff --git a/packages/mui-base/src/Accordion/Root/AccordionRootContext.tsx b/packages/mui-base/src/Accordion/Root/AccordionRootContext.tsx new file mode 100644 index 000000000..0f862f8dd --- /dev/null +++ b/packages/mui-base/src/Accordion/Root/AccordionRootContext.tsx @@ -0,0 +1,22 @@ +'use client'; +import * as React from 'react'; +import type { AccordionRoot } from './AccordionRoot'; + +/** + * @ignore - internal component. + */ +export const AccordionRootContext = React.createContext( + undefined, +); + +if (process.env.NODE_ENV !== 'production') { + AccordionRootContext.displayName = 'AccordionRootContext'; +} + +export function useAccordionRootContext() { + const context = React.useContext(AccordionRootContext); + if (context === undefined) { + throw new Error('useAccordionRootContext must be used inside a Accordion component'); + } + return context; +} diff --git a/packages/mui-base/src/Accordion/Root/styleHooks.ts b/packages/mui-base/src/Accordion/Root/styleHooks.ts new file mode 100644 index 000000000..e69de29bb diff --git a/packages/mui-base/src/Accordion/Root/useAccordionRoot.ts b/packages/mui-base/src/Accordion/Root/useAccordionRoot.ts new file mode 100644 index 000000000..7a591fb2d --- /dev/null +++ b/packages/mui-base/src/Accordion/Root/useAccordionRoot.ts @@ -0,0 +1,260 @@ +'use client'; +import * as React from 'react'; +import { mergeReactProps } from '../../utils/mergeReactProps'; +import { NOOP } from '../../utils/noop'; +import { useControlled } from '../../utils/useControlled'; +import { ARROW_DOWN, ARROW_UP, ARROW_RIGHT, ARROW_LEFT } from '../../Composite/composite'; + +const SUPPORTED_KEYS = [ARROW_DOWN, ARROW_UP, ARROW_RIGHT, ARROW_LEFT, 'Home', 'End']; + +function isDisabled(element: HTMLElement | null) { + return ( + element === null || + element.hasAttribute('disabled') || + element.getAttribute('data-disabled') === 'true' + ); +} +/** + * + * Demos: + * + * - [Accordion](https://mui.com/base-ui/react-accordion/#hook) + * + * API: + * + * - [useAccordionRoot API](https://mui.com/base-ui/react-accordion/hooks-api/#use-accordion-root) + */ +export function useAccordionRoot( + parameters: useAccordionRoot.Parameters, +): useAccordionRoot.ReturnValue { + const { + animated = true, + disabled = false, + direction = 'ltr', + onOpenChange = NOOP, + orientation = 'vertical', + openMultiple = true, + value: valueParam, + defaultValue, + } = parameters; + + const accordionSectionRefs = React.useRef<(HTMLElement | null)[]>([]); + + const [value, setValue] = useControlled({ + controlled: valueParam, + default: valueParam ?? defaultValue ?? [], + name: 'Accordion', + state: 'value', + }); + + const handleOpenChange = React.useCallback( + (newValue: number | string, nextOpen: boolean) => { + // console.group('useAccordionRoot handleOpenChange'); + // console.log('newValue', newValue, 'nextOpen', nextOpen, 'openValues', value); + if (!openMultiple) { + const nextValue = value[0] === newValue ? [] : [newValue]; + setValue(nextValue); + onOpenChange(nextValue); + } else if (nextOpen) { + const nextOpenValues = value.slice(); + nextOpenValues.push(newValue); + // console.log('nextOpenValues', nextOpenValues); + setValue(nextOpenValues); + onOpenChange(nextOpenValues); + } else { + const nextOpenValues = value.filter((v) => v !== newValue); + // console.log('nextOpenValues', nextOpenValues); + setValue(nextOpenValues); + onOpenChange(nextOpenValues); + } + // console.groupEnd(); + }, + [onOpenChange, openMultiple, setValue, value], + ); + + const getRootProps = React.useCallback( + (externalProps = {}) => { + const isRtl = direction === 'rtl'; + const isHorizontal = orientation === 'horizontal'; + return mergeReactProps(externalProps, { + dir: direction, + role: 'region', + onKeyDown(event: React.KeyboardEvent) { + if (!SUPPORTED_KEYS.includes(event.key)) { + return; + } + + // console.group('onKeyDown'); + const { current: accordionSectionElements } = accordionSectionRefs; + + // TODO: memo this outside + const triggers: HTMLButtonElement[] = []; + + for (let i = 0; i < accordionSectionElements.length; i += 1) { + const section = accordionSectionElements[i]; + if (!isDisabled(section)) { + const trigger = section?.querySelector('[type="button"]') as HTMLButtonElement; + if (!isDisabled(trigger)) { + triggers.push(trigger); + } + } + } + + const numOfEnabledTriggers = triggers.length; + const lastIndex = numOfEnabledTriggers - 1; + + let nextIndex = -1; + + const thisIndex = triggers.indexOf(event.target as HTMLButtonElement); + + function toNext() { + nextIndex = Math.min(thisIndex + 1, lastIndex); + } + + function toPrev() { + nextIndex = thisIndex - 1; + } + + switch (event.key) { + case ARROW_DOWN: + if (!isHorizontal) { + toNext(); + } + break; + case ARROW_UP: + if (!isHorizontal) { + toPrev(); + } + break; + case ARROW_RIGHT: + if (isHorizontal) { + if (isRtl) { + toPrev(); + } else { + toNext(); + } + } + break; + case ARROW_LEFT: + if (isHorizontal) { + if (isRtl) { + toNext(); + } else { + toPrev(); + } + } + break; + case 'Home': + nextIndex = 0; + break; + case 'End': + nextIndex = lastIndex; + break; + default: + break; + } + + if (nextIndex > -1) { + // console.log('focus nextIndex', nextIndex); + triggers[nextIndex].focus(); + } + // console.groupEnd(); + }, + }); + }, + [direction, orientation], + ); + + return React.useMemo( + () => ({ + getRootProps, + accordionSectionRefs, + animated, + direction, + disabled, + handleOpenChange, + orientation, + value, + }), + [ + getRootProps, + accordionSectionRefs, + animated, + direction, + disabled, + handleOpenChange, + orientation, + value, + ], + ); +} + +export namespace useAccordionRoot { + export type Value = readonly (string | number)[]; + + export type Direction = 'ltr' | 'rtl'; + + export type Orientation = 'horizontal' | 'vertical'; + + export interface Parameters { + /** + * The value of the currently open `Accordion.Section` + * This is the controlled counterpart of `defaultValue`. + */ + value?: Value; + /** + * The default value representing the currently open `Accordion.Section` + * This is the uncontrolled counterpart of `value`. + * @default 0 + */ + defaultValue?: Value; + /** + * If `true`, the component supports CSS/JS-based animations and transitions. + * @default true + */ + animated?: boolean; + /** + * If `true`, the component is disabled. + * @default false + */ + disabled?: boolean; + /** + * @default 'ltr' + */ + direction?: Direction; + /** + * Callback fired when an Accordion section is opened or closed. + * The value representing the involved section is provided as an argument. + */ + onOpenChange?: (value: Value) => void; + /** + * Whether multiple Accordion sections can be opened at the same time + * @default true + */ + openMultiple?: boolean; + /** + * @default 'vertical' + */ + orientation?: Orientation; + } + + export interface ReturnValue { + getRootProps: ( + externalProps?: React.ComponentPropsWithRef<'div'>, + ) => React.ComponentPropsWithRef<'div'>; + accordionSectionRefs: React.MutableRefObject<(HTMLElement | null)[]>; + animated: boolean; + direction: Direction; + /** + * The disabled state of the Accordion + */ + disabled: boolean; + handleOpenChange: (value: number | string, nextOpen: boolean) => void; + orientation: Orientation; + /** + * The open state of the Accordion represented by an array of the values + * of all open ``s + */ + value: Value; + } +} diff --git a/packages/mui-base/src/Accordion/Section/AccordionSection.test.tsx b/packages/mui-base/src/Accordion/Section/AccordionSection.test.tsx new file mode 100644 index 000000000..355a16839 --- /dev/null +++ b/packages/mui-base/src/Accordion/Section/AccordionSection.test.tsx @@ -0,0 +1,41 @@ +import * as React from 'react'; +// import { expect } from 'chai'; +// import { spy } from 'sinon'; +import { createRenderer /* , act */ } from '@mui/internal-test-utils'; +import * as Accordion from '@base_ui/react/Accordion'; +import { describeConformance } from '../../../test/describeConformance'; + +const { AccordionRootContext } = Accordion; + +const accordionRootContextValue: Accordion.Root.Context = { + accordionSectionRefs: { current: [] }, + animated: false, + direction: 'ltr', + disabled: false, + handleOpenChange() {}, + orientation: 'vertical', + ownerState: { + value: [0], + disabled: false, + orientation: 'vertical', + }, + value: [0], +}; + +describe('', () => { + const { render } = createRenderer(); + + describeConformance(, () => ({ + inheritComponent: 'div', + render: (node) => { + const { container, ...other } = render( + + {node} + , + ); + + return { container, ...other }; + }, + refInstanceof: window.HTMLDivElement, + })); +}); diff --git a/packages/mui-base/src/Accordion/Section/AccordionSection.tsx b/packages/mui-base/src/Accordion/Section/AccordionSection.tsx new file mode 100644 index 000000000..d510a1c14 --- /dev/null +++ b/packages/mui-base/src/Accordion/Section/AccordionSection.tsx @@ -0,0 +1,192 @@ +'use client'; +import * as React from 'react'; +import PropTypes from 'prop-types'; +import { useForkRef } from '../../utils/useForkRef'; +import { BaseUIComponentProps } from '../../utils/types'; +import { useComponentRenderer } from '../../utils/useComponentRenderer'; +import { useEventCallback } from '../../utils/useEventCallback'; +import { useId } from '../../utils/useId'; +import type { TransitionStatus } from '../../utils/useTransitionStatus'; +import { useCollapsibleRoot } from '../../Collapsible/Root/useCollapsibleRoot'; +import type { CollapsibleRoot } from '../../Collapsible/Root/CollapsibleRoot'; +import { CollapsibleContext } from '../../Collapsible/Root/CollapsibleContext'; +import { useCompositeListItem } from '../../Composite/List/useCompositeListItem'; +import type { AccordionRoot } from '../Root/AccordionRoot'; +import { useAccordionRootContext } from '../Root/AccordionRootContext'; +import { AccordionSectionContext } from './AccordionSectionContext'; +import { accordionStyleHookMapping } from './styleHooks'; +/** + * + * Demos: + * + * - [Accordion](https://base-ui.netlify.app/components/react-accordion/) + * + * API: + * + * - [AccordionSection API](https://base-ui.netlify.app/components/react-accordion/#api-reference-AccordionSection) + */ +const AccordionSection = React.forwardRef(function AccordionSection( + props: AccordionSection.Props, + forwardedRef: React.ForwardedRef, +) { + const { + className, + disabled: disabledProp, + onOpenChange: onOpenChangeProp, + render, + value: valueProp, + ...otherProps + } = props; + + const sectionRef = React.useRef(null); + const { ref: listItemRef, index } = useCompositeListItem(); + const mergedRef = useForkRef(forwardedRef, listItemRef, sectionRef); + + const { + animated, + disabled: contextDisabled, + handleOpenChange, + ownerState: rootOwnerState, + value: openValues, + } = useAccordionRootContext(); + + const value = valueProp ?? index; + + const disabled = disabledProp || contextDisabled; + + const isOpen = React.useMemo(() => { + if (!openValues) { + return false; + } + + for (let i = 0; i < openValues.length; i += 1) { + if (openValues[i] === value) { + return true; + } + } + + return false; + }, [openValues, value]); + + const onOpenChange = useEventCallback((nextOpen: boolean) => { + handleOpenChange(value, nextOpen); + if (onOpenChangeProp) { + onOpenChangeProp(nextOpen); + } + }); + + const collapsible = useCollapsibleRoot({ + animated, + open: isOpen, + onOpenChange, + disabled, + }); + + const collapsibleOwnerState: CollapsibleRoot.OwnerState = React.useMemo( + () => ({ + open: collapsible.open, + disabled: collapsible.disabled, + transitionStatus: collapsible.transitionStatus, + }), + [collapsible.open, collapsible.disabled, collapsible.transitionStatus], + ); + + const collapsibleContext: CollapsibleRoot.Context = React.useMemo( + () => ({ + ...collapsible, + ownerState: collapsibleOwnerState, + }), + [collapsible, collapsibleOwnerState], + ); + + const ownerState: AccordionSection.OwnerState = React.useMemo( + () => ({ + ...rootOwnerState, + index, + disabled, + open: isOpen, + transitionStatus: collapsible.transitionStatus, + }), + [collapsible.transitionStatus, disabled, index, isOpen, rootOwnerState], + ); + + const triggerId = useId(); + + const accordionSectionContext: AccordionSection.Context = React.useMemo( + () => ({ + open: isOpen, + triggerId, + ownerState, + }), + [isOpen, ownerState, triggerId], + ); + + const { renderElement } = useComponentRenderer({ + render: render ?? 'div', + className, + ownerState, + ref: mergedRef, + extraProps: otherProps, + customStyleHookMapping: accordionStyleHookMapping, + }); + + return ( + + + {renderElement()} + + + ); +}); + +AccordionSection.propTypes /* remove-proptypes */ = { + // ┌────────────────────────────── Warning ──────────────────────────────┐ + // │ These PropTypes are generated from the TypeScript type definitions. │ + // │ To update them, edit the TypeScript types and run `pnpm proptypes`. │ + // └─────────────────────────────────────────────────────────────────────┘ + /** + * Class names applied to the element or a function that returns them based on the component's state. + */ + className: PropTypes.oneOfType([PropTypes.func, PropTypes.string]), + /** + * If `true`, the component is disabled. + * @default false + */ + disabled: PropTypes.bool, + /** + * Callback fired when the Collapsible is opened or closed. + */ + onOpenChange: PropTypes.func, + /** + * A function to customize rendering of the component. + */ + render: PropTypes.oneOfType([PropTypes.element, PropTypes.func]), + /** + * @ignore + */ + value: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), +} as any; + +export { AccordionSection }; + +export namespace AccordionSection { + export type Value = number | string; + + export interface Context { + open: boolean; + triggerId?: string; + ownerState: OwnerState; + } + + export interface OwnerState extends AccordionRoot.OwnerState { + index: number; + open: boolean; + transitionStatus: TransitionStatus; + } + + export interface Props + extends BaseUIComponentProps, + Pick { + value?: Value; + } +} diff --git a/packages/mui-base/src/Accordion/Section/AccordionSectionContext.tsx b/packages/mui-base/src/Accordion/Section/AccordionSectionContext.tsx new file mode 100644 index 000000000..291a16a06 --- /dev/null +++ b/packages/mui-base/src/Accordion/Section/AccordionSectionContext.tsx @@ -0,0 +1,24 @@ +'use client'; +import * as React from 'react'; +import type { AccordionSection } from './AccordionSection'; + +/** + * @ignore - internal component. + */ +export const AccordionSectionContext = React.createContext( + undefined, +); + +if (process.env.NODE_ENV !== 'production') { + AccordionSectionContext.displayName = 'AccordionSectionContext'; +} + +export function useAccordionSectionContext() { + const context = React.useContext(AccordionSectionContext); + if (context === undefined) { + throw new Error( + 'useAccordionSectionContext must be used inside the component', + ); + } + return context; +} diff --git a/packages/mui-base/src/Accordion/Section/styleHooks.ts b/packages/mui-base/src/Accordion/Section/styleHooks.ts new file mode 100644 index 000000000..cb56d531b --- /dev/null +++ b/packages/mui-base/src/Accordion/Section/styleHooks.ts @@ -0,0 +1,27 @@ +import type { CustomStyleHookMapping } from '../../utils/getStyleHookProps'; +import type { AccordionSection } from './AccordionSection'; + +export const accordionStyleHookMapping: CustomStyleHookMapping = { + disabled: (value) => { + if (value) { + return { 'data-disabled': '' }; + } + return null; + }, + index: (value) => { + return Number.isInteger(value) ? { 'data-index': String(value) } : null; + }, + open: (value) => { + return value ? { 'data-state': 'open' } : { 'data-state': 'closed' }; + }, + transitionStatus: (value) => { + if (value === 'entering') { + return { 'data-entering': '' } as Record; + } + if (value === 'exiting') { + return { 'data-exiting': '' }; + } + return null; + }, + value: () => null, +}; diff --git a/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.test.tsx b/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.test.tsx new file mode 100644 index 000000000..ca58f13ef --- /dev/null +++ b/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.test.tsx @@ -0,0 +1,77 @@ +import * as React from 'react'; +// import { expect } from 'chai'; +// import { spy } from 'sinon'; +import { createRenderer /* , act */ } from '@mui/internal-test-utils'; +import * as Accordion from '@base_ui/react/Accordion'; +import * as Collapsible from '@base_ui/react/Collapsible'; +import { describeConformance } from '../../../test/describeConformance'; + +const { AccordionRootContext, AccordionSectionContext } = Accordion; + +const { CollapsibleContext } = Collapsible; + +const accordionRootContextValue: Accordion.Root.Context = { + accordionSectionRefs: { current: [] }, + animated: false, + direction: 'ltr', + disabled: false, + handleOpenChange() {}, + orientation: 'vertical', + ownerState: { + value: [0], + disabled: false, + orientation: 'vertical', + }, + value: [0], +}; + +const accordionSectionContextValue: Accordion.Section.Context = { + open: true, + ownerState: { + value: [0], + disabled: false, + index: 0, + open: true, + orientation: 'vertical', + transitionStatus: undefined, + }, +}; + +const collapsibleContextValue: Collapsible.Root.Context = { + animated: false, + contentId: ':content:', + disabled: false, + mounted: true, + open: true, + setContentId() {}, + setMounted() {}, + setOpen() {}, + transitionStatus: undefined, + ownerState: { + open: true, + disabled: false, + transitionStatus: undefined, + }, +}; + +describe('', () => { + const { render } = createRenderer(); + + describeConformance(, () => ({ + inheritComponent: 'button', + render: (node) => { + const { container, ...other } = render( + + + + {node} + + + , + ); + + return { container, ...other }; + }, + refInstanceof: window.HTMLButtonElement, + })); +}); diff --git a/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.tsx b/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.tsx new file mode 100644 index 000000000..e44053457 --- /dev/null +++ b/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.tsx @@ -0,0 +1,78 @@ +'use client'; +import * as React from 'react'; +import PropTypes from 'prop-types'; +import { useComponentRenderer } from '../../utils/useComponentRenderer'; +import { BaseUIComponentProps } from '../../utils/types'; +import { useCollapsibleContext } from '../../Collapsible/Root/CollapsibleContext'; +import { useCollapsibleTrigger } from '../../Collapsible/Trigger/useCollapsibleTrigger'; +import type { AccordionSection } from '../Section/AccordionSection'; +import { useAccordionSectionContext } from '../Section/AccordionSectionContext'; +import { accordionStyleHookMapping } from '../Section/styleHooks'; +/** + * + * Demos: + * + * - [Accordion](https://base-ui.netlify.app/components/react-accordion/) + * + * API: + * + * - [AccordionTrigger API](https://base-ui.netlify.app/components/react-accordion/#api-reference-AccordionTrigger) + */ +const AccordionTrigger = React.forwardRef(function AccordionTrigger( + props: AccordionTrigger.Props, + forwardedRef: React.ForwardedRef, +) { + const { disabled: disabledProp, className, render, ...otherProps } = props; + + const { contentId, disabled: contextDisabled, open, setOpen } = useCollapsibleContext(); + + const { getRootProps } = useCollapsibleTrigger({ + contentId, + open, + setOpen, + disabled: disabledProp || contextDisabled, + }); + + const { ownerState, triggerId } = useAccordionSectionContext(); + + const { renderElement } = useComponentRenderer({ + propGetter: getRootProps, + render: render ?? 'button', + ownerState, + className, + ref: forwardedRef, + extraProps: { ...otherProps, id: triggerId }, + customStyleHookMapping: accordionStyleHookMapping, + }); + + return renderElement(); +}); + +AccordionTrigger.propTypes /* remove-proptypes */ = { + // ┌────────────────────────────── Warning ──────────────────────────────┐ + // │ These PropTypes are generated from the TypeScript type definitions. │ + // │ To update them, edit the TypeScript types and run `pnpm proptypes`. │ + // └─────────────────────────────────────────────────────────────────────┘ + /** + * @ignore + */ + children: PropTypes.node, + /** + * Class names applied to the element or a function that returns them based on the component's state. + */ + className: PropTypes.oneOfType([PropTypes.func, PropTypes.string]), + /** + * @ignore + */ + disabled: PropTypes.bool, + /** + * A function to customize rendering of the component. + */ + render: PropTypes.oneOfType([PropTypes.element, PropTypes.func]), +} as any; + +export { AccordionTrigger }; + +namespace AccordionTrigger { + export interface Props extends BaseUIComponentProps<'button', AccordionSection.OwnerState> {} +} diff --git a/packages/mui-base/src/Accordion/index.barrel.ts b/packages/mui-base/src/Accordion/index.barrel.ts new file mode 100644 index 000000000..0d057e061 --- /dev/null +++ b/packages/mui-base/src/Accordion/index.barrel.ts @@ -0,0 +1,5 @@ +export * from './Root/AccordionRoot'; +export * from './Section/AccordionSection'; +export * from './Heading/AccordionHeading'; +export * from './Trigger/AccordionTrigger'; +export * from './Panel/AccordionPanel'; diff --git a/packages/mui-base/src/Accordion/index.ts b/packages/mui-base/src/Accordion/index.ts new file mode 100644 index 000000000..7a9efb6c1 --- /dev/null +++ b/packages/mui-base/src/Accordion/index.ts @@ -0,0 +1,13 @@ +export { AccordionRoot as Root } from './Root/AccordionRoot'; +export { useAccordionRoot } from './Root/useAccordionRoot'; +export { AccordionRootContext, useAccordionRootContext } from './Root/AccordionRootContext'; + +export { AccordionSection as Section } from './Section/AccordionSection'; +export { + AccordionSectionContext, + useAccordionSectionContext, +} from './Section/AccordionSectionContext'; + +export { AccordionHeading as Heading } from './Heading/AccordionHeading'; +export { AccordionTrigger as Trigger } from './Trigger/AccordionTrigger'; +export { AccordionPanel as Panel } from './Panel/AccordionPanel'; diff --git a/packages/mui-base/src/Collapsible/Content/useCollapsibleContent.ts b/packages/mui-base/src/Collapsible/Content/useCollapsibleContent.ts index e9e0b7324..227368106 100644 --- a/packages/mui-base/src/Collapsible/Content/useCollapsibleContent.ts +++ b/packages/mui-base/src/Collapsible/Content/useCollapsibleContent.ts @@ -273,6 +273,8 @@ export function useCollapsibleContent( } export namespace useCollapsibleContent { + export type HtmlHiddenType = 'hidden' | 'until-found'; + export interface Parameters { /** * If `true`, the component supports CSS/JS-based animations and transitions. @@ -283,7 +285,7 @@ export namespace useCollapsibleContent { * The hidden state when closed * @default 'hidden' */ - htmlHidden?: 'hidden' | 'until-found'; + htmlHidden?: HtmlHiddenType; id?: React.HTMLAttributes['id']; mounted: boolean; /** diff --git a/packages/mui-base/src/Collapsible/Trigger/useCollapsibleTrigger.ts b/packages/mui-base/src/Collapsible/Trigger/useCollapsibleTrigger.ts index a9db4730e..28e07b0c4 100644 --- a/packages/mui-base/src/Collapsible/Trigger/useCollapsibleTrigger.ts +++ b/packages/mui-base/src/Collapsible/Trigger/useCollapsibleTrigger.ts @@ -5,7 +5,7 @@ import { mergeReactProps } from '../../utils/mergeReactProps'; export function useCollapsibleTrigger( parameters: useCollapsibleTrigger.Parameters, ): useCollapsibleTrigger.ReturnValue { - const { contentId, open, setOpen } = parameters; + const { contentId, disabled, open, setOpen } = parameters; const getRootProps: useCollapsibleTrigger.ReturnValue['getRootProps'] = React.useCallback( (externalProps = {}) => @@ -13,11 +13,12 @@ export function useCollapsibleTrigger( type: 'button', 'aria-controls': contentId, 'aria-expanded': open, + disabled, onClick() { setOpen(!open); }, }), - [contentId, open, setOpen], + [contentId, disabled, open, setOpen], ); return { @@ -31,6 +32,7 @@ export namespace useCollapsibleTrigger { * The id of the element controlled by the Trigger */ contentId: React.HTMLAttributes['id']; + disabled?: boolean; /** * The open state of the Collapsible */ diff --git a/packages/mui-base/src/index.ts b/packages/mui-base/src/index.ts index 9a3bda5f7..aa552e736 100644 --- a/packages/mui-base/src/index.ts +++ b/packages/mui-base/src/index.ts @@ -1,3 +1,4 @@ +export * from './Accordion/index.barrel'; export * from './AlertDialog/index.barrel'; export * from './Checkbox/index.barrel'; export * from './CheckboxGroup/index.barrel'; diff --git a/packages/mui-base/src/utils/defaultRenderFunctions.tsx b/packages/mui-base/src/utils/defaultRenderFunctions.tsx index 2dc313060..6bcdd575e 100644 --- a/packages/mui-base/src/utils/defaultRenderFunctions.tsx +++ b/packages/mui-base/src/utils/defaultRenderFunctions.tsx @@ -11,6 +11,10 @@ export const defaultRenderFunctions = { // eslint-disable-next-line jsx-a11y/heading-has-content return

; }, + h3: (props: React.ComponentPropsWithRef<'h3'>) => { + // eslint-disable-next-line jsx-a11y/heading-has-content + return

; + }, output: (props: React.ComponentPropsWithRef<'output'>) => { return ; }, From 12353ff96d97877b327da5914c265e278cca12c2 Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Wed, 4 Sep 2024 12:54:03 +0800 Subject: [PATCH 03/37] Add docs and demos --- docs/app/experiments/accordion-horizontal.tsx | 179 +++++++++++++++ docs/app/experiments/accordion-material.tsx | 108 +++++++++ docs/app/experiments/accordion.tsx | 60 ++++- .../UnstyledAccordionIntroduction.js | 135 ++++++++++++ .../UnstyledAccordionIntroduction.tsx | 135 ++++++++++++ docs/data/components/accordion/accordion.mdx | 206 +++++++++++++++++- 6 files changed, 812 insertions(+), 11 deletions(-) create mode 100644 docs/app/experiments/accordion-horizontal.tsx create mode 100644 docs/app/experiments/accordion-material.tsx create mode 100644 docs/data/components/accordion/UnstyledAccordionIntroduction.js create mode 100644 docs/data/components/accordion/UnstyledAccordionIntroduction.tsx diff --git a/docs/app/experiments/accordion-horizontal.tsx b/docs/app/experiments/accordion-horizontal.tsx new file mode 100644 index 000000000..96e1f02ff --- /dev/null +++ b/docs/app/experiments/accordion-horizontal.tsx @@ -0,0 +1,179 @@ +import * as React from 'react'; +import * as Accordion from '@base_ui/react/Accordion'; + +function classNames(...classes: Array) { + return classes.filter(Boolean).join(' '); +} + +export default function App() { + const [val, setVal] = React.useState(['one']); + return ( +
+

Horizontal LTR

+ + {['one', 'two', 'three'].map((value, index) => ( + + + + {index + 1} + {value} + + + + This is the contents of Accordion.Panel {index + 1} + + + ))} + + + +

Horizontal RTL

+

one section must remain open

+
+ { + if (newValue.length > 0) { + setVal(newValue); + } + }} + > + {['one', 'two', 'three'].map((value, index) => ( + + + + {index + 1} + {value} + + + + This is the contents of Accordion.Panel {index + 1} + + + ))} + + +
+ ); +} + +function HorizontalStyles() { + return ( + + ); +} diff --git a/docs/app/experiments/accordion-material.tsx b/docs/app/experiments/accordion-material.tsx new file mode 100644 index 000000000..3130c291a --- /dev/null +++ b/docs/app/experiments/accordion-material.tsx @@ -0,0 +1,108 @@ +import * as React from 'react'; +import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; +import * as Accordion from '@base_ui/react/Accordion'; + +export default function App() { + return ( +
+ + {[0, 1, 2, 3].map((index) => ( + + + + Trigger {index + 1} + + + + + This is the contents of Accordion.Panel {index + 1} + + + ))} + + +
+ ); +} + +function MaterialStyles() { + return ( + + ); +} diff --git a/docs/app/experiments/accordion.tsx b/docs/app/experiments/accordion.tsx index 94e537a39..069c45343 100644 --- a/docs/app/experiments/accordion.tsx +++ b/docs/app/experiments/accordion.tsx @@ -1,12 +1,14 @@ +'use client'; import * as React from 'react'; import Check from '@mui/icons-material/Check'; -import { useTheme } from '@mui/system'; +// import { useTheme } from '@mui/system'; import * as Checkbox from '@base_ui/react/Checkbox'; import * as Accordion from '@base_ui/react/Accordion'; export default function App() { const [openMultiple, setOpenMultiple] = React.useState(true); const [val, setVal] = React.useState(['one']); + const [val2, setVal2] = React.useState(['one']); return (
multiple `Accordion.Section`s can be open at the same time: @@ -116,6 +118,50 @@ export default function App() { + +
+ +

Controlled, at least one section must remain open

+ + { + // console.log(newValue); + if (newValue.length > 0) { + setVal2(newValue); + } + }} + aria-label="Controlled Accordion, one section must remain open" + openMultiple={openMultiple} + > + + + Trigger 1 + + + This is the contents of Accordion.Panel 1, the value is "one" + + + + + + Trigger 2 + + + This is the contents of Accordion.Panel 2, the value is "two" + + + + + + Trigger 3 + + + This is the contents of Accordion.Panel 3, the value is "three" + + +
); @@ -130,14 +176,14 @@ const grey = { 900: '#1C2025', }; -function useIsDarkMode() { - const theme = useTheme(); - return theme.palette.mode === 'dark'; -} +// function useIsDarkMode() { +// const theme = useTheme(); +// return theme.palette.mode === 'dark'; +// } function Styles() { // Replace this with your app logic for determining dark mode - const isDarkMode = useIsDarkMode(); + // const isDarkMode = useIsDarkMode(); return ( + ); +} diff --git a/docs/data/components/accordion/UnstyledAccordionIntroduction.tsx b/docs/data/components/accordion/UnstyledAccordionIntroduction.tsx new file mode 100644 index 000000000..dcfddb641 --- /dev/null +++ b/docs/data/components/accordion/UnstyledAccordionIntroduction.tsx @@ -0,0 +1,135 @@ +import * as React from 'react'; +import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; +import * as Accordion from '@base_ui/react/Accordion'; + +export default function UnstyledAccordionIntroduction() { + return ( +
+ + + + + Trigger 1 + + + + + This is the contents of Accordion.Panel 1 + + + + + + Trigger 2 + + + + + This is the contents of Accordion.Panel 2 + + + + + + Trigger 3 + + + + + This is the contents of Accordion.Panel 3 + + + + +
+ ); +} + +function Styles() { + return ( + + ); +} diff --git a/docs/data/components/accordion/accordion.mdx b/docs/data/components/accordion/accordion.mdx index 59558b41b..c1edbe207 100644 --- a/docs/data/components/accordion/accordion.mdx +++ b/docs/data/components/accordion/accordion.mdx @@ -10,7 +10,205 @@ packageName: '@base_ui/react' # Accordion -

- Accordion is a stacked set of interactive headings that each reveal an associated section of - content. -

+ + + + +## Introduction + + + +## Installation + +Base UI components are all available as a single package. + + + +```bash npm +npm install @base_ui/react +``` + +```bash yarn +yarn add @base_ui/react +``` + +```bash pnpm +pnpm add @base_ui/react +``` + + + +Once you have the package installed, import the components. + +```ts +import * as Accordion from '@base_ui/react/Accordion'; +``` + +## Anatomy + +Accordions are implemented using a collection of related components: + +- `` is a top-level component that wraps the other components. +- `` is a component that wraps each section of content +- `` is a button that toggles the open state of it's section +- `` is an element that wraps the `Trigger` +- `` is the element that contains content in a `Section` + +```tsx + + + + Toggle one + + Section one content + + + + Toggle two + + Section two content + + +``` + +## Value + +Each `Accordion.Section` is represented by a value, which by default is its zero-based index by DOM position. +The first section has an implicit `value` of `0`, the second section has a `value` of `1`, and so on. + +The open state of the accordion is represented an array holding the `value`s of all open `Section`s. + +You can optionally specify a custom `value` prop on `Section`: + +```tsx + + + + Toggle one + + Section one content + + + + Toggle two + + Section two content + + +``` + +### Default value + +When uncontrolled, use the `defaultValue` prop to set the initial state of the accordion: + +```tsx + + + {' '} + {/* `value={0}` by default */} + + Toggle one + + Section one content + + + {' '} + {/* `value={1}` by default */} + + Toggle two + + Section two content + +; + +{ + /* with custom `value`s */ +} + + + + Toggle one + + Section one content + + + + Toggle two + + Section two content + +; +``` + +### Controlled + +When controlled, pass the `value` and `onOpenChange` props to `Accordion.Root`: + +```tsx +const [value, setValue] = React.useState(['a']); + +return ( + + + + Toggle one + + Section one content + + + + Toggle two + + Section two content + + +); +``` + +## Customization + +### Only one section open at a time + +By default, all accordion sections can be opened at the same time. Use the `openMultiple` prop to only allow one open section at a time: + +```tsx +{/* subcomponents */} +``` + +### At least one section remains open + +Use controlled mode to always keep one section open: + +```tsx +const [value, setValue] = React.useState([0]); + +const handleOpenChange = (newValue) => { + if (newValue.length > 0) { + setValue(newValue); + } +}; + +return ( + + {/* subcomponents */} + +); +``` + +## Horizontal + +Use the `orientation` prop to configure a horizontal accordion. In a horizontal accordion, focus will move between `Accordion.Trigger`s with the Right Arrow and Left Arrow keys, instead of Down/Up. + +```tsx +{/* subcomponents */} +``` + +## RTL + +Use the `direction` prop to configure a RTL accordion: + +```tsx +{/* subcomponents */} +``` + +When a horizontal accordion is set to `direction="rtl"`, keyboard actions are reversed accordingly - Left Arrow moves focus to the next trigger and Right Arrow moves focus to the previous trigger. From adb4ce285907982e9a4e0503bf8fd7bec7d32c36 Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Wed, 4 Sep 2024 14:59:58 +0800 Subject: [PATCH 04/37] Misc fixes Fix uncontrolled mode Fix broken links --- docs/app/experiments/accordion-animations.tsx | 190 ++++++++++++++++++ docs/app/experiments/accordion-horizontal.tsx | 1 + docs/app/experiments/accordion-material.tsx | 1 + docs/app/experiments/accordion.tsx | 2 +- .../UnstyledAccordionIntroduction.js | 3 +- .../UnstyledAccordionIntroduction.tsx | 3 +- docs/data/components/accordion/accordion.mdx | 157 ++++++++++++++- .../components/collapsible/collapsible.mdx | 6 +- .../src/Accordion/Root/AccordionRoot.tsx | 12 +- .../mui-base/src/Accordion/Root/styleHooks.ts | 0 .../src/Accordion/Root/useAccordionRoot.ts | 45 +++-- .../src/Accordion/Section/styleHooks.ts | 2 +- 12 files changed, 383 insertions(+), 39 deletions(-) create mode 100644 docs/app/experiments/accordion-animations.tsx delete mode 100644 packages/mui-base/src/Accordion/Root/styleHooks.ts diff --git a/docs/app/experiments/accordion-animations.tsx b/docs/app/experiments/accordion-animations.tsx new file mode 100644 index 000000000..7676e5b62 --- /dev/null +++ b/docs/app/experiments/accordion-animations.tsx @@ -0,0 +1,190 @@ +'use client'; +import * as React from 'react'; +import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; +import * as Accordion from '@base_ui/react/Accordion'; + +const DURATION = '300ms'; + +export default function App() { + return ( +
+

CSS @keyframe animations + `hidden="until-found"`

+ + {[0, 1, 2].map((index) => ( + + + + Trigger {index + 1} + + + + +

+ This is the contents of Accordion.Panel {index + 1} +
+ It uses `hidden="until-found"` and can be opened by the browser's + in-page search +

+
+
+ ))} +
+ +

CSS transitions

+ + {[0, 1, 2].map((index) => ( + + + + Trigger {index + 1} + + + + +

This is the contents of Accordion.Panel {index + 1}

+
+
+ ))} +
+ +
+ ); +} + +function MaterialStyles() { + return ( + + ); +} diff --git a/docs/app/experiments/accordion-horizontal.tsx b/docs/app/experiments/accordion-horizontal.tsx index 96e1f02ff..de74513f9 100644 --- a/docs/app/experiments/accordion-horizontal.tsx +++ b/docs/app/experiments/accordion-horizontal.tsx @@ -1,3 +1,4 @@ +'use client'; import * as React from 'react'; import * as Accordion from '@base_ui/react/Accordion'; diff --git a/docs/app/experiments/accordion-material.tsx b/docs/app/experiments/accordion-material.tsx index 3130c291a..201f6e210 100644 --- a/docs/app/experiments/accordion-material.tsx +++ b/docs/app/experiments/accordion-material.tsx @@ -1,3 +1,4 @@ +'use client'; import * as React from 'react'; import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; import * as Accordion from '@base_ui/react/Accordion'; diff --git a/docs/app/experiments/accordion.tsx b/docs/app/experiments/accordion.tsx index 069c45343..6be6c7156 100644 --- a/docs/app/experiments/accordion.tsx +++ b/docs/app/experiments/accordion.tsx @@ -185,7 +185,7 @@ function Styles() { // Replace this with your app logic for determining dark mode // const isDarkMode = useIsDarkMode(); return ( - + + + ); } diff --git a/docs/data/components/accordion/UnstyledAccordionIntroduction.tsx b/docs/data/components/accordion/UnstyledAccordionIntroduction.tsx index 33efa25cb..5c839ae06 100644 --- a/docs/data/components/accordion/UnstyledAccordionIntroduction.tsx +++ b/docs/data/components/accordion/UnstyledAccordionIntroduction.tsx @@ -1,136 +1,61 @@ 'use client'; import * as React from 'react'; -import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; import * as Accordion from '@base_ui/react/Accordion'; +import classes from './styles.module.css'; export default function UnstyledAccordionIntroduction() { return ( -
- - - - - Trigger 1 +
+ + + + + Trigger 1 - + This is the contents of Accordion.Panel 1 - - - - Trigger 2 + + + + Trigger 2 - + This is the contents of Accordion.Panel 2 - - - - Trigger 3 + + + + Trigger 3 - + This is the contents of Accordion.Panel 3 -
); } -function Styles() { +function ExpandMoreIcon(props: React.SVGProps) { return ( - + + + ); } diff --git a/docs/data/components/accordion/accordion.mdx b/docs/data/components/accordion/accordion.mdx index f98a178c8..e2ac80d12 100644 --- a/docs/data/components/accordion/accordion.mdx +++ b/docs/data/components/accordion/accordion.mdx @@ -20,29 +20,7 @@ packageName: '@base_ui/react' ## Installation -Base UI components are all available as a single package. - - - -```bash npm -npm install @base_ui/react -``` - -```bash yarn -yarn add @base_ui/react -``` - -```bash pnpm -pnpm add @base_ui/react -``` - - - -Once you have the package installed, import the components. - -```ts -import * as Accordion from '@base_ui/react/Accordion'; -``` + ## Anatomy @@ -209,10 +187,11 @@ When a horizontal accordion is set to `direction="rtl"`, keyboard actions are re ## Improving searchability of hidden content -:::warning -This is [not yet supported](https://caniuse.com/mdn-html_global_attributes_hidden_until-found_value) in Safari and Firefox as of August 2024 and will fall back to the default `hidden` behavior. - -::: + + This is [not yet + supported](https://caniuse.com/mdn-html_global_attributes_hidden_until-found_value) in Safari and + Firefox as of August 2024 and will fall back to the default `hidden` behavior. + Content hidden by `Accordion.Panel` components can be made accessible only to a browser's find-in-page functionality with the `htmlHidden` prop to improve searchability: diff --git a/docs/data/components/accordion/styles.module.css b/docs/data/components/accordion/styles.module.css new file mode 100644 index 000000000..433cc38ed --- /dev/null +++ b/docs/data/components/accordion/styles.module.css @@ -0,0 +1,81 @@ +.demo { + width: 40rem; + margin: 1rem; +} + +.root { + --Paper-shadow: 0px 2px 1px -1px rgba(0, 0, 0, 0.2), 0px 1px 1px 0px rgba(0, 0, 0, 0.14), + 0px 1px 3px 0px rgba(0, 0, 0, 0.12); + + font-family: system-ui, sans-serif; + box-shadow: var(--Paper-shadow); + background-color: rgba(0, 0, 0, 0.12); + border-radius: 0.3rem; +} + +.section { + position: relative; + background-color: #fff; + color: rgba(0, 0, 0, 0.87); +} + +.section:not(:first-of-type) { + margin-top: 1px; +} + +.section:first-of-type { + border-top-left-radius: 0.25rem; + border-top-right-radius: 0.25rem; +} + +.section:last-of-type { + border-bottom-left-radius: 0.25rem; + border-bottom-right-radius: 0.25rem; +} + +.heading { + margin: 0; + border-radius: inherit; +} + +.heading:hover { + cursor: pointer; +} + +.trigger { + appearance: none; + background-color: transparent; + border: 0; + border-radius: inherit; + color: inherit; + padding: 0 1rem; + position: relative; + width: 100%; + display: flex; + flex-flow: row nowrap; + align-items: center; +} + +.trigger:hover { + cursor: pointer; + background-color: rgba(0, 0, 0, 0.12); +} + +.trigger:focus-visible { + outline: 2px solid black; + z-index: 1; +} + +.trigger .triggerText { + font-size: 1rem; + line-height: 1.5; + margin: 12px auto 12px 0; +} + +.trigger[data-collapsible='open'] svg { + transform: rotate(180deg); +} + +.panel { + padding: 1rem; +} diff --git a/packages/mui-base/src/Accordion/Heading/AccordionHeading.test.tsx b/packages/mui-base/src/Accordion/Heading/AccordionHeading.test.tsx index 6a219aa06..5f0352d28 100644 --- a/packages/mui-base/src/Accordion/Heading/AccordionHeading.test.tsx +++ b/packages/mui-base/src/Accordion/Heading/AccordionHeading.test.tsx @@ -1,10 +1,9 @@ import * as React from 'react'; // import { expect } from 'chai'; // import { spy } from 'sinon'; -import { createRenderer /* , act */ } from '@mui/internal-test-utils'; import * as Accordion from '@base_ui/react/Accordion'; import * as Collapsible from '@base_ui/react/Collapsible'; -import { describeConformance } from '../../../test/describeConformance'; +import { describeConformance, createRenderer } from '#test-utils'; const { AccordionRootContext, AccordionSectionContext } = Accordion; @@ -59,8 +58,8 @@ describe('', () => { describeConformance(, () => ({ inheritComponent: 'h3', - render: (node) => { - const { container, ...other } = render( + render: (node) => + render( @@ -68,10 +67,7 @@ describe('', () => { , - ); - - return { container, ...other }; - }, + ), refInstanceof: window.HTMLHeadingElement, })); }); diff --git a/packages/mui-base/src/Accordion/Heading/AccordionHeading.tsx b/packages/mui-base/src/Accordion/Heading/AccordionHeading.tsx index 4bae16fd5..55584806c 100644 --- a/packages/mui-base/src/Accordion/Heading/AccordionHeading.tsx +++ b/packages/mui-base/src/Accordion/Heading/AccordionHeading.tsx @@ -6,6 +6,7 @@ import { useComponentRenderer } from '../../utils/useComponentRenderer'; import type { AccordionSection } from '../Section/AccordionSection'; import { useAccordionSectionContext } from '../Section/AccordionSectionContext'; import { accordionStyleHookMapping } from '../Section/styleHooks'; + /** * * Demos: @@ -36,6 +37,12 @@ const AccordionHeading = React.forwardRef(function AccordionHeading( return renderElement(); }); +export { AccordionHeading }; + +export namespace AccordionHeading { + export interface Props extends BaseUIComponentProps<'h3', AccordionSection.OwnerState> {} +} + AccordionHeading.propTypes /* remove-proptypes */ = { // ┌────────────────────────────── Warning ──────────────────────────────┐ // │ These PropTypes are generated from the TypeScript type definitions. │ @@ -54,9 +61,3 @@ AccordionHeading.propTypes /* remove-proptypes */ = { */ render: PropTypes.oneOfType([PropTypes.element, PropTypes.func]), } as any; - -export { AccordionHeading }; - -export namespace AccordionHeading { - export interface Props extends BaseUIComponentProps<'h3', AccordionSection.OwnerState> {} -} diff --git a/packages/mui-base/src/Accordion/Panel/AccordionPanel.test.tsx b/packages/mui-base/src/Accordion/Panel/AccordionPanel.test.tsx index f03b91751..43426a7ff 100644 --- a/packages/mui-base/src/Accordion/Panel/AccordionPanel.test.tsx +++ b/packages/mui-base/src/Accordion/Panel/AccordionPanel.test.tsx @@ -1,10 +1,9 @@ import * as React from 'react'; // import { expect } from 'chai'; // import { spy } from 'sinon'; -import { createRenderer /* , act */ } from '@mui/internal-test-utils'; import * as Accordion from '@base_ui/react/Accordion'; import * as Collapsible from '@base_ui/react/Collapsible'; -import { describeConformance } from '../../../test/describeConformance'; +import { describeConformance, createRenderer } from '#test-utils'; const { AccordionRootContext, AccordionSectionContext } = Accordion; @@ -59,8 +58,8 @@ describe('', () => { describeConformance(, () => ({ inheritComponent: 'div', - render: (node) => { - const { container, ...other } = render( + render: (node) => + render( @@ -68,10 +67,7 @@ describe('', () => { , - ); - - return { container, ...other }; - }, + ), refInstanceof: window.HTMLDivElement, })); }); diff --git a/packages/mui-base/src/Accordion/Panel/AccordionPanel.tsx b/packages/mui-base/src/Accordion/Panel/AccordionPanel.tsx index 795e8ea02..e0af4fbde 100644 --- a/packages/mui-base/src/Accordion/Panel/AccordionPanel.tsx +++ b/packages/mui-base/src/Accordion/Panel/AccordionPanel.tsx @@ -9,6 +9,7 @@ import { useAccordionRootContext } from '../Root/AccordionRootContext'; import type { AccordionSection } from '../Section/AccordionSection'; import { useAccordionSectionContext } from '../Section/AccordionSectionContext'; import { accordionStyleHookMapping } from '../Section/styleHooks'; + /** * * Demos: @@ -64,6 +65,14 @@ const AccordionPanel = React.forwardRef(function AccordionPanel( return renderElement(); }); +export { AccordionPanel }; + +export namespace AccordionPanel { + export interface Props + extends BaseUIComponentProps<'div', AccordionSection.OwnerState>, + Pick {} +} + AccordionPanel.propTypes /* remove-proptypes */ = { // ┌────────────────────────────── Warning ──────────────────────────────┐ // │ These PropTypes are generated from the TypeScript type definitions. │ @@ -87,11 +96,3 @@ AccordionPanel.propTypes /* remove-proptypes */ = { */ render: PropTypes.oneOfType([PropTypes.element, PropTypes.func]), } as any; - -export { AccordionPanel }; - -export namespace AccordionPanel { - export interface Props - extends BaseUIComponentProps<'div', AccordionSection.OwnerState>, - Pick {} -} diff --git a/packages/mui-base/src/Accordion/Root/AccordionRoot.test.tsx b/packages/mui-base/src/Accordion/Root/AccordionRoot.test.tsx index 6597bf2e1..e8fdbc9a0 100644 --- a/packages/mui-base/src/Accordion/Root/AccordionRoot.test.tsx +++ b/packages/mui-base/src/Accordion/Root/AccordionRoot.test.tsx @@ -1,9 +1,8 @@ import * as React from 'react'; // import { expect } from 'chai'; // import { spy } from 'sinon'; -import { createRenderer /* , act */ } from '@mui/internal-test-utils'; import * as Accordion from '@base_ui/react/Accordion'; -import { describeConformance } from '../../../test/describeConformance'; +import { describeConformance, createRenderer } from '#test-utils'; describe('', () => { const { render } = createRenderer(); diff --git a/packages/mui-base/src/Accordion/Root/AccordionRoot.tsx b/packages/mui-base/src/Accordion/Root/AccordionRoot.tsx index 0ae48b1fc..13e3d62a5 100644 --- a/packages/mui-base/src/Accordion/Root/AccordionRoot.tsx +++ b/packages/mui-base/src/Accordion/Root/AccordionRoot.tsx @@ -7,6 +7,7 @@ import type { useCollapsibleContent } from '../../Collapsible/Content/useCollaps import { CompositeList } from '../../Composite/List/CompositeList'; import { useAccordionRoot } from './useAccordionRoot'; import { AccordionRootContext } from './AccordionRootContext'; + /** * * Demos: @@ -101,6 +102,27 @@ const AccordionRoot = React.forwardRef(function AccordionRoot( ); }); +export { AccordionRoot }; + +export namespace AccordionRoot { + export interface Context extends Omit { + ownerState: OwnerState; + htmlHidden?: useCollapsibleContent.HtmlHiddenType; + } + + export interface OwnerState { + value: useAccordionRoot.Value; + disabled: boolean; + orientation: useAccordionRoot.Orientation; + } + + export interface Props + extends useAccordionRoot.Parameters, + BaseUIComponentProps { + htmlHidden?: useCollapsibleContent.HtmlHiddenType; + } +} + AccordionRoot.propTypes /* remove-proptypes */ = { // ┌────────────────────────────── Warning ──────────────────────────────┐ // │ These PropTypes are generated from the TypeScript type definitions. │ @@ -160,24 +182,3 @@ AccordionRoot.propTypes /* remove-proptypes */ = { */ value: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired), } as any; - -export { AccordionRoot }; - -export namespace AccordionRoot { - export interface Context extends Omit { - ownerState: OwnerState; - htmlHidden?: useCollapsibleContent.HtmlHiddenType; - } - - export interface OwnerState { - value: useAccordionRoot.Value; - disabled: boolean; - orientation: useAccordionRoot.Orientation; - } - - export interface Props - extends useAccordionRoot.Parameters, - BaseUIComponentProps { - htmlHidden?: useCollapsibleContent.HtmlHiddenType; - } -} diff --git a/packages/mui-base/src/Accordion/Root/useAccordionRoot.ts b/packages/mui-base/src/Accordion/Root/useAccordionRoot.ts index af72a5f57..1aaada22a 100644 --- a/packages/mui-base/src/Accordion/Root/useAccordionRoot.ts +++ b/packages/mui-base/src/Accordion/Root/useAccordionRoot.ts @@ -34,16 +34,7 @@ function isDisabled(element: HTMLElement | null) { element.getAttribute('data-disabled') === 'true' ); } -/** - * - * Demos: - * - * - [Accordion](https://mui.com/base-ui/react-accordion/#hook) - * - * API: - * - * - [useAccordionRoot API](https://mui.com/base-ui/react-accordion/hooks-api/#use-accordion-root) - */ + export function useAccordionRoot( parameters: useAccordionRoot.Parameters, ): useAccordionRoot.ReturnValue { diff --git a/packages/mui-base/src/Accordion/Section/AccordionSection.test.tsx b/packages/mui-base/src/Accordion/Section/AccordionSection.test.tsx index 355a16839..f13adf883 100644 --- a/packages/mui-base/src/Accordion/Section/AccordionSection.test.tsx +++ b/packages/mui-base/src/Accordion/Section/AccordionSection.test.tsx @@ -1,9 +1,8 @@ import * as React from 'react'; // import { expect } from 'chai'; // import { spy } from 'sinon'; -import { createRenderer /* , act */ } from '@mui/internal-test-utils'; import * as Accordion from '@base_ui/react/Accordion'; -import { describeConformance } from '../../../test/describeConformance'; +import { describeConformance, createRenderer } from '#test-utils'; const { AccordionRootContext } = Accordion; @@ -27,15 +26,12 @@ describe('', () => { describeConformance(, () => ({ inheritComponent: 'div', - render: (node) => { - const { container, ...other } = render( + render: (node) => + render( {node} , - ); - - return { container, ...other }; - }, + ), refInstanceof: window.HTMLDivElement, })); }); diff --git a/packages/mui-base/src/Accordion/Section/AccordionSection.tsx b/packages/mui-base/src/Accordion/Section/AccordionSection.tsx index d510a1c14..77b4d1914 100644 --- a/packages/mui-base/src/Accordion/Section/AccordionSection.tsx +++ b/packages/mui-base/src/Accordion/Section/AccordionSection.tsx @@ -15,6 +15,7 @@ import type { AccordionRoot } from '../Root/AccordionRoot'; import { useAccordionRootContext } from '../Root/AccordionRootContext'; import { AccordionSectionContext } from './AccordionSectionContext'; import { accordionStyleHookMapping } from './styleHooks'; + /** * * Demos: @@ -139,6 +140,30 @@ const AccordionSection = React.forwardRef(function AccordionSection( ); }); +export { AccordionSection }; + +export namespace AccordionSection { + export type Value = number | string; + + export interface Context { + open: boolean; + triggerId?: string; + ownerState: OwnerState; + } + + export interface OwnerState extends AccordionRoot.OwnerState { + index: number; + open: boolean; + transitionStatus: TransitionStatus; + } + + export interface Props + extends BaseUIComponentProps, + Pick { + value?: Value; + } +} + AccordionSection.propTypes /* remove-proptypes */ = { // ┌────────────────────────────── Warning ──────────────────────────────┐ // │ These PropTypes are generated from the TypeScript type definitions. │ @@ -166,27 +191,3 @@ AccordionSection.propTypes /* remove-proptypes */ = { */ value: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), } as any; - -export { AccordionSection }; - -export namespace AccordionSection { - export type Value = number | string; - - export interface Context { - open: boolean; - triggerId?: string; - ownerState: OwnerState; - } - - export interface OwnerState extends AccordionRoot.OwnerState { - index: number; - open: boolean; - transitionStatus: TransitionStatus; - } - - export interface Props - extends BaseUIComponentProps, - Pick { - value?: Value; - } -} diff --git a/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.test.tsx b/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.test.tsx index ca58f13ef..815cf3f5c 100644 --- a/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.test.tsx +++ b/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.test.tsx @@ -1,10 +1,9 @@ import * as React from 'react'; // import { expect } from 'chai'; // import { spy } from 'sinon'; -import { createRenderer /* , act */ } from '@mui/internal-test-utils'; import * as Accordion from '@base_ui/react/Accordion'; import * as Collapsible from '@base_ui/react/Collapsible'; -import { describeConformance } from '../../../test/describeConformance'; +import { describeConformance, createRenderer } from '#test-utils'; const { AccordionRootContext, AccordionSectionContext } = Accordion; @@ -59,8 +58,8 @@ describe('', () => { describeConformance(, () => ({ inheritComponent: 'button', - render: (node) => { - const { container, ...other } = render( + render: (node) => + render( @@ -68,10 +67,7 @@ describe('', () => { , - ); - - return { container, ...other }; - }, + ), refInstanceof: window.HTMLButtonElement, })); }); diff --git a/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.tsx b/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.tsx index 9ace5192f..c67f264ef 100644 --- a/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.tsx +++ b/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.tsx @@ -8,6 +8,7 @@ import { useCollapsibleTrigger } from '../../Collapsible/Trigger/useCollapsibleT import type { AccordionSection } from '../Section/AccordionSection'; import { useAccordionSectionContext } from '../Section/AccordionSectionContext'; import { accordionStyleHookMapping } from '../Section/styleHooks'; + /** * * Demos: @@ -48,6 +49,12 @@ const AccordionTrigger = React.forwardRef(function AccordionTrigger( return renderElement(); }); +export { AccordionTrigger }; + +namespace AccordionTrigger { + export interface Props extends BaseUIComponentProps<'button', AccordionSection.OwnerState> {} +} + AccordionTrigger.propTypes /* remove-proptypes */ = { // ┌────────────────────────────── Warning ──────────────────────────────┐ // │ These PropTypes are generated from the TypeScript type definitions. │ @@ -70,9 +77,3 @@ AccordionTrigger.propTypes /* remove-proptypes */ = { */ render: PropTypes.oneOfType([PropTypes.element, PropTypes.func]), } as any; - -export { AccordionTrigger }; - -namespace AccordionTrigger { - export interface Props extends BaseUIComponentProps<'button', AccordionSection.OwnerState> {} -} diff --git a/packages/mui-base/src/Collapsible/index.barrel.ts b/packages/mui-base/src/Collapsible/index.barrel.ts new file mode 100644 index 000000000..34a4d1b71 --- /dev/null +++ b/packages/mui-base/src/Collapsible/index.barrel.ts @@ -0,0 +1,4 @@ +export * from './Root/CollapsibleRoot'; +export * from './Root/CollapsibleContext'; +export * from './Trigger/CollapsibleTrigger'; +export * from './Content/CollapsibleContent'; diff --git a/packages/mui-base/src/index.ts b/packages/mui-base/src/index.ts index aa552e736..609c605dd 100644 --- a/packages/mui-base/src/index.ts +++ b/packages/mui-base/src/index.ts @@ -2,6 +2,7 @@ export * from './Accordion/index.barrel'; export * from './AlertDialog/index.barrel'; export * from './Checkbox/index.barrel'; export * from './CheckboxGroup/index.barrel'; +export * from './Collapsible/index.barrel'; export * from './Dialog/index.barrel'; export * from './NumberField/index.barrel'; export * from './Popover/index.barrel'; From 895872c06e5ee4425c78aa2ecae9ce4f3c923065 Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Wed, 11 Sep 2024 15:13:32 +0800 Subject: [PATCH 07/37] Rename subcomponents --- docs/app/experiments/accordion-animations.tsx | 26 ++-- docs/app/experiments/accordion-horizontal.tsx | 16 +- docs/app/experiments/accordion-material.tsx | 18 +-- docs/app/experiments/accordion.tsx | 90 +++++------ docs/data/api/accordion-header.json | 19 +++ docs/data/api/accordion-item.json | 21 +++ .../UnstyledAccordionIntroduction.js | 24 +-- .../UnstyledAccordionIntroduction.tsx | 24 +-- docs/data/components/accordion/accordion.mdx | 141 +++++++++--------- .../components/accordion/styles.module.css | 12 +- .../accordion-header.json} | 0 .../accordion-item.json} | 0 .../accordion-root/accordion-root.json | 4 +- .../AccordionHeader.test.tsx} | 14 +- .../AccordionHeader.tsx} | 22 +-- .../AccordionItem.test.tsx} | 6 +- .../AccordionItem.tsx} | 22 +-- .../Accordion/Item/AccordionItemContext.tsx | 22 +++ .../Accordion/{Section => Item}/styleHooks.ts | 4 +- .../Accordion/Panel/AccordionPanel.test.tsx | 10 +- .../src/Accordion/Panel/AccordionPanel.tsx | 10 +- .../src/Accordion/Root/AccordionRoot.tsx | 6 +- .../src/Accordion/Root/useAccordionRoot.ts | 24 +-- .../Section/AccordionSectionContext.tsx | 24 --- .../Trigger/AccordionTrigger.test.tsx | 10 +- .../Accordion/Trigger/AccordionTrigger.tsx | 10 +- .../mui-base/src/Accordion/index.barrel.ts | 4 +- packages/mui-base/src/Accordion/index.ts | 9 +- 28 files changed, 313 insertions(+), 279 deletions(-) create mode 100644 docs/data/api/accordion-header.json create mode 100644 docs/data/api/accordion-item.json rename docs/data/translations/api-docs/{accordion-heading/accordion-heading.json => accordion-header/accordion-header.json} (100%) rename docs/data/translations/api-docs/{accordion-section/accordion-section.json => accordion-item/accordion-item.json} (100%) rename packages/mui-base/src/Accordion/{Heading/AccordionHeading.test.tsx => Header/AccordionHeader.test.tsx} (79%) rename packages/mui-base/src/Accordion/{Heading/AccordionHeading.tsx => Header/AccordionHeader.tsx} (73%) rename packages/mui-base/src/Accordion/{Section/AccordionSection.test.tsx => Item/AccordionItem.test.tsx} (85%) rename packages/mui-base/src/Accordion/{Section/AccordionSection.tsx => Item/AccordionItem.tsx} (88%) create mode 100644 packages/mui-base/src/Accordion/Item/AccordionItemContext.tsx rename packages/mui-base/src/Accordion/{Section => Item}/styleHooks.ts (88%) delete mode 100644 packages/mui-base/src/Accordion/Section/AccordionSectionContext.tsx diff --git a/docs/app/experiments/accordion-animations.tsx b/docs/app/experiments/accordion-animations.tsx index 2e8c3957a..c6f88e71c 100644 --- a/docs/app/experiments/accordion-animations.tsx +++ b/docs/app/experiments/accordion-animations.tsx @@ -15,13 +15,13 @@ export default function App() { htmlHidden="until-found" > {[0, 1, 2].map((index) => ( - - + + Trigger {index + 1} - +

This is the contents of Accordion.Panel {index + 1} @@ -30,24 +30,24 @@ export default function App() { in-page search

-
+ ))}

CSS transitions

{[0, 1, 2].map((index) => ( - - + + Trigger {index + 1} - +

This is the contents of Accordion.Panel {index + 1}

-
+ ))}
@@ -79,27 +79,27 @@ function MaterialStyles() { border-radius: .3rem; } - .MyAccordion-section { + .MyAccordion-item { position: relative; background-color: #fff; color: rgba(0, 0, 0, .87); } - .MyAccordion-section:not(:first-of-type) { + .MyAccordion-item:not(:first-of-type) { margin-top: 1px; } - .MyAccordion-section:first-of-type { + .MyAccordion-item:first-of-type { border-top-left-radius: .25rem; border-top-right-radius: .25rem; } - .MyAccordion-section:last-of-type { + .MyAccordion-item:last-of-type { border-bottom-left-radius: .25rem; border-bottom-right-radius: .25rem; } - .MyAccordion-heading { + .MyAccordion-header { margin: 0; } diff --git a/docs/app/experiments/accordion-horizontal.tsx b/docs/app/experiments/accordion-horizontal.tsx index de74513f9..81cb8a0bf 100644 --- a/docs/app/experiments/accordion-horizontal.tsx +++ b/docs/app/experiments/accordion-horizontal.tsx @@ -18,17 +18,17 @@ export default function App() { orientation="horizontal" > {['one', 'two', 'three'].map((value, index) => ( - - + + {index + 1} {value} - + This is the contents of Accordion.Panel {index + 1} - + ))}
@@ -50,17 +50,17 @@ export default function App() { }} > {['one', 'two', 'three'].map((value, index) => ( - - + + {index + 1} {value} - + This is the contents of Accordion.Panel {index + 1} - + ))} diff --git a/docs/app/experiments/accordion-material.tsx b/docs/app/experiments/accordion-material.tsx index 425ffe2d8..cd430c7a5 100644 --- a/docs/app/experiments/accordion-material.tsx +++ b/docs/app/experiments/accordion-material.tsx @@ -8,17 +8,17 @@ export default function App() {
{[0, 1, 2, 3].map((index) => ( - - + + Trigger {index + 1} - + This is the contents of Accordion.Panel {index + 1} - + ))} @@ -47,27 +47,27 @@ function MaterialStyles() { border-radius: .3rem; } - .MyAccordion-section { + .MyAccordion-item { position: relative; background-color: #fff; color: rgba(0, 0, 0, .87); } - .MyAccordion-section:not(:first-of-type) { + .MyAccordion-item:not(:first-of-type) { margin-top: 1px; } - .MyAccordion-section:first-of-type { + .MyAccordion-item:first-of-type { border-top-left-radius: .25rem; border-top-right-radius: .25rem; } - .MyAccordion-section:last-of-type { + .MyAccordion-item:last-of-type { border-bottom-left-radius: .25rem; border-bottom-right-radius: .25rem; } - .MyAccordion-heading { + .MyAccordion-header { margin: 0; } diff --git a/docs/app/experiments/accordion.tsx b/docs/app/experiments/accordion.tsx index 264313070..eaa04e279 100644 --- a/docs/app/experiments/accordion.tsx +++ b/docs/app/experiments/accordion.tsx @@ -9,7 +9,7 @@ export default function App() { const [val2, setVal2] = React.useState(['one']); return (
- multiple `Accordion.Section`s can be open at the same time: + multiple `Accordion.Item`s can be open at the same time: - - + + Trigger 1 - + This is the contents of Accordion.Panel 1 - + - - + + Trigger 2 - + This is the contents of Accordion.Panel 2 - + - - + + Trigger 3 - + This is the contents of Accordion.Panel 3 - + - - + + Trigger 4 - + This is the contents of Accordion.Panel 4 - + - - + + Trigger 5 - + This is the contents of Accordion.Panel 5 - +
@@ -89,32 +89,32 @@ export default function App() { aria-label="Controlled Accordion" openMultiple={openMultiple} > - - + + Trigger 1 - + This is the contents of Accordion.Panel 1, the value is "one" - + - - + + Trigger 2 - + This is the contents of Accordion.Panel 2, the value is "two" - + - - + + Trigger 3 - + This is the contents of Accordion.Panel 3, the value is "three" - +
@@ -133,32 +133,32 @@ export default function App() { aria-label="Controlled Accordion, one section must remain open" openMultiple={openMultiple} > - - + + Trigger 1 - + This is the contents of Accordion.Panel 1, the value is "one" - + - - + + Trigger 2 - + This is the contents of Accordion.Panel 2, the value is "two" - + - - + + Trigger 3 - + This is the contents of Accordion.Panel 3, the value is "three" - +
diff --git a/docs/data/api/accordion-header.json b/docs/data/api/accordion-header.json new file mode 100644 index 000000000..f5802943d --- /dev/null +++ b/docs/data/api/accordion-header.json @@ -0,0 +1,19 @@ +{ + "props": { + "className": { "type": { "name": "union", "description": "func
| string" } }, + "render": { "type": { "name": "union", "description": "element
| func" } } + }, + "name": "AccordionHeader", + "imports": [ + "import * as Accordion from '@base_ui/react/Accordion';\nconst AccordionHeader = Accordion.Header;" + ], + "classes": [], + "spread": true, + "themeDefaultProps": true, + "muiName": "AccordionHeader", + "forwardsRefTo": "HTMLHeadingElement", + "filename": "/packages/mui-base/src/Accordion/Header/AccordionHeader.tsx", + "inheritance": null, + "demos": "", + "cssComponent": false +} diff --git a/docs/data/api/accordion-item.json b/docs/data/api/accordion-item.json new file mode 100644 index 000000000..f85d3793f --- /dev/null +++ b/docs/data/api/accordion-item.json @@ -0,0 +1,21 @@ +{ + "props": { + "className": { "type": { "name": "union", "description": "func
| string" } }, + "disabled": { "type": { "name": "bool" }, "default": "false" }, + "onOpenChange": { "type": { "name": "func" } }, + "render": { "type": { "name": "union", "description": "element
| func" } } + }, + "name": "AccordionItem", + "imports": [ + "import * as Accordion from '@base_ui/react/Accordion';\nconst AccordionItem = Accordion.Item;" + ], + "classes": [], + "spread": true, + "themeDefaultProps": true, + "muiName": "AccordionItem", + "forwardsRefTo": "HTMLDivElement", + "filename": "/packages/mui-base/src/Accordion/Item/AccordionItem.tsx", + "inheritance": null, + "demos": "", + "cssComponent": false +} diff --git a/docs/data/components/accordion/UnstyledAccordionIntroduction.js b/docs/data/components/accordion/UnstyledAccordionIntroduction.js index 0307584a4..05aef368b 100644 --- a/docs/data/components/accordion/UnstyledAccordionIntroduction.js +++ b/docs/data/components/accordion/UnstyledAccordionIntroduction.js @@ -7,39 +7,39 @@ export default function UnstyledAccordionIntroduction() { return (
- - + + Trigger 1 - + This is the contents of Accordion.Panel 1 - - - + + + Trigger 2 - + This is the contents of Accordion.Panel 2 - - - + + + Trigger 3 - + This is the contents of Accordion.Panel 3 - +
); diff --git a/docs/data/components/accordion/UnstyledAccordionIntroduction.tsx b/docs/data/components/accordion/UnstyledAccordionIntroduction.tsx index 5c839ae06..01120baca 100644 --- a/docs/data/components/accordion/UnstyledAccordionIntroduction.tsx +++ b/docs/data/components/accordion/UnstyledAccordionIntroduction.tsx @@ -7,39 +7,39 @@ export default function UnstyledAccordionIntroduction() { return (
- - + + Trigger 1 - + This is the contents of Accordion.Panel 1 - - - + + + Trigger 2 - + This is the contents of Accordion.Panel 2 - - - + + + Trigger 3 - + This is the contents of Accordion.Panel 3 - +
); diff --git a/docs/data/components/accordion/accordion.mdx b/docs/data/components/accordion/accordion.mdx index e2ac80d12..aea5106ee 100644 --- a/docs/data/components/accordion/accordion.mdx +++ b/docs/data/components/accordion/accordion.mdx @@ -1,8 +1,7 @@ --- productId: base-ui title: React Accordion components -components: AccordionRoot, AccordionSection, AccordionHeading, AccordionTrigger, AccordionPanel -hooks: useAccordionRoot +components: AccordionRoot, AccordionItem, AccordionHeader, AccordionTrigger, AccordionPanel githubLabel: 'component: accordion' waiAria: https://www.w3.org/WAI/ARIA/apg/patterns/accordion/ packageName: '@base_ui/react' @@ -27,51 +26,51 @@ packageName: '@base_ui/react' Accordions are implemented using a collection of related components: - `` is a top-level component that wraps the other components. -- `` is a component that wraps each section of content -- `` is a button that toggles the open state of it's section -- `` is an element that wraps the `Trigger` -- `` is the element that contains content in a `Section` +- `` is a component that wraps each section of content +- `` is a button that toggles the open state of it's associated `Item` +- `` is an element that wraps the `Trigger` +- `` is the element that contains content in a `Item` ```tsx - - + + Toggle one - - Section one content - - - + + Panel one content + + + Toggle two - - Section two content - + + Panel two content + ``` ## Value -Each `Accordion.Section` is represented by a value, which by default is its zero-based index by DOM position. -The first section has an implicit `value` of `0`, the second section has a `value` of `1`, and so on. +Each `Accordion.Item` is represented by a value, which by default is its zero-based index by DOM position. +The first one has an implicit `value` of `0`, the second one has a `value` of `1`, and so on. -The open state of the accordion is represented an array holding the `value`s of all open `Section`s. +The open state of the accordion is represented an array holding the `value`s of all open `Item`s. -You can optionally specify a custom `value` prop on `Section`: +You can optionally specify a custom `value` prop on `Item`: ```tsx - - + + Toggle one - - Section one content - - - + + Panel one content + + + Toggle two - - Section two content - + + Panel two content + ``` @@ -81,34 +80,34 @@ When uncontrolled, use the `defaultValue` prop to set the initial state of the a ```tsx - - + + Toggle one - - Section one content - - - + + Panel one content + + + Toggle two - - Section two content - + + Panel two content + ; // with custom `value`s - - + + Toggle one - - Section one content - - - + + Panel one content + + + Toggle two - - Section two content - + + Panel two content + ; ``` @@ -121,35 +120,35 @@ const [value, setValue] = React.useState(['a']); return ( - - + + Toggle one - - Section one content - - - + + Panel one content + + + Toggle two - - Section two content - + + Panel two content + ); ``` ## Customization -### Only one section open at a time +### Only one `Item` open at a time -By default, all accordion sections can be opened at the same time. Use the `openMultiple` prop to only allow one open section at a time: +By default, all accordion items can be opened at the same time. Use the `openMultiple` prop to only allow one open item at a time: ```tsx {/* subcomponents */} ``` -### At least one section remains open +### At least one `Item` remains open -Use controlled mode to always keep one section open: +Use controlled mode to always keep one `Item` open: ```tsx const [value, setValue] = React.useState([0]); @@ -199,7 +198,7 @@ Content hidden by `Accordion.Panel` components can be made accessible only to a {/* subcomponents */} ``` -Alternatively `htmlHidden` can be passed to `Accordion.Panel` directly to enable this for only one section instead of the whole accordion. +Alternatively `htmlHidden` can be passed to `Accordion.Panel` directly to enable this for only one `Item` instead of the whole accordion. We recommend using [CSS animations](#css-animations) for animated accordions that use this feature. Currently there is browser bug that does not highlight the found text inside elements that have a [CSS transition](#css-transitions) applied. @@ -290,17 +289,17 @@ When using CSS transitions, styles for the `Panel` must be applied to three stat ### JavaScript Animations -When using external libraries for animation, for example `framer-motion`, be aware that `Accordion.Section`s hides content using the html `hidden` attribute in the closed state, and does not unmount from the DOM. +When using external libraries for animation, for example `framer-motion`, be aware that `Accordion.Item`s hides content using the html `hidden` attribute in the closed state, and does not unmount from the DOM. ```js function App() { const [value, setValue] = useState([0]); return ( - - + + Toggle - + This is the content - - {/* more accordion sections */} + + {/* more accordion items */} ); } diff --git a/docs/data/components/accordion/styles.module.css b/docs/data/components/accordion/styles.module.css index 433cc38ed..0bd0b5974 100644 --- a/docs/data/components/accordion/styles.module.css +++ b/docs/data/components/accordion/styles.module.css @@ -13,32 +13,32 @@ border-radius: 0.3rem; } -.section { +.item { position: relative; background-color: #fff; color: rgba(0, 0, 0, 0.87); } -.section:not(:first-of-type) { +.item:not(:first-of-type) { margin-top: 1px; } -.section:first-of-type { +.item:first-of-type { border-top-left-radius: 0.25rem; border-top-right-radius: 0.25rem; } -.section:last-of-type { +.item:last-of-type { border-bottom-left-radius: 0.25rem; border-bottom-right-radius: 0.25rem; } -.heading { +.header { margin: 0; border-radius: inherit; } -.heading:hover { +.header:hover { cursor: pointer; } diff --git a/docs/data/translations/api-docs/accordion-heading/accordion-heading.json b/docs/data/translations/api-docs/accordion-header/accordion-header.json similarity index 100% rename from docs/data/translations/api-docs/accordion-heading/accordion-heading.json rename to docs/data/translations/api-docs/accordion-header/accordion-header.json diff --git a/docs/data/translations/api-docs/accordion-section/accordion-section.json b/docs/data/translations/api-docs/accordion-item/accordion-item.json similarity index 100% rename from docs/data/translations/api-docs/accordion-section/accordion-section.json rename to docs/data/translations/api-docs/accordion-item/accordion-item.json diff --git a/docs/data/translations/api-docs/accordion-root/accordion-root.json b/docs/data/translations/api-docs/accordion-root/accordion-root.json index ceb5a5e1b..900b8b029 100644 --- a/docs/data/translations/api-docs/accordion-root/accordion-root.json +++ b/docs/data/translations/api-docs/accordion-root/accordion-root.json @@ -8,7 +8,7 @@ "description": "Class names applied to the element or a function that returns them based on the component's state." }, "defaultValue": { - "description": "The default value representing the currently open Accordion.Section This is the uncontrolled counterpart of value." + "description": "The default value representing the currently open Accordion.Item This is the uncontrolled counterpart of value." }, "disabled": { "description": "If true, the component is disabled." }, "onOpenChange": { @@ -19,7 +19,7 @@ }, "render": { "description": "A function to customize rendering of the component." }, "value": { - "description": "The value of the currently open Accordion.Section This is the controlled counterpart of defaultValue." + "description": "The value of the currently open Accordion.Item This is the controlled counterpart of defaultValue." } }, "classDescriptions": {} diff --git a/packages/mui-base/src/Accordion/Heading/AccordionHeading.test.tsx b/packages/mui-base/src/Accordion/Header/AccordionHeader.test.tsx similarity index 79% rename from packages/mui-base/src/Accordion/Heading/AccordionHeading.test.tsx rename to packages/mui-base/src/Accordion/Header/AccordionHeader.test.tsx index 5f0352d28..506bb7755 100644 --- a/packages/mui-base/src/Accordion/Heading/AccordionHeading.test.tsx +++ b/packages/mui-base/src/Accordion/Header/AccordionHeader.test.tsx @@ -5,12 +5,12 @@ import * as Accordion from '@base_ui/react/Accordion'; import * as Collapsible from '@base_ui/react/Collapsible'; import { describeConformance, createRenderer } from '#test-utils'; -const { AccordionRootContext, AccordionSectionContext } = Accordion; +const { AccordionRootContext, AccordionItemContext } = Accordion; const { CollapsibleContext } = Collapsible; const accordionRootContextValue: Accordion.Root.Context = { - accordionSectionRefs: { current: [] }, + accordionItemRefs: { current: [] }, animated: false, direction: 'ltr', disabled: false, @@ -24,7 +24,7 @@ const accordionRootContextValue: Accordion.Root.Context = { value: [0], }; -const accordionSectionContextValue: Accordion.Section.Context = { +const accordionItemContextValue: Accordion.Item.Context = { open: true, ownerState: { value: [0], @@ -53,18 +53,18 @@ const collapsibleContextValue: Collapsible.Root.Context = { }, }; -describe('', () => { +describe('', () => { const { render } = createRenderer(); - describeConformance(, () => ({ + describeConformance(, () => ({ inheritComponent: 'h3', render: (node) => render( - + {node} - + , ), diff --git a/packages/mui-base/src/Accordion/Heading/AccordionHeading.tsx b/packages/mui-base/src/Accordion/Header/AccordionHeader.tsx similarity index 73% rename from packages/mui-base/src/Accordion/Heading/AccordionHeading.tsx rename to packages/mui-base/src/Accordion/Header/AccordionHeader.tsx index 55584806c..280462943 100644 --- a/packages/mui-base/src/Accordion/Heading/AccordionHeading.tsx +++ b/packages/mui-base/src/Accordion/Header/AccordionHeader.tsx @@ -3,9 +3,9 @@ import * as React from 'react'; import PropTypes from 'prop-types'; import { BaseUIComponentProps } from '../../utils/types'; import { useComponentRenderer } from '../../utils/useComponentRenderer'; -import type { AccordionSection } from '../Section/AccordionSection'; -import { useAccordionSectionContext } from '../Section/AccordionSectionContext'; -import { accordionStyleHookMapping } from '../Section/styleHooks'; +import type { AccordionItem } from '../Item/AccordionItem'; +import { useAccordionItemContext } from '../Item/AccordionItemContext'; +import { accordionStyleHookMapping } from '../Item/styleHooks'; /** * @@ -15,15 +15,15 @@ import { accordionStyleHookMapping } from '../Section/styleHooks'; * * API: * - * - [AccordionHeading API](https://base-ui.netlify.app/components/react-accordion/#api-reference-AccordionHeading) + * - [AccordionHeader API](https://base-ui.netlify.app/components/react-accordion/#api-reference-AccordionHeader) */ -const AccordionHeading = React.forwardRef(function AccordionHeading( - props: AccordionHeading.Props, +const AccordionHeader = React.forwardRef(function AccordionHeader( + props: AccordionHeader.Props, forwardedRef: React.ForwardedRef, ) { const { render, className, ...otherProps } = props; - const { ownerState } = useAccordionSectionContext(); + const { ownerState } = useAccordionItemContext(); const { renderElement } = useComponentRenderer({ render: render ?? 'h3', @@ -37,13 +37,13 @@ const AccordionHeading = React.forwardRef(function AccordionHeading( return renderElement(); }); -export { AccordionHeading }; +export { AccordionHeader }; -export namespace AccordionHeading { - export interface Props extends BaseUIComponentProps<'h3', AccordionSection.OwnerState> {} +export namespace AccordionHeader { + export interface Props extends BaseUIComponentProps<'h3', AccordionItem.OwnerState> {} } -AccordionHeading.propTypes /* remove-proptypes */ = { +AccordionHeader.propTypes /* remove-proptypes */ = { // ┌────────────────────────────── Warning ──────────────────────────────┐ // │ These PropTypes are generated from the TypeScript type definitions. │ // │ To update them, edit the TypeScript types and run `pnpm proptypes`. │ diff --git a/packages/mui-base/src/Accordion/Section/AccordionSection.test.tsx b/packages/mui-base/src/Accordion/Item/AccordionItem.test.tsx similarity index 85% rename from packages/mui-base/src/Accordion/Section/AccordionSection.test.tsx rename to packages/mui-base/src/Accordion/Item/AccordionItem.test.tsx index f13adf883..c4e0d80ad 100644 --- a/packages/mui-base/src/Accordion/Section/AccordionSection.test.tsx +++ b/packages/mui-base/src/Accordion/Item/AccordionItem.test.tsx @@ -7,7 +7,7 @@ import { describeConformance, createRenderer } from '#test-utils'; const { AccordionRootContext } = Accordion; const accordionRootContextValue: Accordion.Root.Context = { - accordionSectionRefs: { current: [] }, + accordionItemRefs: { current: [] }, animated: false, direction: 'ltr', disabled: false, @@ -21,10 +21,10 @@ const accordionRootContextValue: Accordion.Root.Context = { value: [0], }; -describe('', () => { +describe('', () => { const { render } = createRenderer(); - describeConformance(, () => ({ + describeConformance(, () => ({ inheritComponent: 'div', render: (node) => render( diff --git a/packages/mui-base/src/Accordion/Section/AccordionSection.tsx b/packages/mui-base/src/Accordion/Item/AccordionItem.tsx similarity index 88% rename from packages/mui-base/src/Accordion/Section/AccordionSection.tsx rename to packages/mui-base/src/Accordion/Item/AccordionItem.tsx index 77b4d1914..59a007e13 100644 --- a/packages/mui-base/src/Accordion/Section/AccordionSection.tsx +++ b/packages/mui-base/src/Accordion/Item/AccordionItem.tsx @@ -13,7 +13,7 @@ import { CollapsibleContext } from '../../Collapsible/Root/CollapsibleContext'; import { useCompositeListItem } from '../../Composite/List/useCompositeListItem'; import type { AccordionRoot } from '../Root/AccordionRoot'; import { useAccordionRootContext } from '../Root/AccordionRootContext'; -import { AccordionSectionContext } from './AccordionSectionContext'; +import { AccordionItemContext } from './AccordionItemContext'; import { accordionStyleHookMapping } from './styleHooks'; /** @@ -24,10 +24,10 @@ import { accordionStyleHookMapping } from './styleHooks'; * * API: * - * - [AccordionSection API](https://base-ui.netlify.app/components/react-accordion/#api-reference-AccordionSection) + * - [AccordionItem API](https://base-ui.netlify.app/components/react-accordion/#api-reference-AccordionItem) */ -const AccordionSection = React.forwardRef(function AccordionSection( - props: AccordionSection.Props, +const AccordionItem = React.forwardRef(function AccordionItem( + props: AccordionItem.Props, forwardedRef: React.ForwardedRef, ) { const { @@ -100,7 +100,7 @@ const AccordionSection = React.forwardRef(function AccordionSection( [collapsible, collapsibleOwnerState], ); - const ownerState: AccordionSection.OwnerState = React.useMemo( + const ownerState: AccordionItem.OwnerState = React.useMemo( () => ({ ...rootOwnerState, index, @@ -113,7 +113,7 @@ const AccordionSection = React.forwardRef(function AccordionSection( const triggerId = useId(); - const accordionSectionContext: AccordionSection.Context = React.useMemo( + const accordionItemContext: AccordionItem.Context = React.useMemo( () => ({ open: isOpen, triggerId, @@ -133,16 +133,16 @@ const AccordionSection = React.forwardRef(function AccordionSection( return ( - + {renderElement()} - + ); }); -export { AccordionSection }; +export { AccordionItem }; -export namespace AccordionSection { +export namespace AccordionItem { export type Value = number | string; export interface Context { @@ -164,7 +164,7 @@ export namespace AccordionSection { } } -AccordionSection.propTypes /* remove-proptypes */ = { +AccordionItem.propTypes /* remove-proptypes */ = { // ┌────────────────────────────── Warning ──────────────────────────────┐ // │ These PropTypes are generated from the TypeScript type definitions. │ // │ To update them, edit the TypeScript types and run `pnpm proptypes`. │ diff --git a/packages/mui-base/src/Accordion/Item/AccordionItemContext.tsx b/packages/mui-base/src/Accordion/Item/AccordionItemContext.tsx new file mode 100644 index 000000000..5d9acd817 --- /dev/null +++ b/packages/mui-base/src/Accordion/Item/AccordionItemContext.tsx @@ -0,0 +1,22 @@ +'use client'; +import * as React from 'react'; +import type { AccordionItem } from './AccordionItem'; + +/** + * @ignore - internal component. + */ +export const AccordionItemContext = React.createContext( + undefined, +); + +if (process.env.NODE_ENV !== 'production') { + AccordionItemContext.displayName = 'AccordionItemContext'; +} + +export function useAccordionItemContext() { + const context = React.useContext(AccordionItemContext); + if (context === undefined) { + throw new Error('useAccordionItemContext must be used inside the component'); + } + return context; +} diff --git a/packages/mui-base/src/Accordion/Section/styleHooks.ts b/packages/mui-base/src/Accordion/Item/styleHooks.ts similarity index 88% rename from packages/mui-base/src/Accordion/Section/styleHooks.ts rename to packages/mui-base/src/Accordion/Item/styleHooks.ts index 09c391732..266bfa99e 100644 --- a/packages/mui-base/src/Accordion/Section/styleHooks.ts +++ b/packages/mui-base/src/Accordion/Item/styleHooks.ts @@ -1,7 +1,7 @@ import type { CustomStyleHookMapping } from '../../utils/getStyleHookProps'; -import type { AccordionSection } from './AccordionSection'; +import type { AccordionItem } from './AccordionItem'; -export const accordionStyleHookMapping: CustomStyleHookMapping = { +export const accordionStyleHookMapping: CustomStyleHookMapping = { disabled: (value) => { if (value) { return { 'data-disabled': '' }; diff --git a/packages/mui-base/src/Accordion/Panel/AccordionPanel.test.tsx b/packages/mui-base/src/Accordion/Panel/AccordionPanel.test.tsx index 43426a7ff..7b3c88def 100644 --- a/packages/mui-base/src/Accordion/Panel/AccordionPanel.test.tsx +++ b/packages/mui-base/src/Accordion/Panel/AccordionPanel.test.tsx @@ -5,12 +5,12 @@ import * as Accordion from '@base_ui/react/Accordion'; import * as Collapsible from '@base_ui/react/Collapsible'; import { describeConformance, createRenderer } from '#test-utils'; -const { AccordionRootContext, AccordionSectionContext } = Accordion; +const { AccordionRootContext, AccordionItemContext } = Accordion; const { CollapsibleContext } = Collapsible; const accordionRootContextValue: Accordion.Root.Context = { - accordionSectionRefs: { current: [] }, + accordionItemRefs: { current: [] }, animated: false, direction: 'ltr', disabled: false, @@ -24,7 +24,7 @@ const accordionRootContextValue: Accordion.Root.Context = { value: [0], }; -const accordionSectionContextValue: Accordion.Section.Context = { +const accordionItemContextValue: Accordion.Item.Context = { open: true, ownerState: { value: [0], @@ -62,9 +62,9 @@ describe('', () => { render( - + {node} - + , ), diff --git a/packages/mui-base/src/Accordion/Panel/AccordionPanel.tsx b/packages/mui-base/src/Accordion/Panel/AccordionPanel.tsx index e0af4fbde..dd42ff9dd 100644 --- a/packages/mui-base/src/Accordion/Panel/AccordionPanel.tsx +++ b/packages/mui-base/src/Accordion/Panel/AccordionPanel.tsx @@ -6,9 +6,9 @@ import { useComponentRenderer } from '../../utils/useComponentRenderer'; import { useCollapsibleContext } from '../../Collapsible/Root/CollapsibleContext'; import { useCollapsibleContent } from '../../Collapsible/Content/useCollapsibleContent'; import { useAccordionRootContext } from '../Root/AccordionRootContext'; -import type { AccordionSection } from '../Section/AccordionSection'; -import { useAccordionSectionContext } from '../Section/AccordionSectionContext'; -import { accordionStyleHookMapping } from '../Section/styleHooks'; +import type { AccordionItem } from '../Item/AccordionItem'; +import { useAccordionItemContext } from '../Item/AccordionItemContext'; +import { accordionStyleHookMapping } from '../Item/styleHooks'; /** * @@ -43,7 +43,7 @@ const AccordionPanel = React.forwardRef(function AccordionPanel( setOpen, }); - const { ownerState, triggerId } = useAccordionSectionContext(); + const { ownerState, triggerId } = useAccordionItemContext(); const { renderElement } = useComponentRenderer({ propGetter: getRootProps, @@ -69,7 +69,7 @@ export { AccordionPanel }; export namespace AccordionPanel { export interface Props - extends BaseUIComponentProps<'div', AccordionSection.OwnerState>, + extends BaseUIComponentProps<'div', AccordionItem.OwnerState>, Pick {} } diff --git a/packages/mui-base/src/Accordion/Root/AccordionRoot.tsx b/packages/mui-base/src/Accordion/Root/AccordionRoot.tsx index 13e3d62a5..59ed59ce5 100644 --- a/packages/mui-base/src/Accordion/Root/AccordionRoot.tsx +++ b/packages/mui-base/src/Accordion/Root/AccordionRoot.tsx @@ -97,7 +97,7 @@ const AccordionRoot = React.forwardRef(function AccordionRoot( return ( - {renderElement()} + {renderElement()} ); }); @@ -138,7 +138,7 @@ AccordionRoot.propTypes /* remove-proptypes */ = { */ className: PropTypes.oneOfType([PropTypes.func, PropTypes.string]), /** - * The default value representing the currently open `Accordion.Section` + * The default value representing the currently open `Accordion.Item` * This is the uncontrolled counterpart of `value`. * @default 0 */ @@ -177,7 +177,7 @@ AccordionRoot.propTypes /* remove-proptypes */ = { */ render: PropTypes.oneOfType([PropTypes.element, PropTypes.func]), /** - * The value of the currently open `Accordion.Section` + * The value of the currently open `Accordion.Item` * This is the controlled counterpart of `defaultValue`. */ value: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired), diff --git a/packages/mui-base/src/Accordion/Root/useAccordionRoot.ts b/packages/mui-base/src/Accordion/Root/useAccordionRoot.ts index 1aaada22a..6a3a75a7e 100644 --- a/packages/mui-base/src/Accordion/Root/useAccordionRoot.ts +++ b/packages/mui-base/src/Accordion/Root/useAccordionRoot.ts @@ -7,15 +7,15 @@ import { ARROW_DOWN, ARROW_UP, ARROW_RIGHT, ARROW_LEFT } from '../../Composite/c const SUPPORTED_KEYS = [ARROW_DOWN, ARROW_UP, ARROW_RIGHT, ARROW_LEFT, 'Home', 'End']; -function getActiveTriggers(accordionSectionRefs: { +function getActiveTriggers(accordionItemRefs: { current: (HTMLElement | null)[]; }): HTMLButtonElement[] { - const { current: accordionSectionElements } = accordionSectionRefs; + const { current: accordionItemElements } = accordionItemRefs; const output: HTMLButtonElement[] = []; - for (let i = 0; i < accordionSectionElements.length; i += 1) { - const section = accordionSectionElements[i]; + for (let i = 0; i < accordionItemElements.length; i += 1) { + const section = accordionItemElements[i]; if (!isDisabled(section)) { const trigger = section?.querySelector('[type="button"]') as HTMLButtonElement; if (!isDisabled(trigger)) { @@ -49,7 +49,7 @@ export function useAccordionRoot( defaultValue, } = parameters; - const accordionSectionRefs = React.useRef<(HTMLElement | null)[]>([]); + const accordionItemRefs = React.useRef<(HTMLElement | null)[]>([]); const [value, setValue] = useControlled({ controlled: valueParam, @@ -92,7 +92,7 @@ export function useAccordionRoot( event.preventDefault(); - const triggers = getActiveTriggers(accordionSectionRefs); + const triggers = getActiveTriggers(accordionItemRefs); const numOfEnabledTriggers = triggers.length; const lastIndex = numOfEnabledTriggers - 1; @@ -160,7 +160,7 @@ export function useAccordionRoot( return React.useMemo( () => ({ getRootProps, - accordionSectionRefs, + accordionItemRefs, animated, direction, disabled, @@ -170,7 +170,7 @@ export function useAccordionRoot( }), [ getRootProps, - accordionSectionRefs, + accordionItemRefs, animated, direction, disabled, @@ -190,12 +190,12 @@ export namespace useAccordionRoot { export interface Parameters { /** - * The value of the currently open `Accordion.Section` + * The value of the currently open `Accordion.Item` * This is the controlled counterpart of `defaultValue`. */ value?: Value; /** - * The default value representing the currently open `Accordion.Section` + * The default value representing the currently open `Accordion.Item` * This is the uncontrolled counterpart of `value`. * @default 0 */ @@ -234,7 +234,7 @@ export namespace useAccordionRoot { getRootProps: ( externalProps?: React.ComponentPropsWithRef<'div'>, ) => React.ComponentPropsWithRef<'div'>; - accordionSectionRefs: React.MutableRefObject<(HTMLElement | null)[]>; + accordionItemRefs: React.MutableRefObject<(HTMLElement | null)[]>; animated: boolean; direction: Direction; /** @@ -245,7 +245,7 @@ export namespace useAccordionRoot { orientation: Orientation; /** * The open state of the Accordion represented by an array of the values - * of all open ``s + * of all open ``s */ value: Value; } diff --git a/packages/mui-base/src/Accordion/Section/AccordionSectionContext.tsx b/packages/mui-base/src/Accordion/Section/AccordionSectionContext.tsx deleted file mode 100644 index 291a16a06..000000000 --- a/packages/mui-base/src/Accordion/Section/AccordionSectionContext.tsx +++ /dev/null @@ -1,24 +0,0 @@ -'use client'; -import * as React from 'react'; -import type { AccordionSection } from './AccordionSection'; - -/** - * @ignore - internal component. - */ -export const AccordionSectionContext = React.createContext( - undefined, -); - -if (process.env.NODE_ENV !== 'production') { - AccordionSectionContext.displayName = 'AccordionSectionContext'; -} - -export function useAccordionSectionContext() { - const context = React.useContext(AccordionSectionContext); - if (context === undefined) { - throw new Error( - 'useAccordionSectionContext must be used inside the component', - ); - } - return context; -} diff --git a/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.test.tsx b/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.test.tsx index 815cf3f5c..504a86493 100644 --- a/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.test.tsx +++ b/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.test.tsx @@ -5,12 +5,12 @@ import * as Accordion from '@base_ui/react/Accordion'; import * as Collapsible from '@base_ui/react/Collapsible'; import { describeConformance, createRenderer } from '#test-utils'; -const { AccordionRootContext, AccordionSectionContext } = Accordion; +const { AccordionRootContext, AccordionItemContext } = Accordion; const { CollapsibleContext } = Collapsible; const accordionRootContextValue: Accordion.Root.Context = { - accordionSectionRefs: { current: [] }, + accordionItemRefs: { current: [] }, animated: false, direction: 'ltr', disabled: false, @@ -24,7 +24,7 @@ const accordionRootContextValue: Accordion.Root.Context = { value: [0], }; -const accordionSectionContextValue: Accordion.Section.Context = { +const accordionItemContextValue: Accordion.Item.Context = { open: true, ownerState: { value: [0], @@ -62,9 +62,9 @@ describe('', () => { render( - + {node} - + , ), diff --git a/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.tsx b/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.tsx index c67f264ef..26dca018c 100644 --- a/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.tsx +++ b/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.tsx @@ -5,9 +5,9 @@ import { useComponentRenderer } from '../../utils/useComponentRenderer'; import { BaseUIComponentProps } from '../../utils/types'; import { useCollapsibleContext } from '../../Collapsible/Root/CollapsibleContext'; import { useCollapsibleTrigger } from '../../Collapsible/Trigger/useCollapsibleTrigger'; -import type { AccordionSection } from '../Section/AccordionSection'; -import { useAccordionSectionContext } from '../Section/AccordionSectionContext'; -import { accordionStyleHookMapping } from '../Section/styleHooks'; +import type { AccordionItem } from '../Item/AccordionItem'; +import { useAccordionItemContext } from '../Item/AccordionItemContext'; +import { accordionStyleHookMapping } from '../Item/styleHooks'; /** * @@ -35,7 +35,7 @@ const AccordionTrigger = React.forwardRef(function AccordionTrigger( setOpen, }); - const { ownerState, triggerId } = useAccordionSectionContext(); + const { ownerState, triggerId } = useAccordionItemContext(); const { renderElement } = useComponentRenderer({ propGetter: getRootProps, @@ -52,7 +52,7 @@ const AccordionTrigger = React.forwardRef(function AccordionTrigger( export { AccordionTrigger }; namespace AccordionTrigger { - export interface Props extends BaseUIComponentProps<'button', AccordionSection.OwnerState> {} + export interface Props extends BaseUIComponentProps<'button', AccordionItem.OwnerState> {} } AccordionTrigger.propTypes /* remove-proptypes */ = { diff --git a/packages/mui-base/src/Accordion/index.barrel.ts b/packages/mui-base/src/Accordion/index.barrel.ts index 0d057e061..bb850626d 100644 --- a/packages/mui-base/src/Accordion/index.barrel.ts +++ b/packages/mui-base/src/Accordion/index.barrel.ts @@ -1,5 +1,5 @@ export * from './Root/AccordionRoot'; -export * from './Section/AccordionSection'; -export * from './Heading/AccordionHeading'; +export * from './Item/AccordionItem'; +export * from './Header/AccordionHeader'; export * from './Trigger/AccordionTrigger'; export * from './Panel/AccordionPanel'; diff --git a/packages/mui-base/src/Accordion/index.ts b/packages/mui-base/src/Accordion/index.ts index 7a9efb6c1..3077ffa4a 100644 --- a/packages/mui-base/src/Accordion/index.ts +++ b/packages/mui-base/src/Accordion/index.ts @@ -2,12 +2,9 @@ export { AccordionRoot as Root } from './Root/AccordionRoot'; export { useAccordionRoot } from './Root/useAccordionRoot'; export { AccordionRootContext, useAccordionRootContext } from './Root/AccordionRootContext'; -export { AccordionSection as Section } from './Section/AccordionSection'; -export { - AccordionSectionContext, - useAccordionSectionContext, -} from './Section/AccordionSectionContext'; +export { AccordionItem as Item } from './Item/AccordionItem'; +export { AccordionItemContext, useAccordionItemContext } from './Item/AccordionItemContext'; -export { AccordionHeading as Heading } from './Heading/AccordionHeading'; +export { AccordionHeader as Header } from './Header/AccordionHeader'; export { AccordionTrigger as Trigger } from './Trigger/AccordionTrigger'; export { AccordionPanel as Panel } from './Panel/AccordionPanel'; From 9605d9f832780903c3ee523d28cffee27fe420ac Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Wed, 11 Sep 2024 17:14:59 +0800 Subject: [PATCH 08/37] Support focus loop --- docs/data/api/accordion-root.json | 1 + .../accordion-root/accordion-root.json | 3 +++ .../src/Accordion/Root/AccordionRoot.tsx | 8 +++++++ .../src/Accordion/Root/useAccordionRoot.ts | 21 ++++++++++++++++--- 4 files changed, 30 insertions(+), 3 deletions(-) diff --git a/docs/data/api/accordion-root.json b/docs/data/api/accordion-root.json index 64ea416c3..0ae33d890 100644 --- a/docs/data/api/accordion-root.json +++ b/docs/data/api/accordion-root.json @@ -7,6 +7,7 @@ "default": "0" }, "disabled": { "type": { "name": "bool" }, "default": "false" }, + "loop": { "type": { "name": "bool" }, "default": "true" }, "onOpenChange": { "type": { "name": "func" } }, "openMultiple": { "type": { "name": "bool" }, "default": "true" }, "render": { "type": { "name": "union", "description": "element
| func" } }, diff --git a/docs/data/translations/api-docs/accordion-root/accordion-root.json b/docs/data/translations/api-docs/accordion-root/accordion-root.json index 900b8b029..251be809f 100644 --- a/docs/data/translations/api-docs/accordion-root/accordion-root.json +++ b/docs/data/translations/api-docs/accordion-root/accordion-root.json @@ -11,6 +11,9 @@ "description": "The default value representing the currently open Accordion.Item This is the uncontrolled counterpart of value." }, "disabled": { "description": "If true, the component is disabled." }, + "loop": { + "description": "If true, focus will loop when moving focus between Triggers using the arrow keys." + }, "onOpenChange": { "description": "Callback fired when an Accordion section is opened or closed. The value representing the involved section is provided as an argument." }, diff --git a/packages/mui-base/src/Accordion/Root/AccordionRoot.tsx b/packages/mui-base/src/Accordion/Root/AccordionRoot.tsx index 59ed59ce5..820fb3111 100644 --- a/packages/mui-base/src/Accordion/Root/AccordionRoot.tsx +++ b/packages/mui-base/src/Accordion/Root/AccordionRoot.tsx @@ -28,6 +28,7 @@ const AccordionRoot = React.forwardRef(function AccordionRoot( direction, disabled = false, htmlHidden, + loop, onOpenChange, openMultiple = true, orientation, @@ -52,6 +53,7 @@ const AccordionRoot = React.forwardRef(function AccordionRoot( direction, disabled, defaultValue, + loop, orientation, onOpenChange, openMultiple, @@ -158,6 +160,12 @@ AccordionRoot.propTypes /* remove-proptypes */ = { * @ignore */ htmlHidden: PropTypes.oneOf(['hidden', 'until-found']), + /** + * If `true`, focus will loop when moving focus between `Trigger`s using + * the arrow keys. + * @default true + */ + loop: PropTypes.bool, /** * Callback fired when an Accordion section is opened or closed. * The value representing the involved section is provided as an argument. diff --git a/packages/mui-base/src/Accordion/Root/useAccordionRoot.ts b/packages/mui-base/src/Accordion/Root/useAccordionRoot.ts index 6a3a75a7e..b4f4caafc 100644 --- a/packages/mui-base/src/Accordion/Root/useAccordionRoot.ts +++ b/packages/mui-base/src/Accordion/Root/useAccordionRoot.ts @@ -42,6 +42,7 @@ export function useAccordionRoot( animated = true, disabled = false, direction = 'ltr', + loop = true, onOpenChange = NOOP, orientation = 'vertical', openMultiple = true, @@ -102,11 +103,19 @@ export function useAccordionRoot( const thisIndex = triggers.indexOf(event.target as HTMLButtonElement); function toNext() { - nextIndex = Math.min(thisIndex + 1, lastIndex); + if (loop) { + nextIndex = thisIndex + 1 > lastIndex ? 0 : thisIndex + 1; + } else { + nextIndex = Math.min(thisIndex + 1, lastIndex); + } } function toPrev() { - nextIndex = thisIndex - 1; + if (loop) { + nextIndex = thisIndex === 0 ? lastIndex : thisIndex - 1; + } else { + nextIndex = thisIndex - 1; + } } switch (event.key) { @@ -154,7 +163,7 @@ export function useAccordionRoot( }, }); }, - [direction, orientation], + [direction, loop, orientation], ); return React.useMemo( @@ -214,6 +223,12 @@ export namespace useAccordionRoot { * @default 'ltr' */ direction?: Direction; + /** + * If `true`, focus will loop when moving focus between `Trigger`s using + * the arrow keys. + * @default true + */ + loop?: boolean; /** * Callback fired when an Accordion section is opened or closed. * The value representing the involved section is provided as an argument. From bfc09a128af58cf24b6a62f0de1e640db57d5552 Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Mon, 16 Sep 2024 18:56:18 +0800 Subject: [PATCH 09/37] Add tests --- docs/data/components/accordion/accordion.mdx | 4 +- .../Accordion/Header/AccordionHeader.test.tsx | 9 +- .../src/Accordion/Item/AccordionItem.test.tsx | 3 +- .../src/Accordion/Item/AccordionItem.tsx | 10 +- .../mui-base/src/Accordion/Item/styleHooks.ts | 2 +- .../Accordion/Panel/AccordionPanel.test.tsx | 11 +- .../src/Accordion/Panel/AccordionPanel.tsx | 8 +- .../src/Accordion/Root/AccordionRoot.test.tsx | 817 +++++++++++++++++- .../Trigger/AccordionTrigger.test.tsx | 11 +- .../Accordion/Trigger/AccordionTrigger.tsx | 17 +- .../Trigger/useCollapsibleTrigger.ts | 6 +- 11 files changed, 871 insertions(+), 27 deletions(-) diff --git a/docs/data/components/accordion/accordion.mdx b/docs/data/components/accordion/accordion.mdx index aea5106ee..a561d8dcd 100644 --- a/docs/data/components/accordion/accordion.mdx +++ b/docs/data/components/accordion/accordion.mdx @@ -210,8 +210,8 @@ Accordion uses [`Collapsible`](/components/react-collapsible/) internally, and c Four states are available as data attributes to animate the `Accordion.Panel`: -- `[data-collapsible="open"]` - `open` state is `true`. -- `[data-collapsible="closed"]` - `open` state is `false`. Can still be mounted to the DOM if closing. +- `[data-accordion="open"]` - `open` state is `true`. +- `[data-accordion="closed"]` - `open` state is `false`. Can still be mounted to the DOM if closing. - `[data-entering]` - the `hidden` attribute was just removed from the DOM and the content element participates in page layout. The `data-entering` attribute will be removed 1 animation frame later. - `[data-exiting]` - the content element is in the process of being hidden from the DOM, but is still mounted. diff --git a/packages/mui-base/src/Accordion/Header/AccordionHeader.test.tsx b/packages/mui-base/src/Accordion/Header/AccordionHeader.test.tsx index 506bb7755..608b8cbd5 100644 --- a/packages/mui-base/src/Accordion/Header/AccordionHeader.test.tsx +++ b/packages/mui-base/src/Accordion/Header/AccordionHeader.test.tsx @@ -4,6 +4,7 @@ import * as React from 'react'; import * as Accordion from '@base_ui/react/Accordion'; import * as Collapsible from '@base_ui/react/Collapsible'; import { describeConformance, createRenderer } from '#test-utils'; +import { NOOP } from '../../utils/noop'; const { AccordionRootContext, AccordionItemContext } = Accordion; @@ -34,6 +35,8 @@ const accordionItemContextValue: Accordion.Item.Context = { orientation: 'vertical', transitionStatus: undefined, }, + setTriggerId: NOOP, + triggerId: ':trigger:', }; const collapsibleContextValue: Collapsible.Root.Context = { @@ -42,9 +45,9 @@ const collapsibleContextValue: Collapsible.Root.Context = { disabled: false, mounted: true, open: true, - setContentId() {}, - setMounted() {}, - setOpen() {}, + setContentId: NOOP, + setMounted: NOOP, + setOpen: NOOP, transitionStatus: undefined, ownerState: { open: true, diff --git a/packages/mui-base/src/Accordion/Item/AccordionItem.test.tsx b/packages/mui-base/src/Accordion/Item/AccordionItem.test.tsx index c4e0d80ad..c8feca507 100644 --- a/packages/mui-base/src/Accordion/Item/AccordionItem.test.tsx +++ b/packages/mui-base/src/Accordion/Item/AccordionItem.test.tsx @@ -3,6 +3,7 @@ import * as React from 'react'; // import { spy } from 'sinon'; import * as Accordion from '@base_ui/react/Accordion'; import { describeConformance, createRenderer } from '#test-utils'; +import { NOOP } from '../../utils/noop'; const { AccordionRootContext } = Accordion; @@ -11,7 +12,7 @@ const accordionRootContextValue: Accordion.Root.Context = { animated: false, direction: 'ltr', disabled: false, - handleOpenChange() {}, + handleOpenChange: NOOP, orientation: 'vertical', ownerState: { value: [0], diff --git a/packages/mui-base/src/Accordion/Item/AccordionItem.tsx b/packages/mui-base/src/Accordion/Item/AccordionItem.tsx index 59a007e13..f09d0fcf8 100644 --- a/packages/mui-base/src/Accordion/Item/AccordionItem.tsx +++ b/packages/mui-base/src/Accordion/Item/AccordionItem.tsx @@ -111,15 +111,16 @@ const AccordionItem = React.forwardRef(function AccordionItem( [collapsible.transitionStatus, disabled, index, isOpen, rootOwnerState], ); - const triggerId = useId(); + const [triggerId, setTriggerId] = React.useState(useId()); const accordionItemContext: AccordionItem.Context = React.useMemo( () => ({ open: isOpen, - triggerId, ownerState, + setTriggerId, + triggerId, }), - [isOpen, ownerState, triggerId], + [isOpen, ownerState, setTriggerId, triggerId], ); const { renderElement } = useComponentRenderer({ @@ -147,8 +148,9 @@ export namespace AccordionItem { export interface Context { open: boolean; - triggerId?: string; ownerState: OwnerState; + setTriggerId: (id: string | undefined) => void; + triggerId?: string; } export interface OwnerState extends AccordionRoot.OwnerState { diff --git a/packages/mui-base/src/Accordion/Item/styleHooks.ts b/packages/mui-base/src/Accordion/Item/styleHooks.ts index 266bfa99e..391fa5585 100644 --- a/packages/mui-base/src/Accordion/Item/styleHooks.ts +++ b/packages/mui-base/src/Accordion/Item/styleHooks.ts @@ -12,7 +12,7 @@ export const accordionStyleHookMapping: CustomStyleHookMapping { - return value ? { 'data-collapsible': 'open' } : { 'data-collapsible': 'closed' }; + return value ? { 'data-accordion': 'open' } : { 'data-accordion': 'closed' }; }, transitionStatus: (value) => { if (value === 'entering') { diff --git a/packages/mui-base/src/Accordion/Panel/AccordionPanel.test.tsx b/packages/mui-base/src/Accordion/Panel/AccordionPanel.test.tsx index 7b3c88def..748afdc14 100644 --- a/packages/mui-base/src/Accordion/Panel/AccordionPanel.test.tsx +++ b/packages/mui-base/src/Accordion/Panel/AccordionPanel.test.tsx @@ -4,6 +4,7 @@ import * as React from 'react'; import * as Accordion from '@base_ui/react/Accordion'; import * as Collapsible from '@base_ui/react/Collapsible'; import { describeConformance, createRenderer } from '#test-utils'; +import { NOOP } from '../../utils/noop'; const { AccordionRootContext, AccordionItemContext } = Accordion; @@ -14,7 +15,7 @@ const accordionRootContextValue: Accordion.Root.Context = { animated: false, direction: 'ltr', disabled: false, - handleOpenChange() {}, + handleOpenChange: NOOP, orientation: 'vertical', ownerState: { value: [0], @@ -34,6 +35,8 @@ const accordionItemContextValue: Accordion.Item.Context = { orientation: 'vertical', transitionStatus: undefined, }, + setTriggerId: NOOP, + triggerId: ':trigger:', }; const collapsibleContextValue: Collapsible.Root.Context = { @@ -42,9 +45,9 @@ const collapsibleContextValue: Collapsible.Root.Context = { disabled: false, mounted: true, open: true, - setContentId() {}, - setMounted() {}, - setOpen() {}, + setContentId: NOOP, + setMounted: NOOP, + setOpen: NOOP, transitionStatus: undefined, ownerState: { open: true, diff --git a/packages/mui-base/src/Accordion/Panel/AccordionPanel.tsx b/packages/mui-base/src/Accordion/Panel/AccordionPanel.tsx index dd42ff9dd..a282745c9 100644 --- a/packages/mui-base/src/Accordion/Panel/AccordionPanel.tsx +++ b/packages/mui-base/src/Accordion/Panel/AccordionPanel.tsx @@ -24,7 +24,7 @@ const AccordionPanel = React.forwardRef(function AccordionPanel( props: AccordionPanel.Props, forwardedRef: React.ForwardedRef, ) { - const { className, htmlHidden: htmlHiddenProp, render, ...otherProps } = props; + const { className, htmlHidden: htmlHiddenProp, id: idProp, render, ...otherProps } = props; const { animated, mounted, open, contentId, setContentId, setMounted, setOpen } = useCollapsibleContext(); @@ -34,7 +34,7 @@ const AccordionPanel = React.forwardRef(function AccordionPanel( const { getRootProps, height, width } = useCollapsibleContent({ animated, htmlHidden: htmlHiddenProp || htmlHidden, - id: contentId, + id: idProp ?? contentId, mounted, open, ref: forwardedRef, @@ -91,6 +91,10 @@ AccordionPanel.propTypes /* remove-proptypes */ = { * @default 'hidden' */ htmlHidden: PropTypes.oneOf(['hidden', 'until-found']), + /** + * @ignore + */ + id: PropTypes.string, /** * A function to customize rendering of the component. */ diff --git a/packages/mui-base/src/Accordion/Root/AccordionRoot.test.tsx b/packages/mui-base/src/Accordion/Root/AccordionRoot.test.tsx index e8fdbc9a0..38eeaae7e 100644 --- a/packages/mui-base/src/Accordion/Root/AccordionRoot.test.tsx +++ b/packages/mui-base/src/Accordion/Root/AccordionRoot.test.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; -// import { expect } from 'chai'; -// import { spy } from 'sinon'; +import { expect } from 'chai'; +import { spy } from 'sinon'; import * as Accordion from '@base_ui/react/Accordion'; import { describeConformance, createRenderer } from '#test-utils'; @@ -12,4 +12,817 @@ describe('', () => { render, refInstanceof: window.HTMLDivElement, })); + + describe('ARIA attributes', () => { + it('renders correct ARIA attributes', async () => { + const { getByRole, getByTestId } = await render( + + + + Trigger 1 + + + This is the contents of Accordion.Panel 1 + + + , + ); + + const root = getByTestId('root'); + const trigger = getByRole('button'); + const panel = getByTestId('panel'); + + expect(root).to.have.attribute('role', 'region'); + expect(trigger).to.have.attribute('id', 'Trigger1'); + expect(trigger).to.have.attribute('aria-controls', 'Panel1'); + expect(panel).to.have.attribute('role', 'region'); + expect(panel).to.have.attribute('id', 'Panel1'); + expect(panel).to.have.attribute('aria-labelledby', 'Trigger1'); + }); + }); + + describe('uncontrolled', () => { + it('open state', async () => { + const { getByRole, getByTestId, user } = await render( + + + + Trigger 1 + + + This is the contents of Accordion.Panel 1 + + + , + ); + + const trigger = getByRole('button'); + const panel = getByTestId('panel'); + + expect(trigger).to.have.attribute('aria-expanded', 'false'); + expect(trigger).to.have.attribute('data-accordion', 'closed'); + expect(panel).to.have.attribute('hidden'); + expect(panel).to.have.attribute('data-accordion', 'closed'); + + await user.pointer({ keys: '[MouseLeft]', target: trigger }); + + expect(trigger).to.have.attribute('aria-expanded', 'true'); + expect(trigger).to.have.attribute('data-accordion', 'open'); + expect(panel).to.not.have.attribute('hidden'); + expect(panel).to.have.attribute('data-accordion', 'open'); + + await user.pointer({ keys: '[MouseLeft]', target: trigger }); + + expect(trigger).to.have.attribute('aria-expanded', 'false'); + expect(trigger).to.have.attribute('data-accordion', 'closed'); + expect(panel).to.have.attribute('hidden'); + expect(panel).to.have.attribute('data-accordion', 'closed'); + }); + + describe('prop: defaultValue', () => { + it('default item value', async () => { + const { getByTestId } = await render( + + + + Trigger 1 + + + This is the contents of Accordion.Panel 1 + + + + + Trigger 2 + + + This is the contents of Accordion.Panel 2 + + + , + ); + + const panel1 = getByTestId('panel1'); + const panel2 = getByTestId('panel2'); + + expect(panel1).to.have.attribute('data-accordion', 'closed'); + expect(panel2).to.have.attribute('data-accordion', 'open'); + }); + + it('custom item value', async () => { + const { getByTestId } = await render( + + + + Trigger 1 + + + This is the contents of Accordion.Panel 1 + + + + + Trigger 2 + + + This is the contents of Accordion.Panel 2 + + + , + ); + + const panel1 = getByTestId('panel1'); + const panel2 = getByTestId('panel2'); + + expect(panel1).to.have.attribute('data-accordion', 'open'); + expect(panel2).to.have.attribute('data-accordion', 'closed'); + }); + }); + }); + + describe('controlled', () => { + it('open state', async () => { + const { getByRole, getByTestId, setProps } = await render( + + + + Trigger 1 + + + This is the contents of Accordion.Panel 1 + + + , + ); + + const trigger = getByRole('button'); + const panel = getByTestId('panel'); + + expect(trigger).to.have.attribute('aria-expanded', 'false'); + expect(trigger).to.have.attribute('data-accordion', 'closed'); + expect(panel).to.have.attribute('hidden'); + expect(panel).to.have.attribute('data-accordion', 'closed'); + + setProps({ value: [0] }); + + expect(trigger).to.have.attribute('aria-expanded', 'true'); + expect(trigger).to.have.attribute('data-accordion', 'open'); + expect(panel).to.not.have.attribute('hidden'); + expect(panel).to.have.attribute('data-accordion', 'open'); + + setProps({ value: [] }); + + expect(trigger).to.have.attribute('aria-expanded', 'false'); + expect(trigger).to.have.attribute('data-accordion', 'closed'); + expect(panel).to.have.attribute('hidden'); + expect(panel).to.have.attribute('data-accordion', 'closed'); + }); + + describe('prop: value', () => { + it('default item value', async () => { + const { getByTestId } = await render( + + + + Trigger 1 + + + This is the contents of Accordion.Panel 1 + + + + + Trigger 2 + + + This is the contents of Accordion.Panel 2 + + + , + ); + + const panel1 = getByTestId('panel1'); + const panel2 = getByTestId('panel2'); + + expect(panel1).to.have.attribute('data-accordion', 'closed'); + expect(panel2).to.have.attribute('data-accordion', 'open'); + }); + + it('custom item value', async () => { + const { getByTestId } = await render( + + + + Trigger 1 + + + This is the contents of Accordion.Panel 1 + + + + + Trigger 2 + + + This is the contents of Accordion.Panel 2 + + + , + ); + + const panel1 = getByTestId('panel1'); + const panel2 = getByTestId('panel2'); + + expect(panel1).to.have.attribute('data-accordion', 'open'); + expect(panel2).to.have.attribute('data-accordion', 'closed'); + }); + }); + }); + + describe('prop: disabled', () => { + it('can disable the whole accordion', async () => { + const { getByTestId } = await render( + + + + Trigger 1 + + + This is the contents of Accordion.Panel 1 + + + + + Trigger 2 + + + This is the contents of Accordion.Panel 2 + + + , + ); + + const item1 = getByTestId('item1'); + const header1 = getByTestId('header1'); + const trigger1 = getByTestId('trigger1'); + const panel1 = getByTestId('panel1'); + const item2 = getByTestId('item2'); + const header2 = getByTestId('header2'); + const trigger2 = getByTestId('trigger2'); + const panel2 = getByTestId('panel2'); + + [item1, header1, trigger1, panel1, item2, header2, trigger2, panel2].forEach((element) => { + expect(element).to.have.attribute('data-disabled'); + }); + }); + + it('can disable one accordion item', async () => { + const { getByTestId } = await render( + + + + Trigger 1 + + + This is the contents of Accordion.Panel 1 + + + + + Trigger 2 + + + This is the contents of Accordion.Panel 2 + + + , + ); + + const item1 = getByTestId('item1'); + const header1 = getByTestId('header1'); + const trigger1 = getByTestId('trigger1'); + const panel1 = getByTestId('panel1'); + const item2 = getByTestId('item2'); + const header2 = getByTestId('header2'); + const trigger2 = getByTestId('trigger2'); + const panel2 = getByTestId('panel2'); + + [item1, header1, trigger1, panel1].forEach((element) => { + expect(element).to.have.attribute('data-disabled'); + }); + [item2, header2, trigger2, panel2].forEach((element) => { + expect(element).to.not.have.attribute('data-disabled'); + }); + }); + }); + + describe('keyboard interactions', () => { + ['Enter', 'Space'].forEach((key) => { + it(`key: ${key} toggles the Accordion open state`, async () => { + const { getByTestId, getByRole, user } = await render( + + + + Trigger 1 + + + This is the contents of Accordion.Panel 1 + + + , + ); + + const trigger = getByRole('button'); + const panel = getByTestId('panel'); + + expect(trigger).to.have.attribute('aria-expanded', 'false'); + expect(panel).to.have.attribute('hidden'); + expect(panel).to.have.attribute('data-accordion', 'closed'); + + await user.keyboard('[Tab]'); + expect(trigger).toHaveFocus(); + await user.keyboard(`[${key}]`); + + expect(trigger).to.have.attribute('aria-expanded', 'true'); + expect(panel).to.not.have.attribute('hidden'); + expect(panel).to.have.attribute('data-accordion', 'open'); + + await user.keyboard(`[${key}]`); + + expect(trigger).to.have.attribute('aria-expanded', 'false'); + expect(panel).to.have.attribute('data-accordion', 'closed'); + expect(panel).to.have.attribute('hidden'); + }); + }); + + it('ArrowUp and ArrowDown moves focus between triggers and loops by default', async () => { + const { getByTestId, user } = await render( + + + + Trigger 1 + + This is the contents of Accordion.Panel 1 + + + + Trigger 2 + + This is the contents of Accordion.Panel 2 + + , + ); + + const trigger1 = getByTestId('trigger1'); + const trigger2 = getByTestId('trigger2'); + + await user.keyboard('[Tab]'); + expect(trigger1).toHaveFocus(); + + await user.keyboard('[ArrowDown]'); + expect(trigger2).toHaveFocus(); + + await user.keyboard('[ArrowUp]'); + expect(trigger1).toHaveFocus(); + + await user.keyboard('[ArrowDown]'); + expect(trigger2).toHaveFocus(); + + await user.keyboard('[ArrowDown]'); + expect(trigger1).toHaveFocus(); + }); + + it('Arrow keys should not put focus on disabled accordion items', async () => { + const { getByTestId, user } = await render( + + + + Trigger 1 + + This is the contents of Accordion.Panel 1 + + + + Trigger 2 + + This is the contents of Accordion.Panel 2 + + + + Trigger 3 + + This is the contents of Accordion.Panel 3 + + , + ); + + const trigger1 = getByTestId('trigger1'); + const trigger3 = getByTestId('trigger3'); + + await user.keyboard('[Tab]'); + expect(trigger1).toHaveFocus(); + + await user.keyboard('[ArrowDown]'); + expect(trigger3).toHaveFocus(); + + await user.keyboard('[ArrowUp]'); + expect(trigger1).toHaveFocus(); + }); + + describe('key: End/Home', () => { + it('End key moves focus the last trigger', async () => { + const { getByTestId, user } = await render( + + + + Trigger 1 + + This is the contents of Accordion.Panel 1 + + + + Trigger 2 + + This is the contents of Accordion.Panel 2 + + + + Trigger 3 + + This is the contents of Accordion.Panel 3 + + + + Trigger 4 + + This is the contents of Accordion.Panel 4 + + , + ); + + const trigger1 = getByTestId('trigger1'); + const triggerFour = getByTestId('triggerFour'); + + await user.keyboard('[Tab]'); + expect(trigger1).toHaveFocus(); + + await user.keyboard('[End]'); + expect(triggerFour).toHaveFocus(); + }); + + it('Home key moves focus to the first trigger', async () => { + const { getByTestId, user } = await render( + + + + Trigger 1 + + This is the contents of Accordion.Panel 1 + + + + Trigger 2 + + This is the contents of Accordion.Panel 2 + + + + Trigger 3 + + This is the contents of Accordion.Panel 3 + + + + Trigger 4 + + This is the contents of Accordion.Panel 4 + + , + ); + + const trigger1 = getByTestId('trigger1'); + const triggerFour = getByTestId('triggerFour'); + + await user.pointer({ keys: '[MouseLeft]', target: triggerFour }); + expect(triggerFour).toHaveFocus(); + + await user.keyboard('[Home]'); + expect(trigger1).toHaveFocus(); + }); + }); + + describe('prop: loop', () => { + it('can disable focus looping between triggers', async () => { + const { getByTestId, user } = await render( + + + + Trigger 1 + + This is the contents of Accordion.Panel 1 + + + + Trigger 2 + + This is the contents of Accordion.Panel 2 + + , + ); + + const trigger1 = getByTestId('trigger1'); + const trigger2 = getByTestId('trigger2'); + + await user.keyboard('[Tab]'); + expect(trigger1).toHaveFocus(); + + await user.keyboard('[ArrowDown]'); + expect(trigger2).toHaveFocus(); + + await user.keyboard('[ArrowDown]'); + expect(trigger2).toHaveFocus(); + }); + }); + }); + + describe('prop: openMultiple', () => { + it('multiple items can be open by default', async () => { + const { getByTestId, user } = await render( + + + + Trigger 1 + + + This is the contents of Accordion.Panel 1 + + + + + Trigger 2 + + + This is the contents of Accordion.Panel 2 + + + , + ); + + const trigger1 = getByTestId('trigger1'); + const panel1 = getByTestId('panel1'); + const trigger2 = getByTestId('trigger2'); + const panel2 = getByTestId('panel2'); + + [trigger1, panel1, trigger2, panel2].forEach((element) => { + expect(element).to.have.attribute('data-accordion', 'closed'); + }); + + await user.pointer({ keys: '[MouseLeft]', target: trigger1 }); + await user.pointer({ keys: '[MouseLeft]', target: trigger2 }); + + [trigger1, panel1, trigger2, panel2].forEach((element) => { + expect(element).to.have.attribute('data-accordion', 'open'); + }); + }); + + it('when false only one item can be open', async () => { + const { getByTestId, user } = await render( + + + + Trigger 1 + + + This is the contents of Accordion.Panel 1 + + + + + Trigger 2 + + + This is the contents of Accordion.Panel 2 + + + , + ); + + const trigger1 = getByTestId('trigger1'); + const panel1 = getByTestId('panel1'); + const trigger2 = getByTestId('trigger2'); + const panel2 = getByTestId('panel2'); + + [trigger1, panel1, trigger2, panel2].forEach((element) => { + expect(element).to.have.attribute('data-accordion', 'closed'); + }); + + await user.pointer({ keys: '[MouseLeft]', target: trigger1 }); + + [trigger1, panel1].forEach((element) => { + expect(element).to.have.attribute('data-accordion', 'open'); + }); + + await user.pointer({ keys: '[MouseLeft]', target: trigger2 }); + + [trigger2, panel2].forEach((element) => { + expect(element).to.have.attribute('data-accordion', 'open'); + }); + [trigger1, panel1].forEach((element) => { + expect(element).to.have.attribute('data-accordion', 'closed'); + }); + }); + }); + + describe('horizontal orientation', () => { + it('ArrowLeft/Right moves focus in horizontal orientation', async () => { + const { getByTestId, user } = await render( + + + + Trigger 1 + + This is the contents of Accordion.Panel 1 + + + + Trigger 2 + + This is the contents of Accordion.Panel 2 + + , + ); + + const trigger1 = getByTestId('trigger1'); + const trigger2 = getByTestId('trigger2'); + + await user.keyboard('[Tab]'); + expect(trigger1).toHaveFocus(); + + await user.keyboard('[ArrowRight]'); + expect(trigger2).toHaveFocus(); + + await user.keyboard('[ArrowLeft]'); + expect(trigger1).toHaveFocus(); + + await user.keyboard('[ArrowRight]'); + expect(trigger2).toHaveFocus(); + + await user.keyboard('[ArrowRight]'); + expect(trigger1).toHaveFocus(); + }); + + describe('RTL', () => { + it('ArrowLeft/Right is reversed for horizontal accordions in RTL mode', async () => { + const { getByTestId, user } = await render( + + + + Trigger 1 + + This is the contents of Accordion.Panel 1 + + + + Trigger 2 + + This is the contents of Accordion.Panel 2 + + , + ); + + const trigger1 = getByTestId('trigger1'); + const trigger2 = getByTestId('trigger2'); + + await user.keyboard('[Tab]'); + expect(trigger1).toHaveFocus(); + + await user.keyboard('[ArrowLeft]'); + expect(trigger2).toHaveFocus(); + + await user.keyboard('[ArrowRight]'); + expect(trigger1).toHaveFocus(); + + await user.keyboard('[ArrowLeft]'); + expect(trigger2).toHaveFocus(); + + await user.keyboard('[ArrowLeft]'); + expect(trigger1).toHaveFocus(); + }); + }); + }); + + describe('prop: onOpenChange', () => { + it('default item value', async () => { + const onOpenChange = spy(); + + const { getByTestId, user } = await render( + + + + Trigger 1 + + This is the contents of Accordion.Panel 1 + + + + Trigger 2 + + This is the contents of Accordion.Panel 2 + + , + ); + + const trigger1 = getByTestId('trigger1'); + const trigger2 = getByTestId('trigger2'); + + expect(onOpenChange.callCount).to.equal(0); + + await user.pointer({ keys: '[MouseLeft]', target: trigger1 }); + + expect(onOpenChange.callCount).to.equal(1); + expect(onOpenChange.args[0][0]).to.deep.equal([0]); + + await user.pointer({ keys: '[MouseLeft]', target: trigger2 }); + + expect(onOpenChange.callCount).to.equal(2); + expect(onOpenChange.args[1][0]).to.deep.equal([0, 1]); + }); + + it('custom item value', async () => { + const onOpenChange = spy(); + + const { getByTestId, user } = await render( + + + + Trigger 1 + + This is the contents of Accordion.Panel 1 + + + + Trigger 2 + + This is the contents of Accordion.Panel 2 + + , + ); + + const trigger1 = getByTestId('trigger1'); + const trigger2 = getByTestId('trigger2'); + + expect(onOpenChange.callCount).to.equal(0); + + await user.pointer({ keys: '[MouseLeft]', target: trigger2 }); + + expect(onOpenChange.callCount).to.equal(1); + expect(onOpenChange.args[0][0]).to.deep.equal(['two']); + + await user.pointer({ keys: '[MouseLeft]', target: trigger1 }); + + expect(onOpenChange.callCount).to.equal(2); + expect(onOpenChange.args[1][0]).to.deep.equal(['two', 'one']); + }); + + it('openMultiple is false', async () => { + const onOpenChange = spy(); + + const { getByTestId, user } = await render( + + + + Trigger 1 + + This is the contents of Accordion.Panel 1 + + + + Trigger 2 + + This is the contents of Accordion.Panel 2 + + , + ); + + const trigger1 = getByTestId('trigger1'); + const trigger2 = getByTestId('trigger2'); + + expect(onOpenChange.callCount).to.equal(0); + + await user.pointer({ keys: '[MouseLeft]', target: trigger1 }); + + expect(onOpenChange.callCount).to.equal(1); + expect(onOpenChange.args[0][0]).to.deep.equal(['one']); + + await user.pointer({ keys: '[MouseLeft]', target: trigger2 }); + + expect(onOpenChange.callCount).to.equal(2); + expect(onOpenChange.args[1][0]).to.deep.equal(['two']); + }); + }); }); diff --git a/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.test.tsx b/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.test.tsx index 504a86493..35e19cabb 100644 --- a/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.test.tsx +++ b/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.test.tsx @@ -4,6 +4,7 @@ import * as React from 'react'; import * as Accordion from '@base_ui/react/Accordion'; import * as Collapsible from '@base_ui/react/Collapsible'; import { describeConformance, createRenderer } from '#test-utils'; +import { NOOP } from '../../utils/noop'; const { AccordionRootContext, AccordionItemContext } = Accordion; @@ -14,7 +15,7 @@ const accordionRootContextValue: Accordion.Root.Context = { animated: false, direction: 'ltr', disabled: false, - handleOpenChange() {}, + handleOpenChange: NOOP, orientation: 'vertical', ownerState: { value: [0], @@ -34,6 +35,8 @@ const accordionItemContextValue: Accordion.Item.Context = { orientation: 'vertical', transitionStatus: undefined, }, + setTriggerId: NOOP, + triggerId: ':trigger:', }; const collapsibleContextValue: Collapsible.Root.Context = { @@ -42,9 +45,9 @@ const collapsibleContextValue: Collapsible.Root.Context = { disabled: false, mounted: true, open: true, - setContentId() {}, - setMounted() {}, - setOpen() {}, + setContentId: NOOP, + setMounted: NOOP, + setOpen: NOOP, transitionStatus: undefined, ownerState: { open: true, diff --git a/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.tsx b/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.tsx index 26dca018c..dbea4f15f 100644 --- a/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.tsx +++ b/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.tsx @@ -2,6 +2,7 @@ import * as React from 'react'; import PropTypes from 'prop-types'; import { useComponentRenderer } from '../../utils/useComponentRenderer'; +import { useEnhancedEffect } from '../../utils/useEnhancedEffect'; import { BaseUIComponentProps } from '../../utils/types'; import { useCollapsibleContext } from '../../Collapsible/Root/CollapsibleContext'; import { useCollapsibleTrigger } from '../../Collapsible/Trigger/useCollapsibleTrigger'; @@ -23,19 +24,27 @@ const AccordionTrigger = React.forwardRef(function AccordionTrigger( props: AccordionTrigger.Props, forwardedRef: React.ForwardedRef, ) { - const { disabled: disabledProp, className, render, ...otherProps } = props; + const { disabled: disabledProp, className, id, render, ...otherProps } = props; const { contentId, disabled: contextDisabled, open, setOpen } = useCollapsibleContext(); const { getRootProps } = useCollapsibleTrigger({ contentId, disabled: disabledProp || contextDisabled, + id, open, rootRef: forwardedRef, setOpen, }); - const { ownerState, triggerId } = useAccordionItemContext(); + const { ownerState, setTriggerId, triggerId } = useAccordionItemContext(); + + useEnhancedEffect(() => { + setTriggerId(id); + return () => { + setTriggerId(undefined); + }; + }, [id, setTriggerId]); const { renderElement } = useComponentRenderer({ propGetter: getRootProps, @@ -72,6 +81,10 @@ AccordionTrigger.propTypes /* remove-proptypes */ = { * @ignore */ disabled: PropTypes.bool, + /** + * @ignore + */ + id: PropTypes.string, /** * A function to customize rendering of the component. */ diff --git a/packages/mui-base/src/Collapsible/Trigger/useCollapsibleTrigger.ts b/packages/mui-base/src/Collapsible/Trigger/useCollapsibleTrigger.ts index 5af2603db..a2c072c16 100644 --- a/packages/mui-base/src/Collapsible/Trigger/useCollapsibleTrigger.ts +++ b/packages/mui-base/src/Collapsible/Trigger/useCollapsibleTrigger.ts @@ -17,7 +17,7 @@ import { useButton } from '../../useButton'; export function useCollapsibleTrigger( parameters: useCollapsibleTrigger.Parameters, ): useCollapsibleTrigger.ReturnValue { - const { contentId, disabled, open, rootRef: externalRef, setOpen } = parameters; + const { contentId, disabled, id, open, rootRef: externalRef, setOpen } = parameters; const { getRootProps: getButtonProps, rootRef: buttonRef } = useButton({ disabled, @@ -37,6 +37,7 @@ export function useCollapsibleTrigger( 'aria-controls': contentId, 'aria-expanded': open, disabled, + id, onClick() { setOpen(!open); }, @@ -45,7 +46,7 @@ export function useCollapsibleTrigger( getButtonProps(), ), ), - [contentId, disabled, getButtonProps, handleRef, open, setOpen], + [contentId, disabled, getButtonProps, handleRef, id, open, setOpen], ); return { @@ -60,6 +61,7 @@ export namespace useCollapsibleTrigger { */ contentId: React.HTMLAttributes['id']; disabled?: boolean; + id?: React.HTMLAttributes['id']; /** * The open state of the Collapsible */ From 3c687fa7ef470e57ceb6630a8dc71123eb607353 Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Tue, 17 Sep 2024 14:55:53 +0800 Subject: [PATCH 10/37] Rename data-state for Accordion and Collapsible --- docs/app/experiments/accordion-horizontal.tsx | 2 +- docs/app/experiments/accordion-material.tsx | 109 ---------- docs/app/experiments/accordion.tsx | 71 ------- .../app/experiments/collapsible-accordion.tsx | 152 -------------- docs/app/experiments/collapsible-framer.tsx | 2 +- .../collapsible-hidden-until-found.tsx | 10 +- docs/app/experiments/collapsible.tsx | 194 ------------------ .../collapsible/CssAnimatedCollapsible.js | 6 +- .../collapsible/CssAnimatedCollapsible.tsx | 6 +- .../collapsible/CssTransitionCollapsible.js | 6 +- .../collapsible/CssTransitionCollapsible.tsx | 6 +- .../UnstyledCollapsibleIntroduction.js | 2 +- .../UnstyledCollapsibleIntroduction.tsx | 2 +- .../components/collapsible/collapsible.mdx | 16 +- docs/src/components/demo/Demo.module.css | 4 +- .../Collapsible/Root/CollapsibleRoot.test.tsx | 22 +- .../src/Collapsible/Root/styleHooks.ts | 2 +- 17 files changed, 43 insertions(+), 569 deletions(-) delete mode 100644 docs/app/experiments/accordion-material.tsx delete mode 100644 docs/app/experiments/collapsible-accordion.tsx delete mode 100644 docs/app/experiments/collapsible.tsx diff --git a/docs/app/experiments/accordion-horizontal.tsx b/docs/app/experiments/accordion-horizontal.tsx index 81cb8a0bf..e483cf3b3 100644 --- a/docs/app/experiments/accordion-horizontal.tsx +++ b/docs/app/experiments/accordion-horizontal.tsx @@ -166,7 +166,7 @@ function HorizontalStyles() { transform: rotate(-90deg); } - .MyHorizontalAccordion-trigger[data-state="open"] svg { + .MyHorizontalAccordion-trigger[data-accordion="open"] svg { transform: rotate(180deg); } diff --git a/docs/app/experiments/accordion-material.tsx b/docs/app/experiments/accordion-material.tsx deleted file mode 100644 index cd430c7a5..000000000 --- a/docs/app/experiments/accordion-material.tsx +++ /dev/null @@ -1,109 +0,0 @@ -'use client'; -import * as React from 'react'; -import * as Accordion from '@base_ui/react/Accordion'; -import { ExpandMoreIcon } from './accordion'; - -export default function App() { - return ( -
- - {[0, 1, 2, 3].map((index) => ( - - - - Trigger {index + 1} - - - - - This is the contents of Accordion.Panel {index + 1} - - - ))} - - -
- ); -} - -function MaterialStyles() { - return ( - - ); -} diff --git a/docs/app/experiments/accordion.tsx b/docs/app/experiments/accordion.tsx index eaa04e279..a753b0427 100644 --- a/docs/app/experiments/accordion.tsx +++ b/docs/app/experiments/accordion.tsx @@ -125,7 +125,6 @@ export default function App() { className="MyAccordion-root" value={val2} onOpenChange={(newValue: Accordion.Root.Props['Value']) => { - // console.log(newValue); if (newValue.length > 0) { setVal2(newValue); } @@ -160,7 +159,6 @@ export default function App() {
-
); } @@ -194,72 +192,3 @@ export function ExpandMoreIcon(props: React.SVGProps) { ); } - -const grey = { - 100: '#E5EAF2', - 300: '#C7D0DD', - 500: '#9DA8B7', - 600: '#6B7A90', - 800: '#303740', - 900: '#1C2025', -}; - -// function useIsDarkMode() { -// const theme = useTheme(); -// return theme.palette.mode === 'dark'; -// } - -function Styles() { - // Replace this with your app logic for determining dark mode - // const isDarkMode = useIsDarkMode(); - return ( - - ); -} diff --git a/docs/app/experiments/collapsible-accordion.tsx b/docs/app/experiments/collapsible-accordion.tsx deleted file mode 100644 index ceec392ed..000000000 --- a/docs/app/experiments/collapsible-accordion.tsx +++ /dev/null @@ -1,152 +0,0 @@ -'use client'; - -import * as React from 'react'; -import * as Collapsible from '@base_ui/react/Collapsible'; - -const TRANSITION_DURATION = '350ms'; - -function AccordionSection(props: { - index: number; - openIndex: number; - setOpen: (nextOpenIndex: number) => void; -}) { - const { index, openIndex, setOpen } = props; - const isOpen = index === openIndex; - return ( - setOpen(isOpen ? -1 : index)}> - - - - - - - {isOpen ? 'Close' : 'Open'} Panel {index} - - -

This is the collapsed content of Panel {index}

-

This is the second paragraph

-

This is the third paragraph

-
- -
- ); -} - -export default function CollapsibleAccordion() { - const [openIndex, setOpen] = React.useState(-1); - return ( -
-
-        A crude accordion where only 1 of the 3 {``}s can be open at any time
-        
- Animated using CSS transitions -
- {[0, 1, 2].map((index) => ( - - ))} -
- ); -} - -const grey = { - 50: '#F3F6F9', - 100: '#E5EAF2', - 200: '#DAE2ED', - 300: '#C7D0DD', - 400: '#B0B8C4', - 500: '#9DA8B7', - 600: '#6B7A90', - 700: '#434D5B', - 800: '#303740', - 900: '#1C2025', -}; - -export function Styles() { - return ( - - ); -} diff --git a/docs/app/experiments/collapsible-framer.tsx b/docs/app/experiments/collapsible-framer.tsx index 918e4699b..84cf24222 100644 --- a/docs/app/experiments/collapsible-framer.tsx +++ b/docs/app/experiments/collapsible-framer.tsx @@ -135,7 +135,7 @@ export function Styles() { fill: #00f; } - .FramerCollapsible-trigger[data-state='open'] svg { + .FramerCollapsible-trigger[data-collapsible='open'] svg { transform: rotate(90deg); } diff --git a/docs/app/experiments/collapsible-hidden-until-found.tsx b/docs/app/experiments/collapsible-hidden-until-found.tsx index 9e2cd7d60..5be93b94e 100644 --- a/docs/app/experiments/collapsible-hidden-until-found.tsx +++ b/docs/app/experiments/collapsible-hidden-until-found.tsx @@ -166,7 +166,7 @@ export function Styles() { fill: #00f; } - .MyCollapsible-trigger[data-state='open'] svg { + .MyCollapsible-trigger[data-collapsible='open'] svg { transform: rotate(90deg); } @@ -175,20 +175,20 @@ export function Styles() { overflow: hidden; } - .MyCollapsible-content.animation[data-state='open'] { + .MyCollapsible-content.animation[data-collapsible='open'] { animation: slideDown ${DURATION} ease-out; } - .MyCollapsible-content.animation[data-state='closed'] { + .MyCollapsible-content.animation[data-collapsible='closed'] { animation: slideUp ${DURATION} ease-in; } - .MyCollapsible-content.csstransition[data-state='open'] { + .MyCollapsible-content.csstransition[data-collapsible='open'] { height: var(--collapsible-content-height); transition: height ${DURATION} ease-out; } - .MyCollapsible-content.csstransition[data-state='closed'] { + .MyCollapsible-content.csstransition[data-collapsible='closed'] { height: 0; transition: height ${DURATION} ease-in; } diff --git a/docs/app/experiments/collapsible.tsx b/docs/app/experiments/collapsible.tsx deleted file mode 100644 index a69c9c0d3..000000000 --- a/docs/app/experiments/collapsible.tsx +++ /dev/null @@ -1,194 +0,0 @@ -'use client'; - -import * as React from 'react'; -import * as Collapsible from '@base_ui/react/Collapsible'; - -const DURATION = '350ms'; - -export default function CollapsibleDemo() { - return ( -
-
- - - - - - - - Trigger (CSS animation) - - -

This is the collapsed content

-

This component is animated with CSS @keyframe animations

-

demo: https://codepen.io/aardrian/pen/QWjBNQG

-

https://adrianroselli.com/2020/05/disclosure-widgets.html

-
-
-
- -
- - - - - - - - Trigger (CSS transition) - - -

This is the collapsed content

-

This component is animated with CSS transitions

-

demo: https://codepen.io/aardrian/pen/QWjBNQG

-

https://adrianroselli.com/2020/05/disclosure-widgets.html

-
-
-
- - - - - - - - - Trigger (root renders a span + CSS transition) - - -

This is the collapsed content

-

This component is animated with CSS transitions

-

demo: https://codepen.io/aardrian/pen/QWjBNQG

-

https://adrianroselli.com/2020/05/disclosure-widgets.html

-
-
- -
- ); -} - -const grey = { - 50: '#F3F6F9', - 100: '#E5EAF2', - 200: '#DAE2ED', - 300: '#C7D0DD', - 400: '#B0B8C4', - 500: '#9DA8B7', - 600: '#6B7A90', - 700: '#434D5B', - 800: '#303740', - 900: '#1C2025', -}; - -export function Styles() { - return ( - - ); -} diff --git a/docs/data/components/collapsible/CssAnimatedCollapsible.js b/docs/data/components/collapsible/CssAnimatedCollapsible.js index fe5e8fd2d..5b1d15dc9 100644 --- a/docs/data/components/collapsible/CssAnimatedCollapsible.js +++ b/docs/data/components/collapsible/CssAnimatedCollapsible.js @@ -97,7 +97,7 @@ export function Styles() { transform-origin: center 45%; } - .CssAnimatedCollapsible-trigger[data-state="open"] svg { + .CssAnimatedCollapsible-trigger[data-collapsible="open"] svg { transform: rotate(90deg); } @@ -110,10 +110,10 @@ export function Styles() { padding: 0 1rem; } - .CssAnimatedCollapsible-content[data-state='open'] { + .CssAnimatedCollapsible-content[data-collapsible='open'] { animation: slideDown 300ms ease-out; } - .CssAnimatedCollapsible-content[data-state='closed'] { + .CssAnimatedCollapsible-content[data-collapsible='closed'] { animation: slideUp 300ms ease-out; } diff --git a/docs/data/components/collapsible/CssAnimatedCollapsible.tsx b/docs/data/components/collapsible/CssAnimatedCollapsible.tsx index fe5e8fd2d..5b1d15dc9 100644 --- a/docs/data/components/collapsible/CssAnimatedCollapsible.tsx +++ b/docs/data/components/collapsible/CssAnimatedCollapsible.tsx @@ -97,7 +97,7 @@ export function Styles() { transform-origin: center 45%; } - .CssAnimatedCollapsible-trigger[data-state="open"] svg { + .CssAnimatedCollapsible-trigger[data-collapsible="open"] svg { transform: rotate(90deg); } @@ -110,10 +110,10 @@ export function Styles() { padding: 0 1rem; } - .CssAnimatedCollapsible-content[data-state='open'] { + .CssAnimatedCollapsible-content[data-collapsible='open'] { animation: slideDown 300ms ease-out; } - .CssAnimatedCollapsible-content[data-state='closed'] { + .CssAnimatedCollapsible-content[data-collapsible='closed'] { animation: slideUp 300ms ease-out; } diff --git a/docs/data/components/collapsible/CssTransitionCollapsible.js b/docs/data/components/collapsible/CssTransitionCollapsible.js index 164082bb7..29e70d2ce 100644 --- a/docs/data/components/collapsible/CssTransitionCollapsible.js +++ b/docs/data/components/collapsible/CssTransitionCollapsible.js @@ -97,7 +97,7 @@ export function Styles() { transform-origin: center 45%; } - .CssTransitionCollapsible-trigger[data-state="open"] svg { + .CssTransitionCollapsible-trigger[data-collapsible="open"] svg { transform: rotate(90deg); } @@ -110,12 +110,12 @@ export function Styles() { padding: 0 1rem; } - .CssTransitionCollapsible-content[data-state='open'] { + .CssTransitionCollapsible-content[data-collapsible='open'] { height: var(--collapsible-content-height); transition: height 200ms ease-out; } - .CssTransitionCollapsible-content[data-state='closed'] { + .CssTransitionCollapsible-content[data-collapsible='closed'] { height: 0; transition: height 200ms ease-in; } diff --git a/docs/data/components/collapsible/CssTransitionCollapsible.tsx b/docs/data/components/collapsible/CssTransitionCollapsible.tsx index 164082bb7..29e70d2ce 100644 --- a/docs/data/components/collapsible/CssTransitionCollapsible.tsx +++ b/docs/data/components/collapsible/CssTransitionCollapsible.tsx @@ -97,7 +97,7 @@ export function Styles() { transform-origin: center 45%; } - .CssTransitionCollapsible-trigger[data-state="open"] svg { + .CssTransitionCollapsible-trigger[data-collapsible="open"] svg { transform: rotate(90deg); } @@ -110,12 +110,12 @@ export function Styles() { padding: 0 1rem; } - .CssTransitionCollapsible-content[data-state='open'] { + .CssTransitionCollapsible-content[data-collapsible='open'] { height: var(--collapsible-content-height); transition: height 200ms ease-out; } - .CssTransitionCollapsible-content[data-state='closed'] { + .CssTransitionCollapsible-content[data-collapsible='closed'] { height: 0; transition: height 200ms ease-in; } diff --git a/docs/data/components/collapsible/UnstyledCollapsibleIntroduction.js b/docs/data/components/collapsible/UnstyledCollapsibleIntroduction.js index e829370f9..a8b7654a3 100644 --- a/docs/data/components/collapsible/UnstyledCollapsibleIntroduction.js +++ b/docs/data/components/collapsible/UnstyledCollapsibleIntroduction.js @@ -16,7 +16,7 @@ const CollapsibleTrigger = styled(BaseCollapsible.Trigger)` margin-top: 1px; } - &[data-state='open'] svg { + &[data-collapsible='open'] svg { transform: rotate(180deg); } `; diff --git a/docs/data/components/collapsible/UnstyledCollapsibleIntroduction.tsx b/docs/data/components/collapsible/UnstyledCollapsibleIntroduction.tsx index e829370f9..a8b7654a3 100644 --- a/docs/data/components/collapsible/UnstyledCollapsibleIntroduction.tsx +++ b/docs/data/components/collapsible/UnstyledCollapsibleIntroduction.tsx @@ -16,7 +16,7 @@ const CollapsibleTrigger = styled(BaseCollapsible.Trigger)` margin-top: 1px; } - &[data-state='open'] svg { + &[data-collapsible='open'] svg { transform: rotate(180deg); } `; diff --git a/docs/data/components/collapsible/collapsible.mdx b/docs/data/components/collapsible/collapsible.mdx index 9f4a240af..66673b8b2 100644 --- a/docs/data/components/collapsible/collapsible.mdx +++ b/docs/data/components/collapsible/collapsible.mdx @@ -63,8 +63,8 @@ This relies on the HTML `hidden="until-found"` attribute which only has [partial Four states are available as data attributes to animate the Collapsible: -- `[data-state="open"]` - `open` state is `true`. -- `[data-state="closed"]` - `open` state is `false`. Can still be mounted to the DOM if closing. +- `[data-collapsible="open"]` - `open` state is `true`. +- `[data-collapsible="closed"]` - `open` state is `false`. Can still be mounted to the DOM if closing. - `[data-entering]` - the `hidden` attribute was just removed from the DOM and the content element participates in page layout. The `data-entering` attribute will be removed 1 animation frame later. - `[data-exiting]` - the content element is in the process of being hidden from the DOM, but is still mounted. @@ -85,11 +85,11 @@ CSS animations can be used with two declarations: overflow: hidden; } -.Collapsible-content[data-state='open'] { +.Collapsible-content[data-collapsible='open'] { animation: slideDown 300ms ease-out; } -.Collapsible-content[data-state='closed'] { +.Collapsible-content[data-collapsible='closed'] { animation: slideUp 300ms ease-in; } @@ -118,8 +118,8 @@ CSS animations can be used with two declarations: When using CSS transitions, styles for the `Content` subcomponent must be applied to three states: -- The closed styles with `[data-state="closed"]` -- The open styles with `[data-state="open"]` +- The closed styles with `[data-collapsible="closed"]` +- The open styles with `[data-collapsible="open"]` - The entering styles with `[data-entering]` ```css @@ -127,7 +127,7 @@ When using CSS transitions, styles for the `Content` subcomponent must be applie overflow: hidden; } -.Collapsible-content[data-state='open'] { +.Collapsible-content[data-collapsible='open'] { height: var(--collapsible-content-height); transition: height 300ms ease-out; } @@ -136,7 +136,7 @@ When using CSS transitions, styles for the `Content` subcomponent must be applie height: 0; } -.Collapsible-content[data-state='closed'] { +.Collapsible-content[data-collapsible='closed'] { height: 0; transition: height 300ms ease-in; } diff --git a/docs/src/components/demo/Demo.module.css b/docs/src/components/demo/Demo.module.css index a4910b833..416593f1f 100644 --- a/docs/src/components/demo/Demo.module.css +++ b/docs/src/components/demo/Demo.module.css @@ -97,11 +97,11 @@ .collapsible { overflow: hidden; - &[data-state='open'] { + &[data-collapsible='open'] { animation: slideDown 200ms ease-out; } - &[data-state='closed'] { + &[data-collapsible='closed'] { animation: slideUp 200ms ease-in; } } diff --git a/packages/mui-base/src/Collapsible/Root/CollapsibleRoot.test.tsx b/packages/mui-base/src/Collapsible/Root/CollapsibleRoot.test.tsx index d14d5365e..22271189d 100644 --- a/packages/mui-base/src/Collapsible/Root/CollapsibleRoot.test.tsx +++ b/packages/mui-base/src/Collapsible/Root/CollapsibleRoot.test.tsx @@ -48,18 +48,18 @@ describe('', () => { expect(trigger).to.have.attribute('aria-expanded', 'false'); expect(content).to.have.attribute('hidden'); - expect(content).to.have.attribute('data-state', 'closed'); + expect(content).to.have.attribute('data-collapsible', 'closed'); setProps({ open: true }); expect(trigger).to.have.attribute('aria-expanded', 'true'); expect(content).to.not.have.attribute('hidden'); - expect(content).to.have.attribute('data-state', 'open'); + expect(content).to.have.attribute('data-collapsible', 'open'); setProps({ open: false }); expect(trigger).to.have.attribute('aria-expanded', 'false'); - expect(content).to.have.attribute('data-state', 'closed'); + expect(content).to.have.attribute('data-collapsible', 'closed'); expect(content).to.have.attribute('hidden'); }); @@ -76,18 +76,18 @@ describe('', () => { expect(trigger).to.have.attribute('aria-expanded', 'false'); expect(content).to.have.attribute('hidden'); - expect(content).to.have.attribute('data-state', 'closed'); + expect(content).to.have.attribute('data-collapsible', 'closed'); await user.pointer({ keys: '[MouseLeft]', target: trigger }); expect(trigger).to.have.attribute('aria-expanded', 'true'); expect(content).to.not.have.attribute('hidden'); - expect(content).to.have.attribute('data-state', 'open'); + expect(content).to.have.attribute('data-collapsible', 'open'); await user.pointer({ keys: '[MouseLeft]', target: trigger }); expect(trigger).to.have.attribute('aria-expanded', 'false'); - expect(content).to.have.attribute('data-state', 'closed'); + expect(content).to.have.attribute('data-collapsible', 'closed'); expect(content).to.have.attribute('hidden'); }); }); @@ -107,7 +107,7 @@ describe('', () => { expect(trigger).to.have.attribute('aria-expanded', 'false'); expect(content).to.have.attribute('hidden'); - expect(content).to.have.attribute('data-state', 'closed'); + expect(content).to.have.attribute('data-collapsible', 'closed'); await user.keyboard('[Tab]'); expect(trigger).toHaveFocus(); @@ -115,12 +115,12 @@ describe('', () => { expect(trigger).to.have.attribute('aria-expanded', 'true'); expect(content).to.not.have.attribute('hidden'); - expect(content).to.have.attribute('data-state', 'open'); + expect(content).to.have.attribute('data-collapsible', 'open'); await user.keyboard(`[${key}]`); expect(trigger).to.have.attribute('aria-expanded', 'false'); - expect(content).to.have.attribute('data-state', 'closed'); + expect(content).to.have.attribute('data-collapsible', 'closed'); expect(content).to.have.attribute('hidden'); }); }); @@ -144,7 +144,7 @@ describe('', () => { const content = getByTestId('content'); - expect(content).to.have.attribute('data-state', 'closed'); + expect(content).to.have.attribute('data-collapsible', 'closed'); act(() => { const event = new window.Event('beforematch', { @@ -155,7 +155,7 @@ describe('', () => { }); expect(handleOpenChange.callCount).to.equal(1); - expect(content).to.have.attribute('data-state', 'open'); + expect(content).to.have.attribute('data-collapsible', 'open'); }); }); }); diff --git a/packages/mui-base/src/Collapsible/Root/styleHooks.ts b/packages/mui-base/src/Collapsible/Root/styleHooks.ts index bf81e8868..b47f9f0bc 100644 --- a/packages/mui-base/src/Collapsible/Root/styleHooks.ts +++ b/packages/mui-base/src/Collapsible/Root/styleHooks.ts @@ -3,7 +3,7 @@ import type { CollapsibleRoot } from './CollapsibleRoot'; export const collapsibleStyleHookMapping: CustomStyleHookMapping = { open: (value) => { - return value ? { 'data-state': 'open' } : { 'data-state': 'closed' }; + return value ? { 'data-collapsible': 'open' } : { 'data-collapsible': 'closed' }; }, transitionStatus: (value) => { if (value === 'entering') { From 28978bb1aa90e4ef2238f11170d9ab9e2b9c9feb Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Tue, 17 Sep 2024 15:11:28 +0800 Subject: [PATCH 11/37] Use a boolean prop to apply hidden-until-found --- docs/app/experiments/accordion-animations.tsx | 2 +- .../collapsible-hidden-until-found.tsx | 7 ++----- docs/data/api/accordion-panel.json | 5 +---- docs/data/api/collapsible-content.json | 5 +---- docs/data/components/accordion/accordion.mdx | 6 +++--- .../components/collapsible/collapsible.mdx | 4 ++-- .../accordion-panel/accordion-panel.json | 4 +++- .../collapsible-content.json | 4 +++- .../Accordion/Header/AccordionHeader.test.tsx | 1 + .../src/Accordion/Item/AccordionItem.test.tsx | 1 + .../Accordion/Panel/AccordionPanel.test.tsx | 1 + .../src/Accordion/Panel/AccordionPanel.tsx | 21 ++++++++++++------- .../src/Accordion/Root/AccordionRoot.tsx | 14 ++++++------- .../Trigger/AccordionTrigger.test.tsx | 1 + .../Content/CollapsibleContent.tsx | 17 ++++++++------- .../Content/useCollapsibleContent.ts | 21 ++++++++++--------- .../Collapsible/Root/CollapsibleRoot.test.tsx | 6 +++--- .../Trigger/CollapsibleTrigger.tsx | 4 ++-- 18 files changed, 65 insertions(+), 59 deletions(-) diff --git a/docs/app/experiments/accordion-animations.tsx b/docs/app/experiments/accordion-animations.tsx index c6f88e71c..d2cd903a5 100644 --- a/docs/app/experiments/accordion-animations.tsx +++ b/docs/app/experiments/accordion-animations.tsx @@ -12,7 +12,7 @@ export default function App() { {[0, 1, 2].map((index) => ( diff --git a/docs/app/experiments/collapsible-hidden-until-found.tsx b/docs/app/experiments/collapsible-hidden-until-found.tsx index 5be93b94e..725e6dc7f 100644 --- a/docs/app/experiments/collapsible-hidden-until-found.tsx +++ b/docs/app/experiments/collapsible-hidden-until-found.tsx @@ -52,7 +52,7 @@ export default function CollapsibleHiddenUntilFound() { Toggle 2 - +

This is the collapsed content

May the force be with you

@@ -68,10 +68,7 @@ export default function CollapsibleHiddenUntilFound() { Toggle 3 - +

This is the collapsed content

May the force be with you

diff --git a/docs/data/api/accordion-panel.json b/docs/data/api/accordion-panel.json index cc3d42099..0f9116022 100644 --- a/docs/data/api/accordion-panel.json +++ b/docs/data/api/accordion-panel.json @@ -1,10 +1,7 @@ { "props": { "className": { "type": { "name": "union", "description": "func
| string" } }, - "htmlHidden": { - "type": { "name": "enum", "description": "'hidden'
| 'until-found'" }, - "default": "'hidden'" - }, + "hiddenUntilFound": { "type": { "name": "bool" }, "default": "false" }, "render": { "type": { "name": "union", "description": "element
| func" } } }, "name": "AccordionPanel", diff --git a/docs/data/api/collapsible-content.json b/docs/data/api/collapsible-content.json index f756bd0bd..b9d48da67 100644 --- a/docs/data/api/collapsible-content.json +++ b/docs/data/api/collapsible-content.json @@ -1,10 +1,7 @@ { "props": { "className": { "type": { "name": "union", "description": "func
| string" } }, - "htmlHidden": { - "type": { "name": "enum", "description": "'hidden'
| 'until-found'" }, - "default": "'hidden'" - }, + "hiddenUntilFound": { "type": { "name": "bool" }, "default": "false" }, "render": { "type": { "name": "union", "description": "element
| func" } } }, "name": "CollapsibleContent", diff --git a/docs/data/components/accordion/accordion.mdx b/docs/data/components/accordion/accordion.mdx index a561d8dcd..da514142c 100644 --- a/docs/data/components/accordion/accordion.mdx +++ b/docs/data/components/accordion/accordion.mdx @@ -192,13 +192,13 @@ When a horizontal accordion is set to `direction="rtl"`, keyboard actions are re Firefox as of August 2024 and will fall back to the default `hidden` behavior. -Content hidden by `Accordion.Panel` components can be made accessible only to a browser's find-in-page functionality with the `htmlHidden` prop to improve searchability: +Content hidden by `Accordion.Panel` components can be made accessible only to a browser's find-in-page functionality with the `hiddenUntilFound` prop to improve searchability: ```js -{/* subcomponents */} +{/* subcomponents */} ``` -Alternatively `htmlHidden` can be passed to `Accordion.Panel` directly to enable this for only one `Item` instead of the whole accordion. +Alternatively `hiddenUntilFound` can be passed to `Accordion.Panel`s directly to enable this for only one `Item` instead of the whole accordion. We recommend using [CSS animations](#css-animations) for animated accordions that use this feature. Currently there is browser bug that does not highlight the found text inside elements that have a [CSS transition](#css-transitions) applied. diff --git a/docs/data/components/collapsible/collapsible.mdx b/docs/data/components/collapsible/collapsible.mdx index 66673b8b2..5efe2b491 100644 --- a/docs/data/components/collapsible/collapsible.mdx +++ b/docs/data/components/collapsible/collapsible.mdx @@ -41,12 +41,12 @@ packageName: '@base_ui/react' Firefox as of August 2024 and will fall back to the default `hidden` behavior. -Content hidden in the `Collapsible.Content` component can be made accessible only to a browser's find-in-page functionality with the `htmlHidden` prop to improve searchability: +Content hidden in the `Collapsible.Content` component can be made accessible only to a browser's find-in-page functionality with the `hiddenUntilFound` prop to improve searchability: ```js Toggle - + When this component is closed, this sentence will only be accessible to the browser's native find-in-page functionality diff --git a/docs/data/translations/api-docs/accordion-panel/accordion-panel.json b/docs/data/translations/api-docs/accordion-panel/accordion-panel.json index 722a5c7ab..3a629b202 100644 --- a/docs/data/translations/api-docs/accordion-panel/accordion-panel.json +++ b/docs/data/translations/api-docs/accordion-panel/accordion-panel.json @@ -4,7 +4,9 @@ "className": { "description": "Class names applied to the element or a function that returns them based on the component's state." }, - "htmlHidden": { "description": "The hidden state when closed" }, + "hiddenUntilFound": { + "description": "If true, sets hidden="until-found" when closed. If false, sets hidden when closed." + }, "render": { "description": "A function to customize rendering of the component." } }, "classDescriptions": {} diff --git a/docs/data/translations/api-docs/collapsible-content/collapsible-content.json b/docs/data/translations/api-docs/collapsible-content/collapsible-content.json index 722a5c7ab..3a629b202 100644 --- a/docs/data/translations/api-docs/collapsible-content/collapsible-content.json +++ b/docs/data/translations/api-docs/collapsible-content/collapsible-content.json @@ -4,7 +4,9 @@ "className": { "description": "Class names applied to the element or a function that returns them based on the component's state." }, - "htmlHidden": { "description": "The hidden state when closed" }, + "hiddenUntilFound": { + "description": "If true, sets hidden="until-found" when closed. If false, sets hidden when closed." + }, "render": { "description": "A function to customize rendering of the component." } }, "classDescriptions": {} diff --git a/packages/mui-base/src/Accordion/Header/AccordionHeader.test.tsx b/packages/mui-base/src/Accordion/Header/AccordionHeader.test.tsx index 608b8cbd5..4c01472af 100644 --- a/packages/mui-base/src/Accordion/Header/AccordionHeader.test.tsx +++ b/packages/mui-base/src/Accordion/Header/AccordionHeader.test.tsx @@ -16,6 +16,7 @@ const accordionRootContextValue: Accordion.Root.Context = { direction: 'ltr', disabled: false, handleOpenChange() {}, + hiddenUntilFound: false, orientation: 'vertical', ownerState: { value: [0], diff --git a/packages/mui-base/src/Accordion/Item/AccordionItem.test.tsx b/packages/mui-base/src/Accordion/Item/AccordionItem.test.tsx index c8feca507..46bddc12f 100644 --- a/packages/mui-base/src/Accordion/Item/AccordionItem.test.tsx +++ b/packages/mui-base/src/Accordion/Item/AccordionItem.test.tsx @@ -13,6 +13,7 @@ const accordionRootContextValue: Accordion.Root.Context = { direction: 'ltr', disabled: false, handleOpenChange: NOOP, + hiddenUntilFound: false, orientation: 'vertical', ownerState: { value: [0], diff --git a/packages/mui-base/src/Accordion/Panel/AccordionPanel.test.tsx b/packages/mui-base/src/Accordion/Panel/AccordionPanel.test.tsx index 748afdc14..e146cbe8c 100644 --- a/packages/mui-base/src/Accordion/Panel/AccordionPanel.test.tsx +++ b/packages/mui-base/src/Accordion/Panel/AccordionPanel.test.tsx @@ -16,6 +16,7 @@ const accordionRootContextValue: Accordion.Root.Context = { direction: 'ltr', disabled: false, handleOpenChange: NOOP, + hiddenUntilFound: false, orientation: 'vertical', ownerState: { value: [0], diff --git a/packages/mui-base/src/Accordion/Panel/AccordionPanel.tsx b/packages/mui-base/src/Accordion/Panel/AccordionPanel.tsx index a282745c9..a4f95a399 100644 --- a/packages/mui-base/src/Accordion/Panel/AccordionPanel.tsx +++ b/packages/mui-base/src/Accordion/Panel/AccordionPanel.tsx @@ -24,16 +24,22 @@ const AccordionPanel = React.forwardRef(function AccordionPanel( props: AccordionPanel.Props, forwardedRef: React.ForwardedRef, ) { - const { className, htmlHidden: htmlHiddenProp, id: idProp, render, ...otherProps } = props; + const { + className, + hiddenUntilFound: hiddenUntilFoundProp, + id: idProp, + render, + ...otherProps + } = props; const { animated, mounted, open, contentId, setContentId, setMounted, setOpen } = useCollapsibleContext(); - const { htmlHidden } = useAccordionRootContext(); + const { hiddenUntilFound } = useAccordionRootContext(); const { getRootProps, height, width } = useCollapsibleContent({ animated, - htmlHidden: htmlHiddenProp || htmlHidden, + hiddenUntilFound: hiddenUntilFoundProp || hiddenUntilFound, id: idProp ?? contentId, mounted, open, @@ -70,7 +76,7 @@ export { AccordionPanel }; export namespace AccordionPanel { export interface Props extends BaseUIComponentProps<'div', AccordionItem.OwnerState>, - Pick {} + Pick {} } AccordionPanel.propTypes /* remove-proptypes */ = { @@ -87,10 +93,11 @@ AccordionPanel.propTypes /* remove-proptypes */ = { */ className: PropTypes.oneOfType([PropTypes.func, PropTypes.string]), /** - * The hidden state when closed - * @default 'hidden' + * If `true`, sets `hidden="until-found"` when closed. + * If `false`, sets `hidden` when closed. + * @default false */ - htmlHidden: PropTypes.oneOf(['hidden', 'until-found']), + hiddenUntilFound: PropTypes.bool, /** * @ignore */ diff --git a/packages/mui-base/src/Accordion/Root/AccordionRoot.tsx b/packages/mui-base/src/Accordion/Root/AccordionRoot.tsx index 820fb3111..838b7e3c7 100644 --- a/packages/mui-base/src/Accordion/Root/AccordionRoot.tsx +++ b/packages/mui-base/src/Accordion/Root/AccordionRoot.tsx @@ -3,7 +3,6 @@ import * as React from 'react'; import PropTypes from 'prop-types'; import { BaseUIComponentProps } from '../../utils/types'; import { useComponentRenderer } from '../../utils/useComponentRenderer'; -import type { useCollapsibleContent } from '../../Collapsible/Content/useCollapsibleContent'; import { CompositeList } from '../../Composite/List/CompositeList'; import { useAccordionRoot } from './useAccordionRoot'; import { AccordionRootContext } from './AccordionRootContext'; @@ -27,7 +26,7 @@ const AccordionRoot = React.forwardRef(function AccordionRoot( className, direction, disabled = false, - htmlHidden, + hiddenUntilFound = false, loop, onOpenChange, openMultiple = true, @@ -65,7 +64,6 @@ const AccordionRoot = React.forwardRef(function AccordionRoot( value: accordion.value, disabled: accordion.disabled, orientation: accordion.orientation, - // transitionStatus: accordion.transitionStatus, }), [accordion.value, accordion.disabled, accordion.orientation], ); @@ -73,10 +71,10 @@ const AccordionRoot = React.forwardRef(function AccordionRoot( const contextValue: AccordionRoot.Context = React.useMemo( () => ({ ...accordion, - htmlHidden, + hiddenUntilFound, ownerState, }), - [accordion, htmlHidden, ownerState], + [accordion, hiddenUntilFound, ownerState], ); const { renderElement } = useComponentRenderer({ @@ -109,7 +107,7 @@ export { AccordionRoot }; export namespace AccordionRoot { export interface Context extends Omit { ownerState: OwnerState; - htmlHidden?: useCollapsibleContent.HtmlHiddenType; + hiddenUntilFound: boolean; } export interface OwnerState { @@ -121,7 +119,7 @@ export namespace AccordionRoot { export interface Props extends useAccordionRoot.Parameters, BaseUIComponentProps { - htmlHidden?: useCollapsibleContent.HtmlHiddenType; + hiddenUntilFound?: boolean; } } @@ -159,7 +157,7 @@ AccordionRoot.propTypes /* remove-proptypes */ = { /** * @ignore */ - htmlHidden: PropTypes.oneOf(['hidden', 'until-found']), + hiddenUntilFound: PropTypes.bool, /** * If `true`, focus will loop when moving focus between `Trigger`s using * the arrow keys. diff --git a/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.test.tsx b/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.test.tsx index 35e19cabb..fba9ab8b5 100644 --- a/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.test.tsx +++ b/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.test.tsx @@ -16,6 +16,7 @@ const accordionRootContextValue: Accordion.Root.Context = { direction: 'ltr', disabled: false, handleOpenChange: NOOP, + hiddenUntilFound: false, orientation: 'vertical', ownerState: { value: [0], diff --git a/packages/mui-base/src/Collapsible/Content/CollapsibleContent.tsx b/packages/mui-base/src/Collapsible/Content/CollapsibleContent.tsx index 5d522d324..a83078a9d 100644 --- a/packages/mui-base/src/Collapsible/Content/CollapsibleContent.tsx +++ b/packages/mui-base/src/Collapsible/Content/CollapsibleContent.tsx @@ -22,14 +22,14 @@ const CollapsibleContent = React.forwardRef(function CollapsibleContent( props: CollapsibleContent.Props, forwardedRef: React.ForwardedRef, ) { - const { className, htmlHidden, render, ...otherProps } = props; + const { className, hiddenUntilFound, render, ...otherProps } = props; const { animated, mounted, open, contentId, setContentId, setMounted, setOpen, ownerState } = useCollapsibleContext(); const { getRootProps, height, width } = useCollapsibleContent({ animated, - htmlHidden, + hiddenUntilFound, id: contentId, mounted, open, @@ -57,10 +57,12 @@ const CollapsibleContent = React.forwardRef(function CollapsibleContent( return renderElement(); }); +export { CollapsibleContent }; + namespace CollapsibleContent { export interface Props extends BaseUIComponentProps<'div', CollapsibleRoot.OwnerState>, - Pick {} + Pick {} } CollapsibleContent.propTypes /* remove-proptypes */ = { @@ -77,14 +79,13 @@ CollapsibleContent.propTypes /* remove-proptypes */ = { */ className: PropTypes.oneOfType([PropTypes.func, PropTypes.string]), /** - * The hidden state when closed - * @default 'hidden' + * If `true`, sets `hidden="until-found"` when closed. + * If `false`, sets `hidden` when closed. + * @default false */ - htmlHidden: PropTypes.oneOf(['hidden', 'until-found']), + hiddenUntilFound: PropTypes.bool, /** * A function to customize rendering of the component. */ render: PropTypes.oneOfType([PropTypes.element, PropTypes.func]), } as any; - -export { CollapsibleContent }; diff --git a/packages/mui-base/src/Collapsible/Content/useCollapsibleContent.ts b/packages/mui-base/src/Collapsible/Content/useCollapsibleContent.ts index 227368106..368c21fe0 100644 --- a/packages/mui-base/src/Collapsible/Content/useCollapsibleContent.ts +++ b/packages/mui-base/src/Collapsible/Content/useCollapsibleContent.ts @@ -37,7 +37,7 @@ export function useCollapsibleContent( ): useCollapsibleContent.ReturnValue { const { animated = false, - htmlHidden = 'hidden', + hiddenUntilFound = false, id: idParam, open, mounted: contextMounted, @@ -245,21 +245,23 @@ export function useCollapsibleContent( supportsHiddenUntilFound(element) && element?.hidden && !isOpen && - htmlHidden === 'until-found' + hiddenUntilFound === true ) { // @ts-ignore element.hidden = 'until-found'; } - }, [htmlHidden, isOpen]); + }, [hiddenUntilFound, isOpen]); + + const hidden = hiddenUntilFound ? 'until-found' : 'hidden'; const getRootProps: useCollapsibleContent.ReturnValue['getRootProps'] = React.useCallback( (externalProps = {}) => mergeReactProps(externalProps, { id, - hidden: isOpen ? undefined : htmlHidden, + hidden: isOpen ? undefined : hidden, ref: mergedRef, }), - [htmlHidden, id, isOpen, mergedRef], + [hidden, id, isOpen, mergedRef], ); return React.useMemo( @@ -273,8 +275,6 @@ export function useCollapsibleContent( } export namespace useCollapsibleContent { - export type HtmlHiddenType = 'hidden' | 'until-found'; - export interface Parameters { /** * If `true`, the component supports CSS/JS-based animations and transitions. @@ -282,10 +282,11 @@ export namespace useCollapsibleContent { */ animated?: boolean; /** - * The hidden state when closed - * @default 'hidden' + * If `true`, sets `hidden="until-found"` when closed. + * If `false`, sets `hidden` when closed. + * @default false */ - htmlHidden?: HtmlHiddenType; + hiddenUntilFound?: boolean; id?: React.HTMLAttributes['id']; mounted: boolean; /** diff --git a/packages/mui-base/src/Collapsible/Root/CollapsibleRoot.test.tsx b/packages/mui-base/src/Collapsible/Root/CollapsibleRoot.test.tsx index 22271189d..9184d234c 100644 --- a/packages/mui-base/src/Collapsible/Root/CollapsibleRoot.test.tsx +++ b/packages/mui-base/src/Collapsible/Root/CollapsibleRoot.test.tsx @@ -126,8 +126,8 @@ describe('', () => { }); }); - describe('prop: htmlHidden', () => { - it('supports "hidden until found" state', async function test() { + describe('prop: hiddenUntilFound', () => { + it('uses `hidden="until-found" to hide content when true', async function test() { // we test firefox in browserstack which does not support this yet if (!('onbeforematch' in window)) { this.skip(); @@ -138,7 +138,7 @@ describe('', () => { const { getByTestId } = await render( - + , ); diff --git a/packages/mui-base/src/Collapsible/Trigger/CollapsibleTrigger.tsx b/packages/mui-base/src/Collapsible/Trigger/CollapsibleTrigger.tsx index 063f11f43..f35bfbf40 100644 --- a/packages/mui-base/src/Collapsible/Trigger/CollapsibleTrigger.tsx +++ b/packages/mui-base/src/Collapsible/Trigger/CollapsibleTrigger.tsx @@ -45,6 +45,8 @@ const CollapsibleTrigger = React.forwardRef(function CollapsibleTrigger( return renderElement(); }); +export { CollapsibleTrigger }; + namespace CollapsibleTrigger { export interface Props extends BaseUIComponentProps<'button', CollapsibleRoot.OwnerState> {} } @@ -67,5 +69,3 @@ CollapsibleTrigger.propTypes /* remove-proptypes */ = { */ render: PropTypes.oneOfType([PropTypes.element, PropTypes.func]), } as any; - -export { CollapsibleTrigger }; From 03010881769dfa799af1b2eeb37a240212c88e7e Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Mon, 23 Sep 2024 18:27:46 +0200 Subject: [PATCH 12/37] PR review fixes --- docs/data/components/accordion/accordion.mdx | 2 +- .../src/Accordion/Header/AccordionHeader.test.tsx | 7 ++----- .../src/Accordion/Header/AccordionHeader.tsx | 8 ++++---- .../src/Accordion/Item/AccordionItem.test.tsx | 6 +----- .../mui-base/src/Accordion/Item/AccordionItem.tsx | 15 ++++++--------- .../src/Accordion/Panel/AccordionPanel.test.tsx | 7 ++----- .../src/Accordion/Panel/AccordionPanel.tsx | 4 ++-- .../src/Accordion/Root/AccordionRoot.test.tsx | 1 - .../mui-base/src/Accordion/Root/AccordionRoot.tsx | 4 ++-- .../Accordion/Trigger/AccordionTrigger.test.tsx | 7 ++----- .../src/Accordion/Trigger/AccordionTrigger.tsx | 4 ++-- packages/mui-base/src/Accordion/index.ts | 5 ----- 12 files changed, 24 insertions(+), 46 deletions(-) diff --git a/docs/data/components/accordion/accordion.mdx b/docs/data/components/accordion/accordion.mdx index da514142c..6e9d3b4f9 100644 --- a/docs/data/components/accordion/accordion.mdx +++ b/docs/data/components/accordion/accordion.mdx @@ -28,7 +28,7 @@ Accordions are implemented using a collection of related components: - `` is a top-level component that wraps the other components. - `` is a component that wraps each section of content - `` is a button that toggles the open state of it's associated `Item` -- `` is an element that wraps the `Trigger` +- `` is a heading (`h3` by default) that wraps the `Trigger` - `` is the element that contains content in a `Item` ```tsx diff --git a/packages/mui-base/src/Accordion/Header/AccordionHeader.test.tsx b/packages/mui-base/src/Accordion/Header/AccordionHeader.test.tsx index 4c01472af..9c04d3872 100644 --- a/packages/mui-base/src/Accordion/Header/AccordionHeader.test.tsx +++ b/packages/mui-base/src/Accordion/Header/AccordionHeader.test.tsx @@ -1,12 +1,10 @@ import * as React from 'react'; -// import { expect } from 'chai'; -// import { spy } from 'sinon'; import * as Accordion from '@base_ui/react/Accordion'; import * as Collapsible from '@base_ui/react/Collapsible'; import { describeConformance, createRenderer } from '#test-utils'; import { NOOP } from '../../utils/noop'; - -const { AccordionRootContext, AccordionItemContext } = Accordion; +import { AccordionRootContext } from '../Root/AccordionRootContext'; +import { AccordionItemContext } from '../Item/AccordionItemContext'; const { CollapsibleContext } = Collapsible; @@ -61,7 +59,6 @@ describe('', () => { const { render } = createRenderer(); describeConformance(, () => ({ - inheritComponent: 'h3', render: (node) => render( diff --git a/packages/mui-base/src/Accordion/Header/AccordionHeader.tsx b/packages/mui-base/src/Accordion/Header/AccordionHeader.tsx index 280462943..1dff33d0e 100644 --- a/packages/mui-base/src/Accordion/Header/AccordionHeader.tsx +++ b/packages/mui-base/src/Accordion/Header/AccordionHeader.tsx @@ -21,7 +21,7 @@ const AccordionHeader = React.forwardRef(function AccordionHeader( props: AccordionHeader.Props, forwardedRef: React.ForwardedRef, ) { - const { render, className, ...otherProps } = props; + const { render, className, ...other } = props; const { ownerState } = useAccordionItemContext(); @@ -30,19 +30,19 @@ const AccordionHeader = React.forwardRef(function AccordionHeader( ownerState, className, ref: forwardedRef, - extraProps: otherProps, + extraProps: other, customStyleHookMapping: accordionStyleHookMapping, }); return renderElement(); }); -export { AccordionHeader }; - export namespace AccordionHeader { export interface Props extends BaseUIComponentProps<'h3', AccordionItem.OwnerState> {} } +export { AccordionHeader }; + AccordionHeader.propTypes /* remove-proptypes */ = { // ┌────────────────────────────── Warning ──────────────────────────────┐ // │ These PropTypes are generated from the TypeScript type definitions. │ diff --git a/packages/mui-base/src/Accordion/Item/AccordionItem.test.tsx b/packages/mui-base/src/Accordion/Item/AccordionItem.test.tsx index 46bddc12f..b32219e16 100644 --- a/packages/mui-base/src/Accordion/Item/AccordionItem.test.tsx +++ b/packages/mui-base/src/Accordion/Item/AccordionItem.test.tsx @@ -1,11 +1,8 @@ import * as React from 'react'; -// import { expect } from 'chai'; -// import { spy } from 'sinon'; import * as Accordion from '@base_ui/react/Accordion'; import { describeConformance, createRenderer } from '#test-utils'; import { NOOP } from '../../utils/noop'; - -const { AccordionRootContext } = Accordion; +import { AccordionRootContext } from '../Root/AccordionRootContext'; const accordionRootContextValue: Accordion.Root.Context = { accordionItemRefs: { current: [] }, @@ -27,7 +24,6 @@ describe('', () => { const { render } = createRenderer(); describeConformance(, () => ({ - inheritComponent: 'div', render: (node) => render( diff --git a/packages/mui-base/src/Accordion/Item/AccordionItem.tsx b/packages/mui-base/src/Accordion/Item/AccordionItem.tsx index f09d0fcf8..8fd50d08e 100644 --- a/packages/mui-base/src/Accordion/Item/AccordionItem.tsx +++ b/packages/mui-base/src/Accordion/Item/AccordionItem.tsx @@ -36,12 +36,11 @@ const AccordionItem = React.forwardRef(function AccordionItem( onOpenChange: onOpenChangeProp, render, value: valueProp, - ...otherProps + ...other } = props; - const sectionRef = React.useRef(null); const { ref: listItemRef, index } = useCompositeListItem(); - const mergedRef = useForkRef(forwardedRef, listItemRef, sectionRef); + const mergedRef = useForkRef(forwardedRef, listItemRef); const { animated, @@ -71,9 +70,7 @@ const AccordionItem = React.forwardRef(function AccordionItem( const onOpenChange = useEventCallback((nextOpen: boolean) => { handleOpenChange(value, nextOpen); - if (onOpenChangeProp) { - onOpenChangeProp(nextOpen); - } + onOpenChangeProp?.(nextOpen); }); const collapsible = useCollapsibleRoot({ @@ -128,7 +125,7 @@ const AccordionItem = React.forwardRef(function AccordionItem( className, ownerState, ref: mergedRef, - extraProps: otherProps, + extraProps: other, customStyleHookMapping: accordionStyleHookMapping, }); @@ -141,8 +138,6 @@ const AccordionItem = React.forwardRef(function AccordionItem( ); }); -export { AccordionItem }; - export namespace AccordionItem { export type Value = number | string; @@ -166,6 +161,8 @@ export namespace AccordionItem { } } +export { AccordionItem }; + AccordionItem.propTypes /* remove-proptypes */ = { // ┌────────────────────────────── Warning ──────────────────────────────┐ // │ These PropTypes are generated from the TypeScript type definitions. │ diff --git a/packages/mui-base/src/Accordion/Panel/AccordionPanel.test.tsx b/packages/mui-base/src/Accordion/Panel/AccordionPanel.test.tsx index e146cbe8c..6fca9fa52 100644 --- a/packages/mui-base/src/Accordion/Panel/AccordionPanel.test.tsx +++ b/packages/mui-base/src/Accordion/Panel/AccordionPanel.test.tsx @@ -1,12 +1,10 @@ import * as React from 'react'; -// import { expect } from 'chai'; -// import { spy } from 'sinon'; import * as Accordion from '@base_ui/react/Accordion'; import * as Collapsible from '@base_ui/react/Collapsible'; import { describeConformance, createRenderer } from '#test-utils'; import { NOOP } from '../../utils/noop'; - -const { AccordionRootContext, AccordionItemContext } = Accordion; +import { AccordionRootContext } from '../Root/AccordionRootContext'; +import { AccordionItemContext } from '../Item/AccordionItemContext'; const { CollapsibleContext } = Collapsible; @@ -61,7 +59,6 @@ describe('', () => { const { render } = createRenderer(); describeConformance(, () => ({ - inheritComponent: 'div', render: (node) => render( diff --git a/packages/mui-base/src/Accordion/Panel/AccordionPanel.tsx b/packages/mui-base/src/Accordion/Panel/AccordionPanel.tsx index a4f95a399..c040990e9 100644 --- a/packages/mui-base/src/Accordion/Panel/AccordionPanel.tsx +++ b/packages/mui-base/src/Accordion/Panel/AccordionPanel.tsx @@ -71,14 +71,14 @@ const AccordionPanel = React.forwardRef(function AccordionPanel( return renderElement(); }); -export { AccordionPanel }; - export namespace AccordionPanel { export interface Props extends BaseUIComponentProps<'div', AccordionItem.OwnerState>, Pick {} } +export { AccordionPanel }; + AccordionPanel.propTypes /* remove-proptypes */ = { // ┌────────────────────────────── Warning ──────────────────────────────┐ // │ These PropTypes are generated from the TypeScript type definitions. │ diff --git a/packages/mui-base/src/Accordion/Root/AccordionRoot.test.tsx b/packages/mui-base/src/Accordion/Root/AccordionRoot.test.tsx index 38eeaae7e..064e0cec1 100644 --- a/packages/mui-base/src/Accordion/Root/AccordionRoot.test.tsx +++ b/packages/mui-base/src/Accordion/Root/AccordionRoot.test.tsx @@ -8,7 +8,6 @@ describe('', () => { const { render } = createRenderer(); describeConformance(, () => ({ - inheritComponent: 'div', render, refInstanceof: window.HTMLDivElement, })); diff --git a/packages/mui-base/src/Accordion/Root/AccordionRoot.tsx b/packages/mui-base/src/Accordion/Root/AccordionRoot.tsx index 838b7e3c7..18b4754bf 100644 --- a/packages/mui-base/src/Accordion/Root/AccordionRoot.tsx +++ b/packages/mui-base/src/Accordion/Root/AccordionRoot.tsx @@ -102,8 +102,6 @@ const AccordionRoot = React.forwardRef(function AccordionRoot( ); }); -export { AccordionRoot }; - export namespace AccordionRoot { export interface Context extends Omit { ownerState: OwnerState; @@ -123,6 +121,8 @@ export namespace AccordionRoot { } } +export { AccordionRoot }; + AccordionRoot.propTypes /* remove-proptypes */ = { // ┌────────────────────────────── Warning ──────────────────────────────┐ // │ These PropTypes are generated from the TypeScript type definitions. │ diff --git a/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.test.tsx b/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.test.tsx index fba9ab8b5..e7c1d82f0 100644 --- a/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.test.tsx +++ b/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.test.tsx @@ -1,12 +1,10 @@ import * as React from 'react'; -// import { expect } from 'chai'; -// import { spy } from 'sinon'; import * as Accordion from '@base_ui/react/Accordion'; import * as Collapsible from '@base_ui/react/Collapsible'; import { describeConformance, createRenderer } from '#test-utils'; import { NOOP } from '../../utils/noop'; - -const { AccordionRootContext, AccordionItemContext } = Accordion; +import { AccordionRootContext } from '../Root/AccordionRootContext'; +import { AccordionItemContext } from '../Item/AccordionItemContext'; const { CollapsibleContext } = Collapsible; @@ -61,7 +59,6 @@ describe('', () => { const { render } = createRenderer(); describeConformance(, () => ({ - inheritComponent: 'button', render: (node) => render( diff --git a/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.tsx b/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.tsx index dbea4f15f..a35c56799 100644 --- a/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.tsx +++ b/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.tsx @@ -58,12 +58,12 @@ const AccordionTrigger = React.forwardRef(function AccordionTrigger( return renderElement(); }); -export { AccordionTrigger }; - namespace AccordionTrigger { export interface Props extends BaseUIComponentProps<'button', AccordionItem.OwnerState> {} } +export { AccordionTrigger }; + AccordionTrigger.propTypes /* remove-proptypes */ = { // ┌────────────────────────────── Warning ──────────────────────────────┐ // │ These PropTypes are generated from the TypeScript type definitions. │ diff --git a/packages/mui-base/src/Accordion/index.ts b/packages/mui-base/src/Accordion/index.ts index 3077ffa4a..cfd89a887 100644 --- a/packages/mui-base/src/Accordion/index.ts +++ b/packages/mui-base/src/Accordion/index.ts @@ -1,10 +1,5 @@ export { AccordionRoot as Root } from './Root/AccordionRoot'; -export { useAccordionRoot } from './Root/useAccordionRoot'; -export { AccordionRootContext, useAccordionRootContext } from './Root/AccordionRootContext'; - export { AccordionItem as Item } from './Item/AccordionItem'; -export { AccordionItemContext, useAccordionItemContext } from './Item/AccordionItemContext'; - export { AccordionHeader as Header } from './Header/AccordionHeader'; export { AccordionTrigger as Trigger } from './Trigger/AccordionTrigger'; export { AccordionPanel as Panel } from './Panel/AccordionPanel'; From b37d00eaeec44c4291f9d5cfca8f3a02fe158ae8 Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Wed, 9 Oct 2024 18:35:59 +0800 Subject: [PATCH 13/37] Rename onOpenChange to onValueChange and misc fixes --- docs/data/api/accordion-root.json | 2 +- docs/data/components/accordion/accordion.mdx | 10 ++--- .../accordion-root/accordion-root.json | 2 +- .../Accordion/Header/AccordionHeader.test.tsx | 2 +- .../src/Accordion/Item/AccordionItem.test.tsx | 2 +- .../src/Accordion/Item/AccordionItem.tsx | 4 +- .../Accordion/Panel/AccordionPanel.test.tsx | 2 +- .../src/Accordion/Panel/AccordionPanel.tsx | 6 +++ .../src/Accordion/Root/AccordionRoot.test.tsx | 44 +++++++++---------- .../src/Accordion/Root/AccordionRoot.tsx | 6 +-- .../src/Accordion/Root/useAccordionRoot.ts | 20 ++++----- .../Trigger/AccordionTrigger.test.tsx | 2 +- .../Trigger/useCollapsibleTrigger.ts | 2 +- 13 files changed, 55 insertions(+), 49 deletions(-) diff --git a/docs/data/api/accordion-root.json b/docs/data/api/accordion-root.json index 0ae33d890..97156a66f 100644 --- a/docs/data/api/accordion-root.json +++ b/docs/data/api/accordion-root.json @@ -8,7 +8,7 @@ }, "disabled": { "type": { "name": "bool" }, "default": "false" }, "loop": { "type": { "name": "bool" }, "default": "true" }, - "onOpenChange": { "type": { "name": "func" } }, + "onValueChange": { "type": { "name": "func" } }, "openMultiple": { "type": { "name": "bool" }, "default": "true" }, "render": { "type": { "name": "union", "description": "element
| func" } }, "value": { diff --git a/docs/data/components/accordion/accordion.mdx b/docs/data/components/accordion/accordion.mdx index 6e9d3b4f9..1f2046e5b 100644 --- a/docs/data/components/accordion/accordion.mdx +++ b/docs/data/components/accordion/accordion.mdx @@ -113,13 +113,13 @@ When uncontrolled, use the `defaultValue` prop to set the initial state of the a ### Controlled -When controlled, pass the `value` and `onOpenChange` props to `Accordion.Root`: +When controlled, pass the `value` and `onValueChange` props to `Accordion.Root`: ```tsx const [value, setValue] = React.useState(['a']); return ( - + Toggle one @@ -153,14 +153,14 @@ Use controlled mode to always keep one `Item` open: ```tsx const [value, setValue] = React.useState([0]); -const handleOpenChange = (newValue) => { +const handleValueChange = (newValue) => { if (newValue.length > 0) { setValue(newValue); } }; return ( - + {/* subcomponents */} ); @@ -295,7 +295,7 @@ When using external libraries for animation, for example `framer-motion`, be awa function App() { const [value, setValue] = useState([0]); return ( - + Toggle diff --git a/docs/data/translations/api-docs/accordion-root/accordion-root.json b/docs/data/translations/api-docs/accordion-root/accordion-root.json index 251be809f..812b05541 100644 --- a/docs/data/translations/api-docs/accordion-root/accordion-root.json +++ b/docs/data/translations/api-docs/accordion-root/accordion-root.json @@ -14,7 +14,7 @@ "loop": { "description": "If true, focus will loop when moving focus between Triggers using the arrow keys." }, - "onOpenChange": { + "onValueChange": { "description": "Callback fired when an Accordion section is opened or closed. The value representing the involved section is provided as an argument." }, "openMultiple": { diff --git a/packages/mui-base/src/Accordion/Header/AccordionHeader.test.tsx b/packages/mui-base/src/Accordion/Header/AccordionHeader.test.tsx index 9c04d3872..234f78332 100644 --- a/packages/mui-base/src/Accordion/Header/AccordionHeader.test.tsx +++ b/packages/mui-base/src/Accordion/Header/AccordionHeader.test.tsx @@ -13,7 +13,7 @@ const accordionRootContextValue: Accordion.Root.Context = { animated: false, direction: 'ltr', disabled: false, - handleOpenChange() {}, + handleValueChange: NOOP, hiddenUntilFound: false, orientation: 'vertical', ownerState: { diff --git a/packages/mui-base/src/Accordion/Item/AccordionItem.test.tsx b/packages/mui-base/src/Accordion/Item/AccordionItem.test.tsx index b32219e16..0d22a096f 100644 --- a/packages/mui-base/src/Accordion/Item/AccordionItem.test.tsx +++ b/packages/mui-base/src/Accordion/Item/AccordionItem.test.tsx @@ -9,7 +9,7 @@ const accordionRootContextValue: Accordion.Root.Context = { animated: false, direction: 'ltr', disabled: false, - handleOpenChange: NOOP, + handleValueChange: NOOP, hiddenUntilFound: false, orientation: 'vertical', ownerState: { diff --git a/packages/mui-base/src/Accordion/Item/AccordionItem.tsx b/packages/mui-base/src/Accordion/Item/AccordionItem.tsx index 8fd50d08e..0fe6e8726 100644 --- a/packages/mui-base/src/Accordion/Item/AccordionItem.tsx +++ b/packages/mui-base/src/Accordion/Item/AccordionItem.tsx @@ -45,7 +45,7 @@ const AccordionItem = React.forwardRef(function AccordionItem( const { animated, disabled: contextDisabled, - handleOpenChange, + handleValueChange, ownerState: rootOwnerState, value: openValues, } = useAccordionRootContext(); @@ -69,7 +69,7 @@ const AccordionItem = React.forwardRef(function AccordionItem( }, [openValues, value]); const onOpenChange = useEventCallback((nextOpen: boolean) => { - handleOpenChange(value, nextOpen); + handleValueChange(value, nextOpen); onOpenChangeProp?.(nextOpen); }); diff --git a/packages/mui-base/src/Accordion/Panel/AccordionPanel.test.tsx b/packages/mui-base/src/Accordion/Panel/AccordionPanel.test.tsx index 6fca9fa52..1e8c767dd 100644 --- a/packages/mui-base/src/Accordion/Panel/AccordionPanel.test.tsx +++ b/packages/mui-base/src/Accordion/Panel/AccordionPanel.test.tsx @@ -13,7 +13,7 @@ const accordionRootContextValue: Accordion.Root.Context = { animated: false, direction: 'ltr', disabled: false, - handleOpenChange: NOOP, + handleValueChange: NOOP, hiddenUntilFound: false, orientation: 'vertical', ownerState: { diff --git a/packages/mui-base/src/Accordion/Panel/AccordionPanel.tsx b/packages/mui-base/src/Accordion/Panel/AccordionPanel.tsx index c040990e9..08ce784c8 100644 --- a/packages/mui-base/src/Accordion/Panel/AccordionPanel.tsx +++ b/packages/mui-base/src/Accordion/Panel/AccordionPanel.tsx @@ -29,6 +29,7 @@ const AccordionPanel = React.forwardRef(function AccordionPanel( hiddenUntilFound: hiddenUntilFoundProp, id: idProp, render, + style: styleProp, ...otherProps } = props; @@ -63,6 +64,7 @@ const AccordionPanel = React.forwardRef(function AccordionPanel( style: { '--accordion-content-height': height ? `${height}px` : undefined, '--accordion-content-width': width ? `${width}px` : undefined, + ...styleProp, }, }, customStyleHookMapping: accordionStyleHookMapping, @@ -106,4 +108,8 @@ AccordionPanel.propTypes /* remove-proptypes */ = { * A function to customize rendering of the component. */ render: PropTypes.oneOfType([PropTypes.element, PropTypes.func]), + /** + * @ignore + */ + style: PropTypes.object, } as any; diff --git a/packages/mui-base/src/Accordion/Root/AccordionRoot.test.tsx b/packages/mui-base/src/Accordion/Root/AccordionRoot.test.tsx index 064e0cec1..bb09dd029 100644 --- a/packages/mui-base/src/Accordion/Root/AccordionRoot.test.tsx +++ b/packages/mui-base/src/Accordion/Root/AccordionRoot.test.tsx @@ -710,12 +710,12 @@ describe('', () => { }); }); - describe('prop: onOpenChange', () => { + describe('prop: onValueChange', () => { it('default item value', async () => { - const onOpenChange = spy(); + const onValueChange = spy(); const { getByTestId, user } = await render( - + Trigger 1 @@ -734,24 +734,24 @@ describe('', () => { const trigger1 = getByTestId('trigger1'); const trigger2 = getByTestId('trigger2'); - expect(onOpenChange.callCount).to.equal(0); + expect(onValueChange.callCount).to.equal(0); await user.pointer({ keys: '[MouseLeft]', target: trigger1 }); - expect(onOpenChange.callCount).to.equal(1); - expect(onOpenChange.args[0][0]).to.deep.equal([0]); + expect(onValueChange.callCount).to.equal(1); + expect(onValueChange.args[0][0]).to.deep.equal([0]); await user.pointer({ keys: '[MouseLeft]', target: trigger2 }); - expect(onOpenChange.callCount).to.equal(2); - expect(onOpenChange.args[1][0]).to.deep.equal([0, 1]); + expect(onValueChange.callCount).to.equal(2); + expect(onValueChange.args[1][0]).to.deep.equal([0, 1]); }); it('custom item value', async () => { - const onOpenChange = spy(); + const onValueChange = spy(); const { getByTestId, user } = await render( - + Trigger 1 @@ -770,27 +770,27 @@ describe('', () => { const trigger1 = getByTestId('trigger1'); const trigger2 = getByTestId('trigger2'); - expect(onOpenChange.callCount).to.equal(0); + expect(onValueChange.callCount).to.equal(0); await user.pointer({ keys: '[MouseLeft]', target: trigger2 }); - expect(onOpenChange.callCount).to.equal(1); - expect(onOpenChange.args[0][0]).to.deep.equal(['two']); + expect(onValueChange.callCount).to.equal(1); + expect(onValueChange.args[0][0]).to.deep.equal(['two']); await user.pointer({ keys: '[MouseLeft]', target: trigger1 }); - expect(onOpenChange.callCount).to.equal(2); - expect(onOpenChange.args[1][0]).to.deep.equal(['two', 'one']); + expect(onValueChange.callCount).to.equal(2); + expect(onValueChange.args[1][0]).to.deep.equal(['two', 'one']); }); it('openMultiple is false', async () => { - const onOpenChange = spy(); + const onValueChange = spy(); const { getByTestId, user } = await render( @@ -811,17 +811,17 @@ describe('', () => { const trigger1 = getByTestId('trigger1'); const trigger2 = getByTestId('trigger2'); - expect(onOpenChange.callCount).to.equal(0); + expect(onValueChange.callCount).to.equal(0); await user.pointer({ keys: '[MouseLeft]', target: trigger1 }); - expect(onOpenChange.callCount).to.equal(1); - expect(onOpenChange.args[0][0]).to.deep.equal(['one']); + expect(onValueChange.callCount).to.equal(1); + expect(onValueChange.args[0][0]).to.deep.equal(['one']); await user.pointer({ keys: '[MouseLeft]', target: trigger2 }); - expect(onOpenChange.callCount).to.equal(2); - expect(onOpenChange.args[1][0]).to.deep.equal(['two']); + expect(onValueChange.callCount).to.equal(2); + expect(onValueChange.args[1][0]).to.deep.equal(['two']); }); }); }); diff --git a/packages/mui-base/src/Accordion/Root/AccordionRoot.tsx b/packages/mui-base/src/Accordion/Root/AccordionRoot.tsx index 18b4754bf..ed606d9de 100644 --- a/packages/mui-base/src/Accordion/Root/AccordionRoot.tsx +++ b/packages/mui-base/src/Accordion/Root/AccordionRoot.tsx @@ -28,7 +28,7 @@ const AccordionRoot = React.forwardRef(function AccordionRoot( disabled = false, hiddenUntilFound = false, loop, - onOpenChange, + onValueChange, openMultiple = true, orientation, value, @@ -54,7 +54,7 @@ const AccordionRoot = React.forwardRef(function AccordionRoot( defaultValue, loop, orientation, - onOpenChange, + onValueChange, openMultiple, value, }); @@ -168,7 +168,7 @@ AccordionRoot.propTypes /* remove-proptypes */ = { * Callback fired when an Accordion section is opened or closed. * The value representing the involved section is provided as an argument. */ - onOpenChange: PropTypes.func, + onValueChange: PropTypes.func, /** * Whether multiple Accordion sections can be opened at the same time * @default true diff --git a/packages/mui-base/src/Accordion/Root/useAccordionRoot.ts b/packages/mui-base/src/Accordion/Root/useAccordionRoot.ts index b4f4caafc..b4c875824 100644 --- a/packages/mui-base/src/Accordion/Root/useAccordionRoot.ts +++ b/packages/mui-base/src/Accordion/Root/useAccordionRoot.ts @@ -43,7 +43,7 @@ export function useAccordionRoot( disabled = false, direction = 'ltr', loop = true, - onOpenChange = NOOP, + onValueChange = NOOP, orientation = 'vertical', openMultiple = true, value: valueParam, @@ -59,24 +59,24 @@ export function useAccordionRoot( state: 'value', }); - const handleOpenChange = React.useCallback( + const handleValueChange = React.useCallback( (newValue: number | string, nextOpen: boolean) => { if (!openMultiple) { const nextValue = value[0] === newValue ? [] : [newValue]; setValue(nextValue); - onOpenChange(nextValue); + onValueChange(nextValue); } else if (nextOpen) { const nextOpenValues = value.slice(); nextOpenValues.push(newValue); setValue(nextOpenValues); - onOpenChange(nextOpenValues); + onValueChange(nextOpenValues); } else { const nextOpenValues = value.filter((v) => v !== newValue); setValue(nextOpenValues); - onOpenChange(nextOpenValues); + onValueChange(nextOpenValues); } }, - [onOpenChange, openMultiple, setValue, value], + [onValueChange, openMultiple, setValue, value], ); const getRootProps = React.useCallback( @@ -173,7 +173,7 @@ export function useAccordionRoot( animated, direction, disabled, - handleOpenChange, + handleValueChange, orientation, value, }), @@ -183,7 +183,7 @@ export function useAccordionRoot( animated, direction, disabled, - handleOpenChange, + handleValueChange, orientation, value, ], @@ -233,7 +233,7 @@ export namespace useAccordionRoot { * Callback fired when an Accordion section is opened or closed. * The value representing the involved section is provided as an argument. */ - onOpenChange?: (value: Value) => void; + onValueChange?: (value: Value) => void; /** * Whether multiple Accordion sections can be opened at the same time * @default true @@ -256,7 +256,7 @@ export namespace useAccordionRoot { * The disabled state of the Accordion */ disabled: boolean; - handleOpenChange: (value: number | string, nextOpen: boolean) => void; + handleValueChange: (value: number | string, nextOpen: boolean) => void; orientation: Orientation; /** * The open state of the Accordion represented by an array of the values diff --git a/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.test.tsx b/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.test.tsx index e7c1d82f0..82320b0b7 100644 --- a/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.test.tsx +++ b/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.test.tsx @@ -13,7 +13,7 @@ const accordionRootContextValue: Accordion.Root.Context = { animated: false, direction: 'ltr', disabled: false, - handleOpenChange: NOOP, + handleValueChange: NOOP, hiddenUntilFound: false, orientation: 'vertical', ownerState: { diff --git a/packages/mui-base/src/Collapsible/Trigger/useCollapsibleTrigger.ts b/packages/mui-base/src/Collapsible/Trigger/useCollapsibleTrigger.ts index a2c072c16..b8134383b 100644 --- a/packages/mui-base/src/Collapsible/Trigger/useCollapsibleTrigger.ts +++ b/packages/mui-base/src/Collapsible/Trigger/useCollapsibleTrigger.ts @@ -19,7 +19,7 @@ export function useCollapsibleTrigger( ): useCollapsibleTrigger.ReturnValue { const { contentId, disabled, id, open, rootRef: externalRef, setOpen } = parameters; - const { getRootProps: getButtonProps, rootRef: buttonRef } = useButton({ + const { getButtonProps, buttonRef } = useButton({ disabled, focusableWhenDisabled: true, type: 'button', From 85a3e12d3bce9d3617cd25d241a640e028cf9e8f Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Sun, 13 Oct 2024 15:39:48 +0800 Subject: [PATCH 14/37] Update experiments --- docs/app/experiments/accordion.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/app/experiments/accordion.tsx b/docs/app/experiments/accordion.tsx index a753b0427..4313d34d6 100644 --- a/docs/app/experiments/accordion.tsx +++ b/docs/app/experiments/accordion.tsx @@ -36,6 +36,7 @@ export default function App() { This is the contents of Accordion.Panel 1 + @@ -45,6 +46,7 @@ export default function App() { This is the contents of Accordion.Panel 2 + @@ -55,7 +57,7 @@ export default function App() {
- This is the contents of Accordion.Panel 3 + This is the contents of Accordion.Panel 3MUI
From a26bf0343a4b519add4f05a570bb8d966c6c5920 Mon Sep 17 00:00:00 2001 From: Olivier Tassinari Date: Thu, 10 Oct 2024 20:34:29 +0200 Subject: [PATCH 15/37] [core] Increase the minimum Node.js version support to 14.0.0 (#658) --- .browserslistrc | 8 ++++---- packages/mui-base/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.browserslistrc b/.browserslistrc index c5908f981..1b20f6868 100644 --- a/.browserslistrc +++ b/.browserslistrc @@ -43,16 +43,16 @@ samsung 22 # snapshot of `npx browserslist "maintained node versions"` # On update check all #stable-snapshot markers [node] -node 18.0 +node 14.0 # same as `node` [coverage] -node 18.0 +node 14.0 # same as `node` [development] -node 18.0 +node 14.0 # same as `node` [test] -node 18.0 +node 14.0 diff --git a/packages/mui-base/package.json b/packages/mui-base/package.json index e936c416a..0faaf17c5 100644 --- a/packages/mui-base/package.json +++ b/packages/mui-base/package.json @@ -86,6 +86,6 @@ "directory": "build" }, "engines": { - "node": ">=12.0.0" + "node": ">=14.0.0" } } From 95e7a1cd1dce0e5b50c77023cd692de092db740c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 11 Oct 2024 11:16:15 +0200 Subject: [PATCH 16/37] Bump Public packages' dependencies (major) (#725) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Michał Dudak --- .../eslint-plugin-material-ui/package.json | 2 +- packages/mui-base/package.json | 4 +- pnpm-lock.yaml | 167 ++++++++++++------ renovate.json | 4 +- 4 files changed, 116 insertions(+), 61 deletions(-) diff --git a/packages/eslint-plugin-material-ui/package.json b/packages/eslint-plugin-material-ui/package.json index 9385a40ae..5a7e5a991 100644 --- a/packages/eslint-plugin-material-ui/package.json +++ b/packages/eslint-plugin-material-ui/package.json @@ -7,7 +7,7 @@ "devDependencies": { "@types/eslint": "^8.56.12", "@typescript-eslint/experimental-utils": "^5.62.0", - "@typescript-eslint/parser": "^7.8.0" + "@typescript-eslint/parser": "^8.8.1" }, "scripts": { "test": "cd ../../ && cross-env NODE_ENV=test mocha 'packages/eslint-plugin-material-ui/**/*.test.js' --timeout 3000" diff --git a/packages/mui-base/package.json b/packages/mui-base/package.json index 0faaf17c5..0a2c4e0c5 100644 --- a/packages/mui-base/package.json +++ b/packages/mui-base/package.json @@ -53,7 +53,7 @@ }, "devDependencies": { "@mui/internal-test-utils": "1.0.14", - "@testing-library/react": "^15.0.7", + "@testing-library/react": "^16.0.1", "@testing-library/user-event": "^14.5.2", "@types/chai": "^4.3.20", "@types/chai-dom": "^1.11.3", @@ -67,7 +67,7 @@ "lodash": "^4.17.21", "react": "^18.3.1", "react-dom": "^18.3.1", - "sinon": "^17.0.1", + "sinon": "^19.0.2", "typescript": "^5.4.5" }, "peerDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a38792543..08ae29252 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -540,8 +540,8 @@ importers: specifier: ^5.62.0 version: 5.62.0(eslint@9.8.0)(typescript@5.6.3) '@typescript-eslint/parser': - specifier: ^7.8.0 - version: 7.8.0(eslint@9.8.0)(typescript@5.6.3) + specifier: ^8.8.1 + version: 8.8.1(eslint@9.8.0)(typescript@5.6.3) packages/mui-base: dependencies: @@ -577,8 +577,8 @@ importers: specifier: 1.0.14 version: 1.0.14(@babel/core@7.25.2)(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@testing-library/react': - specifier: ^15.0.7 - version: 15.0.7(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: ^16.0.1 + version: 16.0.1(@testing-library/dom@10.4.0)(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@testing-library/user-event': specifier: ^14.5.2 version: 14.5.2(@testing-library/dom@10.4.0) @@ -619,8 +619,8 @@ importers: specifier: ^18.3.1 version: 18.3.1(react@18.3.1) sinon: - specifier: ^17.0.1 - version: 17.0.1 + specifier: ^19.0.2 + version: 19.0.2 typescript: specifier: ^5.4.5 version: 5.6.3 @@ -2544,20 +2544,20 @@ packages: resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==} engines: {node: '>=18'} - '@sinonjs/commons@2.0.0': - resolution: {integrity: sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==} - '@sinonjs/commons@3.0.1': resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==} '@sinonjs/fake-timers@11.2.2': resolution: {integrity: sha512-G2piCSxQ7oWOxwGSAyFHfPIsyeJGXYtc6mFbnFA+kRXkiEnTl8c/8jul2S329iFBnDI9HGoeWWAZvuvOkZccgw==} - '@sinonjs/samsam@8.0.0': - resolution: {integrity: sha512-Bp8KUVlLp8ibJZrnvq2foVhP0IVX2CIprMJPK0vqGqgrDa0OHVKeZyBykqskkrdxV6yKBPmGasO8LVjAKR3Gew==} + '@sinonjs/fake-timers@13.0.2': + resolution: {integrity: sha512-4Bb+oqXZTSTZ1q27Izly9lv8B9dlV61CROxPiVtywwzv5SnytJqhvYe6FclHYuXml4cd1VHPo1zd5PmTeJozvA==} + + '@sinonjs/samsam@8.0.2': + resolution: {integrity: sha512-v46t/fwnhejRSFTGqbpn9u+LQ9xJDse10gNnPgAcxgdoCDMXj/G2asWAC/8Qs+BAZDicX+MNZouXT1A7c83kVw==} - '@sinonjs/text-encoding@0.7.2': - resolution: {integrity: sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==} + '@sinonjs/text-encoding@0.7.3': + resolution: {integrity: sha512-DE427ROAphMQzU4ENbliGYrBSYPXF+TtLg9S8vzeA+OF4ZKzoDdzfL8sxuMUGS/lgRhM6j1URSk9ghf7Xo1tyA==} '@slack/bolt@3.22.0': resolution: {integrity: sha512-iKDqGPEJDnrVwxSVlFW6OKTkijd7s4qLBeSufoBsTM0reTyfdp/5izIQVkxNfzjHi3o6qjdYbRXkYad5HBsBog==} @@ -2604,17 +2604,6 @@ packages: resolution: {integrity: sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==} engines: {node: '>=18'} - '@testing-library/react@15.0.7': - resolution: {integrity: sha512-cg0RvEdD1TIhhkm1IeYMQxrzy0MtUNfa3minv4MjbgcYzJAZ7yD0i0lwoPOTPr+INtiXFezt2o8xMSnyHhEn2Q==} - engines: {node: '>=18'} - peerDependencies: - '@types/react': ^18.3.10 - react: ^18.0.0 - react-dom: ^18.0.0 - peerDependenciesMeta: - '@types/react': - optional: true - '@testing-library/react@16.0.1': resolution: {integrity: sha512-dSmwJVtJXmku+iocRhWOUFbrERC76TX2Mnf0ATODz8brzAZrMBbzLwQixlBSanZxR6LddK3eiwpSFZgDET1URg==} engines: {node: '>=18'} @@ -2849,6 +2838,16 @@ packages: typescript: optional: true + '@typescript-eslint/parser@8.8.1': + resolution: {integrity: sha512-hQUVn2Lij2NAxVFEdvIGxT9gP1tq2yM83m+by3whWFsWC+1y8pxxxHUFE1UqDu2VsGi2i6RLcv4QvouM84U+ow==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + '@typescript-eslint/scope-manager@5.62.0': resolution: {integrity: sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -2857,6 +2856,10 @@ packages: resolution: {integrity: sha512-viEmZ1LmwsGcnr85gIq+FCYI7nO90DVbE37/ll51hjv9aG+YZMb4WDE2fyWpUR4O/UrhGRpYXK/XajcGTk2B8g==} engines: {node: ^18.18.0 || >=20.0.0} + '@typescript-eslint/scope-manager@8.8.1': + resolution: {integrity: sha512-X4JdU+66Mazev/J0gfXlcC/dV6JI37h+93W9BRYXrSn0hrE64IoWgVkO9MSJgEzoWkxONgaQpICWg8vAN74wlA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/type-utils@7.8.0': resolution: {integrity: sha512-H70R3AefQDQpz9mGv13Uhi121FNMh+WEaRqcXTX09YEDky21km4dV1ZXJIp8QjXc4ZaVkXVdohvWDzbnbHDS+A==} engines: {node: ^18.18.0 || >=20.0.0} @@ -2875,6 +2878,10 @@ packages: resolution: {integrity: sha512-wf0peJ+ZGlcH+2ZS23aJbOv+ztjeeP8uQ9GgwMJGVLx/Nj9CJt17GWgWWoSmoRVKAX2X+7fzEnAjxdvK2gqCLw==} engines: {node: ^18.18.0 || >=20.0.0} + '@typescript-eslint/types@8.8.1': + resolution: {integrity: sha512-WCcTP4SDXzMd23N27u66zTKMuEevH4uzU8C9jf0RO4E04yVHgQgW+r+TeVTNnO1KIfrL8ebgVVYYMMO3+jC55Q==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/typescript-estree@5.62.0': resolution: {integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -2893,6 +2900,15 @@ packages: typescript: optional: true + '@typescript-eslint/typescript-estree@8.8.1': + resolution: {integrity: sha512-A5d1R9p+X+1js4JogdNilDuuq+EHZdsH9MjTVxXOdVFfTJXunKJR/v+fNNyO4TnoOn5HqobzfRlc70NC6HTcdg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + '@typescript-eslint/utils@5.62.0': resolution: {integrity: sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -2913,6 +2929,10 @@ packages: resolution: {integrity: sha512-q4/gibTNBQNA0lGyYQCmWRS5D15n8rXh4QjK3KV+MBPlTYHpfBUT3D3PaPR/HeNiI9W6R7FvlkcGhNyAoP+caA==} engines: {node: ^18.18.0 || >=20.0.0} + '@typescript-eslint/visitor-keys@8.8.1': + resolution: {integrity: sha512-0/TdC3aeRAsW7MDvYRwEc1Uwm0TIBfzjPFgg60UU2Haj5qsCs9cc3zNgY71edqE3LbWfF/WoZQd3lJoDXFQpag==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@ungap/structured-clone@1.2.0': resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} @@ -4064,6 +4084,10 @@ packages: resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==} engines: {node: '>=0.3.1'} + diff@7.0.0: + resolution: {integrity: sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==} + engines: {node: '>=0.3.1'} + dir-glob@3.0.1: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} @@ -6437,8 +6461,8 @@ packages: nise@5.1.9: resolution: {integrity: sha512-qOnoujW4SV6e40dYxJOb3uvuoPHtmLzIk4TFo+j0jPJoC+5Z9xja5qH5JZobEPsa8+YYphMrOSwnrshEhG2qww==} - nise@6.0.0: - resolution: {integrity: sha512-K8ePqo9BFvN31HXwEtTNGzgrPpmvgciDsFz8aztFjt4LqKO/JeFD8tBOeuDiCMXrIl/m1YvfH8auSpxfaD09wg==} + nise@6.1.1: + resolution: {integrity: sha512-aMSAzLVY7LyeM60gvBS423nBmIPP+Wy7St7hsb+8/fc1HmeoHJfLO8CKse4u3BtOZvQLJghYPI2i/1WZrEj5/g==} no-case@3.0.4: resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} @@ -7696,6 +7720,9 @@ packages: sinon@18.0.1: resolution: {integrity: sha512-a2N2TDY1uGviajJ6r4D1CyRAkzE9NNVlYOV1wX5xQDuAk0ONgzgRl0EjCQuRCPxOwp13ghsMwt9Gdldujs39qw==} + sinon@19.0.2: + resolution: {integrity: sha512-euuToqM+PjO4UgXeLETsfQiuoyPXlqFezr6YZDFwHR3t4qaX0fZUe1MfPMznTL5f8BWrVS89KduLdMUsxFCO6g==} + sirv@2.0.4: resolution: {integrity: sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==} engines: {node: '>= 10'} @@ -11000,10 +11027,6 @@ snapshots: '@sindresorhus/merge-streams@4.0.0': {} - '@sinonjs/commons@2.0.0': - dependencies: - type-detect: 4.0.8 - '@sinonjs/commons@3.0.1': dependencies: type-detect: 4.0.8 @@ -11012,13 +11035,17 @@ snapshots: dependencies: '@sinonjs/commons': 3.0.1 - '@sinonjs/samsam@8.0.0': + '@sinonjs/fake-timers@13.0.2': dependencies: - '@sinonjs/commons': 2.0.0 + '@sinonjs/commons': 3.0.1 + + '@sinonjs/samsam@8.0.2': + dependencies: + '@sinonjs/commons': 3.0.1 lodash.get: 4.4.2 type-detect: 4.1.0 - '@sinonjs/text-encoding@0.7.2': {} + '@sinonjs/text-encoding@0.7.3': {} '@slack/bolt@3.22.0': dependencies: @@ -11121,16 +11148,6 @@ snapshots: lz-string: 1.5.0 pretty-format: 27.5.1 - '@testing-library/react@15.0.7(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@babel/runtime': 7.25.6 - '@testing-library/dom': 10.4.0 - '@types/react-dom': 18.3.0 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - optionalDependencies: - '@types/react': 18.3.10 - '@testing-library/react@16.0.1(@testing-library/dom@10.4.0)(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.25.6 @@ -11376,12 +11393,12 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@7.8.0(eslint@9.8.0)(typescript@5.6.3)': + '@typescript-eslint/parser@8.8.1(eslint@9.8.0)(typescript@5.6.3)': dependencies: - '@typescript-eslint/scope-manager': 7.8.0 - '@typescript-eslint/types': 7.8.0 - '@typescript-eslint/typescript-estree': 7.8.0(typescript@5.6.3) - '@typescript-eslint/visitor-keys': 7.8.0 + '@typescript-eslint/scope-manager': 8.8.1 + '@typescript-eslint/types': 8.8.1 + '@typescript-eslint/typescript-estree': 8.8.1(typescript@5.6.3) + '@typescript-eslint/visitor-keys': 8.8.1 debug: 4.3.7(supports-color@8.1.1) eslint: 9.8.0 optionalDependencies: @@ -11399,6 +11416,11 @@ snapshots: '@typescript-eslint/types': 7.8.0 '@typescript-eslint/visitor-keys': 7.8.0 + '@typescript-eslint/scope-manager@8.8.1': + dependencies: + '@typescript-eslint/types': 8.8.1 + '@typescript-eslint/visitor-keys': 8.8.1 + '@typescript-eslint/type-utils@7.8.0(eslint@8.57.1)(typescript@5.6.3)': dependencies: '@typescript-eslint/typescript-estree': 7.8.0(typescript@5.6.3) @@ -11415,6 +11437,8 @@ snapshots: '@typescript-eslint/types@7.8.0': {} + '@typescript-eslint/types@8.8.1': {} + '@typescript-eslint/typescript-estree@5.62.0(typescript@5.6.3)': dependencies: '@typescript-eslint/types': 5.62.0 @@ -11444,6 +11468,21 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/typescript-estree@8.8.1(typescript@5.6.3)': + dependencies: + '@typescript-eslint/types': 8.8.1 + '@typescript-eslint/visitor-keys': 8.8.1 + debug: 4.3.7(supports-color@8.1.1) + fast-glob: 3.3.2 + is-glob: 4.0.3 + minimatch: 9.0.4 + semver: 7.6.3 + ts-api-utils: 1.3.0(typescript@5.6.3) + optionalDependencies: + typescript: 5.6.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/utils@5.62.0(eslint@8.57.1)(typescript@5.6.3)': dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.1) @@ -11498,6 +11537,11 @@ snapshots: '@typescript-eslint/types': 7.8.0 eslint-visitor-keys: 3.4.3 + '@typescript-eslint/visitor-keys@8.8.1': + dependencies: + '@typescript-eslint/types': 8.8.1 + eslint-visitor-keys: 3.4.3 + '@ungap/structured-clone@1.2.0': {} '@webassemblyjs/ast@1.12.1': @@ -12786,6 +12830,8 @@ snapshots: diff@5.2.0: {} + diff@7.0.0: {} + dir-glob@3.0.1: dependencies: path-type: 4.0.0 @@ -15990,17 +16036,17 @@ snapshots: dependencies: '@sinonjs/commons': 3.0.1 '@sinonjs/fake-timers': 11.2.2 - '@sinonjs/text-encoding': 0.7.2 + '@sinonjs/text-encoding': 0.7.3 just-extend: 6.2.0 path-to-regexp: 6.2.2 - nise@6.0.0: + nise@6.1.1: dependencies: '@sinonjs/commons': 3.0.1 - '@sinonjs/fake-timers': 11.2.2 - '@sinonjs/text-encoding': 0.7.2 + '@sinonjs/fake-timers': 13.0.2 + '@sinonjs/text-encoding': 0.7.3 just-extend: 6.2.0 - path-to-regexp: 6.2.2 + path-to-regexp: 8.2.0 no-case@3.0.4: dependencies: @@ -17479,7 +17525,7 @@ snapshots: dependencies: '@sinonjs/commons': 3.0.1 '@sinonjs/fake-timers': 11.2.2 - '@sinonjs/samsam': 8.0.0 + '@sinonjs/samsam': 8.0.2 diff: 5.2.0 nise: 5.1.9 supports-color: 7.2.0 @@ -17488,9 +17534,18 @@ snapshots: dependencies: '@sinonjs/commons': 3.0.1 '@sinonjs/fake-timers': 11.2.2 - '@sinonjs/samsam': 8.0.0 + '@sinonjs/samsam': 8.0.2 diff: 5.2.0 - nise: 6.0.0 + nise: 6.1.1 + supports-color: 7.2.0 + + sinon@19.0.2: + dependencies: + '@sinonjs/commons': 3.0.1 + '@sinonjs/fake-timers': 13.0.2 + '@sinonjs/samsam': 8.0.2 + diff: 7.0.0 + nise: 6.1.1 supports-color: 7.2.0 sirv@2.0.4: diff --git a/renovate.json b/renovate.json index 5dbdb963f..9f3c3927b 100644 --- a/renovate.json +++ b/renovate.json @@ -96,7 +96,7 @@ }, { "groupName": "chai - incompatible versions", - "matchPackageNames": ["chai"], + "matchPackageNames": ["chai", "@types/chai"], "allowedVersions": "< 5.0.0" }, { @@ -106,7 +106,7 @@ }, { "groupName": "eslint - incompatible versions", - "matchPackageNames": ["eslint"], + "matchPackageNames": ["eslint", "@types/eslint"], "allowedVersions": "< 9.0.0" } ], From 2572aa271a47d04cc53b04e18992843a86255525 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 11 Oct 2024 12:03:40 +0200 Subject: [PATCH 17/37] Bump Public packages' dependencies (#724) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Michał Dudak --- packages/mui-base/package.json | 10 ++--- packages/mui-base/test/createRenderer.ts | 8 +++- pnpm-lock.yaml | 49 +++--------------------- 3 files changed, 16 insertions(+), 51 deletions(-) diff --git a/packages/mui-base/package.json b/packages/mui-base/package.json index 0a2c4e0c5..275f1d144 100644 --- a/packages/mui-base/package.json +++ b/packages/mui-base/package.json @@ -41,18 +41,18 @@ "typescript": "tsc -b tsconfig.json" }, "dependencies": { - "@babel/runtime": "^7.25.6", + "@babel/runtime": "^7.25.7", "@floating-ui/react": "^0.26.24", "@floating-ui/react-dom": "^2.1.2", "@floating-ui/utils": "^0.2.8", - "@mui/types": "^7.2.17", - "@mui/utils": "^6.1.1", + "@mui/types": "^7.2.18", + "@mui/utils": "^6.1.3", "clsx": "^2.1.1", "prop-types": "^15.8.1", "use-sync-external-store": "^1.2.2" }, "devDependencies": { - "@mui/internal-test-utils": "1.0.14", + "@mui/internal-test-utils": "1.0.16", "@testing-library/react": "^16.0.1", "@testing-library/user-event": "^14.5.2", "@types/chai": "^4.3.20", @@ -68,7 +68,7 @@ "react": "^18.3.1", "react-dom": "^18.3.1", "sinon": "^19.0.2", - "typescript": "^5.4.5" + "typescript": "^5.6.3" }, "peerDependencies": { "@types/react": "^17.0.0 || ^18.0.0", diff --git a/packages/mui-base/test/createRenderer.ts b/packages/mui-base/test/createRenderer.ts index a71f56089..d0e237f2c 100644 --- a/packages/mui-base/test/createRenderer.ts +++ b/packages/mui-base/test/createRenderer.ts @@ -10,16 +10,20 @@ import { type BaseUITestRenderer = Omit & { render: ( - element: React.ReactElement, + element: React.ReactElement, options?: RenderOptions, ) => Promise; }; +interface DataAttributes { + [key: `data-${string}`]: string; +} + export function createRenderer(globalOptions?: CreateRendererOptions): BaseUITestRenderer { const createRendererResult = sharedCreateRenderer(globalOptions); const { render: originalRender } = createRendererResult; - const render = async (element: React.ReactElement, options?: RenderOptions) => + const render = async (element: React.ReactElement, options?: RenderOptions) => act(async () => { const result = await originalRender(element, options); await flushMicrotasks(); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 08ae29252..5c674c693 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -558,10 +558,10 @@ importers: specifier: ^0.2.8 version: 0.2.8 '@mui/types': - specifier: ^7.2.17 + specifier: ^7.2.18 version: 7.2.18(@types/react@18.3.10) '@mui/utils': - specifier: ^6.1.1 + specifier: ^6.1.3 version: 6.1.3(@types/react@18.3.10)(react@18.3.1) clsx: specifier: ^2.1.1 @@ -574,8 +574,8 @@ importers: version: 1.2.2(react@18.3.1) devDependencies: '@mui/internal-test-utils': - specifier: 1.0.14 - version: 1.0.14(@babel/core@7.25.2)(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: 1.0.16 + version: 1.0.16(@babel/core@7.25.2)(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@testing-library/react': specifier: ^16.0.1 version: 16.0.1(@testing-library/dom@10.4.0)(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -622,7 +622,7 @@ importers: specifier: ^19.0.2 version: 19.0.2 typescript: - specifier: ^5.4.5 + specifier: ^5.6.3 version: 5.6.3 publishDirectory: build @@ -1913,12 +1913,6 @@ packages: '@mui/internal-scripts@1.0.23': resolution: {integrity: sha512-YUaIaZLpeazuw4tWt5G6aKXW9Zxy1fmOe/Xz0XlnbY9pINYEE8A4nNEU2kDZ8dWqgNxp0Hxzp0t/XrCm1EBDQQ==} - '@mui/internal-test-utils@1.0.14': - resolution: {integrity: sha512-yjaSlij39hzWZ643b9gTLLPur8JUF3lQDIs9fwDAgBERhyuhhfV7+6L7xpqAZ7hrkZ7Rr7YqbtiCtSgfgDRG5g==} - peerDependencies: - react: ^18.2.0 - react-dom: ^18.2.0 - '@mui/internal-test-utils@1.0.16': resolution: {integrity: sha512-giAwbpBEr61qZA2+aW1D+ZM9ZOfKdNnc9lfecTPmAoGr+Zg7sBS6OAjdNFUKjFWYFrR6yyZxNPeec8NiE26HBw==} peerDependencies: @@ -10267,39 +10261,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@mui/internal-test-utils@1.0.14(@babel/core@7.25.2)(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@babel/plugin-transform-modules-commonjs': 7.24.8(@babel/core@7.25.2) - '@babel/preset-typescript': 7.24.7(@babel/core@7.25.2) - '@babel/register': 7.24.6(@babel/core@7.25.2) - '@babel/runtime': 7.25.6 - '@emotion/cache': 11.13.1 - '@emotion/react': 11.13.3(@types/react@18.3.10)(react@18.3.1) - '@testing-library/dom': 10.4.0 - '@testing-library/react': 16.0.1(@testing-library/dom@10.4.0)(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@testing-library/user-event': 14.5.2(@testing-library/dom@10.4.0) - chai: 4.5.0 - chai-dom: 1.12.0(chai@4.5.0) - dom-accessibility-api: 0.7.0 - format-util: 1.0.5 - fs-extra: 11.2.0 - jsdom: 24.0.0 - lodash: 4.17.21 - mocha: 10.7.3 - playwright: 1.48.0 - prop-types: 15.8.1 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - sinon: 18.0.1 - transitivePeerDependencies: - - '@babel/core' - - '@types/react' - - '@types/react-dom' - - bufferutil - - canvas - - supports-color - - utf-8-validate - '@mui/internal-test-utils@1.0.16(@babel/core@7.25.2)(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/plugin-transform-modules-commonjs': 7.24.8(@babel/core@7.25.2) From c28dcf1ae58240c1d4bfd83b22034f271c47332a Mon Sep 17 00:00:00 2001 From: Olivier Tassinari Date: Sun, 13 Oct 2024 20:10:43 +0200 Subject: [PATCH 18/37] [examples] Avoid git diff when playing with examples --- examples/.gitignore | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/.gitignore b/examples/.gitignore index e0f7d4b6d..d11ce49a1 100644 --- a/examples/.gitignore +++ b/examples/.gitignore @@ -1 +1,3 @@ -**/yarn.lock +package-lock.json +pnpm-lock.yaml +yarn.lock From ef3c012198eb10d4597173331ce93ab37ebf657e Mon Sep 17 00:00:00 2001 From: atomiks Date: Mon, 14 Oct 2024 12:45:34 +1100 Subject: [PATCH 19/37] =?UTF-8?q?[Checkbox][Switch]=20Split=20data-state?= =?UTF-8?q?=20into=20data-checked,=20data-unchecked=E2=80=A6=20(#721)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../css/index.js | 6 ++--- .../css/index.tsx | 6 ++--- .../system/index.js | 6 ++--- .../system/index.tsx | 6 ++--- .../tailwind/index.js | 2 +- .../tailwind/index.tsx | 2 +- .../UnstyledCheckboxGroupNested.js | 6 ++--- .../UnstyledCheckboxGroupNested.tsx | 6 ++--- .../checkbox/UnstyledCheckboxIndeterminate.js | 8 +++--- .../UnstyledCheckboxIndeterminate.tsx | 8 +++--- .../UnstyledCheckboxIndeterminateGroup.js | 6 ++--- .../UnstyledCheckboxIndeterminateGroup.tsx | 6 ++--- .../css-modules/index.js | 6 ++--- .../css-modules/index.tsx | 6 ++--- .../system/index.js | 6 ++--- .../system/index.tsx | 6 ++--- .../tailwind/index.js | 2 +- .../tailwind/index.tsx | 2 +- .../css-modules/styles.module.css | 6 ++--- .../system/index.js | 6 ++--- .../system/index.tsx | 6 ++--- .../src/Checkbox/Root/CheckboxRoot.test.tsx | 26 ++++++++++++------- .../utils/useCustomStyleHookMapping.ts | 16 +++++++----- .../src/Switch/Root/SwitchRoot.test.tsx | 20 +++++++++----- packages/mui-base/src/Switch/styleHooks.ts | 12 ++++++++- 25 files changed, 109 insertions(+), 79 deletions(-) diff --git a/docs/data/components/checkbox-group/UnstyledCheckboxGroupIntroduction/css/index.js b/docs/data/components/checkbox-group/UnstyledCheckboxGroupIntroduction/css/index.js index 7a8dff8d4..6bd20db61 100644 --- a/docs/data/components/checkbox-group/UnstyledCheckboxGroupIntroduction/css/index.js +++ b/docs/data/components/checkbox-group/UnstyledCheckboxGroupIntroduction/css/index.js @@ -100,7 +100,7 @@ function Styles() { outline-offset: 2px; } - .Checkbox[data-state="checked"] { + .Checkbox[data-checked] { border-color: ${grey[800]}; background: ${grey[800]}; } @@ -112,7 +112,7 @@ function Styles() { color: ${grey[100]}; } - .Checkbox-indicator[data-state="checked"] { + .Checkbox-indicator[data-checked] { visibility: visible; } @@ -131,7 +131,7 @@ function Styles() { outline-offset: 2px; } - .Checkbox[data-state="checked"] { + .Checkbox[data-checked] { border-color: ${grey[300]}; background: ${grey[300]}; } diff --git a/docs/data/components/checkbox-group/UnstyledCheckboxGroupIntroduction/css/index.tsx b/docs/data/components/checkbox-group/UnstyledCheckboxGroupIntroduction/css/index.tsx index ad487a037..3d7b05826 100644 --- a/docs/data/components/checkbox-group/UnstyledCheckboxGroupIntroduction/css/index.tsx +++ b/docs/data/components/checkbox-group/UnstyledCheckboxGroupIntroduction/css/index.tsx @@ -100,7 +100,7 @@ function Styles() { outline-offset: 2px; } - .Checkbox[data-state="checked"] { + .Checkbox[data-checked] { border-color: ${grey[800]}; background: ${grey[800]}; } @@ -112,7 +112,7 @@ function Styles() { color: ${grey[100]}; } - .Checkbox-indicator[data-state="checked"] { + .Checkbox-indicator[data-checked] { visibility: visible; } @@ -131,7 +131,7 @@ function Styles() { outline-offset: 2px; } - .Checkbox[data-state="checked"] { + .Checkbox[data-checked] { border-color: ${grey[300]}; background: ${grey[300]}; } diff --git a/docs/data/components/checkbox-group/UnstyledCheckboxGroupIntroduction/system/index.js b/docs/data/components/checkbox-group/UnstyledCheckboxGroupIntroduction/system/index.js index 22affdf91..1033cfc87 100644 --- a/docs/data/components/checkbox-group/UnstyledCheckboxGroupIntroduction/system/index.js +++ b/docs/data/components/checkbox-group/UnstyledCheckboxGroupIntroduction/system/index.js @@ -98,7 +98,7 @@ const Checkbox = styled(BaseCheckbox.Root)( outline-offset: 2px; } - &[data-state="checked"], &[data-state="mixed"] { + &[data-checked], &[data-indeterminate] { border-color: transparent; background: ${blue[600]}; } @@ -132,8 +132,8 @@ const Indicator = styled(BaseCheckbox.Indicator)` visibility: hidden; color: ${grey[100]}; - &[data-state='checked'], - &[data-state='mixed'] { + &[data-checked], + &[data-indeterminate] { visibility: visible; } `; diff --git a/docs/data/components/checkbox-group/UnstyledCheckboxGroupIntroduction/system/index.tsx b/docs/data/components/checkbox-group/UnstyledCheckboxGroupIntroduction/system/index.tsx index d3e65b1c7..a83acafc0 100644 --- a/docs/data/components/checkbox-group/UnstyledCheckboxGroupIntroduction/system/index.tsx +++ b/docs/data/components/checkbox-group/UnstyledCheckboxGroupIntroduction/system/index.tsx @@ -98,7 +98,7 @@ const Checkbox = styled(BaseCheckbox.Root)( outline-offset: 2px; } - &[data-state="checked"], &[data-state="mixed"] { + &[data-checked], &[data-indeterminate] { border-color: transparent; background: ${blue[600]}; } @@ -132,8 +132,8 @@ const Indicator = styled(BaseCheckbox.Indicator)` visibility: hidden; color: ${grey[100]}; - &[data-state='checked'], - &[data-state='mixed'] { + &[data-checked], + &[data-indeterminate] { visibility: visible; } `; diff --git a/docs/data/components/checkbox-group/UnstyledCheckboxGroupIntroduction/tailwind/index.js b/docs/data/components/checkbox-group/UnstyledCheckboxGroupIntroduction/tailwind/index.js index f058738f5..577e7db15 100644 --- a/docs/data/components/checkbox-group/UnstyledCheckboxGroupIntroduction/tailwind/index.js +++ b/docs/data/components/checkbox-group/UnstyledCheckboxGroupIntroduction/tailwind/index.js @@ -104,7 +104,7 @@ const Indicator = React.forwardRef(function Indicator(props, ref) { ref={ref} className={(state) => classNames( - 'h-full inline-block invisible data-[state=checked]:visible text-gray-100', + 'h-full inline-block invisible data-[checked]:visible text-gray-100', typeof props.className === 'function' ? props.className(state) : props.className, diff --git a/docs/data/components/checkbox-group/UnstyledCheckboxGroupIntroduction/tailwind/index.tsx b/docs/data/components/checkbox-group/UnstyledCheckboxGroupIntroduction/tailwind/index.tsx index 5c0615461..3169ca830 100644 --- a/docs/data/components/checkbox-group/UnstyledCheckboxGroupIntroduction/tailwind/index.tsx +++ b/docs/data/components/checkbox-group/UnstyledCheckboxGroupIntroduction/tailwind/index.tsx @@ -99,7 +99,7 @@ const Indicator = React.forwardRef classNames( - 'h-full inline-block invisible data-[state=checked]:visible text-gray-100', + 'h-full inline-block invisible data-[checked]:visible text-gray-100', typeof props.className === 'function' ? props.className(state) : props.className, diff --git a/docs/data/components/checkbox-group/UnstyledCheckboxGroupNested.js b/docs/data/components/checkbox-group/UnstyledCheckboxGroupNested.js index ffe0f6883..c70d40384 100644 --- a/docs/data/components/checkbox-group/UnstyledCheckboxGroupNested.js +++ b/docs/data/components/checkbox-group/UnstyledCheckboxGroupNested.js @@ -89,7 +89,7 @@ const Checkbox = styled(BaseCheckbox.Root)( outline-offset: 2px; } - &[data-state="checked"], &[data-state="mixed"] { + &[data-checked], &[data-indeterminate] { border-color: transparent; background: ${blue[600]}; } @@ -141,8 +141,8 @@ const Indicator = styled(BaseCheckbox.Indicator)` visibility: hidden; color: ${grey[100]}; - &[data-state='checked'], - &[data-state='mixed'] { + &[data-checked], + &[data-indeterminate] { visibility: visible; } `; diff --git a/docs/data/components/checkbox-group/UnstyledCheckboxGroupNested.tsx b/docs/data/components/checkbox-group/UnstyledCheckboxGroupNested.tsx index 2a212b9e9..13326baf0 100644 --- a/docs/data/components/checkbox-group/UnstyledCheckboxGroupNested.tsx +++ b/docs/data/components/checkbox-group/UnstyledCheckboxGroupNested.tsx @@ -89,7 +89,7 @@ const Checkbox = styled(BaseCheckbox.Root)( outline-offset: 2px; } - &[data-state="checked"], &[data-state="mixed"] { + &[data-checked], &[data-indeterminate] { border-color: transparent; background: ${blue[600]}; } @@ -143,8 +143,8 @@ const Indicator = styled(BaseCheckbox.Indicator)` visibility: hidden; color: ${grey[100]}; - &[data-state='checked'], - &[data-state='mixed'] { + &[data-checked], + &[data-indeterminate] { visibility: visible; } `; diff --git a/docs/data/components/checkbox/UnstyledCheckboxIndeterminate.js b/docs/data/components/checkbox/UnstyledCheckboxIndeterminate.js index 167666851..786d49acc 100644 --- a/docs/data/components/checkbox/UnstyledCheckboxIndeterminate.js +++ b/docs/data/components/checkbox/UnstyledCheckboxIndeterminate.js @@ -52,8 +52,8 @@ const Checkbox = styled(BaseCheckbox.Root)( outline-offset: 2px; } - &[data-state='checked'], - &[data-state='mixed'] { + &[data-checked], + &[data-indeterminate] { border-color: transparent; background: ${blue[600]}; } @@ -84,8 +84,8 @@ const Indicator = styled(BaseCheckbox.Indicator)` display: inline-block; visibility: hidden; - &[data-state='checked'], - &[data-state='mixed'] { + &[data-checked], + &[data-indeterminate] { visibility: visible; } `; diff --git a/docs/data/components/checkbox/UnstyledCheckboxIndeterminate.tsx b/docs/data/components/checkbox/UnstyledCheckboxIndeterminate.tsx index 2a41d4853..3b9e87f9a 100644 --- a/docs/data/components/checkbox/UnstyledCheckboxIndeterminate.tsx +++ b/docs/data/components/checkbox/UnstyledCheckboxIndeterminate.tsx @@ -52,8 +52,8 @@ const Checkbox = styled(BaseCheckbox.Root)( outline-offset: 2px; } - &[data-state='checked'], - &[data-state='mixed'] { + &[data-checked], + &[data-indeterminate] { border-color: transparent; background: ${blue[600]}; } @@ -86,8 +86,8 @@ const Indicator = styled(BaseCheckbox.Indicator)` display: inline-block; visibility: hidden; - &[data-state='checked'], - &[data-state='mixed'] { + &[data-checked], + &[data-indeterminate] { visibility: visible; } `; diff --git a/docs/data/components/checkbox/UnstyledCheckboxIndeterminateGroup.js b/docs/data/components/checkbox/UnstyledCheckboxIndeterminateGroup.js index d80db2e23..44234bb4c 100644 --- a/docs/data/components/checkbox/UnstyledCheckboxIndeterminateGroup.js +++ b/docs/data/components/checkbox/UnstyledCheckboxIndeterminateGroup.js @@ -101,7 +101,7 @@ const Checkbox = styled(BaseCheckbox.Root)( outline-offset: 2px; } - &[data-state="checked"], &[data-state="mixed"] { + &[data-checked], &[data-indeterminate] { border-color: transparent; background: ${blue[600]}; } @@ -153,8 +153,8 @@ const Indicator = styled(BaseCheckbox.Indicator)` visibility: hidden; color: ${grey[100]}; - &[data-state='checked'], - &[data-state='mixed'] { + &[data-checked], + &[data-indeterminate] { visibility: visible; } `; diff --git a/docs/data/components/checkbox/UnstyledCheckboxIndeterminateGroup.tsx b/docs/data/components/checkbox/UnstyledCheckboxIndeterminateGroup.tsx index 4f8cb9e50..f6907fe19 100644 --- a/docs/data/components/checkbox/UnstyledCheckboxIndeterminateGroup.tsx +++ b/docs/data/components/checkbox/UnstyledCheckboxIndeterminateGroup.tsx @@ -101,7 +101,7 @@ const Checkbox = styled(BaseCheckbox.Root)( outline-offset: 2px; } - &[data-state="checked"], &[data-state="mixed"] { + &[data-checked], &[data-indeterminate] { border-color: transparent; background: ${blue[600]}; } @@ -155,8 +155,8 @@ const Indicator = styled(BaseCheckbox.Indicator)` visibility: hidden; color: ${grey[100]}; - &[data-state='checked'], - &[data-state='mixed'] { + &[data-checked], + &[data-indeterminate] { visibility: visible; } `; diff --git a/docs/data/components/checkbox/UnstyledCheckboxIntroduction/css-modules/index.js b/docs/data/components/checkbox/UnstyledCheckboxIntroduction/css-modules/index.js index 1b5d63a53..b4a264dad 100644 --- a/docs/data/components/checkbox/UnstyledCheckboxIntroduction/css-modules/index.js +++ b/docs/data/components/checkbox/UnstyledCheckboxIntroduction/css-modules/index.js @@ -92,7 +92,7 @@ function Styles() { outline-offset: 2px; } - .Checkbox[data-state="checked"] { + .Checkbox[data-checked] { border-color: ${grey[800]}; background: ${grey[800]}; } @@ -104,7 +104,7 @@ function Styles() { color: ${isDarkMode ? grey[900] : grey[100]}; } - .Checkbox-indicator[data-state="checked"] { + .Checkbox-indicator[data-checked] { visibility: visible; } @@ -118,7 +118,7 @@ function Styles() { border-color: ${grey[500]}; } - .Checkbox[data-state="checked"] { + .Checkbox[data-checked] { border-color: ${grey[300]}; background: ${grey[300]}; } diff --git a/docs/data/components/checkbox/UnstyledCheckboxIntroduction/css-modules/index.tsx b/docs/data/components/checkbox/UnstyledCheckboxIntroduction/css-modules/index.tsx index 130758f8f..758acd41b 100644 --- a/docs/data/components/checkbox/UnstyledCheckboxIntroduction/css-modules/index.tsx +++ b/docs/data/components/checkbox/UnstyledCheckboxIntroduction/css-modules/index.tsx @@ -92,7 +92,7 @@ function Styles() { outline-offset: 2px; } - .Checkbox[data-state="checked"] { + .Checkbox[data-checked] { border-color: ${grey[800]}; background: ${grey[800]}; } @@ -104,7 +104,7 @@ function Styles() { color: ${isDarkMode ? grey[900] : grey[100]}; } - .Checkbox-indicator[data-state="checked"] { + .Checkbox-indicator[data-checked] { visibility: visible; } @@ -118,7 +118,7 @@ function Styles() { border-color: ${grey[500]}; } - .Checkbox[data-state="checked"] { + .Checkbox[data-checked] { border-color: ${grey[300]}; background: ${grey[300]}; } diff --git a/docs/data/components/checkbox/UnstyledCheckboxIntroduction/system/index.js b/docs/data/components/checkbox/UnstyledCheckboxIntroduction/system/index.js index 517b2c262..d5004c166 100644 --- a/docs/data/components/checkbox/UnstyledCheckboxIntroduction/system/index.js +++ b/docs/data/components/checkbox/UnstyledCheckboxIntroduction/system/index.js @@ -66,7 +66,7 @@ const Checkbox = styled(BaseCheckbox.Root)( outline-offset: 2px; } - &[data-state="checked"], &[data-state="mixed"] { + &[data-checked], &[data-indeterminate] { border-color: transparent; background: ${blue[600]}; } @@ -100,8 +100,8 @@ const Indicator = styled(BaseCheckbox.Indicator)` display: inline-block; visibility: hidden; - &[data-state='checked'], - &[data-state='mixed'] { + &[data-checked], + &[data-indeterminate] { visibility: visible; } `; diff --git a/docs/data/components/checkbox/UnstyledCheckboxIntroduction/system/index.tsx b/docs/data/components/checkbox/UnstyledCheckboxIntroduction/system/index.tsx index f3990ce3c..599539a6e 100644 --- a/docs/data/components/checkbox/UnstyledCheckboxIntroduction/system/index.tsx +++ b/docs/data/components/checkbox/UnstyledCheckboxIntroduction/system/index.tsx @@ -66,7 +66,7 @@ const Checkbox = styled(BaseCheckbox.Root)( outline-offset: 2px; } - &[data-state="checked"], &[data-state="mixed"] { + &[data-checked], &[data-indeterminate] { border-color: transparent; background: ${blue[600]}; } @@ -100,8 +100,8 @@ const Indicator = styled(BaseCheckbox.Indicator)` display: inline-block; visibility: hidden; - &[data-state='checked'], - &[data-state='mixed'] { + &[data-checked], + &[data-indeterminate] { visibility: visible; } `; diff --git a/docs/data/components/checkbox/UnstyledCheckboxIntroduction/tailwind/index.js b/docs/data/components/checkbox/UnstyledCheckboxIntroduction/tailwind/index.js index d85f45e48..f27426ca2 100644 --- a/docs/data/components/checkbox/UnstyledCheckboxIntroduction/tailwind/index.js +++ b/docs/data/components/checkbox/UnstyledCheckboxIntroduction/tailwind/index.js @@ -76,7 +76,7 @@ const Indicator = React.forwardRef(function Indicator(props, ref) { ref={ref} className={(state) => classNames( - 'h-full inline-block invisible data-[state=checked]:visible text-gray-100', + 'h-full inline-block invisible data-[checked]:visible text-gray-100', typeof props.className === 'function' ? props.className(state) : props.className, diff --git a/docs/data/components/checkbox/UnstyledCheckboxIntroduction/tailwind/index.tsx b/docs/data/components/checkbox/UnstyledCheckboxIntroduction/tailwind/index.tsx index 43d903023..595509db4 100644 --- a/docs/data/components/checkbox/UnstyledCheckboxIntroduction/tailwind/index.tsx +++ b/docs/data/components/checkbox/UnstyledCheckboxIntroduction/tailwind/index.tsx @@ -71,7 +71,7 @@ const Indicator = React.forwardRef classNames( - 'h-full inline-block invisible data-[state=checked]:visible text-gray-100', + 'h-full inline-block invisible data-[checked]:visible text-gray-100', typeof props.className === 'function' ? props.className(state) : props.className, diff --git a/docs/data/components/switch/UnstyledSwitchIntroduction/css-modules/styles.module.css b/docs/data/components/switch/UnstyledSwitchIntroduction/css-modules/styles.module.css index d0b25a599..37dde94ec 100644 --- a/docs/data/components/switch/UnstyledSwitchIntroduction/css-modules/styles.module.css +++ b/docs/data/components/switch/UnstyledSwitchIntroduction/css-modules/styles.module.css @@ -42,12 +42,12 @@ } } - &[data-state='checked'] { + &[data-checked] { border: none; background: var(--cyan-500); } - &[data-state='checked']:not([data-disabled]):hover { + &[data-checked]:not([data-disabled]):hover { background: var(--cyan-700); } } @@ -73,7 +73,7 @@ } } -.thumb[data-state='checked'] { +.thumb[data-checked] { left: 18px; background-color: #fff; box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.3); diff --git a/docs/data/components/switch/UnstyledSwitchIntroduction/system/index.js b/docs/data/components/switch/UnstyledSwitchIntroduction/system/index.js index bac765760..12d3ea815 100644 --- a/docs/data/components/switch/UnstyledSwitchIntroduction/system/index.js +++ b/docs/data/components/switch/UnstyledSwitchIntroduction/system/index.js @@ -72,12 +72,12 @@ const Switch = styled(BaseSwitch.Root)( box-shadow: 0 0 0 3px ${theme.palette.mode === 'dark' ? blue[700] : blue[200]}; } - &[data-state="checked"] { + &[data-checked] { border: none; background: ${blue[500]}; } - &[data-state="checked"]:not([data-disabled]):hover { + &[data-checked]:not([data-disabled]):hover { background: ${blue[700]}; } `, @@ -101,7 +101,7 @@ const Thumb = styled(BaseSwitch.Thumb)( theme.palette.mode === 'dark' ? 'rgba(0, 0, 0, 0.25)' : 'rgba(0, 0, 0, 0.1)' }; - &[data-state="checked"] { + &[data-checked] { left: 18px; background-color: #fff; box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.3); diff --git a/docs/data/components/switch/UnstyledSwitchIntroduction/system/index.tsx b/docs/data/components/switch/UnstyledSwitchIntroduction/system/index.tsx index bac765760..12d3ea815 100644 --- a/docs/data/components/switch/UnstyledSwitchIntroduction/system/index.tsx +++ b/docs/data/components/switch/UnstyledSwitchIntroduction/system/index.tsx @@ -72,12 +72,12 @@ const Switch = styled(BaseSwitch.Root)( box-shadow: 0 0 0 3px ${theme.palette.mode === 'dark' ? blue[700] : blue[200]}; } - &[data-state="checked"] { + &[data-checked] { border: none; background: ${blue[500]}; } - &[data-state="checked"]:not([data-disabled]):hover { + &[data-checked]:not([data-disabled]):hover { background: ${blue[700]}; } `, @@ -101,7 +101,7 @@ const Thumb = styled(BaseSwitch.Thumb)( theme.palette.mode === 'dark' ? 'rgba(0, 0, 0, 0.25)' : 'rgba(0, 0, 0, 0.1)' }; - &[data-state="checked"] { + &[data-checked] { left: 18px; background-color: #fff; box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.3); diff --git a/packages/mui-base/src/Checkbox/Root/CheckboxRoot.test.tsx b/packages/mui-base/src/Checkbox/Root/CheckboxRoot.test.tsx index 5f136f54b..169a0f38a 100644 --- a/packages/mui-base/src/Checkbox/Root/CheckboxRoot.test.tsx +++ b/packages/mui-base/src/Checkbox/Root/CheckboxRoot.test.tsx @@ -17,7 +17,7 @@ describe('', () => { describe('extra props', () => { it('can override the built-in attributes', async () => { - const { container } = await render(); + const { container } = await render(); expect(container.firstElementChild as HTMLElement).to.have.attribute('role', 'switch'); }); }); @@ -156,11 +156,6 @@ describe('', () => { expect(checkbox).to.have.attribute('aria-checked', 'mixed'); }); - it('should not set the `data-indeterminate` attribute', async () => { - const { getAllByRole } = await render(); - expect(getAllByRole('checkbox')[0]).to.not.have.attribute('data-indeterminate', 'true'); - }); - it('should not have the aria attribute when `indeterminate` is not set', async () => { const { getAllByRole } = await render(); expect(getAllByRole('checkbox')[0]).not.to.have.attribute('aria-checked', 'mixed'); @@ -185,7 +180,7 @@ describe('', () => { }); it('should place the style hooks on the root and the indicator', async () => { - const { getAllByRole } = await render( + const { getAllByRole, setProps } = await render( , @@ -194,15 +189,28 @@ describe('', () => { const [checkbox] = getAllByRole('checkbox'); const indicator = checkbox.querySelector('span'); - expect(checkbox).to.have.attribute('data-state', 'checked'); + expect(checkbox).to.have.attribute('data-checked', ''); + expect(checkbox).not.to.have.attribute('data-unchecked'); + expect(checkbox).to.have.attribute('data-disabled', 'true'); expect(checkbox).to.have.attribute('data-readonly', 'true'); expect(checkbox).to.have.attribute('data-required', 'true'); - expect(indicator).to.have.attribute('data-state', 'checked'); + expect(indicator).to.have.attribute('data-checked', ''); + expect(indicator).not.to.have.attribute('data-unchecked'); + expect(indicator).to.have.attribute('data-disabled', 'true'); expect(indicator).to.have.attribute('data-readonly', 'true'); expect(indicator).to.have.attribute('data-required', 'true'); + + setProps({ disabled: false, readOnly: false }); + fireEvent.click(checkbox); + + expect(checkbox).to.have.attribute('data-unchecked', ''); + expect(checkbox).not.to.have.attribute('data-checked'); + + expect(indicator).to.have.attribute('data-unchecked', ''); + expect(indicator).not.to.have.attribute('data-checked'); }); it('should set the name attribute on the input', async () => { diff --git a/packages/mui-base/src/Checkbox/utils/useCustomStyleHookMapping.ts b/packages/mui-base/src/Checkbox/utils/useCustomStyleHookMapping.ts index d0b604d65..7b2d06cfc 100644 --- a/packages/mui-base/src/Checkbox/utils/useCustomStyleHookMapping.ts +++ b/packages/mui-base/src/Checkbox/utils/useCustomStyleHookMapping.ts @@ -6,16 +6,20 @@ import type { CheckboxRoot } from '../Root/CheckboxRoot'; export function useCustomStyleHookMapping(ownerState: CheckboxRoot.OwnerState) { return React.useMemo>( () => ({ - // `data-state="mixed"` is used to style the checkbox when it's indeterminate - indeterminate: () => null, - checked(value) { - let state = value ? 'checked' : 'unchecked'; + checked(value): Record { if (ownerState.indeterminate) { - state = 'mixed'; + // `data-indeterminate` is already handled by the `indeterminate` prop. + return {}; + } + + if (value) { + return { + 'data-checked': '', + }; } return { - 'data-state': state, + 'data-unchecked': '', }; }, }), diff --git a/packages/mui-base/src/Switch/Root/SwitchRoot.test.tsx b/packages/mui-base/src/Switch/Root/SwitchRoot.test.tsx index ecfc91645..110ee301e 100644 --- a/packages/mui-base/src/Switch/Root/SwitchRoot.test.tsx +++ b/packages/mui-base/src/Switch/Root/SwitchRoot.test.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import { expect } from 'chai'; import { spy } from 'sinon'; -import { act, screen } from '@mui/internal-test-utils'; +import { act, fireEvent, screen } from '@mui/internal-test-utils'; import * as Switch from '@base_ui/react/Switch'; import { userEvent } from '@testing-library/user-event'; import { describeConformance, createRenderer } from '#test-utils'; @@ -72,9 +72,8 @@ describe('', () => { describe('extra props', () => { it('should override the built-in attributes', async () => { - await render(); + await render(); expect(screen.getByTestId('switch')).to.have.attribute('role', 'checkbox'); - expect(screen.getByTestId('switch')).to.have.attribute('data-state', 'checked'); }); }); @@ -247,7 +246,7 @@ describe('', () => { }); it('should place the style hooks on the root and the thumb', async () => { - await render( + const { setProps } = await render( , @@ -256,15 +255,24 @@ describe('', () => { const switchElement = screen.getByRole('switch'); const thumb = screen.getByTestId('thumb'); - expect(switchElement).to.have.attribute('data-state', 'checked'); + expect(switchElement).to.have.attribute('data-checked', ''); expect(switchElement).to.have.attribute('data-disabled', 'true'); expect(switchElement).to.have.attribute('data-readonly', 'true'); expect(switchElement).to.have.attribute('data-required', 'true'); - expect(thumb).to.have.attribute('data-state', 'checked'); + expect(thumb).to.have.attribute('data-checked', ''); expect(thumb).to.have.attribute('data-disabled', 'true'); expect(thumb).to.have.attribute('data-readonly', 'true'); expect(thumb).to.have.attribute('data-required', 'true'); + + setProps({ disabled: false, readOnly: false }); + fireEvent.click(switchElement); + + expect(switchElement).to.have.attribute('data-unchecked', ''); + expect(switchElement).not.to.have.attribute('data-checked'); + + expect(thumb).to.have.attribute('data-unchecked', ''); + expect(thumb).not.to.have.attribute('data-checked'); }); it('should set the name attribute on the input', async () => { diff --git a/packages/mui-base/src/Switch/styleHooks.ts b/packages/mui-base/src/Switch/styleHooks.ts index 0c8fd40ab..c95bcd792 100644 --- a/packages/mui-base/src/Switch/styleHooks.ts +++ b/packages/mui-base/src/Switch/styleHooks.ts @@ -2,5 +2,15 @@ import type { SwitchRoot } from './Root/SwitchRoot'; import type { CustomStyleHookMapping } from '../utils/getStyleHookProps'; export const styleHookMapping: CustomStyleHookMapping = { - checked: (value) => ({ 'data-state': value ? 'checked' : 'unchecked' }), + checked(value): Record { + if (value) { + return { + 'data-checked': '', + }; + } + + return { + 'data-unchecked': '', + }; + }, }; From 094b55834cb68a495740435e76e3ab3361bf09f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dudak?= Date: Mon, 14 Oct 2024 09:26:42 +0200 Subject: [PATCH 20/37] [core] Improve DX of importing Base UI components (#700) --- docs/app/DocsProviders.tsx | 2 +- .../app/experiments/collapsible-accordion.tsx | 2 +- docs/app/experiments/collapsible-framer.tsx | 2 +- .../collapsible-hidden-until-found.tsx | 2 +- docs/app/experiments/collapsible.tsx | 2 +- docs/app/experiments/dialog.tsx | 2 +- docs/app/experiments/menu-anchor-el.tsx | 2 +- docs/app/experiments/menu-anchor-ref.tsx | 2 +- docs/app/experiments/progress.tsx | 2 +- .../slider-change-committed-lag.tsx | 2 +- docs/app/experiments/slider-marks.tsx | 5 +- docs/app/experiments/slider-template.tsx | 2 +- docs/app/experiments/slider-tooltip.tsx | 4 +- docs/app/experiments/slider.tsx | 5 +- docs/app/experiments/tabs.tsx | 2 +- docs/app/experiments/tooltip.tsx | 2 +- docs/data/api/alert-dialog-backdrop.json | 2 +- docs/data/api/alert-dialog-close.json | 2 +- docs/data/api/alert-dialog-description.json | 2 +- docs/data/api/alert-dialog-popup.json | 2 +- docs/data/api/alert-dialog-root.json | 2 +- docs/data/api/alert-dialog-title.json | 2 +- docs/data/api/alert-dialog-trigger.json | 2 +- docs/data/api/checkbox-group-root.json | 2 +- docs/data/api/checkbox-indicator.json | 2 +- docs/data/api/checkbox-root.json | 2 +- docs/data/api/collapsible-content.json | 2 +- docs/data/api/collapsible-root.json | 2 +- docs/data/api/collapsible-trigger.json | 2 +- docs/data/api/dialog-backdrop.json | 2 +- docs/data/api/dialog-close.json | 4 +- docs/data/api/dialog-description.json | 2 +- docs/data/api/dialog-popup.json | 4 +- docs/data/api/dialog-root.json | 2 +- docs/data/api/dialog-title.json | 4 +- docs/data/api/dialog-trigger.json | 2 +- docs/data/api/field-control.json | 4 +- docs/data/api/field-description.json | 2 +- docs/data/api/field-error.json | 2 +- docs/data/api/field-label.json | 2 +- docs/data/api/field-root.json | 2 +- docs/data/api/field-validity.json | 2 +- docs/data/api/fieldset-legend.json | 2 +- docs/data/api/fieldset-root.json | 2 +- docs/data/api/form-root.json | 2 +- docs/data/api/menu-arrow.json | 2 +- .../api/menu-checkbox-item-indicator.json | 2 +- docs/data/api/menu-checkbox-item.json | 2 +- docs/data/api/menu-group-label.json | 2 +- docs/data/api/menu-group.json | 2 +- docs/data/api/menu-item.json | 2 +- docs/data/api/menu-popup.json | 2 +- docs/data/api/menu-positioner.json | 2 +- docs/data/api/menu-radio-group.json | 2 +- docs/data/api/menu-radio-item-indicator.json | 2 +- docs/data/api/menu-radio-item.json | 4 +- docs/data/api/menu-root.json | 2 +- docs/data/api/menu-separator.json | 4 +- docs/data/api/menu-trigger.json | 2 +- docs/data/api/number-field-decrement.json | 2 +- docs/data/api/number-field-group.json | 2 +- docs/data/api/number-field-increment.json | 2 +- docs/data/api/number-field-input.json | 2 +- docs/data/api/number-field-root.json | 2 +- .../api/number-field-scrub-area-cursor.json | 2 +- docs/data/api/number-field-scrub-area.json | 2 +- docs/data/api/popover-arrow.json | 2 +- docs/data/api/popover-backdrop.json | 2 +- docs/data/api/popover-close.json | 2 +- docs/data/api/popover-description.json | 2 +- docs/data/api/popover-popup.json | 2 +- docs/data/api/popover-positioner.json | 2 +- docs/data/api/popover-root.json | 2 +- docs/data/api/popover-title.json | 2 +- docs/data/api/popover-trigger.json | 2 +- docs/data/api/preview-card-arrow.json | 2 +- docs/data/api/preview-card-backdrop.json | 2 +- docs/data/api/preview-card-popup.json | 2 +- docs/data/api/preview-card-positioner.json | 2 +- docs/data/api/preview-card-root.json | 2 +- docs/data/api/preview-card-trigger.json | 2 +- docs/data/api/progress-indicator.json | 2 +- docs/data/api/progress-root.json | 2 +- docs/data/api/progress-track.json | 2 +- docs/data/api/radio-group-root.json | 2 +- docs/data/api/radio-indicator.json | 2 +- docs/data/api/radio-root.json | 2 +- docs/data/api/separator-root.json | 2 +- docs/data/api/slider-control.json | 2 +- docs/data/api/slider-indicator.json | 2 +- docs/data/api/slider-output.json | 2 +- docs/data/api/slider-root.json | 2 +- docs/data/api/slider-thumb.json | 4 +- docs/data/api/slider-track.json | 4 +- docs/data/api/switch-root.json | 2 +- docs/data/api/switch-thumb.json | 4 +- docs/data/api/tab-indicator.json | 2 +- docs/data/api/tab-panel.json | 2 +- docs/data/api/tab.json | 2 +- docs/data/api/tabs-list.json | 2 +- docs/data/api/tabs-root.json | 2 +- docs/data/api/tooltip-arrow.json | 2 +- docs/data/api/tooltip-popup.json | 2 +- docs/data/api/tooltip-positioner.json | 2 +- docs/data/api/tooltip-provider.json | 2 +- docs/data/api/tooltip-root.json | 2 +- docs/data/api/tooltip-trigger.json | 2 +- .../css-modules/index.js | 2 +- .../css-modules/index.tsx | 2 +- .../AlertDialogIntroduction/system/index.js | 2 +- .../AlertDialogIntroduction/system/index.tsx | 2 +- .../AlertDialogIntroduction/tailwind/index.js | 2 +- .../tailwind/index.tsx | 2 +- .../AlertDialogWithTransitions.js | 2 +- .../AlertDialogWithTransitions.tsx | 2 +- .../alert-dialog/NestedAlertDialogs.js | 2 +- .../alert-dialog/NestedAlertDialogs.tsx | 2 +- .../css/index.js | 6 +-- .../css/index.tsx | 6 +-- .../system/index.js | 6 +-- .../system/index.tsx | 6 +-- .../tailwind/index.js | 6 +-- .../tailwind/index.tsx | 6 +-- .../UnstyledCheckboxGroupNested.js | 6 +-- .../UnstyledCheckboxGroupNested.tsx | 6 +-- .../checkbox-group/checkbox-group.mdx | 2 +- .../checkbox/UnstyledCheckboxIndeterminate.js | 2 +- .../UnstyledCheckboxIndeterminate.tsx | 2 +- .../UnstyledCheckboxIndeterminateGroup.js | 2 +- .../UnstyledCheckboxIndeterminateGroup.tsx | 2 +- .../css-modules/index.js | 2 +- .../css-modules/index.tsx | 2 +- .../system/index.js | 2 +- .../system/index.tsx | 2 +- .../tailwind/index.js | 2 +- .../tailwind/index.tsx | 2 +- .../collapsible/CssAnimatedCollapsible.js | 2 +- .../collapsible/CssAnimatedCollapsible.tsx | 2 +- .../collapsible/CssTransitionCollapsible.js | 2 +- .../collapsible/CssTransitionCollapsible.tsx | 2 +- .../UnstyledCollapsibleIntroduction.js | 2 +- .../UnstyledCollapsibleIntroduction.tsx | 2 +- .../dialog/DialogWithTransitions.js | 2 +- .../dialog/DialogWithTransitions.tsx | 2 +- docs/data/components/dialog/NestedDialogs.js | 2 +- docs/data/components/dialog/NestedDialogs.tsx | 2 +- .../css-modules/index.js | 2 +- .../css-modules/index.tsx | 2 +- .../system/index.js | 2 +- .../system/index.tsx | 2 +- .../tailwind/index.js | 2 +- .../tailwind/index.tsx | 2 +- .../components/field/UnstyledFieldAsync.js | 2 +- .../components/field/UnstyledFieldAsync.tsx | 2 +- .../UnstyledFieldIntroduction/system/index.js | 2 +- .../system/index.tsx | 2 +- .../components/field/UnstyledFieldPassword.js | 2 +- .../field/UnstyledFieldPassword.tsx | 2 +- .../field/UnstyledFieldServerError.js | 2 +- .../field/UnstyledFieldServerError.tsx | 2 +- .../system/index.js | 4 +- .../system/index.tsx | 4 +- .../form/FormIntroduction/system/index.js | 6 +-- .../form/FormIntroduction/system/index.tsx | 6 +-- docs/data/components/form/form.mdx | 4 +- docs/data/components/menu/CheckboxItems.js | 2 +- docs/data/components/menu/CheckboxItems.tsx | 2 +- .../menu/MenuIntroduction/css-modules/Menu.js | 2 +- .../MenuIntroduction/css-modules/Menu.tsx | 2 +- .../menu/MenuIntroduction/system/index.js | 2 +- .../menu/MenuIntroduction/system/index.tsx | 2 +- .../menu/MenuIntroduction/tailwind/index.js | 2 +- .../menu/MenuIntroduction/tailwind/index.tsx | 2 +- docs/data/components/menu/NestedMenu.js | 2 +- docs/data/components/menu/NestedMenu.tsx | 2 +- docs/data/components/menu/RadioItems.js | 2 +- docs/data/components/menu/RadioItems.tsx | 2 +- .../number-field/UnstyledNumberFieldFormat.js | 2 +- .../UnstyledNumberFieldFormat.tsx | 2 +- .../css-modules/index.js | 2 +- .../css-modules/index.tsx | 2 +- .../system/index.js | 4 +- .../system/index.tsx | 4 +- .../tailwind/index.js | 2 +- .../tailwind/index.tsx | 2 +- .../number-field/UnstyledNumberFieldScrub.js | 2 +- .../number-field/UnstyledNumberFieldScrub.tsx | 2 +- .../UnstyledNumberFieldWheelScrub.js | 2 +- .../UnstyledNumberFieldWheelScrub.tsx | 2 +- .../system/index.js | 2 +- .../system/index.tsx | 2 +- .../popover/UnstyledPopoverTransition.js | 2 +- .../popover/UnstyledPopoverTransition.tsx | 2 +- .../system/index.js | 2 +- .../system/index.tsx | 2 +- .../UnstyledPreviewCardTransition.js | 2 +- .../UnstyledPreviewCardTransition.tsx | 2 +- .../progress/IndeterminateProgress.js | 2 +- .../progress/IndeterminateProgress.tsx | 2 +- docs/data/components/progress/RtlProgress.js | 2 +- docs/data/components/progress/RtlProgress.tsx | 2 +- .../css-modules/index.js | 2 +- .../css-modules/index.tsx | 2 +- .../system/index.js | 2 +- .../system/index.tsx | 2 +- .../tailwind/index.js | 2 +- .../tailwind/index.tsx | 2 +- .../system/index.js | 4 +- .../system/index.tsx | 4 +- .../separator/SeparatorIntroduction.js | 2 +- .../separator/SeparatorIntroduction.tsx | 2 +- docs/data/components/slider/RangeSlider.js | 2 +- docs/data/components/slider/RangeSlider.tsx | 2 +- docs/data/components/slider/RtlSlider.js | 2 +- docs/data/components/slider/RtlSlider.tsx | 2 +- .../css-modules/index.js | 2 +- .../css-modules/index.tsx | 2 +- .../system/index.js | 2 +- .../system/index.tsx | 2 +- .../tailwind/index.js | 2 +- .../tailwind/index.tsx | 2 +- docs/data/components/slider/VerticalSlider.js | 2 +- .../data/components/slider/VerticalSlider.tsx | 2 +- .../css-modules/index.js | 2 +- .../css-modules/index.tsx | 2 +- .../system/index.js | 2 +- .../system/index.tsx | 2 +- .../tailwind/index.js | 2 +- .../tailwind/index.tsx | 2 +- docs/data/components/tabs/IndicatorBubble.js | 2 +- docs/data/components/tabs/IndicatorBubble.tsx | 2 +- .../components/tabs/IndicatorUnderline.js | 2 +- .../components/tabs/IndicatorUnderline.tsx | 2 +- .../components/tabs/KeyboardNavigation.js | 2 +- .../components/tabs/KeyboardNavigation.tsx | 2 +- .../css-modules/index.js | 2 +- .../css-modules/index.tsx | 2 +- .../UnstyledTabsIntroduction/system/index.js | 2 +- .../UnstyledTabsIntroduction/system/index.tsx | 2 +- .../tailwind/index.js | 2 +- .../tailwind/index.tsx | 2 +- .../components/tabs/UnstyledTabsRouting.js | 2 +- .../components/tabs/UnstyledTabsRouting.tsx | 2 +- .../tooltip/UnstyledTooltipDelayGroup.js | 2 +- .../tooltip/UnstyledTooltipDelayGroup.tsx | 2 +- .../tooltip/UnstyledTooltipFollowCursor.js | 2 +- .../tooltip/UnstyledTooltipFollowCursor.tsx | 2 +- .../system/index.js | 2 +- .../system/index.tsx | 2 +- .../tooltip/UnstyledTooltipTransition.js | 2 +- .../tooltip/UnstyledTooltipTransition.tsx | 2 +- .../accessibility/FocusRing.js | 2 +- .../accessibility/FocusRing.tsx | 2 +- .../PackageManagerSnippetCode.tsx | 2 +- .../PackageManagerSnippetRoot.tsx | 2 +- docs/src/components/DocsVersionSelector.tsx | 2 +- .../content/InstallationInstructions.tsx | 2 +- docs/src/components/demo/Demo.tsx | 2 +- docs/src/components/demo/DemoFileSelector.tsx | 2 +- docs/src/design-system/Tooltip.tsx | 2 +- .../Backdrop/AlertDialogBackdrop.test.tsx | 2 +- .../Close/AlertDialogClose.test.tsx | 2 +- .../AlertDialogDescription.test.tsx | 2 +- .../Popup/AlertDialogPopup.test.tsx | 2 +- .../Title/AlertDialogTitle.test.tsx | 2 +- .../Trigger/AlertDialogTrigger.test.tsx | 2 +- .../mui-base/src/AlertDialog/index.barrel.ts | 7 --- .../mui-base/src/AlertDialog/index.parts.ts | 7 +++ packages/mui-base/src/AlertDialog/index.ts | 8 +-- .../Indicator/CheckboxIndicator.test.tsx | 2 +- .../src/Checkbox/Root/CheckboxRoot.test.tsx | 2 +- .../mui-base/src/Checkbox/index.barrel.ts | 2 - packages/mui-base/src/Checkbox/index.parts.ts | 2 + packages/mui-base/src/Checkbox/index.ts | 3 +- .../Parent/useCheckboxGroupParent.test.tsx | 4 +- .../Root/CheckboxGroupRoot.test.tsx | 4 +- .../src/CheckboxGroup/index.barrel.ts | 1 - .../mui-base/src/CheckboxGroup/index.parts.ts | 1 + packages/mui-base/src/CheckboxGroup/index.ts | 2 +- .../Content/CollapsibleContent.test.tsx | 4 +- .../Collapsible/Root/CollapsibleRoot.test.tsx | 2 +- .../Trigger/CollapsibleTrigger.test.tsx | 4 +- .../mui-base/src/Collapsible/index.parts.ts | 3 ++ packages/mui-base/src/Collapsible/index.ts | 10 +--- .../Dialog/Backdrop/DialogBackdrop.test.tsx | 2 +- .../src/Dialog/Close/DialogClose.test.tsx | 2 +- .../Description/DialogDescription.test.tsx | 2 +- .../src/Dialog/Popup/DialogPopup.test.tsx | 2 +- .../src/Dialog/Root/DialogRoot.test.tsx | 2 +- .../src/Dialog/Title/DialogTitle.test.tsx | 2 +- .../src/Dialog/Trigger/DialogTrigger.test.tsx | 2 +- packages/mui-base/src/Dialog/index.barrel.ts | 7 --- packages/mui-base/src/Dialog/index.parts.ts | 7 +++ packages/mui-base/src/Dialog/index.ts | 8 +-- .../src/Field/Control/FieldControl.test.tsx | 2 +- .../Description/FieldDescription.test.tsx | 14 +++--- .../src/Field/Error/FieldError.test.tsx | 2 +- .../src/Field/Label/FieldLabel.test.tsx | 14 +++--- .../src/Field/Root/FieldRoot.test.tsx | 14 +++--- .../src/Field/Validity/FieldValidity.test.tsx | 2 +- packages/mui-base/src/Field/index.barrel.ts | 8 --- packages/mui-base/src/Field/index.parts.ts | 8 +++ packages/mui-base/src/Field/index.ts | 9 +--- .../Fieldset/Legend/FieldsetLegend.test.tsx | 2 +- .../src/Fieldset/Root/FieldsetRoot.test.tsx | 2 +- .../mui-base/src/Fieldset/index.barrel.ts | 2 - packages/mui-base/src/Fieldset/index.parts.ts | 2 + packages/mui-base/src/Fieldset/index.ts | 3 +- .../mui-base/src/Form/Root/FormRoot.test.tsx | 4 +- packages/mui-base/src/Form/index.barrel.ts | 1 - packages/mui-base/src/Form/index.parts.ts | 1 + packages/mui-base/src/Form/index.ts | 2 +- .../src/Menu/Arrow/MenuArrow.test.tsx | 2 +- .../CheckboxItem/MenuCheckboxItem.test.tsx | 2 +- .../MenuCheckboxItemIndicator.test.tsx | 2 +- .../src/Menu/Group/MenuGroup.test.tsx | 2 +- .../Menu/GroupLabel/MenuGroupLabel.test.tsx | 2 +- .../mui-base/src/Menu/Item/MenuItem.test.tsx | 2 +- .../src/Menu/Popup/MenuPopup.test.tsx | 2 +- .../Menu/Positioner/MenuPositioner.test.tsx | 2 +- .../Menu/RadioGroup/MenuRadioGroup.test.tsx | 2 +- .../src/Menu/RadioItem/MenuRadioItem.test.tsx | 2 +- .../MenuRadioItemIndicator.test.tsx | 2 +- .../mui-base/src/Menu/Root/MenuRoot.test.tsx | 2 +- .../src/Menu/Trigger/MenuTrigger.test.tsx | 2 +- packages/mui-base/src/Menu/index.barrel.ts | 14 ------ packages/mui-base/src/Menu/index.parts.ts | 15 ++++++ packages/mui-base/src/Menu/index.ts | 16 +----- .../Decrement/NumberFieldDecrement.test.tsx | 2 +- .../Group/NumberFieldGroup.test.tsx | 2 +- .../Increment/NumberFieldIncrement.test.tsx | 2 +- .../Input/NumberFieldInput.test.tsx | 2 +- .../NumberField/Root/NumberFieldRoot.test.tsx | 2 +- .../ScrubArea/NumberFieldScrubArea.test.tsx | 2 +- .../NumberFieldScrubAreaCursor.test.tsx | 2 +- .../mui-base/src/NumberField/index.barrel.ts | 7 --- .../mui-base/src/NumberField/index.parts.ts | 7 +++ packages/mui-base/src/NumberField/index.ts | 8 +-- .../src/Popover/Arrow/PopoverArrow.test.tsx | 2 +- .../Popover/Backdrop/PopoverBackdrop.test.tsx | 2 +- .../src/Popover/Close/PopoverClose.test.tsx | 2 +- .../Description/PopoverDescription.test.tsx | 2 +- .../src/Popover/Popup/PopoverPopup.test.tsx | 2 +- .../Positioner/PopoverPositioner.test.tsx | 2 +- .../src/Popover/Root/PopoverRoot.test.tsx | 2 +- .../src/Popover/Title/PopoverTitle.test.tsx | 2 +- .../Popover/Trigger/PopoverTrigger.test.tsx | 2 +- packages/mui-base/src/Popover/index.barrel.ts | 9 ---- packages/mui-base/src/Popover/index.parts.ts | 9 ++++ packages/mui-base/src/Popover/index.ts | 10 +--- .../Arrow/PreviewCardArrow.test.tsx | 2 +- .../Backdrop/PreviewCardBackdrop.test.tsx | 2 +- .../Popup/PreviewCardPopup.test.tsx | 2 +- .../Positioner/PreviewCardPositioner.test.tsx | 2 +- .../PreviewCard/Root/PreviewCardRoot.test.tsx | 2 +- .../Trigger/PreviewCardTrigger.test.tsx | 2 +- .../mui-base/src/PreviewCard/index.barrel.ts | 6 --- .../mui-base/src/PreviewCard/index.parts.ts | 6 +++ packages/mui-base/src/PreviewCard/index.ts | 7 +-- .../Indicator/ProgressIndicator.test.tsx | 2 +- .../src/Progress/Root/ProgressRoot.test.tsx | 2 +- .../src/Progress/Track/ProgressTrack.test.tsx | 2 +- .../mui-base/src/Progress/index.barrel.ts | 8 --- packages/mui-base/src/Progress/index.parts.ts | 8 +++ packages/mui-base/src/Progress/index.ts | 9 +--- .../Radio/Indicator/RadioIndicator.test.tsx | 2 +- .../src/Radio/Root/RadioRoot.test.tsx | 2 +- packages/mui-base/src/Radio/index.barrel.ts | 2 - packages/mui-base/src/Radio/index.parts.ts | 2 + packages/mui-base/src/Radio/index.ts | 3 +- .../RadioGroup/Root/RadioGroupRoot.test.tsx | 4 +- .../mui-base/src/RadioGroup/index.barrel.ts | 1 - .../mui-base/src/RadioGroup/index.parts.ts | 1 + packages/mui-base/src/RadioGroup/index.ts | 2 +- .../src/Separator/Root/SeparatorRoot.test.tsx | 2 +- .../mui-base/src/Separator/index.barrel.ts | 1 - .../mui-base/src/Separator/index.parts.ts | 1 + packages/mui-base/src/Separator/index.ts | 2 +- .../src/Slider/Control/SliderControl.test.tsx | 4 +- .../Slider/Indicator/SliderIndicator.test.tsx | 4 +- .../src/Slider/Output/SliderOutput.test.tsx | 4 +- .../src/Slider/Root/SliderRoot.test.tsx | 2 +- .../src/Slider/Thumb/SliderThumb.test.tsx | 4 +- .../src/Slider/Track/SliderTrack.test.tsx | 4 +- .../{index.barrel.ts => index.parts.ts} | 29 +++++++---- packages/mui-base/src/Slider/index.ts | 50 +------------------ .../src/Switch/Root/SwitchRoot.test.tsx | 2 +- .../src/Switch/Thumb/SwitchThumb.test.tsx | 2 +- packages/mui-base/src/Switch/index.barrel.ts | 2 - packages/mui-base/src/Switch/index.parts.ts | 2 + packages/mui-base/src/Switch/index.ts | 3 +- .../mui-base/src/Tabs/Root/TabsRoot.test.tsx | 2 +- packages/mui-base/src/Tabs/Tab/Tab.test.tsx | 2 +- .../mui-base/src/Tabs/Tab/useTab.test.tsx | 2 +- .../Tabs/TabIndicator/TabIndicator.test.tsx | 2 +- .../src/Tabs/TabPanel/TabPanel.test.tsx | 2 +- .../src/Tabs/TabPanel/useTabPanel.test.tsx | 2 +- .../src/Tabs/TabsList/TabsList.test.tsx | 2 +- .../src/Tabs/TabsList/useTabsList.test.tsx | 2 +- packages/mui-base/src/Tabs/index.barrel.ts | 5 -- packages/mui-base/src/Tabs/index.parts.ts | 5 ++ packages/mui-base/src/Tabs/index.ts | 6 +-- .../src/Tooltip/Arrow/TooltipArrow.test.tsx | 2 +- .../src/Tooltip/Popup/TooltipPopup.test.tsx | 2 +- .../Positioner/TooltipPositioner.test.tsx | 2 +- .../Tooltip/Provider/TooltipProvider.test.tsx | 2 +- .../src/Tooltip/Root/TooltipRoot.test.tsx | 2 +- .../Tooltip/Trigger/TooltipTrigger.test.tsx | 2 +- packages/mui-base/src/Tooltip/index.barrel.ts | 6 --- packages/mui-base/src/Tooltip/index.parts.ts | 6 +++ packages/mui-base/src/Tooltip/index.ts | 7 +-- packages/mui-base/src/index.ts | 34 +++++++------ .../config/getComponentImports.ts | 4 +- 413 files changed, 565 insertions(+), 696 deletions(-) delete mode 100644 packages/mui-base/src/AlertDialog/index.barrel.ts create mode 100644 packages/mui-base/src/AlertDialog/index.parts.ts delete mode 100644 packages/mui-base/src/Checkbox/index.barrel.ts create mode 100644 packages/mui-base/src/Checkbox/index.parts.ts delete mode 100644 packages/mui-base/src/CheckboxGroup/index.barrel.ts create mode 100644 packages/mui-base/src/CheckboxGroup/index.parts.ts create mode 100644 packages/mui-base/src/Collapsible/index.parts.ts delete mode 100644 packages/mui-base/src/Dialog/index.barrel.ts create mode 100644 packages/mui-base/src/Dialog/index.parts.ts delete mode 100644 packages/mui-base/src/Field/index.barrel.ts create mode 100644 packages/mui-base/src/Field/index.parts.ts delete mode 100644 packages/mui-base/src/Fieldset/index.barrel.ts create mode 100644 packages/mui-base/src/Fieldset/index.parts.ts delete mode 100644 packages/mui-base/src/Form/index.barrel.ts create mode 100644 packages/mui-base/src/Form/index.parts.ts delete mode 100644 packages/mui-base/src/Menu/index.barrel.ts create mode 100644 packages/mui-base/src/Menu/index.parts.ts delete mode 100644 packages/mui-base/src/NumberField/index.barrel.ts create mode 100644 packages/mui-base/src/NumberField/index.parts.ts delete mode 100644 packages/mui-base/src/Popover/index.barrel.ts create mode 100644 packages/mui-base/src/Popover/index.parts.ts delete mode 100644 packages/mui-base/src/PreviewCard/index.barrel.ts create mode 100644 packages/mui-base/src/PreviewCard/index.parts.ts delete mode 100644 packages/mui-base/src/Progress/index.barrel.ts create mode 100644 packages/mui-base/src/Progress/index.parts.ts delete mode 100644 packages/mui-base/src/Radio/index.barrel.ts create mode 100644 packages/mui-base/src/Radio/index.parts.ts delete mode 100644 packages/mui-base/src/RadioGroup/index.barrel.ts create mode 100644 packages/mui-base/src/RadioGroup/index.parts.ts delete mode 100644 packages/mui-base/src/Separator/index.barrel.ts create mode 100644 packages/mui-base/src/Separator/index.parts.ts rename packages/mui-base/src/Slider/{index.barrel.ts => index.parts.ts} (53%) delete mode 100644 packages/mui-base/src/Switch/index.barrel.ts create mode 100644 packages/mui-base/src/Switch/index.parts.ts delete mode 100644 packages/mui-base/src/Tabs/index.barrel.ts create mode 100644 packages/mui-base/src/Tabs/index.parts.ts delete mode 100644 packages/mui-base/src/Tooltip/index.barrel.ts create mode 100644 packages/mui-base/src/Tooltip/index.parts.ts diff --git a/docs/app/DocsProviders.tsx b/docs/app/DocsProviders.tsx index 7caa4a4ef..39b504c7c 100644 --- a/docs/app/DocsProviders.tsx +++ b/docs/app/DocsProviders.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import * as Tooltip from '@base_ui/react/Tooltip'; +import { Tooltip } from '@base_ui/react/Tooltip'; import { DemoVariantSelectorProvider } from 'docs-base/src/components/demo/DemoVariantSelectorProvider'; import { PackageManagerSnippetProvider } from 'docs-base/src/blocks/PackageManagerSnippet/PackageManagerSnippetProvider'; diff --git a/docs/app/experiments/collapsible-accordion.tsx b/docs/app/experiments/collapsible-accordion.tsx index fa14e5ac6..65e531eb0 100644 --- a/docs/app/experiments/collapsible-accordion.tsx +++ b/docs/app/experiments/collapsible-accordion.tsx @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as Collapsible from '@base_ui/react/Collapsible'; +import { Collapsible } from '@base_ui/react/Collapsible'; const TRANSITION_DURATION = '350ms'; diff --git a/docs/app/experiments/collapsible-framer.tsx b/docs/app/experiments/collapsible-framer.tsx index 47c0301d4..62bf360ee 100644 --- a/docs/app/experiments/collapsible-framer.tsx +++ b/docs/app/experiments/collapsible-framer.tsx @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; import { useTheme } from '@mui/system'; -import * as Collapsible from '@base_ui/react/Collapsible'; +import { Collapsible } from '@base_ui/react/Collapsible'; import { motion } from 'framer-motion'; export default function CollapsibleFramer() { diff --git a/docs/app/experiments/collapsible-hidden-until-found.tsx b/docs/app/experiments/collapsible-hidden-until-found.tsx index 3b926caae..befbb2b0b 100644 --- a/docs/app/experiments/collapsible-hidden-until-found.tsx +++ b/docs/app/experiments/collapsible-hidden-until-found.tsx @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as Collapsible from '@base_ui/react/Collapsible'; +import { Collapsible } from '@base_ui/react/Collapsible'; const DURATION = '350ms'; diff --git a/docs/app/experiments/collapsible.tsx b/docs/app/experiments/collapsible.tsx index 55d3477a4..a1e2429a6 100644 --- a/docs/app/experiments/collapsible.tsx +++ b/docs/app/experiments/collapsible.tsx @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as Collapsible from '@base_ui/react/Collapsible'; +import { Collapsible } from '@base_ui/react/Collapsible'; const DURATION = '350ms'; diff --git a/docs/app/experiments/dialog.tsx b/docs/app/experiments/dialog.tsx index c1dd9fe76..9d72f1bf8 100644 --- a/docs/app/experiments/dialog.tsx +++ b/docs/app/experiments/dialog.tsx @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; import clsx from 'clsx'; -import * as Dialog from '@base_ui/react/Dialog'; +import { Dialog } from '@base_ui/react/Dialog'; // eslint-disable-next-line no-restricted-imports import { useTransitionStatus } from '@base_ui/react/utils/useTransitionStatus'; import { animated as springAnimated, useSpring, useSpringRef } from '@react-spring/web'; diff --git a/docs/app/experiments/menu-anchor-el.tsx b/docs/app/experiments/menu-anchor-el.tsx index 883bd9a72..bad4bdc47 100644 --- a/docs/app/experiments/menu-anchor-el.tsx +++ b/docs/app/experiments/menu-anchor-el.tsx @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; -import * as Menu from '@base_ui/react/Menu'; +import { Menu } from '@base_ui/react/Menu'; export default function Page() { const [anchorEl, setAnchor] = React.useState(null); diff --git a/docs/app/experiments/menu-anchor-ref.tsx b/docs/app/experiments/menu-anchor-ref.tsx index e375b201d..68d67f7e8 100644 --- a/docs/app/experiments/menu-anchor-ref.tsx +++ b/docs/app/experiments/menu-anchor-ref.tsx @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; -import * as Menu from '@base_ui/react/Menu'; +import { Menu } from '@base_ui/react/Menu'; export default function Page() { const anchor = React.useRef(null); diff --git a/docs/app/experiments/progress.tsx b/docs/app/experiments/progress.tsx index 1db6f0dc5..230fb3e45 100644 --- a/docs/app/experiments/progress.tsx +++ b/docs/app/experiments/progress.tsx @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; import { useTheme } from '@mui/system'; -import * as Progress from '@base_ui/react/Progress'; +import { Progress } from '@base_ui/react/Progress'; const VAL1 = 33; diff --git a/docs/app/experiments/slider-change-committed-lag.tsx b/docs/app/experiments/slider-change-committed-lag.tsx index 8ced35a40..673b39ad7 100644 --- a/docs/app/experiments/slider-change-committed-lag.tsx +++ b/docs/app/experiments/slider-change-committed-lag.tsx @@ -2,7 +2,7 @@ // https://github.com/mui/material-ui/issues/41739 // to cross check whether this issue would still occur in the new API import * as React from 'react'; -import * as Slider from '@base_ui/react/Slider'; +import { Slider } from '@base_ui/react/Slider'; import { Styles } from './slider'; export default function App() { diff --git a/docs/app/experiments/slider-marks.tsx b/docs/app/experiments/slider-marks.tsx index 2026be9b0..04194347c 100644 --- a/docs/app/experiments/slider-marks.tsx +++ b/docs/app/experiments/slider-marks.tsx @@ -1,7 +1,6 @@ 'use client'; import * as React from 'react'; -import * as Slider from '@base_ui/react/Slider'; -import { useSliderContext } from '@base_ui/react/Slider'; +import { Slider } from '@base_ui/react/Slider'; const STOPS = [ { @@ -33,7 +32,7 @@ function getSliderThumbAriaValueText(value: number) { // for "inverted track", the track/rail can be styled with CSS but a prop is needed to flip the "mark active" state function MarkWithLabel(props: { index: number; value: number; label: string; inverted?: boolean }) { const { index, value, label, inverted = false } = props; - const { direction, values } = useSliderContext(); + const { direction, values } = Slider.useSliderContext(); const isRtl = direction === 'rtl'; const isFilled = inverted ? value >= values[0] : values[0] >= value; return ( diff --git a/docs/app/experiments/slider-template.tsx b/docs/app/experiments/slider-template.tsx index 33bee84cf..7472d3a32 100644 --- a/docs/app/experiments/slider-template.tsx +++ b/docs/app/experiments/slider-template.tsx @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as Slider from '@base_ui/react/Slider'; +import { Slider } from '@base_ui/react/Slider'; import { Styles } from './slider'; export default function App() { diff --git a/docs/app/experiments/slider-tooltip.tsx b/docs/app/experiments/slider-tooltip.tsx index d221b5c63..2d8b14085 100644 --- a/docs/app/experiments/slider-tooltip.tsx +++ b/docs/app/experiments/slider-tooltip.tsx @@ -1,8 +1,8 @@ 'use client'; import * as React from 'react'; import { useTheme } from '@mui/system'; -import * as Slider from '@base_ui/react/Slider'; -import * as Tooltip from '@base_ui/react/Tooltip'; +import { Slider } from '@base_ui/react/Slider'; +import { Tooltip } from '@base_ui/react/Tooltip'; function useIsDarkMode() { const theme = useTheme(); diff --git a/docs/app/experiments/slider.tsx b/docs/app/experiments/slider.tsx index 449930434..3e8d29dc8 100644 --- a/docs/app/experiments/slider.tsx +++ b/docs/app/experiments/slider.tsx @@ -1,8 +1,7 @@ 'use client'; import * as React from 'react'; import { useTheme } from '@mui/system'; -import * as Slider from '@base_ui/react/Slider'; -import { useSliderContext } from '@base_ui/react/Slider'; +import { Slider } from '@base_ui/react/Slider'; export default function App() { const [val1, setVal1] = React.useState(50); @@ -233,7 +232,7 @@ function Label(props: any) { const defaultId = React.useId(); const labelId = idProp ?? defaultId; - const { subitems } = useSliderContext(); + const { subitems } = Slider.useSliderContext(); const htmlFor = Array.from(subitems.values()) .reduce((acc, item) => { diff --git a/docs/app/experiments/tabs.tsx b/docs/app/experiments/tabs.tsx index c78781513..36c8271b5 100644 --- a/docs/app/experiments/tabs.tsx +++ b/docs/app/experiments/tabs.tsx @@ -2,7 +2,7 @@ /* eslint-disable react/no-danger */ import * as React from 'react'; import { css, styled } from '@mui/system'; -import * as BaseTabs from '@base_ui/react/Tabs'; +import { Tabs as BaseTabs } from '@base_ui/react/Tabs'; export default function UnstyledTabsIntroduction() { const [v, sv] = React.useState(0); diff --git a/docs/app/experiments/tooltip.tsx b/docs/app/experiments/tooltip.tsx index 7a6cf11d4..40f010864 100644 --- a/docs/app/experiments/tooltip.tsx +++ b/docs/app/experiments/tooltip.tsx @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as Tooltip from '@base_ui/react/Tooltip'; +import { Tooltip } from '@base_ui/react/Tooltip'; import { styled, keyframes } from '@mui/system'; import { motion, AnimatePresence } from 'framer-motion'; diff --git a/docs/data/api/alert-dialog-backdrop.json b/docs/data/api/alert-dialog-backdrop.json index e4c113258..4a4cadeae 100644 --- a/docs/data/api/alert-dialog-backdrop.json +++ b/docs/data/api/alert-dialog-backdrop.json @@ -6,7 +6,7 @@ }, "name": "AlertDialogBackdrop", "imports": [ - "import * as AlertDialog from '@base_ui/react/AlertDialog';\nconst AlertDialogBackdrop = AlertDialog.Backdrop;" + "import { AlertDialog } from '@base_ui/react/AlertDialog';\nconst AlertDialogBackdrop = AlertDialog.Backdrop;" ], "classes": [], "spread": true, diff --git a/docs/data/api/alert-dialog-close.json b/docs/data/api/alert-dialog-close.json index ed0de8e5c..04e289d03 100644 --- a/docs/data/api/alert-dialog-close.json +++ b/docs/data/api/alert-dialog-close.json @@ -5,7 +5,7 @@ }, "name": "AlertDialogClose", "imports": [ - "import * as AlertDialog from '@base_ui/react/AlertDialog';\nconst AlertDialogClose = AlertDialog.Close;" + "import { AlertDialog } from '@base_ui/react/AlertDialog';\nconst AlertDialogClose = AlertDialog.Close;" ], "classes": [], "spread": true, diff --git a/docs/data/api/alert-dialog-description.json b/docs/data/api/alert-dialog-description.json index 4004c33a3..ac3110306 100644 --- a/docs/data/api/alert-dialog-description.json +++ b/docs/data/api/alert-dialog-description.json @@ -5,7 +5,7 @@ }, "name": "AlertDialogDescription", "imports": [ - "import * as AlertDialog from '@base_ui/react/AlertDialog';\nconst AlertDialogDescription = AlertDialog.Description;" + "import { AlertDialog } from '@base_ui/react/AlertDialog';\nconst AlertDialogDescription = AlertDialog.Description;" ], "classes": [], "spread": true, diff --git a/docs/data/api/alert-dialog-popup.json b/docs/data/api/alert-dialog-popup.json index 4e0642280..902e31c78 100644 --- a/docs/data/api/alert-dialog-popup.json +++ b/docs/data/api/alert-dialog-popup.json @@ -7,7 +7,7 @@ }, "name": "AlertDialogPopup", "imports": [ - "import * as AlertDialog from '@base_ui/react/AlertDialog';\nconst AlertDialogPopup = AlertDialog.Popup;" + "import { AlertDialog } from '@base_ui/react/AlertDialog';\nconst AlertDialogPopup = AlertDialog.Popup;" ], "classes": [], "spread": true, diff --git a/docs/data/api/alert-dialog-root.json b/docs/data/api/alert-dialog-root.json index dddc81760..8e3b7c663 100644 --- a/docs/data/api/alert-dialog-root.json +++ b/docs/data/api/alert-dialog-root.json @@ -7,7 +7,7 @@ }, "name": "AlertDialogRoot", "imports": [ - "import * as AlertDialog from '@base_ui/react/AlertDialog';\nconst AlertDialogRoot = AlertDialog.Root;" + "import { AlertDialog } from '@base_ui/react/AlertDialog';\nconst AlertDialogRoot = AlertDialog.Root;" ], "classes": [], "spread": true, diff --git a/docs/data/api/alert-dialog-title.json b/docs/data/api/alert-dialog-title.json index 7d11d2f33..7ad51049e 100644 --- a/docs/data/api/alert-dialog-title.json +++ b/docs/data/api/alert-dialog-title.json @@ -5,7 +5,7 @@ }, "name": "AlertDialogTitle", "imports": [ - "import * as AlertDialog from '@base_ui/react/AlertDialog';\nconst AlertDialogTitle = AlertDialog.Title;" + "import { AlertDialog } from '@base_ui/react/AlertDialog';\nconst AlertDialogTitle = AlertDialog.Title;" ], "classes": [], "spread": true, diff --git a/docs/data/api/alert-dialog-trigger.json b/docs/data/api/alert-dialog-trigger.json index e78589333..9e32aadba 100644 --- a/docs/data/api/alert-dialog-trigger.json +++ b/docs/data/api/alert-dialog-trigger.json @@ -5,7 +5,7 @@ }, "name": "AlertDialogTrigger", "imports": [ - "import * as AlertDialog from '@base_ui/react/AlertDialog';\nconst AlertDialogTrigger = AlertDialog.Trigger;" + "import { AlertDialog } from '@base_ui/react/AlertDialog';\nconst AlertDialogTrigger = AlertDialog.Trigger;" ], "classes": [], "spread": true, diff --git a/docs/data/api/checkbox-group-root.json b/docs/data/api/checkbox-group-root.json index d7a9319d0..b030723dc 100644 --- a/docs/data/api/checkbox-group-root.json +++ b/docs/data/api/checkbox-group-root.json @@ -11,7 +11,7 @@ }, "name": "CheckboxGroupRoot", "imports": [ - "import * as CheckboxGroup from '@base_ui/react/CheckboxGroup';\nconst CheckboxGroupRoot = CheckboxGroup.Root;" + "import { CheckboxGroup } from '@base_ui/react/CheckboxGroup';\nconst CheckboxGroupRoot = CheckboxGroup.Root;" ], "classes": [], "spread": true, diff --git a/docs/data/api/checkbox-indicator.json b/docs/data/api/checkbox-indicator.json index 14420a5b9..042044e63 100644 --- a/docs/data/api/checkbox-indicator.json +++ b/docs/data/api/checkbox-indicator.json @@ -6,7 +6,7 @@ }, "name": "CheckboxIndicator", "imports": [ - "import * as Checkbox from '@base_ui/react/Checkbox';\nconst CheckboxIndicator = Checkbox.Indicator;" + "import { Checkbox } from '@base_ui/react/Checkbox';\nconst CheckboxIndicator = Checkbox.Indicator;" ], "classes": [], "spread": true, diff --git a/docs/data/api/checkbox-root.json b/docs/data/api/checkbox-root.json index 7e2138278..a9dff6d98 100644 --- a/docs/data/api/checkbox-root.json +++ b/docs/data/api/checkbox-root.json @@ -23,7 +23,7 @@ }, "name": "CheckboxRoot", "imports": [ - "import * as Checkbox from '@base_ui/react/Checkbox';\nconst CheckboxRoot = Checkbox.Root;" + "import { Checkbox } from '@base_ui/react/Checkbox';\nconst CheckboxRoot = Checkbox.Root;" ], "classes": [], "spread": true, diff --git a/docs/data/api/collapsible-content.json b/docs/data/api/collapsible-content.json index b9d48da67..424829be7 100644 --- a/docs/data/api/collapsible-content.json +++ b/docs/data/api/collapsible-content.json @@ -6,7 +6,7 @@ }, "name": "CollapsibleContent", "imports": [ - "import * as Collapsible from '@base_ui/react/Collapsible';\nconst CollapsibleContent = Collapsible.Content;" + "import { Collapsible } from '@base_ui/react/Collapsible';\nconst CollapsibleContent = Collapsible.Content;" ], "classes": [], "spread": true, diff --git a/docs/data/api/collapsible-root.json b/docs/data/api/collapsible-root.json index 4e1abe2c4..911399fe4 100644 --- a/docs/data/api/collapsible-root.json +++ b/docs/data/api/collapsible-root.json @@ -10,7 +10,7 @@ }, "name": "CollapsibleRoot", "imports": [ - "import * as Collapsible from '@base_ui/react/Collapsible';\nconst CollapsibleRoot = Collapsible.Root;" + "import { Collapsible } from '@base_ui/react/Collapsible';\nconst CollapsibleRoot = Collapsible.Root;" ], "classes": [], "spread": true, diff --git a/docs/data/api/collapsible-trigger.json b/docs/data/api/collapsible-trigger.json index 0aa32c8e7..784494b73 100644 --- a/docs/data/api/collapsible-trigger.json +++ b/docs/data/api/collapsible-trigger.json @@ -5,7 +5,7 @@ }, "name": "CollapsibleTrigger", "imports": [ - "import * as Collapsible from '@base_ui/react/Collapsible';\nconst CollapsibleTrigger = Collapsible.Trigger;" + "import { Collapsible } from '@base_ui/react/Collapsible';\nconst CollapsibleTrigger = Collapsible.Trigger;" ], "classes": [], "spread": true, diff --git a/docs/data/api/dialog-backdrop.json b/docs/data/api/dialog-backdrop.json index 041757b2b..9a48a406a 100644 --- a/docs/data/api/dialog-backdrop.json +++ b/docs/data/api/dialog-backdrop.json @@ -6,7 +6,7 @@ }, "name": "DialogBackdrop", "imports": [ - "import * as Dialog from '@base_ui/react/Dialog';\nconst DialogBackdrop = Dialog.Backdrop;" + "import { Dialog } from '@base_ui/react/Dialog';\nconst DialogBackdrop = Dialog.Backdrop;" ], "classes": [], "spread": true, diff --git a/docs/data/api/dialog-close.json b/docs/data/api/dialog-close.json index f3c98f9ce..1229ef445 100644 --- a/docs/data/api/dialog-close.json +++ b/docs/data/api/dialog-close.json @@ -4,9 +4,7 @@ "render": { "type": { "name": "union", "description": "element
| func" } } }, "name": "DialogClose", - "imports": [ - "import * as Dialog from '@base_ui/react/Dialog';\nconst DialogClose = Dialog.Close;" - ], + "imports": ["import { Dialog } from '@base_ui/react/Dialog';\nconst DialogClose = Dialog.Close;"], "classes": [], "spread": true, "themeDefaultProps": true, diff --git a/docs/data/api/dialog-description.json b/docs/data/api/dialog-description.json index 8733b10c7..8d2a1cf80 100644 --- a/docs/data/api/dialog-description.json +++ b/docs/data/api/dialog-description.json @@ -5,7 +5,7 @@ }, "name": "DialogDescription", "imports": [ - "import * as Dialog from '@base_ui/react/Dialog';\nconst DialogDescription = Dialog.Description;" + "import { Dialog } from '@base_ui/react/Dialog';\nconst DialogDescription = Dialog.Description;" ], "classes": [], "spread": true, diff --git a/docs/data/api/dialog-popup.json b/docs/data/api/dialog-popup.json index 3072b9ff3..4bb1be663 100644 --- a/docs/data/api/dialog-popup.json +++ b/docs/data/api/dialog-popup.json @@ -6,9 +6,7 @@ "render": { "type": { "name": "union", "description": "element
| func" } } }, "name": "DialogPopup", - "imports": [ - "import * as Dialog from '@base_ui/react/Dialog';\nconst DialogPopup = Dialog.Popup;" - ], + "imports": ["import { Dialog } from '@base_ui/react/Dialog';\nconst DialogPopup = Dialog.Popup;"], "classes": [], "spread": true, "themeDefaultProps": true, diff --git a/docs/data/api/dialog-root.json b/docs/data/api/dialog-root.json index 20a26cb4f..3e8b87e70 100644 --- a/docs/data/api/dialog-root.json +++ b/docs/data/api/dialog-root.json @@ -8,7 +8,7 @@ "open": { "type": { "name": "bool" } } }, "name": "DialogRoot", - "imports": ["import * as Dialog from '@base_ui/react/Dialog';\nconst DialogRoot = Dialog.Root;"], + "imports": ["import { Dialog } from '@base_ui/react/Dialog';\nconst DialogRoot = Dialog.Root;"], "classes": [], "spread": true, "themeDefaultProps": null, diff --git a/docs/data/api/dialog-title.json b/docs/data/api/dialog-title.json index 5a9cfb7e4..a05f6bd49 100644 --- a/docs/data/api/dialog-title.json +++ b/docs/data/api/dialog-title.json @@ -4,9 +4,7 @@ "render": { "type": { "name": "union", "description": "element
| func" } } }, "name": "DialogTitle", - "imports": [ - "import * as Dialog from '@base_ui/react/Dialog';\nconst DialogTitle = Dialog.Title;" - ], + "imports": ["import { Dialog } from '@base_ui/react/Dialog';\nconst DialogTitle = Dialog.Title;"], "classes": [], "spread": true, "themeDefaultProps": true, diff --git a/docs/data/api/dialog-trigger.json b/docs/data/api/dialog-trigger.json index 08ba0d1ed..10f8f5139 100644 --- a/docs/data/api/dialog-trigger.json +++ b/docs/data/api/dialog-trigger.json @@ -5,7 +5,7 @@ }, "name": "DialogTrigger", "imports": [ - "import * as Dialog from '@base_ui/react/Dialog';\nconst DialogTrigger = Dialog.Trigger;" + "import { Dialog } from '@base_ui/react/Dialog';\nconst DialogTrigger = Dialog.Trigger;" ], "classes": [], "spread": true, diff --git a/docs/data/api/field-control.json b/docs/data/api/field-control.json index 7932e11fc..fe0b98ff5 100644 --- a/docs/data/api/field-control.json +++ b/docs/data/api/field-control.json @@ -5,9 +5,7 @@ "render": { "type": { "name": "union", "description": "element
| func" } } }, "name": "FieldControl", - "imports": [ - "import * as Field from '@base_ui/react/Field';\nconst FieldControl = Field.Control;" - ], + "imports": ["import { Field } from '@base_ui/react/Field';\nconst FieldControl = Field.Control;"], "classes": [], "spread": true, "themeDefaultProps": true, diff --git a/docs/data/api/field-description.json b/docs/data/api/field-description.json index 4654b11ac..88400bc52 100644 --- a/docs/data/api/field-description.json +++ b/docs/data/api/field-description.json @@ -5,7 +5,7 @@ }, "name": "FieldDescription", "imports": [ - "import * as Field from '@base_ui/react/Field';\nconst FieldDescription = Field.Description;" + "import { Field } from '@base_ui/react/Field';\nconst FieldDescription = Field.Description;" ], "classes": [], "spread": true, diff --git a/docs/data/api/field-error.json b/docs/data/api/field-error.json index b52587e68..b80033d4b 100644 --- a/docs/data/api/field-error.json +++ b/docs/data/api/field-error.json @@ -11,7 +11,7 @@ "render": { "type": { "name": "union", "description": "element
| func" } } }, "name": "FieldError", - "imports": ["import * as Field from '@base_ui/react/Field';\nconst FieldError = Field.Error;"], + "imports": ["import { Field } from '@base_ui/react/Field';\nconst FieldError = Field.Error;"], "classes": [], "spread": true, "themeDefaultProps": true, diff --git a/docs/data/api/field-label.json b/docs/data/api/field-label.json index feebb4e27..87db1074c 100644 --- a/docs/data/api/field-label.json +++ b/docs/data/api/field-label.json @@ -4,7 +4,7 @@ "render": { "type": { "name": "union", "description": "element
| func" } } }, "name": "FieldLabel", - "imports": ["import * as Field from '@base_ui/react/Field';\nconst FieldLabel = Field.Label;"], + "imports": ["import { Field } from '@base_ui/react/Field';\nconst FieldLabel = Field.Label;"], "classes": [], "spread": true, "themeDefaultProps": true, diff --git a/docs/data/api/field-root.json b/docs/data/api/field-root.json index 946b4cc5b..a9cdf945a 100644 --- a/docs/data/api/field-root.json +++ b/docs/data/api/field-root.json @@ -13,7 +13,7 @@ } }, "name": "FieldRoot", - "imports": ["import * as Field from '@base_ui/react/Field';\nconst FieldRoot = Field.Root;"], + "imports": ["import { Field } from '@base_ui/react/Field';\nconst FieldRoot = Field.Root;"], "classes": [], "spread": true, "themeDefaultProps": true, diff --git a/docs/data/api/field-validity.json b/docs/data/api/field-validity.json index 39bbdadb2..3e7b3c8d9 100644 --- a/docs/data/api/field-validity.json +++ b/docs/data/api/field-validity.json @@ -2,7 +2,7 @@ "props": {}, "name": "FieldValidity", "imports": [ - "import * as Field from '@base_ui/react/Field';\nconst FieldValidity = Field.Validity;" + "import { Field } from '@base_ui/react/Field';\nconst FieldValidity = Field.Validity;" ], "classes": [], "spread": true, diff --git a/docs/data/api/fieldset-legend.json b/docs/data/api/fieldset-legend.json index 08643190f..abebed30d 100644 --- a/docs/data/api/fieldset-legend.json +++ b/docs/data/api/fieldset-legend.json @@ -5,7 +5,7 @@ }, "name": "FieldsetLegend", "imports": [ - "import * as Fieldset from '@base_ui/react/Fieldset';\nconst FieldsetLegend = Fieldset.Legend;" + "import { Fieldset } from '@base_ui/react/Fieldset';\nconst FieldsetLegend = Fieldset.Legend;" ], "classes": [], "spread": true, diff --git a/docs/data/api/fieldset-root.json b/docs/data/api/fieldset-root.json index cd34d7cfc..7434ad43b 100644 --- a/docs/data/api/fieldset-root.json +++ b/docs/data/api/fieldset-root.json @@ -5,7 +5,7 @@ }, "name": "FieldsetRoot", "imports": [ - "import * as Fieldset from '@base_ui/react/Fieldset';\nconst FieldsetRoot = Fieldset.Root;" + "import { Fieldset } from '@base_ui/react/Fieldset';\nconst FieldsetRoot = Fieldset.Root;" ], "classes": [], "spread": true, diff --git a/docs/data/api/form-root.json b/docs/data/api/form-root.json index a7517e42e..afcada879 100644 --- a/docs/data/api/form-root.json +++ b/docs/data/api/form-root.json @@ -6,7 +6,7 @@ "render": { "type": { "name": "union", "description": "element
| func" } } }, "name": "FormRoot", - "imports": ["import * as Form from '@base_ui/react/Form';\nconst FormRoot = Form.Root;"], + "imports": ["import { Form } from '@base_ui/react/Form';\nconst FormRoot = Form.Root;"], "classes": [], "spread": true, "themeDefaultProps": true, diff --git a/docs/data/api/menu-arrow.json b/docs/data/api/menu-arrow.json index 026e242c1..39bf1b773 100644 --- a/docs/data/api/menu-arrow.json +++ b/docs/data/api/menu-arrow.json @@ -5,7 +5,7 @@ "render": { "type": { "name": "union", "description": "element
| func" } } }, "name": "MenuArrow", - "imports": ["import * as Menu from '@base_ui/react/Menu';\nconst MenuArrow = Menu.Arrow;"], + "imports": ["import { Menu } from '@base_ui/react/Menu';\nconst MenuArrow = Menu.Arrow;"], "classes": [], "spread": true, "themeDefaultProps": true, diff --git a/docs/data/api/menu-checkbox-item-indicator.json b/docs/data/api/menu-checkbox-item-indicator.json index aaf1adec7..ae9716f80 100644 --- a/docs/data/api/menu-checkbox-item-indicator.json +++ b/docs/data/api/menu-checkbox-item-indicator.json @@ -6,7 +6,7 @@ }, "name": "MenuCheckboxItemIndicator", "imports": [ - "import * as Menu from '@base_ui/react/Menu';\nconst MenuCheckboxItemIndicator = Menu.CheckboxItemIndicator;" + "import { Menu } from '@base_ui/react/Menu';\nconst MenuCheckboxItemIndicator = Menu.CheckboxItemIndicator;" ], "classes": [], "spread": true, diff --git a/docs/data/api/menu-checkbox-item.json b/docs/data/api/menu-checkbox-item.json index c622f6901..71f0dc291 100644 --- a/docs/data/api/menu-checkbox-item.json +++ b/docs/data/api/menu-checkbox-item.json @@ -8,7 +8,7 @@ }, "name": "MenuCheckboxItem", "imports": [ - "import * as Menu from '@base_ui/react/Menu';\nconst MenuCheckboxItem = Menu.CheckboxItem;" + "import { Menu } from '@base_ui/react/Menu';\nconst MenuCheckboxItem = Menu.CheckboxItem;" ], "classes": [], "spread": true, diff --git a/docs/data/api/menu-group-label.json b/docs/data/api/menu-group-label.json index f25161ff1..31f344174 100644 --- a/docs/data/api/menu-group-label.json +++ b/docs/data/api/menu-group-label.json @@ -5,7 +5,7 @@ }, "name": "MenuGroupLabel", "imports": [ - "import * as Menu from '@base_ui/react/Menu';\nconst MenuGroupLabel = Menu.GroupLabel;" + "import { Menu } from '@base_ui/react/Menu';\nconst MenuGroupLabel = Menu.GroupLabel;" ], "classes": [], "spread": true, diff --git a/docs/data/api/menu-group.json b/docs/data/api/menu-group.json index 5ef36cb04..a0c0074ed 100644 --- a/docs/data/api/menu-group.json +++ b/docs/data/api/menu-group.json @@ -5,7 +5,7 @@ "render": { "type": { "name": "union", "description": "element
| func" } } }, "name": "MenuGroup", - "imports": ["import * as Menu from '@base_ui/react/Menu';\nconst MenuGroup = Menu.Group;"], + "imports": ["import { Menu } from '@base_ui/react/Menu';\nconst MenuGroup = Menu.Group;"], "classes": [], "spread": true, "themeDefaultProps": true, diff --git a/docs/data/api/menu-item.json b/docs/data/api/menu-item.json index 639cb2516..de2ce393b 100644 --- a/docs/data/api/menu-item.json +++ b/docs/data/api/menu-item.json @@ -7,7 +7,7 @@ "onClick": { "type": { "name": "func" } } }, "name": "MenuItem", - "imports": ["import * as Menu from '@base_ui/react/Menu';\nconst MenuItem = Menu.Item;"], + "imports": ["import { Menu } from '@base_ui/react/Menu';\nconst MenuItem = Menu.Item;"], "classes": [], "spread": true, "themeDefaultProps": true, diff --git a/docs/data/api/menu-popup.json b/docs/data/api/menu-popup.json index 49cc98f61..ad8b18e3b 100644 --- a/docs/data/api/menu-popup.json +++ b/docs/data/api/menu-popup.json @@ -5,7 +5,7 @@ "render": { "type": { "name": "union", "description": "element
| func" } } }, "name": "MenuPopup", - "imports": ["import * as Menu from '@base_ui/react/Menu';\nconst MenuPopup = Menu.Popup;"], + "imports": ["import { Menu } from '@base_ui/react/Menu';\nconst MenuPopup = Menu.Popup;"], "classes": [], "spread": true, "themeDefaultProps": true, diff --git a/docs/data/api/menu-positioner.json b/docs/data/api/menu-positioner.json index 6356647f8..c92652b6f 100644 --- a/docs/data/api/menu-positioner.json +++ b/docs/data/api/menu-positioner.json @@ -50,7 +50,7 @@ }, "name": "MenuPositioner", "imports": [ - "import * as Menu from '@base_ui/react/Menu';\nconst MenuPositioner = Menu.Positioner;" + "import { Menu } from '@base_ui/react/Menu';\nconst MenuPositioner = Menu.Positioner;" ], "classes": [], "spread": true, diff --git a/docs/data/api/menu-radio-group.json b/docs/data/api/menu-radio-group.json index 7c93dbc87..5e70dafa4 100644 --- a/docs/data/api/menu-radio-group.json +++ b/docs/data/api/menu-radio-group.json @@ -9,7 +9,7 @@ }, "name": "MenuRadioGroup", "imports": [ - "import * as Menu from '@base_ui/react/Menu';\nconst MenuRadioGroup = Menu.RadioGroup;" + "import { Menu } from '@base_ui/react/Menu';\nconst MenuRadioGroup = Menu.RadioGroup;" ], "classes": [], "spread": true, diff --git a/docs/data/api/menu-radio-item-indicator.json b/docs/data/api/menu-radio-item-indicator.json index 9cd21ccb5..eb88d1bfd 100644 --- a/docs/data/api/menu-radio-item-indicator.json +++ b/docs/data/api/menu-radio-item-indicator.json @@ -6,7 +6,7 @@ }, "name": "MenuRadioItemIndicator", "imports": [ - "import * as Menu from '@base_ui/react/Menu';\nconst MenuRadioItemIndicator = Menu.RadioItemIndicator;" + "import { Menu } from '@base_ui/react/Menu';\nconst MenuRadioItemIndicator = Menu.RadioItemIndicator;" ], "classes": [], "spread": true, diff --git a/docs/data/api/menu-radio-item.json b/docs/data/api/menu-radio-item.json index fc3ac0f34..04a1482ed 100644 --- a/docs/data/api/menu-radio-item.json +++ b/docs/data/api/menu-radio-item.json @@ -8,9 +8,7 @@ "onClick": { "type": { "name": "func" } } }, "name": "MenuRadioItem", - "imports": [ - "import * as Menu from '@base_ui/react/Menu';\nconst MenuRadioItem = Menu.RadioItem;" - ], + "imports": ["import { Menu } from '@base_ui/react/Menu';\nconst MenuRadioItem = Menu.RadioItem;"], "classes": [], "spread": true, "themeDefaultProps": true, diff --git a/docs/data/api/menu-root.json b/docs/data/api/menu-root.json index d79474fbb..216ed4544 100644 --- a/docs/data/api/menu-root.json +++ b/docs/data/api/menu-root.json @@ -19,7 +19,7 @@ } }, "name": "MenuRoot", - "imports": ["import * as Menu from '@base_ui/react/Menu';\nconst MenuRoot = Menu.Root;"], + "imports": ["import { Menu } from '@base_ui/react/Menu';\nconst MenuRoot = Menu.Root;"], "classes": [], "spread": true, "themeDefaultProps": null, diff --git a/docs/data/api/menu-separator.json b/docs/data/api/menu-separator.json index b61e1d141..afb282bf2 100644 --- a/docs/data/api/menu-separator.json +++ b/docs/data/api/menu-separator.json @@ -5,9 +5,7 @@ "render": { "type": { "name": "union", "description": "element
| func" } } }, "name": "MenuSeparator", - "imports": [ - "import * as Menu from '@base_ui/react/Menu';\nconst MenuSeparator = Menu.Separator;" - ], + "imports": ["import { Menu } from '@base_ui/react/Menu';\nconst MenuSeparator = Menu.Separator;"], "classes": [], "spread": true, "themeDefaultProps": true, diff --git a/docs/data/api/menu-trigger.json b/docs/data/api/menu-trigger.json index 05e73a2a8..f8f82aa2e 100644 --- a/docs/data/api/menu-trigger.json +++ b/docs/data/api/menu-trigger.json @@ -7,7 +7,7 @@ "render": { "type": { "name": "union", "description": "element
| func" } } }, "name": "MenuTrigger", - "imports": ["import * as Menu from '@base_ui/react/Menu';\nconst MenuTrigger = Menu.Trigger;"], + "imports": ["import { Menu } from '@base_ui/react/Menu';\nconst MenuTrigger = Menu.Trigger;"], "classes": [], "spread": true, "themeDefaultProps": true, diff --git a/docs/data/api/number-field-decrement.json b/docs/data/api/number-field-decrement.json index cd1e3cea3..4a622144a 100644 --- a/docs/data/api/number-field-decrement.json +++ b/docs/data/api/number-field-decrement.json @@ -5,7 +5,7 @@ }, "name": "NumberFieldDecrement", "imports": [ - "import * as NumberField from '@base_ui/react/NumberField';\nconst NumberFieldDecrement = NumberField.Decrement;" + "import { NumberField } from '@base_ui/react/NumberField';\nconst NumberFieldDecrement = NumberField.Decrement;" ], "classes": [], "spread": true, diff --git a/docs/data/api/number-field-group.json b/docs/data/api/number-field-group.json index fc0aa6baf..c5538cf2a 100644 --- a/docs/data/api/number-field-group.json +++ b/docs/data/api/number-field-group.json @@ -5,7 +5,7 @@ }, "name": "NumberFieldGroup", "imports": [ - "import * as NumberField from '@base_ui/react/NumberField';\nconst NumberFieldGroup = NumberField.Group;" + "import { NumberField } from '@base_ui/react/NumberField';\nconst NumberFieldGroup = NumberField.Group;" ], "classes": [], "spread": true, diff --git a/docs/data/api/number-field-increment.json b/docs/data/api/number-field-increment.json index ccf741cae..b895d9a1e 100644 --- a/docs/data/api/number-field-increment.json +++ b/docs/data/api/number-field-increment.json @@ -5,7 +5,7 @@ }, "name": "NumberFieldIncrement", "imports": [ - "import * as NumberField from '@base_ui/react/NumberField';\nconst NumberFieldIncrement = NumberField.Increment;" + "import { NumberField } from '@base_ui/react/NumberField';\nconst NumberFieldIncrement = NumberField.Increment;" ], "classes": [], "spread": true, diff --git a/docs/data/api/number-field-input.json b/docs/data/api/number-field-input.json index e2252d771..5131ab443 100644 --- a/docs/data/api/number-field-input.json +++ b/docs/data/api/number-field-input.json @@ -5,7 +5,7 @@ }, "name": "NumberFieldInput", "imports": [ - "import * as NumberField from '@base_ui/react/NumberField';\nconst NumberFieldInput = NumberField.Input;" + "import { NumberField } from '@base_ui/react/NumberField';\nconst NumberFieldInput = NumberField.Input;" ], "classes": [], "spread": true, diff --git a/docs/data/api/number-field-root.json b/docs/data/api/number-field-root.json index 5b3e34aca..eb1020629 100644 --- a/docs/data/api/number-field-root.json +++ b/docs/data/api/number-field-root.json @@ -33,7 +33,7 @@ }, "name": "NumberFieldRoot", "imports": [ - "import * as NumberField from '@base_ui/react/NumberField';\nconst NumberFieldRoot = NumberField.Root;" + "import { NumberField } from '@base_ui/react/NumberField';\nconst NumberFieldRoot = NumberField.Root;" ], "classes": [], "spread": true, diff --git a/docs/data/api/number-field-scrub-area-cursor.json b/docs/data/api/number-field-scrub-area-cursor.json index 095efebcb..006077f92 100644 --- a/docs/data/api/number-field-scrub-area-cursor.json +++ b/docs/data/api/number-field-scrub-area-cursor.json @@ -5,7 +5,7 @@ }, "name": "NumberFieldScrubAreaCursor", "imports": [ - "import * as NumberField from '@base_ui/react/NumberField';\nconst NumberFieldScrubAreaCursor = NumberField.ScrubAreaCursor;" + "import { NumberField } from '@base_ui/react/NumberField';\nconst NumberFieldScrubAreaCursor = NumberField.ScrubAreaCursor;" ], "classes": [], "spread": true, diff --git a/docs/data/api/number-field-scrub-area.json b/docs/data/api/number-field-scrub-area.json index f4c83c108..e328020db 100644 --- a/docs/data/api/number-field-scrub-area.json +++ b/docs/data/api/number-field-scrub-area.json @@ -11,7 +11,7 @@ }, "name": "NumberFieldScrubArea", "imports": [ - "import * as NumberField from '@base_ui/react/NumberField';\nconst NumberFieldScrubArea = NumberField.ScrubArea;" + "import { NumberField } from '@base_ui/react/NumberField';\nconst NumberFieldScrubArea = NumberField.ScrubArea;" ], "classes": [], "spread": true, diff --git a/docs/data/api/popover-arrow.json b/docs/data/api/popover-arrow.json index 278c8cfd6..3e9eb76f2 100644 --- a/docs/data/api/popover-arrow.json +++ b/docs/data/api/popover-arrow.json @@ -6,7 +6,7 @@ }, "name": "PopoverArrow", "imports": [ - "import * as Popover from '@base_ui/react/Popover';\nconst PopoverArrow = Popover.Arrow;" + "import { Popover } from '@base_ui/react/Popover';\nconst PopoverArrow = Popover.Arrow;" ], "classes": [], "spread": true, diff --git a/docs/data/api/popover-backdrop.json b/docs/data/api/popover-backdrop.json index c2c9ea760..62b24c08c 100644 --- a/docs/data/api/popover-backdrop.json +++ b/docs/data/api/popover-backdrop.json @@ -10,7 +10,7 @@ }, "name": "PopoverBackdrop", "imports": [ - "import * as Popover from '@base_ui/react/Popover';\nconst PopoverBackdrop = Popover.Backdrop;" + "import { Popover } from '@base_ui/react/Popover';\nconst PopoverBackdrop = Popover.Backdrop;" ], "classes": [], "spread": true, diff --git a/docs/data/api/popover-close.json b/docs/data/api/popover-close.json index 31957848c..cc6e27f18 100644 --- a/docs/data/api/popover-close.json +++ b/docs/data/api/popover-close.json @@ -5,7 +5,7 @@ }, "name": "PopoverClose", "imports": [ - "import * as Popover from '@base_ui/react/Popover';\nconst PopoverClose = Popover.Close;" + "import { Popover } from '@base_ui/react/Popover';\nconst PopoverClose = Popover.Close;" ], "classes": [], "spread": true, diff --git a/docs/data/api/popover-description.json b/docs/data/api/popover-description.json index b3eeb77f9..6fdaf51d5 100644 --- a/docs/data/api/popover-description.json +++ b/docs/data/api/popover-description.json @@ -5,7 +5,7 @@ }, "name": "PopoverDescription", "imports": [ - "import * as Popover from '@base_ui/react/Popover';\nconst PopoverDescription = Popover.Description;" + "import { Popover } from '@base_ui/react/Popover';\nconst PopoverDescription = Popover.Description;" ], "classes": [], "spread": true, diff --git a/docs/data/api/popover-popup.json b/docs/data/api/popover-popup.json index 06a36805b..7a5894df8 100644 --- a/docs/data/api/popover-popup.json +++ b/docs/data/api/popover-popup.json @@ -5,7 +5,7 @@ }, "name": "PopoverPopup", "imports": [ - "import * as Popover from '@base_ui/react/Popover';\nconst PopoverPopup = Popover.Popup;" + "import { Popover } from '@base_ui/react/Popover';\nconst PopoverPopup = Popover.Popup;" ], "classes": [], "spread": true, diff --git a/docs/data/api/popover-positioner.json b/docs/data/api/popover-positioner.json index adc543325..dc1d42a20 100644 --- a/docs/data/api/popover-positioner.json +++ b/docs/data/api/popover-positioner.json @@ -50,7 +50,7 @@ }, "name": "PopoverPositioner", "imports": [ - "import * as Popover from '@base_ui/react/Popover';\nconst PopoverPositioner = Popover.Positioner;" + "import { Popover } from '@base_ui/react/Popover';\nconst PopoverPositioner = Popover.Positioner;" ], "classes": [], "spread": true, diff --git a/docs/data/api/popover-root.json b/docs/data/api/popover-root.json index 29da12e96..a18b9808e 100644 --- a/docs/data/api/popover-root.json +++ b/docs/data/api/popover-root.json @@ -14,7 +14,7 @@ }, "name": "PopoverRoot", "imports": [ - "import * as Popover from '@base_ui/react/Popover';\nconst PopoverRoot = Popover.Root;" + "import { Popover } from '@base_ui/react/Popover';\nconst PopoverRoot = Popover.Root;" ], "classes": [], "spread": true, diff --git a/docs/data/api/popover-title.json b/docs/data/api/popover-title.json index 239fcf291..b4661b4fa 100644 --- a/docs/data/api/popover-title.json +++ b/docs/data/api/popover-title.json @@ -5,7 +5,7 @@ }, "name": "PopoverTitle", "imports": [ - "import * as Popover from '@base_ui/react/Popover';\nconst PopoverTitle = Popover.Title;" + "import { Popover } from '@base_ui/react/Popover';\nconst PopoverTitle = Popover.Title;" ], "classes": [], "spread": true, diff --git a/docs/data/api/popover-trigger.json b/docs/data/api/popover-trigger.json index cd6204789..b4b5fb84c 100644 --- a/docs/data/api/popover-trigger.json +++ b/docs/data/api/popover-trigger.json @@ -5,7 +5,7 @@ }, "name": "PopoverTrigger", "imports": [ - "import * as Popover from '@base_ui/react/Popover';\nconst PopoverTrigger = Popover.Trigger;" + "import { Popover } from '@base_ui/react/Popover';\nconst PopoverTrigger = Popover.Trigger;" ], "classes": [], "spread": true, diff --git a/docs/data/api/preview-card-arrow.json b/docs/data/api/preview-card-arrow.json index a37473e60..bd8d29a51 100644 --- a/docs/data/api/preview-card-arrow.json +++ b/docs/data/api/preview-card-arrow.json @@ -6,7 +6,7 @@ }, "name": "PreviewCardArrow", "imports": [ - "import * as PreviewCard from '@base_ui/react/PreviewCard';\nconst PreviewCardArrow = PreviewCard.Arrow;" + "import { PreviewCard } from '@base_ui/react/PreviewCard';\nconst PreviewCardArrow = PreviewCard.Arrow;" ], "classes": [], "spread": true, diff --git a/docs/data/api/preview-card-backdrop.json b/docs/data/api/preview-card-backdrop.json index ef40f420f..131edeaef 100644 --- a/docs/data/api/preview-card-backdrop.json +++ b/docs/data/api/preview-card-backdrop.json @@ -7,7 +7,7 @@ }, "name": "PreviewCardBackdrop", "imports": [ - "import * as PreviewCard from '@base_ui/react/PreviewCard';\nconst PreviewCardBackdrop = PreviewCard.Backdrop;" + "import { PreviewCard } from '@base_ui/react/PreviewCard';\nconst PreviewCardBackdrop = PreviewCard.Backdrop;" ], "classes": [], "spread": true, diff --git a/docs/data/api/preview-card-popup.json b/docs/data/api/preview-card-popup.json index 3d1b7e10a..18778886b 100644 --- a/docs/data/api/preview-card-popup.json +++ b/docs/data/api/preview-card-popup.json @@ -5,7 +5,7 @@ }, "name": "PreviewCardPopup", "imports": [ - "import * as PreviewCard from '@base_ui/react/PreviewCard';\nconst PreviewCardPopup = PreviewCard.Popup;" + "import { PreviewCard } from '@base_ui/react/PreviewCard';\nconst PreviewCardPopup = PreviewCard.Popup;" ], "classes": [], "spread": true, diff --git a/docs/data/api/preview-card-positioner.json b/docs/data/api/preview-card-positioner.json index ae28e1f9c..bf14a1c1e 100644 --- a/docs/data/api/preview-card-positioner.json +++ b/docs/data/api/preview-card-positioner.json @@ -50,7 +50,7 @@ }, "name": "PreviewCardPositioner", "imports": [ - "import * as PreviewCard from '@base_ui/react/PreviewCard';\nconst PreviewCardPositioner = PreviewCard.Positioner;" + "import { PreviewCard } from '@base_ui/react/PreviewCard';\nconst PreviewCardPositioner = PreviewCard.Positioner;" ], "classes": [], "spread": true, diff --git a/docs/data/api/preview-card-root.json b/docs/data/api/preview-card-root.json index 02a5916f0..df36fdd35 100644 --- a/docs/data/api/preview-card-root.json +++ b/docs/data/api/preview-card-root.json @@ -13,7 +13,7 @@ }, "name": "PreviewCardRoot", "imports": [ - "import * as PreviewCard from '@base_ui/react/PreviewCard';\nconst PreviewCardRoot = PreviewCard.Root;" + "import { PreviewCard } from '@base_ui/react/PreviewCard';\nconst PreviewCardRoot = PreviewCard.Root;" ], "classes": [], "spread": true, diff --git a/docs/data/api/preview-card-trigger.json b/docs/data/api/preview-card-trigger.json index 4fa0b2fa9..c6052f1b7 100644 --- a/docs/data/api/preview-card-trigger.json +++ b/docs/data/api/preview-card-trigger.json @@ -5,7 +5,7 @@ }, "name": "PreviewCardTrigger", "imports": [ - "import * as PreviewCard from '@base_ui/react/PreviewCard';\nconst PreviewCardTrigger = PreviewCard.Trigger;" + "import { PreviewCard } from '@base_ui/react/PreviewCard';\nconst PreviewCardTrigger = PreviewCard.Trigger;" ], "classes": [], "spread": true, diff --git a/docs/data/api/progress-indicator.json b/docs/data/api/progress-indicator.json index 533523f18..8e5bbc7cd 100644 --- a/docs/data/api/progress-indicator.json +++ b/docs/data/api/progress-indicator.json @@ -5,7 +5,7 @@ }, "name": "ProgressIndicator", "imports": [ - "import * as Progress from '@base_ui/react/Progress';\nconst ProgressIndicator = Progress.Indicator;" + "import { Progress } from '@base_ui/react/Progress';\nconst ProgressIndicator = Progress.Indicator;" ], "classes": [], "spread": true, diff --git a/docs/data/api/progress-root.json b/docs/data/api/progress-root.json index 125c799f7..f1bac0dae 100644 --- a/docs/data/api/progress-root.json +++ b/docs/data/api/progress-root.json @@ -29,7 +29,7 @@ }, "name": "ProgressRoot", "imports": [ - "import * as Progress from '@base_ui/react/Progress';\nconst ProgressRoot = Progress.Root;" + "import { Progress } from '@base_ui/react/Progress';\nconst ProgressRoot = Progress.Root;" ], "classes": [], "spread": true, diff --git a/docs/data/api/progress-track.json b/docs/data/api/progress-track.json index 22ed96222..fb0b9370b 100644 --- a/docs/data/api/progress-track.json +++ b/docs/data/api/progress-track.json @@ -5,7 +5,7 @@ }, "name": "ProgressTrack", "imports": [ - "import * as Progress from '@base_ui/react/Progress';\nconst ProgressTrack = Progress.Track;" + "import { Progress } from '@base_ui/react/Progress';\nconst ProgressTrack = Progress.Track;" ], "classes": [], "spread": true, diff --git a/docs/data/api/radio-group-root.json b/docs/data/api/radio-group-root.json index c18ad3f6c..064787ec8 100644 --- a/docs/data/api/radio-group-root.json +++ b/docs/data/api/radio-group-root.json @@ -12,7 +12,7 @@ }, "name": "RadioGroupRoot", "imports": [ - "import * as RadioGroup from '@base_ui/react/RadioGroup';\nconst RadioGroupRoot = RadioGroup.Root;" + "import { RadioGroup } from '@base_ui/react/RadioGroup';\nconst RadioGroupRoot = RadioGroup.Root;" ], "classes": [], "spread": true, diff --git a/docs/data/api/radio-indicator.json b/docs/data/api/radio-indicator.json index 871ffdf1e..2ddde1f26 100644 --- a/docs/data/api/radio-indicator.json +++ b/docs/data/api/radio-indicator.json @@ -6,7 +6,7 @@ }, "name": "RadioIndicator", "imports": [ - "import * as Radio from '@base_ui/react/Radio';\nconst RadioIndicator = Radio.Indicator;" + "import { Radio } from '@base_ui/react/Radio';\nconst RadioIndicator = Radio.Indicator;" ], "classes": [], "spread": true, diff --git a/docs/data/api/radio-root.json b/docs/data/api/radio-root.json index 277bbc807..342dc2694 100644 --- a/docs/data/api/radio-root.json +++ b/docs/data/api/radio-root.json @@ -8,7 +8,7 @@ "required": { "type": { "name": "bool" }, "default": "false" } }, "name": "RadioRoot", - "imports": ["import * as Radio from '@base_ui/react/Radio';\nconst RadioRoot = Radio.Root;"], + "imports": ["import { Radio } from '@base_ui/react/Radio';\nconst RadioRoot = Radio.Root;"], "classes": [], "spread": true, "themeDefaultProps": true, diff --git a/docs/data/api/separator-root.json b/docs/data/api/separator-root.json index 3ecf0bed9..ec0c91e37 100644 --- a/docs/data/api/separator-root.json +++ b/docs/data/api/separator-root.json @@ -5,7 +5,7 @@ }, "name": "SeparatorRoot", "imports": [ - "import * as Separator from '@base_ui/react/Separator';\nconst SeparatorRoot = Separator.Root;" + "import { Separator } from '@base_ui/react/Separator';\nconst SeparatorRoot = Separator.Root;" ], "classes": [], "spread": true, diff --git a/docs/data/api/slider-control.json b/docs/data/api/slider-control.json index a5a029fd2..d48aef56c 100644 --- a/docs/data/api/slider-control.json +++ b/docs/data/api/slider-control.json @@ -5,7 +5,7 @@ }, "name": "SliderControl", "imports": [ - "import * as Slider from '@base_ui/react/Slider';\nconst SliderControl = Slider.Control;" + "import { Slider } from '@base_ui/react/Slider';\nconst SliderControl = Slider.Control;" ], "classes": [], "spread": true, diff --git a/docs/data/api/slider-indicator.json b/docs/data/api/slider-indicator.json index f56dec033..f84c3ee22 100644 --- a/docs/data/api/slider-indicator.json +++ b/docs/data/api/slider-indicator.json @@ -5,7 +5,7 @@ }, "name": "SliderIndicator", "imports": [ - "import * as Slider from '@base_ui/react/Slider';\nconst SliderIndicator = Slider.Indicator;" + "import { Slider } from '@base_ui/react/Slider';\nconst SliderIndicator = Slider.Indicator;" ], "classes": [], "spread": true, diff --git a/docs/data/api/slider-output.json b/docs/data/api/slider-output.json index 674878e39..63690fe61 100644 --- a/docs/data/api/slider-output.json +++ b/docs/data/api/slider-output.json @@ -5,7 +5,7 @@ }, "name": "SliderOutput", "imports": [ - "import * as Slider from '@base_ui/react/Slider';\nconst SliderOutput = Slider.Output;" + "import { Slider } from '@base_ui/react/Slider';\nconst SliderOutput = Slider.Output;" ], "classes": [], "spread": true, diff --git a/docs/data/api/slider-root.json b/docs/data/api/slider-root.json index 6c83045dc..9bf64ced0 100644 --- a/docs/data/api/slider-root.json +++ b/docs/data/api/slider-root.json @@ -42,7 +42,7 @@ } }, "name": "SliderRoot", - "imports": ["import * as Slider from '@base_ui/react/Slider';\nconst SliderRoot = Slider.Root;"], + "imports": ["import { Slider } from '@base_ui/react/Slider';\nconst SliderRoot = Slider.Root;"], "classes": [], "spread": true, "themeDefaultProps": true, diff --git a/docs/data/api/slider-thumb.json b/docs/data/api/slider-thumb.json index 17027ffd0..c0af6817d 100644 --- a/docs/data/api/slider-thumb.json +++ b/docs/data/api/slider-thumb.json @@ -17,9 +17,7 @@ "render": { "type": { "name": "union", "description": "func
| node" } } }, "name": "SliderThumb", - "imports": [ - "import * as Slider from '@base_ui/react/Slider';\nconst SliderThumb = Slider.Thumb;" - ], + "imports": ["import { Slider } from '@base_ui/react/Slider';\nconst SliderThumb = Slider.Thumb;"], "classes": [], "spread": true, "themeDefaultProps": true, diff --git a/docs/data/api/slider-track.json b/docs/data/api/slider-track.json index e226d779a..eb2d84441 100644 --- a/docs/data/api/slider-track.json +++ b/docs/data/api/slider-track.json @@ -4,9 +4,7 @@ "render": { "type": { "name": "union", "description": "element
| func" } } }, "name": "SliderTrack", - "imports": [ - "import * as Slider from '@base_ui/react/Slider';\nconst SliderTrack = Slider.Track;" - ], + "imports": ["import { Slider } from '@base_ui/react/Slider';\nconst SliderTrack = Slider.Track;"], "classes": [], "spread": true, "themeDefaultProps": true, diff --git a/docs/data/api/switch-root.json b/docs/data/api/switch-root.json index ab1c15cd3..125ef0411 100644 --- a/docs/data/api/switch-root.json +++ b/docs/data/api/switch-root.json @@ -18,7 +18,7 @@ "required": { "type": { "name": "bool" }, "default": "false" } }, "name": "SwitchRoot", - "imports": ["import * as Switch from '@base_ui/react/Switch';\nconst SwitchRoot = Switch.Root;"], + "imports": ["import { Switch } from '@base_ui/react/Switch';\nconst SwitchRoot = Switch.Root;"], "classes": [], "spread": true, "themeDefaultProps": true, diff --git a/docs/data/api/switch-thumb.json b/docs/data/api/switch-thumb.json index 7da6d60ff..a64466e39 100644 --- a/docs/data/api/switch-thumb.json +++ b/docs/data/api/switch-thumb.json @@ -4,9 +4,7 @@ "render": { "type": { "name": "union", "description": "element
| func" } } }, "name": "SwitchThumb", - "imports": [ - "import * as Switch from '@base_ui/react/Switch';\nconst SwitchThumb = Switch.Thumb;" - ], + "imports": ["import { Switch } from '@base_ui/react/Switch';\nconst SwitchThumb = Switch.Thumb;"], "classes": [], "spread": true, "themeDefaultProps": true, diff --git a/docs/data/api/tab-indicator.json b/docs/data/api/tab-indicator.json index e6661a774..54f4e04e1 100644 --- a/docs/data/api/tab-indicator.json +++ b/docs/data/api/tab-indicator.json @@ -5,7 +5,7 @@ "renderBeforeHydration": { "type": { "name": "bool" }, "default": "false" } }, "name": "TabIndicator", - "imports": ["import * as Tabs from '@base_ui/react/Tabs';\nconst TabIndicator = Tabs.Indicator;"], + "imports": ["import { Tabs } from '@base_ui/react/Tabs';\nconst TabIndicator = Tabs.Indicator;"], "classes": [], "spread": true, "themeDefaultProps": true, diff --git a/docs/data/api/tab-panel.json b/docs/data/api/tab-panel.json index dc09c16d6..6221e09bd 100644 --- a/docs/data/api/tab-panel.json +++ b/docs/data/api/tab-panel.json @@ -6,7 +6,7 @@ "value": { "type": { "name": "any" } } }, "name": "TabPanel", - "imports": ["import * as Tabs from '@base_ui/react/Tabs';\nconst TabPanel = Tabs.Panel;"], + "imports": ["import { Tabs } from '@base_ui/react/Tabs';\nconst TabPanel = Tabs.Panel;"], "classes": [], "spread": true, "themeDefaultProps": true, diff --git a/docs/data/api/tab.json b/docs/data/api/tab.json index 02c7d764c..9fbe333f5 100644 --- a/docs/data/api/tab.json +++ b/docs/data/api/tab.json @@ -5,7 +5,7 @@ "value": { "type": { "name": "any" } } }, "name": "Tab", - "imports": ["import * as Tabs from '@base_ui/react/Tabs';\nconst Tab = Tabs.Tab;"], + "imports": ["import { Tabs } from '@base_ui/react/Tabs';\nconst Tab = Tabs.Tab;"], "classes": [], "spread": true, "themeDefaultProps": true, diff --git a/docs/data/api/tabs-list.json b/docs/data/api/tabs-list.json index c6f0fd0e7..c9d641eae 100644 --- a/docs/data/api/tabs-list.json +++ b/docs/data/api/tabs-list.json @@ -6,7 +6,7 @@ "render": { "type": { "name": "union", "description": "element
| func" } } }, "name": "TabsList", - "imports": ["import * as Tabs from '@base_ui/react/Tabs';\nconst TabsList = Tabs.List;"], + "imports": ["import { Tabs } from '@base_ui/react/Tabs';\nconst TabsList = Tabs.List;"], "classes": [], "spread": true, "themeDefaultProps": true, diff --git a/docs/data/api/tabs-root.json b/docs/data/api/tabs-root.json index 1560c4cc2..4be24aeb8 100644 --- a/docs/data/api/tabs-root.json +++ b/docs/data/api/tabs-root.json @@ -15,7 +15,7 @@ "value": { "type": { "name": "any" } } }, "name": "TabsRoot", - "imports": ["import * as Tabs from '@base_ui/react/Tabs';\nconst TabsRoot = Tabs.Root;"], + "imports": ["import { Tabs } from '@base_ui/react/Tabs';\nconst TabsRoot = Tabs.Root;"], "classes": [], "spread": true, "themeDefaultProps": true, diff --git a/docs/data/api/tooltip-arrow.json b/docs/data/api/tooltip-arrow.json index b0c2e7756..25368d286 100644 --- a/docs/data/api/tooltip-arrow.json +++ b/docs/data/api/tooltip-arrow.json @@ -6,7 +6,7 @@ }, "name": "TooltipArrow", "imports": [ - "import * as Tooltip from '@base_ui/react/Tooltip';\nconst TooltipArrow = Tooltip.Arrow;" + "import { Tooltip } from '@base_ui/react/Tooltip';\nconst TooltipArrow = Tooltip.Arrow;" ], "classes": [], "spread": true, diff --git a/docs/data/api/tooltip-popup.json b/docs/data/api/tooltip-popup.json index d9fb393ef..7cba917a8 100644 --- a/docs/data/api/tooltip-popup.json +++ b/docs/data/api/tooltip-popup.json @@ -5,7 +5,7 @@ }, "name": "TooltipPopup", "imports": [ - "import * as Tooltip from '@base_ui/react/Tooltip';\nconst TooltipPopup = Tooltip.Popup;" + "import { Tooltip } from '@base_ui/react/Tooltip';\nconst TooltipPopup = Tooltip.Popup;" ], "classes": [], "spread": true, diff --git a/docs/data/api/tooltip-positioner.json b/docs/data/api/tooltip-positioner.json index 3d29c4807..23ca83cce 100644 --- a/docs/data/api/tooltip-positioner.json +++ b/docs/data/api/tooltip-positioner.json @@ -50,7 +50,7 @@ }, "name": "TooltipPositioner", "imports": [ - "import * as Tooltip from '@base_ui/react/Tooltip';\nconst TooltipPositioner = Tooltip.Positioner;" + "import { Tooltip } from '@base_ui/react/Tooltip';\nconst TooltipPositioner = Tooltip.Positioner;" ], "classes": [], "spread": true, diff --git a/docs/data/api/tooltip-provider.json b/docs/data/api/tooltip-provider.json index aecb4bf44..3454a0ef2 100644 --- a/docs/data/api/tooltip-provider.json +++ b/docs/data/api/tooltip-provider.json @@ -6,7 +6,7 @@ }, "name": "TooltipProvider", "imports": [ - "import * as Tooltip from '@base_ui/react/Tooltip';\nconst TooltipProvider = Tooltip.Provider;" + "import { Tooltip } from '@base_ui/react/Tooltip';\nconst TooltipProvider = Tooltip.Provider;" ], "classes": [], "spread": true, diff --git a/docs/data/api/tooltip-root.json b/docs/data/api/tooltip-root.json index 268cce71d..fb548b9ca 100644 --- a/docs/data/api/tooltip-root.json +++ b/docs/data/api/tooltip-root.json @@ -21,7 +21,7 @@ }, "name": "TooltipRoot", "imports": [ - "import * as Tooltip from '@base_ui/react/Tooltip';\nconst TooltipRoot = Tooltip.Root;" + "import { Tooltip } from '@base_ui/react/Tooltip';\nconst TooltipRoot = Tooltip.Root;" ], "classes": [], "spread": true, diff --git a/docs/data/api/tooltip-trigger.json b/docs/data/api/tooltip-trigger.json index d7727ec84..e9b46eea5 100644 --- a/docs/data/api/tooltip-trigger.json +++ b/docs/data/api/tooltip-trigger.json @@ -5,7 +5,7 @@ }, "name": "TooltipTrigger", "imports": [ - "import * as Tooltip from '@base_ui/react/Tooltip';\nconst TooltipTrigger = Tooltip.Trigger;" + "import { Tooltip } from '@base_ui/react/Tooltip';\nconst TooltipTrigger = Tooltip.Trigger;" ], "classes": [], "spread": true, diff --git a/docs/data/components/alert-dialog/AlertDialogIntroduction/css-modules/index.js b/docs/data/components/alert-dialog/AlertDialogIntroduction/css-modules/index.js index dfece4502..73a50d374 100644 --- a/docs/data/components/alert-dialog/AlertDialogIntroduction/css-modules/index.js +++ b/docs/data/components/alert-dialog/AlertDialogIntroduction/css-modules/index.js @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as AlertDialog from '@base_ui/react/AlertDialog'; +import { AlertDialog } from '@base_ui/react/AlertDialog'; import classes from './styles.module.css'; export default function AlertDialogIntroduction() { diff --git a/docs/data/components/alert-dialog/AlertDialogIntroduction/css-modules/index.tsx b/docs/data/components/alert-dialog/AlertDialogIntroduction/css-modules/index.tsx index dfece4502..73a50d374 100644 --- a/docs/data/components/alert-dialog/AlertDialogIntroduction/css-modules/index.tsx +++ b/docs/data/components/alert-dialog/AlertDialogIntroduction/css-modules/index.tsx @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as AlertDialog from '@base_ui/react/AlertDialog'; +import { AlertDialog } from '@base_ui/react/AlertDialog'; import classes from './styles.module.css'; export default function AlertDialogIntroduction() { diff --git a/docs/data/components/alert-dialog/AlertDialogIntroduction/system/index.js b/docs/data/components/alert-dialog/AlertDialogIntroduction/system/index.js index d61c8a6af..72336480b 100644 --- a/docs/data/components/alert-dialog/AlertDialogIntroduction/system/index.js +++ b/docs/data/components/alert-dialog/AlertDialogIntroduction/system/index.js @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as AlertDialog from '@base_ui/react/AlertDialog'; +import { AlertDialog } from '@base_ui/react/AlertDialog'; import { styled } from '@mui/system'; export default function AlertDialogIntroduction() { diff --git a/docs/data/components/alert-dialog/AlertDialogIntroduction/system/index.tsx b/docs/data/components/alert-dialog/AlertDialogIntroduction/system/index.tsx index d61c8a6af..72336480b 100644 --- a/docs/data/components/alert-dialog/AlertDialogIntroduction/system/index.tsx +++ b/docs/data/components/alert-dialog/AlertDialogIntroduction/system/index.tsx @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as AlertDialog from '@base_ui/react/AlertDialog'; +import { AlertDialog } from '@base_ui/react/AlertDialog'; import { styled } from '@mui/system'; export default function AlertDialogIntroduction() { diff --git a/docs/data/components/alert-dialog/AlertDialogIntroduction/tailwind/index.js b/docs/data/components/alert-dialog/AlertDialogIntroduction/tailwind/index.js index 282a7bada..a01762d0d 100644 --- a/docs/data/components/alert-dialog/AlertDialogIntroduction/tailwind/index.js +++ b/docs/data/components/alert-dialog/AlertDialogIntroduction/tailwind/index.js @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as AlertDialog from '@base_ui/react/AlertDialog'; +import { AlertDialog } from '@base_ui/react/AlertDialog'; export default function UnstyledDialogIntroduction() { return ( diff --git a/docs/data/components/alert-dialog/AlertDialogIntroduction/tailwind/index.tsx b/docs/data/components/alert-dialog/AlertDialogIntroduction/tailwind/index.tsx index c667df7e4..17c58e16a 100644 --- a/docs/data/components/alert-dialog/AlertDialogIntroduction/tailwind/index.tsx +++ b/docs/data/components/alert-dialog/AlertDialogIntroduction/tailwind/index.tsx @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as AlertDialog from '@base_ui/react/AlertDialog'; +import { AlertDialog } from '@base_ui/react/AlertDialog'; export default function UnstyledDialogIntroduction() { return ( diff --git a/docs/data/components/alert-dialog/AlertDialogWithTransitions.js b/docs/data/components/alert-dialog/AlertDialogWithTransitions.js index e1a4044c4..321e5e713 100644 --- a/docs/data/components/alert-dialog/AlertDialogWithTransitions.js +++ b/docs/data/components/alert-dialog/AlertDialogWithTransitions.js @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as BaseAlertDialog from '@base_ui/react/AlertDialog'; +import { AlertDialog as BaseAlertDialog } from '@base_ui/react/AlertDialog'; import { styled } from '@mui/system'; export default function AlertDialogWithTransitions() { diff --git a/docs/data/components/alert-dialog/AlertDialogWithTransitions.tsx b/docs/data/components/alert-dialog/AlertDialogWithTransitions.tsx index e1a4044c4..321e5e713 100644 --- a/docs/data/components/alert-dialog/AlertDialogWithTransitions.tsx +++ b/docs/data/components/alert-dialog/AlertDialogWithTransitions.tsx @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as BaseAlertDialog from '@base_ui/react/AlertDialog'; +import { AlertDialog as BaseAlertDialog } from '@base_ui/react/AlertDialog'; import { styled } from '@mui/system'; export default function AlertDialogWithTransitions() { diff --git a/docs/data/components/alert-dialog/NestedAlertDialogs.js b/docs/data/components/alert-dialog/NestedAlertDialogs.js index 3e54627ca..4fc25e829 100644 --- a/docs/data/components/alert-dialog/NestedAlertDialogs.js +++ b/docs/data/components/alert-dialog/NestedAlertDialogs.js @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as BaseAlertDialog from '@base_ui/react/AlertDialog'; +import { AlertDialog as BaseAlertDialog } from '@base_ui/react/AlertDialog'; import { styled } from '@mui/system'; export default function NestedAlertDialogs() { diff --git a/docs/data/components/alert-dialog/NestedAlertDialogs.tsx b/docs/data/components/alert-dialog/NestedAlertDialogs.tsx index 3e54627ca..4fc25e829 100644 --- a/docs/data/components/alert-dialog/NestedAlertDialogs.tsx +++ b/docs/data/components/alert-dialog/NestedAlertDialogs.tsx @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as BaseAlertDialog from '@base_ui/react/AlertDialog'; +import { AlertDialog as BaseAlertDialog } from '@base_ui/react/AlertDialog'; import { styled } from '@mui/system'; export default function NestedAlertDialogs() { diff --git a/docs/data/components/checkbox-group/UnstyledCheckboxGroupIntroduction/css/index.js b/docs/data/components/checkbox-group/UnstyledCheckboxGroupIntroduction/css/index.js index 6bd20db61..c98646c9e 100644 --- a/docs/data/components/checkbox-group/UnstyledCheckboxGroupIntroduction/css/index.js +++ b/docs/data/components/checkbox-group/UnstyledCheckboxGroupIntroduction/css/index.js @@ -1,8 +1,8 @@ 'use client'; import * as React from 'react'; -import * as Checkbox from '@base_ui/react/Checkbox'; -import * as CheckboxGroup from '@base_ui/react/CheckboxGroup'; -import * as Field from '@base_ui/react/Field'; +import { Checkbox } from '@base_ui/react/Checkbox'; +import { CheckboxGroup } from '@base_ui/react/CheckboxGroup'; +import { Field } from '@base_ui/react/Field'; export default function UnstyledCheckboxIndeterminateGroup() { return ( diff --git a/docs/data/components/checkbox-group/UnstyledCheckboxGroupIntroduction/css/index.tsx b/docs/data/components/checkbox-group/UnstyledCheckboxGroupIntroduction/css/index.tsx index 3d7b05826..6354c14fd 100644 --- a/docs/data/components/checkbox-group/UnstyledCheckboxGroupIntroduction/css/index.tsx +++ b/docs/data/components/checkbox-group/UnstyledCheckboxGroupIntroduction/css/index.tsx @@ -1,8 +1,8 @@ 'use client'; import * as React from 'react'; -import * as Checkbox from '@base_ui/react/Checkbox'; -import * as CheckboxGroup from '@base_ui/react/CheckboxGroup'; -import * as Field from '@base_ui/react/Field'; +import { Checkbox } from '@base_ui/react/Checkbox'; +import { CheckboxGroup } from '@base_ui/react/CheckboxGroup'; +import { Field } from '@base_ui/react/Field'; export default function UnstyledCheckboxIndeterminateGroup() { return ( diff --git a/docs/data/components/checkbox-group/UnstyledCheckboxGroupIntroduction/system/index.js b/docs/data/components/checkbox-group/UnstyledCheckboxGroupIntroduction/system/index.js index 1033cfc87..e9a4e28e4 100644 --- a/docs/data/components/checkbox-group/UnstyledCheckboxGroupIntroduction/system/index.js +++ b/docs/data/components/checkbox-group/UnstyledCheckboxGroupIntroduction/system/index.js @@ -1,9 +1,9 @@ 'use client'; import * as React from 'react'; import { css, styled } from '@mui/system'; -import * as BaseCheckbox from '@base_ui/react/Checkbox'; -import * as CheckboxGroup from '@base_ui/react/CheckboxGroup'; -import * as Field from '@base_ui/react/Field'; +import { Checkbox as BaseCheckbox } from '@base_ui/react/Checkbox'; +import { CheckboxGroup } from '@base_ui/react/CheckboxGroup'; +import { Field } from '@base_ui/react/Field'; export default function UnstyledCheckboxIndeterminateGroup() { return ( diff --git a/docs/data/components/checkbox-group/UnstyledCheckboxGroupIntroduction/system/index.tsx b/docs/data/components/checkbox-group/UnstyledCheckboxGroupIntroduction/system/index.tsx index a83acafc0..3cf31369e 100644 --- a/docs/data/components/checkbox-group/UnstyledCheckboxGroupIntroduction/system/index.tsx +++ b/docs/data/components/checkbox-group/UnstyledCheckboxGroupIntroduction/system/index.tsx @@ -1,9 +1,9 @@ 'use client'; import * as React from 'react'; import { css, styled } from '@mui/system'; -import * as BaseCheckbox from '@base_ui/react/Checkbox'; -import * as CheckboxGroup from '@base_ui/react/CheckboxGroup'; -import * as Field from '@base_ui/react/Field'; +import { Checkbox as BaseCheckbox } from '@base_ui/react/Checkbox'; +import { CheckboxGroup } from '@base_ui/react/CheckboxGroup'; +import { Field } from '@base_ui/react/Field'; export default function UnstyledCheckboxIndeterminateGroup() { return ( diff --git a/docs/data/components/checkbox-group/UnstyledCheckboxGroupIntroduction/tailwind/index.js b/docs/data/components/checkbox-group/UnstyledCheckboxGroupIntroduction/tailwind/index.js index 577e7db15..2dd01a12d 100644 --- a/docs/data/components/checkbox-group/UnstyledCheckboxGroupIntroduction/tailwind/index.js +++ b/docs/data/components/checkbox-group/UnstyledCheckboxGroupIntroduction/tailwind/index.js @@ -2,9 +2,9 @@ import * as React from 'react'; import PropTypes from 'prop-types'; import { useTheme } from '@mui/system'; -import * as BaseCheckbox from '@base_ui/react/Checkbox'; -import * as CheckboxGroup from '@base_ui/react/CheckboxGroup'; -import * as Field from '@base_ui/react/Field'; +import { Checkbox as BaseCheckbox } from '@base_ui/react/Checkbox'; +import { CheckboxGroup } from '@base_ui/react/CheckboxGroup'; +import { Field } from '@base_ui/react/Field'; function classNames(...classes) { return classes.filter(Boolean).join(' '); diff --git a/docs/data/components/checkbox-group/UnstyledCheckboxGroupIntroduction/tailwind/index.tsx b/docs/data/components/checkbox-group/UnstyledCheckboxGroupIntroduction/tailwind/index.tsx index 3169ca830..a0a666edf 100644 --- a/docs/data/components/checkbox-group/UnstyledCheckboxGroupIntroduction/tailwind/index.tsx +++ b/docs/data/components/checkbox-group/UnstyledCheckboxGroupIntroduction/tailwind/index.tsx @@ -1,9 +1,9 @@ 'use client'; import * as React from 'react'; import { useTheme } from '@mui/system'; -import * as BaseCheckbox from '@base_ui/react/Checkbox'; -import * as CheckboxGroup from '@base_ui/react/CheckboxGroup'; -import * as Field from '@base_ui/react/Field'; +import { Checkbox as BaseCheckbox } from '@base_ui/react/Checkbox'; +import { CheckboxGroup } from '@base_ui/react/CheckboxGroup'; +import { Field } from '@base_ui/react/Field'; function classNames(...classes: Array) { return classes.filter(Boolean).join(' '); diff --git a/docs/data/components/checkbox-group/UnstyledCheckboxGroupNested.js b/docs/data/components/checkbox-group/UnstyledCheckboxGroupNested.js index c70d40384..9201619d6 100644 --- a/docs/data/components/checkbox-group/UnstyledCheckboxGroupNested.js +++ b/docs/data/components/checkbox-group/UnstyledCheckboxGroupNested.js @@ -1,8 +1,8 @@ 'use client'; import * as React from 'react'; -import * as BaseCheckbox from '@base_ui/react/Checkbox'; -import * as CheckboxGroup from '@base_ui/react/CheckboxGroup'; -import * as Field from '@base_ui/react/Field'; +import { Checkbox as BaseCheckbox } from '@base_ui/react/Checkbox'; +import { CheckboxGroup } from '@base_ui/react/CheckboxGroup'; +import { Field } from '@base_ui/react/Field'; import { styled } from '@mui/system'; const colors = ['red', 'green', 'blue']; diff --git a/docs/data/components/checkbox-group/UnstyledCheckboxGroupNested.tsx b/docs/data/components/checkbox-group/UnstyledCheckboxGroupNested.tsx index 13326baf0..649d3e5d8 100644 --- a/docs/data/components/checkbox-group/UnstyledCheckboxGroupNested.tsx +++ b/docs/data/components/checkbox-group/UnstyledCheckboxGroupNested.tsx @@ -1,8 +1,8 @@ 'use client'; import * as React from 'react'; -import * as BaseCheckbox from '@base_ui/react/Checkbox'; -import * as CheckboxGroup from '@base_ui/react/CheckboxGroup'; -import * as Field from '@base_ui/react/Field'; +import { Checkbox as BaseCheckbox } from '@base_ui/react/Checkbox'; +import { CheckboxGroup } from '@base_ui/react/CheckboxGroup'; +import { Field } from '@base_ui/react/Field'; import { styled } from '@mui/system'; const colors = ['red', 'green', 'blue']; diff --git a/docs/data/components/checkbox-group/checkbox-group.mdx b/docs/data/components/checkbox-group/checkbox-group.mdx index e113cb30c..851d14b84 100644 --- a/docs/data/components/checkbox-group/checkbox-group.mdx +++ b/docs/data/components/checkbox-group/checkbox-group.mdx @@ -39,7 +39,7 @@ Checkbox Group is composed of a `Root` component and `Checkbox` components: `Field` components are used to label the Checkbox Group and individual Checkboxes: ```jsx -import * as Field from '@base_ui/react/Field'; +import { Field } from '@base_ui/react/Field'; ``` ```tsx diff --git a/docs/data/components/checkbox/UnstyledCheckboxIndeterminate.js b/docs/data/components/checkbox/UnstyledCheckboxIndeterminate.js index 786d49acc..edb83d101 100644 --- a/docs/data/components/checkbox/UnstyledCheckboxIndeterminate.js +++ b/docs/data/components/checkbox/UnstyledCheckboxIndeterminate.js @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; import { styled } from '@mui/system'; -import * as BaseCheckbox from '@base_ui/react/Checkbox'; +import { Checkbox as BaseCheckbox } from '@base_ui/react/Checkbox'; export default function UnstyledCheckboxIndeterminate() { return ( diff --git a/docs/data/components/checkbox/UnstyledCheckboxIndeterminate.tsx b/docs/data/components/checkbox/UnstyledCheckboxIndeterminate.tsx index 3b9e87f9a..07c87a75c 100644 --- a/docs/data/components/checkbox/UnstyledCheckboxIndeterminate.tsx +++ b/docs/data/components/checkbox/UnstyledCheckboxIndeterminate.tsx @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; import { styled } from '@mui/system'; -import * as BaseCheckbox from '@base_ui/react/Checkbox'; +import { Checkbox as BaseCheckbox } from '@base_ui/react/Checkbox'; export default function UnstyledCheckboxIndeterminate() { return ( diff --git a/docs/data/components/checkbox/UnstyledCheckboxIndeterminateGroup.js b/docs/data/components/checkbox/UnstyledCheckboxIndeterminateGroup.js index 44234bb4c..7415e0637 100644 --- a/docs/data/components/checkbox/UnstyledCheckboxIndeterminateGroup.js +++ b/docs/data/components/checkbox/UnstyledCheckboxIndeterminateGroup.js @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; import { styled } from '@mui/system'; -import * as BaseCheckbox from '@base_ui/react/Checkbox'; +import { Checkbox as BaseCheckbox } from '@base_ui/react/Checkbox'; const colors = ['Red', 'Green', 'Blue']; diff --git a/docs/data/components/checkbox/UnstyledCheckboxIndeterminateGroup.tsx b/docs/data/components/checkbox/UnstyledCheckboxIndeterminateGroup.tsx index f6907fe19..3c60042b8 100644 --- a/docs/data/components/checkbox/UnstyledCheckboxIndeterminateGroup.tsx +++ b/docs/data/components/checkbox/UnstyledCheckboxIndeterminateGroup.tsx @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; import { styled } from '@mui/system'; -import * as BaseCheckbox from '@base_ui/react/Checkbox'; +import { Checkbox as BaseCheckbox } from '@base_ui/react/Checkbox'; const colors = ['Red', 'Green', 'Blue']; diff --git a/docs/data/components/checkbox/UnstyledCheckboxIntroduction/css-modules/index.js b/docs/data/components/checkbox/UnstyledCheckboxIntroduction/css-modules/index.js index b4a264dad..a5b0de642 100644 --- a/docs/data/components/checkbox/UnstyledCheckboxIntroduction/css-modules/index.js +++ b/docs/data/components/checkbox/UnstyledCheckboxIntroduction/css-modules/index.js @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as Checkbox from '@base_ui/react/Checkbox'; +import { Checkbox } from '@base_ui/react/Checkbox'; import { useTheme } from '@mui/system'; export default function UnstyledCheckboxIntroduction() { diff --git a/docs/data/components/checkbox/UnstyledCheckboxIntroduction/css-modules/index.tsx b/docs/data/components/checkbox/UnstyledCheckboxIntroduction/css-modules/index.tsx index 758acd41b..1605c4e7c 100644 --- a/docs/data/components/checkbox/UnstyledCheckboxIntroduction/css-modules/index.tsx +++ b/docs/data/components/checkbox/UnstyledCheckboxIntroduction/css-modules/index.tsx @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as Checkbox from '@base_ui/react/Checkbox'; +import { Checkbox } from '@base_ui/react/Checkbox'; import { useTheme } from '@mui/system'; export default function UnstyledCheckboxIntroduction() { diff --git a/docs/data/components/checkbox/UnstyledCheckboxIntroduction/system/index.js b/docs/data/components/checkbox/UnstyledCheckboxIntroduction/system/index.js index d5004c166..b4e424d54 100644 --- a/docs/data/components/checkbox/UnstyledCheckboxIntroduction/system/index.js +++ b/docs/data/components/checkbox/UnstyledCheckboxIntroduction/system/index.js @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; import { styled } from '@mui/system'; -import * as BaseCheckbox from '@base_ui/react/Checkbox'; +import { Checkbox as BaseCheckbox } from '@base_ui/react/Checkbox'; export default function UnstyledSwitchIntroduction() { return ( diff --git a/docs/data/components/checkbox/UnstyledCheckboxIntroduction/system/index.tsx b/docs/data/components/checkbox/UnstyledCheckboxIntroduction/system/index.tsx index 599539a6e..155601a9f 100644 --- a/docs/data/components/checkbox/UnstyledCheckboxIntroduction/system/index.tsx +++ b/docs/data/components/checkbox/UnstyledCheckboxIntroduction/system/index.tsx @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; import { styled } from '@mui/system'; -import * as BaseCheckbox from '@base_ui/react/Checkbox'; +import { Checkbox as BaseCheckbox } from '@base_ui/react/Checkbox'; export default function UnstyledSwitchIntroduction() { return ( diff --git a/docs/data/components/checkbox/UnstyledCheckboxIntroduction/tailwind/index.js b/docs/data/components/checkbox/UnstyledCheckboxIntroduction/tailwind/index.js index f27426ca2..42197c24e 100644 --- a/docs/data/components/checkbox/UnstyledCheckboxIntroduction/tailwind/index.js +++ b/docs/data/components/checkbox/UnstyledCheckboxIntroduction/tailwind/index.js @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; import PropTypes from 'prop-types'; -import * as BaseCheckbox from '@base_ui/react/Checkbox'; +import { Checkbox as BaseCheckbox } from '@base_ui/react/Checkbox'; import { useTheme } from '@mui/system'; function classNames(...classes) { diff --git a/docs/data/components/checkbox/UnstyledCheckboxIntroduction/tailwind/index.tsx b/docs/data/components/checkbox/UnstyledCheckboxIntroduction/tailwind/index.tsx index 595509db4..9175a5bf8 100644 --- a/docs/data/components/checkbox/UnstyledCheckboxIntroduction/tailwind/index.tsx +++ b/docs/data/components/checkbox/UnstyledCheckboxIntroduction/tailwind/index.tsx @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as BaseCheckbox from '@base_ui/react/Checkbox'; +import { Checkbox as BaseCheckbox } from '@base_ui/react/Checkbox'; import { useTheme } from '@mui/system'; function classNames(...classes: Array) { diff --git a/docs/data/components/collapsible/CssAnimatedCollapsible.js b/docs/data/components/collapsible/CssAnimatedCollapsible.js index 5b1d15dc9..e80819527 100644 --- a/docs/data/components/collapsible/CssAnimatedCollapsible.js +++ b/docs/data/components/collapsible/CssAnimatedCollapsible.js @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; import { useTheme } from '@mui/system'; -import * as Collapsible from '@base_ui/react/Collapsible'; +import { Collapsible } from '@base_ui/react/Collapsible'; export default function CssAnimatedCollapsible() { const [open, setOpen] = React.useState(true); diff --git a/docs/data/components/collapsible/CssAnimatedCollapsible.tsx b/docs/data/components/collapsible/CssAnimatedCollapsible.tsx index 5b1d15dc9..e80819527 100644 --- a/docs/data/components/collapsible/CssAnimatedCollapsible.tsx +++ b/docs/data/components/collapsible/CssAnimatedCollapsible.tsx @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; import { useTheme } from '@mui/system'; -import * as Collapsible from '@base_ui/react/Collapsible'; +import { Collapsible } from '@base_ui/react/Collapsible'; export default function CssAnimatedCollapsible() { const [open, setOpen] = React.useState(true); diff --git a/docs/data/components/collapsible/CssTransitionCollapsible.js b/docs/data/components/collapsible/CssTransitionCollapsible.js index 29e70d2ce..d87a29a72 100644 --- a/docs/data/components/collapsible/CssTransitionCollapsible.js +++ b/docs/data/components/collapsible/CssTransitionCollapsible.js @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; import { useTheme } from '@mui/system'; -import * as Collapsible from '@base_ui/react/Collapsible'; +import { Collapsible } from '@base_ui/react/Collapsible'; export default function CssTransitionCollapsible() { const [open, setOpen] = React.useState(true); diff --git a/docs/data/components/collapsible/CssTransitionCollapsible.tsx b/docs/data/components/collapsible/CssTransitionCollapsible.tsx index 29e70d2ce..d87a29a72 100644 --- a/docs/data/components/collapsible/CssTransitionCollapsible.tsx +++ b/docs/data/components/collapsible/CssTransitionCollapsible.tsx @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; import { useTheme } from '@mui/system'; -import * as Collapsible from '@base_ui/react/Collapsible'; +import { Collapsible } from '@base_ui/react/Collapsible'; export default function CssTransitionCollapsible() { const [open, setOpen] = React.useState(true); diff --git a/docs/data/components/collapsible/UnstyledCollapsibleIntroduction.js b/docs/data/components/collapsible/UnstyledCollapsibleIntroduction.js index a8b7654a3..6bd55ebe7 100644 --- a/docs/data/components/collapsible/UnstyledCollapsibleIntroduction.js +++ b/docs/data/components/collapsible/UnstyledCollapsibleIntroduction.js @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; import { styled, useTheme, Box } from '@mui/system'; -import * as BaseCollapsible from '@base_ui/react/Collapsible'; +import { Collapsible as BaseCollapsible } from '@base_ui/react/Collapsible'; const Collapsible = BaseCollapsible.Root; diff --git a/docs/data/components/collapsible/UnstyledCollapsibleIntroduction.tsx b/docs/data/components/collapsible/UnstyledCollapsibleIntroduction.tsx index a8b7654a3..6bd55ebe7 100644 --- a/docs/data/components/collapsible/UnstyledCollapsibleIntroduction.tsx +++ b/docs/data/components/collapsible/UnstyledCollapsibleIntroduction.tsx @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; import { styled, useTheme, Box } from '@mui/system'; -import * as BaseCollapsible from '@base_ui/react/Collapsible'; +import { Collapsible as BaseCollapsible } from '@base_ui/react/Collapsible'; const Collapsible = BaseCollapsible.Root; diff --git a/docs/data/components/dialog/DialogWithTransitions.js b/docs/data/components/dialog/DialogWithTransitions.js index 7b219eb98..933fe38fa 100644 --- a/docs/data/components/dialog/DialogWithTransitions.js +++ b/docs/data/components/dialog/DialogWithTransitions.js @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as BaseDialog from '@base_ui/react/Dialog'; +import { Dialog as BaseDialog } from '@base_ui/react/Dialog'; import { styled } from '@mui/system'; export default function DialogWithTransitions() { diff --git a/docs/data/components/dialog/DialogWithTransitions.tsx b/docs/data/components/dialog/DialogWithTransitions.tsx index 7b219eb98..933fe38fa 100644 --- a/docs/data/components/dialog/DialogWithTransitions.tsx +++ b/docs/data/components/dialog/DialogWithTransitions.tsx @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as BaseDialog from '@base_ui/react/Dialog'; +import { Dialog as BaseDialog } from '@base_ui/react/Dialog'; import { styled } from '@mui/system'; export default function DialogWithTransitions() { diff --git a/docs/data/components/dialog/NestedDialogs.js b/docs/data/components/dialog/NestedDialogs.js index 1ecbc0446..b154fdf96 100644 --- a/docs/data/components/dialog/NestedDialogs.js +++ b/docs/data/components/dialog/NestedDialogs.js @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as BaseDialog from '@base_ui/react/Dialog'; +import { Dialog as BaseDialog } from '@base_ui/react/Dialog'; import { styled } from '@mui/system'; export default function NestedDialogs() { diff --git a/docs/data/components/dialog/NestedDialogs.tsx b/docs/data/components/dialog/NestedDialogs.tsx index 1ecbc0446..b154fdf96 100644 --- a/docs/data/components/dialog/NestedDialogs.tsx +++ b/docs/data/components/dialog/NestedDialogs.tsx @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as BaseDialog from '@base_ui/react/Dialog'; +import { Dialog as BaseDialog } from '@base_ui/react/Dialog'; import { styled } from '@mui/system'; export default function NestedDialogs() { diff --git a/docs/data/components/dialog/UnstyledDialogIntroduction/css-modules/index.js b/docs/data/components/dialog/UnstyledDialogIntroduction/css-modules/index.js index 9e9eaab47..e6868505f 100644 --- a/docs/data/components/dialog/UnstyledDialogIntroduction/css-modules/index.js +++ b/docs/data/components/dialog/UnstyledDialogIntroduction/css-modules/index.js @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as Dialog from '@base_ui/react/Dialog'; +import { Dialog } from '@base_ui/react/Dialog'; import classes from './styles.module.css'; export default function UnstyledDialogIntroduction() { diff --git a/docs/data/components/dialog/UnstyledDialogIntroduction/css-modules/index.tsx b/docs/data/components/dialog/UnstyledDialogIntroduction/css-modules/index.tsx index 9e9eaab47..e6868505f 100644 --- a/docs/data/components/dialog/UnstyledDialogIntroduction/css-modules/index.tsx +++ b/docs/data/components/dialog/UnstyledDialogIntroduction/css-modules/index.tsx @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as Dialog from '@base_ui/react/Dialog'; +import { Dialog } from '@base_ui/react/Dialog'; import classes from './styles.module.css'; export default function UnstyledDialogIntroduction() { diff --git a/docs/data/components/dialog/UnstyledDialogIntroduction/system/index.js b/docs/data/components/dialog/UnstyledDialogIntroduction/system/index.js index 4129596a8..6627436c7 100644 --- a/docs/data/components/dialog/UnstyledDialogIntroduction/system/index.js +++ b/docs/data/components/dialog/UnstyledDialogIntroduction/system/index.js @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as Dialog from '@base_ui/react/Dialog'; +import { Dialog } from '@base_ui/react/Dialog'; import { styled } from '@mui/system'; export default function UnstyledDialogIntroduction() { diff --git a/docs/data/components/dialog/UnstyledDialogIntroduction/system/index.tsx b/docs/data/components/dialog/UnstyledDialogIntroduction/system/index.tsx index 4129596a8..6627436c7 100644 --- a/docs/data/components/dialog/UnstyledDialogIntroduction/system/index.tsx +++ b/docs/data/components/dialog/UnstyledDialogIntroduction/system/index.tsx @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as Dialog from '@base_ui/react/Dialog'; +import { Dialog } from '@base_ui/react/Dialog'; import { styled } from '@mui/system'; export default function UnstyledDialogIntroduction() { diff --git a/docs/data/components/dialog/UnstyledDialogIntroduction/tailwind/index.js b/docs/data/components/dialog/UnstyledDialogIntroduction/tailwind/index.js index f4ebdf05b..988a1e274 100644 --- a/docs/data/components/dialog/UnstyledDialogIntroduction/tailwind/index.js +++ b/docs/data/components/dialog/UnstyledDialogIntroduction/tailwind/index.js @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as Dialog from '@base_ui/react/Dialog'; +import { Dialog } from '@base_ui/react/Dialog'; export default function UnstyledDialogIntroduction() { return ( diff --git a/docs/data/components/dialog/UnstyledDialogIntroduction/tailwind/index.tsx b/docs/data/components/dialog/UnstyledDialogIntroduction/tailwind/index.tsx index 5b07e9724..b1127efec 100644 --- a/docs/data/components/dialog/UnstyledDialogIntroduction/tailwind/index.tsx +++ b/docs/data/components/dialog/UnstyledDialogIntroduction/tailwind/index.tsx @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as Dialog from '@base_ui/react/Dialog'; +import { Dialog } from '@base_ui/react/Dialog'; export default function UnstyledDialogIntroduction() { return ( diff --git a/docs/data/components/field/UnstyledFieldAsync.js b/docs/data/components/field/UnstyledFieldAsync.js index 92d0baa38..e966a060e 100644 --- a/docs/data/components/field/UnstyledFieldAsync.js +++ b/docs/data/components/field/UnstyledFieldAsync.js @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as Field from '@base_ui/react/Field'; +import { Field } from '@base_ui/react/Field'; import { styled } from '@mui/system'; const cache = new Map(); diff --git a/docs/data/components/field/UnstyledFieldAsync.tsx b/docs/data/components/field/UnstyledFieldAsync.tsx index d560b2107..60f064b3e 100644 --- a/docs/data/components/field/UnstyledFieldAsync.tsx +++ b/docs/data/components/field/UnstyledFieldAsync.tsx @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as Field from '@base_ui/react/Field'; +import { Field } from '@base_ui/react/Field'; import { styled } from '@mui/system'; const cache = new Map(); diff --git a/docs/data/components/field/UnstyledFieldIntroduction/system/index.js b/docs/data/components/field/UnstyledFieldIntroduction/system/index.js index e0f42d8ce..a1dd1e451 100644 --- a/docs/data/components/field/UnstyledFieldIntroduction/system/index.js +++ b/docs/data/components/field/UnstyledFieldIntroduction/system/index.js @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as Field from '@base_ui/react/Field'; +import { Field } from '@base_ui/react/Field'; import { styled } from '@mui/system'; export default function UnstyledFieldIntroduction() { diff --git a/docs/data/components/field/UnstyledFieldIntroduction/system/index.tsx b/docs/data/components/field/UnstyledFieldIntroduction/system/index.tsx index e0f42d8ce..a1dd1e451 100644 --- a/docs/data/components/field/UnstyledFieldIntroduction/system/index.tsx +++ b/docs/data/components/field/UnstyledFieldIntroduction/system/index.tsx @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as Field from '@base_ui/react/Field'; +import { Field } from '@base_ui/react/Field'; import { styled } from '@mui/system'; export default function UnstyledFieldIntroduction() { diff --git a/docs/data/components/field/UnstyledFieldPassword.js b/docs/data/components/field/UnstyledFieldPassword.js index ccc729cd0..2e233b17f 100644 --- a/docs/data/components/field/UnstyledFieldPassword.js +++ b/docs/data/components/field/UnstyledFieldPassword.js @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as Field from '@base_ui/react/Field'; +import { Field } from '@base_ui/react/Field'; import { styled } from '@mui/system'; function validate(value) { diff --git a/docs/data/components/field/UnstyledFieldPassword.tsx b/docs/data/components/field/UnstyledFieldPassword.tsx index 1181ef90e..63adfbdf9 100644 --- a/docs/data/components/field/UnstyledFieldPassword.tsx +++ b/docs/data/components/field/UnstyledFieldPassword.tsx @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as Field from '@base_ui/react/Field'; +import { Field } from '@base_ui/react/Field'; import { styled } from '@mui/system'; function validate(value: string) { diff --git a/docs/data/components/field/UnstyledFieldServerError.js b/docs/data/components/field/UnstyledFieldServerError.js index a9875b9e8..24e281a83 100644 --- a/docs/data/components/field/UnstyledFieldServerError.js +++ b/docs/data/components/field/UnstyledFieldServerError.js @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as Field from '@base_ui/react/Field'; +import { Field } from '@base_ui/react/Field'; import { styled } from '@mui/system'; export default function UnstyledFieldServerError() { diff --git a/docs/data/components/field/UnstyledFieldServerError.tsx b/docs/data/components/field/UnstyledFieldServerError.tsx index 35a880e84..edca241ac 100644 --- a/docs/data/components/field/UnstyledFieldServerError.tsx +++ b/docs/data/components/field/UnstyledFieldServerError.tsx @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as Field from '@base_ui/react/Field'; +import { Field } from '@base_ui/react/Field'; import { styled } from '@mui/system'; type Status = 'initial' | 'loading' | 'success' | 'error'; diff --git a/docs/data/components/fieldset/UnstyledFieldsetIntroduction/system/index.js b/docs/data/components/fieldset/UnstyledFieldsetIntroduction/system/index.js index fc0380e07..24178b06b 100644 --- a/docs/data/components/fieldset/UnstyledFieldsetIntroduction/system/index.js +++ b/docs/data/components/fieldset/UnstyledFieldsetIntroduction/system/index.js @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; -import * as Field from '@base_ui/react/Field'; -import * as Fieldset from '@base_ui/react/Fieldset'; +import { Field } from '@base_ui/react/Field'; +import { Fieldset } from '@base_ui/react/Fieldset'; import { styled } from '@mui/system'; export default function UnstyledFieldsetIntroduction() { diff --git a/docs/data/components/fieldset/UnstyledFieldsetIntroduction/system/index.tsx b/docs/data/components/fieldset/UnstyledFieldsetIntroduction/system/index.tsx index fc0380e07..24178b06b 100644 --- a/docs/data/components/fieldset/UnstyledFieldsetIntroduction/system/index.tsx +++ b/docs/data/components/fieldset/UnstyledFieldsetIntroduction/system/index.tsx @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; -import * as Field from '@base_ui/react/Field'; -import * as Fieldset from '@base_ui/react/Fieldset'; +import { Field } from '@base_ui/react/Field'; +import { Fieldset } from '@base_ui/react/Fieldset'; import { styled } from '@mui/system'; export default function UnstyledFieldsetIntroduction() { diff --git a/docs/data/components/form/FormIntroduction/system/index.js b/docs/data/components/form/FormIntroduction/system/index.js index 2e3d2a2c8..a36554850 100644 --- a/docs/data/components/form/FormIntroduction/system/index.js +++ b/docs/data/components/form/FormIntroduction/system/index.js @@ -1,9 +1,9 @@ 'use client'; import * as React from 'react'; -import * as Form from '@base_ui/react/Form'; -import * as Fieldset from '@base_ui/react/Fieldset'; -import * as Field from '@base_ui/react/Field'; +import { Form } from '@base_ui/react/Form'; +import { Fieldset } from '@base_ui/react/Fieldset'; +import { Field } from '@base_ui/react/Field'; import { styled } from '@mui/system'; export default function FormIntroduction() { diff --git a/docs/data/components/form/FormIntroduction/system/index.tsx b/docs/data/components/form/FormIntroduction/system/index.tsx index be54ebd50..e4b3bb49e 100644 --- a/docs/data/components/form/FormIntroduction/system/index.tsx +++ b/docs/data/components/form/FormIntroduction/system/index.tsx @@ -1,9 +1,9 @@ 'use client'; import * as React from 'react'; -import * as Form from '@base_ui/react/Form'; -import * as Fieldset from '@base_ui/react/Fieldset'; -import * as Field from '@base_ui/react/Field'; +import { Form } from '@base_ui/react/Form'; +import { Fieldset } from '@base_ui/react/Fieldset'; +import { Field } from '@base_ui/react/Field'; import { styled } from '@mui/system'; type Status = 'initial' | 'loading' | 'success' | 'error'; diff --git a/docs/data/components/form/form.mdx b/docs/data/components/form/form.mdx index 72eaf9a5a..999b0bcaf 100644 --- a/docs/data/components/form/form.mdx +++ b/docs/data/components/form/form.mdx @@ -37,8 +37,8 @@ Forms are implemented using a `Root` component and `Field` components: Forms are intended to be used with the `Field` component, which provides labeling and validation for individual form controls. These are nested inside `Form.Root`: ```ts -import * as Form from '@base_ui/react/Form'; -import * as Field from '@base_ui/react/Field'; +import { Form } from '@base_ui/react/Form'; +import { Field } from '@base_ui/react/Field'; ``` ```jsx diff --git a/docs/data/components/menu/CheckboxItems.js b/docs/data/components/menu/CheckboxItems.js index 8b316c8b4..0dd752b86 100644 --- a/docs/data/components/menu/CheckboxItems.js +++ b/docs/data/components/menu/CheckboxItems.js @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; -import * as Menu from '@base_ui/react/Menu'; +import { Menu } from '@base_ui/react/Menu'; import { styled } from '@mui/system'; export default function CheckboxItems() { diff --git a/docs/data/components/menu/CheckboxItems.tsx b/docs/data/components/menu/CheckboxItems.tsx index 930e8c709..1efbbd4de 100644 --- a/docs/data/components/menu/CheckboxItems.tsx +++ b/docs/data/components/menu/CheckboxItems.tsx @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; -import * as Menu from '@base_ui/react/Menu'; +import { Menu } from '@base_ui/react/Menu'; import { styled } from '@mui/system'; export default function CheckboxItems() { diff --git a/docs/data/components/menu/MenuIntroduction/css-modules/Menu.js b/docs/data/components/menu/MenuIntroduction/css-modules/Menu.js index d5c3d1b7f..37fec5c5a 100644 --- a/docs/data/components/menu/MenuIntroduction/css-modules/Menu.js +++ b/docs/data/components/menu/MenuIntroduction/css-modules/Menu.js @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; import PropTypes from 'prop-types'; -import * as BaseMenu from '@base_ui/react/Menu'; +import { Menu as BaseMenu } from '@base_ui/react/Menu'; import classes from './Menu.module.css'; export const Menu = BaseMenu.Root; diff --git a/docs/data/components/menu/MenuIntroduction/css-modules/Menu.tsx b/docs/data/components/menu/MenuIntroduction/css-modules/Menu.tsx index 81ee796e8..87def4d72 100644 --- a/docs/data/components/menu/MenuIntroduction/css-modules/Menu.tsx +++ b/docs/data/components/menu/MenuIntroduction/css-modules/Menu.tsx @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as BaseMenu from '@base_ui/react/Menu'; +import { Menu as BaseMenu } from '@base_ui/react/Menu'; import classes from './Menu.module.css'; export const Menu = BaseMenu.Root; diff --git a/docs/data/components/menu/MenuIntroduction/system/index.js b/docs/data/components/menu/MenuIntroduction/system/index.js index 945f5bd82..3b7dca224 100644 --- a/docs/data/components/menu/MenuIntroduction/system/index.js +++ b/docs/data/components/menu/MenuIntroduction/system/index.js @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as Menu from '@base_ui/react/Menu'; +import { Menu } from '@base_ui/react/Menu'; import { styled } from '@mui/system'; export default function MenuIntroduction() { diff --git a/docs/data/components/menu/MenuIntroduction/system/index.tsx b/docs/data/components/menu/MenuIntroduction/system/index.tsx index 587097e71..a45fce979 100644 --- a/docs/data/components/menu/MenuIntroduction/system/index.tsx +++ b/docs/data/components/menu/MenuIntroduction/system/index.tsx @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as Menu from '@base_ui/react/Menu'; +import { Menu } from '@base_ui/react/Menu'; import { styled } from '@mui/system'; export default function MenuIntroduction() { diff --git a/docs/data/components/menu/MenuIntroduction/tailwind/index.js b/docs/data/components/menu/MenuIntroduction/tailwind/index.js index c88827b7e..74361643e 100644 --- a/docs/data/components/menu/MenuIntroduction/tailwind/index.js +++ b/docs/data/components/menu/MenuIntroduction/tailwind/index.js @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as Menu from '@base_ui/react/Menu'; +import { Menu } from '@base_ui/react/Menu'; import { useTheme } from '@mui/system'; function useIsDarkMode() { diff --git a/docs/data/components/menu/MenuIntroduction/tailwind/index.tsx b/docs/data/components/menu/MenuIntroduction/tailwind/index.tsx index 61821bb4a..c1203da2e 100644 --- a/docs/data/components/menu/MenuIntroduction/tailwind/index.tsx +++ b/docs/data/components/menu/MenuIntroduction/tailwind/index.tsx @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as Menu from '@base_ui/react/Menu'; +import { Menu } from '@base_ui/react/Menu'; import { useTheme } from '@mui/system'; function useIsDarkMode() { diff --git a/docs/data/components/menu/NestedMenu.js b/docs/data/components/menu/NestedMenu.js index 82d31a822..32a7cca1f 100644 --- a/docs/data/components/menu/NestedMenu.js +++ b/docs/data/components/menu/NestedMenu.js @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as Menu from '@base_ui/react/Menu'; +import { Menu } from '@base_ui/react/Menu'; import { styled } from '@mui/system'; export default function NestedMenu() { diff --git a/docs/data/components/menu/NestedMenu.tsx b/docs/data/components/menu/NestedMenu.tsx index 9eb43acaf..b13f069b1 100644 --- a/docs/data/components/menu/NestedMenu.tsx +++ b/docs/data/components/menu/NestedMenu.tsx @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as Menu from '@base_ui/react/Menu'; +import { Menu } from '@base_ui/react/Menu'; import { styled } from '@mui/system'; export default function NestedMenu() { diff --git a/docs/data/components/menu/RadioItems.js b/docs/data/components/menu/RadioItems.js index 314d6f34d..e00fdf1fd 100644 --- a/docs/data/components/menu/RadioItems.js +++ b/docs/data/components/menu/RadioItems.js @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as Menu from '@base_ui/react/Menu'; +import { Menu } from '@base_ui/react/Menu'; import { styled } from '@mui/system'; export default function RadioItems() { diff --git a/docs/data/components/menu/RadioItems.tsx b/docs/data/components/menu/RadioItems.tsx index 314d6f34d..e00fdf1fd 100644 --- a/docs/data/components/menu/RadioItems.tsx +++ b/docs/data/components/menu/RadioItems.tsx @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as Menu from '@base_ui/react/Menu'; +import { Menu } from '@base_ui/react/Menu'; import { styled } from '@mui/system'; export default function RadioItems() { diff --git a/docs/data/components/number-field/UnstyledNumberFieldFormat.js b/docs/data/components/number-field/UnstyledNumberFieldFormat.js index 6354175c3..250b32426 100644 --- a/docs/data/components/number-field/UnstyledNumberFieldFormat.js +++ b/docs/data/components/number-field/UnstyledNumberFieldFormat.js @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as BaseNumberField from '@base_ui/react/NumberField'; +import { NumberField as BaseNumberField } from '@base_ui/react/NumberField'; import { styled, css } from '@mui/system'; export default function UnstyledNumberFieldFormat() { diff --git a/docs/data/components/number-field/UnstyledNumberFieldFormat.tsx b/docs/data/components/number-field/UnstyledNumberFieldFormat.tsx index 6354175c3..250b32426 100644 --- a/docs/data/components/number-field/UnstyledNumberFieldFormat.tsx +++ b/docs/data/components/number-field/UnstyledNumberFieldFormat.tsx @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as BaseNumberField from '@base_ui/react/NumberField'; +import { NumberField as BaseNumberField } from '@base_ui/react/NumberField'; import { styled, css } from '@mui/system'; export default function UnstyledNumberFieldFormat() { diff --git a/docs/data/components/number-field/UnstyledNumberFieldIntroduction/css-modules/index.js b/docs/data/components/number-field/UnstyledNumberFieldIntroduction/css-modules/index.js index f4919cd48..799163407 100644 --- a/docs/data/components/number-field/UnstyledNumberFieldIntroduction/css-modules/index.js +++ b/docs/data/components/number-field/UnstyledNumberFieldIntroduction/css-modules/index.js @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as NumberField from '@base_ui/react/NumberField'; +import { NumberField } from '@base_ui/react/NumberField'; import { useTheme } from '@mui/system'; function useIsDarkMode() { diff --git a/docs/data/components/number-field/UnstyledNumberFieldIntroduction/css-modules/index.tsx b/docs/data/components/number-field/UnstyledNumberFieldIntroduction/css-modules/index.tsx index f4919cd48..799163407 100644 --- a/docs/data/components/number-field/UnstyledNumberFieldIntroduction/css-modules/index.tsx +++ b/docs/data/components/number-field/UnstyledNumberFieldIntroduction/css-modules/index.tsx @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as NumberField from '@base_ui/react/NumberField'; +import { NumberField } from '@base_ui/react/NumberField'; import { useTheme } from '@mui/system'; function useIsDarkMode() { diff --git a/docs/data/components/number-field/UnstyledNumberFieldIntroduction/system/index.js b/docs/data/components/number-field/UnstyledNumberFieldIntroduction/system/index.js index 0ecfce83e..d93b97b1f 100644 --- a/docs/data/components/number-field/UnstyledNumberFieldIntroduction/system/index.js +++ b/docs/data/components/number-field/UnstyledNumberFieldIntroduction/system/index.js @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; -import * as BaseNumberField from '@base_ui/react/NumberField'; -import * as Field from '@base_ui/react/Field'; +import { NumberField as BaseNumberField } from '@base_ui/react/NumberField'; +import { Field } from '@base_ui/react/Field'; import { css, styled, useTheme } from '@mui/system'; function useIsDarkMode() { diff --git a/docs/data/components/number-field/UnstyledNumberFieldIntroduction/system/index.tsx b/docs/data/components/number-field/UnstyledNumberFieldIntroduction/system/index.tsx index 0ecfce83e..d93b97b1f 100644 --- a/docs/data/components/number-field/UnstyledNumberFieldIntroduction/system/index.tsx +++ b/docs/data/components/number-field/UnstyledNumberFieldIntroduction/system/index.tsx @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; -import * as BaseNumberField from '@base_ui/react/NumberField'; -import * as Field from '@base_ui/react/Field'; +import { NumberField as BaseNumberField } from '@base_ui/react/NumberField'; +import { Field } from '@base_ui/react/Field'; import { css, styled, useTheme } from '@mui/system'; function useIsDarkMode() { diff --git a/docs/data/components/number-field/UnstyledNumberFieldIntroduction/tailwind/index.js b/docs/data/components/number-field/UnstyledNumberFieldIntroduction/tailwind/index.js index 7fb70bffe..465c128cb 100644 --- a/docs/data/components/number-field/UnstyledNumberFieldIntroduction/tailwind/index.js +++ b/docs/data/components/number-field/UnstyledNumberFieldIntroduction/tailwind/index.js @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; import PropTypes from 'prop-types'; -import * as BaseNumberField from '@base_ui/react/NumberField'; +import { NumberField as BaseNumberField } from '@base_ui/react/NumberField'; import { useTheme } from '@mui/system'; function classNames(...classes) { diff --git a/docs/data/components/number-field/UnstyledNumberFieldIntroduction/tailwind/index.tsx b/docs/data/components/number-field/UnstyledNumberFieldIntroduction/tailwind/index.tsx index a93e48dcb..2fddd401f 100644 --- a/docs/data/components/number-field/UnstyledNumberFieldIntroduction/tailwind/index.tsx +++ b/docs/data/components/number-field/UnstyledNumberFieldIntroduction/tailwind/index.tsx @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as BaseNumberField from '@base_ui/react/NumberField'; +import { NumberField as BaseNumberField } from '@base_ui/react/NumberField'; import { useTheme } from '@mui/system'; function classNames(...classes: Array) { diff --git a/docs/data/components/number-field/UnstyledNumberFieldScrub.js b/docs/data/components/number-field/UnstyledNumberFieldScrub.js index 164de5acf..e1a458e47 100644 --- a/docs/data/components/number-field/UnstyledNumberFieldScrub.js +++ b/docs/data/components/number-field/UnstyledNumberFieldScrub.js @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as BaseNumberField from '@base_ui/react/NumberField'; +import { NumberField as BaseNumberField } from '@base_ui/react/NumberField'; import { styled } from '@mui/system'; export default function UnstyledNumberFieldScrub() { diff --git a/docs/data/components/number-field/UnstyledNumberFieldScrub.tsx b/docs/data/components/number-field/UnstyledNumberFieldScrub.tsx index 164de5acf..e1a458e47 100644 --- a/docs/data/components/number-field/UnstyledNumberFieldScrub.tsx +++ b/docs/data/components/number-field/UnstyledNumberFieldScrub.tsx @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as BaseNumberField from '@base_ui/react/NumberField'; +import { NumberField as BaseNumberField } from '@base_ui/react/NumberField'; import { styled } from '@mui/system'; export default function UnstyledNumberFieldScrub() { diff --git a/docs/data/components/number-field/UnstyledNumberFieldWheelScrub.js b/docs/data/components/number-field/UnstyledNumberFieldWheelScrub.js index b0ef9a2b7..f452ec03a 100644 --- a/docs/data/components/number-field/UnstyledNumberFieldWheelScrub.js +++ b/docs/data/components/number-field/UnstyledNumberFieldWheelScrub.js @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as BaseNumberField from '@base_ui/react/NumberField'; +import { NumberField as BaseNumberField } from '@base_ui/react/NumberField'; import { styled } from '@mui/system'; export default function UnstyledNumberFieldWheelScrub() { diff --git a/docs/data/components/number-field/UnstyledNumberFieldWheelScrub.tsx b/docs/data/components/number-field/UnstyledNumberFieldWheelScrub.tsx index b0ef9a2b7..f452ec03a 100644 --- a/docs/data/components/number-field/UnstyledNumberFieldWheelScrub.tsx +++ b/docs/data/components/number-field/UnstyledNumberFieldWheelScrub.tsx @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as BaseNumberField from '@base_ui/react/NumberField'; +import { NumberField as BaseNumberField } from '@base_ui/react/NumberField'; import { styled } from '@mui/system'; export default function UnstyledNumberFieldWheelScrub() { diff --git a/docs/data/components/popover/UnstyledPopoverIntroduction/system/index.js b/docs/data/components/popover/UnstyledPopoverIntroduction/system/index.js index 38d2d2de2..dc7cdccd4 100644 --- a/docs/data/components/popover/UnstyledPopoverIntroduction/system/index.js +++ b/docs/data/components/popover/UnstyledPopoverIntroduction/system/index.js @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as Popover from '@base_ui/react/Popover'; +import { Popover } from '@base_ui/react/Popover'; import { styled } from '@mui/system'; export default function UnstyledPopoverIntroduction() { diff --git a/docs/data/components/popover/UnstyledPopoverIntroduction/system/index.tsx b/docs/data/components/popover/UnstyledPopoverIntroduction/system/index.tsx index 38d2d2de2..dc7cdccd4 100644 --- a/docs/data/components/popover/UnstyledPopoverIntroduction/system/index.tsx +++ b/docs/data/components/popover/UnstyledPopoverIntroduction/system/index.tsx @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as Popover from '@base_ui/react/Popover'; +import { Popover } from '@base_ui/react/Popover'; import { styled } from '@mui/system'; export default function UnstyledPopoverIntroduction() { diff --git a/docs/data/components/popover/UnstyledPopoverTransition.js b/docs/data/components/popover/UnstyledPopoverTransition.js index 5e50a7e09..b0af18359 100644 --- a/docs/data/components/popover/UnstyledPopoverTransition.js +++ b/docs/data/components/popover/UnstyledPopoverTransition.js @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as Popover from '@base_ui/react/Popover'; +import { Popover } from '@base_ui/react/Popover'; import { styled } from '@mui/system'; export default function UnstyledPopoverTransition() { diff --git a/docs/data/components/popover/UnstyledPopoverTransition.tsx b/docs/data/components/popover/UnstyledPopoverTransition.tsx index 5e50a7e09..b0af18359 100644 --- a/docs/data/components/popover/UnstyledPopoverTransition.tsx +++ b/docs/data/components/popover/UnstyledPopoverTransition.tsx @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as Popover from '@base_ui/react/Popover'; +import { Popover } from '@base_ui/react/Popover'; import { styled } from '@mui/system'; export default function UnstyledPopoverTransition() { diff --git a/docs/data/components/preview-card/UnstyledPreviewCardIntroduction/system/index.js b/docs/data/components/preview-card/UnstyledPreviewCardIntroduction/system/index.js index e7506c5c7..98e97754b 100644 --- a/docs/data/components/preview-card/UnstyledPreviewCardIntroduction/system/index.js +++ b/docs/data/components/preview-card/UnstyledPreviewCardIntroduction/system/index.js @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as PreviewCard from '@base_ui/react/PreviewCard'; +import { PreviewCard } from '@base_ui/react/PreviewCard'; import { styled } from '@mui/system'; export default function UnstyledPreviewCardIntroduction() { diff --git a/docs/data/components/preview-card/UnstyledPreviewCardIntroduction/system/index.tsx b/docs/data/components/preview-card/UnstyledPreviewCardIntroduction/system/index.tsx index e7506c5c7..98e97754b 100644 --- a/docs/data/components/preview-card/UnstyledPreviewCardIntroduction/system/index.tsx +++ b/docs/data/components/preview-card/UnstyledPreviewCardIntroduction/system/index.tsx @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as PreviewCard from '@base_ui/react/PreviewCard'; +import { PreviewCard } from '@base_ui/react/PreviewCard'; import { styled } from '@mui/system'; export default function UnstyledPreviewCardIntroduction() { diff --git a/docs/data/components/preview-card/UnstyledPreviewCardTransition.js b/docs/data/components/preview-card/UnstyledPreviewCardTransition.js index 346ba7917..0c40c7588 100644 --- a/docs/data/components/preview-card/UnstyledPreviewCardTransition.js +++ b/docs/data/components/preview-card/UnstyledPreviewCardTransition.js @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as PreviewCard from '@base_ui/react/PreviewCard'; +import { PreviewCard } from '@base_ui/react/PreviewCard'; import { styled } from '@mui/system'; export default function UnstyledPreviewCardTransition() { diff --git a/docs/data/components/preview-card/UnstyledPreviewCardTransition.tsx b/docs/data/components/preview-card/UnstyledPreviewCardTransition.tsx index 346ba7917..0c40c7588 100644 --- a/docs/data/components/preview-card/UnstyledPreviewCardTransition.tsx +++ b/docs/data/components/preview-card/UnstyledPreviewCardTransition.tsx @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as PreviewCard from '@base_ui/react/PreviewCard'; +import { PreviewCard } from '@base_ui/react/PreviewCard'; import { styled } from '@mui/system'; export default function UnstyledPreviewCardTransition() { diff --git a/docs/data/components/progress/IndeterminateProgress.js b/docs/data/components/progress/IndeterminateProgress.js index b3195b7a1..2b81c447f 100644 --- a/docs/data/components/progress/IndeterminateProgress.js +++ b/docs/data/components/progress/IndeterminateProgress.js @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as BaseProgress from '@base_ui/react/Progress'; +import { Progress as BaseProgress } from '@base_ui/react/Progress'; import { Box, styled, keyframes, css } from '@mui/system'; export default function IndeterminateProgress() { diff --git a/docs/data/components/progress/IndeterminateProgress.tsx b/docs/data/components/progress/IndeterminateProgress.tsx index b3195b7a1..2b81c447f 100644 --- a/docs/data/components/progress/IndeterminateProgress.tsx +++ b/docs/data/components/progress/IndeterminateProgress.tsx @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as BaseProgress from '@base_ui/react/Progress'; +import { Progress as BaseProgress } from '@base_ui/react/Progress'; import { Box, styled, keyframes, css } from '@mui/system'; export default function IndeterminateProgress() { diff --git a/docs/data/components/progress/RtlProgress.js b/docs/data/components/progress/RtlProgress.js index 1c95abdc8..6654e62b6 100644 --- a/docs/data/components/progress/RtlProgress.js +++ b/docs/data/components/progress/RtlProgress.js @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as BaseProgress from '@base_ui/react/Progress'; +import { Progress as BaseProgress } from '@base_ui/react/Progress'; import { Box, styled } from '@mui/system'; export default function RtlProgress() { diff --git a/docs/data/components/progress/RtlProgress.tsx b/docs/data/components/progress/RtlProgress.tsx index 1c95abdc8..6654e62b6 100644 --- a/docs/data/components/progress/RtlProgress.tsx +++ b/docs/data/components/progress/RtlProgress.tsx @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as BaseProgress from '@base_ui/react/Progress'; +import { Progress as BaseProgress } from '@base_ui/react/Progress'; import { Box, styled } from '@mui/system'; export default function RtlProgress() { diff --git a/docs/data/components/progress/UnstyledProgressIntroduction/css-modules/index.js b/docs/data/components/progress/UnstyledProgressIntroduction/css-modules/index.js index bee6da9c0..5a2c23b5a 100644 --- a/docs/data/components/progress/UnstyledProgressIntroduction/css-modules/index.js +++ b/docs/data/components/progress/UnstyledProgressIntroduction/css-modules/index.js @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; import { useTheme } from '@mui/system'; -import * as Progress from '@base_ui/react/Progress'; +import { Progress } from '@base_ui/react/Progress'; export default function UnstyledProgressIntroduction() { return ( diff --git a/docs/data/components/progress/UnstyledProgressIntroduction/css-modules/index.tsx b/docs/data/components/progress/UnstyledProgressIntroduction/css-modules/index.tsx index bee6da9c0..5a2c23b5a 100644 --- a/docs/data/components/progress/UnstyledProgressIntroduction/css-modules/index.tsx +++ b/docs/data/components/progress/UnstyledProgressIntroduction/css-modules/index.tsx @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; import { useTheme } from '@mui/system'; -import * as Progress from '@base_ui/react/Progress'; +import { Progress } from '@base_ui/react/Progress'; export default function UnstyledProgressIntroduction() { return ( diff --git a/docs/data/components/progress/UnstyledProgressIntroduction/system/index.js b/docs/data/components/progress/UnstyledProgressIntroduction/system/index.js index 750a30a67..435d7d43b 100644 --- a/docs/data/components/progress/UnstyledProgressIntroduction/system/index.js +++ b/docs/data/components/progress/UnstyledProgressIntroduction/system/index.js @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; import { styled, useTheme, Box } from '@mui/system'; -import * as BaseProgress from '@base_ui/react/Progress'; +import { Progress as BaseProgress } from '@base_ui/react/Progress'; export default function UnstyledProgressIntroduction() { // Replace this with your app logic for determining dark mode diff --git a/docs/data/components/progress/UnstyledProgressIntroduction/system/index.tsx b/docs/data/components/progress/UnstyledProgressIntroduction/system/index.tsx index 750a30a67..435d7d43b 100644 --- a/docs/data/components/progress/UnstyledProgressIntroduction/system/index.tsx +++ b/docs/data/components/progress/UnstyledProgressIntroduction/system/index.tsx @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; import { styled, useTheme, Box } from '@mui/system'; -import * as BaseProgress from '@base_ui/react/Progress'; +import { Progress as BaseProgress } from '@base_ui/react/Progress'; export default function UnstyledProgressIntroduction() { // Replace this with your app logic for determining dark mode diff --git a/docs/data/components/progress/UnstyledProgressIntroduction/tailwind/index.js b/docs/data/components/progress/UnstyledProgressIntroduction/tailwind/index.js index 65cdae0d4..41cc11ec5 100644 --- a/docs/data/components/progress/UnstyledProgressIntroduction/tailwind/index.js +++ b/docs/data/components/progress/UnstyledProgressIntroduction/tailwind/index.js @@ -2,7 +2,7 @@ import * as React from 'react'; import PropTypes from 'prop-types'; import { useTheme } from '@mui/system'; -import * as BaseProgress from '@base_ui/react/Progress'; +import { Progress as BaseProgress } from '@base_ui/react/Progress'; export default function UnstyledProgressIntroduction() { // Replace this with your app logic for determining dark mode diff --git a/docs/data/components/progress/UnstyledProgressIntroduction/tailwind/index.tsx b/docs/data/components/progress/UnstyledProgressIntroduction/tailwind/index.tsx index badde7161..650a4198d 100644 --- a/docs/data/components/progress/UnstyledProgressIntroduction/tailwind/index.tsx +++ b/docs/data/components/progress/UnstyledProgressIntroduction/tailwind/index.tsx @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; import { useTheme } from '@mui/system'; -import * as BaseProgress from '@base_ui/react/Progress'; +import { Progress as BaseProgress } from '@base_ui/react/Progress'; export default function UnstyledProgressIntroduction() { // Replace this with your app logic for determining dark mode diff --git a/docs/data/components/radio-group/UnstyledRadioGroupIntroduction/system/index.js b/docs/data/components/radio-group/UnstyledRadioGroupIntroduction/system/index.js index 37a96630a..f1e246848 100644 --- a/docs/data/components/radio-group/UnstyledRadioGroupIntroduction/system/index.js +++ b/docs/data/components/radio-group/UnstyledRadioGroupIntroduction/system/index.js @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; -import * as RadioGroup from '@base_ui/react/RadioGroup'; -import * as Radio from '@base_ui/react/Radio'; +import { RadioGroup } from '@base_ui/react/RadioGroup'; +import { Radio } from '@base_ui/react/Radio'; import { styled } from '@mui/system'; export default function UnstyledRadioGroupIntroduction() { diff --git a/docs/data/components/radio-group/UnstyledRadioGroupIntroduction/system/index.tsx b/docs/data/components/radio-group/UnstyledRadioGroupIntroduction/system/index.tsx index 37a96630a..f1e246848 100644 --- a/docs/data/components/radio-group/UnstyledRadioGroupIntroduction/system/index.tsx +++ b/docs/data/components/radio-group/UnstyledRadioGroupIntroduction/system/index.tsx @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; -import * as RadioGroup from '@base_ui/react/RadioGroup'; -import * as Radio from '@base_ui/react/Radio'; +import { RadioGroup } from '@base_ui/react/RadioGroup'; +import { Radio } from '@base_ui/react/Radio'; import { styled } from '@mui/system'; export default function UnstyledRadioGroupIntroduction() { diff --git a/docs/data/components/separator/SeparatorIntroduction.js b/docs/data/components/separator/SeparatorIntroduction.js index d22184c6d..fdacf2965 100644 --- a/docs/data/components/separator/SeparatorIntroduction.js +++ b/docs/data/components/separator/SeparatorIntroduction.js @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as Separator from '@base_ui/react/Separator'; +import { Separator } from '@base_ui/react/Separator'; import { styled } from '@mui/system'; export default function SeparatorIntroduction() { diff --git a/docs/data/components/separator/SeparatorIntroduction.tsx b/docs/data/components/separator/SeparatorIntroduction.tsx index d22184c6d..fdacf2965 100644 --- a/docs/data/components/separator/SeparatorIntroduction.tsx +++ b/docs/data/components/separator/SeparatorIntroduction.tsx @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as Separator from '@base_ui/react/Separator'; +import { Separator } from '@base_ui/react/Separator'; import { styled } from '@mui/system'; export default function SeparatorIntroduction() { diff --git a/docs/data/components/slider/RangeSlider.js b/docs/data/components/slider/RangeSlider.js index f8b56822b..43c1a0158 100644 --- a/docs/data/components/slider/RangeSlider.js +++ b/docs/data/components/slider/RangeSlider.js @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; import { styled, useTheme, Box } from '@mui/system'; -import * as BaseSlider from '@base_ui/react/Slider'; +import { Slider as BaseSlider } from '@base_ui/react/Slider'; export default function RangeSlider() { // Replace this with your app logic for determining dark mode diff --git a/docs/data/components/slider/RangeSlider.tsx b/docs/data/components/slider/RangeSlider.tsx index ddb0cdaba..53279eade 100644 --- a/docs/data/components/slider/RangeSlider.tsx +++ b/docs/data/components/slider/RangeSlider.tsx @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; import { styled, useTheme, Box } from '@mui/system'; -import * as BaseSlider from '@base_ui/react/Slider'; +import { Slider as BaseSlider } from '@base_ui/react/Slider'; export default function RangeSlider() { // Replace this with your app logic for determining dark mode diff --git a/docs/data/components/slider/RtlSlider.js b/docs/data/components/slider/RtlSlider.js index 13c3d16ca..472dce469 100644 --- a/docs/data/components/slider/RtlSlider.js +++ b/docs/data/components/slider/RtlSlider.js @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; import PropTypes from 'prop-types'; -import * as BaseSlider from '@base_ui/react/Slider'; +import { Slider as BaseSlider } from '@base_ui/react/Slider'; import { styled, useTheme, Box } from '@mui/system'; export default function RtlSlider() { diff --git a/docs/data/components/slider/RtlSlider.tsx b/docs/data/components/slider/RtlSlider.tsx index 62f0aea2d..31961f628 100644 --- a/docs/data/components/slider/RtlSlider.tsx +++ b/docs/data/components/slider/RtlSlider.tsx @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as BaseSlider from '@base_ui/react/Slider'; +import { Slider as BaseSlider } from '@base_ui/react/Slider'; import { styled, useTheme, Box } from '@mui/system'; export default function RtlSlider() { diff --git a/docs/data/components/slider/UnstyledSliderIntroduction/css-modules/index.js b/docs/data/components/slider/UnstyledSliderIntroduction/css-modules/index.js index 966ce832a..c5c0546f4 100644 --- a/docs/data/components/slider/UnstyledSliderIntroduction/css-modules/index.js +++ b/docs/data/components/slider/UnstyledSliderIntroduction/css-modules/index.js @@ -2,7 +2,7 @@ import * as React from 'react'; import PropTypes from 'prop-types'; import { useTheme } from '@mui/system'; -import * as Slider from '@base_ui/react/Slider'; +import { Slider } from '@base_ui/react/Slider'; export default function UnstyledSliderIntroduction() { // Replace this with your app logic for determining dark mode diff --git a/docs/data/components/slider/UnstyledSliderIntroduction/css-modules/index.tsx b/docs/data/components/slider/UnstyledSliderIntroduction/css-modules/index.tsx index d69cde9cf..a7ca9c845 100644 --- a/docs/data/components/slider/UnstyledSliderIntroduction/css-modules/index.tsx +++ b/docs/data/components/slider/UnstyledSliderIntroduction/css-modules/index.tsx @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; import { useTheme } from '@mui/system'; -import * as Slider from '@base_ui/react/Slider'; +import { Slider } from '@base_ui/react/Slider'; export default function UnstyledSliderIntroduction() { // Replace this with your app logic for determining dark mode diff --git a/docs/data/components/slider/UnstyledSliderIntroduction/system/index.js b/docs/data/components/slider/UnstyledSliderIntroduction/system/index.js index dc0b9eec0..61da914e5 100644 --- a/docs/data/components/slider/UnstyledSliderIntroduction/system/index.js +++ b/docs/data/components/slider/UnstyledSliderIntroduction/system/index.js @@ -2,7 +2,7 @@ import * as React from 'react'; import PropTypes from 'prop-types'; import { styled, useTheme, Box } from '@mui/system'; -import * as BaseSlider from '@base_ui/react/Slider'; +import { Slider as BaseSlider } from '@base_ui/react/Slider'; export default function UnstyledSliderIntroduction() { // Replace this with your app logic for determining dark mode diff --git a/docs/data/components/slider/UnstyledSliderIntroduction/system/index.tsx b/docs/data/components/slider/UnstyledSliderIntroduction/system/index.tsx index 4d971a0cd..3e07ad98a 100644 --- a/docs/data/components/slider/UnstyledSliderIntroduction/system/index.tsx +++ b/docs/data/components/slider/UnstyledSliderIntroduction/system/index.tsx @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; import { styled, useTheme, Box } from '@mui/system'; -import * as BaseSlider from '@base_ui/react/Slider'; +import { Slider as BaseSlider } from '@base_ui/react/Slider'; export default function UnstyledSliderIntroduction() { // Replace this with your app logic for determining dark mode diff --git a/docs/data/components/slider/UnstyledSliderIntroduction/tailwind/index.js b/docs/data/components/slider/UnstyledSliderIntroduction/tailwind/index.js index 5f1c30861..5e06ad386 100644 --- a/docs/data/components/slider/UnstyledSliderIntroduction/tailwind/index.js +++ b/docs/data/components/slider/UnstyledSliderIntroduction/tailwind/index.js @@ -2,7 +2,7 @@ import * as React from 'react'; import PropTypes from 'prop-types'; import { useTheme } from '@mui/system'; -import * as BaseSlider from '@base_ui/react/Slider'; +import { Slider as BaseSlider } from '@base_ui/react/Slider'; function classNames(...classes) { return classes.filter(Boolean).join(' '); diff --git a/docs/data/components/slider/UnstyledSliderIntroduction/tailwind/index.tsx b/docs/data/components/slider/UnstyledSliderIntroduction/tailwind/index.tsx index f079c3ad4..232b32436 100644 --- a/docs/data/components/slider/UnstyledSliderIntroduction/tailwind/index.tsx +++ b/docs/data/components/slider/UnstyledSliderIntroduction/tailwind/index.tsx @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; import { useTheme } from '@mui/system'; -import * as BaseSlider from '@base_ui/react/Slider'; +import { Slider as BaseSlider } from '@base_ui/react/Slider'; function classNames(...classes: Array) { return classes.filter(Boolean).join(' '); diff --git a/docs/data/components/slider/VerticalSlider.js b/docs/data/components/slider/VerticalSlider.js index 13c57c833..0548448e7 100644 --- a/docs/data/components/slider/VerticalSlider.js +++ b/docs/data/components/slider/VerticalSlider.js @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; import PropTypes from 'prop-types'; -import * as Slider from '@base_ui/react/Slider'; +import { Slider } from '@base_ui/react/Slider'; import { useTheme } from '@mui/system'; export default function VerticalSlider() { diff --git a/docs/data/components/slider/VerticalSlider.tsx b/docs/data/components/slider/VerticalSlider.tsx index a535eb341..e38e7c64a 100644 --- a/docs/data/components/slider/VerticalSlider.tsx +++ b/docs/data/components/slider/VerticalSlider.tsx @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as Slider from '@base_ui/react/Slider'; +import { Slider } from '@base_ui/react/Slider'; import { useTheme } from '@mui/system'; export default function VerticalSlider() { diff --git a/docs/data/components/switch/UnstyledSwitchIntroduction/css-modules/index.js b/docs/data/components/switch/UnstyledSwitchIntroduction/css-modules/index.js index d48f24dbe..3ad7b327d 100644 --- a/docs/data/components/switch/UnstyledSwitchIntroduction/css-modules/index.js +++ b/docs/data/components/switch/UnstyledSwitchIntroduction/css-modules/index.js @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as Switch from '@base_ui/react/Switch'; +import { Switch } from '@base_ui/react/Switch'; import classes from './styles.module.css'; export default function UnstyledSwitchIntroduction() { diff --git a/docs/data/components/switch/UnstyledSwitchIntroduction/css-modules/index.tsx b/docs/data/components/switch/UnstyledSwitchIntroduction/css-modules/index.tsx index d48f24dbe..3ad7b327d 100644 --- a/docs/data/components/switch/UnstyledSwitchIntroduction/css-modules/index.tsx +++ b/docs/data/components/switch/UnstyledSwitchIntroduction/css-modules/index.tsx @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as Switch from '@base_ui/react/Switch'; +import { Switch } from '@base_ui/react/Switch'; import classes from './styles.module.css'; export default function UnstyledSwitchIntroduction() { diff --git a/docs/data/components/switch/UnstyledSwitchIntroduction/system/index.js b/docs/data/components/switch/UnstyledSwitchIntroduction/system/index.js index 12d3ea815..c8ca0841b 100644 --- a/docs/data/components/switch/UnstyledSwitchIntroduction/system/index.js +++ b/docs/data/components/switch/UnstyledSwitchIntroduction/system/index.js @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; import { styled } from '@mui/system'; -import * as BaseSwitch from '@base_ui/react/Switch'; +import { Switch as BaseSwitch } from '@base_ui/react/Switch'; export default function UnstyledSwitchIntroduction() { return ( diff --git a/docs/data/components/switch/UnstyledSwitchIntroduction/system/index.tsx b/docs/data/components/switch/UnstyledSwitchIntroduction/system/index.tsx index 12d3ea815..c8ca0841b 100644 --- a/docs/data/components/switch/UnstyledSwitchIntroduction/system/index.tsx +++ b/docs/data/components/switch/UnstyledSwitchIntroduction/system/index.tsx @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; import { styled } from '@mui/system'; -import * as BaseSwitch from '@base_ui/react/Switch'; +import { Switch as BaseSwitch } from '@base_ui/react/Switch'; export default function UnstyledSwitchIntroduction() { return ( diff --git a/docs/data/components/switch/UnstyledSwitchIntroduction/tailwind/index.js b/docs/data/components/switch/UnstyledSwitchIntroduction/tailwind/index.js index 9343aef64..53e9b4b23 100644 --- a/docs/data/components/switch/UnstyledSwitchIntroduction/tailwind/index.js +++ b/docs/data/components/switch/UnstyledSwitchIntroduction/tailwind/index.js @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as BaseSwitch from '@base_ui/react/Switch'; +import { Switch as BaseSwitch } from '@base_ui/react/Switch'; import { useTheme } from '@mui/system'; function useIsDarkMode() { diff --git a/docs/data/components/switch/UnstyledSwitchIntroduction/tailwind/index.tsx b/docs/data/components/switch/UnstyledSwitchIntroduction/tailwind/index.tsx index d3c6a6a13..36874d892 100644 --- a/docs/data/components/switch/UnstyledSwitchIntroduction/tailwind/index.tsx +++ b/docs/data/components/switch/UnstyledSwitchIntroduction/tailwind/index.tsx @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as BaseSwitch from '@base_ui/react/Switch'; +import { Switch as BaseSwitch } from '@base_ui/react/Switch'; import { useTheme } from '@mui/system'; function useIsDarkMode() { diff --git a/docs/data/components/tabs/IndicatorBubble.js b/docs/data/components/tabs/IndicatorBubble.js index 6866800e4..80ce1ffbd 100644 --- a/docs/data/components/tabs/IndicatorBubble.js +++ b/docs/data/components/tabs/IndicatorBubble.js @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; import { css, styled } from '@mui/system'; -import * as BaseTabs from '@base_ui/react/Tabs'; +import { Tabs as BaseTabs } from '@base_ui/react/Tabs'; export default function IndicatorBubble() { return ( diff --git a/docs/data/components/tabs/IndicatorBubble.tsx b/docs/data/components/tabs/IndicatorBubble.tsx index 6866800e4..80ce1ffbd 100644 --- a/docs/data/components/tabs/IndicatorBubble.tsx +++ b/docs/data/components/tabs/IndicatorBubble.tsx @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; import { css, styled } from '@mui/system'; -import * as BaseTabs from '@base_ui/react/Tabs'; +import { Tabs as BaseTabs } from '@base_ui/react/Tabs'; export default function IndicatorBubble() { return ( diff --git a/docs/data/components/tabs/IndicatorUnderline.js b/docs/data/components/tabs/IndicatorUnderline.js index cf78e34dd..441448e03 100644 --- a/docs/data/components/tabs/IndicatorUnderline.js +++ b/docs/data/components/tabs/IndicatorUnderline.js @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; import { css, styled } from '@mui/system'; -import * as BaseTabs from '@base_ui/react/Tabs'; +import { Tabs as BaseTabs } from '@base_ui/react/Tabs'; export default function IndicatorUnderline() { return ( diff --git a/docs/data/components/tabs/IndicatorUnderline.tsx b/docs/data/components/tabs/IndicatorUnderline.tsx index cf78e34dd..441448e03 100644 --- a/docs/data/components/tabs/IndicatorUnderline.tsx +++ b/docs/data/components/tabs/IndicatorUnderline.tsx @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; import { css, styled } from '@mui/system'; -import * as BaseTabs from '@base_ui/react/Tabs'; +import { Tabs as BaseTabs } from '@base_ui/react/Tabs'; export default function IndicatorUnderline() { return ( diff --git a/docs/data/components/tabs/KeyboardNavigation.js b/docs/data/components/tabs/KeyboardNavigation.js index 163f1229c..47d402c90 100644 --- a/docs/data/components/tabs/KeyboardNavigation.js +++ b/docs/data/components/tabs/KeyboardNavigation.js @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; import { styled } from '@mui/system'; -import * as Tabs from '@base_ui/react/Tabs'; +import { Tabs } from '@base_ui/react/Tabs'; export default function KeyboardNavigation() { return ( diff --git a/docs/data/components/tabs/KeyboardNavigation.tsx b/docs/data/components/tabs/KeyboardNavigation.tsx index 163f1229c..47d402c90 100644 --- a/docs/data/components/tabs/KeyboardNavigation.tsx +++ b/docs/data/components/tabs/KeyboardNavigation.tsx @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; import { styled } from '@mui/system'; -import * as Tabs from '@base_ui/react/Tabs'; +import { Tabs } from '@base_ui/react/Tabs'; export default function KeyboardNavigation() { return ( diff --git a/docs/data/components/tabs/UnstyledTabsIntroduction/css-modules/index.js b/docs/data/components/tabs/UnstyledTabsIntroduction/css-modules/index.js index 1044ae513..ba96422e6 100644 --- a/docs/data/components/tabs/UnstyledTabsIntroduction/css-modules/index.js +++ b/docs/data/components/tabs/UnstyledTabsIntroduction/css-modules/index.js @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; import { useTheme } from '@mui/system'; -import * as Tabs from '@base_ui/react/Tabs'; +import { Tabs } from '@base_ui/react/Tabs'; export default function UnstyledTabsIntroduction() { return ( diff --git a/docs/data/components/tabs/UnstyledTabsIntroduction/css-modules/index.tsx b/docs/data/components/tabs/UnstyledTabsIntroduction/css-modules/index.tsx index 1044ae513..ba96422e6 100644 --- a/docs/data/components/tabs/UnstyledTabsIntroduction/css-modules/index.tsx +++ b/docs/data/components/tabs/UnstyledTabsIntroduction/css-modules/index.tsx @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; import { useTheme } from '@mui/system'; -import * as Tabs from '@base_ui/react/Tabs'; +import { Tabs } from '@base_ui/react/Tabs'; export default function UnstyledTabsIntroduction() { return ( diff --git a/docs/data/components/tabs/UnstyledTabsIntroduction/system/index.js b/docs/data/components/tabs/UnstyledTabsIntroduction/system/index.js index aea0b9744..021c449cb 100644 --- a/docs/data/components/tabs/UnstyledTabsIntroduction/system/index.js +++ b/docs/data/components/tabs/UnstyledTabsIntroduction/system/index.js @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; import { styled } from '@mui/system'; -import * as Tabs from '@base_ui/react/Tabs'; +import { Tabs } from '@base_ui/react/Tabs'; export default function UnstyledTabsIntroduction() { return ( diff --git a/docs/data/components/tabs/UnstyledTabsIntroduction/system/index.tsx b/docs/data/components/tabs/UnstyledTabsIntroduction/system/index.tsx index aea0b9744..021c449cb 100644 --- a/docs/data/components/tabs/UnstyledTabsIntroduction/system/index.tsx +++ b/docs/data/components/tabs/UnstyledTabsIntroduction/system/index.tsx @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; import { styled } from '@mui/system'; -import * as Tabs from '@base_ui/react/Tabs'; +import { Tabs } from '@base_ui/react/Tabs'; export default function UnstyledTabsIntroduction() { return ( diff --git a/docs/data/components/tabs/UnstyledTabsIntroduction/tailwind/index.js b/docs/data/components/tabs/UnstyledTabsIntroduction/tailwind/index.js index d8bd50d5b..fe9fc5625 100644 --- a/docs/data/components/tabs/UnstyledTabsIntroduction/tailwind/index.js +++ b/docs/data/components/tabs/UnstyledTabsIntroduction/tailwind/index.js @@ -2,7 +2,7 @@ import * as React from 'react'; import PropTypes from 'prop-types'; import clsx from 'clsx'; -import * as Tabs from '@base_ui/react/Tabs'; +import { Tabs } from '@base_ui/react/Tabs'; import { useTheme } from '@mui/system'; function useIsDarkMode() { diff --git a/docs/data/components/tabs/UnstyledTabsIntroduction/tailwind/index.tsx b/docs/data/components/tabs/UnstyledTabsIntroduction/tailwind/index.tsx index 92957ad45..609491d86 100644 --- a/docs/data/components/tabs/UnstyledTabsIntroduction/tailwind/index.tsx +++ b/docs/data/components/tabs/UnstyledTabsIntroduction/tailwind/index.tsx @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; import clsx from 'clsx'; -import * as Tabs from '@base_ui/react/Tabs'; +import { Tabs } from '@base_ui/react/Tabs'; import { useTheme } from '@mui/system'; function useIsDarkMode() { diff --git a/docs/data/components/tabs/UnstyledTabsRouting.js b/docs/data/components/tabs/UnstyledTabsRouting.js index 5bd42b9d8..5782a0785 100644 --- a/docs/data/components/tabs/UnstyledTabsRouting.js +++ b/docs/data/components/tabs/UnstyledTabsRouting.js @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; import PropTypes from 'prop-types'; -import * as Tabs from '@base_ui/react/Tabs'; +import { Tabs } from '@base_ui/react/Tabs'; import { MemoryRouter, Route, diff --git a/docs/data/components/tabs/UnstyledTabsRouting.tsx b/docs/data/components/tabs/UnstyledTabsRouting.tsx index fff226d17..0ff86ac06 100644 --- a/docs/data/components/tabs/UnstyledTabsRouting.tsx +++ b/docs/data/components/tabs/UnstyledTabsRouting.tsx @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as Tabs from '@base_ui/react/Tabs'; +import { Tabs } from '@base_ui/react/Tabs'; import { MemoryRouter, Route, diff --git a/docs/data/components/tooltip/UnstyledTooltipDelayGroup.js b/docs/data/components/tooltip/UnstyledTooltipDelayGroup.js index cfe835f23..e886d41b7 100644 --- a/docs/data/components/tooltip/UnstyledTooltipDelayGroup.js +++ b/docs/data/components/tooltip/UnstyledTooltipDelayGroup.js @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as Tooltip from '@base_ui/react/Tooltip'; +import { Tooltip } from '@base_ui/react/Tooltip'; import { styled } from '@mui/system'; export default function UnstyledTooltipDelayGroup() { diff --git a/docs/data/components/tooltip/UnstyledTooltipDelayGroup.tsx b/docs/data/components/tooltip/UnstyledTooltipDelayGroup.tsx index cfe835f23..e886d41b7 100644 --- a/docs/data/components/tooltip/UnstyledTooltipDelayGroup.tsx +++ b/docs/data/components/tooltip/UnstyledTooltipDelayGroup.tsx @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as Tooltip from '@base_ui/react/Tooltip'; +import { Tooltip } from '@base_ui/react/Tooltip'; import { styled } from '@mui/system'; export default function UnstyledTooltipDelayGroup() { diff --git a/docs/data/components/tooltip/UnstyledTooltipFollowCursor.js b/docs/data/components/tooltip/UnstyledTooltipFollowCursor.js index 1d8e8265a..cd2f93ed0 100644 --- a/docs/data/components/tooltip/UnstyledTooltipFollowCursor.js +++ b/docs/data/components/tooltip/UnstyledTooltipFollowCursor.js @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as Tooltip from '@base_ui/react/Tooltip'; +import { Tooltip } from '@base_ui/react/Tooltip'; import { styled } from '@mui/system'; export default function UnstyledTooltipFollowCursor() { diff --git a/docs/data/components/tooltip/UnstyledTooltipFollowCursor.tsx b/docs/data/components/tooltip/UnstyledTooltipFollowCursor.tsx index 1d8e8265a..cd2f93ed0 100644 --- a/docs/data/components/tooltip/UnstyledTooltipFollowCursor.tsx +++ b/docs/data/components/tooltip/UnstyledTooltipFollowCursor.tsx @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as Tooltip from '@base_ui/react/Tooltip'; +import { Tooltip } from '@base_ui/react/Tooltip'; import { styled } from '@mui/system'; export default function UnstyledTooltipFollowCursor() { diff --git a/docs/data/components/tooltip/UnstyledTooltipIntroduction/system/index.js b/docs/data/components/tooltip/UnstyledTooltipIntroduction/system/index.js index 6d2492f1c..f729f3763 100644 --- a/docs/data/components/tooltip/UnstyledTooltipIntroduction/system/index.js +++ b/docs/data/components/tooltip/UnstyledTooltipIntroduction/system/index.js @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as Tooltip from '@base_ui/react/Tooltip'; +import { Tooltip } from '@base_ui/react/Tooltip'; import { styled } from '@mui/system'; export default function UnstyledTooltipIntroduction() { diff --git a/docs/data/components/tooltip/UnstyledTooltipIntroduction/system/index.tsx b/docs/data/components/tooltip/UnstyledTooltipIntroduction/system/index.tsx index 6d2492f1c..f729f3763 100644 --- a/docs/data/components/tooltip/UnstyledTooltipIntroduction/system/index.tsx +++ b/docs/data/components/tooltip/UnstyledTooltipIntroduction/system/index.tsx @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as Tooltip from '@base_ui/react/Tooltip'; +import { Tooltip } from '@base_ui/react/Tooltip'; import { styled } from '@mui/system'; export default function UnstyledTooltipIntroduction() { diff --git a/docs/data/components/tooltip/UnstyledTooltipTransition.js b/docs/data/components/tooltip/UnstyledTooltipTransition.js index 1ac008c3d..d07593a93 100644 --- a/docs/data/components/tooltip/UnstyledTooltipTransition.js +++ b/docs/data/components/tooltip/UnstyledTooltipTransition.js @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as Tooltip from '@base_ui/react/Tooltip'; +import { Tooltip } from '@base_ui/react/Tooltip'; import { styled } from '@mui/system'; export default function UnstyledTooltipTransition() { diff --git a/docs/data/components/tooltip/UnstyledTooltipTransition.tsx b/docs/data/components/tooltip/UnstyledTooltipTransition.tsx index 1ac008c3d..d07593a93 100644 --- a/docs/data/components/tooltip/UnstyledTooltipTransition.tsx +++ b/docs/data/components/tooltip/UnstyledTooltipTransition.tsx @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as Tooltip from '@base_ui/react/Tooltip'; +import { Tooltip } from '@base_ui/react/Tooltip'; import { styled } from '@mui/system'; export default function UnstyledTooltipTransition() { diff --git a/docs/data/getting-started/accessibility/FocusRing.js b/docs/data/getting-started/accessibility/FocusRing.js index d115f561c..24d3c25be 100644 --- a/docs/data/getting-started/accessibility/FocusRing.js +++ b/docs/data/getting-started/accessibility/FocusRing.js @@ -1,6 +1,6 @@ import * as React from 'react'; import { styled, alpha, Box } from '@mui/system'; -import * as BaseSlider from '@base_ui/react/Slider'; +import { Slider as BaseSlider } from '@base_ui/react/Slider'; export default function FocusRing() { return ( diff --git a/docs/data/getting-started/accessibility/FocusRing.tsx b/docs/data/getting-started/accessibility/FocusRing.tsx index d115f561c..24d3c25be 100644 --- a/docs/data/getting-started/accessibility/FocusRing.tsx +++ b/docs/data/getting-started/accessibility/FocusRing.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import { styled, alpha, Box } from '@mui/system'; -import * as BaseSlider from '@base_ui/react/Slider'; +import { Slider as BaseSlider } from '@base_ui/react/Slider'; export default function FocusRing() { return ( diff --git a/docs/src/blocks/PackageManagerSnippet/PackageManagerSnippetCode.tsx b/docs/src/blocks/PackageManagerSnippet/PackageManagerSnippetCode.tsx index e2d74a1f1..1fd44aa06 100644 --- a/docs/src/blocks/PackageManagerSnippet/PackageManagerSnippetCode.tsx +++ b/docs/src/blocks/PackageManagerSnippet/PackageManagerSnippetCode.tsx @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as Tabs from '@base_ui/react/Tabs'; +import { Tabs } from '@base_ui/react/Tabs'; export function PackageManagerSnippetCode(props: PackageManagerSnippetCode.Props) { const { value, children } = props; diff --git a/docs/src/blocks/PackageManagerSnippet/PackageManagerSnippetRoot.tsx b/docs/src/blocks/PackageManagerSnippet/PackageManagerSnippetRoot.tsx index a9d8e6c23..cd230bc1c 100644 --- a/docs/src/blocks/PackageManagerSnippet/PackageManagerSnippetRoot.tsx +++ b/docs/src/blocks/PackageManagerSnippet/PackageManagerSnippetRoot.tsx @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as Tabs from '@base_ui/react/Tabs'; +import { Tabs } from '@base_ui/react/Tabs'; // eslint-disable-next-line no-restricted-imports import { useEnhancedEffect } from '@base_ui/react/utils/useEnhancedEffect'; import { usePackageManagerSnippetContext } from './PackageManagerSnippetProvider'; diff --git a/docs/src/components/DocsVersionSelector.tsx b/docs/src/components/DocsVersionSelector.tsx index f1bb24dea..9ec9fdd78 100644 --- a/docs/src/components/DocsVersionSelector.tsx +++ b/docs/src/components/DocsVersionSelector.tsx @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; import { SelectIcon } from 'docs-base/src/icons/Select'; -import * as Menu from '@base_ui/react/Menu'; +import { Menu } from '@base_ui/react/Menu'; import classes from './DocsVersionSelector.module.css'; export interface DocumentationVersion { diff --git a/docs/src/components/content/InstallationInstructions.tsx b/docs/src/components/content/InstallationInstructions.tsx index c7f5bfcdb..63d9e1f19 100644 --- a/docs/src/components/content/InstallationInstructions.tsx +++ b/docs/src/components/content/InstallationInstructions.tsx @@ -27,7 +27,7 @@ export function InstallationInstructions(props: InstallationInstructionsProps) {

Once you have the package installed, import the component.

         {componentNames
-          .map((name) => `import * as ${name} from '@base_ui/react/${name}';`)
+          .map((name) => `import { ${name} } from '@base_ui/react/${name}';`)
           .join('\n')}
       
diff --git a/docs/src/components/demo/Demo.tsx b/docs/src/components/demo/Demo.tsx index cfeb7b6a8..519e82adb 100644 --- a/docs/src/components/demo/Demo.tsx +++ b/docs/src/components/demo/Demo.tsx @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; import clsx from 'clsx'; -import * as Collapsible from '@base_ui/react/Collapsible'; +import { Collapsible } from '@base_ui/react/Collapsible'; import { ErrorBoundary } from 'react-error-boundary'; import * as BaseDemo from 'docs-base/src/blocks/Demo'; import { CopyIcon } from 'docs-base/src/icons/Copy'; diff --git a/docs/src/components/demo/DemoFileSelector.tsx b/docs/src/components/demo/DemoFileSelector.tsx index c15610dc3..ad9bc98b3 100644 --- a/docs/src/components/demo/DemoFileSelector.tsx +++ b/docs/src/components/demo/DemoFileSelector.tsx @@ -2,7 +2,7 @@ import * as React from 'react'; import clsx from 'clsx'; import { DemoContext } from 'docs-base/src/blocks/Demo'; -import * as Tabs from '@base_ui/react/Tabs'; +import { Tabs } from '@base_ui/react/Tabs'; import classes from './DemoFileSelector.module.css'; export interface DemoFileSelectorProps { diff --git a/docs/src/design-system/Tooltip.tsx b/docs/src/design-system/Tooltip.tsx index c18a043e4..c887c66de 100644 --- a/docs/src/design-system/Tooltip.tsx +++ b/docs/src/design-system/Tooltip.tsx @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as BaseTooltip from '@base_ui/react/Tooltip'; +import { Tooltip as BaseTooltip } from '@base_ui/react/Tooltip'; import classes from './Tooltip.module.css'; export function Tooltip(props: Tooltip.Props) { diff --git a/packages/mui-base/src/AlertDialog/Backdrop/AlertDialogBackdrop.test.tsx b/packages/mui-base/src/AlertDialog/Backdrop/AlertDialogBackdrop.test.tsx index 323a65516..dc7e7ebc3 100644 --- a/packages/mui-base/src/AlertDialog/Backdrop/AlertDialogBackdrop.test.tsx +++ b/packages/mui-base/src/AlertDialog/Backdrop/AlertDialogBackdrop.test.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import { expect } from 'chai'; -import * as AlertDialog from '@base_ui/react/AlertDialog'; +import { AlertDialog } from '@base_ui/react/AlertDialog'; import { createRenderer, describeConformance } from '#test-utils'; describe('', () => { diff --git a/packages/mui-base/src/AlertDialog/Close/AlertDialogClose.test.tsx b/packages/mui-base/src/AlertDialog/Close/AlertDialogClose.test.tsx index 65f4bba90..7490ada7a 100644 --- a/packages/mui-base/src/AlertDialog/Close/AlertDialogClose.test.tsx +++ b/packages/mui-base/src/AlertDialog/Close/AlertDialogClose.test.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import * as AlertDialog from '@base_ui/react/AlertDialog'; +import { AlertDialog } from '@base_ui/react/AlertDialog'; import { createRenderer, describeConformance } from '#test-utils'; describe('', () => { diff --git a/packages/mui-base/src/AlertDialog/Description/AlertDialogDescription.test.tsx b/packages/mui-base/src/AlertDialog/Description/AlertDialogDescription.test.tsx index da704e271..802229101 100644 --- a/packages/mui-base/src/AlertDialog/Description/AlertDialogDescription.test.tsx +++ b/packages/mui-base/src/AlertDialog/Description/AlertDialogDescription.test.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import * as AlertDialog from '@base_ui/react/AlertDialog'; +import { AlertDialog } from '@base_ui/react/AlertDialog'; import { createRenderer, describeConformance } from '#test-utils'; describe('', () => { diff --git a/packages/mui-base/src/AlertDialog/Popup/AlertDialogPopup.test.tsx b/packages/mui-base/src/AlertDialog/Popup/AlertDialogPopup.test.tsx index 40fec9672..e11cd0b2a 100644 --- a/packages/mui-base/src/AlertDialog/Popup/AlertDialogPopup.test.tsx +++ b/packages/mui-base/src/AlertDialog/Popup/AlertDialogPopup.test.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import { expect } from 'chai'; -import * as AlertDialog from '@base_ui/react/AlertDialog'; +import { AlertDialog } from '@base_ui/react/AlertDialog'; import { createRenderer, describeConformance } from '#test-utils'; describe('', () => { diff --git a/packages/mui-base/src/AlertDialog/Title/AlertDialogTitle.test.tsx b/packages/mui-base/src/AlertDialog/Title/AlertDialogTitle.test.tsx index 44ba27380..d2711e623 100644 --- a/packages/mui-base/src/AlertDialog/Title/AlertDialogTitle.test.tsx +++ b/packages/mui-base/src/AlertDialog/Title/AlertDialogTitle.test.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import * as AlertDialog from '@base_ui/react/AlertDialog'; +import { AlertDialog } from '@base_ui/react/AlertDialog'; import { createRenderer, describeConformance } from '#test-utils'; describe('', () => { diff --git a/packages/mui-base/src/AlertDialog/Trigger/AlertDialogTrigger.test.tsx b/packages/mui-base/src/AlertDialog/Trigger/AlertDialogTrigger.test.tsx index c06bb9ea5..a4dc6cc12 100644 --- a/packages/mui-base/src/AlertDialog/Trigger/AlertDialogTrigger.test.tsx +++ b/packages/mui-base/src/AlertDialog/Trigger/AlertDialogTrigger.test.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import * as AlertDialog from '@base_ui/react/AlertDialog'; +import { AlertDialog } from '@base_ui/react/AlertDialog'; import { createRenderer, describeConformance } from '#test-utils'; describe('', () => { diff --git a/packages/mui-base/src/AlertDialog/index.barrel.ts b/packages/mui-base/src/AlertDialog/index.barrel.ts deleted file mode 100644 index 281822c58..000000000 --- a/packages/mui-base/src/AlertDialog/index.barrel.ts +++ /dev/null @@ -1,7 +0,0 @@ -export { AlertDialogBackdrop } from './Backdrop/AlertDialogBackdrop'; -export { AlertDialogClose } from './Close/AlertDialogClose'; -export { AlertDialogDescription } from './Description/AlertDialogDescription'; -export { AlertDialogPopup } from './Popup/AlertDialogPopup'; -export { AlertDialogRoot } from './Root/AlertDialogRoot'; -export { AlertDialogTitle } from './Title/AlertDialogTitle'; -export { AlertDialogTrigger } from './Trigger/AlertDialogTrigger'; diff --git a/packages/mui-base/src/AlertDialog/index.parts.ts b/packages/mui-base/src/AlertDialog/index.parts.ts new file mode 100644 index 000000000..ad0f1a228 --- /dev/null +++ b/packages/mui-base/src/AlertDialog/index.parts.ts @@ -0,0 +1,7 @@ +export { AlertDialogBackdrop as Backdrop } from './Backdrop/AlertDialogBackdrop'; +export { AlertDialogClose as Close } from './Close/AlertDialogClose'; +export { AlertDialogDescription as Description } from './Description/AlertDialogDescription'; +export { AlertDialogPopup as Popup } from './Popup/AlertDialogPopup'; +export { AlertDialogRoot as Root } from './Root/AlertDialogRoot'; +export { AlertDialogTitle as Title } from './Title/AlertDialogTitle'; +export { AlertDialogTrigger as Trigger } from './Trigger/AlertDialogTrigger'; diff --git a/packages/mui-base/src/AlertDialog/index.ts b/packages/mui-base/src/AlertDialog/index.ts index ad0f1a228..766a0ca54 100644 --- a/packages/mui-base/src/AlertDialog/index.ts +++ b/packages/mui-base/src/AlertDialog/index.ts @@ -1,7 +1 @@ -export { AlertDialogBackdrop as Backdrop } from './Backdrop/AlertDialogBackdrop'; -export { AlertDialogClose as Close } from './Close/AlertDialogClose'; -export { AlertDialogDescription as Description } from './Description/AlertDialogDescription'; -export { AlertDialogPopup as Popup } from './Popup/AlertDialogPopup'; -export { AlertDialogRoot as Root } from './Root/AlertDialogRoot'; -export { AlertDialogTitle as Title } from './Title/AlertDialogTitle'; -export { AlertDialogTrigger as Trigger } from './Trigger/AlertDialogTrigger'; +export * as AlertDialog from './index.parts'; diff --git a/packages/mui-base/src/Checkbox/Indicator/CheckboxIndicator.test.tsx b/packages/mui-base/src/Checkbox/Indicator/CheckboxIndicator.test.tsx index 7dbca304d..1bcc780c2 100644 --- a/packages/mui-base/src/Checkbox/Indicator/CheckboxIndicator.test.tsx +++ b/packages/mui-base/src/Checkbox/Indicator/CheckboxIndicator.test.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import { expect } from 'chai'; -import * as Checkbox from '@base_ui/react/Checkbox'; +import { Checkbox } from '@base_ui/react/Checkbox'; import { createRenderer, describeConformance } from '#test-utils'; import { CheckboxRootContext } from '../Root/CheckboxRootContext'; diff --git a/packages/mui-base/src/Checkbox/Root/CheckboxRoot.test.tsx b/packages/mui-base/src/Checkbox/Root/CheckboxRoot.test.tsx index 169a0f38a..40a9eccbe 100644 --- a/packages/mui-base/src/Checkbox/Root/CheckboxRoot.test.tsx +++ b/packages/mui-base/src/Checkbox/Root/CheckboxRoot.test.tsx @@ -2,7 +2,7 @@ import * as React from 'react'; import { expect } from 'chai'; import { spy } from 'sinon'; import { act, fireEvent } from '@mui/internal-test-utils'; -import * as Checkbox from '@base_ui/react/Checkbox'; +import { Checkbox } from '@base_ui/react/Checkbox'; import { createRenderer, describeConformance } from '#test-utils'; const isJSDOM = /jsdom/.test(window.navigator.userAgent); diff --git a/packages/mui-base/src/Checkbox/index.barrel.ts b/packages/mui-base/src/Checkbox/index.barrel.ts deleted file mode 100644 index 5a27a441d..000000000 --- a/packages/mui-base/src/Checkbox/index.barrel.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { CheckboxRoot } from './Root/CheckboxRoot'; -export { CheckboxIndicator } from './Indicator/CheckboxIndicator'; diff --git a/packages/mui-base/src/Checkbox/index.parts.ts b/packages/mui-base/src/Checkbox/index.parts.ts new file mode 100644 index 000000000..c046f6b44 --- /dev/null +++ b/packages/mui-base/src/Checkbox/index.parts.ts @@ -0,0 +1,2 @@ +export { CheckboxRoot as Root } from './Root/CheckboxRoot'; +export { CheckboxIndicator as Indicator } from './Indicator/CheckboxIndicator'; diff --git a/packages/mui-base/src/Checkbox/index.ts b/packages/mui-base/src/Checkbox/index.ts index c046f6b44..4e96104ea 100644 --- a/packages/mui-base/src/Checkbox/index.ts +++ b/packages/mui-base/src/Checkbox/index.ts @@ -1,2 +1 @@ -export { CheckboxRoot as Root } from './Root/CheckboxRoot'; -export { CheckboxIndicator as Indicator } from './Indicator/CheckboxIndicator'; +export * as Checkbox from './index.parts'; diff --git a/packages/mui-base/src/CheckboxGroup/Parent/useCheckboxGroupParent.test.tsx b/packages/mui-base/src/CheckboxGroup/Parent/useCheckboxGroupParent.test.tsx index a3ae0e9fc..98cb90bfd 100644 --- a/packages/mui-base/src/CheckboxGroup/Parent/useCheckboxGroupParent.test.tsx +++ b/packages/mui-base/src/CheckboxGroup/Parent/useCheckboxGroupParent.test.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import { createRenderer, fireEvent, screen } from '@mui/internal-test-utils'; -import * as CheckboxGroup from '@base_ui/react/CheckboxGroup'; -import * as Checkbox from '@base_ui/react/Checkbox'; +import { CheckboxGroup } from '@base_ui/react/CheckboxGroup'; +import { Checkbox } from '@base_ui/react/Checkbox'; import { expect } from 'chai'; describe('useCheckboxGroupParent', () => { diff --git a/packages/mui-base/src/CheckboxGroup/Root/CheckboxGroupRoot.test.tsx b/packages/mui-base/src/CheckboxGroup/Root/CheckboxGroupRoot.test.tsx index 402769c6a..e7011b524 100644 --- a/packages/mui-base/src/CheckboxGroup/Root/CheckboxGroupRoot.test.tsx +++ b/packages/mui-base/src/CheckboxGroup/Root/CheckboxGroupRoot.test.tsx @@ -1,8 +1,8 @@ import * as React from 'react'; import { expect } from 'chai'; import { createRenderer, screen, fireEvent } from '@mui/internal-test-utils'; -import * as CheckboxGroup from '@base_ui/react/CheckboxGroup'; -import * as Checkbox from '@base_ui/react/Checkbox'; +import { CheckboxGroup } from '@base_ui/react/CheckboxGroup'; +import { Checkbox } from '@base_ui/react/Checkbox'; import { describeConformance } from '../../../test/describeConformance'; describe('', () => { diff --git a/packages/mui-base/src/CheckboxGroup/index.barrel.ts b/packages/mui-base/src/CheckboxGroup/index.barrel.ts deleted file mode 100644 index 2f4786b2a..000000000 --- a/packages/mui-base/src/CheckboxGroup/index.barrel.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './Root/CheckboxGroupRoot'; diff --git a/packages/mui-base/src/CheckboxGroup/index.parts.ts b/packages/mui-base/src/CheckboxGroup/index.parts.ts new file mode 100644 index 000000000..dd08fe5b4 --- /dev/null +++ b/packages/mui-base/src/CheckboxGroup/index.parts.ts @@ -0,0 +1 @@ +export { CheckboxGroupRoot as Root } from './Root/CheckboxGroupRoot'; diff --git a/packages/mui-base/src/CheckboxGroup/index.ts b/packages/mui-base/src/CheckboxGroup/index.ts index dd08fe5b4..da7ae148d 100644 --- a/packages/mui-base/src/CheckboxGroup/index.ts +++ b/packages/mui-base/src/CheckboxGroup/index.ts @@ -1 +1 @@ -export { CheckboxGroupRoot as Root } from './Root/CheckboxGroupRoot'; +export * as CheckboxGroup from './index.parts'; diff --git a/packages/mui-base/src/Collapsible/Content/CollapsibleContent.test.tsx b/packages/mui-base/src/Collapsible/Content/CollapsibleContent.test.tsx index 2fa98e940..435562e03 100644 --- a/packages/mui-base/src/Collapsible/Content/CollapsibleContent.test.tsx +++ b/packages/mui-base/src/Collapsible/Content/CollapsibleContent.test.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import { createRenderer } from '@mui/internal-test-utils'; -import * as Collapsible from '@base_ui/react/Collapsible'; -import { CollapsibleContext } from '@base_ui/react/Collapsible'; +import { Collapsible } from '@base_ui/react/Collapsible'; +import { CollapsibleContext } from '../Root/CollapsibleContext'; import { describeConformance } from '../../../test/describeConformance'; const contextValue: Collapsible.Root.Context = { diff --git a/packages/mui-base/src/Collapsible/Root/CollapsibleRoot.test.tsx b/packages/mui-base/src/Collapsible/Root/CollapsibleRoot.test.tsx index 6c0bae0ca..770e2a69e 100644 --- a/packages/mui-base/src/Collapsible/Root/CollapsibleRoot.test.tsx +++ b/packages/mui-base/src/Collapsible/Root/CollapsibleRoot.test.tsx @@ -3,7 +3,7 @@ import * as React from 'react'; import { expect } from 'chai'; import { spy } from 'sinon'; import { createRenderer, act } from '@mui/internal-test-utils'; -import * as Collapsible from '@base_ui/react/Collapsible'; +import { Collapsible } from '@base_ui/react/Collapsible'; import { describeConformance } from '../../../test/describeConformance'; describe('', () => { diff --git a/packages/mui-base/src/Collapsible/Trigger/CollapsibleTrigger.test.tsx b/packages/mui-base/src/Collapsible/Trigger/CollapsibleTrigger.test.tsx index 13ffe3567..0e7a77d5d 100644 --- a/packages/mui-base/src/Collapsible/Trigger/CollapsibleTrigger.test.tsx +++ b/packages/mui-base/src/Collapsible/Trigger/CollapsibleTrigger.test.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import { createRenderer } from '@mui/internal-test-utils'; -import * as Collapsible from '@base_ui/react/Collapsible'; -import { CollapsibleContext } from '@base_ui/react/Collapsible'; +import { Collapsible } from '@base_ui/react/Collapsible'; +import { CollapsibleContext } from '../Root/CollapsibleContext'; import { describeConformance } from '../../../test/describeConformance'; const contextValue: Collapsible.Root.Context = { diff --git a/packages/mui-base/src/Collapsible/index.parts.ts b/packages/mui-base/src/Collapsible/index.parts.ts new file mode 100644 index 000000000..3736ae4de --- /dev/null +++ b/packages/mui-base/src/Collapsible/index.parts.ts @@ -0,0 +1,3 @@ +export { CollapsibleRoot as Root } from './Root/CollapsibleRoot'; +export { CollapsibleTrigger as Trigger } from './Trigger/CollapsibleTrigger'; +export { CollapsibleContent as Content } from './Content/CollapsibleContent'; diff --git a/packages/mui-base/src/Collapsible/index.ts b/packages/mui-base/src/Collapsible/index.ts index facd5dee2..6d2cba0c7 100644 --- a/packages/mui-base/src/Collapsible/index.ts +++ b/packages/mui-base/src/Collapsible/index.ts @@ -1,9 +1 @@ -export { CollapsibleRoot as Root } from './Root/CollapsibleRoot'; -export { useCollapsibleRoot } from './Root/useCollapsibleRoot'; -export { CollapsibleContext, useCollapsibleContext } from './Root/CollapsibleContext'; - -export { CollapsibleTrigger as Trigger } from './Trigger/CollapsibleTrigger'; -export { useCollapsibleTrigger } from './Trigger/useCollapsibleTrigger'; - -export { CollapsibleContent as Content } from './Content/CollapsibleContent'; -export { useCollapsibleContent } from './Content/useCollapsibleContent'; +export * as Collapsible from './index.parts'; diff --git a/packages/mui-base/src/Dialog/Backdrop/DialogBackdrop.test.tsx b/packages/mui-base/src/Dialog/Backdrop/DialogBackdrop.test.tsx index f59fdf0fe..8dead2426 100644 --- a/packages/mui-base/src/Dialog/Backdrop/DialogBackdrop.test.tsx +++ b/packages/mui-base/src/Dialog/Backdrop/DialogBackdrop.test.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import { expect } from 'chai'; -import * as Dialog from '@base_ui/react/Dialog'; +import { Dialog } from '@base_ui/react/Dialog'; import { createRenderer, describeConformance } from '#test-utils'; describe('', () => { diff --git a/packages/mui-base/src/Dialog/Close/DialogClose.test.tsx b/packages/mui-base/src/Dialog/Close/DialogClose.test.tsx index f91456aa7..511b62008 100644 --- a/packages/mui-base/src/Dialog/Close/DialogClose.test.tsx +++ b/packages/mui-base/src/Dialog/Close/DialogClose.test.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import * as Dialog from '@base_ui/react/Dialog'; +import { Dialog } from '@base_ui/react/Dialog'; import { createRenderer, describeConformance } from '#test-utils'; describe('', () => { diff --git a/packages/mui-base/src/Dialog/Description/DialogDescription.test.tsx b/packages/mui-base/src/Dialog/Description/DialogDescription.test.tsx index 31ce4b158..3bc0abdb0 100644 --- a/packages/mui-base/src/Dialog/Description/DialogDescription.test.tsx +++ b/packages/mui-base/src/Dialog/Description/DialogDescription.test.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import * as Dialog from '@base_ui/react/Dialog'; +import { Dialog } from '@base_ui/react/Dialog'; import { createRenderer, describeConformance } from '#test-utils'; describe('', () => { diff --git a/packages/mui-base/src/Dialog/Popup/DialogPopup.test.tsx b/packages/mui-base/src/Dialog/Popup/DialogPopup.test.tsx index 056effacd..7f1114b7c 100644 --- a/packages/mui-base/src/Dialog/Popup/DialogPopup.test.tsx +++ b/packages/mui-base/src/Dialog/Popup/DialogPopup.test.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import { expect } from 'chai'; -import * as Dialog from '@base_ui/react/Dialog'; +import { Dialog } from '@base_ui/react/Dialog'; import { describeConformance, createRenderer } from '#test-utils'; describe('', () => { diff --git a/packages/mui-base/src/Dialog/Root/DialogRoot.test.tsx b/packages/mui-base/src/Dialog/Root/DialogRoot.test.tsx index 0c7afd848..6ae50fd2a 100644 --- a/packages/mui-base/src/Dialog/Root/DialogRoot.test.tsx +++ b/packages/mui-base/src/Dialog/Root/DialogRoot.test.tsx @@ -2,7 +2,7 @@ import * as React from 'react'; import { expect } from 'chai'; import { spy } from 'sinon'; import { act, fireEvent, waitFor } from '@mui/internal-test-utils'; -import * as Dialog from '@base_ui/react/Dialog'; +import { Dialog } from '@base_ui/react/Dialog'; import { createRenderer } from '#test-utils'; describe('', () => { diff --git a/packages/mui-base/src/Dialog/Title/DialogTitle.test.tsx b/packages/mui-base/src/Dialog/Title/DialogTitle.test.tsx index 726da92fb..92e6f9679 100644 --- a/packages/mui-base/src/Dialog/Title/DialogTitle.test.tsx +++ b/packages/mui-base/src/Dialog/Title/DialogTitle.test.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import * as Dialog from '@base_ui/react/Dialog'; +import { Dialog } from '@base_ui/react/Dialog'; import { createRenderer, describeConformance } from '#test-utils'; describe('', () => { diff --git a/packages/mui-base/src/Dialog/Trigger/DialogTrigger.test.tsx b/packages/mui-base/src/Dialog/Trigger/DialogTrigger.test.tsx index 07594a959..14eff99a0 100644 --- a/packages/mui-base/src/Dialog/Trigger/DialogTrigger.test.tsx +++ b/packages/mui-base/src/Dialog/Trigger/DialogTrigger.test.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import * as Dialog from '@base_ui/react/Dialog'; +import { Dialog } from '@base_ui/react/Dialog'; import { createRenderer, describeConformance } from '#test-utils'; describe('', () => { diff --git a/packages/mui-base/src/Dialog/index.barrel.ts b/packages/mui-base/src/Dialog/index.barrel.ts deleted file mode 100644 index b12eac69e..000000000 --- a/packages/mui-base/src/Dialog/index.barrel.ts +++ /dev/null @@ -1,7 +0,0 @@ -export { DialogBackdrop } from './Backdrop/DialogBackdrop'; -export { DialogClose } from './Close/DialogClose'; -export { DialogDescription } from './Description/DialogDescription'; -export { DialogPopup } from './Popup/DialogPopup'; -export { DialogRoot } from './Root/DialogRoot'; -export { DialogTitle } from './Title/DialogTitle'; -export { DialogTrigger } from './Trigger/DialogTrigger'; diff --git a/packages/mui-base/src/Dialog/index.parts.ts b/packages/mui-base/src/Dialog/index.parts.ts new file mode 100644 index 000000000..f242e5602 --- /dev/null +++ b/packages/mui-base/src/Dialog/index.parts.ts @@ -0,0 +1,7 @@ +export { DialogBackdrop as Backdrop } from './Backdrop/DialogBackdrop'; +export { DialogClose as Close } from './Close/DialogClose'; +export { DialogDescription as Description } from './Description/DialogDescription'; +export { DialogPopup as Popup } from './Popup/DialogPopup'; +export { DialogRoot as Root } from './Root/DialogRoot'; +export { DialogTitle as Title } from './Title/DialogTitle'; +export { DialogTrigger as Trigger } from './Trigger/DialogTrigger'; diff --git a/packages/mui-base/src/Dialog/index.ts b/packages/mui-base/src/Dialog/index.ts index f242e5602..823c17d24 100644 --- a/packages/mui-base/src/Dialog/index.ts +++ b/packages/mui-base/src/Dialog/index.ts @@ -1,7 +1 @@ -export { DialogBackdrop as Backdrop } from './Backdrop/DialogBackdrop'; -export { DialogClose as Close } from './Close/DialogClose'; -export { DialogDescription as Description } from './Description/DialogDescription'; -export { DialogPopup as Popup } from './Popup/DialogPopup'; -export { DialogRoot as Root } from './Root/DialogRoot'; -export { DialogTitle as Title } from './Title/DialogTitle'; -export { DialogTrigger as Trigger } from './Trigger/DialogTrigger'; +export * as Dialog from './index.parts'; diff --git a/packages/mui-base/src/Field/Control/FieldControl.test.tsx b/packages/mui-base/src/Field/Control/FieldControl.test.tsx index 677cac06a..cf6187722 100644 --- a/packages/mui-base/src/Field/Control/FieldControl.test.tsx +++ b/packages/mui-base/src/Field/Control/FieldControl.test.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import { createRenderer } from '@mui/internal-test-utils'; -import * as Field from '@base_ui/react/Field'; +import { Field } from '@base_ui/react/Field'; import { describeConformance } from '../../../test/describeConformance'; describe('', () => { diff --git a/packages/mui-base/src/Field/Description/FieldDescription.test.tsx b/packages/mui-base/src/Field/Description/FieldDescription.test.tsx index 56ade9fbf..c0aa55dec 100644 --- a/packages/mui-base/src/Field/Description/FieldDescription.test.tsx +++ b/packages/mui-base/src/Field/Description/FieldDescription.test.tsx @@ -1,11 +1,11 @@ import * as React from 'react'; -import * as Field from '@base_ui/react/Field'; -import * as Checkbox from '@base_ui/react/Checkbox'; -import * as Switch from '@base_ui/react/Switch'; -import * as NumberField from '@base_ui/react/NumberField'; -import * as Slider from '@base_ui/react/Slider'; -import * as RadioGroup from '@base_ui/react/RadioGroup'; -import * as Radio from '@base_ui/react/Radio'; +import { Field } from '@base_ui/react/Field'; +import { Checkbox } from '@base_ui/react/Checkbox'; +import { Switch } from '@base_ui/react/Switch'; +import { NumberField } from '@base_ui/react/NumberField'; +import { Slider } from '@base_ui/react/Slider'; +import { RadioGroup } from '@base_ui/react/RadioGroup'; +import { Radio } from '@base_ui/react/Radio'; import { createRenderer, screen } from '@mui/internal-test-utils'; import { expect } from 'chai'; import { describeConformance } from '../../../test/describeConformance'; diff --git a/packages/mui-base/src/Field/Error/FieldError.test.tsx b/packages/mui-base/src/Field/Error/FieldError.test.tsx index 0fb6ea967..1255e3598 100644 --- a/packages/mui-base/src/Field/Error/FieldError.test.tsx +++ b/packages/mui-base/src/Field/Error/FieldError.test.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import { createRenderer, fireEvent, screen } from '@mui/internal-test-utils'; import { expect } from 'chai'; -import * as Field from '@base_ui/react/Field'; +import { Field } from '@base_ui/react/Field'; import { describeConformance } from '../../../test/describeConformance'; describe('', () => { diff --git a/packages/mui-base/src/Field/Label/FieldLabel.test.tsx b/packages/mui-base/src/Field/Label/FieldLabel.test.tsx index c1cf8d645..39424f57c 100644 --- a/packages/mui-base/src/Field/Label/FieldLabel.test.tsx +++ b/packages/mui-base/src/Field/Label/FieldLabel.test.tsx @@ -1,11 +1,11 @@ import * as React from 'react'; -import * as Field from '@base_ui/react/Field'; -import * as Checkbox from '@base_ui/react/Checkbox'; -import * as Switch from '@base_ui/react/Switch'; -import * as NumberField from '@base_ui/react/NumberField'; -import * as Slider from '@base_ui/react/Slider'; -import * as RadioGroup from '@base_ui/react/RadioGroup'; -import * as Radio from '@base_ui/react/Radio'; +import { Field } from '@base_ui/react/Field'; +import { Checkbox } from '@base_ui/react/Checkbox'; +import { Switch } from '@base_ui/react/Switch'; +import { NumberField } from '@base_ui/react/NumberField'; +import { Slider } from '@base_ui/react/Slider'; +import { RadioGroup } from '@base_ui/react/RadioGroup'; +import { Radio } from '@base_ui/react/Radio'; import { createRenderer, screen } from '@mui/internal-test-utils'; import { expect } from 'chai'; import { describeConformance } from '../../../test/describeConformance'; diff --git a/packages/mui-base/src/Field/Root/FieldRoot.test.tsx b/packages/mui-base/src/Field/Root/FieldRoot.test.tsx index a488d8053..8fe0d8b65 100644 --- a/packages/mui-base/src/Field/Root/FieldRoot.test.tsx +++ b/packages/mui-base/src/Field/Root/FieldRoot.test.tsx @@ -1,11 +1,11 @@ import * as React from 'react'; -import * as Field from '@base_ui/react/Field'; -import * as Checkbox from '@base_ui/react/Checkbox'; -import * as Switch from '@base_ui/react/Switch'; -import * as NumberField from '@base_ui/react/NumberField'; -import * as Slider from '@base_ui/react/Slider'; -import * as RadioGroup from '@base_ui/react/RadioGroup'; -import * as Radio from '@base_ui/react/Radio'; +import { Field } from '@base_ui/react/Field'; +import { Checkbox } from '@base_ui/react/Checkbox'; +import { Switch } from '@base_ui/react/Switch'; +import { NumberField } from '@base_ui/react/NumberField'; +import { Slider } from '@base_ui/react/Slider'; +import { RadioGroup } from '@base_ui/react/RadioGroup'; +import { Radio } from '@base_ui/react/Radio'; import userEvent from '@testing-library/user-event'; import { act, diff --git a/packages/mui-base/src/Field/Validity/FieldValidity.test.tsx b/packages/mui-base/src/Field/Validity/FieldValidity.test.tsx index 8974a440b..98ba936da 100644 --- a/packages/mui-base/src/Field/Validity/FieldValidity.test.tsx +++ b/packages/mui-base/src/Field/Validity/FieldValidity.test.tsx @@ -2,7 +2,7 @@ import * as React from 'react'; import { createRenderer, fireEvent, screen } from '@mui/internal-test-utils'; import { expect } from 'chai'; import { spy } from 'sinon'; -import * as Field from '@base_ui/react/Field'; +import { Field } from '@base_ui/react/Field'; describe('', () => { const { render } = createRenderer(); diff --git a/packages/mui-base/src/Field/index.barrel.ts b/packages/mui-base/src/Field/index.barrel.ts deleted file mode 100644 index e9604532c..000000000 --- a/packages/mui-base/src/Field/index.barrel.ts +++ /dev/null @@ -1,8 +0,0 @@ -export * from './Root/FieldRoot'; -export * from './Label/FieldLabel'; -export * from './Error/FieldError'; -export * from './Description/FieldDescription'; -export * from './Control/FieldControl'; -export * from './Validity/FieldValidity'; - -export type { FieldValidityData } from './Root/FieldRoot'; diff --git a/packages/mui-base/src/Field/index.parts.ts b/packages/mui-base/src/Field/index.parts.ts new file mode 100644 index 000000000..caded1396 --- /dev/null +++ b/packages/mui-base/src/Field/index.parts.ts @@ -0,0 +1,8 @@ +export { FieldRoot as Root } from './Root/FieldRoot'; +export { FieldLabel as Label } from './Label/FieldLabel'; +export { FieldError as Error } from './Error/FieldError'; +export { FieldDescription as Description } from './Description/FieldDescription'; +export { FieldControl as Control } from './Control/FieldControl'; +export { FieldValidity as Validity } from './Validity/FieldValidity'; + +export type { FieldValidityData as ValidityData } from './Root/FieldRoot'; diff --git a/packages/mui-base/src/Field/index.ts b/packages/mui-base/src/Field/index.ts index caded1396..45425dec2 100644 --- a/packages/mui-base/src/Field/index.ts +++ b/packages/mui-base/src/Field/index.ts @@ -1,8 +1 @@ -export { FieldRoot as Root } from './Root/FieldRoot'; -export { FieldLabel as Label } from './Label/FieldLabel'; -export { FieldError as Error } from './Error/FieldError'; -export { FieldDescription as Description } from './Description/FieldDescription'; -export { FieldControl as Control } from './Control/FieldControl'; -export { FieldValidity as Validity } from './Validity/FieldValidity'; - -export type { FieldValidityData as ValidityData } from './Root/FieldRoot'; +export * as Field from './index.parts'; diff --git a/packages/mui-base/src/Fieldset/Legend/FieldsetLegend.test.tsx b/packages/mui-base/src/Fieldset/Legend/FieldsetLegend.test.tsx index 101280858..44b65dc34 100644 --- a/packages/mui-base/src/Fieldset/Legend/FieldsetLegend.test.tsx +++ b/packages/mui-base/src/Fieldset/Legend/FieldsetLegend.test.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import { createRenderer, screen } from '@mui/internal-test-utils'; -import * as Fieldset from '@base_ui/react/Fieldset'; +import { Fieldset } from '@base_ui/react/Fieldset'; import { expect } from 'chai'; import { describeConformance } from '../../../test/describeConformance'; diff --git a/packages/mui-base/src/Fieldset/Root/FieldsetRoot.test.tsx b/packages/mui-base/src/Fieldset/Root/FieldsetRoot.test.tsx index a397f47d9..1172c88a7 100644 --- a/packages/mui-base/src/Fieldset/Root/FieldsetRoot.test.tsx +++ b/packages/mui-base/src/Fieldset/Root/FieldsetRoot.test.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import { createRenderer } from '@mui/internal-test-utils'; -import * as Fieldset from '@base_ui/react/Fieldset'; +import { Fieldset } from '@base_ui/react/Fieldset'; import { describeConformance } from '../../../test/describeConformance'; describe('', () => { diff --git a/packages/mui-base/src/Fieldset/index.barrel.ts b/packages/mui-base/src/Fieldset/index.barrel.ts deleted file mode 100644 index b5a4cbaf4..000000000 --- a/packages/mui-base/src/Fieldset/index.barrel.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './Root/FieldsetRoot'; -export * from './Legend/FieldsetLegend'; diff --git a/packages/mui-base/src/Fieldset/index.parts.ts b/packages/mui-base/src/Fieldset/index.parts.ts new file mode 100644 index 000000000..ee2ae05cb --- /dev/null +++ b/packages/mui-base/src/Fieldset/index.parts.ts @@ -0,0 +1,2 @@ +export { FieldsetRoot as Root } from './Root/FieldsetRoot'; +export { FieldsetLegend as Legend } from './Legend/FieldsetLegend'; diff --git a/packages/mui-base/src/Fieldset/index.ts b/packages/mui-base/src/Fieldset/index.ts index ee2ae05cb..1320ce190 100644 --- a/packages/mui-base/src/Fieldset/index.ts +++ b/packages/mui-base/src/Fieldset/index.ts @@ -1,2 +1 @@ -export { FieldsetRoot as Root } from './Root/FieldsetRoot'; -export { FieldsetLegend as Legend } from './Legend/FieldsetLegend'; +export * as Fieldset from './index.parts'; diff --git a/packages/mui-base/src/Form/Root/FormRoot.test.tsx b/packages/mui-base/src/Form/Root/FormRoot.test.tsx index ae08084c8..bfaca78d8 100644 --- a/packages/mui-base/src/Form/Root/FormRoot.test.tsx +++ b/packages/mui-base/src/Form/Root/FormRoot.test.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; -import * as Form from '@base_ui/react/Form'; -import * as Field from '@base_ui/react/Field'; +import { Form } from '@base_ui/react/Form'; +import { Field } from '@base_ui/react/Field'; import { expect } from 'chai'; import { createRenderer, fireEvent, screen } from '@mui/internal-test-utils'; import { describeConformance } from '../../../test/describeConformance'; diff --git a/packages/mui-base/src/Form/index.barrel.ts b/packages/mui-base/src/Form/index.barrel.ts deleted file mode 100644 index acab7f429..000000000 --- a/packages/mui-base/src/Form/index.barrel.ts +++ /dev/null @@ -1 +0,0 @@ -export { FormRoot } from './Root/FormRoot'; diff --git a/packages/mui-base/src/Form/index.parts.ts b/packages/mui-base/src/Form/index.parts.ts new file mode 100644 index 000000000..896025acc --- /dev/null +++ b/packages/mui-base/src/Form/index.parts.ts @@ -0,0 +1 @@ +export { FormRoot as Root } from './Root/FormRoot'; diff --git a/packages/mui-base/src/Form/index.ts b/packages/mui-base/src/Form/index.ts index 896025acc..75652f7f1 100644 --- a/packages/mui-base/src/Form/index.ts +++ b/packages/mui-base/src/Form/index.ts @@ -1 +1 @@ -export { FormRoot as Root } from './Root/FormRoot'; +export * as Form from './index.parts'; diff --git a/packages/mui-base/src/Menu/Arrow/MenuArrow.test.tsx b/packages/mui-base/src/Menu/Arrow/MenuArrow.test.tsx index 231e31d1e..ac92bb633 100644 --- a/packages/mui-base/src/Menu/Arrow/MenuArrow.test.tsx +++ b/packages/mui-base/src/Menu/Arrow/MenuArrow.test.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import * as Menu from '@base_ui/react/Menu'; +import { Menu } from '@base_ui/react/Menu'; import { createRenderer, describeConformance } from '#test-utils'; describe('', () => { diff --git a/packages/mui-base/src/Menu/CheckboxItem/MenuCheckboxItem.test.tsx b/packages/mui-base/src/Menu/CheckboxItem/MenuCheckboxItem.test.tsx index 9593007d2..b8b598b18 100644 --- a/packages/mui-base/src/Menu/CheckboxItem/MenuCheckboxItem.test.tsx +++ b/packages/mui-base/src/Menu/CheckboxItem/MenuCheckboxItem.test.tsx @@ -4,7 +4,7 @@ import { spy } from 'sinon'; import userEvent from '@testing-library/user-event'; import { fireEvent, act, waitFor } from '@mui/internal-test-utils'; import { FloatingRootContext, FloatingTree } from '@floating-ui/react'; -import * as Menu from '@base_ui/react/Menu'; +import { Menu } from '@base_ui/react/Menu'; import { describeConformance, createRenderer } from '../../../test'; import { MenuRootContext } from '../Root/MenuRootContext'; diff --git a/packages/mui-base/src/Menu/CheckboxItemIndicator/MenuCheckboxItemIndicator.test.tsx b/packages/mui-base/src/Menu/CheckboxItemIndicator/MenuCheckboxItemIndicator.test.tsx index dd0cfefae..769922566 100644 --- a/packages/mui-base/src/Menu/CheckboxItemIndicator/MenuCheckboxItemIndicator.test.tsx +++ b/packages/mui-base/src/Menu/CheckboxItemIndicator/MenuCheckboxItemIndicator.test.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import * as Menu from '@base_ui/react/Menu'; +import { Menu } from '@base_ui/react/Menu'; import { createRenderer, describeConformance } from '#test-utils'; describe('', () => { diff --git a/packages/mui-base/src/Menu/Group/MenuGroup.test.tsx b/packages/mui-base/src/Menu/Group/MenuGroup.test.tsx index 93d0e37d0..d21fa87b8 100644 --- a/packages/mui-base/src/Menu/Group/MenuGroup.test.tsx +++ b/packages/mui-base/src/Menu/Group/MenuGroup.test.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import { expect } from 'chai'; -import * as Menu from '@base_ui/react/Menu'; +import { Menu } from '@base_ui/react/Menu'; import { createRenderer, describeConformance } from '#test-utils'; describe('', () => { diff --git a/packages/mui-base/src/Menu/GroupLabel/MenuGroupLabel.test.tsx b/packages/mui-base/src/Menu/GroupLabel/MenuGroupLabel.test.tsx index ec699ef3a..335aa8f2e 100644 --- a/packages/mui-base/src/Menu/GroupLabel/MenuGroupLabel.test.tsx +++ b/packages/mui-base/src/Menu/GroupLabel/MenuGroupLabel.test.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import * as Menu from '@base_ui/react/Menu'; +import { Menu } from '@base_ui/react/Menu'; import { createRenderer, describeConformance } from '#test-utils'; import { MenuGroupContext } from '../Group/MenuGroupContext'; diff --git a/packages/mui-base/src/Menu/Item/MenuItem.test.tsx b/packages/mui-base/src/Menu/Item/MenuItem.test.tsx index ccb335ca1..1195d4f17 100644 --- a/packages/mui-base/src/Menu/Item/MenuItem.test.tsx +++ b/packages/mui-base/src/Menu/Item/MenuItem.test.tsx @@ -4,7 +4,7 @@ import { spy } from 'sinon'; import userEvent from '@testing-library/user-event'; import { act, waitFor } from '@mui/internal-test-utils'; import { FloatingRootContext, FloatingTree } from '@floating-ui/react'; -import * as Menu from '@base_ui/react/Menu'; +import { Menu } from '@base_ui/react/Menu'; import { describeConformance, createRenderer } from '#test-utils'; import { MenuRootContext } from '../Root/MenuRootContext'; diff --git a/packages/mui-base/src/Menu/Popup/MenuPopup.test.tsx b/packages/mui-base/src/Menu/Popup/MenuPopup.test.tsx index 64951f945..cf5904881 100644 --- a/packages/mui-base/src/Menu/Popup/MenuPopup.test.tsx +++ b/packages/mui-base/src/Menu/Popup/MenuPopup.test.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import * as Menu from '@base_ui/react/Menu'; +import { Menu } from '@base_ui/react/Menu'; import { FloatingRootContext, FloatingTree } from '@floating-ui/react'; import { createRenderer, describeConformance } from '#test-utils'; import { MenuPositionerContext } from '../Positioner/MenuPositionerContext'; diff --git a/packages/mui-base/src/Menu/Positioner/MenuPositioner.test.tsx b/packages/mui-base/src/Menu/Positioner/MenuPositioner.test.tsx index 6e9664d35..70adbf142 100644 --- a/packages/mui-base/src/Menu/Positioner/MenuPositioner.test.tsx +++ b/packages/mui-base/src/Menu/Positioner/MenuPositioner.test.tsx @@ -3,7 +3,7 @@ import { expect } from 'chai'; import { FloatingRootContext, FloatingTree } from '@floating-ui/react'; import userEvent from '@testing-library/user-event'; import { flushMicrotasks } from '@mui/internal-test-utils'; -import * as Menu from '@base_ui/react/Menu'; +import { Menu } from '@base_ui/react/Menu'; import { describeConformance, createRenderer } from '#test-utils'; import { MenuRootContext } from '../Root/MenuRootContext'; diff --git a/packages/mui-base/src/Menu/RadioGroup/MenuRadioGroup.test.tsx b/packages/mui-base/src/Menu/RadioGroup/MenuRadioGroup.test.tsx index 0116f9c17..d3dc7223c 100644 --- a/packages/mui-base/src/Menu/RadioGroup/MenuRadioGroup.test.tsx +++ b/packages/mui-base/src/Menu/RadioGroup/MenuRadioGroup.test.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import { expect } from 'chai'; -import * as Menu from '@base_ui/react/Menu'; +import { Menu } from '@base_ui/react/Menu'; import { createRenderer, describeConformance } from '#test-utils'; describe('', () => { diff --git a/packages/mui-base/src/Menu/RadioItem/MenuRadioItem.test.tsx b/packages/mui-base/src/Menu/RadioItem/MenuRadioItem.test.tsx index 7819cbc12..0a0c1e1c4 100644 --- a/packages/mui-base/src/Menu/RadioItem/MenuRadioItem.test.tsx +++ b/packages/mui-base/src/Menu/RadioItem/MenuRadioItem.test.tsx @@ -4,7 +4,7 @@ import { spy } from 'sinon'; import userEvent from '@testing-library/user-event'; import { fireEvent, act, waitFor } from '@mui/internal-test-utils'; import { FloatingRootContext, FloatingTree } from '@floating-ui/react'; -import * as Menu from '@base_ui/react/Menu'; +import { Menu } from '@base_ui/react/Menu'; import { describeConformance, createRenderer } from '#test-utils'; import { MenuRadioGroupContext } from '../RadioGroup/MenuRadioGroupContext'; import { MenuRootContext } from '../Root/MenuRootContext'; diff --git a/packages/mui-base/src/Menu/RadioItemIndicator/MenuRadioItemIndicator.test.tsx b/packages/mui-base/src/Menu/RadioItemIndicator/MenuRadioItemIndicator.test.tsx index 023aa4437..429b7b793 100644 --- a/packages/mui-base/src/Menu/RadioItemIndicator/MenuRadioItemIndicator.test.tsx +++ b/packages/mui-base/src/Menu/RadioItemIndicator/MenuRadioItemIndicator.test.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import * as Menu from '@base_ui/react/Menu'; +import { Menu } from '@base_ui/react/Menu'; import { createRenderer, describeConformance } from '#test-utils'; describe('', () => { diff --git a/packages/mui-base/src/Menu/Root/MenuRoot.test.tsx b/packages/mui-base/src/Menu/Root/MenuRoot.test.tsx index b3b41ad61..591247046 100644 --- a/packages/mui-base/src/Menu/Root/MenuRoot.test.tsx +++ b/packages/mui-base/src/Menu/Root/MenuRoot.test.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import { expect } from 'chai'; import { act, flushMicrotasks, waitFor } from '@mui/internal-test-utils'; -import * as Menu from '@base_ui/react/Menu'; +import { Menu } from '@base_ui/react/Menu'; import userEvent from '@testing-library/user-event'; import { spy } from 'sinon'; import { createRenderer } from '#test-utils'; diff --git a/packages/mui-base/src/Menu/Trigger/MenuTrigger.test.tsx b/packages/mui-base/src/Menu/Trigger/MenuTrigger.test.tsx index 16b250010..1ee512071 100644 --- a/packages/mui-base/src/Menu/Trigger/MenuTrigger.test.tsx +++ b/packages/mui-base/src/Menu/Trigger/MenuTrigger.test.tsx @@ -3,7 +3,7 @@ import { expect } from 'chai'; import { FloatingRootContext, FloatingTree } from '@floating-ui/react'; import userEvent from '@testing-library/user-event'; import { act } from '@mui/internal-test-utils'; -import * as Menu from '@base_ui/react/Menu'; +import { Menu } from '@base_ui/react/Menu'; import { describeConformance, createRenderer } from '#test-utils'; import { MenuRootContext } from '../Root/MenuRootContext'; diff --git a/packages/mui-base/src/Menu/index.barrel.ts b/packages/mui-base/src/Menu/index.barrel.ts deleted file mode 100644 index 166bf5c67..000000000 --- a/packages/mui-base/src/Menu/index.barrel.ts +++ /dev/null @@ -1,14 +0,0 @@ -export { MenuArrow } from './Arrow/MenuArrow'; -export { MenuCheckboxItem } from './CheckboxItem/MenuCheckboxItem'; -export { MenuCheckboxItemIndicator } from './CheckboxItemIndicator/MenuCheckboxItemIndicator'; -export { MenuGroup } from './Group/MenuGroup'; -export { MenuGroupLabel } from './GroupLabel/MenuGroupLabel'; -export { MenuItem } from './Item/MenuItem'; -export { MenuPopup } from './Popup/MenuPopup'; -export { MenuPositioner } from './Positioner/MenuPositioner'; -export { MenuRadioGroup } from './RadioGroup/MenuRadioGroup'; -export { MenuRadioItem } from './RadioItem/MenuRadioItem'; -export { MenuRadioItemIndicator } from './RadioItemIndicator/MenuRadioItemIndicator'; -export { MenuRoot } from './Root/MenuRoot'; -export { MenuTrigger } from './Trigger/MenuTrigger'; -export { SubmenuTrigger } from './SubmenuTrigger/SubmenuTrigger'; diff --git a/packages/mui-base/src/Menu/index.parts.ts b/packages/mui-base/src/Menu/index.parts.ts new file mode 100644 index 000000000..ac63a706d --- /dev/null +++ b/packages/mui-base/src/Menu/index.parts.ts @@ -0,0 +1,15 @@ +export { MenuArrow as Arrow } from './Arrow/MenuArrow'; +export { MenuCheckboxItem as CheckboxItem } from './CheckboxItem/MenuCheckboxItem'; +export { MenuCheckboxItemIndicator as CheckboxItemIndicator } from './CheckboxItemIndicator/MenuCheckboxItemIndicator'; +export { MenuGroup as Group } from './Group/MenuGroup'; +export { MenuGroupLabel as GroupLabel } from './GroupLabel/MenuGroupLabel'; +export { MenuItem as Item } from './Item/MenuItem'; +export { MenuPopup as Popup } from './Popup/MenuPopup'; +export { MenuPositioner as Positioner } from './Positioner/MenuPositioner'; +export { MenuRadioGroup as RadioGroup } from './RadioGroup/MenuRadioGroup'; +export { MenuRadioItem as RadioItem } from './RadioItem/MenuRadioItem'; +export { MenuRadioItemIndicator as RadioItemIndicator } from './RadioItemIndicator/MenuRadioItemIndicator'; +export { MenuRoot as Root } from './Root/MenuRoot'; +export { MenuTrigger as Trigger } from './Trigger/MenuTrigger'; +export { SeparatorRoot as Separator } from '../Separator/Root/SeparatorRoot'; +export { SubmenuTrigger } from './SubmenuTrigger/SubmenuTrigger'; diff --git a/packages/mui-base/src/Menu/index.ts b/packages/mui-base/src/Menu/index.ts index ac63a706d..515d1290d 100644 --- a/packages/mui-base/src/Menu/index.ts +++ b/packages/mui-base/src/Menu/index.ts @@ -1,15 +1 @@ -export { MenuArrow as Arrow } from './Arrow/MenuArrow'; -export { MenuCheckboxItem as CheckboxItem } from './CheckboxItem/MenuCheckboxItem'; -export { MenuCheckboxItemIndicator as CheckboxItemIndicator } from './CheckboxItemIndicator/MenuCheckboxItemIndicator'; -export { MenuGroup as Group } from './Group/MenuGroup'; -export { MenuGroupLabel as GroupLabel } from './GroupLabel/MenuGroupLabel'; -export { MenuItem as Item } from './Item/MenuItem'; -export { MenuPopup as Popup } from './Popup/MenuPopup'; -export { MenuPositioner as Positioner } from './Positioner/MenuPositioner'; -export { MenuRadioGroup as RadioGroup } from './RadioGroup/MenuRadioGroup'; -export { MenuRadioItem as RadioItem } from './RadioItem/MenuRadioItem'; -export { MenuRadioItemIndicator as RadioItemIndicator } from './RadioItemIndicator/MenuRadioItemIndicator'; -export { MenuRoot as Root } from './Root/MenuRoot'; -export { MenuTrigger as Trigger } from './Trigger/MenuTrigger'; -export { SeparatorRoot as Separator } from '../Separator/Root/SeparatorRoot'; -export { SubmenuTrigger } from './SubmenuTrigger/SubmenuTrigger'; +export * as Menu from './index.parts'; diff --git a/packages/mui-base/src/NumberField/Decrement/NumberFieldDecrement.test.tsx b/packages/mui-base/src/NumberField/Decrement/NumberFieldDecrement.test.tsx index 9b9811abc..2ca25b155 100644 --- a/packages/mui-base/src/NumberField/Decrement/NumberFieldDecrement.test.tsx +++ b/packages/mui-base/src/NumberField/Decrement/NumberFieldDecrement.test.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import { expect } from 'chai'; import { screen, fireEvent } from '@mui/internal-test-utils'; -import * as NumberField from '@base_ui/react/NumberField'; +import { NumberField } from '@base_ui/react/NumberField'; import { createRenderer, describeConformance } from '#test-utils'; import { CHANGE_VALUE_TICK_DELAY, START_AUTO_CHANGE_DELAY } from '../utils/constants'; import { NumberFieldContext } from '../Root/NumberFieldContext'; diff --git a/packages/mui-base/src/NumberField/Group/NumberFieldGroup.test.tsx b/packages/mui-base/src/NumberField/Group/NumberFieldGroup.test.tsx index 140c66865..bda5d52f1 100644 --- a/packages/mui-base/src/NumberField/Group/NumberFieldGroup.test.tsx +++ b/packages/mui-base/src/NumberField/Group/NumberFieldGroup.test.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import { expect } from 'chai'; import { screen } from '@mui/internal-test-utils'; -import * as NumberField from '@base_ui/react/NumberField'; +import { NumberField } from '@base_ui/react/NumberField'; import { createRenderer, describeConformance } from '#test-utils'; import { NumberFieldContext } from '../Root/NumberFieldContext'; diff --git a/packages/mui-base/src/NumberField/Increment/NumberFieldIncrement.test.tsx b/packages/mui-base/src/NumberField/Increment/NumberFieldIncrement.test.tsx index e2153caa9..dc90a6857 100644 --- a/packages/mui-base/src/NumberField/Increment/NumberFieldIncrement.test.tsx +++ b/packages/mui-base/src/NumberField/Increment/NumberFieldIncrement.test.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import { expect } from 'chai'; import { screen, fireEvent } from '@mui/internal-test-utils'; -import * as NumberField from '@base_ui/react/NumberField'; +import { NumberField } from '@base_ui/react/NumberField'; import { createRenderer, describeConformance } from '#test-utils'; import { CHANGE_VALUE_TICK_DELAY, START_AUTO_CHANGE_DELAY } from '../utils/constants'; import { NumberFieldContext } from '../Root/NumberFieldContext'; diff --git a/packages/mui-base/src/NumberField/Input/NumberFieldInput.test.tsx b/packages/mui-base/src/NumberField/Input/NumberFieldInput.test.tsx index b9c97f093..46ef5531e 100644 --- a/packages/mui-base/src/NumberField/Input/NumberFieldInput.test.tsx +++ b/packages/mui-base/src/NumberField/Input/NumberFieldInput.test.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import { expect } from 'chai'; import { act, screen, fireEvent } from '@mui/internal-test-utils'; -import * as NumberField from '@base_ui/react/NumberField'; +import { NumberField } from '@base_ui/react/NumberField'; import { createRenderer, describeConformance } from '#test-utils'; import { NumberFieldContext } from '../Root/NumberFieldContext'; diff --git a/packages/mui-base/src/NumberField/Root/NumberFieldRoot.test.tsx b/packages/mui-base/src/NumberField/Root/NumberFieldRoot.test.tsx index 24b9547e1..f9f0e6aae 100644 --- a/packages/mui-base/src/NumberField/Root/NumberFieldRoot.test.tsx +++ b/packages/mui-base/src/NumberField/Root/NumberFieldRoot.test.tsx @@ -2,7 +2,7 @@ import * as React from 'react'; import { expect } from 'chai'; import { spy } from 'sinon'; import { act, screen, fireEvent } from '@mui/internal-test-utils'; -import * as NumberFieldBase from '@base_ui/react/NumberField'; +import { NumberField as NumberFieldBase } from '@base_ui/react/NumberField'; import { createRenderer, describeConformance } from '#test-utils'; describe('', () => { diff --git a/packages/mui-base/src/NumberField/ScrubArea/NumberFieldScrubArea.test.tsx b/packages/mui-base/src/NumberField/ScrubArea/NumberFieldScrubArea.test.tsx index a368ea791..26a693730 100644 --- a/packages/mui-base/src/NumberField/ScrubArea/NumberFieldScrubArea.test.tsx +++ b/packages/mui-base/src/NumberField/ScrubArea/NumberFieldScrubArea.test.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import { expect } from 'chai'; import { screen, waitFor } from '@mui/internal-test-utils'; -import * as NumberField from '@base_ui/react/NumberField'; +import { NumberField } from '@base_ui/react/NumberField'; import { createRenderer, describeConformance } from '#test-utils'; import { isWebKit } from '../../utils/detectBrowser'; import { NumberFieldContext } from '../Root/NumberFieldContext'; diff --git a/packages/mui-base/src/NumberField/ScrubAreaCursor/NumberFieldScrubAreaCursor.test.tsx b/packages/mui-base/src/NumberField/ScrubAreaCursor/NumberFieldScrubAreaCursor.test.tsx index 4b577113b..de3ef46f0 100644 --- a/packages/mui-base/src/NumberField/ScrubAreaCursor/NumberFieldScrubAreaCursor.test.tsx +++ b/packages/mui-base/src/NumberField/ScrubAreaCursor/NumberFieldScrubAreaCursor.test.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import { expect } from 'chai'; import { screen } from '@mui/internal-test-utils'; -import * as NumberField from '@base_ui/react/NumberField'; +import { NumberField } from '@base_ui/react/NumberField'; import { createRenderer, describeConformance } from '#test-utils'; import { isWebKit } from '../../utils/detectBrowser'; import { NumberFieldContext } from '../Root/NumberFieldContext'; diff --git a/packages/mui-base/src/NumberField/index.barrel.ts b/packages/mui-base/src/NumberField/index.barrel.ts deleted file mode 100644 index c11c363b2..000000000 --- a/packages/mui-base/src/NumberField/index.barrel.ts +++ /dev/null @@ -1,7 +0,0 @@ -export { NumberFieldRoot } from './Root/NumberFieldRoot'; -export { NumberFieldGroup } from './Group/NumberFieldGroup'; -export { NumberFieldIncrement } from './Increment/NumberFieldIncrement'; -export { NumberFieldDecrement } from './Decrement/NumberFieldDecrement'; -export { NumberFieldInput } from './Input/NumberFieldInput'; -export { NumberFieldScrubArea } from './ScrubArea/NumberFieldScrubArea'; -export { NumberFieldScrubAreaCursor } from './ScrubAreaCursor/NumberFieldScrubAreaCursor'; diff --git a/packages/mui-base/src/NumberField/index.parts.ts b/packages/mui-base/src/NumberField/index.parts.ts new file mode 100644 index 000000000..1f0f7cd87 --- /dev/null +++ b/packages/mui-base/src/NumberField/index.parts.ts @@ -0,0 +1,7 @@ +export { NumberFieldRoot as Root } from './Root/NumberFieldRoot'; +export { NumberFieldGroup as Group } from './Group/NumberFieldGroup'; +export { NumberFieldIncrement as Increment } from './Increment/NumberFieldIncrement'; +export { NumberFieldDecrement as Decrement } from './Decrement/NumberFieldDecrement'; +export { NumberFieldInput as Input } from './Input/NumberFieldInput'; +export { NumberFieldScrubArea as ScrubArea } from './ScrubArea/NumberFieldScrubArea'; +export { NumberFieldScrubAreaCursor as ScrubAreaCursor } from './ScrubAreaCursor/NumberFieldScrubAreaCursor'; diff --git a/packages/mui-base/src/NumberField/index.ts b/packages/mui-base/src/NumberField/index.ts index 1f0f7cd87..e97deaf60 100644 --- a/packages/mui-base/src/NumberField/index.ts +++ b/packages/mui-base/src/NumberField/index.ts @@ -1,7 +1 @@ -export { NumberFieldRoot as Root } from './Root/NumberFieldRoot'; -export { NumberFieldGroup as Group } from './Group/NumberFieldGroup'; -export { NumberFieldIncrement as Increment } from './Increment/NumberFieldIncrement'; -export { NumberFieldDecrement as Decrement } from './Decrement/NumberFieldDecrement'; -export { NumberFieldInput as Input } from './Input/NumberFieldInput'; -export { NumberFieldScrubArea as ScrubArea } from './ScrubArea/NumberFieldScrubArea'; -export { NumberFieldScrubAreaCursor as ScrubAreaCursor } from './ScrubAreaCursor/NumberFieldScrubAreaCursor'; +export * as NumberField from './index.parts'; diff --git a/packages/mui-base/src/Popover/Arrow/PopoverArrow.test.tsx b/packages/mui-base/src/Popover/Arrow/PopoverArrow.test.tsx index f65456fa2..3a4642d49 100644 --- a/packages/mui-base/src/Popover/Arrow/PopoverArrow.test.tsx +++ b/packages/mui-base/src/Popover/Arrow/PopoverArrow.test.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import * as Popover from '@base_ui/react/Popover'; +import { Popover } from '@base_ui/react/Popover'; import { createRenderer, describeConformance } from '#test-utils'; describe('', () => { diff --git a/packages/mui-base/src/Popover/Backdrop/PopoverBackdrop.test.tsx b/packages/mui-base/src/Popover/Backdrop/PopoverBackdrop.test.tsx index 4ac40c877..98dccd1c0 100644 --- a/packages/mui-base/src/Popover/Backdrop/PopoverBackdrop.test.tsx +++ b/packages/mui-base/src/Popover/Backdrop/PopoverBackdrop.test.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import * as Popover from '@base_ui/react/Popover'; +import { Popover } from '@base_ui/react/Popover'; import { createRenderer, describeConformance } from '#test-utils'; describe('', () => { diff --git a/packages/mui-base/src/Popover/Close/PopoverClose.test.tsx b/packages/mui-base/src/Popover/Close/PopoverClose.test.tsx index afae2d742..c1c5f89d8 100644 --- a/packages/mui-base/src/Popover/Close/PopoverClose.test.tsx +++ b/packages/mui-base/src/Popover/Close/PopoverClose.test.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import * as Popover from '@base_ui/react/Popover'; +import { Popover } from '@base_ui/react/Popover'; import { fireEvent, screen } from '@mui/internal-test-utils'; import { expect } from 'chai'; import { createRenderer, describeConformance } from '#test-utils'; diff --git a/packages/mui-base/src/Popover/Description/PopoverDescription.test.tsx b/packages/mui-base/src/Popover/Description/PopoverDescription.test.tsx index ee77306db..0a5026766 100644 --- a/packages/mui-base/src/Popover/Description/PopoverDescription.test.tsx +++ b/packages/mui-base/src/Popover/Description/PopoverDescription.test.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import * as Popover from '@base_ui/react/Popover'; +import { Popover } from '@base_ui/react/Popover'; import { screen } from '@mui/internal-test-utils'; import { expect } from 'chai'; import { createRenderer, describeConformance } from '#test-utils'; diff --git a/packages/mui-base/src/Popover/Popup/PopoverPopup.test.tsx b/packages/mui-base/src/Popover/Popup/PopoverPopup.test.tsx index 6475a3162..f3f3b6809 100644 --- a/packages/mui-base/src/Popover/Popup/PopoverPopup.test.tsx +++ b/packages/mui-base/src/Popover/Popup/PopoverPopup.test.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import * as Popover from '@base_ui/react/Popover'; +import { Popover } from '@base_ui/react/Popover'; import { screen } from '@mui/internal-test-utils'; import { expect } from 'chai'; import { createRenderer, describeConformance } from '#test-utils'; diff --git a/packages/mui-base/src/Popover/Positioner/PopoverPositioner.test.tsx b/packages/mui-base/src/Popover/Positioner/PopoverPositioner.test.tsx index 826b63acb..f784a5109 100644 --- a/packages/mui-base/src/Popover/Positioner/PopoverPositioner.test.tsx +++ b/packages/mui-base/src/Popover/Positioner/PopoverPositioner.test.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import * as Popover from '@base_ui/react/Popover'; +import { Popover } from '@base_ui/react/Popover'; import { createRenderer, describeConformance } from '#test-utils'; import { screen } from '@mui/internal-test-utils'; import { expect } from 'chai'; diff --git a/packages/mui-base/src/Popover/Root/PopoverRoot.test.tsx b/packages/mui-base/src/Popover/Root/PopoverRoot.test.tsx index 1beb90695..029c349c1 100644 --- a/packages/mui-base/src/Popover/Root/PopoverRoot.test.tsx +++ b/packages/mui-base/src/Popover/Root/PopoverRoot.test.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import * as Popover from '@base_ui/react/Popover'; +import { Popover } from '@base_ui/react/Popover'; import { fireEvent, flushMicrotasks, screen, waitFor } from '@mui/internal-test-utils'; import userEvent from '@testing-library/user-event'; import { expect } from 'chai'; diff --git a/packages/mui-base/src/Popover/Title/PopoverTitle.test.tsx b/packages/mui-base/src/Popover/Title/PopoverTitle.test.tsx index 9898507ba..3b039e6c2 100644 --- a/packages/mui-base/src/Popover/Title/PopoverTitle.test.tsx +++ b/packages/mui-base/src/Popover/Title/PopoverTitle.test.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import * as Popover from '@base_ui/react/Popover'; +import { Popover } from '@base_ui/react/Popover'; import { screen } from '@mui/internal-test-utils'; import { expect } from 'chai'; import { createRenderer, describeConformance } from '#test-utils'; diff --git a/packages/mui-base/src/Popover/Trigger/PopoverTrigger.test.tsx b/packages/mui-base/src/Popover/Trigger/PopoverTrigger.test.tsx index 2a6f1879a..9bb0c7773 100644 --- a/packages/mui-base/src/Popover/Trigger/PopoverTrigger.test.tsx +++ b/packages/mui-base/src/Popover/Trigger/PopoverTrigger.test.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import * as Popover from '@base_ui/react/Popover'; +import { Popover } from '@base_ui/react/Popover'; import { createRenderer, describeConformance } from '#test-utils'; describe('', () => { diff --git a/packages/mui-base/src/Popover/index.barrel.ts b/packages/mui-base/src/Popover/index.barrel.ts deleted file mode 100644 index d970c32ab..000000000 --- a/packages/mui-base/src/Popover/index.barrel.ts +++ /dev/null @@ -1,9 +0,0 @@ -export { PopoverRoot } from './Root/PopoverRoot'; -export { PopoverTrigger } from './Trigger/PopoverTrigger'; -export { PopoverPositioner } from './Positioner/PopoverPositioner'; -export { PopoverPopup } from './Popup/PopoverPopup'; -export { PopoverArrow } from './Arrow/PopoverArrow'; -export { PopoverBackdrop } from './Backdrop/PopoverBackdrop'; -export { PopoverTitle } from './Title/PopoverTitle'; -export { PopoverDescription } from './Description/PopoverDescription'; -export { PopoverClose } from './Close/PopoverClose'; diff --git a/packages/mui-base/src/Popover/index.parts.ts b/packages/mui-base/src/Popover/index.parts.ts new file mode 100644 index 000000000..a025e3962 --- /dev/null +++ b/packages/mui-base/src/Popover/index.parts.ts @@ -0,0 +1,9 @@ +export { PopoverRoot as Root } from './Root/PopoverRoot'; +export { PopoverTrigger as Trigger } from './Trigger/PopoverTrigger'; +export { PopoverPositioner as Positioner } from './Positioner/PopoverPositioner'; +export { PopoverPopup as Popup } from './Popup/PopoverPopup'; +export { PopoverArrow as Arrow } from './Arrow/PopoverArrow'; +export { PopoverBackdrop as Backdrop } from './Backdrop/PopoverBackdrop'; +export { PopoverTitle as Title } from './Title/PopoverTitle'; +export { PopoverDescription as Description } from './Description/PopoverDescription'; +export { PopoverClose as Close } from './Close/PopoverClose'; diff --git a/packages/mui-base/src/Popover/index.ts b/packages/mui-base/src/Popover/index.ts index a025e3962..9d2d8d70b 100644 --- a/packages/mui-base/src/Popover/index.ts +++ b/packages/mui-base/src/Popover/index.ts @@ -1,9 +1 @@ -export { PopoverRoot as Root } from './Root/PopoverRoot'; -export { PopoverTrigger as Trigger } from './Trigger/PopoverTrigger'; -export { PopoverPositioner as Positioner } from './Positioner/PopoverPositioner'; -export { PopoverPopup as Popup } from './Popup/PopoverPopup'; -export { PopoverArrow as Arrow } from './Arrow/PopoverArrow'; -export { PopoverBackdrop as Backdrop } from './Backdrop/PopoverBackdrop'; -export { PopoverTitle as Title } from './Title/PopoverTitle'; -export { PopoverDescription as Description } from './Description/PopoverDescription'; -export { PopoverClose as Close } from './Close/PopoverClose'; +export * as Popover from './index.parts'; diff --git a/packages/mui-base/src/PreviewCard/Arrow/PreviewCardArrow.test.tsx b/packages/mui-base/src/PreviewCard/Arrow/PreviewCardArrow.test.tsx index 5fa3656de..4ba368f3c 100644 --- a/packages/mui-base/src/PreviewCard/Arrow/PreviewCardArrow.test.tsx +++ b/packages/mui-base/src/PreviewCard/Arrow/PreviewCardArrow.test.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import * as PreviewCard from '@base_ui/react/PreviewCard'; +import { PreviewCard } from '@base_ui/react/PreviewCard'; import { createRenderer, describeConformance } from '#test-utils'; describe('', () => { diff --git a/packages/mui-base/src/PreviewCard/Backdrop/PreviewCardBackdrop.test.tsx b/packages/mui-base/src/PreviewCard/Backdrop/PreviewCardBackdrop.test.tsx index 92bba7d84..41bef53f6 100644 --- a/packages/mui-base/src/PreviewCard/Backdrop/PreviewCardBackdrop.test.tsx +++ b/packages/mui-base/src/PreviewCard/Backdrop/PreviewCardBackdrop.test.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import * as PreviewCard from '@base_ui/react/PreviewCard'; +import { PreviewCard } from '@base_ui/react/PreviewCard'; import { createRenderer, describeConformance } from '#test-utils'; describe('', () => { diff --git a/packages/mui-base/src/PreviewCard/Popup/PreviewCardPopup.test.tsx b/packages/mui-base/src/PreviewCard/Popup/PreviewCardPopup.test.tsx index b7568d8e5..9f417277c 100644 --- a/packages/mui-base/src/PreviewCard/Popup/PreviewCardPopup.test.tsx +++ b/packages/mui-base/src/PreviewCard/Popup/PreviewCardPopup.test.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import * as PreviewCard from '@base_ui/react/PreviewCard'; +import { PreviewCard } from '@base_ui/react/PreviewCard'; import { screen } from '@mui/internal-test-utils'; import { expect } from 'chai'; import { createRenderer, describeConformance } from '#test-utils'; diff --git a/packages/mui-base/src/PreviewCard/Positioner/PreviewCardPositioner.test.tsx b/packages/mui-base/src/PreviewCard/Positioner/PreviewCardPositioner.test.tsx index 30ce4ce86..1c57cda67 100644 --- a/packages/mui-base/src/PreviewCard/Positioner/PreviewCardPositioner.test.tsx +++ b/packages/mui-base/src/PreviewCard/Positioner/PreviewCardPositioner.test.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import * as PreviewCard from '@base_ui/react/PreviewCard'; +import { PreviewCard } from '@base_ui/react/PreviewCard'; import { createRenderer, describeConformance } from '#test-utils'; describe('', () => { diff --git a/packages/mui-base/src/PreviewCard/Root/PreviewCardRoot.test.tsx b/packages/mui-base/src/PreviewCard/Root/PreviewCardRoot.test.tsx index 14d80b1e6..b379c31fe 100644 --- a/packages/mui-base/src/PreviewCard/Root/PreviewCardRoot.test.tsx +++ b/packages/mui-base/src/PreviewCard/Root/PreviewCardRoot.test.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import * as PreviewCard from '@base_ui/react/PreviewCard'; +import { PreviewCard } from '@base_ui/react/PreviewCard'; import { act, fireEvent, screen, flushMicrotasks } from '@mui/internal-test-utils'; import { expect } from 'chai'; import { spy } from 'sinon'; diff --git a/packages/mui-base/src/PreviewCard/Trigger/PreviewCardTrigger.test.tsx b/packages/mui-base/src/PreviewCard/Trigger/PreviewCardTrigger.test.tsx index 8afd7ddc5..6051aafcc 100644 --- a/packages/mui-base/src/PreviewCard/Trigger/PreviewCardTrigger.test.tsx +++ b/packages/mui-base/src/PreviewCard/Trigger/PreviewCardTrigger.test.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import * as PreviewCard from '@base_ui/react/PreviewCard'; +import { PreviewCard } from '@base_ui/react/PreviewCard'; import { createRenderer, describeConformance } from '#test-utils'; describe('', () => { diff --git a/packages/mui-base/src/PreviewCard/index.barrel.ts b/packages/mui-base/src/PreviewCard/index.barrel.ts deleted file mode 100644 index 685af207d..000000000 --- a/packages/mui-base/src/PreviewCard/index.barrel.ts +++ /dev/null @@ -1,6 +0,0 @@ -export { PreviewCardRoot } from './Root/PreviewCardRoot'; -export { PreviewCardTrigger } from './Trigger/PreviewCardTrigger'; -export { PreviewCardPositioner } from './Positioner/PreviewCardPositioner'; -export { PreviewCardPopup } from './Popup/PreviewCardPopup'; -export { PreviewCardArrow } from './Arrow/PreviewCardArrow'; -export { PreviewCardBackdrop } from './Backdrop/PreviewCardBackdrop'; diff --git a/packages/mui-base/src/PreviewCard/index.parts.ts b/packages/mui-base/src/PreviewCard/index.parts.ts new file mode 100644 index 000000000..291940ad6 --- /dev/null +++ b/packages/mui-base/src/PreviewCard/index.parts.ts @@ -0,0 +1,6 @@ +export { PreviewCardRoot as Root } from './Root/PreviewCardRoot'; +export { PreviewCardTrigger as Trigger } from './Trigger/PreviewCardTrigger'; +export { PreviewCardPositioner as Positioner } from './Positioner/PreviewCardPositioner'; +export { PreviewCardPopup as Popup } from './Popup/PreviewCardPopup'; +export { PreviewCardArrow as Arrow } from './Arrow/PreviewCardArrow'; +export { PreviewCardBackdrop as Backdrop } from './Backdrop/PreviewCardBackdrop'; diff --git a/packages/mui-base/src/PreviewCard/index.ts b/packages/mui-base/src/PreviewCard/index.ts index 291940ad6..848affb96 100644 --- a/packages/mui-base/src/PreviewCard/index.ts +++ b/packages/mui-base/src/PreviewCard/index.ts @@ -1,6 +1 @@ -export { PreviewCardRoot as Root } from './Root/PreviewCardRoot'; -export { PreviewCardTrigger as Trigger } from './Trigger/PreviewCardTrigger'; -export { PreviewCardPositioner as Positioner } from './Positioner/PreviewCardPositioner'; -export { PreviewCardPopup as Popup } from './Popup/PreviewCardPopup'; -export { PreviewCardArrow as Arrow } from './Arrow/PreviewCardArrow'; -export { PreviewCardBackdrop as Backdrop } from './Backdrop/PreviewCardBackdrop'; +export * as PreviewCard from './index.parts'; diff --git a/packages/mui-base/src/Progress/Indicator/ProgressIndicator.test.tsx b/packages/mui-base/src/Progress/Indicator/ProgressIndicator.test.tsx index 33256bf37..a2012fb4c 100644 --- a/packages/mui-base/src/Progress/Indicator/ProgressIndicator.test.tsx +++ b/packages/mui-base/src/Progress/Indicator/ProgressIndicator.test.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import { expect } from 'chai'; -import * as Progress from '@base_ui/react/Progress'; +import { Progress } from '@base_ui/react/Progress'; import { createRenderer, describeConformance } from '#test-utils'; import { ProgressRootContext } from '../Root/ProgressRootContext'; diff --git a/packages/mui-base/src/Progress/Root/ProgressRoot.test.tsx b/packages/mui-base/src/Progress/Root/ProgressRoot.test.tsx index 1e9e12fca..344f4d981 100644 --- a/packages/mui-base/src/Progress/Root/ProgressRoot.test.tsx +++ b/packages/mui-base/src/Progress/Root/ProgressRoot.test.tsx @@ -1,6 +1,6 @@ import { expect } from 'chai'; import * as React from 'react'; -import * as Progress from '@base_ui/react/Progress'; +import { Progress } from '@base_ui/react/Progress'; import { createRenderer, describeConformance } from '#test-utils'; import type { ProgressRoot } from './ProgressRoot'; diff --git a/packages/mui-base/src/Progress/Track/ProgressTrack.test.tsx b/packages/mui-base/src/Progress/Track/ProgressTrack.test.tsx index 197207bfa..27e8c204a 100644 --- a/packages/mui-base/src/Progress/Track/ProgressTrack.test.tsx +++ b/packages/mui-base/src/Progress/Track/ProgressTrack.test.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import * as Progress from '@base_ui/react/Progress'; +import { Progress } from '@base_ui/react/Progress'; import { createRenderer, describeConformance } from '#test-utils'; import { ProgressRootContext } from '../Root/ProgressRootContext'; diff --git a/packages/mui-base/src/Progress/index.barrel.ts b/packages/mui-base/src/Progress/index.barrel.ts deleted file mode 100644 index 677acec64..000000000 --- a/packages/mui-base/src/Progress/index.barrel.ts +++ /dev/null @@ -1,8 +0,0 @@ -export { ProgressRoot } from './Root/ProgressRoot'; -export { ProgressTrack } from './Track/ProgressTrack'; -export { ProgressIndicator } from './Indicator/ProgressIndicator'; - -export type { - ProgressStatus as Status, - ProgressDirection as Direction, -} from './Root/useProgressRoot'; diff --git a/packages/mui-base/src/Progress/index.parts.ts b/packages/mui-base/src/Progress/index.parts.ts new file mode 100644 index 000000000..5e0d1453f --- /dev/null +++ b/packages/mui-base/src/Progress/index.parts.ts @@ -0,0 +1,8 @@ +export { ProgressRoot as Root } from './Root/ProgressRoot'; +export { ProgressTrack as Track } from './Track/ProgressTrack'; +export { ProgressIndicator as Indicator } from './Indicator/ProgressIndicator'; + +export type { + ProgressStatus as Status, + ProgressDirection as Direction, +} from './Root/useProgressRoot'; diff --git a/packages/mui-base/src/Progress/index.ts b/packages/mui-base/src/Progress/index.ts index 5e0d1453f..ee913fe81 100644 --- a/packages/mui-base/src/Progress/index.ts +++ b/packages/mui-base/src/Progress/index.ts @@ -1,8 +1 @@ -export { ProgressRoot as Root } from './Root/ProgressRoot'; -export { ProgressTrack as Track } from './Track/ProgressTrack'; -export { ProgressIndicator as Indicator } from './Indicator/ProgressIndicator'; - -export type { - ProgressStatus as Status, - ProgressDirection as Direction, -} from './Root/useProgressRoot'; +export * as Progress from './index.parts'; diff --git a/packages/mui-base/src/Radio/Indicator/RadioIndicator.test.tsx b/packages/mui-base/src/Radio/Indicator/RadioIndicator.test.tsx index d2d03649d..9250c941f 100644 --- a/packages/mui-base/src/Radio/Indicator/RadioIndicator.test.tsx +++ b/packages/mui-base/src/Radio/Indicator/RadioIndicator.test.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import { createRenderer } from '@mui/internal-test-utils'; -import * as Radio from '@base_ui/react/Radio'; +import { Radio } from '@base_ui/react/Radio'; import { describeConformance } from '../../../test/describeConformance'; describe('', () => { diff --git a/packages/mui-base/src/Radio/Root/RadioRoot.test.tsx b/packages/mui-base/src/Radio/Root/RadioRoot.test.tsx index cc117d358..75fac1a11 100644 --- a/packages/mui-base/src/Radio/Root/RadioRoot.test.tsx +++ b/packages/mui-base/src/Radio/Root/RadioRoot.test.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import { createRenderer } from '@mui/internal-test-utils'; -import * as Radio from '@base_ui/react/Radio'; +import { Radio } from '@base_ui/react/Radio'; import { describeConformance } from '../../../test/describeConformance'; describe('', () => { diff --git a/packages/mui-base/src/Radio/index.barrel.ts b/packages/mui-base/src/Radio/index.barrel.ts deleted file mode 100644 index dc4fbc653..000000000 --- a/packages/mui-base/src/Radio/index.barrel.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { RadioRoot } from './Root/RadioRoot'; -export { RadioIndicator } from './Indicator/RadioIndicator'; diff --git a/packages/mui-base/src/Radio/index.parts.ts b/packages/mui-base/src/Radio/index.parts.ts new file mode 100644 index 000000000..e5baf0747 --- /dev/null +++ b/packages/mui-base/src/Radio/index.parts.ts @@ -0,0 +1,2 @@ +export { RadioRoot as Root } from './Root/RadioRoot'; +export { RadioIndicator as Indicator } from './Indicator/RadioIndicator'; diff --git a/packages/mui-base/src/Radio/index.ts b/packages/mui-base/src/Radio/index.ts index e5baf0747..19f101399 100644 --- a/packages/mui-base/src/Radio/index.ts +++ b/packages/mui-base/src/Radio/index.ts @@ -1,2 +1 @@ -export { RadioRoot as Root } from './Root/RadioRoot'; -export { RadioIndicator as Indicator } from './Indicator/RadioIndicator'; +export * as Radio from './index.parts'; diff --git a/packages/mui-base/src/RadioGroup/Root/RadioGroupRoot.test.tsx b/packages/mui-base/src/RadioGroup/Root/RadioGroupRoot.test.tsx index ff9cc5b44..8336d7c4e 100644 --- a/packages/mui-base/src/RadioGroup/Root/RadioGroupRoot.test.tsx +++ b/packages/mui-base/src/RadioGroup/Root/RadioGroupRoot.test.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; -import * as RadioGroup from '@base_ui/react/RadioGroup'; -import * as Radio from '@base_ui/react/Radio'; +import { RadioGroup } from '@base_ui/react/RadioGroup'; +import { Radio } from '@base_ui/react/Radio'; import { expect } from 'chai'; import { spy } from 'sinon'; import { createRenderer, act, screen, fireEvent } from '@mui/internal-test-utils'; diff --git a/packages/mui-base/src/RadioGroup/index.barrel.ts b/packages/mui-base/src/RadioGroup/index.barrel.ts deleted file mode 100644 index 3d7b2c936..000000000 --- a/packages/mui-base/src/RadioGroup/index.barrel.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './Root/RadioGroupRoot'; diff --git a/packages/mui-base/src/RadioGroup/index.parts.ts b/packages/mui-base/src/RadioGroup/index.parts.ts new file mode 100644 index 000000000..f78d65457 --- /dev/null +++ b/packages/mui-base/src/RadioGroup/index.parts.ts @@ -0,0 +1 @@ +export { RadioGroupRoot as Root } from './Root/RadioGroupRoot'; diff --git a/packages/mui-base/src/RadioGroup/index.ts b/packages/mui-base/src/RadioGroup/index.ts index f78d65457..4dd85fb1e 100644 --- a/packages/mui-base/src/RadioGroup/index.ts +++ b/packages/mui-base/src/RadioGroup/index.ts @@ -1 +1 @@ -export { RadioGroupRoot as Root } from './Root/RadioGroupRoot'; +export * as RadioGroup from './index.parts'; diff --git a/packages/mui-base/src/Separator/Root/SeparatorRoot.test.tsx b/packages/mui-base/src/Separator/Root/SeparatorRoot.test.tsx index a6b54ae71..9edbcbd32 100644 --- a/packages/mui-base/src/Separator/Root/SeparatorRoot.test.tsx +++ b/packages/mui-base/src/Separator/Root/SeparatorRoot.test.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import { expect } from 'chai'; -import * as Separator from '@base_ui/react/Separator'; +import { Separator } from '@base_ui/react/Separator'; import { createRenderer, describeConformance } from '#test-utils'; describe('', () => { diff --git a/packages/mui-base/src/Separator/index.barrel.ts b/packages/mui-base/src/Separator/index.barrel.ts deleted file mode 100644 index 92574247c..000000000 --- a/packages/mui-base/src/Separator/index.barrel.ts +++ /dev/null @@ -1 +0,0 @@ -export { SeparatorRoot } from './Root/SeparatorRoot'; diff --git a/packages/mui-base/src/Separator/index.parts.ts b/packages/mui-base/src/Separator/index.parts.ts new file mode 100644 index 000000000..01851cba2 --- /dev/null +++ b/packages/mui-base/src/Separator/index.parts.ts @@ -0,0 +1 @@ +export { SeparatorRoot as Root } from './Root/SeparatorRoot'; diff --git a/packages/mui-base/src/Separator/index.ts b/packages/mui-base/src/Separator/index.ts index 01851cba2..da5e8c68c 100644 --- a/packages/mui-base/src/Separator/index.ts +++ b/packages/mui-base/src/Separator/index.ts @@ -1 +1 @@ -export { SeparatorRoot as Root } from './Root/SeparatorRoot'; +export * as Separator from './index.parts'; diff --git a/packages/mui-base/src/Slider/Control/SliderControl.test.tsx b/packages/mui-base/src/Slider/Control/SliderControl.test.tsx index 45f5c31eb..c09ba78a1 100644 --- a/packages/mui-base/src/Slider/Control/SliderControl.test.tsx +++ b/packages/mui-base/src/Slider/Control/SliderControl.test.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; -import * as Slider from '@base_ui/react/Slider'; -import { SliderProvider, type SliderProviderValue } from '@base_ui/react/Slider'; +import { Slider } from '@base_ui/react/Slider'; +import { SliderProvider, type SliderProviderValue } from '@base_ui/react/Slider/index.parts'; import { createRenderer, describeConformance } from '#test-utils'; const NOOP = () => {}; diff --git a/packages/mui-base/src/Slider/Indicator/SliderIndicator.test.tsx b/packages/mui-base/src/Slider/Indicator/SliderIndicator.test.tsx index b5f19049b..979b288ed 100644 --- a/packages/mui-base/src/Slider/Indicator/SliderIndicator.test.tsx +++ b/packages/mui-base/src/Slider/Indicator/SliderIndicator.test.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; -import * as Slider from '@base_ui/react/Slider'; -import { SliderProvider, type SliderProviderValue } from '@base_ui/react/Slider'; +import { Slider } from '@base_ui/react/Slider'; +import { SliderProvider, type SliderProviderValue } from '@base_ui/react/Slider/index.parts'; import { createRenderer, describeConformance } from '#test-utils'; const NOOP = () => {}; diff --git a/packages/mui-base/src/Slider/Output/SliderOutput.test.tsx b/packages/mui-base/src/Slider/Output/SliderOutput.test.tsx index fac49ee9e..62d26e9c5 100644 --- a/packages/mui-base/src/Slider/Output/SliderOutput.test.tsx +++ b/packages/mui-base/src/Slider/Output/SliderOutput.test.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import { expect } from 'chai'; -import * as Slider from '@base_ui/react/Slider'; -import { SliderProvider, type SliderProviderValue } from '@base_ui/react/Slider'; +import { Slider } from '@base_ui/react/Slider'; +import { SliderProvider, type SliderProviderValue } from '@base_ui/react/Slider/index.parts'; import { createRenderer, describeConformance } from '#test-utils'; const NOOP = () => {}; diff --git a/packages/mui-base/src/Slider/Root/SliderRoot.test.tsx b/packages/mui-base/src/Slider/Root/SliderRoot.test.tsx index 6a1741c2b..e6ca53c50 100644 --- a/packages/mui-base/src/Slider/Root/SliderRoot.test.tsx +++ b/packages/mui-base/src/Slider/Root/SliderRoot.test.tsx @@ -2,7 +2,7 @@ import { expect } from 'chai'; import * as React from 'react'; import { spy, stub } from 'sinon'; import { act, fireEvent, screen } from '@mui/internal-test-utils'; -import * as Slider from '@base_ui/react/Slider'; +import { Slider } from '@base_ui/react/Slider'; import { createRenderer, describeConformance } from '#test-utils'; import type { SliderRootProps } from './SliderRoot.types'; diff --git a/packages/mui-base/src/Slider/Thumb/SliderThumb.test.tsx b/packages/mui-base/src/Slider/Thumb/SliderThumb.test.tsx index 3d6519853..c04cf8180 100644 --- a/packages/mui-base/src/Slider/Thumb/SliderThumb.test.tsx +++ b/packages/mui-base/src/Slider/Thumb/SliderThumb.test.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; -import * as Slider from '@base_ui/react/Slider'; -import { SliderProvider, type SliderProviderValue } from '@base_ui/react/Slider'; +import { Slider } from '@base_ui/react/Slider'; +import { SliderProvider, type SliderProviderValue } from '@base_ui/react/Slider/index.parts'; import { createRenderer, describeConformance } from '#test-utils'; const NOOP = () => {}; diff --git a/packages/mui-base/src/Slider/Track/SliderTrack.test.tsx b/packages/mui-base/src/Slider/Track/SliderTrack.test.tsx index a28829b12..382583c21 100644 --- a/packages/mui-base/src/Slider/Track/SliderTrack.test.tsx +++ b/packages/mui-base/src/Slider/Track/SliderTrack.test.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; -import * as Slider from '@base_ui/react/Slider'; -import { SliderProvider, type SliderProviderValue } from '@base_ui/react/Slider'; +import { Slider } from '@base_ui/react/Slider'; +import { SliderProvider, type SliderProviderValue } from '@base_ui/react/Slider/index.parts'; import { createRenderer, describeConformance } from '#test-utils'; const NOOP = () => {}; diff --git a/packages/mui-base/src/Slider/index.barrel.ts b/packages/mui-base/src/Slider/index.parts.ts similarity index 53% rename from packages/mui-base/src/Slider/index.barrel.ts rename to packages/mui-base/src/Slider/index.parts.ts index 79a640ba7..be5d9c2dc 100644 --- a/packages/mui-base/src/Slider/index.barrel.ts +++ b/packages/mui-base/src/Slider/index.parts.ts @@ -1,9 +1,18 @@ -export { SliderRoot } from './Root/SliderRoot'; -export type * from './Root/SliderRoot.types'; +export { SliderRoot as Root } from './Root/SliderRoot'; +export type { + SliderRootOwnerState as SliderOwnerState, + SliderRootProps as RootProps, + UseSliderParameters, + UseSliderReturnValue, + SliderContextValue, + SliderProviderValue, + SliderThumbMetadata, + Axis, +} from './Root/SliderRoot.types'; export { useSliderRoot } from './Root/useSliderRoot'; export * from './Root/SliderProvider'; -export { SliderOutput } from './Output/SliderOutput'; +export { SliderOutput as Output } from './Output/SliderOutput'; export type { SliderOutputProps as OutputProps, UseSliderOutputParameters, @@ -11,7 +20,7 @@ export type { } from './Output/SliderOutput.types'; export { useSliderOutput } from './Output/useSliderOutput'; -export { SliderControl } from './Control/SliderControl'; +export { SliderControl as Control } from './Control/SliderControl'; export type { SliderControlProps as ControlProps, UseSliderControlParameters, @@ -19,19 +28,19 @@ export type { } from './Control/SliderControl.types'; export { useSliderControl } from './Control/useSliderControl'; -export { SliderTrack } from './Track/SliderTrack'; -export type { SliderTrackProps } from './Track/SliderTrack.types'; +export { SliderTrack as Track } from './Track/SliderTrack'; +export type { SliderTrackProps as TrackProps } from './Track/SliderTrack.types'; -export { SliderThumb } from './Thumb/SliderThumb'; +export { SliderThumb as Thumb } from './Thumb/SliderThumb'; export type { - SliderThumbOwnerState, - SliderThumbProps, + SliderThumbOwnerState as ThumbOwnerState, + SliderThumbProps as ThumbProps, UseSliderThumbParameters, UseSliderThumbReturnValue, } from './Thumb/SliderThumb.types'; export { useSliderThumb } from './Thumb/useSliderThumb'; -export { SliderIndicator } from './Indicator/SliderIndicator'; +export { SliderIndicator as Indicator } from './Indicator/SliderIndicator'; export type { SliderIndicatorProps as IndicatorProps, UseSliderIndicatorParameters, diff --git a/packages/mui-base/src/Slider/index.ts b/packages/mui-base/src/Slider/index.ts index be5d9c2dc..953696abe 100644 --- a/packages/mui-base/src/Slider/index.ts +++ b/packages/mui-base/src/Slider/index.ts @@ -1,49 +1 @@ -export { SliderRoot as Root } from './Root/SliderRoot'; -export type { - SliderRootOwnerState as SliderOwnerState, - SliderRootProps as RootProps, - UseSliderParameters, - UseSliderReturnValue, - SliderContextValue, - SliderProviderValue, - SliderThumbMetadata, - Axis, -} from './Root/SliderRoot.types'; -export { useSliderRoot } from './Root/useSliderRoot'; -export * from './Root/SliderProvider'; - -export { SliderOutput as Output } from './Output/SliderOutput'; -export type { - SliderOutputProps as OutputProps, - UseSliderOutputParameters, - UseSliderOutputReturnValue, -} from './Output/SliderOutput.types'; -export { useSliderOutput } from './Output/useSliderOutput'; - -export { SliderControl as Control } from './Control/SliderControl'; -export type { - SliderControlProps as ControlProps, - UseSliderControlParameters, - UseSliderControlReturnValue, -} from './Control/SliderControl.types'; -export { useSliderControl } from './Control/useSliderControl'; - -export { SliderTrack as Track } from './Track/SliderTrack'; -export type { SliderTrackProps as TrackProps } from './Track/SliderTrack.types'; - -export { SliderThumb as Thumb } from './Thumb/SliderThumb'; -export type { - SliderThumbOwnerState as ThumbOwnerState, - SliderThumbProps as ThumbProps, - UseSliderThumbParameters, - UseSliderThumbReturnValue, -} from './Thumb/SliderThumb.types'; -export { useSliderThumb } from './Thumb/useSliderThumb'; - -export { SliderIndicator as Indicator } from './Indicator/SliderIndicator'; -export type { - SliderIndicatorProps as IndicatorProps, - UseSliderIndicatorParameters, - UseSliderIndicatorReturnValue, -} from './Indicator/SliderIndicator.types'; -export { useSliderIndicator } from './Indicator/useSliderIndicator'; +export * as Slider from './index.parts'; diff --git a/packages/mui-base/src/Switch/Root/SwitchRoot.test.tsx b/packages/mui-base/src/Switch/Root/SwitchRoot.test.tsx index 110ee301e..0a612b998 100644 --- a/packages/mui-base/src/Switch/Root/SwitchRoot.test.tsx +++ b/packages/mui-base/src/Switch/Root/SwitchRoot.test.tsx @@ -2,7 +2,7 @@ import * as React from 'react'; import { expect } from 'chai'; import { spy } from 'sinon'; import { act, fireEvent, screen } from '@mui/internal-test-utils'; -import * as Switch from '@base_ui/react/Switch'; +import { Switch } from '@base_ui/react/Switch'; import { userEvent } from '@testing-library/user-event'; import { describeConformance, createRenderer } from '#test-utils'; diff --git a/packages/mui-base/src/Switch/Thumb/SwitchThumb.test.tsx b/packages/mui-base/src/Switch/Thumb/SwitchThumb.test.tsx index 9e49e094b..8f002d66b 100644 --- a/packages/mui-base/src/Switch/Thumb/SwitchThumb.test.tsx +++ b/packages/mui-base/src/Switch/Thumb/SwitchThumb.test.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import * as Switch from '@base_ui/react/Switch'; +import { Switch } from '@base_ui/react/Switch'; import { createRenderer, describeConformance } from '#test-utils'; import { SwitchRootContext } from '../Root/SwitchRootContext'; diff --git a/packages/mui-base/src/Switch/index.barrel.ts b/packages/mui-base/src/Switch/index.barrel.ts deleted file mode 100644 index f717fab5a..000000000 --- a/packages/mui-base/src/Switch/index.barrel.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { SwitchRoot } from './Root/SwitchRoot'; -export { SwitchThumb } from './Thumb/SwitchThumb'; diff --git a/packages/mui-base/src/Switch/index.parts.ts b/packages/mui-base/src/Switch/index.parts.ts new file mode 100644 index 000000000..7edb4a433 --- /dev/null +++ b/packages/mui-base/src/Switch/index.parts.ts @@ -0,0 +1,2 @@ +export { SwitchRoot as Root } from './Root/SwitchRoot'; +export { SwitchThumb as Thumb } from './Thumb/SwitchThumb'; diff --git a/packages/mui-base/src/Switch/index.ts b/packages/mui-base/src/Switch/index.ts index 7edb4a433..4b7a983cb 100644 --- a/packages/mui-base/src/Switch/index.ts +++ b/packages/mui-base/src/Switch/index.ts @@ -1,2 +1 @@ -export { SwitchRoot as Root } from './Root/SwitchRoot'; -export { SwitchThumb as Thumb } from './Thumb/SwitchThumb'; +export * as Switch from './index.parts'; diff --git a/packages/mui-base/src/Tabs/Root/TabsRoot.test.tsx b/packages/mui-base/src/Tabs/Root/TabsRoot.test.tsx index 24900b5a2..30be9b350 100644 --- a/packages/mui-base/src/Tabs/Root/TabsRoot.test.tsx +++ b/packages/mui-base/src/Tabs/Root/TabsRoot.test.tsx @@ -2,7 +2,7 @@ import * as React from 'react'; import { expect } from 'chai'; import { spy } from 'sinon'; import { act, fireEvent, screen } from '@mui/internal-test-utils'; -import * as Tabs from '@base_ui/react/Tabs'; +import { Tabs } from '@base_ui/react/Tabs'; import { createRenderer, describeConformance } from '#test-utils'; describe('', () => { diff --git a/packages/mui-base/src/Tabs/Tab/Tab.test.tsx b/packages/mui-base/src/Tabs/Tab/Tab.test.tsx index 328052085..5a899d1fb 100644 --- a/packages/mui-base/src/Tabs/Tab/Tab.test.tsx +++ b/packages/mui-base/src/Tabs/Tab/Tab.test.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import * as Tabs from '@base_ui/react/Tabs'; +import { Tabs } from '@base_ui/react/Tabs'; import { createRenderer, describeConformance } from '#test-utils'; import { TabsListProviderValue, TabsListProvider } from '../TabsList/TabsListProvider'; import { TabsRootContext } from '../Root/TabsRootContext'; diff --git a/packages/mui-base/src/Tabs/Tab/useTab.test.tsx b/packages/mui-base/src/Tabs/Tab/useTab.test.tsx index 34b550ee9..7d7e5a304 100644 --- a/packages/mui-base/src/Tabs/Tab/useTab.test.tsx +++ b/packages/mui-base/src/Tabs/Tab/useTab.test.tsx @@ -2,7 +2,7 @@ import * as React from 'react'; import { expect } from 'chai'; import { spy } from 'sinon'; import { createRenderer, screen, fireEvent } from '@mui/internal-test-utils'; -import * as Tabs from '@base_ui/react/Tabs'; +import { Tabs } from '@base_ui/react/Tabs'; import { useTab } from './useTab'; describe('useTab', () => { diff --git a/packages/mui-base/src/Tabs/TabIndicator/TabIndicator.test.tsx b/packages/mui-base/src/Tabs/TabIndicator/TabIndicator.test.tsx index 7cfbe38a8..16b755f0d 100644 --- a/packages/mui-base/src/Tabs/TabIndicator/TabIndicator.test.tsx +++ b/packages/mui-base/src/Tabs/TabIndicator/TabIndicator.test.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import { expect } from 'chai'; -import * as Tabs from '@base_ui/react/Tabs'; +import { Tabs } from '@base_ui/react/Tabs'; import { waitFor } from '@mui/internal-test-utils'; import { createRenderer, describeConformance } from '#test-utils'; diff --git a/packages/mui-base/src/Tabs/TabPanel/TabPanel.test.tsx b/packages/mui-base/src/Tabs/TabPanel/TabPanel.test.tsx index b17e0b994..727044873 100644 --- a/packages/mui-base/src/Tabs/TabPanel/TabPanel.test.tsx +++ b/packages/mui-base/src/Tabs/TabPanel/TabPanel.test.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import * as Tabs from '@base_ui/react/Tabs'; +import { Tabs } from '@base_ui/react/Tabs'; import { createRenderer, describeConformance } from '#test-utils'; import { TabsProvider, TabsProviderValue } from '../Root/TabsProvider'; diff --git a/packages/mui-base/src/Tabs/TabPanel/useTabPanel.test.tsx b/packages/mui-base/src/Tabs/TabPanel/useTabPanel.test.tsx index 3e9b644a9..bbbe3ba40 100644 --- a/packages/mui-base/src/Tabs/TabPanel/useTabPanel.test.tsx +++ b/packages/mui-base/src/Tabs/TabPanel/useTabPanel.test.tsx @@ -2,7 +2,7 @@ import * as React from 'react'; import { expect } from 'chai'; import { spy } from 'sinon'; import { createRenderer, screen, fireEvent } from '@mui/internal-test-utils'; -import * as Tabs from '@base_ui/react/Tabs'; +import { Tabs } from '@base_ui/react/Tabs'; import { useTabPanel } from './useTabPanel'; describe('useTabPanel', () => { diff --git a/packages/mui-base/src/Tabs/TabsList/TabsList.test.tsx b/packages/mui-base/src/Tabs/TabsList/TabsList.test.tsx index 959a65bca..9f040541c 100644 --- a/packages/mui-base/src/Tabs/TabsList/TabsList.test.tsx +++ b/packages/mui-base/src/Tabs/TabsList/TabsList.test.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import { expect } from 'chai'; import { act } from '@mui/internal-test-utils'; -import * as Tabs from '@base_ui/react/Tabs'; +import { Tabs } from '@base_ui/react/Tabs'; import { createRenderer, describeConformance } from '#test-utils'; import { TabsRootContext } from '../Root/TabsRootContext'; diff --git a/packages/mui-base/src/Tabs/TabsList/useTabsList.test.tsx b/packages/mui-base/src/Tabs/TabsList/useTabsList.test.tsx index 5efc61429..7a89c7d6d 100644 --- a/packages/mui-base/src/Tabs/TabsList/useTabsList.test.tsx +++ b/packages/mui-base/src/Tabs/TabsList/useTabsList.test.tsx @@ -2,7 +2,7 @@ import * as React from 'react'; import { expect } from 'chai'; import { spy } from 'sinon'; import { createRenderer, screen, fireEvent } from '@mui/internal-test-utils'; -import * as Tabs from '@base_ui/react/Tabs'; +import { Tabs } from '@base_ui/react/Tabs'; import { useTabsList } from './useTabsList'; describe('useTabsList', () => { diff --git a/packages/mui-base/src/Tabs/index.barrel.ts b/packages/mui-base/src/Tabs/index.barrel.ts deleted file mode 100644 index d8c499e9e..000000000 --- a/packages/mui-base/src/Tabs/index.barrel.ts +++ /dev/null @@ -1,5 +0,0 @@ -export { TabsRoot } from './Root/TabsRoot'; -export { Tab } from './Tab/Tab'; -export { TabIndicator } from './TabIndicator/TabIndicator'; -export { TabPanel } from './TabPanel/TabPanel'; -export { TabsList } from './TabsList/TabsList'; diff --git a/packages/mui-base/src/Tabs/index.parts.ts b/packages/mui-base/src/Tabs/index.parts.ts new file mode 100644 index 000000000..acb9d122d --- /dev/null +++ b/packages/mui-base/src/Tabs/index.parts.ts @@ -0,0 +1,5 @@ +export { TabsRoot as Root } from './Root/TabsRoot'; +export { Tab } from './Tab/Tab'; +export { TabIndicator as Indicator } from './TabIndicator/TabIndicator'; +export { TabPanel as Panel } from './TabPanel/TabPanel'; +export { TabsList as List } from './TabsList/TabsList'; diff --git a/packages/mui-base/src/Tabs/index.ts b/packages/mui-base/src/Tabs/index.ts index acb9d122d..10ed66c37 100644 --- a/packages/mui-base/src/Tabs/index.ts +++ b/packages/mui-base/src/Tabs/index.ts @@ -1,5 +1 @@ -export { TabsRoot as Root } from './Root/TabsRoot'; -export { Tab } from './Tab/Tab'; -export { TabIndicator as Indicator } from './TabIndicator/TabIndicator'; -export { TabPanel as Panel } from './TabPanel/TabPanel'; -export { TabsList as List } from './TabsList/TabsList'; +export * as Tabs from './index.parts'; diff --git a/packages/mui-base/src/Tooltip/Arrow/TooltipArrow.test.tsx b/packages/mui-base/src/Tooltip/Arrow/TooltipArrow.test.tsx index 53fda0b47..f7311dd8d 100644 --- a/packages/mui-base/src/Tooltip/Arrow/TooltipArrow.test.tsx +++ b/packages/mui-base/src/Tooltip/Arrow/TooltipArrow.test.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import * as Tooltip from '@base_ui/react/Tooltip'; +import { Tooltip } from '@base_ui/react/Tooltip'; import { createRenderer, describeConformance } from '#test-utils'; describe('', () => { diff --git a/packages/mui-base/src/Tooltip/Popup/TooltipPopup.test.tsx b/packages/mui-base/src/Tooltip/Popup/TooltipPopup.test.tsx index 8841512bb..b0fa70b6c 100644 --- a/packages/mui-base/src/Tooltip/Popup/TooltipPopup.test.tsx +++ b/packages/mui-base/src/Tooltip/Popup/TooltipPopup.test.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import * as Tooltip from '@base_ui/react/Tooltip'; +import { Tooltip } from '@base_ui/react/Tooltip'; import { screen } from '@mui/internal-test-utils'; import { expect } from 'chai'; import { createRenderer, describeConformance } from '#test-utils'; diff --git a/packages/mui-base/src/Tooltip/Positioner/TooltipPositioner.test.tsx b/packages/mui-base/src/Tooltip/Positioner/TooltipPositioner.test.tsx index 7d8af1460..eba09c753 100644 --- a/packages/mui-base/src/Tooltip/Positioner/TooltipPositioner.test.tsx +++ b/packages/mui-base/src/Tooltip/Positioner/TooltipPositioner.test.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import * as Tooltip from '@base_ui/react/Tooltip'; +import { Tooltip } from '@base_ui/react/Tooltip'; import { createRenderer, describeConformance } from '#test-utils'; describe('', () => { diff --git a/packages/mui-base/src/Tooltip/Provider/TooltipProvider.test.tsx b/packages/mui-base/src/Tooltip/Provider/TooltipProvider.test.tsx index 9fd5b8acb..503541aff 100644 --- a/packages/mui-base/src/Tooltip/Provider/TooltipProvider.test.tsx +++ b/packages/mui-base/src/Tooltip/Provider/TooltipProvider.test.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import * as Tooltip from '@base_ui/react/Tooltip'; +import { Tooltip } from '@base_ui/react/Tooltip'; import { screen, fireEvent, flushMicrotasks } from '@mui/internal-test-utils'; import { expect } from 'chai'; import { createRenderer } from '#test-utils'; diff --git a/packages/mui-base/src/Tooltip/Root/TooltipRoot.test.tsx b/packages/mui-base/src/Tooltip/Root/TooltipRoot.test.tsx index a73c74901..809bc2ce6 100644 --- a/packages/mui-base/src/Tooltip/Root/TooltipRoot.test.tsx +++ b/packages/mui-base/src/Tooltip/Root/TooltipRoot.test.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import * as Tooltip from '@base_ui/react/Tooltip'; +import { Tooltip } from '@base_ui/react/Tooltip'; import { act, fireEvent, flushMicrotasks, screen } from '@mui/internal-test-utils'; import { expect } from 'chai'; import { spy } from 'sinon'; diff --git a/packages/mui-base/src/Tooltip/Trigger/TooltipTrigger.test.tsx b/packages/mui-base/src/Tooltip/Trigger/TooltipTrigger.test.tsx index d030237d1..c3406649d 100644 --- a/packages/mui-base/src/Tooltip/Trigger/TooltipTrigger.test.tsx +++ b/packages/mui-base/src/Tooltip/Trigger/TooltipTrigger.test.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import * as Tooltip from '@base_ui/react/Tooltip'; +import { Tooltip } from '@base_ui/react/Tooltip'; import { createRenderer, describeConformance } from '#test-utils'; describe('', () => { diff --git a/packages/mui-base/src/Tooltip/index.barrel.ts b/packages/mui-base/src/Tooltip/index.barrel.ts deleted file mode 100644 index 79e7247ec..000000000 --- a/packages/mui-base/src/Tooltip/index.barrel.ts +++ /dev/null @@ -1,6 +0,0 @@ -export { TooltipRoot } from './Root/TooltipRoot'; -export { TooltipTrigger } from './Trigger/TooltipTrigger'; -export { TooltipPositioner } from './Positioner/TooltipPositioner'; -export { TooltipPopup } from './Popup/TooltipPopup'; -export { TooltipArrow } from './Arrow/TooltipArrow'; -export { TooltipProvider } from './Provider/TooltipProvider'; diff --git a/packages/mui-base/src/Tooltip/index.parts.ts b/packages/mui-base/src/Tooltip/index.parts.ts new file mode 100644 index 000000000..00ec741c9 --- /dev/null +++ b/packages/mui-base/src/Tooltip/index.parts.ts @@ -0,0 +1,6 @@ +export { TooltipRoot as Root } from './Root/TooltipRoot'; +export { TooltipTrigger as Trigger } from './Trigger/TooltipTrigger'; +export { TooltipPositioner as Positioner } from './Positioner/TooltipPositioner'; +export { TooltipPopup as Popup } from './Popup/TooltipPopup'; +export { TooltipArrow as Arrow } from './Arrow/TooltipArrow'; +export { TooltipProvider as Provider } from './Provider/TooltipProvider'; diff --git a/packages/mui-base/src/Tooltip/index.ts b/packages/mui-base/src/Tooltip/index.ts index 00ec741c9..6fb3a4251 100644 --- a/packages/mui-base/src/Tooltip/index.ts +++ b/packages/mui-base/src/Tooltip/index.ts @@ -1,6 +1 @@ -export { TooltipRoot as Root } from './Root/TooltipRoot'; -export { TooltipTrigger as Trigger } from './Trigger/TooltipTrigger'; -export { TooltipPositioner as Positioner } from './Positioner/TooltipPositioner'; -export { TooltipPopup as Popup } from './Popup/TooltipPopup'; -export { TooltipArrow as Arrow } from './Arrow/TooltipArrow'; -export { TooltipProvider as Provider } from './Provider/TooltipProvider'; +export * as Tooltip from './index.parts'; diff --git a/packages/mui-base/src/index.ts b/packages/mui-base/src/index.ts index d7044b96a..5c2fbaeff 100644 --- a/packages/mui-base/src/index.ts +++ b/packages/mui-base/src/index.ts @@ -1,15 +1,19 @@ -export * from './Accordion/index.barrel'; -export * from './AlertDialog/index.barrel'; -export * from './Checkbox/index.barrel'; -export * from './CheckboxGroup/index.barrel'; -export * from './Collapsible/index.barrel'; -export * from './Dialog/index.barrel'; -export * from './Menu/index.barrel'; -export * from './NumberField/index.barrel'; -export * from './Popover/index.barrel'; -export * from './Progress/index.barrel'; -export * from './Separator/index.barrel'; -export * from './Slider/index.barrel'; -export * from './Switch/index.barrel'; -export * from './Tabs/index.barrel'; -export * from './Tooltip/index.barrel'; +export * from './AlertDialog'; +export * from './Checkbox'; +export * from './CheckboxGroup'; +export * from './Collapsible'; +export * from './Dialog'; +export * from './Field'; +export * from './Fieldset'; +export * from './Form'; +export * from './Menu'; +export * from './NumberField'; +export * from './Popover'; +export * from './PreviewCard'; +export * from './Progress'; +export * from './RadioGroup'; +export * from './Separator'; +export * from './Slider'; +export * from './Switch'; +export * from './Tabs'; +export * from './Tooltip'; diff --git a/scripts/buildApiDocs/config/getComponentImports.ts b/scripts/buildApiDocs/config/getComponentImports.ts index 4e2968527..0e88f6fcc 100644 --- a/scripts/buildApiDocs/config/getComponentImports.ts +++ b/scripts/buildApiDocs/config/getComponentImports.ts @@ -27,7 +27,7 @@ export function getComponentImports(name: string, filename: string) { if (Object.keys(componentExportExceptions).includes(name)) { return [ - `import * as ${componentDirectory} from '@base_ui/react/${componentDirectory}';\nconst ${name} = ${componentDirectory}.${componentExportExceptions[name]};`, + `import { ${componentDirectory} } from '@base_ui/react/${componentDirectory}';\nconst ${name} = ${componentDirectory}.${componentExportExceptions[name]};`, ]; } @@ -35,7 +35,7 @@ export function getComponentImports(name: string, filename: string) { // cases like Switch/SwitchTrack.tsx const childName = name.slice(componentDirectory.length); return [ - `import * as ${componentDirectory} from '@base_ui/react/${componentDirectory}';\nconst ${name} = ${componentDirectory}.${childName};`, + `import { ${componentDirectory} } from '@base_ui/react/${componentDirectory}';\nconst ${name} = ${componentDirectory}.${childName};`, ]; } From 19cfa44633473378acacbebf2ce48f66a0fc5a93 Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Mon, 14 Oct 2024 16:50:14 +0800 Subject: [PATCH 21/37] Update exports and types --- docs/app/experiments/accordion-animations.tsx | 2 +- docs/app/experiments/accordion-horizontal.tsx | 7 ++--- docs/app/experiments/accordion.tsx | 4 +-- docs/data/api/accordion-header.json | 2 +- docs/data/api/accordion-heading.json | 2 +- docs/data/api/accordion-item.json | 2 +- docs/data/api/accordion-panel.json | 2 +- docs/data/api/accordion-root.json | 2 +- docs/data/api/accordion-section.json | 2 +- docs/data/api/accordion-trigger.json | 2 +- .../UnstyledAccordionIntroduction.js | 2 +- .../UnstyledAccordionIntroduction.tsx | 2 +- .../Accordion/Header/AccordionHeader.test.tsx | 14 +++++----- .../src/Accordion/Item/AccordionItem.test.tsx | 2 +- .../src/Accordion/Item/AccordionItem.tsx | 17 ++++-------- .../Accordion/Item/AccordionItemContext.tsx | 8 +++++- .../Accordion/Panel/AccordionPanel.test.tsx | 14 +++++----- .../src/Accordion/Panel/AccordionPanel.tsx | 4 +-- .../src/Accordion/Root/AccordionRoot.test.tsx | 2 +- .../Trigger/AccordionTrigger.test.tsx | 14 +++++----- .../Accordion/Trigger/AccordionTrigger.tsx | 4 +-- .../mui-base/src/Accordion/index.barrel.ts | 5 ---- .../mui-base/src/Accordion/index.parts.ts | 5 ++++ packages/mui-base/src/Accordion/index.ts | 6 +---- .../Content/CollapsibleContent.test.tsx | 8 +++--- .../Content/CollapsibleContent.tsx | 4 +-- .../Collapsible/Root/CollapsibleContext.tsx | 22 ---------------- .../src/Collapsible/Root/CollapsibleRoot.tsx | 16 +++++------- .../Root/CollapsibleRootContext.tsx | 26 +++++++++++++++++++ .../Trigger/CollapsibleTrigger.test.tsx | 8 +++--- .../Trigger/CollapsibleTrigger.tsx | 4 +-- .../Trigger/useCollapsibleTrigger.ts | 11 +------- .../mui-base/src/Collapsible/index.barrel.ts | 4 --- packages/mui-base/src/index.ts | 1 + 34 files changed, 107 insertions(+), 123 deletions(-) delete mode 100644 packages/mui-base/src/Accordion/index.barrel.ts create mode 100644 packages/mui-base/src/Accordion/index.parts.ts delete mode 100644 packages/mui-base/src/Collapsible/Root/CollapsibleContext.tsx create mode 100644 packages/mui-base/src/Collapsible/Root/CollapsibleRootContext.tsx delete mode 100644 packages/mui-base/src/Collapsible/index.barrel.ts diff --git a/docs/app/experiments/accordion-animations.tsx b/docs/app/experiments/accordion-animations.tsx index d2cd903a5..64116beab 100644 --- a/docs/app/experiments/accordion-animations.tsx +++ b/docs/app/experiments/accordion-animations.tsx @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as Accordion from '@base_ui/react/Accordion'; +import { Accordion } from '@base_ui/react/Accordion'; import { ExpandMoreIcon } from './accordion'; const DURATION = '300ms'; diff --git a/docs/app/experiments/accordion-horizontal.tsx b/docs/app/experiments/accordion-horizontal.tsx index e483cf3b3..5362107bb 100644 --- a/docs/app/experiments/accordion-horizontal.tsx +++ b/docs/app/experiments/accordion-horizontal.tsx @@ -1,9 +1,10 @@ 'use client'; import * as React from 'react'; -import * as Accordion from '@base_ui/react/Accordion'; +import { Accordion } from '@base_ui/react/Accordion'; +import classes from './accordion.horizontal.module.css'; -function classNames(...classes: Array) { - return classes.filter(Boolean).join(' '); +function classNames(...c: Array) { + return c.filter(Boolean).join(' '); } export default function App() { diff --git a/docs/app/experiments/accordion.tsx b/docs/app/experiments/accordion.tsx index 4313d34d6..6b2fb60ac 100644 --- a/docs/app/experiments/accordion.tsx +++ b/docs/app/experiments/accordion.tsx @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; -import * as Checkbox from '@base_ui/react/Checkbox'; -import * as Accordion from '@base_ui/react/Accordion'; +import { Checkbox } from '@base_ui/react/Checkbox'; +import { Accordion } from '@base_ui/react/Accordion'; export default function App() { const [openMultiple, setOpenMultiple] = React.useState(true); diff --git a/docs/data/api/accordion-header.json b/docs/data/api/accordion-header.json index f5802943d..b1399816f 100644 --- a/docs/data/api/accordion-header.json +++ b/docs/data/api/accordion-header.json @@ -5,7 +5,7 @@ }, "name": "AccordionHeader", "imports": [ - "import * as Accordion from '@base_ui/react/Accordion';\nconst AccordionHeader = Accordion.Header;" + "import { Accordion } from '@base_ui/react/Accordion';\nconst AccordionHeader = Accordion.Header;" ], "classes": [], "spread": true, diff --git a/docs/data/api/accordion-heading.json b/docs/data/api/accordion-heading.json index 84859add9..72627dc08 100644 --- a/docs/data/api/accordion-heading.json +++ b/docs/data/api/accordion-heading.json @@ -5,7 +5,7 @@ }, "name": "AccordionHeading", "imports": [ - "import * as Accordion from '@base_ui/react/Accordion';\nconst AccordionHeading = Accordion.Heading;" + "import { Accordion } from '@base_ui/react/Accordion';\nconst AccordionHeading = Accordion.Heading;" ], "classes": [], "spread": true, diff --git a/docs/data/api/accordion-item.json b/docs/data/api/accordion-item.json index f85d3793f..c708653f6 100644 --- a/docs/data/api/accordion-item.json +++ b/docs/data/api/accordion-item.json @@ -7,7 +7,7 @@ }, "name": "AccordionItem", "imports": [ - "import * as Accordion from '@base_ui/react/Accordion';\nconst AccordionItem = Accordion.Item;" + "import { Accordion } from '@base_ui/react/Accordion';\nconst AccordionItem = Accordion.Item;" ], "classes": [], "spread": true, diff --git a/docs/data/api/accordion-panel.json b/docs/data/api/accordion-panel.json index 0f9116022..dd8247c8b 100644 --- a/docs/data/api/accordion-panel.json +++ b/docs/data/api/accordion-panel.json @@ -6,7 +6,7 @@ }, "name": "AccordionPanel", "imports": [ - "import * as Accordion from '@base_ui/react/Accordion';\nconst AccordionPanel = Accordion.Panel;" + "import { Accordion } from '@base_ui/react/Accordion';\nconst AccordionPanel = Accordion.Panel;" ], "classes": [], "spread": true, diff --git a/docs/data/api/accordion-root.json b/docs/data/api/accordion-root.json index 97156a66f..9747dc52f 100644 --- a/docs/data/api/accordion-root.json +++ b/docs/data/api/accordion-root.json @@ -17,7 +17,7 @@ }, "name": "AccordionRoot", "imports": [ - "import * as Accordion from '@base_ui/react/Accordion';\nconst AccordionRoot = Accordion.Root;" + "import { Accordion } from '@base_ui/react/Accordion';\nconst AccordionRoot = Accordion.Root;" ], "classes": [], "spread": true, diff --git a/docs/data/api/accordion-section.json b/docs/data/api/accordion-section.json index e9f2e1d7d..873677030 100644 --- a/docs/data/api/accordion-section.json +++ b/docs/data/api/accordion-section.json @@ -7,7 +7,7 @@ }, "name": "AccordionSection", "imports": [ - "import * as Accordion from '@base_ui/react/Accordion';\nconst AccordionSection = Accordion.Section;" + "import { Accordion } from '@base_ui/react/Accordion';\nconst AccordionSection = Accordion.Section;" ], "classes": [], "spread": true, diff --git a/docs/data/api/accordion-trigger.json b/docs/data/api/accordion-trigger.json index b2016c8d1..0a1dda62c 100644 --- a/docs/data/api/accordion-trigger.json +++ b/docs/data/api/accordion-trigger.json @@ -5,7 +5,7 @@ }, "name": "AccordionTrigger", "imports": [ - "import * as Accordion from '@base_ui/react/Accordion';\nconst AccordionTrigger = Accordion.Trigger;" + "import { Accordion } from '@base_ui/react/Accordion';\nconst AccordionTrigger = Accordion.Trigger;" ], "classes": [], "spread": true, diff --git a/docs/data/components/accordion/UnstyledAccordionIntroduction.js b/docs/data/components/accordion/UnstyledAccordionIntroduction.js index 05aef368b..378b8c0ba 100644 --- a/docs/data/components/accordion/UnstyledAccordionIntroduction.js +++ b/docs/data/components/accordion/UnstyledAccordionIntroduction.js @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as Accordion from '@base_ui/react/Accordion'; +import { Accordion } from '@base_ui/react/Accordion'; import classes from './styles.module.css'; export default function UnstyledAccordionIntroduction() { diff --git a/docs/data/components/accordion/UnstyledAccordionIntroduction.tsx b/docs/data/components/accordion/UnstyledAccordionIntroduction.tsx index 01120baca..09f316335 100644 --- a/docs/data/components/accordion/UnstyledAccordionIntroduction.tsx +++ b/docs/data/components/accordion/UnstyledAccordionIntroduction.tsx @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import * as Accordion from '@base_ui/react/Accordion'; +import { Accordion } from '@base_ui/react/Accordion'; import classes from './styles.module.css'; export default function UnstyledAccordionIntroduction() { diff --git a/packages/mui-base/src/Accordion/Header/AccordionHeader.test.tsx b/packages/mui-base/src/Accordion/Header/AccordionHeader.test.tsx index 234f78332..a1876c855 100644 --- a/packages/mui-base/src/Accordion/Header/AccordionHeader.test.tsx +++ b/packages/mui-base/src/Accordion/Header/AccordionHeader.test.tsx @@ -1,13 +1,11 @@ import * as React from 'react'; -import * as Accordion from '@base_ui/react/Accordion'; -import * as Collapsible from '@base_ui/react/Collapsible'; +import { Accordion } from '@base_ui/react/Accordion'; import { describeConformance, createRenderer } from '#test-utils'; import { NOOP } from '../../utils/noop'; +import { CollapsibleRootContext } from '../../Collapsible/Root/CollapsibleRootContext'; import { AccordionRootContext } from '../Root/AccordionRootContext'; import { AccordionItemContext } from '../Item/AccordionItemContext'; -const { CollapsibleContext } = Collapsible; - const accordionRootContextValue: Accordion.Root.Context = { accordionItemRefs: { current: [] }, animated: false, @@ -24,7 +22,7 @@ const accordionRootContextValue: Accordion.Root.Context = { value: [0], }; -const accordionItemContextValue: Accordion.Item.Context = { +const accordionItemContextValue: AccordionItemContext = { open: true, ownerState: { value: [0], @@ -38,7 +36,7 @@ const accordionItemContextValue: Accordion.Item.Context = { triggerId: ':trigger:', }; -const collapsibleContextValue: Collapsible.Root.Context = { +const collapsibleContextValue: CollapsibleRootContext = { animated: false, contentId: ':content:', disabled: false, @@ -62,11 +60,11 @@ describe('', () => { render: (node) => render( - + {node} - + , ), refInstanceof: window.HTMLHeadingElement, diff --git a/packages/mui-base/src/Accordion/Item/AccordionItem.test.tsx b/packages/mui-base/src/Accordion/Item/AccordionItem.test.tsx index 0d22a096f..47b6363ff 100644 --- a/packages/mui-base/src/Accordion/Item/AccordionItem.test.tsx +++ b/packages/mui-base/src/Accordion/Item/AccordionItem.test.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import * as Accordion from '@base_ui/react/Accordion'; +import { Accordion } from '@base_ui/react/Accordion'; import { describeConformance, createRenderer } from '#test-utils'; import { NOOP } from '../../utils/noop'; import { AccordionRootContext } from '../Root/AccordionRootContext'; diff --git a/packages/mui-base/src/Accordion/Item/AccordionItem.tsx b/packages/mui-base/src/Accordion/Item/AccordionItem.tsx index 0fe6e8726..28a8a8a9e 100644 --- a/packages/mui-base/src/Accordion/Item/AccordionItem.tsx +++ b/packages/mui-base/src/Accordion/Item/AccordionItem.tsx @@ -9,7 +9,7 @@ import { useId } from '../../utils/useId'; import type { TransitionStatus } from '../../utils/useTransitionStatus'; import { useCollapsibleRoot } from '../../Collapsible/Root/useCollapsibleRoot'; import type { CollapsibleRoot } from '../../Collapsible/Root/CollapsibleRoot'; -import { CollapsibleContext } from '../../Collapsible/Root/CollapsibleContext'; +import { CollapsibleRootContext } from '../../Collapsible/Root/CollapsibleRootContext'; import { useCompositeListItem } from '../../Composite/List/useCompositeListItem'; import type { AccordionRoot } from '../Root/AccordionRoot'; import { useAccordionRootContext } from '../Root/AccordionRootContext'; @@ -89,7 +89,7 @@ const AccordionItem = React.forwardRef(function AccordionItem( [collapsible.open, collapsible.disabled, collapsible.transitionStatus], ); - const collapsibleContext: CollapsibleRoot.Context = React.useMemo( + const collapsibleContext: CollapsibleRootContext = React.useMemo( () => ({ ...collapsible, ownerState: collapsibleOwnerState, @@ -110,7 +110,7 @@ const AccordionItem = React.forwardRef(function AccordionItem( const [triggerId, setTriggerId] = React.useState(useId()); - const accordionItemContext: AccordionItem.Context = React.useMemo( + const accordionItemContext: AccordionItemContext = React.useMemo( () => ({ open: isOpen, ownerState, @@ -130,24 +130,17 @@ const AccordionItem = React.forwardRef(function AccordionItem( }); return ( - + {renderElement()} - + ); }); export namespace AccordionItem { export type Value = number | string; - export interface Context { - open: boolean; - ownerState: OwnerState; - setTriggerId: (id: string | undefined) => void; - triggerId?: string; - } - export interface OwnerState extends AccordionRoot.OwnerState { index: number; open: boolean; diff --git a/packages/mui-base/src/Accordion/Item/AccordionItemContext.tsx b/packages/mui-base/src/Accordion/Item/AccordionItemContext.tsx index 5d9acd817..ff58ad475 100644 --- a/packages/mui-base/src/Accordion/Item/AccordionItemContext.tsx +++ b/packages/mui-base/src/Accordion/Item/AccordionItemContext.tsx @@ -2,10 +2,16 @@ import * as React from 'react'; import type { AccordionItem } from './AccordionItem'; +export interface AccordionItemContext { + open: boolean; + ownerState: AccordionItem.OwnerState; + setTriggerId: (id: string | undefined) => void; + triggerId?: string; +} /** * @ignore - internal component. */ -export const AccordionItemContext = React.createContext( +export const AccordionItemContext = React.createContext( undefined, ); diff --git a/packages/mui-base/src/Accordion/Panel/AccordionPanel.test.tsx b/packages/mui-base/src/Accordion/Panel/AccordionPanel.test.tsx index 1e8c767dd..e623bd7b1 100644 --- a/packages/mui-base/src/Accordion/Panel/AccordionPanel.test.tsx +++ b/packages/mui-base/src/Accordion/Panel/AccordionPanel.test.tsx @@ -1,13 +1,11 @@ import * as React from 'react'; -import * as Accordion from '@base_ui/react/Accordion'; -import * as Collapsible from '@base_ui/react/Collapsible'; +import { Accordion } from '@base_ui/react/Accordion'; import { describeConformance, createRenderer } from '#test-utils'; import { NOOP } from '../../utils/noop'; +import { CollapsibleRootContext } from '../../Collapsible/Root/CollapsibleRootContext'; import { AccordionRootContext } from '../Root/AccordionRootContext'; import { AccordionItemContext } from '../Item/AccordionItemContext'; -const { CollapsibleContext } = Collapsible; - const accordionRootContextValue: Accordion.Root.Context = { accordionItemRefs: { current: [] }, animated: false, @@ -24,7 +22,7 @@ const accordionRootContextValue: Accordion.Root.Context = { value: [0], }; -const accordionItemContextValue: Accordion.Item.Context = { +const accordionItemContextValue: AccordionItemContext = { open: true, ownerState: { value: [0], @@ -38,7 +36,7 @@ const accordionItemContextValue: Accordion.Item.Context = { triggerId: ':trigger:', }; -const collapsibleContextValue: Collapsible.Root.Context = { +const collapsibleContextValue: CollapsibleRootContext = { animated: false, contentId: ':content:', disabled: false, @@ -62,11 +60,11 @@ describe('', () => { render: (node) => render( - + {node} - + , ), refInstanceof: window.HTMLDivElement, diff --git a/packages/mui-base/src/Accordion/Panel/AccordionPanel.tsx b/packages/mui-base/src/Accordion/Panel/AccordionPanel.tsx index 08ce784c8..525b3d08e 100644 --- a/packages/mui-base/src/Accordion/Panel/AccordionPanel.tsx +++ b/packages/mui-base/src/Accordion/Panel/AccordionPanel.tsx @@ -3,7 +3,7 @@ import * as React from 'react'; import PropTypes from 'prop-types'; import { BaseUIComponentProps } from '../../utils/types'; import { useComponentRenderer } from '../../utils/useComponentRenderer'; -import { useCollapsibleContext } from '../../Collapsible/Root/CollapsibleContext'; +import { useCollapsibleRootContext } from '../../Collapsible/Root/CollapsibleRootContext'; import { useCollapsibleContent } from '../../Collapsible/Content/useCollapsibleContent'; import { useAccordionRootContext } from '../Root/AccordionRootContext'; import type { AccordionItem } from '../Item/AccordionItem'; @@ -34,7 +34,7 @@ const AccordionPanel = React.forwardRef(function AccordionPanel( } = props; const { animated, mounted, open, contentId, setContentId, setMounted, setOpen } = - useCollapsibleContext(); + useCollapsibleRootContext(); const { hiddenUntilFound } = useAccordionRootContext(); diff --git a/packages/mui-base/src/Accordion/Root/AccordionRoot.test.tsx b/packages/mui-base/src/Accordion/Root/AccordionRoot.test.tsx index bb09dd029..5af9312f9 100644 --- a/packages/mui-base/src/Accordion/Root/AccordionRoot.test.tsx +++ b/packages/mui-base/src/Accordion/Root/AccordionRoot.test.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import { expect } from 'chai'; import { spy } from 'sinon'; -import * as Accordion from '@base_ui/react/Accordion'; +import { Accordion } from '@base_ui/react/Accordion'; import { describeConformance, createRenderer } from '#test-utils'; describe('', () => { diff --git a/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.test.tsx b/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.test.tsx index 82320b0b7..25e84af30 100644 --- a/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.test.tsx +++ b/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.test.tsx @@ -1,13 +1,11 @@ import * as React from 'react'; -import * as Accordion from '@base_ui/react/Accordion'; -import * as Collapsible from '@base_ui/react/Collapsible'; +import { Accordion } from '@base_ui/react/Accordion'; import { describeConformance, createRenderer } from '#test-utils'; import { NOOP } from '../../utils/noop'; +import { CollapsibleRootContext } from '../../Collapsible/Root/CollapsibleRootContext'; import { AccordionRootContext } from '../Root/AccordionRootContext'; import { AccordionItemContext } from '../Item/AccordionItemContext'; -const { CollapsibleContext } = Collapsible; - const accordionRootContextValue: Accordion.Root.Context = { accordionItemRefs: { current: [] }, animated: false, @@ -24,7 +22,7 @@ const accordionRootContextValue: Accordion.Root.Context = { value: [0], }; -const accordionItemContextValue: Accordion.Item.Context = { +const accordionItemContextValue: AccordionItemContext = { open: true, ownerState: { value: [0], @@ -38,7 +36,7 @@ const accordionItemContextValue: Accordion.Item.Context = { triggerId: ':trigger:', }; -const collapsibleContextValue: Collapsible.Root.Context = { +const collapsibleContextValue: CollapsibleRootContext = { animated: false, contentId: ':content:', disabled: false, @@ -62,11 +60,11 @@ describe('', () => { render: (node) => render( - + {node} - + , ), refInstanceof: window.HTMLButtonElement, diff --git a/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.tsx b/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.tsx index a35c56799..e3b881a7b 100644 --- a/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.tsx +++ b/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.tsx @@ -4,7 +4,7 @@ import PropTypes from 'prop-types'; import { useComponentRenderer } from '../../utils/useComponentRenderer'; import { useEnhancedEffect } from '../../utils/useEnhancedEffect'; import { BaseUIComponentProps } from '../../utils/types'; -import { useCollapsibleContext } from '../../Collapsible/Root/CollapsibleContext'; +import { useCollapsibleRootContext } from '../../Collapsible/Root/CollapsibleRootContext'; import { useCollapsibleTrigger } from '../../Collapsible/Trigger/useCollapsibleTrigger'; import type { AccordionItem } from '../Item/AccordionItem'; import { useAccordionItemContext } from '../Item/AccordionItemContext'; @@ -26,7 +26,7 @@ const AccordionTrigger = React.forwardRef(function AccordionTrigger( ) { const { disabled: disabledProp, className, id, render, ...otherProps } = props; - const { contentId, disabled: contextDisabled, open, setOpen } = useCollapsibleContext(); + const { contentId, disabled: contextDisabled, open, setOpen } = useCollapsibleRootContext(); const { getRootProps } = useCollapsibleTrigger({ contentId, diff --git a/packages/mui-base/src/Accordion/index.barrel.ts b/packages/mui-base/src/Accordion/index.barrel.ts deleted file mode 100644 index bb850626d..000000000 --- a/packages/mui-base/src/Accordion/index.barrel.ts +++ /dev/null @@ -1,5 +0,0 @@ -export * from './Root/AccordionRoot'; -export * from './Item/AccordionItem'; -export * from './Header/AccordionHeader'; -export * from './Trigger/AccordionTrigger'; -export * from './Panel/AccordionPanel'; diff --git a/packages/mui-base/src/Accordion/index.parts.ts b/packages/mui-base/src/Accordion/index.parts.ts new file mode 100644 index 000000000..cfd89a887 --- /dev/null +++ b/packages/mui-base/src/Accordion/index.parts.ts @@ -0,0 +1,5 @@ +export { AccordionRoot as Root } from './Root/AccordionRoot'; +export { AccordionItem as Item } from './Item/AccordionItem'; +export { AccordionHeader as Header } from './Header/AccordionHeader'; +export { AccordionTrigger as Trigger } from './Trigger/AccordionTrigger'; +export { AccordionPanel as Panel } from './Panel/AccordionPanel'; diff --git a/packages/mui-base/src/Accordion/index.ts b/packages/mui-base/src/Accordion/index.ts index cfd89a887..bc75beb63 100644 --- a/packages/mui-base/src/Accordion/index.ts +++ b/packages/mui-base/src/Accordion/index.ts @@ -1,5 +1 @@ -export { AccordionRoot as Root } from './Root/AccordionRoot'; -export { AccordionItem as Item } from './Item/AccordionItem'; -export { AccordionHeader as Header } from './Header/AccordionHeader'; -export { AccordionTrigger as Trigger } from './Trigger/AccordionTrigger'; -export { AccordionPanel as Panel } from './Panel/AccordionPanel'; +export * as Accordion from './index.parts'; diff --git a/packages/mui-base/src/Collapsible/Content/CollapsibleContent.test.tsx b/packages/mui-base/src/Collapsible/Content/CollapsibleContent.test.tsx index 435562e03..c570646eb 100644 --- a/packages/mui-base/src/Collapsible/Content/CollapsibleContent.test.tsx +++ b/packages/mui-base/src/Collapsible/Content/CollapsibleContent.test.tsx @@ -1,10 +1,10 @@ import * as React from 'react'; import { createRenderer } from '@mui/internal-test-utils'; import { Collapsible } from '@base_ui/react/Collapsible'; -import { CollapsibleContext } from '../Root/CollapsibleContext'; +import { CollapsibleRootContext } from '../Root/CollapsibleRootContext'; import { describeConformance } from '../../../test/describeConformance'; -const contextValue: Collapsible.Root.Context = { +const contextValue: CollapsibleRootContext = { animated: false, contentId: 'ContentId', disabled: false, @@ -28,7 +28,9 @@ describe('', () => { inheritComponent: 'div', render: (node) => { const { container, ...other } = render( - {node}, + + {node} + , ); return { container, ...other }; diff --git a/packages/mui-base/src/Collapsible/Content/CollapsibleContent.tsx b/packages/mui-base/src/Collapsible/Content/CollapsibleContent.tsx index d485d0734..b62e2db64 100644 --- a/packages/mui-base/src/Collapsible/Content/CollapsibleContent.tsx +++ b/packages/mui-base/src/Collapsible/Content/CollapsibleContent.tsx @@ -3,7 +3,7 @@ import * as React from 'react'; import PropTypes from 'prop-types'; import { BaseUIComponentProps } from '../../utils/types'; import { useComponentRenderer } from '../../utils/useComponentRenderer'; -import { useCollapsibleContext } from '../Root/CollapsibleContext'; +import { useCollapsibleRootContext } from '../Root/CollapsibleRootContext'; import type { CollapsibleRoot } from '../Root/CollapsibleRoot'; import { collapsibleStyleHookMapping } from '../Root/styleHooks'; import { useCollapsibleContent } from './useCollapsibleContent'; @@ -25,7 +25,7 @@ const CollapsibleContent = React.forwardRef(function CollapsibleContent( const { className, hiddenUntilFound, render, ...otherProps } = props; const { animated, mounted, open, contentId, setContentId, setMounted, setOpen, ownerState } = - useCollapsibleContext(); + useCollapsibleRootContext(); const { getRootProps, height, width } = useCollapsibleContent({ animated, diff --git a/packages/mui-base/src/Collapsible/Root/CollapsibleContext.tsx b/packages/mui-base/src/Collapsible/Root/CollapsibleContext.tsx deleted file mode 100644 index befc7670a..000000000 --- a/packages/mui-base/src/Collapsible/Root/CollapsibleContext.tsx +++ /dev/null @@ -1,22 +0,0 @@ -'use client'; -import * as React from 'react'; -import type { CollapsibleRoot } from './CollapsibleRoot'; - -/** - * @ignore - internal component. - */ -export const CollapsibleContext = React.createContext( - undefined, -); - -if (process.env.NODE_ENV !== 'production') { - CollapsibleContext.displayName = 'CollapsibleContext'; -} - -export function useCollapsibleContext() { - const context = React.useContext(CollapsibleContext); - if (context === undefined) { - throw new Error('useCollapsibleContext must be used inside a Collapsible component'); - } - return context; -} diff --git a/packages/mui-base/src/Collapsible/Root/CollapsibleRoot.tsx b/packages/mui-base/src/Collapsible/Root/CollapsibleRoot.tsx index 840e3475c..89959db2e 100644 --- a/packages/mui-base/src/Collapsible/Root/CollapsibleRoot.tsx +++ b/packages/mui-base/src/Collapsible/Root/CollapsibleRoot.tsx @@ -4,7 +4,7 @@ import PropTypes from 'prop-types'; import { BaseUIComponentProps } from '../../utils/types'; import { useComponentRenderer } from '../../utils/useComponentRenderer'; import { useCollapsibleRoot } from './useCollapsibleRoot'; -import { CollapsibleContext } from './CollapsibleContext'; +import { CollapsibleRootContext } from './CollapsibleRootContext'; import { collapsibleStyleHookMapping } from './styleHooks'; /** @@ -50,7 +50,7 @@ const CollapsibleRoot = React.forwardRef(function CollapsibleRoot( [collapsible.open, collapsible.disabled, collapsible.transitionStatus], ); - const contextValue: CollapsibleRoot.Context = React.useMemo( + const contextValue: CollapsibleRootContext = React.useMemo( () => ({ ...collapsible, ownerState, @@ -69,24 +69,22 @@ const CollapsibleRoot = React.forwardRef(function CollapsibleRoot( if (!renderProp) { return ( - {children} + + {children} + ); } return ( - + {renderElement()} - + ); }); export { CollapsibleRoot }; export namespace CollapsibleRoot { - export interface Context extends useCollapsibleRoot.ReturnValue { - ownerState: OwnerState; - } - export interface OwnerState extends Pick {} diff --git a/packages/mui-base/src/Collapsible/Root/CollapsibleRootContext.tsx b/packages/mui-base/src/Collapsible/Root/CollapsibleRootContext.tsx new file mode 100644 index 000000000..98a7491ad --- /dev/null +++ b/packages/mui-base/src/Collapsible/Root/CollapsibleRootContext.tsx @@ -0,0 +1,26 @@ +'use client'; +import * as React from 'react'; +import type { useCollapsibleRoot } from './useCollapsibleRoot'; +import type { CollapsibleRoot } from './CollapsibleRoot'; + +export interface CollapsibleRootContext extends useCollapsibleRoot.ReturnValue { + ownerState: CollapsibleRoot.OwnerState; +} +/** + * @ignore - internal component. + */ +export const CollapsibleRootContext = React.createContext( + undefined, +); + +if (process.env.NODE_ENV !== 'production') { + CollapsibleRootContext.displayName = 'CollapsibleRootContext'; +} + +export function useCollapsibleRootContext() { + const context = React.useContext(CollapsibleRootContext); + if (context === undefined) { + throw new Error('useCollapsibleRootContext must be used inside a Collapsible component'); + } + return context; +} diff --git a/packages/mui-base/src/Collapsible/Trigger/CollapsibleTrigger.test.tsx b/packages/mui-base/src/Collapsible/Trigger/CollapsibleTrigger.test.tsx index 0e7a77d5d..86dc0e675 100644 --- a/packages/mui-base/src/Collapsible/Trigger/CollapsibleTrigger.test.tsx +++ b/packages/mui-base/src/Collapsible/Trigger/CollapsibleTrigger.test.tsx @@ -1,10 +1,10 @@ import * as React from 'react'; import { createRenderer } from '@mui/internal-test-utils'; import { Collapsible } from '@base_ui/react/Collapsible'; -import { CollapsibleContext } from '../Root/CollapsibleContext'; +import { CollapsibleRootContext } from '../Root/CollapsibleRootContext'; import { describeConformance } from '../../../test/describeConformance'; -const contextValue: Collapsible.Root.Context = { +const contextValue: CollapsibleRootContext = { animated: false, contentId: 'ContentId', disabled: false, @@ -28,7 +28,9 @@ describe('', () => { inheritComponent: 'button', render: (node) => { const { container, ...other } = render( - {node}, + + {node} + , ); return { container, ...other }; diff --git a/packages/mui-base/src/Collapsible/Trigger/CollapsibleTrigger.tsx b/packages/mui-base/src/Collapsible/Trigger/CollapsibleTrigger.tsx index f35bfbf40..0a8f72b99 100644 --- a/packages/mui-base/src/Collapsible/Trigger/CollapsibleTrigger.tsx +++ b/packages/mui-base/src/Collapsible/Trigger/CollapsibleTrigger.tsx @@ -3,7 +3,7 @@ import * as React from 'react'; import PropTypes from 'prop-types'; import { useComponentRenderer } from '../../utils/useComponentRenderer'; import { BaseUIComponentProps } from '../../utils/types'; -import { useCollapsibleContext } from '../Root/CollapsibleContext'; +import { useCollapsibleRootContext } from '../Root/CollapsibleRootContext'; import { CollapsibleRoot } from '../Root/CollapsibleRoot'; import { collapsibleStyleHookMapping } from '../Root/styleHooks'; import { useCollapsibleTrigger } from './useCollapsibleTrigger'; @@ -24,7 +24,7 @@ const CollapsibleTrigger = React.forwardRef(function CollapsibleTrigger( ) { const { className, render, ...otherProps } = props; - const { contentId, open, setOpen, ownerState } = useCollapsibleContext(); + const { contentId, open, setOpen, ownerState } = useCollapsibleRootContext(); const { getRootProps } = useCollapsibleTrigger({ contentId, diff --git a/packages/mui-base/src/Collapsible/Trigger/useCollapsibleTrigger.ts b/packages/mui-base/src/Collapsible/Trigger/useCollapsibleTrigger.ts index b8134383b..ed445c2a9 100644 --- a/packages/mui-base/src/Collapsible/Trigger/useCollapsibleTrigger.ts +++ b/packages/mui-base/src/Collapsible/Trigger/useCollapsibleTrigger.ts @@ -4,16 +4,7 @@ import { mergeReactProps } from '../../utils/mergeReactProps'; import { useForkRef } from '../../utils/useForkRef'; import { GenericHTMLProps } from '../../utils/types'; import { useButton } from '../../useButton'; -/** - * - * Demos: - * - * - [Collapsible](https://mui.com/base-ui/react-collapsible/#hooks) - * - * API: - * - * - [useCollapsibleTrigger API](https://mui.com/base-ui/react-collapsible/hooks-api/#use-collapsible-trigger) - */ + export function useCollapsibleTrigger( parameters: useCollapsibleTrigger.Parameters, ): useCollapsibleTrigger.ReturnValue { diff --git a/packages/mui-base/src/Collapsible/index.barrel.ts b/packages/mui-base/src/Collapsible/index.barrel.ts deleted file mode 100644 index 34a4d1b71..000000000 --- a/packages/mui-base/src/Collapsible/index.barrel.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from './Root/CollapsibleRoot'; -export * from './Root/CollapsibleContext'; -export * from './Trigger/CollapsibleTrigger'; -export * from './Content/CollapsibleContent'; diff --git a/packages/mui-base/src/index.ts b/packages/mui-base/src/index.ts index 5c2fbaeff..00b01aa77 100644 --- a/packages/mui-base/src/index.ts +++ b/packages/mui-base/src/index.ts @@ -1,3 +1,4 @@ +export * from './Accordion'; export * from './AlertDialog'; export * from './Checkbox'; export * from './CheckboxGroup'; From 24be486ac59a2d2d3feb481da3cb8b049465ab6f Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Mon, 14 Oct 2024 15:05:21 +0800 Subject: [PATCH 22/37] Update demos --- docs/app/experiments/accordion-animations.tsx | 169 ++------------ docs/app/experiments/accordion-horizontal.tsx | 144 ++---------- .../accordion.horizontal.module.css | 100 ++++++++ docs/app/experiments/accordion.module.css | 124 ++++++++++ docs/app/experiments/accordion.tsx | 6 +- .../app/experiments/collapsible-accordion.tsx | 151 ------------ docs/app/experiments/collapsible-framer.tsx | 121 ++-------- .../collapsible-hidden-until-found.tsx | 214 ++++-------------- docs/app/experiments/collapsible.module.css | 92 ++++++++ docs/app/experiments/collapsible.tsx | 193 ---------------- .../components/accordion/styles.module.css | 2 +- .../collapsible/CssAnimatedCollapsible.js | 156 +++---------- .../collapsible/CssAnimatedCollapsible.tsx | 156 +++---------- .../CssAnimatedCollapsible.tsx.preview | 13 ++ .../collapsible/CssTransitionCollapsible.js | 145 +++--------- .../collapsible/CssTransitionCollapsible.tsx | 145 +++--------- .../CssTransitionCollapsible.tsx.preview | 13 ++ .../UnstyledCollapsibleIntroduction.js | 99 +++----- .../UnstyledCollapsibleIntroduction.tsx | 99 +++----- .../collapsible/animations.module.css | 25 ++ .../components/collapsible/styles.module.css | 24 ++ .../collapsible/transitions.module.css | 13 ++ 22 files changed, 687 insertions(+), 1517 deletions(-) create mode 100644 docs/app/experiments/accordion.horizontal.module.css create mode 100644 docs/app/experiments/accordion.module.css delete mode 100644 docs/app/experiments/collapsible-accordion.tsx create mode 100644 docs/app/experiments/collapsible.module.css delete mode 100644 docs/app/experiments/collapsible.tsx create mode 100644 docs/data/components/collapsible/CssAnimatedCollapsible.tsx.preview create mode 100644 docs/data/components/collapsible/CssTransitionCollapsible.tsx.preview create mode 100644 docs/data/components/collapsible/animations.module.css create mode 100644 docs/data/components/collapsible/styles.module.css create mode 100644 docs/data/components/collapsible/transitions.module.css diff --git a/docs/app/experiments/accordion-animations.tsx b/docs/app/experiments/accordion-animations.tsx index 64116beab..44da2d428 100644 --- a/docs/app/experiments/accordion-animations.tsx +++ b/docs/app/experiments/accordion-animations.tsx @@ -2,32 +2,37 @@ import * as React from 'react'; import { Accordion } from '@base_ui/react/Accordion'; import { ExpandMoreIcon } from './accordion'; +import classes from './accordion.module.css'; -const DURATION = '300ms'; +function classNames(...c: Array) { + return c.filter(Boolean).join(' '); +} export default function App() { return ( -
+

CSS @keyframe animations + `hidden="until-found"`

{[0, 1, 2].map((index) => ( - - - - Trigger {index + 1} + + + + Trigger {index + 1} - +

This is the contents of Accordion.Panel {index + 1}
It uses `hidden="until-found"` and can be opened by the browser's in-page search +
+

@@ -35,156 +40,22 @@ export default function App() {

CSS transitions

- + {[0, 1, 2].map((index) => ( - - - - Trigger {index + 1} + + + + Trigger {index + 1} - +

This is the contents of Accordion.Panel {index + 1}

+ WCAG 2.2
))}
-
); } - -function MaterialStyles() { - return ( - - ); -} diff --git a/docs/app/experiments/accordion-horizontal.tsx b/docs/app/experiments/accordion-horizontal.tsx index 5362107bb..21e7146c8 100644 --- a/docs/app/experiments/accordion-horizontal.tsx +++ b/docs/app/experiments/accordion-horizontal.tsx @@ -10,23 +10,23 @@ function classNames(...c: Array) { export default function App() { const [val, setVal] = React.useState(['one']); return ( -
+

Horizontal LTR

{['one', 'two', 'three'].map((value, index) => ( - - - - {index + 1} - {value} + + + + {index + 1} + {value} - + This is the contents of Accordion.Panel {index + 1} @@ -38,144 +38,32 @@ export default function App() {

one section must remain open

{ + onValueChange={(newValue: Accordion.Root.Props['Value']) => { if (newValue.length > 0) { setVal(newValue); } }} > {['one', 'two', 'three'].map((value, index) => ( - - - - {index + 1} - {value} + + + + {index + 1} + {value} - + This is the contents of Accordion.Panel {index + 1} ))} -
); } - -function HorizontalStyles() { - return ( - - ); -} diff --git a/docs/app/experiments/accordion.horizontal.module.css b/docs/app/experiments/accordion.horizontal.module.css new file mode 100644 index 000000000..289680d10 --- /dev/null +++ b/docs/app/experiments/accordion.horizontal.module.css @@ -0,0 +1,100 @@ +.wrapper { + margin: 1rem; + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 2rem; +} + +.root { + --Paper-shadow: 0px 2px 1px -1px rgba(0, 0, 0, 0.2), 0px 1px 1px 0px rgba(0, 0, 0, 0.14), + 0px 1px 3px 0px rgba(0, 0, 0, 0.12); + + font-family: system-ui, sans-serif; + box-shadow: var(--Paper-shadow); + background-color: rgba(0, 0, 0, 0.12); + border-radius: 0.3rem; + height: 40rem; + display: inline-flex; +} + +.item { + position: relative; + background-color: #fff; + color: rgba(0, 0, 0, 0.87); + display: flex; +} + +.item:not(:first-of-type) { + margin-left: 1px; +} + +.item:first-of-type { + border-top-left-radius: 0.25rem; + border-top-right-radius: 0.25rem; +} + +.item:last-of-type { + border-bottom-left-radius: 0.25rem; + border-bottom-right-radius: 0.25rem; +} + +.header { + margin: 0; + width: 4rem; +} + +.trigger { + appearance: none; + background-color: transparent; + border: 0; + color: inherit; + cursor: pointer; + padding: 1rem; + position: relative; + height: 100%; + width: 100%; + display: flex; + flex-flow: column nowrap; + align-items: center; +} + +.trigger.one { + background-color: #ddd; +} + +.trigger.two { + background-color: #bbb; +} + +.trigger.three { + background-color: #999; +} + +.trigger:focus-visible { + outline: 0; + background-color: rgba(0, 0, 0, 0.88); + color: #eee; +} + +.trigger .triggerText { + font-size: 1rem; + line-height: 1.5; + margin-bottom: auto; +} + +.trigger .triggerLabel { + font-size: 1rem; + line-height: 1.5; + margin-bottom: 1rem; + transform: rotate(-90deg); +} + +.trigger[data-accordion='open'] svg { + transform: rotate(180deg); +} + +.panel { + padding: 1rem; + width: 32rem; +} diff --git a/docs/app/experiments/accordion.module.css b/docs/app/experiments/accordion.module.css new file mode 100644 index 000000000..4500044e2 --- /dev/null +++ b/docs/app/experiments/accordion.module.css @@ -0,0 +1,124 @@ +@keyframes slideDown { + from { + height: 0; + } + to { + height: var(--accordion-content-height); + } +} + +@keyframes slideUp { + from { + height: var(--accordion-content-height); + } + to { + height: 0; + } +} + +.wrapper { + width: 40rem; + margin: 1rem; + display: flex; + flex-direction: column; + gap: 2rem; +} + +.root { + --duration: 300ms; + --Paper-shadow: 0px 2px 1px -1px rgba(0, 0, 0, 0.2), 0px 1px 1px 0px rgba(0, 0, 0, 0.14), + 0px 1px 3px 0px rgba(0, 0, 0, 0.12); + + font-family: system-ui, sans-serif; + box-shadow: var(--Paper-shadow); + background-color: rgba(0, 0, 0, 0.12); + border-radius: 0.3rem; +} + +.item { + position: relative; + background-color: #fff; + color: rgba(0, 0, 0, 0.87); +} + +.item:not(:first-of-type) { + margin-top: 1px; +} + +.item:first-of-type { + border-top-left-radius: 0.25rem; + border-top-right-radius: 0.25rem; +} + +.item:last-of-type { + border-bottom-left-radius: 0.25rem; + border-bottom-right-radius: 0.25rem; +} + +.header { + margin: 0; +} + +.trigger { + appearance: none; + background-color: transparent; + border: 0; + color: inherit; + cursor: pointer; + padding: 0 1rem; + position: relative; + width: 100%; + display: flex; + flex-flow: row nowrap; + align-items: center; +} + +.trigger:focus-visible { + outline: 0; + background-color: rgba(0, 0, 0, 0.12); +} + +.trigger .triggerText { + font-size: 1rem; + line-height: 1.5; + margin: 12px auto 12px 0; +} + +.trigger svg { + transition: transform 300ms; +} + +.trigger[data-accordion='open'] svg { + transform: rotate(180deg); +} + +.panel { + overflow: hidden; +} + +.panel p { + margin: 0; + padding: 1rem; +} + +.panel.cssanimation[data-accordion='open'] { + animation: slideDown var(--duration) ease-out; +} + +.panel.cssanimation[data-accordion='closed'] { + animation: slideUp var(--duration) ease-out; +} + +.panel.csstransition[data-accordion='open'] { + height: var(--accordion-content-height); + transition: height var(--duration) ease-out; +} + +.panel.csstransition[data-accordion='closed'] { + height: 0; + transition: height var(--duration) ease-in; +} + +.panel.csstransition[data-entering] { + height: 0; +} diff --git a/docs/app/experiments/accordion.tsx b/docs/app/experiments/accordion.tsx index 6b2fb60ac..053a1813f 100644 --- a/docs/app/experiments/accordion.tsx +++ b/docs/app/experiments/accordion.tsx @@ -17,7 +17,7 @@ export default function App() { onCheckedChange={setOpenMultiple} > - + {openMultiple && } @@ -87,7 +87,7 @@ export default function App() { @@ -126,7 +126,7 @@ export default function App() { { + onValueChange={(newValue: Accordion.Root.Props['Value']) => { if (newValue.length > 0) { setVal2(newValue); } diff --git a/docs/app/experiments/collapsible-accordion.tsx b/docs/app/experiments/collapsible-accordion.tsx deleted file mode 100644 index 65e531eb0..000000000 --- a/docs/app/experiments/collapsible-accordion.tsx +++ /dev/null @@ -1,151 +0,0 @@ -'use client'; -import * as React from 'react'; -import { Collapsible } from '@base_ui/react/Collapsible'; - -const TRANSITION_DURATION = '350ms'; - -function AccordionSection(props: { - index: number; - openIndex: number; - setOpen: (nextOpenIndex: number) => void; -}) { - const { index, openIndex, setOpen } = props; - const isOpen = index === openIndex; - return ( - setOpen(isOpen ? -1 : index)}> - - - - - - - {isOpen ? 'Close' : 'Open'} Panel {index} - - -

This is the collapsed content of Panel {index}

-

This is the second paragraph

-

This is the third paragraph

-
- -
- ); -} - -export default function CollapsibleAccordion() { - const [openIndex, setOpen] = React.useState(-1); - return ( -
-
-        A crude accordion where only 1 of the 3 {``}s can be open at any time
-        
- Animated using CSS transitions -
- {[0, 1, 2].map((index) => ( - - ))} -
- ); -} - -const grey = { - 50: '#F3F6F9', - 100: '#E5EAF2', - 200: '#DAE2ED', - 300: '#C7D0DD', - 400: '#B0B8C4', - 500: '#9DA8B7', - 600: '#6B7A90', - 700: '#434D5B', - 800: '#303740', - 900: '#1C2025', -}; - -export function Styles() { - return ( - - ); -} diff --git a/docs/app/experiments/collapsible-framer.tsx b/docs/app/experiments/collapsible-framer.tsx index 62bf360ee..85a66fef0 100644 --- a/docs/app/experiments/collapsible-framer.tsx +++ b/docs/app/experiments/collapsible-framer.tsx @@ -1,24 +1,24 @@ 'use client'; import * as React from 'react'; -import { useTheme } from '@mui/system'; import { Collapsible } from '@base_ui/react/Collapsible'; import { motion } from 'framer-motion'; +import classes from './collapsible.module.css'; + +function classNames(...c: Array) { + return c.filter(Boolean).join(' '); +} export default function CollapsibleFramer() { const [open, setOpen] = React.useState(false); return ( -
+
- - - - - - + + Trigger https://adrianroselli.com/2020/05/disclosure-widgets.html

-
); } -const grey = { - 50: '#F3F6F9', - 100: '#E5EAF2', - 200: '#DAE2ED', - 300: '#C7D0DD', - 400: '#B0B8C4', - 500: '#9DA8B7', - 600: '#6B7A90', - 700: '#434D5B', - 800: '#303740', - 900: '#1C2025', -}; - -function useIsDarkMode() { - const theme = useTheme(); - return theme.palette.mode === 'dark'; -} - -export function Styles() { - const isDarkMode = useIsDarkMode(); +function ExpandMoreIcon(props: React.SVGProps) { return ( - + + + ); } diff --git a/docs/app/experiments/collapsible-hidden-until-found.tsx b/docs/app/experiments/collapsible-hidden-until-found.tsx index befbb2b0b..79d87ed7f 100644 --- a/docs/app/experiments/collapsible-hidden-until-found.tsx +++ b/docs/app/experiments/collapsible-hidden-until-found.tsx @@ -1,13 +1,16 @@ 'use client'; import * as React from 'react'; import { Collapsible } from '@base_ui/react/Collapsible'; +import classes from './collapsible.module.css'; -const DURATION = '350ms'; +function classNames(...c: Array) { + return c.filter(Boolean).join(' '); +} export default function CollapsibleHiddenUntilFound() { return ( -
+      
         All 3 Collapsibles contain the text "May the force be with you" but only the
         content in the 2nd and 3rd Collapsible will be revealed by the browser's in-page search
         (e.g. Ctrl/Cmd-F) in{' '}
@@ -20,205 +23,66 @@ export default function CollapsibleHiddenUntilFound() {
         animation will be disabled (one-off) and open instantly
         

- Collapsible #2 is animated using CSS @keyframe animation, while #3 is animated with CSS - transitions. #3 demonstrates a possible browser bug where the matching text is not properly - highlighted by the browser the first time that instance is matched. It only occurs with - transitions, not @keyframe animations. + Collapsible #2 is animated using CSS @keyframe animation, while #1 and #3 is animated with + CSS transitions. #3 demonstrates a possible browser bug where the matching text is not + properly highlighted by the browser the first time that instance is matched. It only occurs + with transitions, not @keyframe animations.
-
+
- - - - - - - Toggle 1 + + + Trigger 1 - +

This is the collapsed content

May the force be with you

-
- - - - - - - Toggle 2 + + + Trigger 2 - +

This is the collapsed content

May the force be with you

-
- - - - - - - Toggle 3 + + + Trigger 3 - +

This is the collapsed content

May the force be with you

-
); } -const grey = { - 50: '#F3F6F9', - 100: '#E5EAF2', - 200: '#DAE2ED', - 300: '#C7D0DD', - 400: '#B0B8C4', - 500: '#9DA8B7', - 600: '#6B7A90', - 700: '#434D5B', - 800: '#303740', - 900: '#1C2025', -}; - -export function Styles() { +function ExpandMoreIcon(props: React.SVGProps) { return ( - + + + ); } diff --git a/docs/app/experiments/collapsible.module.css b/docs/app/experiments/collapsible.module.css new file mode 100644 index 000000000..4e1ee6222 --- /dev/null +++ b/docs/app/experiments/collapsible.module.css @@ -0,0 +1,92 @@ +.wrapper { + font-family: system-ui, sans-serif; + line-height: 1.4; + display: flex; + flex-flow: column nowrap; + align-items: stretch; + width: 400px; + margin: 2rem; +} + +.pre { + line-height: 1.5; + max-width: 75ch; + white-space: pre-wrap; + margin: 1rem 1rem 2rem; +} + +.trigger { + display: flex; + align-items: center; + padding-left: 0; +} + +.trigger:not(:first-of-type) { + margin-top: 3rem; +} + +.icon { + transform: rotate(-90deg); +} + +.trigger[data-collapsible='open'] .icon { + transform: rotate(0); +} + +.content { + --duration: 350ms; + + background-color: #eaeaea; + overflow: hidden; +} + +.content.animation[data-collapsible='open'] { + animation: slideDown var(--duration) ease-out; +} + +.content.animation[data-collapsible='closed'] { + animation: slideUp var(--duration) ease-in; +} + +.content.transition[data-collapsible='open'] { + height: var(--collapsible-content-height); + transition: height var(--duration) ease-out; +} + +.content.transition[data-collapsible='closed'] { + height: 0; + transition: height var(--duration) ease-in; +} + +.content.transition[data-entering] { + height: 0; +} + +.content.transition[hidden='until-found'] { + transition-duration: 0s !important; +} + +.content.framer { + background-color: #eaeaea; + overflow: hidden; + display: flex; + flex-direction: column; +} + +@keyframes slideDown { + from { + height: 0; + } + to { + height: var(--collapsible-content-height); + } +} + +@keyframes slideUp { + from { + height: var(--collapsible-content-height); + } + to { + height: 0; + } +} diff --git a/docs/app/experiments/collapsible.tsx b/docs/app/experiments/collapsible.tsx deleted file mode 100644 index a1e2429a6..000000000 --- a/docs/app/experiments/collapsible.tsx +++ /dev/null @@ -1,193 +0,0 @@ -'use client'; -import * as React from 'react'; -import { Collapsible } from '@base_ui/react/Collapsible'; - -const DURATION = '350ms'; - -export default function CollapsibleDemo() { - return ( -
-
- - - - - - - - Trigger (CSS animation) - - -

This is the collapsed content

-

This component is animated with CSS @keyframe animations

-

demo: https://codepen.io/aardrian/pen/QWjBNQG

-

https://adrianroselli.com/2020/05/disclosure-widgets.html

-
-
-
- -
- - - - - - - - Trigger (CSS transition) - - -

This is the collapsed content

-

This component is animated with CSS transitions

-

demo: https://codepen.io/aardrian/pen/QWjBNQG

-

https://adrianroselli.com/2020/05/disclosure-widgets.html

-
-
-
- - - - - - - - - Trigger (root renders a span + CSS transition) - - -

This is the collapsed content

-

This component is animated with CSS transitions

-

demo: https://codepen.io/aardrian/pen/QWjBNQG

-

https://adrianroselli.com/2020/05/disclosure-widgets.html

-
-
- -
- ); -} - -const grey = { - 50: '#F3F6F9', - 100: '#E5EAF2', - 200: '#DAE2ED', - 300: '#C7D0DD', - 400: '#B0B8C4', - 500: '#9DA8B7', - 600: '#6B7A90', - 700: '#434D5B', - 800: '#303740', - 900: '#1C2025', -}; - -export function Styles() { - return ( - - ); -} diff --git a/docs/data/components/accordion/styles.module.css b/docs/data/components/accordion/styles.module.css index 0bd0b5974..58a901b41 100644 --- a/docs/data/components/accordion/styles.module.css +++ b/docs/data/components/accordion/styles.module.css @@ -72,7 +72,7 @@ margin: 12px auto 12px 0; } -.trigger[data-collapsible='open'] svg { +.trigger[data-accordion='open'] svg { transform: rotate(180deg); } diff --git a/docs/data/components/collapsible/CssAnimatedCollapsible.js b/docs/data/components/collapsible/CssAnimatedCollapsible.js index e80819527..075a59b38 100644 --- a/docs/data/components/collapsible/CssAnimatedCollapsible.js +++ b/docs/data/components/collapsible/CssAnimatedCollapsible.js @@ -1,139 +1,43 @@ 'use client'; import * as React from 'react'; -import { useTheme } from '@mui/system'; import { Collapsible } from '@base_ui/react/Collapsible'; +import animationClasses from './animations.module.css'; +import classes from './styles.module.css'; + +function classNames(...c) { + return c.filter(Boolean).join(' '); +} export default function CssAnimatedCollapsible() { const [open, setOpen] = React.useState(true); return ( -
- - - - - - - - Show {open ? 'less' : 'more'} - - -

This is the collapsed content

-

This is the second paragraph

-

This is a longer sentence and also the third paragraph

-
-
- -
+ + + + Show {open ? 'less' : 'more'} + + +

This is the collapsed content

+

This is the second paragraph

+

This is a longer sentence and also the third paragraph

+
+
); } -const grey = { - 50: '#F3F6F9', - 100: '#E5EAF2', - 200: '#DAE2ED', - 300: '#C7D0DD', - 400: '#B0B8C4', - 500: '#9DA8B7', - 600: '#6B7A90', - 700: '#434D5B', - 800: '#303740', - 900: '#1C2025', -}; - -function useIsDarkMode() { - const theme = useTheme(); - return theme.palette.mode === 'dark'; -} - -export function Styles() { - const isDarkMode = useIsDarkMode(); +function ExpandMoreIcon(props) { return ( - + + + ); } diff --git a/docs/data/components/collapsible/CssAnimatedCollapsible.tsx b/docs/data/components/collapsible/CssAnimatedCollapsible.tsx index e80819527..5621aa5b8 100644 --- a/docs/data/components/collapsible/CssAnimatedCollapsible.tsx +++ b/docs/data/components/collapsible/CssAnimatedCollapsible.tsx @@ -1,139 +1,43 @@ 'use client'; import * as React from 'react'; -import { useTheme } from '@mui/system'; import { Collapsible } from '@base_ui/react/Collapsible'; +import animationClasses from './animations.module.css'; +import classes from './styles.module.css'; + +function classNames(...c: Array) { + return c.filter(Boolean).join(' '); +} export default function CssAnimatedCollapsible() { const [open, setOpen] = React.useState(true); return ( -
- - - - - - - - Show {open ? 'less' : 'more'} - - -

This is the collapsed content

-

This is the second paragraph

-

This is a longer sentence and also the third paragraph

-
-
- -
+ + + + Show {open ? 'less' : 'more'} + + +

This is the collapsed content

+

This is the second paragraph

+

This is a longer sentence and also the third paragraph

+
+
); } -const grey = { - 50: '#F3F6F9', - 100: '#E5EAF2', - 200: '#DAE2ED', - 300: '#C7D0DD', - 400: '#B0B8C4', - 500: '#9DA8B7', - 600: '#6B7A90', - 700: '#434D5B', - 800: '#303740', - 900: '#1C2025', -}; - -function useIsDarkMode() { - const theme = useTheme(); - return theme.palette.mode === 'dark'; -} - -export function Styles() { - const isDarkMode = useIsDarkMode(); +function ExpandMoreIcon(props: React.SVGProps) { return ( - + + + ); } diff --git a/docs/data/components/collapsible/CssAnimatedCollapsible.tsx.preview b/docs/data/components/collapsible/CssAnimatedCollapsible.tsx.preview new file mode 100644 index 000000000..73064abf7 --- /dev/null +++ b/docs/data/components/collapsible/CssAnimatedCollapsible.tsx.preview @@ -0,0 +1,13 @@ + + + + Show {open ? 'less' : 'more'} + + +

This is the collapsed content

+

This is the second paragraph

+

This is a longer sentence and also the third paragraph

+
+
\ No newline at end of file diff --git a/docs/data/components/collapsible/CssTransitionCollapsible.js b/docs/data/components/collapsible/CssTransitionCollapsible.js index d87a29a72..0b1d864a9 100644 --- a/docs/data/components/collapsible/CssTransitionCollapsible.js +++ b/docs/data/components/collapsible/CssTransitionCollapsible.js @@ -1,128 +1,43 @@ 'use client'; import * as React from 'react'; -import { useTheme } from '@mui/system'; import { Collapsible } from '@base_ui/react/Collapsible'; +import transitionClasses from './transitions.module.css'; +import classes from './styles.module.css'; + +function classNames(...c) { + return c.filter(Boolean).join(' '); +} export default function CssTransitionCollapsible() { const [open, setOpen] = React.useState(true); return ( -
- - - - - - - - Show {open ? 'less' : 'more'} - - -

This is the collapsed content

-

This is the second paragraph

-

This is a longer sentence and also the third paragraph

-
-
- -
+ + + + Show {open ? 'less' : 'more'} + + +

This is the collapsed content

+

This is the second paragraph

+

This is a longer sentence and also the third paragraph

+
+
); } -const grey = { - 50: '#F3F6F9', - 100: '#E5EAF2', - 200: '#DAE2ED', - 300: '#C7D0DD', - 400: '#B0B8C4', - 500: '#9DA8B7', - 600: '#6B7A90', - 700: '#434D5B', - 800: '#303740', - 900: '#1C2025', -}; - -function useIsDarkMode() { - const theme = useTheme(); - return theme.palette.mode === 'dark'; -} - -export function Styles() { - const isDarkMode = useIsDarkMode(); +function ExpandMoreIcon(props) { return ( - + + + ); } diff --git a/docs/data/components/collapsible/CssTransitionCollapsible.tsx b/docs/data/components/collapsible/CssTransitionCollapsible.tsx index d87a29a72..3dfc821cb 100644 --- a/docs/data/components/collapsible/CssTransitionCollapsible.tsx +++ b/docs/data/components/collapsible/CssTransitionCollapsible.tsx @@ -1,128 +1,43 @@ 'use client'; import * as React from 'react'; -import { useTheme } from '@mui/system'; import { Collapsible } from '@base_ui/react/Collapsible'; +import transitionClasses from './transitions.module.css'; +import classes from './styles.module.css'; + +function classNames(...c: Array) { + return c.filter(Boolean).join(' '); +} export default function CssTransitionCollapsible() { const [open, setOpen] = React.useState(true); return ( -
- - - - - - - - Show {open ? 'less' : 'more'} - - -

This is the collapsed content

-

This is the second paragraph

-

This is a longer sentence and also the third paragraph

-
-
- -
+ + + + Show {open ? 'less' : 'more'} + + +

This is the collapsed content

+

This is the second paragraph

+

This is a longer sentence and also the third paragraph

+
+
); } -const grey = { - 50: '#F3F6F9', - 100: '#E5EAF2', - 200: '#DAE2ED', - 300: '#C7D0DD', - 400: '#B0B8C4', - 500: '#9DA8B7', - 600: '#6B7A90', - 700: '#434D5B', - 800: '#303740', - 900: '#1C2025', -}; - -function useIsDarkMode() { - const theme = useTheme(); - return theme.palette.mode === 'dark'; -} - -export function Styles() { - const isDarkMode = useIsDarkMode(); +function ExpandMoreIcon(props: React.SVGProps) { return ( - + + + ); } diff --git a/docs/data/components/collapsible/CssTransitionCollapsible.tsx.preview b/docs/data/components/collapsible/CssTransitionCollapsible.tsx.preview new file mode 100644 index 000000000..96c6e8f88 --- /dev/null +++ b/docs/data/components/collapsible/CssTransitionCollapsible.tsx.preview @@ -0,0 +1,13 @@ + + + + Show {open ? 'less' : 'more'} + + +

This is the collapsed content

+

This is the second paragraph

+

This is a longer sentence and also the third paragraph

+
+
\ No newline at end of file diff --git a/docs/data/components/collapsible/UnstyledCollapsibleIntroduction.js b/docs/data/components/collapsible/UnstyledCollapsibleIntroduction.js index 6bd55ebe7..2c23d4a9f 100644 --- a/docs/data/components/collapsible/UnstyledCollapsibleIntroduction.js +++ b/docs/data/components/collapsible/UnstyledCollapsibleIntroduction.js @@ -1,77 +1,42 @@ 'use client'; import * as React from 'react'; -import { styled, useTheme, Box } from '@mui/system'; -import { Collapsible as BaseCollapsible } from '@base_ui/react/Collapsible'; - -const Collapsible = BaseCollapsible.Root; - -const CollapsibleTrigger = styled(BaseCollapsible.Trigger)` - display: flex; - flex-flow: row nowrap; - justify-content: center; - gap: 4px; - font-size: 16px; - - & svg { - margin-top: 1px; - } - - &[data-collapsible='open'] svg { - transform: rotate(180deg); - } -`; - -const CollapsibleContent = styled(BaseCollapsible.Content)``; +import { Collapsible } from '@base_ui/react/Collapsible'; +import classes from './styles.module.css'; export default function UnstyledCollapsibleIntroduction() { - // Replace this with your app logic for determining dark mode - const isDarkMode = useIsDarkMode(); const [open, setOpen] = React.useState(true); return ( - - - - - - - Show {open ? 'less' : 'more'} - - -

- This is the collapsed content. The element that shows and hides the - content has role button -

-

- When the content is visible, the element with role `button` has - `aria-expanded` set to `true` -

-

When the content area is hidden, it is set to `false`

-

- Optionally, the element with role `button` has a value specified for - `aria-controls` that refers to the element that contains all the content - that is shown or hidden -

-
-
-
+ + + + Show {open ? 'less' : 'more'} + + +

+ This is the collapsed content. The element that shows and hides the content + has role button +

+

+ When the content is visible, the element with role `button` has + `aria-expanded` set to `true` +

+

When the content panel is hidden, it is set to `false`

+
+
); } -function useIsDarkMode() { - const theme = useTheme(); - return theme.palette.mode === 'dark'; +function ExpandMoreIcon(props) { + return ( + + + + ); } diff --git a/docs/data/components/collapsible/UnstyledCollapsibleIntroduction.tsx b/docs/data/components/collapsible/UnstyledCollapsibleIntroduction.tsx index 6bd55ebe7..bc2d2281f 100644 --- a/docs/data/components/collapsible/UnstyledCollapsibleIntroduction.tsx +++ b/docs/data/components/collapsible/UnstyledCollapsibleIntroduction.tsx @@ -1,77 +1,42 @@ 'use client'; import * as React from 'react'; -import { styled, useTheme, Box } from '@mui/system'; -import { Collapsible as BaseCollapsible } from '@base_ui/react/Collapsible'; - -const Collapsible = BaseCollapsible.Root; - -const CollapsibleTrigger = styled(BaseCollapsible.Trigger)` - display: flex; - flex-flow: row nowrap; - justify-content: center; - gap: 4px; - font-size: 16px; - - & svg { - margin-top: 1px; - } - - &[data-collapsible='open'] svg { - transform: rotate(180deg); - } -`; - -const CollapsibleContent = styled(BaseCollapsible.Content)``; +import { Collapsible } from '@base_ui/react/Collapsible'; +import classes from './styles.module.css'; export default function UnstyledCollapsibleIntroduction() { - // Replace this with your app logic for determining dark mode - const isDarkMode = useIsDarkMode(); const [open, setOpen] = React.useState(true); return ( - - - - - - - Show {open ? 'less' : 'more'} - - -

- This is the collapsed content. The element that shows and hides the - content has role button -

-

- When the content is visible, the element with role `button` has - `aria-expanded` set to `true` -

-

When the content area is hidden, it is set to `false`

-

- Optionally, the element with role `button` has a value specified for - `aria-controls` that refers to the element that contains all the content - that is shown or hidden -

-
-
-
+ + + + Show {open ? 'less' : 'more'} + + +

+ This is the collapsed content. The element that shows and hides the content + has role button +

+

+ When the content is visible, the element with role `button` has + `aria-expanded` set to `true` +

+

When the content panel is hidden, it is set to `false`

+
+
); } -function useIsDarkMode() { - const theme = useTheme(); - return theme.palette.mode === 'dark'; +function ExpandMoreIcon(props: React.SVGProps) { + return ( + + + + ); } diff --git a/docs/data/components/collapsible/animations.module.css b/docs/data/components/collapsible/animations.module.css new file mode 100644 index 000000000..93483d34c --- /dev/null +++ b/docs/data/components/collapsible/animations.module.css @@ -0,0 +1,25 @@ +@keyframes slideDown { + from { + height: 0; + } + to { + height: var(--collapsible-content-height); + } +} + +@keyframes slideUp { + from { + height: var(--collapsible-content-height); + } + to { + height: 0; + } +} + +.content[data-collapsible='open'] { + animation: slideDown 300ms ease-out; +} + +.content[data-collapsible='closed'] { + animation: slideUp 300ms ease-out; +} diff --git a/docs/data/components/collapsible/styles.module.css b/docs/data/components/collapsible/styles.module.css new file mode 100644 index 000000000..b5e949498 --- /dev/null +++ b/docs/data/components/collapsible/styles.module.css @@ -0,0 +1,24 @@ +.trigger { + display: flex; + width: 320px; + align-items: center; + padding-left: 0; +} + +.icon { + transform: rotate(-90deg); +} + +.trigger[data-collapsible='open'] .icon { + transform: rotate(0); +} + +.content { + overflow: hidden; + box-sizing: border-box; + width: 320px; + padding: 1.5rem 1rem 1rem; + background-color: buttonface; + border-bottom-left-radius: 2px; + border-bottom-right-radius: 2px; +} diff --git a/docs/data/components/collapsible/transitions.module.css b/docs/data/components/collapsible/transitions.module.css new file mode 100644 index 000000000..ce4f95486 --- /dev/null +++ b/docs/data/components/collapsible/transitions.module.css @@ -0,0 +1,13 @@ +.content[data-collapsible='open'] { + height: var(--collapsible-content-height); + transition: height 200ms ease-out; +} + +.content[data-collapsible='closed'] { + height: 0; + transition: height 200ms ease-in; +} + +.content[data-entering] { + height: 0; +} From c76e66802d0e6797dc701917f9fd36c1a4067458 Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Tue, 15 Oct 2024 17:23:02 +0800 Subject: [PATCH 23/37] Merge collapsible internal height and width states --- .../Content/useCollapsibleContent.ts | 58 +++++++++---------- 1 file changed, 28 insertions(+), 30 deletions(-) diff --git a/packages/mui-base/src/Collapsible/Content/useCollapsibleContent.ts b/packages/mui-base/src/Collapsible/Content/useCollapsibleContent.ts index ba1f7afc9..1edbf1b32 100644 --- a/packages/mui-base/src/Collapsible/Content/useCollapsibleContent.ts +++ b/packages/mui-base/src/Collapsible/Content/useCollapsibleContent.ts @@ -51,8 +51,10 @@ export function useCollapsibleContent( const contentRef = React.useRef(null); - const [height, setHeight] = React.useState(0); - const [width, setWidth] = React.useState(0); + const [{ height, width }, setDimensions] = React.useState<{ height: number; width: number }>({ + height: 0, + width: 0, + }); const latestAnimationNameRef = React.useRef('none'); const originalTransitionDurationStyleRef = React.useRef(null); @@ -114,8 +116,7 @@ export function useCollapsibleContent( const rect = element.getBoundingClientRect(); if (!isTransitioning || !(open || contextMounted)) { - setHeight(rect.height); - setWidth(rect.width); + setDimensions({ height: rect.height, width: rect.width }); } element.style.animationName = shouldCancelAnimation ? 'none' : originalAnimationName; @@ -174,37 +175,34 @@ export function useCollapsibleContent( }; }, []); - React.useEffect( - function registerCssTransitionListeners() { - const { current: element } = contentRef; - if (!element) { - return undefined; - } + React.useEffect(function registerCssTransitionListeners() { + const { current: element } = contentRef; + if (!element) { + return undefined; + } - function handleTransitionRun() { - isTransitioningRef.current = true; - } + function handleTransitionRun() { + isTransitioningRef.current = true; + } - function handleTransitionEnd() { - isTransitioningRef.current = false; - } + function handleTransitionEnd() { + isTransitioningRef.current = false; + } - function handleTransitionCancel() { - isTransitioningRef.current = false; - } + function handleTransitionCancel() { + isTransitioningRef.current = false; + } - element.addEventListener('transitioncancel', handleTransitionCancel); - element.addEventListener('transitionend', handleTransitionEnd); - element.addEventListener('transitionrun', handleTransitionRun); + element.addEventListener('transitioncancel', handleTransitionCancel); + element.addEventListener('transitionend', handleTransitionEnd); + element.addEventListener('transitionrun', handleTransitionRun); - return () => { - element.removeEventListener('transitioncancel', handleTransitionCancel); - element.removeEventListener('transitionend', handleTransitionEnd); - element.removeEventListener('transitionrun', handleTransitionRun); - }; - }, - [open, setHeight], - ); + return () => { + element.removeEventListener('transitioncancel', handleTransitionCancel); + element.removeEventListener('transitionend', handleTransitionEnd); + element.removeEventListener('transitionrun', handleTransitionRun); + }; + }, []); // if `hidden="until-found"` content is revealed by browser's in-page search // we need to manually sync the open state From f87d7f0f98d8010e4aee590eddbc30427241debb Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Wed, 16 Oct 2024 13:43:21 +0800 Subject: [PATCH 24/37] Finalize demo margin padding --- docs/app/experiments/collapsible-framer.tsx | 4 ++++ docs/app/experiments/collapsible.module.css | 20 ++++++++++++++----- .../collapsible/CssAnimatedCollapsible.js | 11 +++++++++- .../collapsible/CssAnimatedCollapsible.tsx | 11 +++++++++- .../CssAnimatedCollapsible.tsx.preview | 13 ------------ .../collapsible/CssTransitionCollapsible.js | 16 ++++++++++++--- .../collapsible/CssTransitionCollapsible.tsx | 16 ++++++++++++--- .../CssTransitionCollapsible.tsx.preview | 13 ------------ .../components/collapsible/styles.module.css | 7 ++++++- 9 files changed, 71 insertions(+), 40 deletions(-) delete mode 100644 docs/data/components/collapsible/CssAnimatedCollapsible.tsx.preview delete mode 100644 docs/data/components/collapsible/CssTransitionCollapsible.tsx.preview diff --git a/docs/app/experiments/collapsible-framer.tsx b/docs/app/experiments/collapsible-framer.tsx index 85a66fef0..f5edefa96 100644 --- a/docs/app/experiments/collapsible-framer.tsx +++ b/docs/app/experiments/collapsible-framer.tsx @@ -25,6 +25,10 @@ export default function CollapsibleFramer() { initial={false} animate={open ? 'open' : 'closed'} exit={!open ? 'open' : 'closed'} + // https://github.com/framer/motion/issues/368#issuecomment-898055607 + // it's possible to animate padding on Collapsible.Panel with framer-motion + // it looks much less janky than using CSS animations or transitions, but + // it's still noticeably un-smooth variants={{ open: { height: 'auto', diff --git a/docs/app/experiments/collapsible.module.css b/docs/app/experiments/collapsible.module.css index 4e1ee6222..3b6c3c47c 100644 --- a/docs/app/experiments/collapsible.module.css +++ b/docs/app/experiments/collapsible.module.css @@ -1,10 +1,13 @@ .wrapper { + --width: 320px; + --duration: 300ms; + font-family: system-ui, sans-serif; line-height: 1.4; display: flex; flex-flow: column nowrap; align-items: stretch; - width: 400px; + width: var(--width); margin: 2rem; } @@ -27,17 +30,21 @@ .icon { transform: rotate(-90deg); + transition: transform var(--duration) ease-in; } .trigger[data-collapsible='open'] .icon { transform: rotate(0); + transition: transform var(--duration) ease-out; } .content { - --duration: 350ms; - background-color: #eaeaea; overflow: hidden; + box-sizing: border-box; + width: var(--width); + padding-left: 1rem; + padding-right: 1rem; } .content.animation[data-collapsible='open'] { @@ -67,12 +74,15 @@ } .content.framer { - background-color: #eaeaea; - overflow: hidden; display: flex; flex-direction: column; } +.content p { + margin: 1.25rem auto; + overflow-wrap: break-word; +} + @keyframes slideDown { from { height: 0; diff --git a/docs/data/components/collapsible/CssAnimatedCollapsible.js b/docs/data/components/collapsible/CssAnimatedCollapsible.js index 075a59b38..c0093d1ed 100644 --- a/docs/data/components/collapsible/CssAnimatedCollapsible.js +++ b/docs/data/components/collapsible/CssAnimatedCollapsible.js @@ -20,7 +20,16 @@ export default function CssAnimatedCollapsible() { className={classNames(classes.content, animationClasses.content)} >

This is the collapsed content

-

This is the second paragraph

+

+ You can find the Base UI repository{' '} + + here + +

This is a longer sentence and also the third paragraph

diff --git a/docs/data/components/collapsible/CssAnimatedCollapsible.tsx b/docs/data/components/collapsible/CssAnimatedCollapsible.tsx index 5621aa5b8..f9de682fd 100644 --- a/docs/data/components/collapsible/CssAnimatedCollapsible.tsx +++ b/docs/data/components/collapsible/CssAnimatedCollapsible.tsx @@ -20,7 +20,16 @@ export default function CssAnimatedCollapsible() { className={classNames(classes.content, animationClasses.content)} >

This is the collapsed content

-

This is the second paragraph

+

+ You can find the Base UI repository{' '} + + here + +

This is a longer sentence and also the third paragraph

diff --git a/docs/data/components/collapsible/CssAnimatedCollapsible.tsx.preview b/docs/data/components/collapsible/CssAnimatedCollapsible.tsx.preview deleted file mode 100644 index 73064abf7..000000000 --- a/docs/data/components/collapsible/CssAnimatedCollapsible.tsx.preview +++ /dev/null @@ -1,13 +0,0 @@ - - - - Show {open ? 'less' : 'more'} - - -

This is the collapsed content

-

This is the second paragraph

-

This is a longer sentence and also the third paragraph

-
-
\ No newline at end of file diff --git a/docs/data/components/collapsible/CssTransitionCollapsible.js b/docs/data/components/collapsible/CssTransitionCollapsible.js index 0b1d864a9..12e5541d7 100644 --- a/docs/data/components/collapsible/CssTransitionCollapsible.js +++ b/docs/data/components/collapsible/CssTransitionCollapsible.js @@ -19,9 +19,19 @@ export default function CssTransitionCollapsible() { -

This is the collapsed content

-

This is the second paragraph

-

This is a longer sentence and also the third paragraph

+

This is the collapsed content.

+

+ You can find the Base UI repository{' '} + + here + + . +

+

This is a longer sentence and also the third paragraph.

); diff --git a/docs/data/components/collapsible/CssTransitionCollapsible.tsx b/docs/data/components/collapsible/CssTransitionCollapsible.tsx index 3dfc821cb..d7879af76 100644 --- a/docs/data/components/collapsible/CssTransitionCollapsible.tsx +++ b/docs/data/components/collapsible/CssTransitionCollapsible.tsx @@ -19,9 +19,19 @@ export default function CssTransitionCollapsible() { -

This is the collapsed content

-

This is the second paragraph

-

This is a longer sentence and also the third paragraph

+

This is the collapsed content.

+

+ You can find the Base UI repository{' '} + + here + + . +

+

This is a longer sentence and also the third paragraph.

); diff --git a/docs/data/components/collapsible/CssTransitionCollapsible.tsx.preview b/docs/data/components/collapsible/CssTransitionCollapsible.tsx.preview deleted file mode 100644 index 96c6e8f88..000000000 --- a/docs/data/components/collapsible/CssTransitionCollapsible.tsx.preview +++ /dev/null @@ -1,13 +0,0 @@ - - - - Show {open ? 'less' : 'more'} - - -

This is the collapsed content

-

This is the second paragraph

-

This is a longer sentence and also the third paragraph

-
-
\ No newline at end of file diff --git a/docs/data/components/collapsible/styles.module.css b/docs/data/components/collapsible/styles.module.css index b5e949498..82272cdfe 100644 --- a/docs/data/components/collapsible/styles.module.css +++ b/docs/data/components/collapsible/styles.module.css @@ -17,8 +17,13 @@ overflow: hidden; box-sizing: border-box; width: 320px; - padding: 1.5rem 1rem 1rem; + padding-left: 1rem; + padding-right: 1rem; background-color: buttonface; border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; } + +.content p { + margin: 1.5rem auto 1rem; +} From 283ec66bedb29342faeb63e695e9d98ee056fe18 Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Tue, 15 Oct 2024 17:39:43 +0800 Subject: [PATCH 25/37] Refactor collapsible content internals --- .../Content/useCollapsibleContent.ts | 39 ++++++++++--------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/packages/mui-base/src/Collapsible/Content/useCollapsibleContent.ts b/packages/mui-base/src/Collapsible/Content/useCollapsibleContent.ts index 1edbf1b32..839df0303 100644 --- a/packages/mui-base/src/Collapsible/Content/useCollapsibleContent.ts +++ b/packages/mui-base/src/Collapsible/Content/useCollapsibleContent.ts @@ -32,6 +32,11 @@ function supportsHiddenUntilFound(element: HTMLElement) { return cachedSupportsHiddenUntilFound; } +interface Dimensions { + height: number; + width: number; +} + export function useCollapsibleContent( parameters: useCollapsibleContent.Parameters, ): useCollapsibleContent.ReturnValue { @@ -49,9 +54,9 @@ export function useCollapsibleContent( const id = useId(idParam); - const contentRef = React.useRef(null); + const contentElementRef = React.useRef(null); - const [{ height, width }, setDimensions] = React.useState<{ height: number; width: number }>({ + const [{ height, width }, setDimensions] = React.useState({ height: 0, width: 0, }); @@ -73,7 +78,7 @@ export function useCollapsibleContent( return; } - contentRef.current = element; + contentElementRef.current = element; const computedStyles = getComputedStyles(element); @@ -83,7 +88,7 @@ export function useCollapsibleContent( const mergedRef = useForkRef(ref, handleContentRef); - const runOnceAnimationsFinish = useAnimationsFinished(contentRef); + const runOnceAnimationsFinish = useAnimationsFinished(contentElementRef); const isOpen = animated ? open || contextMounted : open; @@ -92,14 +97,12 @@ export function useCollapsibleContent( const isBeforeMatchRef = React.useRef(false); useEnhancedEffect(() => { - const { current: element } = contentRef; + const { current: element } = contentElementRef; let frame1 = -1; let frame2 = -1; if (element) { - const computedStyles = getComputedStyles(element); - const currentAnimationName = computedStyles.animationName; const isBeforeMatch = isBeforeMatchRef.current; const isInitiallyOpen = isInitialOpenRef.current; const isTransitioning = isTransitioningRef.current; @@ -113,10 +116,14 @@ export function useCollapsibleContent( element.style.animationName = 'none'; - const rect = element.getBoundingClientRect(); + const isClosed = !open && !contextMounted; - if (!isTransitioning || !(open || contextMounted)) { - setDimensions({ height: rect.height, width: rect.width }); + if (!isTransitioning || isClosed) { + const rect = isClosed ? { height: 0, width: 0 } : element.getBoundingClientRect(); + setDimensions({ + height: rect.height, + width: rect.width, + }); } element.style.animationName = shouldCancelAnimation ? 'none' : originalAnimationName; @@ -137,10 +144,6 @@ export function useCollapsibleContent( } }); }); - - if (currentAnimationName !== 'none') { - latestAnimationNameRef.current = currentAnimationName; - } } return () => { @@ -150,7 +153,7 @@ export function useCollapsibleContent( }, [open, contextMounted, runOnceAnimationsFinish, setContextMounted]); React.useEffect(() => { - const { current: element } = contentRef; + const { current: element } = contentElementRef; let frame2 = -1; let frame3 = -1; @@ -176,7 +179,7 @@ export function useCollapsibleContent( }, []); React.useEffect(function registerCssTransitionListeners() { - const { current: element } = contentRef; + const { current: element } = contentElementRef; if (!element) { return undefined; } @@ -208,7 +211,7 @@ export function useCollapsibleContent( // we need to manually sync the open state React.useEffect( function registerBeforeMatchListener() { - const { current: element } = contentRef; + const { current: element } = contentElementRef; if (!element || !supportsHiddenUntilFound(element)) { return undefined; @@ -236,7 +239,7 @@ export function useCollapsibleContent( // so we have to force it back to `'until-found'` in the DOM when applicable // https://github.com/facebook/react/issues/24740 useEnhancedEffect(() => { - const { current: element } = contentRef; + const { current: element } = contentElementRef; if ( element && From ddc25475bcf5de4139e1e8d6a5a2d37c521da272 Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Wed, 16 Oct 2024 17:28:29 +0800 Subject: [PATCH 26/37] Improve getting computed styles performance --- .../Content/useCollapsibleContent.ts | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/packages/mui-base/src/Collapsible/Content/useCollapsibleContent.ts b/packages/mui-base/src/Collapsible/Content/useCollapsibleContent.ts index 839df0303..d1e78d67c 100644 --- a/packages/mui-base/src/Collapsible/Content/useCollapsibleContent.ts +++ b/packages/mui-base/src/Collapsible/Content/useCollapsibleContent.ts @@ -9,9 +9,25 @@ import { useAnimationsFinished } from '../../utils/useAnimationsFinished'; import { useForkRef } from '../../utils/useForkRef'; import { useId } from '../../utils/useId'; -function getComputedStyles(element: HTMLElement) { +let cachedSupportsComputedStyleMap: boolean | undefined; + +function supportsComputedStyleMap(element: HTMLElement) { + if (cachedSupportsComputedStyleMap === undefined) { + cachedSupportsComputedStyleMap = 'computedStyleMap' in element; + } + return cachedSupportsComputedStyleMap; +} + +function getAnimationNameFromComputedStyles(element: HTMLElement) { + if (supportsComputedStyleMap(element)) { + const styleMap = element.computedStyleMap(); + const animationName = styleMap.get('animation-name'); + return (animationName as CSSKeywordValue)?.value ?? undefined; + } + const containerWindow = ownerWindow(element); - return containerWindow.getComputedStyle(element); + const computedStyles = containerWindow.getComputedStyle(element); + return computedStyles.animationName; } let cachedSupportsHiddenUntilFound: boolean | undefined; @@ -80,9 +96,9 @@ export function useCollapsibleContent( contentElementRef.current = element; - const computedStyles = getComputedStyles(element); + const computedAnimationName = getAnimationNameFromComputedStyles(element); - latestAnimationNameRef.current = computedStyles.animationName ?? 'none'; + latestAnimationNameRef.current = computedAnimationName ?? 'none'; originalTransitionDurationStyleRef.current = element.style.transitionDuration; }); From 0b5458f664cd2e3cac60b7fbe0c1b926f38c9b65 Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Wed, 16 Oct 2024 17:40:22 +0800 Subject: [PATCH 27/37] Rename Collapsible.Content to Panel --- docs/app/experiments/accordion.module.css | 6 +- docs/app/experiments/collapsible-framer.tsx | 8 +-- .../collapsible-hidden-until-found.tsx | 16 ++--- docs/app/experiments/collapsible.module.css | 24 +++---- docs/data/api/collapsible-panel.json | 20 ++++++ docs/data/components/accordion/accordion.mdx | 8 +-- .../collapsible/CssAnimatedCollapsible.js | 6 +- .../collapsible/CssAnimatedCollapsible.tsx | 6 +- .../collapsible/CssTransitionCollapsible.js | 6 +- .../collapsible/CssTransitionCollapsible.tsx | 6 +- .../UnstyledCollapsibleIntroduction.js | 4 +- .../UnstyledCollapsibleIntroduction.tsx | 4 +- .../collapsible/animations.module.css | 8 +-- .../components/collapsible/collapsible.mdx | 26 ++++---- .../components/collapsible/styles.module.css | 4 +- .../collapsible/transitions.module.css | 8 +-- .../collapsible-panel.json} | 0 docs/src/components/demo/Demo.module.css | 4 +- docs/src/components/demo/Demo.tsx | 4 +- .../Accordion/Header/AccordionHeader.test.tsx | 4 +- .../Accordion/Panel/AccordionPanel.test.tsx | 4 +- .../src/Accordion/Panel/AccordionPanel.tsx | 16 ++--- .../Trigger/AccordionTrigger.test.tsx | 4 +- .../Accordion/Trigger/AccordionTrigger.tsx | 4 +- .../CollapsiblePanel.test.tsx} | 8 +-- .../CollapsiblePanel.tsx} | 28 ++++---- .../useCollapsiblePanel.ts} | 40 +++++------ .../Collapsible/Root/CollapsibleRoot.test.tsx | 66 +++++++++---------- .../Collapsible/Root/useCollapsibleRoot.ts | 22 ++----- .../Trigger/CollapsibleTrigger.test.tsx | 4 +- .../Trigger/CollapsibleTrigger.tsx | 4 +- .../Trigger/useCollapsibleTrigger.ts | 8 +-- .../mui-base/src/Collapsible/index.parts.ts | 2 +- 33 files changed, 196 insertions(+), 186 deletions(-) create mode 100644 docs/data/api/collapsible-panel.json rename docs/data/translations/api-docs/{collapsible-content/collapsible-content.json => collapsible-panel/collapsible-panel.json} (100%) rename packages/mui-base/src/Collapsible/{Content/CollapsibleContent.test.tsx => Panel/CollapsiblePanel.test.tsx} (86%) rename packages/mui-base/src/Collapsible/{Content/CollapsibleContent.tsx => Panel/CollapsiblePanel.tsx} (74%) rename packages/mui-base/src/Collapsible/{Content/useCollapsibleContent.ts => Panel/useCollapsiblePanel.ts} (90%) diff --git a/docs/app/experiments/accordion.module.css b/docs/app/experiments/accordion.module.css index 4500044e2..8dd426a24 100644 --- a/docs/app/experiments/accordion.module.css +++ b/docs/app/experiments/accordion.module.css @@ -3,13 +3,13 @@ height: 0; } to { - height: var(--accordion-content-height); + height: var(--accordion-panel-height); } } @keyframes slideUp { from { - height: var(--accordion-content-height); + height: var(--accordion-panel-height); } to { height: 0; @@ -110,7 +110,7 @@ } .panel.csstransition[data-accordion='open'] { - height: var(--accordion-content-height); + height: var(--accordion-panel-height); transition: height var(--duration) ease-out; } diff --git a/docs/app/experiments/collapsible-framer.tsx b/docs/app/experiments/collapsible-framer.tsx index f5edefa96..c3b68da96 100644 --- a/docs/app/experiments/collapsible-framer.tsx +++ b/docs/app/experiments/collapsible-framer.tsx @@ -17,11 +17,11 @@ export default function CollapsibleFramer() { Trigger -

demo: https://codepen.io/aardrian/pen/QWjBNQG

https://adrianroselli.com/2020/05/disclosure-widgets.html

-
+
); diff --git a/docs/app/experiments/collapsible-hidden-until-found.tsx b/docs/app/experiments/collapsible-hidden-until-found.tsx index 79d87ed7f..558277c63 100644 --- a/docs/app/experiments/collapsible-hidden-until-found.tsx +++ b/docs/app/experiments/collapsible-hidden-until-found.tsx @@ -34,10 +34,10 @@ export default function CollapsibleHiddenUntilFound() { Trigger 1 - +

This is the collapsed content

May the force be with you

-
+ @@ -45,13 +45,13 @@ export default function CollapsibleHiddenUntilFound() { Trigger 2 -

This is the collapsed content

May the force be with you

-
+
@@ -59,13 +59,13 @@ export default function CollapsibleHiddenUntilFound() { Trigger 3 -

This is the collapsed content

May the force be with you

-
+
diff --git a/docs/app/experiments/collapsible.module.css b/docs/app/experiments/collapsible.module.css index 3b6c3c47c..45cd699dd 100644 --- a/docs/app/experiments/collapsible.module.css +++ b/docs/app/experiments/collapsible.module.css @@ -38,7 +38,7 @@ transition: transform var(--duration) ease-out; } -.content { +.panel { background-color: #eaeaea; overflow: hidden; box-sizing: border-box; @@ -47,38 +47,38 @@ padding-right: 1rem; } -.content.animation[data-collapsible='open'] { +.panel.animation[data-collapsible='open'] { animation: slideDown var(--duration) ease-out; } -.content.animation[data-collapsible='closed'] { +.panel.animation[data-collapsible='closed'] { animation: slideUp var(--duration) ease-in; } -.content.transition[data-collapsible='open'] { - height: var(--collapsible-content-height); +.panel.transition[data-collapsible='open'] { + height: var(--collapsible-panel-height); transition: height var(--duration) ease-out; } -.content.transition[data-collapsible='closed'] { +.panel.transition[data-collapsible='closed'] { height: 0; transition: height var(--duration) ease-in; } -.content.transition[data-entering] { +.panel.transition[data-entering] { height: 0; } -.content.transition[hidden='until-found'] { +.panel.transition[hidden='until-found'] { transition-duration: 0s !important; } -.content.framer { +.panel.framer { display: flex; flex-direction: column; } -.content p { +.panel p { margin: 1.25rem auto; overflow-wrap: break-word; } @@ -88,13 +88,13 @@ height: 0; } to { - height: var(--collapsible-content-height); + height: var(--collapsible-panel-height); } } @keyframes slideUp { from { - height: var(--collapsible-content-height); + height: var(--collapsible-panel-height); } to { height: 0; diff --git a/docs/data/api/collapsible-panel.json b/docs/data/api/collapsible-panel.json new file mode 100644 index 000000000..35c82f11f --- /dev/null +++ b/docs/data/api/collapsible-panel.json @@ -0,0 +1,20 @@ +{ + "props": { + "className": { "type": { "name": "union", "description": "func
| string" } }, + "hiddenUntilFound": { "type": { "name": "bool" }, "default": "false" }, + "render": { "type": { "name": "union", "description": "element
| func" } } + }, + "name": "CollapsiblePanel", + "imports": [ + "import { Collapsible } from '@base_ui/react/Collapsible';\nconst CollapsiblePanel = Collapsible.Panel;" + ], + "classes": [], + "spread": true, + "themeDefaultProps": true, + "muiName": "CollapsiblePanel", + "forwardsRefTo": "HTMLDivElement", + "filename": "/packages/mui-base/src/Collapsible/Panel/CollapsiblePanel.tsx", + "inheritance": null, + "demos": "", + "cssComponent": false +} diff --git a/docs/data/components/accordion/accordion.mdx b/docs/data/components/accordion/accordion.mdx index 1f2046e5b..e96ca5b71 100644 --- a/docs/data/components/accordion/accordion.mdx +++ b/docs/data/components/accordion/accordion.mdx @@ -221,7 +221,7 @@ The component can be animate when opening or closing using either: - CSS transitions - JavaScript animations -The dimensions of the `Accordion.Panel` subcomponent are provided as the `--accordion-content-height` and `--accordion-content-width` CSS variables. +The dimensions of the `Accordion.Panel` subcomponent are provided as the `--accordion-panel-height` and `--accordion-panel-width` CSS variables. ### CSS Animations @@ -245,13 +245,13 @@ CSS animations can be used with two declarations: height: 0; } to { - height: var(--accordion-content-height); + height: var(--accordion-panel-height); } } @keyframes slideUp { from { - height: var(--accordion-content-height); + height: var(--accordion-panel-height); } to { height: 0; @@ -273,7 +273,7 @@ When using CSS transitions, styles for the `Panel` must be applied to three stat } .Accordion-panel[data-collapsible='open'] { - height: var(--accordion-content-height); + height: var(--accordion-panel-height); transition: height 300ms ease-out; } diff --git a/docs/data/components/collapsible/CssAnimatedCollapsible.js b/docs/data/components/collapsible/CssAnimatedCollapsible.js index c0093d1ed..28e91f936 100644 --- a/docs/data/components/collapsible/CssAnimatedCollapsible.js +++ b/docs/data/components/collapsible/CssAnimatedCollapsible.js @@ -16,8 +16,8 @@ export default function CssAnimatedCollapsible() { Show {open ? 'less' : 'more'} -

This is the collapsed content

@@ -31,7 +31,7 @@ export default function CssAnimatedCollapsible() {

This is a longer sentence and also the third paragraph

-
+ ); } diff --git a/docs/data/components/collapsible/CssAnimatedCollapsible.tsx b/docs/data/components/collapsible/CssAnimatedCollapsible.tsx index f9de682fd..2342c7930 100644 --- a/docs/data/components/collapsible/CssAnimatedCollapsible.tsx +++ b/docs/data/components/collapsible/CssAnimatedCollapsible.tsx @@ -16,8 +16,8 @@ export default function CssAnimatedCollapsible() { Show {open ? 'less' : 'more'} -

This is the collapsed content

@@ -31,7 +31,7 @@ export default function CssAnimatedCollapsible() {

This is a longer sentence and also the third paragraph

-
+ ); } diff --git a/docs/data/components/collapsible/CssTransitionCollapsible.js b/docs/data/components/collapsible/CssTransitionCollapsible.js index 12e5541d7..4d1d7d51e 100644 --- a/docs/data/components/collapsible/CssTransitionCollapsible.js +++ b/docs/data/components/collapsible/CssTransitionCollapsible.js @@ -16,8 +16,8 @@ export default function CssTransitionCollapsible() { Show {open ? 'less' : 'more'} -

This is the collapsed content.

@@ -32,7 +32,7 @@ export default function CssTransitionCollapsible() { .

This is a longer sentence and also the third paragraph.

-
+ ); } diff --git a/docs/data/components/collapsible/CssTransitionCollapsible.tsx b/docs/data/components/collapsible/CssTransitionCollapsible.tsx index d7879af76..0800f0b47 100644 --- a/docs/data/components/collapsible/CssTransitionCollapsible.tsx +++ b/docs/data/components/collapsible/CssTransitionCollapsible.tsx @@ -16,8 +16,8 @@ export default function CssTransitionCollapsible() { Show {open ? 'less' : 'more'} -

This is the collapsed content.

@@ -32,7 +32,7 @@ export default function CssTransitionCollapsible() { .

This is a longer sentence and also the third paragraph.

-
+ ); } diff --git a/docs/data/components/collapsible/UnstyledCollapsibleIntroduction.js b/docs/data/components/collapsible/UnstyledCollapsibleIntroduction.js index 2c23d4a9f..f880388d3 100644 --- a/docs/data/components/collapsible/UnstyledCollapsibleIntroduction.js +++ b/docs/data/components/collapsible/UnstyledCollapsibleIntroduction.js @@ -11,7 +11,7 @@ export default function UnstyledCollapsibleIntroduction() { Show {open ? 'less' : 'more'} - +

This is the collapsed content. The element that shows and hides the content has role button @@ -21,7 +21,7 @@ export default function UnstyledCollapsibleIntroduction() { `aria-expanded` set to `true`

When the content panel is hidden, it is set to `false`

-
+ ); } diff --git a/docs/data/components/collapsible/UnstyledCollapsibleIntroduction.tsx b/docs/data/components/collapsible/UnstyledCollapsibleIntroduction.tsx index bc2d2281f..738789210 100644 --- a/docs/data/components/collapsible/UnstyledCollapsibleIntroduction.tsx +++ b/docs/data/components/collapsible/UnstyledCollapsibleIntroduction.tsx @@ -11,7 +11,7 @@ export default function UnstyledCollapsibleIntroduction() { Show {open ? 'less' : 'more'} - +

This is the collapsed content. The element that shows and hides the content has role button @@ -21,7 +21,7 @@ export default function UnstyledCollapsibleIntroduction() { `aria-expanded` set to `true`

When the content panel is hidden, it is set to `false`

-
+ ); } diff --git a/docs/data/components/collapsible/animations.module.css b/docs/data/components/collapsible/animations.module.css index 93483d34c..e045caf48 100644 --- a/docs/data/components/collapsible/animations.module.css +++ b/docs/data/components/collapsible/animations.module.css @@ -3,23 +3,23 @@ height: 0; } to { - height: var(--collapsible-content-height); + height: var(--collapsible-panel-height); } } @keyframes slideUp { from { - height: var(--collapsible-content-height); + height: var(--collapsible-panel-height); } to { height: 0; } } -.content[data-collapsible='open'] { +.panel[data-collapsible='open'] { animation: slideDown 300ms ease-out; } -.content[data-collapsible='closed'] { +.panel[data-collapsible='closed'] { animation: slideUp 300ms ease-out; } diff --git a/docs/data/components/collapsible/collapsible.mdx b/docs/data/components/collapsible/collapsible.mdx index 5efe2b491..2405fc59b 100644 --- a/docs/data/components/collapsible/collapsible.mdx +++ b/docs/data/components/collapsible/collapsible.mdx @@ -2,7 +2,7 @@ productId: base-ui title: React Collapsible components description: Collapsible is a component that shows or hides content. -components: CollapsibleRoot, CollapsibleTrigger, CollapsibleContent +components: CollapsibleRoot, CollapsibleTrigger, CollapsiblePanel githubLabel: 'component: collapsible' waiAria: https://www.w3.org/WAI/ARIA/apg/patterns/disclosure/ packageName: '@base_ui/react' @@ -24,12 +24,12 @@ packageName: '@base_ui/react' - `` is a top-level component that facilitates communication between other components. It does not render to the DOM by default. - `` is the trigger element, a `
- +
-
+
); diff --git a/packages/mui-base/src/Accordion/Header/AccordionHeader.test.tsx b/packages/mui-base/src/Accordion/Header/AccordionHeader.test.tsx index a1876c855..7243b46d7 100644 --- a/packages/mui-base/src/Accordion/Header/AccordionHeader.test.tsx +++ b/packages/mui-base/src/Accordion/Header/AccordionHeader.test.tsx @@ -38,11 +38,11 @@ const accordionItemContextValue: AccordionItemContext = { const collapsibleContextValue: CollapsibleRootContext = { animated: false, - contentId: ':content:', + panelId: ':panel:', disabled: false, mounted: true, open: true, - setContentId: NOOP, + setPanelId: NOOP, setMounted: NOOP, setOpen: NOOP, transitionStatus: undefined, diff --git a/packages/mui-base/src/Accordion/Panel/AccordionPanel.test.tsx b/packages/mui-base/src/Accordion/Panel/AccordionPanel.test.tsx index e623bd7b1..c6da33561 100644 --- a/packages/mui-base/src/Accordion/Panel/AccordionPanel.test.tsx +++ b/packages/mui-base/src/Accordion/Panel/AccordionPanel.test.tsx @@ -38,11 +38,11 @@ const accordionItemContextValue: AccordionItemContext = { const collapsibleContextValue: CollapsibleRootContext = { animated: false, - contentId: ':content:', + panelId: ':panel:', disabled: false, mounted: true, open: true, - setContentId: NOOP, + setPanelId: NOOP, setMounted: NOOP, setOpen: NOOP, transitionStatus: undefined, diff --git a/packages/mui-base/src/Accordion/Panel/AccordionPanel.tsx b/packages/mui-base/src/Accordion/Panel/AccordionPanel.tsx index 525b3d08e..a9ef3ffa8 100644 --- a/packages/mui-base/src/Accordion/Panel/AccordionPanel.tsx +++ b/packages/mui-base/src/Accordion/Panel/AccordionPanel.tsx @@ -4,7 +4,7 @@ import PropTypes from 'prop-types'; import { BaseUIComponentProps } from '../../utils/types'; import { useComponentRenderer } from '../../utils/useComponentRenderer'; import { useCollapsibleRootContext } from '../../Collapsible/Root/CollapsibleRootContext'; -import { useCollapsibleContent } from '../../Collapsible/Content/useCollapsibleContent'; +import { useCollapsiblePanel } from '../../Collapsible/Panel/useCollapsiblePanel'; import { useAccordionRootContext } from '../Root/AccordionRootContext'; import type { AccordionItem } from '../Item/AccordionItem'; import { useAccordionItemContext } from '../Item/AccordionItemContext'; @@ -33,19 +33,19 @@ const AccordionPanel = React.forwardRef(function AccordionPanel( ...otherProps } = props; - const { animated, mounted, open, contentId, setContentId, setMounted, setOpen } = + const { animated, mounted, open, panelId, setPanelId, setMounted, setOpen } = useCollapsibleRootContext(); const { hiddenUntilFound } = useAccordionRootContext(); - const { getRootProps, height, width } = useCollapsibleContent({ + const { getRootProps, height, width } = useCollapsiblePanel({ animated, hiddenUntilFound: hiddenUntilFoundProp || hiddenUntilFound, - id: idProp ?? contentId, + id: idProp ?? panelId, mounted, open, ref: forwardedRef, - setContentId, + setPanelId, setMounted, setOpen, }); @@ -62,8 +62,8 @@ const AccordionPanel = React.forwardRef(function AccordionPanel( 'aria-labelledby': triggerId, role: 'region', style: { - '--accordion-content-height': height ? `${height}px` : undefined, - '--accordion-content-width': width ? `${width}px` : undefined, + '--accordion-panel-height': height ? `${height}px` : undefined, + '--accordion-panel-width': width ? `${width}px` : undefined, ...styleProp, }, }, @@ -76,7 +76,7 @@ const AccordionPanel = React.forwardRef(function AccordionPanel( export namespace AccordionPanel { export interface Props extends BaseUIComponentProps<'div', AccordionItem.OwnerState>, - Pick {} + Pick {} } export { AccordionPanel }; diff --git a/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.test.tsx b/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.test.tsx index 25e84af30..e1655d628 100644 --- a/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.test.tsx +++ b/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.test.tsx @@ -38,11 +38,11 @@ const accordionItemContextValue: AccordionItemContext = { const collapsibleContextValue: CollapsibleRootContext = { animated: false, - contentId: ':content:', + panelId: ':panel:', disabled: false, mounted: true, open: true, - setContentId: NOOP, + setPanelId: NOOP, setMounted: NOOP, setOpen: NOOP, transitionStatus: undefined, diff --git a/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.tsx b/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.tsx index e3b881a7b..10927551e 100644 --- a/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.tsx +++ b/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.tsx @@ -26,10 +26,10 @@ const AccordionTrigger = React.forwardRef(function AccordionTrigger( ) { const { disabled: disabledProp, className, id, render, ...otherProps } = props; - const { contentId, disabled: contextDisabled, open, setOpen } = useCollapsibleRootContext(); + const { panelId, disabled: contextDisabled, open, setOpen } = useCollapsibleRootContext(); const { getRootProps } = useCollapsibleTrigger({ - contentId, + panelId, disabled: disabledProp || contextDisabled, id, open, diff --git a/packages/mui-base/src/Collapsible/Content/CollapsibleContent.test.tsx b/packages/mui-base/src/Collapsible/Panel/CollapsiblePanel.test.tsx similarity index 86% rename from packages/mui-base/src/Collapsible/Content/CollapsibleContent.test.tsx rename to packages/mui-base/src/Collapsible/Panel/CollapsiblePanel.test.tsx index c570646eb..9302b381f 100644 --- a/packages/mui-base/src/Collapsible/Content/CollapsibleContent.test.tsx +++ b/packages/mui-base/src/Collapsible/Panel/CollapsiblePanel.test.tsx @@ -6,11 +6,11 @@ import { describeConformance } from '../../../test/describeConformance'; const contextValue: CollapsibleRootContext = { animated: false, - contentId: 'ContentId', + panelId: 'PanelId', disabled: false, mounted: true, open: true, - setContentId() {}, + setPanelId() {}, setMounted() {}, setOpen() {}, transitionStatus: undefined, @@ -21,10 +21,10 @@ const contextValue: CollapsibleRootContext = { }, }; -describe('', () => { +describe('', () => { const { render } = createRenderer(); - describeConformance(, () => ({ + describeConformance(, () => ({ inheritComponent: 'div', render: (node) => { const { container, ...other } = render( diff --git a/packages/mui-base/src/Collapsible/Content/CollapsibleContent.tsx b/packages/mui-base/src/Collapsible/Panel/CollapsiblePanel.tsx similarity index 74% rename from packages/mui-base/src/Collapsible/Content/CollapsibleContent.tsx rename to packages/mui-base/src/Collapsible/Panel/CollapsiblePanel.tsx index b62e2db64..4d7a0f7be 100644 --- a/packages/mui-base/src/Collapsible/Content/CollapsibleContent.tsx +++ b/packages/mui-base/src/Collapsible/Panel/CollapsiblePanel.tsx @@ -6,7 +6,7 @@ import { useComponentRenderer } from '../../utils/useComponentRenderer'; import { useCollapsibleRootContext } from '../Root/CollapsibleRootContext'; import type { CollapsibleRoot } from '../Root/CollapsibleRoot'; import { collapsibleStyleHookMapping } from '../Root/styleHooks'; -import { useCollapsibleContent } from './useCollapsibleContent'; +import { useCollapsiblePanel } from './useCollapsiblePanel'; /** * @@ -16,25 +16,25 @@ import { useCollapsibleContent } from './useCollapsibleContent'; * * API: * - * - [CollapsibleContent API](https://base-ui.netlify.app/components/react-collapsible/#api-reference-CollapsibleContent) + * - [CollapsiblePanel API](https://base-ui.netlify.app/components/react-collapsible/#api-reference-CollapsiblePanel) */ -const CollapsibleContent = React.forwardRef(function CollapsibleContent( - props: CollapsibleContent.Props, +const CollapsiblePanel = React.forwardRef(function CollapsiblePanel( + props: CollapsiblePanel.Props, forwardedRef: React.ForwardedRef, ) { const { className, hiddenUntilFound, render, ...otherProps } = props; - const { animated, mounted, open, contentId, setContentId, setMounted, setOpen, ownerState } = + const { animated, mounted, open, panelId, setPanelId, setMounted, setOpen, ownerState } = useCollapsibleRootContext(); - const { getRootProps, height, width } = useCollapsibleContent({ + const { getRootProps, height, width } = useCollapsiblePanel({ animated, hiddenUntilFound, - id: contentId, + id: panelId, mounted, open, ref: forwardedRef, - setContentId, + setPanelId, setMounted, setOpen, }); @@ -48,8 +48,8 @@ const CollapsibleContent = React.forwardRef(function CollapsibleContent( ...otherProps, style: { ...otherProps.style, - '--collapsible-content-height': height ? `${height}px` : undefined, - '--collapsible-content-width': width ? `${width}px` : undefined, + '--collapsible-panel-height': height ? `${height}px` : undefined, + '--collapsible-panel-width': width ? `${width}px` : undefined, }, }, customStyleHookMapping: collapsibleStyleHookMapping, @@ -58,15 +58,15 @@ const CollapsibleContent = React.forwardRef(function CollapsibleContent( return renderElement(); }); -export { CollapsibleContent }; +export { CollapsiblePanel }; -namespace CollapsibleContent { +namespace CollapsiblePanel { export interface Props extends BaseUIComponentProps<'div', CollapsibleRoot.OwnerState>, - Pick {} + Pick {} } -CollapsibleContent.propTypes /* remove-proptypes */ = { +CollapsiblePanel.propTypes /* remove-proptypes */ = { // ┌────────────────────────────── Warning ──────────────────────────────┐ // │ These PropTypes are generated from the TypeScript type definitions. │ // │ To update them, edit the TypeScript types and run `pnpm proptypes`. │ diff --git a/packages/mui-base/src/Collapsible/Content/useCollapsibleContent.ts b/packages/mui-base/src/Collapsible/Panel/useCollapsiblePanel.ts similarity index 90% rename from packages/mui-base/src/Collapsible/Content/useCollapsibleContent.ts rename to packages/mui-base/src/Collapsible/Panel/useCollapsiblePanel.ts index d1e78d67c..7b7f1946b 100644 --- a/packages/mui-base/src/Collapsible/Content/useCollapsibleContent.ts +++ b/packages/mui-base/src/Collapsible/Panel/useCollapsiblePanel.ts @@ -53,9 +53,9 @@ interface Dimensions { width: number; } -export function useCollapsibleContent( - parameters: useCollapsibleContent.Parameters, -): useCollapsibleContent.ReturnValue { +export function useCollapsiblePanel( + parameters: useCollapsiblePanel.Parameters, +): useCollapsiblePanel.ReturnValue { const { animated = false, hiddenUntilFound = false, @@ -63,14 +63,14 @@ export function useCollapsibleContent( open, mounted: contextMounted, ref, - setContentId, + setPanelId, setMounted: setContextMounted, setOpen, } = parameters; const id = useId(idParam); - const contentElementRef = React.useRef(null); + const panelRef = React.useRef(null); const [{ height, width }, setDimensions] = React.useState({ height: 0, @@ -83,18 +83,18 @@ export function useCollapsibleContent( const isTransitioningRef = React.useRef(false); useEnhancedEffect(() => { - setContentId(id); + setPanelId(id); return () => { - setContentId(undefined); + setPanelId(undefined); }; - }, [id, setContentId]); + }, [id, setPanelId]); - const handleContentRef = useEventCallback((element: HTMLElement) => { + const handlePanelRef = useEventCallback((element: HTMLElement) => { if (!element) { return; } - contentElementRef.current = element; + panelRef.current = element; const computedAnimationName = getAnimationNameFromComputedStyles(element); @@ -102,9 +102,9 @@ export function useCollapsibleContent( originalTransitionDurationStyleRef.current = element.style.transitionDuration; }); - const mergedRef = useForkRef(ref, handleContentRef); + const mergedRef = useForkRef(ref, handlePanelRef); - const runOnceAnimationsFinish = useAnimationsFinished(contentElementRef); + const runOnceAnimationsFinish = useAnimationsFinished(panelRef); const isOpen = animated ? open || contextMounted : open; @@ -113,7 +113,7 @@ export function useCollapsibleContent( const isBeforeMatchRef = React.useRef(false); useEnhancedEffect(() => { - const { current: element } = contentElementRef; + const { current: element } = panelRef; let frame1 = -1; let frame2 = -1; @@ -169,7 +169,7 @@ export function useCollapsibleContent( }, [open, contextMounted, runOnceAnimationsFinish, setContextMounted]); React.useEffect(() => { - const { current: element } = contentElementRef; + const { current: element } = panelRef; let frame2 = -1; let frame3 = -1; @@ -195,7 +195,7 @@ export function useCollapsibleContent( }, []); React.useEffect(function registerCssTransitionListeners() { - const { current: element } = contentElementRef; + const { current: element } = panelRef; if (!element) { return undefined; } @@ -227,7 +227,7 @@ export function useCollapsibleContent( // we need to manually sync the open state React.useEffect( function registerBeforeMatchListener() { - const { current: element } = contentElementRef; + const { current: element } = panelRef; if (!element || !supportsHiddenUntilFound(element)) { return undefined; @@ -255,7 +255,7 @@ export function useCollapsibleContent( // so we have to force it back to `'until-found'` in the DOM when applicable // https://github.com/facebook/react/issues/24740 useEnhancedEffect(() => { - const { current: element } = contentElementRef; + const { current: element } = panelRef; if ( element && @@ -271,7 +271,7 @@ export function useCollapsibleContent( const hidden = hiddenUntilFound ? 'until-found' : 'hidden'; - const getRootProps: useCollapsibleContent.ReturnValue['getRootProps'] = React.useCallback( + const getRootProps: useCollapsiblePanel.ReturnValue['getRootProps'] = React.useCallback( (externalProps = {}) => mergeReactProps(externalProps, { id, @@ -291,7 +291,7 @@ export function useCollapsibleContent( ); } -export namespace useCollapsibleContent { +export namespace useCollapsiblePanel { export interface Parameters { /** * If `true`, the component supports CSS/JS-based animations and transitions. @@ -311,7 +311,7 @@ export namespace useCollapsibleContent { */ open: boolean; ref: React.Ref; - setContentId: (id: string | undefined) => void; + setPanelId: (id: string | undefined) => void; setOpen: (nextOpen: boolean) => void; setMounted: (nextMounted: boolean) => void; } diff --git a/packages/mui-base/src/Collapsible/Root/CollapsibleRoot.test.tsx b/packages/mui-base/src/Collapsible/Root/CollapsibleRoot.test.tsx index 770e2a69e..c9d2fe667 100644 --- a/packages/mui-base/src/Collapsible/Root/CollapsibleRoot.test.tsx +++ b/packages/mui-base/src/Collapsible/Root/CollapsibleRoot.test.tsx @@ -22,16 +22,16 @@ describe('', () => { const { getByTestId, getByRole } = await render( - + , ); const trigger = getByRole('button'); - const content = getByTestId('content'); + const panel = getByTestId('panel'); expect(trigger).to.have.attribute('aria-expanded'); - expect(trigger.getAttribute('aria-controls')).to.equal(content.getAttribute('id')); + expect(trigger.getAttribute('aria-controls')).to.equal(panel.getAttribute('id')); }); }); @@ -40,56 +40,56 @@ describe('', () => { const { getByTestId, getByRole, setProps } = await render( - + , ); const trigger = getByRole('button'); - const content = getByTestId('content'); + const panel = getByTestId('panel'); expect(trigger).to.have.attribute('aria-expanded', 'false'); - expect(content).to.have.attribute('hidden'); - expect(content).to.have.attribute('data-collapsible', 'closed'); + expect(panel).to.have.attribute('hidden'); + expect(panel).to.have.attribute('data-collapsible', 'closed'); setProps({ open: true }); expect(trigger).to.have.attribute('aria-expanded', 'true'); - expect(content).to.not.have.attribute('hidden'); - expect(content).to.have.attribute('data-collapsible', 'open'); + expect(panel).to.not.have.attribute('hidden'); + expect(panel).to.have.attribute('data-collapsible', 'open'); setProps({ open: false }); expect(trigger).to.have.attribute('aria-expanded', 'false'); - expect(content).to.have.attribute('data-collapsible', 'closed'); - expect(content).to.have.attribute('hidden'); + expect(panel).to.have.attribute('data-collapsible', 'closed'); + expect(panel).to.have.attribute('hidden'); }); it('uncontrolled mode', async () => { const { getByTestId, getByRole, user } = await render( - + , ); const trigger = getByRole('button'); - const content = getByTestId('content'); + const panel = getByTestId('panel'); expect(trigger).to.have.attribute('aria-expanded', 'false'); - expect(content).to.have.attribute('hidden'); - expect(content).to.have.attribute('data-collapsible', 'closed'); + expect(panel).to.have.attribute('hidden'); + expect(panel).to.have.attribute('data-collapsible', 'closed'); await user.pointer({ keys: '[MouseLeft]', target: trigger }); expect(trigger).to.have.attribute('aria-expanded', 'true'); - expect(content).to.not.have.attribute('hidden'); - expect(content).to.have.attribute('data-collapsible', 'open'); + expect(panel).to.not.have.attribute('hidden'); + expect(panel).to.have.attribute('data-collapsible', 'open'); await user.pointer({ keys: '[MouseLeft]', target: trigger }); expect(trigger).to.have.attribute('aria-expanded', 'false'); - expect(content).to.have.attribute('data-collapsible', 'closed'); - expect(content).to.have.attribute('hidden'); + expect(panel).to.have.attribute('data-collapsible', 'closed'); + expect(panel).to.have.attribute('hidden'); }); }); @@ -99,36 +99,36 @@ describe('', () => { const { getByTestId, getByRole, user } = await render( Trigger - + , ); const trigger = getByRole('button'); - const content = getByTestId('content'); + const panel = getByTestId('panel'); expect(trigger).to.have.attribute('aria-expanded', 'false'); - expect(content).to.have.attribute('hidden'); - expect(content).to.have.attribute('data-collapsible', 'closed'); + expect(panel).to.have.attribute('hidden'); + expect(panel).to.have.attribute('data-collapsible', 'closed'); await user.keyboard('[Tab]'); expect(trigger).toHaveFocus(); await user.keyboard(`[${key}]`); expect(trigger).to.have.attribute('aria-expanded', 'true'); - expect(content).to.not.have.attribute('hidden'); - expect(content).to.have.attribute('data-collapsible', 'open'); + expect(panel).to.not.have.attribute('hidden'); + expect(panel).to.have.attribute('data-collapsible', 'open'); await user.keyboard(`[${key}]`); expect(trigger).to.have.attribute('aria-expanded', 'false'); - expect(content).to.have.attribute('data-collapsible', 'closed'); - expect(content).to.have.attribute('hidden'); + expect(panel).to.have.attribute('data-collapsible', 'closed'); + expect(panel).to.have.attribute('hidden'); }); }); }); describe('prop: hiddenUntilFound', () => { - it('uses `hidden="until-found" to hide content when true', async function test() { + it('uses `hidden="until-found" to hide panel when true', async function test() { // we test firefox in browserstack which does not support this yet if (!('onbeforematch' in window)) { this.skip(); @@ -139,24 +139,24 @@ describe('', () => { const { getByTestId } = await render( - + , ); - const content = getByTestId('content'); + const panel = getByTestId('panel'); - expect(content).to.have.attribute('data-collapsible', 'closed'); + expect(panel).to.have.attribute('data-collapsible', 'closed'); act(() => { const event = new window.Event('beforematch', { bubbles: true, cancelable: false, }); - content.dispatchEvent(event); + panel.dispatchEvent(event); }); expect(handleOpenChange.callCount).to.equal(1); - expect(content).to.have.attribute('data-collapsible', 'open'); + expect(panel).to.have.attribute('data-collapsible', 'open'); }); }); }); diff --git a/packages/mui-base/src/Collapsible/Root/useCollapsibleRoot.ts b/packages/mui-base/src/Collapsible/Root/useCollapsibleRoot.ts index 3467b1e12..d40e21d10 100644 --- a/packages/mui-base/src/Collapsible/Root/useCollapsibleRoot.ts +++ b/packages/mui-base/src/Collapsible/Root/useCollapsibleRoot.ts @@ -25,7 +25,7 @@ export function useCollapsibleRoot( const { mounted, setMounted, transitionStatus } = useTransitionStatus(open, animated); - const [contentId, setContentId] = React.useState(useId()); + const [panelId, setPanelId] = React.useState(useId()); const setOpen = useEventCallback((nextOpen: boolean) => { onOpenChange?.(nextOpen); @@ -35,26 +35,16 @@ export function useCollapsibleRoot( return React.useMemo( () => ({ animated, - contentId, + panelId, disabled, mounted, open, - setContentId, + setPanelId, setMounted, setOpen, transitionStatus, }), - [ - animated, - contentId, - disabled, - mounted, - open, - setContentId, - setMounted, - setOpen, - transitionStatus, - ], + [animated, panelId, disabled, mounted, open, setPanelId, setMounted, setOpen, transitionStatus], ); } @@ -89,7 +79,7 @@ export namespace useCollapsibleRoot { export interface ReturnValue { animated: boolean; - contentId: React.HTMLAttributes['id']; + panelId: React.HTMLAttributes['id']; /** * The disabled state of the Collapsible */ @@ -99,7 +89,7 @@ export namespace useCollapsibleRoot { * The open state of the Collapsible */ open: boolean; - setContentId: (id: string | undefined) => void; + setPanelId: (id: string | undefined) => void; setMounted: (open: boolean) => void; setOpen: (open: boolean) => void; transitionStatus: TransitionStatus; diff --git a/packages/mui-base/src/Collapsible/Trigger/CollapsibleTrigger.test.tsx b/packages/mui-base/src/Collapsible/Trigger/CollapsibleTrigger.test.tsx index 86dc0e675..8f9ed3e74 100644 --- a/packages/mui-base/src/Collapsible/Trigger/CollapsibleTrigger.test.tsx +++ b/packages/mui-base/src/Collapsible/Trigger/CollapsibleTrigger.test.tsx @@ -6,11 +6,11 @@ import { describeConformance } from '../../../test/describeConformance'; const contextValue: CollapsibleRootContext = { animated: false, - contentId: 'ContentId', + panelId: 'PanelId', disabled: false, mounted: true, open: true, - setContentId() {}, + setPanelId() {}, setMounted() {}, setOpen() {}, transitionStatus: undefined, diff --git a/packages/mui-base/src/Collapsible/Trigger/CollapsibleTrigger.tsx b/packages/mui-base/src/Collapsible/Trigger/CollapsibleTrigger.tsx index 0a8f72b99..205f3a5b9 100644 --- a/packages/mui-base/src/Collapsible/Trigger/CollapsibleTrigger.tsx +++ b/packages/mui-base/src/Collapsible/Trigger/CollapsibleTrigger.tsx @@ -24,10 +24,10 @@ const CollapsibleTrigger = React.forwardRef(function CollapsibleTrigger( ) { const { className, render, ...otherProps } = props; - const { contentId, open, setOpen, ownerState } = useCollapsibleRootContext(); + const { panelId, open, setOpen, ownerState } = useCollapsibleRootContext(); const { getRootProps } = useCollapsibleTrigger({ - contentId, + panelId, open, setOpen, rootRef: forwardedRef, diff --git a/packages/mui-base/src/Collapsible/Trigger/useCollapsibleTrigger.ts b/packages/mui-base/src/Collapsible/Trigger/useCollapsibleTrigger.ts index ed445c2a9..c8a75f905 100644 --- a/packages/mui-base/src/Collapsible/Trigger/useCollapsibleTrigger.ts +++ b/packages/mui-base/src/Collapsible/Trigger/useCollapsibleTrigger.ts @@ -8,7 +8,7 @@ import { useButton } from '../../useButton'; export function useCollapsibleTrigger( parameters: useCollapsibleTrigger.Parameters, ): useCollapsibleTrigger.ReturnValue { - const { contentId, disabled, id, open, rootRef: externalRef, setOpen } = parameters; + const { panelId, disabled, id, open, rootRef: externalRef, setOpen } = parameters; const { getButtonProps, buttonRef } = useButton({ disabled, @@ -25,7 +25,7 @@ export function useCollapsibleTrigger( mergeReactProps( { type: 'button', - 'aria-controls': contentId, + 'aria-controls': panelId, 'aria-expanded': open, disabled, id, @@ -37,7 +37,7 @@ export function useCollapsibleTrigger( getButtonProps(), ), ), - [contentId, disabled, getButtonProps, handleRef, id, open, setOpen], + [panelId, disabled, getButtonProps, handleRef, id, open, setOpen], ); return { @@ -50,7 +50,7 @@ export namespace useCollapsibleTrigger { /** * The id of the element controlled by the Trigger */ - contentId: React.HTMLAttributes['id']; + panelId: React.HTMLAttributes['id']; disabled?: boolean; id?: React.HTMLAttributes['id']; /** diff --git a/packages/mui-base/src/Collapsible/index.parts.ts b/packages/mui-base/src/Collapsible/index.parts.ts index 3736ae4de..91b27a729 100644 --- a/packages/mui-base/src/Collapsible/index.parts.ts +++ b/packages/mui-base/src/Collapsible/index.parts.ts @@ -1,3 +1,3 @@ export { CollapsibleRoot as Root } from './Root/CollapsibleRoot'; export { CollapsibleTrigger as Trigger } from './Trigger/CollapsibleTrigger'; -export { CollapsibleContent as Content } from './Content/CollapsibleContent'; +export { CollapsiblePanel as Panel } from './Panel/CollapsiblePanel'; From 7ad7ce1549972eb586683ed5ef9abcebfb699c4f Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Wed, 16 Oct 2024 22:15:37 +0800 Subject: [PATCH 28/37] Update style hooks --- .../accordion.horizontal.module.css | 6 +- docs/app/experiments/accordion.module.css | 14 ++-- docs/app/experiments/collapsible.module.css | 14 ++-- .../components/accordion/styles.module.css | 6 +- .../collapsible/animations.module.css | 4 +- .../components/collapsible/styles.module.css | 2 +- .../collapsible/transitions.module.css | 4 +- docs/src/components/demo/Demo.module.css | 7 +- .../mui-base/src/Accordion/Item/styleHooks.ts | 5 +- .../src/Accordion/Root/AccordionRoot.test.tsx | 72 ++++++++----------- .../Accordion/Trigger/AccordionTrigger.tsx | 5 +- .../Collapsible/Root/CollapsibleRoot.test.tsx | 18 ++--- .../src/Collapsible/Root/styleHooks.ts | 5 +- .../Trigger/CollapsibleTrigger.tsx | 4 +- .../src/utils/collapsibleOpenStateMapping.ts | 23 ++++++ 15 files changed, 91 insertions(+), 98 deletions(-) create mode 100644 packages/mui-base/src/utils/collapsibleOpenStateMapping.ts diff --git a/docs/app/experiments/accordion.horizontal.module.css b/docs/app/experiments/accordion.horizontal.module.css index 289680d10..14e57904f 100644 --- a/docs/app/experiments/accordion.horizontal.module.css +++ b/docs/app/experiments/accordion.horizontal.module.css @@ -7,11 +7,11 @@ } .root { - --Paper-shadow: 0px 2px 1px -1px rgba(0, 0, 0, 0.2), 0px 1px 1px 0px rgba(0, 0, 0, 0.14), + --shadow: 0px 2px 1px -1px rgba(0, 0, 0, 0.2), 0px 1px 1px 0px rgba(0, 0, 0, 0.14), 0px 1px 3px 0px rgba(0, 0, 0, 0.12); font-family: system-ui, sans-serif; - box-shadow: var(--Paper-shadow); + box-shadow: var(--shadow); background-color: rgba(0, 0, 0, 0.12); border-radius: 0.3rem; height: 40rem; @@ -90,7 +90,7 @@ transform: rotate(-90deg); } -.trigger[data-accordion='open'] svg { +.trigger[data-panel-open] svg { transform: rotate(180deg); } diff --git a/docs/app/experiments/accordion.module.css b/docs/app/experiments/accordion.module.css index 8dd426a24..6dd3aa695 100644 --- a/docs/app/experiments/accordion.module.css +++ b/docs/app/experiments/accordion.module.css @@ -26,11 +26,11 @@ .root { --duration: 300ms; - --Paper-shadow: 0px 2px 1px -1px rgba(0, 0, 0, 0.2), 0px 1px 1px 0px rgba(0, 0, 0, 0.14), + --shadow: 0px 2px 1px -1px rgba(0, 0, 0, 0.2), 0px 1px 1px 0px rgba(0, 0, 0, 0.14), 0px 1px 3px 0px rgba(0, 0, 0, 0.12); font-family: system-ui, sans-serif; - box-shadow: var(--Paper-shadow); + box-shadow: var(--shadow); background-color: rgba(0, 0, 0, 0.12); border-radius: 0.3rem; } @@ -88,7 +88,7 @@ transition: transform 300ms; } -.trigger[data-accordion='open'] svg { +.trigger[data-panel-open] svg { transform: rotate(180deg); } @@ -101,20 +101,20 @@ padding: 1rem; } -.panel.cssanimation[data-accordion='open'] { +.panel.cssanimation[data-open] { animation: slideDown var(--duration) ease-out; } -.panel.cssanimation[data-accordion='closed'] { +.panel.cssanimation { animation: slideUp var(--duration) ease-out; } -.panel.csstransition[data-accordion='open'] { +.panel.csstransition[data-open] { height: var(--accordion-panel-height); transition: height var(--duration) ease-out; } -.panel.csstransition[data-accordion='closed'] { +.panel.csstransition { height: 0; transition: height var(--duration) ease-in; } diff --git a/docs/app/experiments/collapsible.module.css b/docs/app/experiments/collapsible.module.css index 45cd699dd..d4e2bfd0e 100644 --- a/docs/app/experiments/collapsible.module.css +++ b/docs/app/experiments/collapsible.module.css @@ -33,7 +33,7 @@ transition: transform var(--duration) ease-in; } -.trigger[data-collapsible='open'] .icon { +.trigger[data-open] .icon { transform: rotate(0); transition: transform var(--duration) ease-out; } @@ -47,20 +47,20 @@ padding-right: 1rem; } -.panel.animation[data-collapsible='open'] { +.panel.animation[data-open] { animation: slideDown var(--duration) ease-out; } -.panel.animation[data-collapsible='closed'] { +.panel.animation { animation: slideUp var(--duration) ease-in; } -.panel.transition[data-collapsible='open'] { +.panel.transition[data-open] { height: var(--collapsible-panel-height); transition: height var(--duration) ease-out; } -.panel.transition[data-collapsible='closed'] { +.panel.transition { height: 0; transition: height var(--duration) ease-in; } @@ -69,10 +69,6 @@ height: 0; } -.panel.transition[hidden='until-found'] { - transition-duration: 0s !important; -} - .panel.framer { display: flex; flex-direction: column; diff --git a/docs/data/components/accordion/styles.module.css b/docs/data/components/accordion/styles.module.css index 58a901b41..cfa2e8f3a 100644 --- a/docs/data/components/accordion/styles.module.css +++ b/docs/data/components/accordion/styles.module.css @@ -4,11 +4,11 @@ } .root { - --Paper-shadow: 0px 2px 1px -1px rgba(0, 0, 0, 0.2), 0px 1px 1px 0px rgba(0, 0, 0, 0.14), + --shadow: 0px 2px 1px -1px rgba(0, 0, 0, 0.2), 0px 1px 1px 0px rgba(0, 0, 0, 0.14), 0px 1px 3px 0px rgba(0, 0, 0, 0.12); font-family: system-ui, sans-serif; - box-shadow: var(--Paper-shadow); + box-shadow: var(--shadow); background-color: rgba(0, 0, 0, 0.12); border-radius: 0.3rem; } @@ -72,7 +72,7 @@ margin: 12px auto 12px 0; } -.trigger[data-accordion='open'] svg { +.trigger[data-open] svg { transform: rotate(180deg); } diff --git a/docs/data/components/collapsible/animations.module.css b/docs/data/components/collapsible/animations.module.css index e045caf48..229159fb3 100644 --- a/docs/data/components/collapsible/animations.module.css +++ b/docs/data/components/collapsible/animations.module.css @@ -16,10 +16,10 @@ } } -.panel[data-collapsible='open'] { +.panel[data-open] { animation: slideDown 300ms ease-out; } -.panel[data-collapsible='closed'] { +.panel { animation: slideUp 300ms ease-out; } diff --git a/docs/data/components/collapsible/styles.module.css b/docs/data/components/collapsible/styles.module.css index 2930ce898..82b774a8b 100644 --- a/docs/data/components/collapsible/styles.module.css +++ b/docs/data/components/collapsible/styles.module.css @@ -9,7 +9,7 @@ transform: rotate(-90deg); } -.trigger[data-collapsible='open'] .icon { +.trigger[data-open] .icon { transform: rotate(0); } diff --git a/docs/data/components/collapsible/transitions.module.css b/docs/data/components/collapsible/transitions.module.css index 9e843b92a..6d3b22d79 100644 --- a/docs/data/components/collapsible/transitions.module.css +++ b/docs/data/components/collapsible/transitions.module.css @@ -1,9 +1,9 @@ -.panel[data-collapsible='open'] { +.panel[data-open] { height: var(--collapsible-panel-height); transition: height 200ms ease-out; } -.panel[data-collapsible='closed'] { +.panel { height: 0; transition: height 200ms ease-in; } diff --git a/docs/src/components/demo/Demo.module.css b/docs/src/components/demo/Demo.module.css index 424af58c8..f151931d7 100644 --- a/docs/src/components/demo/Demo.module.css +++ b/docs/src/components/demo/Demo.module.css @@ -96,12 +96,9 @@ .collapsible { overflow: hidden; + animation: slideUp 200ms ease-in; - &[data-collapsible='open'] { + &[data-open] { animation: slideDown 200ms ease-out; } - - &[data-collapsible='closed'] { - animation: slideUp 200ms ease-in; - } } diff --git a/packages/mui-base/src/Accordion/Item/styleHooks.ts b/packages/mui-base/src/Accordion/Item/styleHooks.ts index 391fa5585..6af7d96c6 100644 --- a/packages/mui-base/src/Accordion/Item/styleHooks.ts +++ b/packages/mui-base/src/Accordion/Item/styleHooks.ts @@ -1,7 +1,9 @@ import type { CustomStyleHookMapping } from '../../utils/getStyleHookProps'; +import { collapsibleOpenStateMapping as baseMapping } from '../../utils/collapsibleOpenStateMapping'; import type { AccordionItem } from './AccordionItem'; export const accordionStyleHookMapping: CustomStyleHookMapping = { + ...baseMapping, disabled: (value) => { if (value) { return { 'data-disabled': '' }; @@ -11,9 +13,6 @@ export const accordionStyleHookMapping: CustomStyleHookMapping { return Number.isInteger(value) ? { 'data-index': String(value) } : null; }, - open: (value) => { - return value ? { 'data-accordion': 'open' } : { 'data-accordion': 'closed' }; - }, transitionStatus: (value) => { if (value === 'entering') { return { 'data-entering': '' } as Record; diff --git a/packages/mui-base/src/Accordion/Root/AccordionRoot.test.tsx b/packages/mui-base/src/Accordion/Root/AccordionRoot.test.tsx index 5af9312f9..632eac64f 100644 --- a/packages/mui-base/src/Accordion/Root/AccordionRoot.test.tsx +++ b/packages/mui-base/src/Accordion/Root/AccordionRoot.test.tsx @@ -59,23 +59,19 @@ describe('', () => { const panel = getByTestId('panel'); expect(trigger).to.have.attribute('aria-expanded', 'false'); - expect(trigger).to.have.attribute('data-accordion', 'closed'); expect(panel).to.have.attribute('hidden'); - expect(panel).to.have.attribute('data-accordion', 'closed'); await user.pointer({ keys: '[MouseLeft]', target: trigger }); expect(trigger).to.have.attribute('aria-expanded', 'true'); - expect(trigger).to.have.attribute('data-accordion', 'open'); + expect(trigger).to.have.attribute('data-panel-open'); expect(panel).to.not.have.attribute('hidden'); - expect(panel).to.have.attribute('data-accordion', 'open'); + expect(panel).to.have.attribute('data-open'); await user.pointer({ keys: '[MouseLeft]', target: trigger }); expect(trigger).to.have.attribute('aria-expanded', 'false'); - expect(trigger).to.have.attribute('data-accordion', 'closed'); expect(panel).to.have.attribute('hidden'); - expect(panel).to.have.attribute('data-accordion', 'closed'); }); describe('prop: defaultValue', () => { @@ -101,11 +97,10 @@ describe('', () => { , ); - const panel1 = getByTestId('panel1'); + // const panel1 = getByTestId('panel1'); const panel2 = getByTestId('panel2'); - expect(panel1).to.have.attribute('data-accordion', 'closed'); - expect(panel2).to.have.attribute('data-accordion', 'open'); + expect(panel2).to.have.attribute('data-open'); }); it('custom item value', async () => { @@ -131,10 +126,9 @@ describe('', () => { ); const panel1 = getByTestId('panel1'); - const panel2 = getByTestId('panel2'); + // const panel2 = getByTestId('panel2'); - expect(panel1).to.have.attribute('data-accordion', 'open'); - expect(panel2).to.have.attribute('data-accordion', 'closed'); + expect(panel1).to.have.attribute('data-open'); }); }); }); @@ -158,23 +152,19 @@ describe('', () => { const panel = getByTestId('panel'); expect(trigger).to.have.attribute('aria-expanded', 'false'); - expect(trigger).to.have.attribute('data-accordion', 'closed'); expect(panel).to.have.attribute('hidden'); - expect(panel).to.have.attribute('data-accordion', 'closed'); setProps({ value: [0] }); expect(trigger).to.have.attribute('aria-expanded', 'true'); - expect(trigger).to.have.attribute('data-accordion', 'open'); + expect(trigger).to.have.attribute('data-panel-open'); expect(panel).to.not.have.attribute('hidden'); - expect(panel).to.have.attribute('data-accordion', 'open'); + expect(panel).to.have.attribute('data-open'); setProps({ value: [] }); expect(trigger).to.have.attribute('aria-expanded', 'false'); - expect(trigger).to.have.attribute('data-accordion', 'closed'); expect(panel).to.have.attribute('hidden'); - expect(panel).to.have.attribute('data-accordion', 'closed'); }); describe('prop: value', () => { @@ -200,11 +190,10 @@ describe('', () => { , ); - const panel1 = getByTestId('panel1'); + // const panel1 = getByTestId('panel1'); const panel2 = getByTestId('panel2'); - expect(panel1).to.have.attribute('data-accordion', 'closed'); - expect(panel2).to.have.attribute('data-accordion', 'open'); + expect(panel2).to.have.attribute('data-open'); }); it('custom item value', async () => { @@ -230,10 +219,10 @@ describe('', () => { ); const panel1 = getByTestId('panel1'); - const panel2 = getByTestId('panel2'); + // const panel2 = getByTestId('panel2'); - expect(panel1).to.have.attribute('data-accordion', 'open'); - expect(panel2).to.have.attribute('data-accordion', 'closed'); + expect(panel1).to.have.attribute('data-open'); + // expect(panel2).to.have.attribute('data-accordion', 'closed'); }); }); }); @@ -336,7 +325,6 @@ describe('', () => { expect(trigger).to.have.attribute('aria-expanded', 'false'); expect(panel).to.have.attribute('hidden'); - expect(panel).to.have.attribute('data-accordion', 'closed'); await user.keyboard('[Tab]'); expect(trigger).toHaveFocus(); @@ -344,12 +332,11 @@ describe('', () => { expect(trigger).to.have.attribute('aria-expanded', 'true'); expect(panel).to.not.have.attribute('hidden'); - expect(panel).to.have.attribute('data-accordion', 'open'); + expect(panel).to.have.attribute('data-open'); await user.keyboard(`[${key}]`); expect(trigger).to.have.attribute('aria-expanded', 'false'); - expect(panel).to.have.attribute('data-accordion', 'closed'); expect(panel).to.have.attribute('hidden'); }); }); @@ -573,15 +560,16 @@ describe('', () => { const panel2 = getByTestId('panel2'); [trigger1, panel1, trigger2, panel2].forEach((element) => { - expect(element).to.have.attribute('data-accordion', 'closed'); + expect(element).to.not.have.attribute('data-open'); }); await user.pointer({ keys: '[MouseLeft]', target: trigger1 }); await user.pointer({ keys: '[MouseLeft]', target: trigger2 }); - [trigger1, panel1, trigger2, panel2].forEach((element) => { - expect(element).to.have.attribute('data-accordion', 'open'); - }); + expect(panel1).to.have.attribute('data-open'); + expect(panel2).to.have.attribute('data-open'); + expect(trigger1).to.have.attribute('data-panel-open'); + expect(trigger2).to.have.attribute('data-panel-open'); }); it('when false only one item can be open', async () => { @@ -611,24 +599,22 @@ describe('', () => { const trigger2 = getByTestId('trigger2'); const panel2 = getByTestId('panel2'); - [trigger1, panel1, trigger2, panel2].forEach((element) => { - expect(element).to.have.attribute('data-accordion', 'closed'); - }); + expect(panel1).to.not.have.attribute('data-open'); + expect(panel2).to.not.have.attribute('data-open'); + expect(trigger1).to.not.have.attribute('data-panel-open'); + expect(trigger2).to.not.have.attribute('data-panel-open'); await user.pointer({ keys: '[MouseLeft]', target: trigger1 }); - [trigger1, panel1].forEach((element) => { - expect(element).to.have.attribute('data-accordion', 'open'); - }); + expect(panel1).to.have.attribute('data-open'); + expect(trigger1).to.have.attribute('data-panel-open'); await user.pointer({ keys: '[MouseLeft]', target: trigger2 }); - [trigger2, panel2].forEach((element) => { - expect(element).to.have.attribute('data-accordion', 'open'); - }); - [trigger1, panel1].forEach((element) => { - expect(element).to.have.attribute('data-accordion', 'closed'); - }); + expect(panel2).to.have.attribute('data-open'); + expect(trigger2).to.have.attribute('data-panel-open'); + expect(panel1).to.not.have.attribute('data-open'); + expect(trigger1).to.not.have.attribute('data-panel-open'); }); }); diff --git a/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.tsx b/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.tsx index 10927551e..41c5428f2 100644 --- a/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.tsx +++ b/packages/mui-base/src/Accordion/Trigger/AccordionTrigger.tsx @@ -1,6 +1,7 @@ 'use client'; import * as React from 'react'; import PropTypes from 'prop-types'; +import { triggerOpenStateMapping } from '../../utils/collapsibleOpenStateMapping'; import { useComponentRenderer } from '../../utils/useComponentRenderer'; import { useEnhancedEffect } from '../../utils/useEnhancedEffect'; import { BaseUIComponentProps } from '../../utils/types'; @@ -8,7 +9,6 @@ import { useCollapsibleRootContext } from '../../Collapsible/Root/CollapsibleRoo import { useCollapsibleTrigger } from '../../Collapsible/Trigger/useCollapsibleTrigger'; import type { AccordionItem } from '../Item/AccordionItem'; import { useAccordionItemContext } from '../Item/AccordionItemContext'; -import { accordionStyleHookMapping } from '../Item/styleHooks'; /** * @@ -20,6 +20,7 @@ import { accordionStyleHookMapping } from '../Item/styleHooks'; * * - [AccordionTrigger API](https://base-ui.netlify.app/components/react-accordion/#api-reference-AccordionTrigger) */ + const AccordionTrigger = React.forwardRef(function AccordionTrigger( props: AccordionTrigger.Props, forwardedRef: React.ForwardedRef, @@ -52,7 +53,7 @@ const AccordionTrigger = React.forwardRef(function AccordionTrigger( ownerState, className, extraProps: { ...otherProps, id: triggerId }, - customStyleHookMapping: accordionStyleHookMapping, + customStyleHookMapping: triggerOpenStateMapping, }); return renderElement(); diff --git a/packages/mui-base/src/Collapsible/Root/CollapsibleRoot.test.tsx b/packages/mui-base/src/Collapsible/Root/CollapsibleRoot.test.tsx index c9d2fe667..8b85b0ca2 100644 --- a/packages/mui-base/src/Collapsible/Root/CollapsibleRoot.test.tsx +++ b/packages/mui-base/src/Collapsible/Root/CollapsibleRoot.test.tsx @@ -40,7 +40,7 @@ describe('', () => { const { getByTestId, getByRole, setProps } = await render( - + This is content , ); @@ -49,18 +49,16 @@ describe('', () => { expect(trigger).to.have.attribute('aria-expanded', 'false'); expect(panel).to.have.attribute('hidden'); - expect(panel).to.have.attribute('data-collapsible', 'closed'); setProps({ open: true }); expect(trigger).to.have.attribute('aria-expanded', 'true'); expect(panel).to.not.have.attribute('hidden'); - expect(panel).to.have.attribute('data-collapsible', 'open'); + expect(panel).to.have.attribute('data-open'); setProps({ open: false }); expect(trigger).to.have.attribute('aria-expanded', 'false'); - expect(panel).to.have.attribute('data-collapsible', 'closed'); expect(panel).to.have.attribute('hidden'); }); @@ -77,18 +75,16 @@ describe('', () => { expect(trigger).to.have.attribute('aria-expanded', 'false'); expect(panel).to.have.attribute('hidden'); - expect(panel).to.have.attribute('data-collapsible', 'closed'); await user.pointer({ keys: '[MouseLeft]', target: trigger }); expect(trigger).to.have.attribute('aria-expanded', 'true'); expect(panel).to.not.have.attribute('hidden'); - expect(panel).to.have.attribute('data-collapsible', 'open'); + expect(panel).to.have.attribute('data-open'); await user.pointer({ keys: '[MouseLeft]', target: trigger }); expect(trigger).to.have.attribute('aria-expanded', 'false'); - expect(panel).to.have.attribute('data-collapsible', 'closed'); expect(panel).to.have.attribute('hidden'); }); }); @@ -108,7 +104,6 @@ describe('', () => { expect(trigger).to.have.attribute('aria-expanded', 'false'); expect(panel).to.have.attribute('hidden'); - expect(panel).to.have.attribute('data-collapsible', 'closed'); await user.keyboard('[Tab]'); expect(trigger).toHaveFocus(); @@ -116,12 +111,11 @@ describe('', () => { expect(trigger).to.have.attribute('aria-expanded', 'true'); expect(panel).to.not.have.attribute('hidden'); - expect(panel).to.have.attribute('data-collapsible', 'open'); + expect(panel).to.have.attribute('data-open'); await user.keyboard(`[${key}]`); expect(trigger).to.have.attribute('aria-expanded', 'false'); - expect(panel).to.have.attribute('data-collapsible', 'closed'); expect(panel).to.have.attribute('hidden'); }); }); @@ -145,8 +139,6 @@ describe('', () => { const panel = getByTestId('panel'); - expect(panel).to.have.attribute('data-collapsible', 'closed'); - act(() => { const event = new window.Event('beforematch', { bubbles: true, @@ -156,7 +148,7 @@ describe('', () => { }); expect(handleOpenChange.callCount).to.equal(1); - expect(panel).to.have.attribute('data-collapsible', 'open'); + expect(panel).to.have.attribute('data-open'); }); }); }); diff --git a/packages/mui-base/src/Collapsible/Root/styleHooks.ts b/packages/mui-base/src/Collapsible/Root/styleHooks.ts index b47f9f0bc..483cc786e 100644 --- a/packages/mui-base/src/Collapsible/Root/styleHooks.ts +++ b/packages/mui-base/src/Collapsible/Root/styleHooks.ts @@ -1,10 +1,9 @@ import type { CustomStyleHookMapping } from '../../utils/getStyleHookProps'; +import { collapsibleOpenStateMapping as baseMapping } from '../../utils/collapsibleOpenStateMapping'; import type { CollapsibleRoot } from './CollapsibleRoot'; export const collapsibleStyleHookMapping: CustomStyleHookMapping = { - open: (value) => { - return value ? { 'data-collapsible': 'open' } : { 'data-collapsible': 'closed' }; - }, + ...baseMapping, transitionStatus: (value) => { if (value === 'entering') { return { 'data-entering': '' } as Record; diff --git a/packages/mui-base/src/Collapsible/Trigger/CollapsibleTrigger.tsx b/packages/mui-base/src/Collapsible/Trigger/CollapsibleTrigger.tsx index 205f3a5b9..ef59b7b65 100644 --- a/packages/mui-base/src/Collapsible/Trigger/CollapsibleTrigger.tsx +++ b/packages/mui-base/src/Collapsible/Trigger/CollapsibleTrigger.tsx @@ -1,11 +1,11 @@ 'use client'; import * as React from 'react'; import PropTypes from 'prop-types'; +import { triggerOpenStateMapping } from '../../utils/collapsibleOpenStateMapping'; import { useComponentRenderer } from '../../utils/useComponentRenderer'; import { BaseUIComponentProps } from '../../utils/types'; import { useCollapsibleRootContext } from '../Root/CollapsibleRootContext'; import { CollapsibleRoot } from '../Root/CollapsibleRoot'; -import { collapsibleStyleHookMapping } from '../Root/styleHooks'; import { useCollapsibleTrigger } from './useCollapsibleTrigger'; /** @@ -39,7 +39,7 @@ const CollapsibleTrigger = React.forwardRef(function CollapsibleTrigger( ownerState, className, extraProps: otherProps, - customStyleHookMapping: collapsibleStyleHookMapping, + customStyleHookMapping: triggerOpenStateMapping, }); return renderElement(); diff --git a/packages/mui-base/src/utils/collapsibleOpenStateMapping.ts b/packages/mui-base/src/utils/collapsibleOpenStateMapping.ts new file mode 100644 index 000000000..6f35357a7 --- /dev/null +++ b/packages/mui-base/src/utils/collapsibleOpenStateMapping.ts @@ -0,0 +1,23 @@ +import type { CustomStyleHookMapping } from './getStyleHookProps'; + +export const triggerOpenStateMapping: CustomStyleHookMapping<{ open: boolean }> = { + open(value) { + if (value) { + return { + 'data-panel-open': '', + }; + } + return null; + }, +}; + +export const collapsibleOpenStateMapping: CustomStyleHookMapping<{ open: boolean }> = { + open(value) { + if (value) { + return { + 'data-open': '', + }; + } + return null; + }, +}; From 710c2cd9dec3feb01995376db16bf922f13747d5 Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Wed, 16 Oct 2024 23:53:30 +0800 Subject: [PATCH 29/37] Improve tests --- .../src/Accordion/Root/AccordionRoot.test.tsx | 167 ++++++++---------- .../Collapsible/Root/CollapsibleRoot.test.tsx | 49 ++--- 2 files changed, 96 insertions(+), 120 deletions(-) diff --git a/packages/mui-base/src/Accordion/Root/AccordionRoot.test.tsx b/packages/mui-base/src/Accordion/Root/AccordionRoot.test.tsx index 632eac64f..b0b164013 100644 --- a/packages/mui-base/src/Accordion/Root/AccordionRoot.test.tsx +++ b/packages/mui-base/src/Accordion/Root/AccordionRoot.test.tsx @@ -42,210 +42,193 @@ describe('', () => { describe('uncontrolled', () => { it('open state', async () => { - const { getByRole, getByTestId, user } = await render( + const { getByRole, queryByText, user } = await render( Trigger 1 - - This is the contents of Accordion.Panel 1 - + Panel contents , ); const trigger = getByRole('button'); - const panel = getByTestId('panel'); + const panel = queryByText('Panel contents'); expect(trigger).to.have.attribute('aria-expanded', 'false'); - expect(panel).to.have.attribute('hidden'); + expect(panel).not.toBeVisible(); await user.pointer({ keys: '[MouseLeft]', target: trigger }); expect(trigger).to.have.attribute('aria-expanded', 'true'); expect(trigger).to.have.attribute('data-panel-open'); - expect(panel).to.not.have.attribute('hidden'); + expect(panel).toBeVisible(); expect(panel).to.have.attribute('data-open'); await user.pointer({ keys: '[MouseLeft]', target: trigger }); expect(trigger).to.have.attribute('aria-expanded', 'false'); - expect(panel).to.have.attribute('hidden'); + expect(panel).not.toBeVisible(); }); describe('prop: defaultValue', () => { it('default item value', async () => { - const { getByTestId } = await render( + const { queryByText } = await render( Trigger 1 - - This is the contents of Accordion.Panel 1 - + Panel contents 1 Trigger 2 - - This is the contents of Accordion.Panel 2 - + Panel contents 2 , ); - // const panel1 = getByTestId('panel1'); - const panel2 = getByTestId('panel2'); + const panel1 = queryByText('Panel contents 1'); + const panel2 = queryByText('Panel contents 2'); + expect(panel1).not.toBeVisible(); + expect(panel2).toBeVisible(); expect(panel2).to.have.attribute('data-open'); }); it('custom item value', async () => { - const { getByTestId } = await render( + const { queryByText } = await render( Trigger 1 - - This is the contents of Accordion.Panel 1 - + Panel contents 1 Trigger 2 - - This is the contents of Accordion.Panel 2 - + Panel contents 2 , ); - const panel1 = getByTestId('panel1'); - // const panel2 = getByTestId('panel2'); + const panel1 = queryByText('Panel contents 1'); + const panel2 = queryByText('Panel contents 2'); + expect(panel1).toBeVisible(); expect(panel1).to.have.attribute('data-open'); + expect(panel2).not.toBeVisible(); }); }); }); describe('controlled', () => { it('open state', async () => { - const { getByRole, getByTestId, setProps } = await render( + const { getByRole, queryByText, setProps } = await render( Trigger 1 - - This is the contents of Accordion.Panel 1 - + Panel contents 1 , ); const trigger = getByRole('button'); - const panel = getByTestId('panel'); + const panel = queryByText('Panel contents 1'); expect(trigger).to.have.attribute('aria-expanded', 'false'); - expect(panel).to.have.attribute('hidden'); + expect(panel).not.toBeVisible(); setProps({ value: [0] }); expect(trigger).to.have.attribute('aria-expanded', 'true'); expect(trigger).to.have.attribute('data-panel-open'); - expect(panel).to.not.have.attribute('hidden'); + expect(panel).toBeVisible(); expect(panel).to.have.attribute('data-open'); setProps({ value: [] }); expect(trigger).to.have.attribute('aria-expanded', 'false'); - expect(panel).to.have.attribute('hidden'); + expect(panel).not.toBeVisible(); }); describe('prop: value', () => { it('default item value', async () => { - const { getByTestId } = await render( + const { queryByText } = await render( Trigger 1 - - This is the contents of Accordion.Panel 1 - + Panel contents 1 Trigger 2 - - This is the contents of Accordion.Panel 2 - + Panel contents 2 , ); - // const panel1 = getByTestId('panel1'); - const panel2 = getByTestId('panel2'); + const panel1 = queryByText('Panel contents 1'); + const panel2 = queryByText('Panel contents 2'); + expect(panel1).not.toBeVisible(); + expect(panel2).toBeVisible(); expect(panel2).to.have.attribute('data-open'); }); it('custom item value', async () => { - const { getByTestId } = await render( + const { queryByText } = await render( Trigger 1 - - This is the contents of Accordion.Panel 1 - + Panel contents 1 - + Trigger 2 - - This is the contents of Accordion.Panel 2 - + Panel contents 2 , ); - const panel1 = getByTestId('panel1'); - // const panel2 = getByTestId('panel2'); + const panel1 = queryByText('Panel contents 1'); + const panel2 = queryByText('Panel contents 2'); + expect(panel1).toBeVisible(); expect(panel1).to.have.attribute('data-open'); - // expect(panel2).to.have.attribute('data-accordion', 'closed'); + expect(panel2).not.toBeVisible(); }); }); }); describe('prop: disabled', () => { it('can disable the whole accordion', async () => { - const { getByTestId } = await render( + const { getByTestId, queryByText } = await render( Trigger 1 - - This is the contents of Accordion.Panel 1 - + Panel contents 1 Trigger 2 - - This is the contents of Accordion.Panel 2 - + Panel contents 2 , ); @@ -253,11 +236,11 @@ describe('', () => { const item1 = getByTestId('item1'); const header1 = getByTestId('header1'); const trigger1 = getByTestId('trigger1'); - const panel1 = getByTestId('panel1'); + const panel1 = queryByText('Panel contents 1'); const item2 = getByTestId('item2'); const header2 = getByTestId('header2'); const trigger2 = getByTestId('trigger2'); - const panel2 = getByTestId('panel2'); + const panel2 = queryByText('Panel contents 2'); [item1, header1, trigger1, panel1, item2, header2, trigger2, panel2].forEach((element) => { expect(element).to.have.attribute('data-disabled'); @@ -265,23 +248,19 @@ describe('', () => { }); it('can disable one accordion item', async () => { - const { getByTestId } = await render( + const { getByTestId, queryByText } = await render( Trigger 1 - - This is the contents of Accordion.Panel 1 - + Panel contents 1 Trigger 2 - - This is the contents of Accordion.Panel 2 - + Panel contents 2 , ); @@ -289,11 +268,11 @@ describe('', () => { const item1 = getByTestId('item1'); const header1 = getByTestId('header1'); const trigger1 = getByTestId('trigger1'); - const panel1 = getByTestId('panel1'); + const panel1 = queryByText('Panel contents 1'); const item2 = getByTestId('item2'); const header2 = getByTestId('header2'); const trigger2 = getByTestId('trigger2'); - const panel2 = getByTestId('panel2'); + const panel2 = queryByText('Panel contents 2'); [item1, header1, trigger1, panel1].forEach((element) => { expect(element).to.have.attribute('data-disabled'); @@ -307,37 +286,37 @@ describe('', () => { describe('keyboard interactions', () => { ['Enter', 'Space'].forEach((key) => { it(`key: ${key} toggles the Accordion open state`, async () => { - const { getByTestId, getByRole, user } = await render( + const { getByRole, queryByText, user } = await render( Trigger 1 - - This is the contents of Accordion.Panel 1 - + Panel contents 1 , ); const trigger = getByRole('button'); - const panel = getByTestId('panel'); + const panel = queryByText('Panel contents 1'); expect(trigger).to.have.attribute('aria-expanded', 'false'); - expect(panel).to.have.attribute('hidden'); + + expect(panel).not.toBeVisible(); await user.keyboard('[Tab]'); expect(trigger).toHaveFocus(); await user.keyboard(`[${key}]`); expect(trigger).to.have.attribute('aria-expanded', 'true'); - expect(panel).to.not.have.attribute('hidden'); + expect(trigger).to.have.attribute('data-panel-open'); + expect(panel).toBeVisible(); expect(panel).to.have.attribute('data-open'); await user.keyboard(`[${key}]`); expect(trigger).to.have.attribute('aria-expanded', 'false'); - expect(panel).to.have.attribute('hidden'); + expect(panel).not.toBeVisible(); }); }); @@ -533,31 +512,27 @@ describe('', () => { describe('prop: openMultiple', () => { it('multiple items can be open by default', async () => { - const { getByTestId, user } = await render( + const { getByTestId, queryByText, user } = await render( Trigger 1 - - This is the contents of Accordion.Panel 1 - + Panel contents 1 Trigger 2 - - This is the contents of Accordion.Panel 2 - + Panel contents 2 , ); const trigger1 = getByTestId('trigger1'); - const panel1 = getByTestId('panel1'); + const panel1 = queryByText('Panel contents 1'); const trigger2 = getByTestId('trigger2'); - const panel2 = getByTestId('panel2'); + const panel2 = queryByText('Panel contents 2'); [trigger1, panel1, trigger2, panel2].forEach((element) => { expect(element).to.not.have.attribute('data-open'); @@ -573,31 +548,27 @@ describe('', () => { }); it('when false only one item can be open', async () => { - const { getByTestId, user } = await render( + const { getByTestId, queryByText, user } = await render( Trigger 1 - - This is the contents of Accordion.Panel 1 - + Panel contents 1 Trigger 2 - - This is the contents of Accordion.Panel 2 - + Panel contents 2 , ); const trigger1 = getByTestId('trigger1'); - const panel1 = getByTestId('panel1'); + const panel1 = queryByText('Panel contents 1'); const trigger2 = getByTestId('trigger2'); - const panel2 = getByTestId('panel2'); + const panel2 = queryByText('Panel contents 2'); expect(panel1).to.not.have.attribute('data-open'); expect(panel2).to.not.have.attribute('data-open'); diff --git a/packages/mui-base/src/Collapsible/Root/CollapsibleRoot.test.tsx b/packages/mui-base/src/Collapsible/Root/CollapsibleRoot.test.tsx index 8b85b0ca2..448d67aee 100644 --- a/packages/mui-base/src/Collapsible/Root/CollapsibleRoot.test.tsx +++ b/packages/mui-base/src/Collapsible/Root/CollapsibleRoot.test.tsx @@ -37,86 +37,91 @@ describe('', () => { describe('open state', () => { it('controlled mode', async () => { - const { getByTestId, getByRole, setProps } = await render( + const { queryByText, getByRole, setProps } = await render( - This is content + This is content , ); const trigger = getByRole('button'); - const panel = getByTestId('panel'); + const panel = queryByText('This is content'); expect(trigger).to.have.attribute('aria-expanded', 'false'); - expect(panel).to.have.attribute('hidden'); + expect(panel).not.toBeVisible(); setProps({ open: true }); expect(trigger).to.have.attribute('aria-expanded', 'true'); - expect(panel).to.not.have.attribute('hidden'); + expect(panel).toBeVisible(); expect(panel).to.have.attribute('data-open'); + expect(trigger).to.have.attribute('data-panel-open'); setProps({ open: false }); expect(trigger).to.have.attribute('aria-expanded', 'false'); - expect(panel).to.have.attribute('hidden'); + expect(panel).not.toBeVisible(); }); it('uncontrolled mode', async () => { - const { getByTestId, getByRole, user } = await render( + const { queryByText, getByRole, user } = await render( - + This is content , ); const trigger = getByRole('button'); - const panel = getByTestId('panel'); + const panel = queryByText('This is content'); expect(trigger).to.have.attribute('aria-expanded', 'false'); - expect(panel).to.have.attribute('hidden'); + expect(panel).not.toBeVisible(); await user.pointer({ keys: '[MouseLeft]', target: trigger }); expect(trigger).to.have.attribute('aria-expanded', 'true'); - expect(panel).to.not.have.attribute('hidden'); + expect(panel).toBeVisible(); expect(panel).to.have.attribute('data-open'); + expect(trigger).to.have.attribute('data-panel-open'); await user.pointer({ keys: '[MouseLeft]', target: trigger }); expect(trigger).to.have.attribute('aria-expanded', 'false'); - expect(panel).to.have.attribute('hidden'); + expect(trigger).to.not.have.attribute('data-panel-open'); + expect(panel).not.toBeVisible(); }); }); describe('keyboard interactions', () => { ['Enter', 'Space'].forEach((key) => { it(`key: ${key} should toggle the Collapsible`, async () => { - const { getByTestId, getByRole, user } = await render( + const { queryByText, getByRole, user } = await render( Trigger - + This is content , ); const trigger = getByRole('button'); - const panel = getByTestId('panel'); + const panel = queryByText('This is content'); expect(trigger).to.have.attribute('aria-expanded', 'false'); - expect(panel).to.have.attribute('hidden'); + expect(panel).not.toBeVisible(); await user.keyboard('[Tab]'); expect(trigger).toHaveFocus(); await user.keyboard(`[${key}]`); expect(trigger).to.have.attribute('aria-expanded', 'true'); - expect(panel).to.not.have.attribute('hidden'); + expect(trigger).to.have.attribute('data-panel-open'); + expect(panel).toBeVisible(); expect(panel).to.have.attribute('data-open'); await user.keyboard(`[${key}]`); expect(trigger).to.have.attribute('aria-expanded', 'false'); - expect(panel).to.have.attribute('hidden'); + expect(trigger).not.to.have.attribute('data-panel-open'); + expect(panel).not.toBeVisible(); }); }); }); @@ -130,21 +135,21 @@ describe('', () => { const handleOpenChange = spy(); - const { getByTestId } = await render( + const { queryByText } = await render( - + This is content , ); - const panel = getByTestId('panel'); + const panel = queryByText('This is content'); act(() => { const event = new window.Event('beforematch', { bubbles: true, cancelable: false, }); - panel.dispatchEvent(event); + panel?.dispatchEvent(event); }); expect(handleOpenChange.callCount).to.equal(1); From 5a7803e2c2c1253b993affcbfa74d21483c5a944 Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Thu, 17 Oct 2024 11:51:37 +0800 Subject: [PATCH 30/37] Update docs --- docs/data/components/accordion/accordion.mdx | 51 ++++++++--------- .../components/collapsible/collapsible.mdx | 55 ++++++++++--------- 2 files changed, 54 insertions(+), 52 deletions(-) diff --git a/docs/data/components/accordion/accordion.mdx b/docs/data/components/accordion/accordion.mdx index e96ca5b71..546816c96 100644 --- a/docs/data/components/accordion/accordion.mdx +++ b/docs/data/components/accordion/accordion.mdx @@ -26,7 +26,7 @@ packageName: '@base_ui/react' Accordions are implemented using a collection of related components: - `` is a top-level component that wraps the other components. -- `` is a component that wraps each section of content +- `` is a component that wraps each section of content and it's associated `Trigger` - `` is a button that toggles the open state of it's associated `Item` - `` is a heading (`h3` by default) that wraps the `Trigger` - `` is the element that contains content in a `Item` @@ -51,7 +51,7 @@ Accordions are implemented using a collection of related components: ## Value Each `Accordion.Item` is represented by a value, which by default is its zero-based index by DOM position. -The first one has an implicit `value` of `0`, the second one has a `value` of `1`, and so on. +The first `Item` has an implicit `value` of `0`, the second one `Item` a `value` of `1`, and so on. The open state of the accordion is represented an array holding the `value`s of all open `Item`s. @@ -208,12 +208,11 @@ This relies on the HTML `hidden="until-found"` attribute which only has [partial Accordion uses [`Collapsible`](/components/react-collapsible/) internally, and can be animated in a [similar way](/components/react-collapsible/#animations). -Four states are available as data attributes to animate the `Accordion.Panel`: +Three states are available as data attributes to animate the `Accordion.Panel`: -- `[data-accordion="open"]` - `open` state is `true`. -- `[data-accordion="closed"]` - `open` state is `false`. Can still be mounted to the DOM if closing. -- `[data-entering]` - the `hidden` attribute was just removed from the DOM and the content element participates in page layout. The `data-entering` attribute will be removed 1 animation frame later. -- `[data-exiting]` - the content element is in the process of being hidden from the DOM, but is still mounted. +- `[data-open]` - `open` state is `true`. +- `[data-entering]` - the `hidden` attribute was just removed from the DOM and the panel element participates in page layout. The `data-entering` attribute will be removed 1 animation frame later. +- `[data-exiting]` - the panel element is in the process of being hidden from the DOM, but is still mounted. The component can be animate when opening or closing using either: @@ -221,25 +220,27 @@ The component can be animate when opening or closing using either: - CSS transitions - JavaScript animations -The dimensions of the `Accordion.Panel` subcomponent are provided as the `--accordion-panel-height` and `--accordion-panel-width` CSS variables. +### Styling + +The `Accordion.Panel` element receives the following CSS variables about its dimensions, which can be used to style animations or transitions: + +-- `--accordion-panel-height`: Specifies the height of the `Panel`. +-- `--accordion-panel-width`: Specifies the width of the `Panel`. ### CSS Animations CSS animations can be used with two declarations: ```css -.Accordion-panel { +.AccordionPanel { overflow: hidden; + animation: slideUp 300ms ease-in; } -.Accordion-panel[data-collapsible='open'] { +.AccordionPanel[data-open] { animation: slideDown 300ms ease-out; } -.Accordion-panel[data-collapsible='closed'] { - animation: slideUp 300ms ease-in; -} - @keyframes slideDown { from { height: 0; @@ -263,27 +264,27 @@ CSS animations can be used with two declarations: When using CSS transitions, styles for the `Panel` must be applied to three states: -- The closed styles with `[data-collapsible="closed"]` -- The open styles with `[data-collapsible="open"]` -- The entering styles with `[data-entering]` +- The exiting styles, placed on the base element class +- The open styles, placed on the base element class with `[data-state="open"]` +- The entering styles, placed on the base element class with `[data-entering]` ```css -.Accordion-panel { +.AccordionPanel { overflow: hidden; + /* The final styles once closed/exited */ + height: 0; + transition: height 300ms ease-in; } -.Accordion-panel[data-collapsible='open'] { +/* The final styles once opened/entered */ +.AccordionPanel[data-open] { height: var(--accordion-panel-height); transition: height 300ms ease-out; } -.Accordion-panel[data-entering] { - height: 0; -} - -.Accordion-panel[data-collapsible='closed'] { +/* The initial styles when opening/entering */ +.AccordionPanel[data-entering] { height: 0; - transition: height 300ms ease-in; } ``` diff --git a/docs/data/components/collapsible/collapsible.mdx b/docs/data/components/collapsible/collapsible.mdx index 2405fc59b..744bb9afa 100644 --- a/docs/data/components/collapsible/collapsible.mdx +++ b/docs/data/components/collapsible/collapsible.mdx @@ -23,8 +23,8 @@ packageName: '@base_ui/react' ## Anatomy - `` is a top-level component that facilitates communication between other components. It does not render to the DOM by default. -- `` is the trigger element, a `