-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix: [IGL-100] Disclosure isExpanded issues (#584)
* Fix: [IGL-100] Disclosure isExpanded issues --------- Co-authored-by: Franck Gaudin <franck.gaudin@workleap.com>
- Loading branch information
1 parent
d814f31
commit c981a8b
Showing
5 changed files
with
186 additions
and
119 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
--- | ||
"@igloo-ui/disclosure": major | ||
--- | ||
|
||
Separated the controlled and uncontrolled expanded props. | ||
|
||
## BREAKING CHANGE | ||
|
||
The defaultExpanded prop was added, which means isExpanded may need to be exchanged for this new prop. | ||
If you use isExpanded to make the disclosure expanded by default, rename it to defaultExpanded. | ||
If you use isExpanded to open/close the disclosure programmatically, keep isExpanded. | ||
Rule of thumb: If isExpanded was used without onOpen and onClose, it most likely has to be renamed to defaultExpanded. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,129 +1,130 @@ | ||
import * as React from 'react'; | ||
import cx from 'classnames'; | ||
import { useButton } from 'react-aria'; | ||
import { m, AnimatePresence, LazyMotion, domAnimation } from 'framer-motion'; | ||
import * as React from "react"; | ||
import cx from "classnames"; | ||
import { useToggleButton } from "react-aria"; | ||
import { useToggleState } from "react-stately"; | ||
import { m, AnimatePresence, LazyMotion, domAnimation } from "framer-motion"; | ||
|
||
import ChevronDown from '@igloo-ui/icons/dist/ChevronDown'; | ||
import ChevronDown from "@igloo-ui/icons/dist/ChevronDown"; | ||
|
||
import './disclosure.scss'; | ||
import "./disclosure.scss"; | ||
|
||
export interface DisclosureProps extends React.ComponentProps<'div'> { | ||
/** The component content to display when expanding */ | ||
children: React.ReactNode; | ||
/** Add a specific class to the disclosure */ | ||
className?: string; | ||
/** Add a data-test tag for automated tests */ | ||
dataTest?: string; | ||
/** The description of the disclosure */ | ||
description?: React.ReactNode; | ||
/** An icon to show as the first element in disclosure */ | ||
icon?: React.ReactNode; | ||
/** Whether or not the disclosure is expanded */ | ||
isExpanded?: boolean; | ||
/** True for a light appearance (no shadow, icon or border) */ | ||
isLowContrast?: boolean; | ||
/** Callback when the disclosure is closed */ | ||
onClose?: () => void; | ||
/** Callback when the disclosure is opened */ | ||
onOpen?: () => void; | ||
/** The title of the disclosure */ | ||
title?: string; | ||
export interface DisclosureProps extends React.ComponentProps<"div"> { | ||
/** The component content to display when expanding */ | ||
children: React.ReactNode; | ||
/** Add a specific class to the disclosure */ | ||
className?: string; | ||
/** Add a data-test tag for automated tests */ | ||
dataTest?: string; | ||
/** Whether or not the disclosure is expanded by default (uncontrolled) */ | ||
defaultExpanded?: boolean; | ||
/** The description of the disclosure */ | ||
description?: React.ReactNode; | ||
/** An icon to show as the first element in disclosure */ | ||
icon?: React.ReactNode; | ||
/** Whether or not the disclosure is expanded (controlled) */ | ||
isExpanded?: boolean; | ||
/** True for a light appearance (no shadow, icon or border) */ | ||
isLowContrast?: boolean; | ||
/** Callback when the disclosure is closed */ | ||
onClose?: () => void; | ||
/** Callback when the disclosure is opened */ | ||
onOpen?: () => void; | ||
/** The title of the disclosure */ | ||
title?: string; | ||
} | ||
|
||
const Disclosure: React.FunctionComponent<DisclosureProps> = ({ | ||
children, | ||
className, | ||
dataTest, | ||
description, | ||
icon, | ||
isExpanded = false, | ||
isLowContrast = false, | ||
onClose, | ||
onOpen, | ||
title, | ||
children, | ||
className, | ||
dataTest, | ||
defaultExpanded = false, | ||
description, | ||
icon, | ||
isExpanded, | ||
isLowContrast = false, | ||
onClose, | ||
onOpen, | ||
title | ||
}: DisclosureProps) => { | ||
const btnRef = React.useRef<HTMLButtonElement>(null); | ||
const [expanded, setExpanded] = React.useState(isExpanded); | ||
const btnRef = React.useRef<HTMLButtonElement>(null); | ||
|
||
const { buttonProps } = useButton( | ||
{ | ||
onPress: () => { | ||
setExpanded(!expanded); | ||
}, | ||
}, | ||
btnRef, | ||
); | ||
|
||
React.useEffect(() => { | ||
setExpanded(isExpanded); | ||
}, [isExpanded]); | ||
const state = useToggleState({ | ||
defaultSelected: defaultExpanded, | ||
isSelected: isExpanded, | ||
onChange: isSelected => { | ||
if (isSelected) { | ||
onOpen?.(); | ||
} else { | ||
onClose?.(); | ||
} | ||
} | ||
|
||
React.useEffect(() => { | ||
if (expanded && onOpen) { | ||
onOpen(); | ||
} | ||
if (!expanded && onClose) { | ||
onClose(); | ||
} | ||
}, [expanded, onOpen, onClose]); | ||
}); | ||
|
||
const classes = cx('ids-disclosure', className, { | ||
'ids-disclosure--low-contrast': isLowContrast, | ||
}); | ||
const { buttonProps } = useToggleButton( | ||
{}, | ||
state, | ||
btnRef | ||
); | ||
|
||
return ( | ||
<div className={classes} data-test={dataTest}> | ||
<button | ||
{...buttonProps} | ||
ref={btnRef} | ||
className="ids-disclosure__header" | ||
aria-expanded={expanded} | ||
> | ||
{icon && <span className="ids-disclosure__header-icon">{icon}</span>} | ||
<span className="ids-disclosure__header-content"> | ||
{title && ( | ||
<span className="ids-disclosure__header-title">{title}</span> | ||
)} | ||
{description && ( | ||
<span className="ids-disclosure__header-desc">{description}</span> | ||
)} | ||
</span> | ||
{!isLowContrast && ( | ||
<ChevronDown | ||
size="medium" | ||
className="ids-disclosure__header-chevron" | ||
/> | ||
)} | ||
</button> | ||
<LazyMotion features={domAnimation} strict> | ||
<AnimatePresence initial={false}> | ||
{expanded && ( | ||
<m.div | ||
className="ids-disclosure__content" | ||
key="content" | ||
initial="collapsed" | ||
animate="open" | ||
exit="collapsed" | ||
variants={{ | ||
open: { | ||
opacity: 1, | ||
height: 'auto', | ||
overflow: 'hidden', | ||
transitionEnd: { | ||
overflow: 'visible', | ||
}, | ||
}, | ||
collapsed: { opacity: 0, height: 0, overflow: 'hidden' }, | ||
}} | ||
transition={{ duration: 0.5, ease: [0.04, 0.62, 0.23, 0.98] }} | ||
const classes = cx("ids-disclosure", className, { | ||
"ids-disclosure--low-contrast": isLowContrast | ||
}); | ||
|
||
return ( | ||
<div className={classes} data-test={dataTest}> | ||
<button | ||
{...buttonProps} | ||
ref={btnRef} | ||
className="ids-disclosure__header" | ||
aria-expanded={state.isSelected} | ||
> | ||
{children} | ||
</m.div> | ||
)} | ||
</AnimatePresence> | ||
</LazyMotion> | ||
</div> | ||
); | ||
{icon && <span className="ids-disclosure__header-icon">{icon}</span>} | ||
<span className="ids-disclosure__header-content"> | ||
{title && ( | ||
<span className="ids-disclosure__header-title">{title}</span> | ||
)} | ||
{description && ( | ||
<span className="ids-disclosure__header-desc">{description}</span> | ||
)} | ||
</span> | ||
{!isLowContrast && ( | ||
<ChevronDown | ||
size="medium" | ||
className="ids-disclosure__header-chevron" | ||
/> | ||
)} | ||
</button> | ||
<LazyMotion features={domAnimation} strict> | ||
<AnimatePresence initial={false}> | ||
{state.isSelected && ( | ||
<m.div | ||
className="ids-disclosure__content" | ||
key="content" | ||
initial="collapsed" | ||
animate="open" | ||
exit="collapsed" | ||
variants={{ | ||
open: { | ||
opacity: 1, | ||
height: "auto", | ||
overflow: "hidden", | ||
transitionEnd: { | ||
overflow: "visible" | ||
} | ||
}, | ||
collapsed: { opacity: 0, height: 0, overflow: "hidden" } | ||
}} | ||
transition={{ duration: 0.5, ease: [0.04, 0.62, 0.23, 0.98] }} | ||
> | ||
{children} | ||
</m.div> | ||
)} | ||
</AnimatePresence> | ||
</LazyMotion> | ||
</div> | ||
); | ||
}; | ||
|
||
export default Disclosure; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters