From c981a8b0449a51e709356ae0a0e1a72ac3dcb98d Mon Sep 17 00:00:00 2001 From: vicky-comeau <110498164+vicky-comeau@users.noreply.github.com> Date: Tue, 5 Dec 2023 09:12:30 -0500 Subject: [PATCH] Fix: [IGL-100] Disclosure isExpanded issues (#584) * Fix: [IGL-100] Disclosure isExpanded issues --------- Co-authored-by: Franck Gaudin --- .changeset/fuzzy-rockets-hang.md | 12 + packages/Disclosure/package.json | 3 +- .../Disclosure/src/Disclosure.stories.tsx | 62 ++++- packages/Disclosure/src/Disclosure.tsx | 227 +++++++++--------- .../__snapshots__/Disclosure.test.tsx.snap | 1 + 5 files changed, 186 insertions(+), 119 deletions(-) create mode 100644 .changeset/fuzzy-rockets-hang.md diff --git a/.changeset/fuzzy-rockets-hang.md b/.changeset/fuzzy-rockets-hang.md new file mode 100644 index 00000000..5874212c --- /dev/null +++ b/.changeset/fuzzy-rockets-hang.md @@ -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. \ No newline at end of file diff --git a/packages/Disclosure/package.json b/packages/Disclosure/package.json index 6374eb83..71752d32 100644 --- a/packages/Disclosure/package.json +++ b/packages/Disclosure/package.json @@ -28,7 +28,8 @@ "@hopper-ui/tokens": "^3.1.0", "classnames": "^2.3.2", "framer-motion": "^6.5.1", - "react-aria": "^3.30.0" + "react-aria": "^3.30.0", + "react-stately": "^3.28.0" }, "devDependencies": { "@igloo-ui/button": "^0.7.1" diff --git a/packages/Disclosure/src/Disclosure.stories.tsx b/packages/Disclosure/src/Disclosure.stories.tsx index 908abe98..2920a27a 100644 --- a/packages/Disclosure/src/Disclosure.stories.tsx +++ b/packages/Disclosure/src/Disclosure.stories.tsx @@ -56,7 +56,7 @@ export const Expanded = { <>
- + setIsExpanded(true)} onClose={() => setIsExpanded(false)} /> ); }, @@ -67,16 +67,14 @@ export const Expanded = { ), title: 'Expanded', - icon: , - onOpen: () => console.log('onOpen'), - onClose: () => console.log('onClose'), + icon: }, }; export const LowContrast = { args: { - isExpanded: true, + defaultExpanded: true, isLowContrast: true, children: (
@@ -88,3 +86,57 @@ export const LowContrast = { icon: , }, }; + + +const data = [ + { + id: 1, + title: "Send Good Vibes", + description: + "Celebrate a team member with a thoughtful card that makes their day", + }, + { + id: 2, + title: "Send Good Vibes 2", + description: + "Celebrate a team member with a thoughtful card that makes their day", + }, +]; + +export const VerticallyStacked = { + render: () => { + const [selectedIndex, setSelectedIndex] = React.useState(null); + + const handleDisclosureOpen = (id: number) => { + setSelectedIndex(id); + }; + + const handleDisclosureClose = () => { + setSelectedIndex(null); + }; + + + return ( +
+ {data.map((item, index) => { + const isExpanded = selectedIndex === index; + + return ( + handleDisclosureOpen(index)} + onClose={() => handleDisclosureClose()} + > +
+ +
+
+ ); + })} +
+ ) + } +} diff --git a/packages/Disclosure/src/Disclosure.tsx b/packages/Disclosure/src/Disclosure.tsx index 2f808190..b41ecc11 100644 --- a/packages/Disclosure/src/Disclosure.tsx +++ b/packages/Disclosure/src/Disclosure.tsx @@ -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 = ({ - 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(null); - const [expanded, setExpanded] = React.useState(isExpanded); + const btnRef = React.useRef(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 ( -
- - - - {expanded && ( - +
- ); + {icon && {icon}} + + {title && ( + {title} + )} + {description && ( + {description} + )} + + {!isLowContrast && ( + + )} + + + + {state.isSelected && ( + + {children} + + )} + + +
+ ); }; export default Disclosure; diff --git a/packages/Disclosure/src/__snapshots__/Disclosure.test.tsx.snap b/packages/Disclosure/src/__snapshots__/Disclosure.test.tsx.snap index 8ffbaf79..7aa70287 100644 --- a/packages/Disclosure/src/__snapshots__/Disclosure.test.tsx.snap +++ b/packages/Disclosure/src/__snapshots__/Disclosure.test.tsx.snap @@ -8,6 +8,7 @@ exports[`Disclosure It should render a snapshot 1`] = ` >