From 41a7ba727aa346a641edef3d6abcca0003639baa Mon Sep 17 00:00:00 2001 From: Chris Cedrone Date: Thu, 21 Sep 2023 14:41:02 -0400 Subject: [PATCH] fixing keyboard navigation, added a prop to Accordion to accommodate, amendments per Laura's review, still working on tests --- .../components/Accordion/AccordionButton.tsx | 13 ++++++++-- .../components/Dropdown/Dropdown.stories.tsx | 2 +- .../src/components/Dropdown/Dropdown.tsx | 1 + .../components/Dropdown/DropdownContent.tsx | 6 +++-- .../Dropdown/DropdownExpandableMenuButton.tsx | 21 +++++++++------- .../Dropdown/DropdownExpandableMenuGroup.tsx | 24 +++++++++---------- .../Dropdown/DropdownExpandableMenuItem.tsx | 4 ++-- .../Dropdown/DropdownExpandableMenuPanel.tsx | 6 ++--- .../components/Dropdown/DropdownMenuItem.tsx | 12 +++++----- packages/react-magma-dom/src/index.ts | 1 + 10 files changed, 54 insertions(+), 36 deletions(-) diff --git a/packages/react-magma-dom/src/components/Accordion/AccordionButton.tsx b/packages/react-magma-dom/src/components/Accordion/AccordionButton.tsx index 3d9b353a3..db3a2d399 100644 --- a/packages/react-magma-dom/src/components/Accordion/AccordionButton.tsx +++ b/packages/react-magma-dom/src/components/Accordion/AccordionButton.tsx @@ -23,10 +23,12 @@ export interface AccordionButtonProps /** * @internal */ + hasCustomArray?: boolean; theme?: ThemeInterface; } const StyledButton = styled.button<{ + hasCustomArray?: boolean; isInverse?: boolean; isExpanded?: boolean; }>` @@ -90,7 +92,13 @@ export const AccordionButton = React.forwardRef< HTMLButtonElement, AccordionButtonProps >((props, forwardedRef) => { - const { children, testId, isInverse: isInverseProp, ...rest } = props; + const { + children, + testId, + hasCustomArray, + isInverse: isInverseProp, + ...rest + } = props; const theme = React.useContext(ThemeContext); const isInverse = useIsInverse(isInverseProp); @@ -122,11 +130,12 @@ export const AccordionButton = React.forwardRef< aria-expanded={Boolean(isExpanded)} data-testid={testId} disabled={isDisabled} + hasCustomArray={hasCustomArray} id={buttonId} isExpanded={isExpanded} isInverse={isInverse} onClick={handleClick} - onKeyDown={handleKeyDown} + onKeyDown={hasCustomArray ? null : handleKeyDown} ref={ref} theme={theme} > diff --git a/packages/react-magma-dom/src/components/Dropdown/Dropdown.stories.tsx b/packages/react-magma-dom/src/components/Dropdown/Dropdown.stories.tsx index a0c614302..1e7962ed6 100644 --- a/packages/react-magma-dom/src/components/Dropdown/Dropdown.stories.tsx +++ b/packages/react-magma-dom/src/components/Dropdown/Dropdown.stories.tsx @@ -448,7 +448,7 @@ export const ExpandableItems = args => { export const ExpandableItemsWithIcons = args => { return ( - + Expandable Items Dropdown diff --git a/packages/react-magma-dom/src/components/Dropdown/Dropdown.tsx b/packages/react-magma-dom/src/components/Dropdown/Dropdown.tsx index 4c1eba91b..3681ec996 100644 --- a/packages/react-magma-dom/src/components/Dropdown/Dropdown.tsx +++ b/packages/react-magma-dom/src/components/Dropdown/Dropdown.tsx @@ -174,6 +174,7 @@ export const Dropdown = React.forwardRef( function handleKeyDown(event: React.KeyboardEvent) { if (event.key === 'Escape') { + event.nativeEvent.stopImmediatePropagation(); closeDropdown(event); } diff --git a/packages/react-magma-dom/src/components/Dropdown/DropdownContent.tsx b/packages/react-magma-dom/src/components/Dropdown/DropdownContent.tsx index 96a87b2b4..364a02cb2 100644 --- a/packages/react-magma-dom/src/components/Dropdown/DropdownContent.tsx +++ b/packages/react-magma-dom/src/components/Dropdown/DropdownContent.tsx @@ -117,7 +117,7 @@ export const DropdownContent = React.forwardRef< let hasItemChildren = false; - // Default styling for Expandable Menus to override the max-height used for regular dropdowns + // For Expandable Dropdowns that don't require a max-height let hasExpandableItems = false; React.Children.forEach(children, (child: any) => { @@ -144,7 +144,9 @@ export const DropdownContent = React.forwardRef< maxHeight={context.maxHeight} ref={ref} style={ - hasExpandableItems ? { maxHeight: 'inherit', overflow: 'hidden' } : null + hasExpandableItems + ? { maxHeight: 'inherit', overflow: 'hidden' } + : props.style } tabIndex={-1} testId={testId || 'dropdownContent'} diff --git a/packages/react-magma-dom/src/components/Dropdown/DropdownExpandableMenuButton.tsx b/packages/react-magma-dom/src/components/Dropdown/DropdownExpandableMenuButton.tsx index 58439ea4d..3e5b5d4e1 100644 --- a/packages/react-magma-dom/src/components/Dropdown/DropdownExpandableMenuButton.tsx +++ b/packages/react-magma-dom/src/components/Dropdown/DropdownExpandableMenuButton.tsx @@ -5,7 +5,7 @@ import { IconWrapper, menuBackground } from './DropdownMenuItem'; import { IconProps } from 'react-magma-icons'; import { ThemeContext } from '../../theme/ThemeContext'; import { DropdownContext } from './Dropdown'; -import { DropdownExpandableContext } from './DropdownExpandableMenuGroup'; +import { DropdownExpandableMenuGroupContext } from './DropdownExpandableMenuGroup'; import { useForkedRef } from '../../utils'; export interface DropdownExpandableMenuButtonProps @@ -15,12 +15,13 @@ export interface DropdownExpandableMenuButtonProps } const StyledAccordionButton = styled(AccordionButton)<{ - hasIcon?: boolean; + hasCustomArray?: boolean; + expandableMenuButtonHasIcon?: boolean; icon?: React.ReactElement; }>` font-weight: 400; padding: ${props => - !props.icon && props.hasIcon + !props.icon && props.expandableMenuButtonHasIcon ? `${props.theme.spaceScale.spacing03} ${props.theme.spaceScale.spacing05} ${props.theme.spaceScale.spacing03} ${props.theme.spaceScale.spacing11}` : `${props.theme.spaceScale.spacing03} ${props.theme.spaceScale.spacing05}`}; margin: 0; @@ -36,18 +37,19 @@ const StyledAccordionButton = styled(AccordionButton)<{ const StyledIconWrapper = styled(IconWrapper)` justify-content: center; - /* align-items: center; */ `; export const DropdownExpandableMenuButton = React.forwardRef< HTMLDivElement, DropdownExpandableMenuButtonProps >((props, forwardedRef) => { - const { children, icon, testId, ...other } = props; + const { children, hasCustomArray, icon, testId, ...other } = props; const theme = React.useContext(ThemeContext); const context = React.useContext(DropdownContext); - const expandableContext = React.useContext(DropdownExpandableContext); + const expandableContext = React.useContext( + DropdownExpandableMenuGroupContext + ); const ownRef = React.useRef(); const ref = useForkedRef(forwardedRef, ownRef); @@ -60,9 +62,12 @@ export const DropdownExpandableMenuButton = React.forwardRef< diff --git a/packages/react-magma-dom/src/components/Dropdown/DropdownExpandableMenuGroup.tsx b/packages/react-magma-dom/src/components/Dropdown/DropdownExpandableMenuGroup.tsx index efe2d40aa..a4ae66db9 100644 --- a/packages/react-magma-dom/src/components/Dropdown/DropdownExpandableMenuGroup.tsx +++ b/packages/react-magma-dom/src/components/Dropdown/DropdownExpandableMenuGroup.tsx @@ -3,19 +3,17 @@ import styled from '../../theme/styled'; import { Accordion, AccordionProps } from '../Accordion'; import { DropdownContext } from './Dropdown'; -const StyledAccordion = styled(Accordion)<{ - testId?: string; -}>` +const StyledAccordion = styled(Accordion)<{}>` border: none; `; -export interface DropdownExpandableContext { - hasIcon?: boolean; +export interface DropdownExpandableMenuGroupContextInterface { + expandableMenuButtonHasIcon?: boolean; isExpandablePanel?: boolean; } -export const DropdownExpandableContext = - React.createContext({}); +export const DropdownExpandableMenuGroupContext = + React.createContext({}); export const DropdownExpandableMenuGroup = React.forwardRef< HTMLDivElement, @@ -25,7 +23,7 @@ export const DropdownExpandableMenuGroup = React.forwardRef< const context = React.useContext(DropdownContext); - let hasIcon = false; + let expandableMenuButtonHasIcon = false; let isExpandablePanel = false; React.Children.forEach(children, (child: any) => { @@ -33,7 +31,7 @@ export const DropdownExpandableMenuGroup = React.forwardRef< React.Children.forEach(child.props.children, (c: any) => { if (c.type?.displayName === 'DropdownExpandableMenuButton') { if (c.props.icon) { - hasIcon = true; + expandableMenuButtonHasIcon = true; return; } } @@ -45,16 +43,18 @@ export const DropdownExpandableMenuGroup = React.forwardRef< }); return ( - + {children} - + ); }); diff --git a/packages/react-magma-dom/src/components/Dropdown/DropdownExpandableMenuItem.tsx b/packages/react-magma-dom/src/components/Dropdown/DropdownExpandableMenuItem.tsx index 112cf5cbd..50e244e59 100644 --- a/packages/react-magma-dom/src/components/Dropdown/DropdownExpandableMenuItem.tsx +++ b/packages/react-magma-dom/src/components/Dropdown/DropdownExpandableMenuItem.tsx @@ -21,11 +21,11 @@ export interface DropdownExpandableMenuItemProps extends AccordionItemProps { export const DropdownExpandableMenuItem = React.forwardRef< HTMLDivElement, DropdownExpandableMenuItemProps ->(props => { +>((props, ref) => { const { children, disabled, testId, ...other } = props; return ( - + {children} ); diff --git a/packages/react-magma-dom/src/components/Dropdown/DropdownExpandableMenuPanel.tsx b/packages/react-magma-dom/src/components/Dropdown/DropdownExpandableMenuPanel.tsx index 6b079ec8c..bb640e243 100644 --- a/packages/react-magma-dom/src/components/Dropdown/DropdownExpandableMenuPanel.tsx +++ b/packages/react-magma-dom/src/components/Dropdown/DropdownExpandableMenuPanel.tsx @@ -12,7 +12,7 @@ const StyledAccordionPanel = styled(AccordionPanel)` export const DropdownExpandableMenuPanel = React.forwardRef< HTMLDivElement, DropdownExpandableMenuPanelProps ->(props => { +>((props, ref) => { const { children, testId, ...other } = props; React.Children.map(children, child => { @@ -22,7 +22,7 @@ export const DropdownExpandableMenuPanel = React.forwardRef< console.warn( ` -------------------------------------------------------------------------------------------------------- - Only one group level is supported, anything nested two levels or more isn't accounted for in the styling + React Magma Warning: Only one group level is supported for Expandable Dropdowns, anything nested two levels or more isn't accounted for in the styling -------------------------------------------------------------------------------------------------------- ` ); @@ -30,7 +30,7 @@ export const DropdownExpandableMenuPanel = React.forwardRef< }); return ( - + {children} ); diff --git a/packages/react-magma-dom/src/components/Dropdown/DropdownMenuItem.tsx b/packages/react-magma-dom/src/components/Dropdown/DropdownMenuItem.tsx index 966fbad21..dfbb665db 100644 --- a/packages/react-magma-dom/src/components/Dropdown/DropdownMenuItem.tsx +++ b/packages/react-magma-dom/src/components/Dropdown/DropdownMenuItem.tsx @@ -7,7 +7,7 @@ import { DropdownContext } from './Dropdown'; import { IconProps, CheckIcon } from 'react-magma-icons'; import { transparentize } from 'polished'; import { Omit, useForkedRef } from '../../utils'; -import { DropdownExpandableContext } from './DropdownExpandableMenuGroup'; +import { DropdownExpandableMenuGroupContext } from './DropdownExpandableMenuGroup'; export interface DropdownMenuItemProps extends Omit, 'onClick'> { @@ -63,7 +63,7 @@ export function menuBackground(props) { function menuItemPadding(props) { //For DropdownExpandableMenu styling with an icon - if (props.hasIcon && props.isExpandablePanel) { + if (props.expandableMenuButtonHasIcon && props.isExpandablePanel) { return `${props.theme.spaceScale.spacing03} ${props.theme.spaceScale.spacing05} ${props.theme.spaceScale.spacing03} 72px`; } //For DropdownExpandableMenu styling without an icon @@ -111,7 +111,7 @@ export const MenuItemStyles = props => { const StyledItem = styled.div<{ as?: string; disabled?: boolean; - hasIcon?: boolean; + expandableMenuButtonHasIcon?: boolean; isExpandablePanel?: boolean; isFixedWidth?: boolean; @@ -146,7 +146,7 @@ export const DropdownMenuItem = React.forwardRef< const theme = React.useContext(ThemeContext); const context = React.useContext(DropdownContext); - const expandableContext = React.useContext(DropdownExpandableContext); + const menuGroupContext = React.useContext(DropdownExpandableMenuGroupContext); const ref = useForkedRef(forwardedRef, ownRef); @@ -195,8 +195,8 @@ export const DropdownMenuItem = React.forwardRef< {...other} aria-disabled={disabled} disabled={disabled} - hasIcon={expandableContext.hasIcon} - isExpandablePanel={expandableContext.isExpandablePanel} + expandableMenuButtonHasIcon={menuGroupContext.expandableMenuButtonHasIcon} + isExpandablePanel={menuGroupContext.isExpandablePanel} isFixedWidth={context.isFixedWidth} isInactive={isInactive} isInverse={context.isInverse} diff --git a/packages/react-magma-dom/src/index.ts b/packages/react-magma-dom/src/index.ts index 23a59623a..1597ee444 100644 --- a/packages/react-magma-dom/src/index.ts +++ b/packages/react-magma-dom/src/index.ts @@ -49,6 +49,7 @@ export { Container, ContainerProps } from './components/Container'; export { Datagrid, DatagridProps } from './components/Datagrid'; export { DatePicker, DatePickerProps } from './components/DatePicker'; export { + Dropdown, DropdownAlignment, DropdownDropDirection, DropdownProps,