diff --git a/example/src/Examples/ListAccordionExample.tsx b/example/src/Examples/ListAccordionExample.tsx index 58c3841de5..ac2ab35771 100644 --- a/example/src/Examples/ListAccordionExample.tsx +++ b/example/src/Examples/ListAccordionExample.tsx @@ -56,6 +56,17 @@ const ListAccordionExample = () => { /> + + + } + title="Expandable list item" + expandDirection="upwards" + > + + + + ); }; diff --git a/example/src/Examples/ListAccordionGroupExample.tsx b/example/src/Examples/ListAccordionGroupExample.tsx index 51861858bb..8aa81bd001 100644 --- a/example/src/Examples/ListAccordionGroupExample.tsx +++ b/example/src/Examples/ListAccordionGroupExample.tsx @@ -71,6 +71,25 @@ const ListAccordionGroupExample = () => { + + + } + title="Expandable list item" + id="1" + > + + + + } + title="Expandable list item 2" + id="2" + > + + + + ); }; diff --git a/src/components/List/ListAccordion.tsx b/src/components/List/ListAccordion.tsx index 75505c7367..aecf6fa58c 100644 --- a/src/components/List/ListAccordion.tsx +++ b/src/components/List/ListAccordion.tsx @@ -136,6 +136,11 @@ export type Props = { * This can be used to enlarge the touchable area beyond the visible component. */ hitSlop?: TouchableRippleProps['hitSlop']; + /** + * Sets expansion direction for the accordion. + * Can be 'downwards' (default) or 'upwards'. + */ + expandDirection?: 'downwards' | 'upwards'; }; /** @@ -202,6 +207,7 @@ const ListAccordion = ({ titleMaxFontSizeMultiplier, descriptionMaxFontSizeMultiplier, hitSlop, + expandDirection: expandDirectionProp, }: Props) => { const theme = useInternalTheme(themeOverrides); const [expanded, setExpanded] = React.useState( @@ -252,8 +258,34 @@ const ListAccordion = ({ groupContext && id !== undefined ? () => groupContext.onAccordionPress(id) : handlePressAction; + + const expandDirection = + expandDirectionProp || groupContext?.expandDirection || 'downwards'; + + const expandedContent = isExpanded + ? React.Children.map(children, (child) => { + if ( + left && + React.isValidElement(child) && + !child.props.left && + !child.props.right + ) { + return React.cloneElement(child, { + style: [ + theme.isV3 ? styles.childV3 : styles.child, + child.props.style, + ], + theme, + }); + } + + return child; + }) + : null; + return ( + {expandDirection === 'upwards' ? expandedContent : null} - {isExpanded - ? React.Children.map(children, (child) => { - if ( - left && - React.isValidElement(child) && - !child.props.left && - !child.props.right - ) { - return React.cloneElement(child, { - style: [ - theme.isV3 ? styles.childV3 : styles.child, - child.props.style, - ], - theme, - }); - } - - return child; - }) - : null} + {expandDirection === 'downwards' ? expandedContent : null} ); }; diff --git a/src/components/List/ListAccordionGroup.tsx b/src/components/List/ListAccordionGroup.tsx index 15e148ae6e..a9b2596b86 100644 --- a/src/components/List/ListAccordionGroup.tsx +++ b/src/components/List/ListAccordionGroup.tsx @@ -13,11 +13,17 @@ export type Props = { * React elements containing list accordions */ children: React.ReactNode; + /** + * Sets expansion direction for all accordions in the group. + * Can be 'downwards' (default) or 'upwards'. + */ + expandDirection?: 'downwards' | 'upwards'; }; export type ListAccordionGroupContextType = { expandedId: string | number | undefined; onAccordionPress: (expandedId: string | number) => void; + expandDirection?: 'downwards' | 'upwards'; } | null; export const ListAccordionGroupContext = @@ -60,6 +66,7 @@ const ListAccordionGroup = ({ expandedId: expandedIdProp, onAccordionPress, children, + expandDirection, }: Props) => { const [expandedId, setExpandedId] = React.useState< string | number | undefined @@ -76,6 +83,7 @@ const ListAccordionGroup = ({ value={{ expandedId: expandedIdProp || expandedId, // component can be controlled or uncontrolled onAccordionPress: onAccordionPress || onAccordionPressDefault, + expandDirection, }} > {children}