From 11b99f2728fbd42f4618598815f11f0153cb8c1a Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Wed, 4 Sep 2024 12:54:03 +0800 Subject: [PATCH] Add docs and demos --- .../UnstyledAccordionIntroduction.js | 135 ++++++++++ .../UnstyledAccordionIntroduction.tsx | 135 ++++++++++ .../base/components/accordion/accordion.md | 243 ++++++++++++++++++ .../experiments/accordion-horizontal.tsx | 179 +++++++++++++ docs/pages/experiments/accordion-material.tsx | 108 ++++++++ docs/pages/experiments/accordion.tsx | 57 +++- 6 files changed, 851 insertions(+), 6 deletions(-) create mode 100644 docs/data/base/components/accordion/UnstyledAccordionIntroduction.js create mode 100644 docs/data/base/components/accordion/UnstyledAccordionIntroduction.tsx create mode 100644 docs/pages/experiments/accordion-horizontal.tsx create mode 100644 docs/pages/experiments/accordion-material.tsx diff --git a/docs/data/base/components/accordion/UnstyledAccordionIntroduction.js b/docs/data/base/components/accordion/UnstyledAccordionIntroduction.js new file mode 100644 index 0000000000..dcfddb6413 --- /dev/null +++ b/docs/data/base/components/accordion/UnstyledAccordionIntroduction.js @@ -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/base/components/accordion/UnstyledAccordionIntroduction.tsx b/docs/data/base/components/accordion/UnstyledAccordionIntroduction.tsx new file mode 100644 index 0000000000..dcfddb6413 --- /dev/null +++ b/docs/data/base/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/base/components/accordion/accordion.md b/docs/data/base/components/accordion/accordion.md index 96b8af2955..08d86d4335 100644 --- a/docs/data/base/components/accordion/accordion.md +++ b/docs/data/base/components/accordion/accordion.md @@ -11,3 +11,246 @@ packageName: '@base_ui/react' # Accordion

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

+ +{{"component": "@mui/docs/ComponentLinkHeader", "design": false}} + +{{"component": "modules/components/ComponentPageTabs.js"}} + +## Introduction + +{{"demo": "UnstyledAccordionIntroduction.js", "defaultCodeOpen": false, "bg": "gradient"}} + +## 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. diff --git a/docs/pages/experiments/accordion-horizontal.tsx b/docs/pages/experiments/accordion-horizontal.tsx new file mode 100644 index 0000000000..96e1f02ff2 --- /dev/null +++ b/docs/pages/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/pages/experiments/accordion-material.tsx b/docs/pages/experiments/accordion-material.tsx new file mode 100644 index 0000000000..3130c291ac --- /dev/null +++ b/docs/pages/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/pages/experiments/accordion.tsx b/docs/pages/experiments/accordion.tsx index 94e537a392..eb194c65c7 100644 --- a/docs/pages/experiments/accordion.tsx +++ b/docs/pages/experiments/accordion.tsx @@ -1,12 +1,13 @@ 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 +117,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 +175,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 (