diff --git a/README.md b/README.md index 5a10d81..886185c 100644 --- a/README.md +++ b/README.md @@ -99,19 +99,20 @@ const { getCollapseProps, getToggleProps, isExpanded, setExpanded } = The following are optional properties passed into `useCollapse({ })`: -| Prop | Type | Default | Description | -| --------------- | -------- | ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------- | -| isExpanded | boolean | `undefined` | If true, the Collapse is expanded | -| defaultExpanded | boolean | `false` | If true, the Collapse will be expanded when mounted | -| expandStyles | object | `{}` | Style object applied to the collapse panel when it expands | -| collapseStyles | object | `{}` | Style object applied to the collapse panel when it collapses | -| collapsedHeight | number | `0` | The height of the content when collapsed | -| easing | string | `cubic-bezier(0.4, 0, 0.2, 1)` | The transition timing function for the animation | -| duration | number | `undefined` | The duration of the animation in milliseconds. By default, the duration is programmatically calculated based on the height of the collapsed element | -| onCollapseStart | function | no-op | Handler called when the collapse animation begins | -| onCollapseEnd | function | no-op | Handler called when the collapse animation ends | -| onExpandStart | function | no-op | Handler called when the expand animation begins | -| onExpandEnd | function | no-op | Handler called when the expand animation ends | +| Prop | Type | Default | Description | +| -------------------- | -------- | ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------- | +| isExpanded | boolean | `undefined` | If true, the Collapse is expanded | +| defaultExpanded | boolean | `false` | If true, the Collapse will be expanded when mounted | +| expandStyles | object | `{}` | Style object applied to the collapse panel when it expands | +| collapseStyles | object | `{}` | Style object applied to the collapse panel when it collapses | +| collapsedHeight | number | `0` | The height of the content when collapsed | +| easing | string | `cubic-bezier(0.4, 0, 0.2, 1)` | The transition timing function for the animation | +| duration | number | `undefined` | The duration of the animation in milliseconds. By default, the duration is programmatically calculated based on the height of the collapsed element | +| onCollapseStart | function | no-op | Handler called when the collapse animation begins | +| onCollapseEnd | function | no-op | Handler called when the collapse animation ends | +| onExpandStart | function | no-op | Handler called when the expand animation begins | +| onExpandEnd | function | no-op | Handler called when the expand animation ends | +| hasDisabledAnimation | boolean | false | If true, will disable the animation | ### What you get diff --git a/src/index.ts b/src/index.ts index f822f59..a2ca500 100644 --- a/src/index.ts +++ b/src/index.ts @@ -34,6 +34,7 @@ export default function useCollapse({ onCollapseEnd = noop, isExpanded: configIsExpanded, defaultExpanded = false, + hasDisabledAnimation = false, ...initialConfig }: UseCollapseInput = {}): UseCollapseOutput { const [isExpanded, setExpanded] = useControlledState( @@ -64,9 +65,10 @@ export default function useCollapse({ setStyles((oldStyles) => ({ ...oldStyles, ...newStyles })) } - function getTransitionStyles(height: number | string): { - transition: string - } { + function getTransitionStyles(height: number | string): CSSProperties { + if (hasDisabledAnimation) { + return {} + } const _duration = duration || getAutoHeightDuration(height) return { transition: `height ${_duration}ms ${easing}`, diff --git a/src/stories/basic.stories.tsx b/src/stories/basic.stories.tsx index 2bc5421..ca297fe 100644 --- a/src/stories/basic.stories.tsx +++ b/src/stories/basic.stories.tsx @@ -31,6 +31,42 @@ export const Controlled = () => { ) } +function useReduceMotion() { + const [matches, setMatch] = React.useState( + window.matchMedia('(prefers-reduced-motion: reduce)').matches + ); + React.useEffect(() => { + const mq = window.matchMedia('(prefers-reduced-motion: reduce)'); + const handleChange = () => { + setMatch(mq.matches); + }; + handleChange(); + mq.addEventListener('change', handleChange); + return () => { + mq.removeEventListener('change', handleChange); + }; + }, []); + return matches; +} + +export const PrefersReducedMotion = () => { + const reduceMotion = useReduceMotion() + const [isExpanded, setOpen] = React.useState(true) + const { getCollapseProps, getToggleProps } = useCollapse({ + isExpanded, + hasDisabledAnimation: reduceMotion, + }) + + return ( +
+ setOpen((old) => !old) })}> + {isExpanded ? 'Close' : 'Open'} + + {excerpt} +
+ ) +} + export default { title: 'Basic Usage', } diff --git a/src/types.ts b/src/types.ts index 3a2c97f..69b670e 100644 --- a/src/types.ts +++ b/src/types.ts @@ -65,6 +65,7 @@ export interface UseCollapseInput { onCollapseEnd?: () => void onExpandStart?: () => void onExpandEnd?: () => void + hasDisabledAnimation?: boolean } export interface UseCollapseOutput {