diff --git a/src/components/AvatarMeetingsListItem/AvatarMeetingsListItem.unit.test.tsx.snap b/src/components/AvatarMeetingsListItem/AvatarMeetingsListItem.unit.test.tsx.snap index dac3196d5..b0788788b 100644 --- a/src/components/AvatarMeetingsListItem/AvatarMeetingsListItem.unit.test.tsx.snap +++ b/src/components/AvatarMeetingsListItem/AvatarMeetingsListItem.unit.test.tsx.snap @@ -22,6 +22,7 @@ exports[` snapshot should match snapshot 1`] = ` className="md-avatar-meetings-list-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-padded={false} data-shape="isPilled" @@ -143,6 +144,7 @@ exports[` snapshot should match snapshot with avatarPr className="md-avatar-meetings-list-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-padded={false} data-shape="isPilled" @@ -302,6 +304,7 @@ exports[` snapshot should match snapshot with classNam className="example-class md-avatar-meetings-list-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-padded={false} data-shape="isPilled" @@ -422,6 +425,7 @@ exports[` snapshot should match snapshot with displayM className="md-avatar-meetings-list-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-padded={false} data-shape="isPilled" @@ -620,6 +624,7 @@ exports[` snapshot should match snapshot with displayM className="md-avatar-meetings-list-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-padded={false} data-shape="isPilled" @@ -823,6 +828,7 @@ exports[` snapshot should match snapshot with displayM className="md-avatar-meetings-list-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-padded={false} data-shape="isPilled" @@ -1022,6 +1028,7 @@ exports[` snapshot should match snapshot with firstLin className="md-avatar-meetings-list-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-padded={false} data-shape="isPilled" @@ -1141,6 +1148,7 @@ exports[` snapshot should match snapshot with id 1`] = className="md-avatar-meetings-list-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-padded={false} data-shape="isPilled" @@ -1258,6 +1266,7 @@ exports[` snapshot should match snapshot with schedule className="md-avatar-meetings-list-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-padded={false} data-shape="isPilled" @@ -1404,6 +1413,7 @@ exports[` snapshot should match snapshot with schedule className="md-avatar-meetings-list-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-padded={false} data-shape="isPilled" @@ -1550,6 +1560,7 @@ exports[` snapshot should match snapshot with schedule className="md-avatar-meetings-list-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-padded={false} data-shape="isPilled" @@ -1696,6 +1707,7 @@ exports[` snapshot should match snapshot with schedule className="md-avatar-meetings-list-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-padded={false} data-shape="isPilled" @@ -1842,6 +1854,7 @@ exports[` snapshot should match snapshot with secondLi className="md-avatar-meetings-list-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-padded={false} data-shape="isPilled" @@ -1977,6 +1990,7 @@ exports[` snapshot should match snapshot with style 1` className="md-avatar-meetings-list-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-padded={false} data-shape="isPilled" diff --git a/src/components/ComboBox/ComboBox.constants.ts b/src/components/ComboBox/ComboBox.constants.ts index 046baec9e..259cd1593 100644 --- a/src/components/ComboBox/ComboBox.constants.ts +++ b/src/components/ComboBox/ComboBox.constants.ts @@ -1,50 +1,51 @@ -const CLASS_PREFIX = 'md-combo-box'; +import { FocusStrategy } from '@react-types/shared'; +import { Direction } from './ComboBox.types'; +import { InferredIconName } from '../Icon/Icon.types'; -const DEFAULTS = { - WIDTH:'16.25rem', - PLACEHOLDER:'', - NO_RESULT_TEXT:'No results found', - SHOULD_FILTER_ON_ARROW_BUTTON:true, - ERROR:false, - SELECTEDKEY:'', - DISABLEDKEYS:[], -}; +const CLASS_PREFIX = 'md-combo-box'; const STYLE = { description: `${CLASS_PREFIX}-description`, label: `${CLASS_PREFIX}-label`, wrapper: `${CLASS_PREFIX}-wrapper`, - inputSection: `${CLASS_PREFIX}-input-section`, + trigger: `${CLASS_PREFIX}-trigger`, input: `${CLASS_PREFIX}-input`, - divider: `${CLASS_PREFIX}-divider`, button: `${CLASS_PREFIX}-button`, - arrowIcon: `${CLASS_PREFIX}-arrow-icon`, - selectionPosition: `${CLASS_PREFIX}-selection-position`, - selectionContainer: `${CLASS_PREFIX}-selection-container`, - selection: `${CLASS_PREFIX}-selection`, - noResultText: `${CLASS_PREFIX}-no-result-text`, + listBox: `${CLASS_PREFIX}-listbox`, + popover: `${CLASS_PREFIX}-popover`, }; const KEYS = { - INPUT_SEARCH_NO_RESULT: 'input_search_no_result', + NO_RESULT: 'no_result', }; -const ELEMENT = { - PROPS: { - SELECTION_CONTAINER_MAX_HEIGHT:244, - }, +type IconName = { + [key: string]: InferredIconName; +}; + +const ICON: IconName = { + ARROW_UP: 'arrow-down', + ARROW_DOWN: 'arrow-down', +}; + +const DIRECTIONS: Record = { + bottom: 'bottom', + top: 'top', +}; + +const DEFAULTS = { + DIRECTION: DIRECTIONS.bottom, + FOCUS_STRATEGY: 'first' as FocusStrategy, }; const EVENT = { - KEY:{ - KEYCODE:{ - ESCAPE: 'Escape', - ENTER: 'Enter', - TAB: 'Tab', - ARROW_DOWN: 'ArrowDown', - ARROW_UP: 'ArrowUp', - } - } + KEY: { + ESCAPE: 'Escape', + ENTER: 'Enter', + TAB: 'Tab', + ARROW_DOWN: 'ArrowDown', + ARROW_UP: 'ArrowUp', + }, }; -export{STYLE,DEFAULTS,KEYS,ELEMENT,EVENT}; +export { STYLE, KEYS, EVENT, ICON, DEFAULTS }; diff --git a/src/components/ComboBox/ComboBox.documentation.mdx b/src/components/ComboBox/ComboBox.documentation.mdx index e2ca622fa..8d8703b44 100644 --- a/src/components/ComboBox/ComboBox.documentation.mdx +++ b/src/components/ComboBox/ComboBox.documentation.mdx @@ -43,28 +43,18 @@ and the items within the section accept an iterable list of options. import { Item } from '@react-stately/collections'; const comboBoxGroups = [ - { - items: [ - { key: 'key1', label: 'item1' }, - { key: 'key2', label: 'item2' }, - { key: 'key3', label: 'item3' }, - { key: 'key4', label: 'item4' }, - ] - }, + { key: 'key1', label: 'item1' }, + { key: 'key2', label: 'item2' }, + { key: 'key3', label: 'item3' }, + { key: 'key4', label: 'item4' }, ] - console.log} comboBoxGroups={comboBoxGroups}> - {(sectionGroup) => { + console.log} defaultItems={comboBoxGroups}> + {(menuItem) => { return ( -
- {sectionGroup.items.map((menuItem) => { - return ( - -
{menuItem.label}
-
- ); - })} -
+ +
{menuItem.label}
+
); }}
@@ -120,7 +110,7 @@ const comboBoxGroups = [
{group.items.map((menuItem: IItem) => { return ( - +
{menuItem.label}
); diff --git a/src/components/ComboBox/ComboBox.stories.args.ts b/src/components/ComboBox/ComboBox.stories.args.ts index 06b35cfe6..f17544c4d 100644 --- a/src/components/ComboBox/ComboBox.stories.args.ts +++ b/src/components/ComboBox/ComboBox.stories.args.ts @@ -1,149 +1,135 @@ import { commonStyles } from '../../storybook/helper.stories.argtypes'; -import { ComboBox_CONSTANTS as CONSTANTS } from '.'; - export default { ...commonStyles, - width: { + listboxWidth: { + defaultValue: undefined, description: - 'To override the ComboBox container and selection list width.', + 'To override the list box width. NOTE: if set, the popover strategy will be set to "fixed". To style the list box without applying fixed popover strategy, pass in className instead', control: { type: 'text' }, table: { type: { summary: 'string', }, defaultValue: { - summary: CONSTANTS.DEFAULTS.WIDTH, - }, - }, - }, - error: { - description: 'Sets whether the ComboBox is in error state.', - control: { type: 'boolean' }, - table: { - type: { - summary: 'boolean', - }, - defaultValue: { - summary: false, + summary: undefined, }, }, }, placeholder: { - description: 'Text to display inside the input when there is no inputValue or item selected.', + description: + 'From [AriaComboBoxOptions](https://react-spectrum.adobe.com/react-aria/useComboBox.html). Temporary text that occupies the text input when it is empty.', control: { type: 'text' }, table: { - category: 'React Aria - Input', type: { summary: 'string', }, - defaultValue: { - summary: CONSTANTS.DEFAULTS.PLACEHOLDER, - }, }, }, - onInputChange: { - defaultValue: undefined, + selectedKey: { description: - 'Handler that is called when the InputValue changes.', - control: { type: 'function' }, + 'From [AriaComboBoxOptions](https://react-spectrum.adobe.com/react-aria/useComboBox.html). The currently selected key in the collection (controlled).', + control: { type: 'text' }, table: { - category: 'React Aria - Input', + category: 'React Aria - Select', type: { - summary: '(event: InputEvent) => void', - }, - defaultValue: { - summary: 'undefined', + summary: 'React.Key', }, }, }, - onArrowButtonPress: { - defaultValue: undefined, + defaultSelectedKey: { description: - 'Handler that is called when the press is released over the arrowButton.', - control: { type: 'function' }, + 'From [AriaComboBoxOptions](https://react-spectrum.adobe.com/react-aria/useComboBox.html). The currently selected key in the collection (uncontrolled).', + control: { type: 'text' }, table: { - category: 'React Aria - Button', + category: 'React Aria - Select', type: { - summary: '(event: PressEvent) => void', - }, - defaultValue: { - summary: 'undefined', + summary: 'React.Key', }, - }, + }, }, - shouldFilterOnArrowButton: { + disabledKeys: { description: - 'This property represents whether to filter based on the input value when click the arrowButton.', - control: { type: 'boolean' }, + 'From [AriaComboBoxOptions](https://react-spectrum.adobe.com/react-aria/useComboBox.html). The item keys that are disabled. These items cannot be selected, focused, or otherwise interacted with.', + control: { type: 'array' }, table: { - category: 'React Aria - Button', + category: 'React Aria - Select', type: { - summary: 'boolean', + summary: 'React.Key[]', }, defaultValue: { - summary: CONSTANTS.DEFAULTS.SHOULD_FILTER_ON_ARROW_BUTTON, + summary: '[]', }, - }, + }, }, - selectedKey: { + items: { description: - 'It also affects the value of the input (displayed as the label of the corresponding item.', - control: { type: 'text' }, + 'From [AriaComboBoxOptions](https://react-spectrum.adobe.com/react-aria/useComboBox.html). The list of ComboBox items (controlled).', + control: { type: 'array' }, table: { category: 'React Aria - Select', type: { - summary: 'React.Key', + summary: 'Array', }, defaultValue: { - summary: CONSTANTS.DEFAULTS.SELECTEDKEY, + summary: 'undefined', }, }, }, - disabledKeys: { + defaultItems: { description: - 'List with disabled keys. (They must be exact type as the key)', + 'From [AriaComboBoxOptions](https://react-spectrum.adobe.com/react-aria/useComboBox.html). The list of ComboBox items (uncontrolled).', control: { type: 'array' }, table: { category: 'React Aria - Select', type: { - summary: 'React.Key[]', + summary: 'Array', }, defaultValue: { - summary: '[]', + summary: 'undefined', }, }, }, - comboBoxGroups: { + noResultLabel: { + description: 'Text to display inside the list when there is no results.', + control: { type: 'text' }, + table: { + type: { + summary: 'string', + }, + }, + }, + label: { + defaultValue: undefined, description: - 'The options for this selection list element.', - control: { type: 'array' }, + 'From [AriaComboBoxOptions](https://react-spectrum.adobe.com/react-aria/useComboBox.html). Text displayed on top of the element.', + control: { type: 'text' }, table: { - category: 'React Aria - Select', type: { - summary: 'IComboBoxGroup[]', + summary: 'string', }, defaultValue: { - summary: 'undefined', + summary: undefined, }, }, }, - noResultText: { - description: 'Text to display inside the dropdown when there is no results.', + description: { + defaultValue: undefined, + description: + 'From [AriaComboBoxOptions](https://react-spectrum.adobe.com/react-aria/useComboBox.html). Description associated with this component. Appears below the title.', control: { type: 'text' }, table: { - category: 'React Aria - Select', type: { summary: 'string', }, defaultValue: { - summary: CONSTANTS.DEFAULTS.NO_RESULT_TEXT, + summary: undefined, }, }, }, onSelectionChange: { description: - 'Handler that is called when an item is selected. (if the selected item matches the selectedKey, the parameter is undefined)', + 'From [AriaComboBoxOptions](https://react-spectrum.adobe.com/react-aria/useComboBox.html). Handler that is called when the selection changes.', control: { type: 'function' }, table: { category: 'React Aria - Select', @@ -155,12 +141,11 @@ export default { }, }, }, - openStateChange: { + onOpenChange: { description: - 'Handler that is called when the selection list is expanded or collapsed.', + 'From [AriaComboBoxOptions](https://react-spectrum.adobe.com/react-aria/useComboBox.html). Method that is called when the open state of the menu changes. Returns the new open state and the action that caused the opening of the menu.', control: { type: 'function' }, table: { - category: 'React Aria - Select', type: { summary: '(isOpen: boolean) => void', }, @@ -172,9 +157,8 @@ export default { children: { description: 'Provides the items nodes for this selection list element.', table: { - category: 'React Aria - Select', type: { - summary: 'CollectionChildren', + summary: 'Iterable', }, defaultValue: { summary: 'undefined', diff --git a/src/components/ComboBox/ComboBox.stories.tsx b/src/components/ComboBox/ComboBox.stories.tsx index f553534f1..85ab697bf 100644 --- a/src/components/ComboBox/ComboBox.stories.tsx +++ b/src/components/ComboBox/ComboBox.stories.tsx @@ -13,7 +13,6 @@ import { Template } from '../../storybook/helper.stories.templates'; import { IComboBoxGroup, IComboBoxItem, Props } from './ComboBox.types'; import OverlayAlert from '../OverlayAlert'; - export default { title: 'Momentum UI/ComboBox', component: ComboBox, @@ -25,16 +24,17 @@ export default { }, }; - -const ComboBoxWrapper = (props:Props) => { +const ComboBoxWrapper = (props: Props) => { return ( - - {(group: IComboBoxGroup) => { - const itemsEle = group?.items?.map((menuItem: IComboBoxItem) => { - return ( -
{menuItem.label}
-
); - }); + + {(itemOrGroup: IComboBoxGroup) => { + if ('items' in itemOrGroup) { + const group = itemOrGroup as IComboBoxGroup; + const itemsEle = group.items.map((menuItem: IComboBoxItem) => ( + +
{menuItem.label}
+
+ )); return group.section ? (
@@ -43,53 +43,54 @@ const ComboBoxWrapper = (props:Props) => { ) : (
{itemsEle}
); - }} - + } else { + const item = itemOrGroup as IComboBoxItem; + return ( + + {item.label} + + ); + } + }} + ); }; - - - -const withoutSection: IComboBoxGroup[] = [ - { - items:[ - {key:'key1',label:'item1'}, - {key:'key2',label:'item2'}, - {key:'key3',label:'item3'}, - ] - }, +const withoutSection: IComboBoxItem[] = [ + { key: 'item1', label: 'item1' }, + { key: 'item2', label: 'item2' }, + { key: 'item3', label: 'item3' }, ]; const withSection: IComboBoxGroup[] = [ { - section:'section1', - items:[ - {key:'key1',label:'item1'}, - {key:'key2',label:'item2'}, - {key:'key3',label:'item3'}, - {key:'key4',label:'item4'} - ] + section: 'section1', + items: [ + { key: 'key1', label: 'item1 long long long long long long long' }, + { key: 'key2', label: 'item2' }, + { key: 'key3', label: 'item3' }, + { key: 'key4', label: 'item4' }, + ], }, { - section:'section2', - items:[ - {key:'key5',label:'item5'}, - {key:'key6',label:'item6'}, - {key:'key7',label:'item7'}, - {key:'key8',label:'item8'} - ] + section: 'section2', + items: [ + { key: 'key5', label: 'item5' }, + { key: 'key6', label: 'item6' }, + { key: 'key7', label: 'item7' }, + { key: 'key8', label: 'item8' }, + ], }, ]; const Example = Template(ComboBoxWrapper).bind({}); Example.args = { - placeholder: 'placeholder', - comboBoxGroups: withoutSection, - disabledKeys: ['key3'], - label:'WithoutSection', - description:'Description text', + placeholder: 'placeholder123', + defaultItems: withoutSection, + noResultLabel: 'No Result Found', + label: 'WithoutSection', + description: 'Description text', }; Example.argTypes = { ...argTypes }; @@ -97,21 +98,20 @@ Example.argTypes = { ...argTypes }; const Sections = Template(ComboBoxWrapper).bind({}); Sections.args = { - comboBoxGroups: withSection, - selectedKey: 'key1', - label:'WithSection', - description:'Description text', - disabledKeys: ['key3','key6'], + defaultItems: withSection, + defaultSelectedKey: 'key1', + label: 'WithSection', + description: 'Description text', + disabledKeys: ['key3', 'key6'], }; - Sections.argTypes = { ...argTypes }; -const InListItemTemplate = (props:Props) => { +const InListItemTemplate = (props) => { return ( -
- +
+
); @@ -120,79 +120,65 @@ const InListItemTemplate = (props:Props) => { const InListItem = Template(InListItemTemplate).bind({}); InListItem.args = { - comboBoxGroups: withSection, - label:'InListItem', - placeholder:'long text overflow effect use case' + defaultItems: withoutSection, + label: 'InListItem', + placeholder: 'long text overflow effect use case', + listboxWidth: '20rem', }; - InListItem.argTypes = { ...argTypes }; -const MultipleComboBoxTemplate = (props:Props) => { - return ( - <> - - - - - ); -}; - -const MultipleComboBox = Template(MultipleComboBoxTemplate).bind({}); - -MultipleComboBox.args = { - comboBoxGroups:withSection, - label:'MultipleComboBox', -}; - -MultipleComboBox.argTypes = { ...argTypes }; - -const DynamicDataTemplate = (props:Props) => { - const mockDynamicData = [{section:'section1',items:[{key:'key-1',label:'label-1'}]},{section:'section2',items:[{key:'key-2',label:'label-2'}]}]; - const [dynamicData,setDynamicData] = useState(mockDynamicData); - const [dynamicDataLength,setDynamicDataLength] = useState(0); - const [comboBoxGroups,setComboBoxGroups] = useState(dynamicData); - const [isListOpen,setIsListOpen] = useState(false); - - useEffect(()=>{ - const timer = setInterval(()=>{ +const DynamicDataTemplate = (props: Props) => { + const mockDynamicData = [ + { section: 'section1', items: [{ key: 'key-1', label: 'label-1' }] }, + { section: 'section2', items: [{ key: 'key-2', label: 'label-2' }] }, + ]; + const [dynamicData, setDynamicData] = useState(mockDynamicData); + const [dynamicDataLength, setDynamicDataLength] = useState(0); + const [defaultItems, setDefaultItems] = useState(dynamicData); + const [isListOpen, setIsListOpen] = useState(false); + + useEffect(() => { + const timer = setInterval(() => { const randomText = Math.random().toString(36).substr(2, 10); - mockDynamicData[Math.round(Math.random())].items.push({key:'key-'+randomText,label:'label-'+randomText}); + mockDynamicData[Math.round(Math.random())].items.push({ + key: 'key-' + randomText, + label: 'label-' + randomText, + }); setDynamicData(JSON.parse(JSON.stringify(mockDynamicData))); - },2000); - return ()=>{ + }, 2000); + return () => { clearInterval(timer); }; - },[]); + }, []); - useEffect(()=>{ + useEffect(() => { const length = dynamicData.reduce((total, current) => { return total + current.items.length; }, 0); setDynamicDataLength(length); - },[dynamicData]); + }, [dynamicData]); - const openStateChange = useCallback((isOpen)=>{ + const onOpenChange = useCallback((isOpen) => { setIsListOpen(isOpen); - },[]); + }, []); - const onInputChange = useCallback(()=>{ - setComboBoxGroups(dynamicData); - },[dynamicData]); - - useEffect(()=>{ - if(!isListOpen){ - setComboBoxGroups(dynamicData); + useEffect(() => { + if (!isListOpen) { + setDefaultItems(dynamicData); } - },[isListOpen,dynamicData]); + }, [isListOpen, dynamicData]); return ( <> -
DynamicDataLength:{dynamicDataLength}
-
For dynamic data, it is relatively controllable to not re-render when the list is opened, and to re-render when input changes.
- - - +
DynamicDataLength:{dynamicDataLength}
+
+ For dynamic data, it is relatively controllable to not re-render when the list is opened, + and to re-render when input changes. +
+ + + ); }; @@ -200,10 +186,10 @@ const DynamicDataTemplate = (props:Props) => { const DynamicData = Template(DynamicDataTemplate).bind({}); DynamicData.args = { - label:'DynamicData', + label: 'DynamicData', + listboxWidth: '15rem', }; DynamicData.argTypes = { ...argTypes }; - -export { Example, Sections, InListItem, MultipleComboBox, DynamicData }; +export { Example, Sections, DynamicData, InListItem }; diff --git a/src/components/ComboBox/ComboBox.style.scss b/src/components/ComboBox/ComboBox.style.scss index 9d8db6ab5..d9c811597 100644 --- a/src/components/ComboBox/ComboBox.style.scss +++ b/src/components/ComboBox/ComboBox.style.scss @@ -1,140 +1,145 @@ .md-combo-box-wrapper { + min-width: 16rem; position: relative; - width: var(--local-width); - height: 2rem; - min-height: 1.71rem; + display: inline-block; - .md-menu-item-wrapper { - position: static; - } + --local-width: 100%; - .md-button-pill-wrapper { - background-color: var(--mds-color-theme-background-solid-primary-normal); - border: 1px solid var(--mds-color-theme-outline-input-normal); - border-radius: 0 0.5rem 0.5rem 0; - line-height: 2rem; - width: 2rem; - height: 2rem; - } + label { + display: flex; + color: var(--mds-color-theme-text-primary-normal); + font-size: 0.875rem; + line-height: 1.375rem; + margin-left: 0.75rem; + margin-bottom: 0.25rem; + } - .md-button-pill-wrapper[data-ghost=true][data-outline=false][data-inverted=false] { - background-color: var(--mds-color-theme-background-solid-primary-normal); - } + /* to make sure the popover matches the parent width, we have to override tippy css here: */ + div[data-tippy-root=''] { + width: var(--local-width); + } +} - .md-button-pill-wrapper[data-ghost=true][data-outline=false][data-inverted=false]:hover { - background-color: var(--mds-color-theme-background-primary-hover); - } +.md-combo-box-trigger { + background-color: var(--mds-color-theme-background-solid-primary-normal); + border: 0.0625rem var(--md-globals-border-style-solid) var(--mds-color-theme-outline-input-normal); + border-radius: 0.5rem; + position: relative; + width: var(--local-width); + display: flex; + height: auto; - .md-menu-section-header-wrapper { - line-height: 2rem; - } + &:focus-within { + box-shadow: var(--md-globals-focus-ring-box-shadow); + } - ul.md-menu-wrapper ul[role='group'] { - margin: 0; - } + &:hover { + background-color: var(--mds-color-theme-background-primary-hover); + border-color: var(--mds-color-theme-outline-input-normal); - ul.md-menu-wrapper ul[role='presentation']:not(:first-child)::before { - display: block; - width: 100%; - height: 0.0625rem; - border-bottom: 0.0625rem solid var(--mds-color-theme-outline-input-normal); - content: ''; + input { + color: var(--mds-color-theme-text-primary-normal); } + } - .md-menu-item-wrapper[aria-checked='false'] > div[data-position='fill'] { - width: calc(100% - 1.75rem); - } - - .md-text-input-container { - height: 100%; - border-radius: 0.5rem 0 0 0.5rem; - border-right: 0px; - } + input:focus { + box-shadow: none; + } +} - .md-text-input-container > input { - width: 100%; - padding-right: 0.75rem; - } +.md-combo-box-input { + width: calc(100% - 2rem); + color: var(--mds-color-theme-text-primary-normal); + outline: none; + height: 2rem; + box-sizing: border-box; + box-shadow: none; + background-color: transparent; + border: 0; + font-family: var(--md-globals-font-default); + font-size: 1rem; + padding-left: 0.75rem; + + > span:first-of-type { + display: block; + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + } - .clear-icon { - display: none; - width: 0; - height: 0; - padding: 0; - overflow: hidden; - } + &::placeholder { + color: var(--mds-color-theme-text-secondary-normal); + } + + &::-webkit-contacts-auto-fill-button { + background-color: var(--mds-color-theme-text-secondary-normal); - &[data-input-have-value='false'] { - .md-text-input-container > input { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; + &:hover { + background-color: var(--mds-color-theme-text-primary-normal); } - } - &[data-error='true'] { - .md-text-input-container, - .md-button-pill-wrapper, - .md-combo-box-divider { - border-color: var(--mds-color-theme-text-error-normal); + &:active { + background-color: var(--mds-color-theme-text-secondary-normal); } } - .md-combo-box-input-section { - display: flex; - height: 100%; + &:-webkit-autofill, + &:-webkit-autofill:hover, + &:-webkit-autofill:focus, + &:-webkit-autofill:active { + -webkit-animation: autofill 0s forwards; + animation: autofill 0s forwards; + border-radius: 0.438rem 0 0 0.438rem; } - .md-combo-box-input { - width: 100%; + @keyframes autofill { + 100% { + background: transparent; + color: inherit; + } } - .md-combo-box-selection-position{ - width: var(--local-width); - z-index: 10000; - position: fixed; + @-webkit-keyframes autofill { + 100% { + background: transparent; + color: inherit; + } } - .md-combo-box-selection-container { - width: 100%; - padding: 0.5rem; - margin-top: 0.25rem; - overflow: auto; - background-color: var(--mds-color-theme-background-solid-primary-normal); - border: 0.0625rem solid var(--mds-color-theme-outline-secondary-normal); - border-radius: 0.5rem; - box-sizing: border-box; + &:-webkit-autofill-strong-password { + margin-top: 0.0625rem; + margin-left: 0.0625rem; + -webkit-box-shadow: 0 0 0 3.75rem #f9ffbd inset; + box-shadow: 0 0 0 3.75rem #f9ffbd inset; + border-radius: 0.375rem 0 0 0.375rem; } +} - .md-combo-box-no-result-text { - color: var(--mds-color-theme-text-primary-normal); - } +.md-combo-box-button { + border-width: 0 0 0 1px; + background: transparent; + color: var(--mds-color-theme-text-primary-normal); +} - .md-combo-box-button { - width: var(--local-height); - height: 100%; - min-height: 1.71rem; - position: relative; - - .md-combo-box-arrow-icon { - position: absolute; - top: 50%; - right: 50%; - transform: translate(50%, -50%); - } - } +.md-combo-box-popover { + width: 100%; + padding: 0.25rem !important; + border-radius: 0.75rem !important; +} - .md-combo-box-divider { - width: 2px; - height: 100%; - border-top: 1px solid; - border-bottom: 1px solid; - border-color: var(--mds-color-theme-outline-input-normal); - background-color: var(--mds-color-theme-background-solid-primary-normal); - } +.md-combo-box-listbox { + border: none !important; + background: none !important; + padding: 0 !important; + width: 100%; - .md-combo-box-input:hover ~.md-combo-box-divider { - background-color: var(--mds-color-theme-background-primary-hover); + li { + width: calc(100% - 0.5rem); + margin: 0.25rem; + + div[title='no-results'] { + color: var(--mds-color-theme-text-primary-normal); + } } } diff --git a/src/components/ComboBox/ComboBox.tsx b/src/components/ComboBox/ComboBox.tsx index 182a9c428..2a6d24a2c 100644 --- a/src/components/ComboBox/ComboBox.tsx +++ b/src/components/ComboBox/ComboBox.tsx @@ -1,471 +1,266 @@ -import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; -import { Item } from '@react-stately/collections'; -import TextInput from '../TextInput'; -import Icon from '../Icon'; -import ButtonPill from '../ButtonPill'; -import Menu from '../Menu'; -import { - KEYS, - STYLE, - DEFAULTS, - ELEMENT, - EVENT, -} from './ComboBox.constants'; -import { Props, IComboBoxItem, IComboBoxGroup } from './ComboBox.types'; - +/* eslint-disable @typescript-eslint/ban-ts-comment */ +import React, { + ReactElement, + useCallback, + RefObject, + useRef, + forwardRef, + useState, + useEffect, +} from 'react'; import classnames from 'classnames'; -import './ComboBox.style.scss'; - -import { handleFilter as handleFilterFunc, searchItem as searchItemFunc, getSumScrollTop as getSumScrollTopFunc } from './ComboBox.utils'; - - -const ComboBox: React.FC = (props: Props) => { +import { useComboBox, useFilter } from 'react-aria'; +import './ComboBox.style.scss'; +import { Props, IComboBoxGroup, IComboBoxItem } from './ComboBox.types'; +import { STYLE, DEFAULTS, EVENT, ICON, KEYS } from './ComboBox.constants'; +import { useComboBoxState } from '@react-stately/combobox'; +import { useKeyboard } from '@react-aria/interactions'; +import Icon from '../Icon'; +import ListBoxBase from '../ListBoxBase'; +import ButtonSimple from '../ButtonSimple'; +import Popover, { PopoverInstance } from '../Popover'; +import Text from '../Text'; +import { filterItems } from './ComboBox.utils'; + +// eslint-disable-next-line @typescript-eslint/ban-types +function ComboBox(props: Props, ref: RefObject): ReactElement { const { - onArrowButtonPress: onArrowButtonPressCallback, - onInputChange: onInputChangeCallback, - onSelectionChange: onSelectionChangeCallback, - openStateChange: openStateChangeCallBack, - comboBoxGroups: originComboBoxGroups, - selectedKey: selectedKeyPayload = DEFAULTS.SELECTEDKEY, - disabledKeys: disabledKeysPayload = DEFAULTS.DISABLEDKEYS, - noResultText = DEFAULTS.NO_RESULT_TEXT, - width = DEFAULTS.WIDTH, - placeholder = DEFAULTS.PLACEHOLDER, - shouldFilterOnArrowButton = DEFAULTS.SHOULD_FILTER_ON_ARROW_BUTTON, - error = DEFAULTS.ERROR, - inputRef:inputRefProp, className, - id, style, + id, label, description, - children, + direction, + listboxMaxHeight, + listboxWidth, + noResultLabel, + defaultItems, } = props; - const componentInputRef = useRef(null); - - const menuRef = useRef(null); - const containerRef = useRef(null); - const inputRef = inputRefProp || componentInputRef ; - const selectionPositionRef = useRef(null); - - const [isInit, setIsInit] = useState(true); - const [isOpen, setIsOpen] = useState(false); - const [isFocused,setIsFocused] = useState(false); - const [isPreFocused,setIsPreFocused] = useState(false); - const [shouldFocusItem, setShouldFocusItem] = useState(false); - const [selectionContainerMaxHeight,setSelectionContainerMaxHeight] = useState(); - const [inputValue, setInputValue] = useState(''); - const [selectedKey, setSelectedKey] = useState(selectedKeyPayload); - const [groups, setGroups] = useState(originComboBoxGroups); - - const isInputFocused = useRef(false); - - const wrapperProps = useMemo(()=>({ - className: classnames(className, STYLE.wrapper), - style: { '--local-width': width, ...style }, - id, - 'data-input-have-value': !!inputValue, - 'data-error': error, - }),[className, width, style, id, inputValue, error]); - - const disabledKeys = [KEYS.INPUT_SEARCH_NO_RESULT, ...disabledKeysPayload]; - - - // utils - - const searchItem: (key: string,groups:IComboBoxGroup[]) => IComboBoxItem | undefined = useCallback( - (key,groups) => searchItemFunc(key,groups) - ,[]); - - const handleFocusBackToInput = useCallback( - ()=>{ - inputRef?.current?.focus(); - },[inputRef.current]); - - const handleFilter = useCallback( - (currentInputValue = '') => { - if(currentInputValue){ - const filterGroup = handleFilterFunc(originComboBoxGroups,currentInputValue); - setGroups(filterGroup); - }else{ - setGroups(originComboBoxGroups); - } - },[originComboBoxGroups]); + const { contains } = useFilter({ sensitivity: 'base' }); + const { KEY } = EVENT; - const handleItemFocus = useCallback( - ()=>{ - const listItems: NodeListOf = containerRef?.current?.querySelectorAll('li[role="menuitemradio"][aria-disabled="false"]'); - if (listItems?.length) { - const selectedItem = Array.from(listItems).find(item => item?.ariaChecked === 'true'); - if (selectedItem) { - // prioritize focusing on the selected item. - selectedItem.focus(); - } else { - listItems[0].focus(); - } - } - setShouldFocusItem(false); - },[containerRef.current]); + const [filteredItems, setFilteredItems] = + useState>(defaultItems); + const [items, setItems] = useState>(null); + const [popoverInstance, setPopoverInstance] = useState(); - // Used to prevent the bottom of the list from exceeding the window boundary. - const handleSelectionContainerMaxHeight = useCallback( - ()=>{ - const windowHeight = window.innerHeight; - const {bottom} = inputRef?.current?.getBoundingClientRect(); - - const inputDistanceFromViewportBottom = windowHeight - bottom; - if(inputDistanceFromViewportBottom < ELEMENT.PROPS.SELECTION_CONTAINER_MAX_HEIGHT + 8){ - setSelectionContainerMaxHeight(inputDistanceFromViewportBottom - 8); - } else { - setSelectionContainerMaxHeight(ELEMENT.PROPS.SELECTION_CONTAINER_MAX_HEIGHT); - } - },[inputRef.current]); + const hasBeenOpened = useRef(false); + const isFirstOpen = useRef(true); + const isOpen = useRef(false); - // Since the positioning of the list uses ‘fix’, it is necessary to calculate the height of all scroll bars of the list’s ancestor elements, - // and then set the translate to prevent the positioning of the list from being affected by the scroll bars of the ancestor elements. - const handleSelectionTranslate = useCallback( - ()=>{ - if (isOpen && inputRef?.current && selectionPositionRef.current) { - const scrollTop = getSumScrollTopFunc(inputRef.current); - selectionPositionRef.current.style.transform = `translateY(${-scrollTop}px)`; - } - },[inputRef.current,isOpen]); + const inputRef = ref || useRef(null); + const buttonRef = useRef(null); + const listBoxRef = useRef(null); + const popoverRef = useRef(null); + const triggerRef = useRef(null); - - // event + const addNoResults = (disabledKeys: Iterable = []): Iterable => { + const keysSet = new Set(disabledKeys); + keysSet.add(KEYS.NO_RESULT); + return keysSet; + }; - const handlerStopPropagation = useCallback( - (event)=>{ - if(event.code === EVENT.KEY.KEYCODE.ESCAPE){ - event.stopPropagation(); - } - },[]); + const disabledKeys = addNoResults(props.disabledKeys); - const handleTriggerOutsideForList = useCallback( - (event) => { - if(isOpen){ - if (containerRef?.current && !containerRef?.current?.contains(event.target)) { - setIsOpen(false); - } - } - },[containerRef.current,isOpen]); - - const handleTriggerOutsideForInput = useCallback( - (event) => { - if (containerRef?.current && !containerRef?.current?.contains(event.target)) { - setIsOpen(false); - const currentItem = searchItem(selectedKey,originComboBoxGroups); - handleFilter(currentItem.label); - setInputValue(currentItem.label??''); - } - },[containerRef.current,selectedKey,originComboBoxGroups,handleFilter,searchItem]); + const onInputChange = (value: string) => { + if (props.onInputChange) { + props.onInputChange(value); + } - const handleItemFocusChange = useCallback( - (event) => { - const item = event.target; - const itemRect = item.getBoundingClientRect(); - const ulRect = menuRef?.current?.getBoundingClientRect(); - if (itemRect.top < ulRect.top || itemRect.bottom > ulRect.bottom) { - item.scrollIntoView(); - } - } - ,[menuRef.current]); + isFirstOpen.current = false; + const newFilteredItems = filterItems(defaultItems, value || '', contains); + if (newFilteredItems.length === 0) { + setFilteredItems(noResultLabel ? [{ key: KEYS.NO_RESULT, label: noResultLabel }] : []); + } else { + setFilteredItems(newFilteredItems); + } + }; + + const state = useComboBoxState({ + ...props, + disabledKeys, + defaultItems, + items: props.items ?? items, + onInputChange, + }); + + const { buttonProps, inputProps, listBoxProps, labelProps } = useComboBox( + { + ...props, + inputRef, + buttonRef, + listBoxRef, + popoverRef, + }, + state + ); - const handlePreventScroll = useCallback( - (event)=>{ - if(isOpen && selectionPositionRef?.current){ - if(!selectionPositionRef?.current?.contains(event.target)){ - event.preventDefault(); + const { onKeyDown } = inputProps; + + inputProps.onKeyDown = (e) => { + switch (e.key) { + case KEY.ARROW_DOWN: + case KEY.ARROW_UP: + isFirstOpen.current = true; + break; + case KEY.TAB: + if (state.isOpen) { + e.preventDefault(); + e.stopPropagation(); } - } - },[selectionPositionRef.current,isOpen]); - - const handleInputKeyDown = useCallback( - (event) => { - if (event.code === EVENT.KEY.KEYCODE.ESCAPE) { - if (isOpen) { - setIsOpen(false); + break; + case KEY.ESCAPE: + if (isOpen.current) { + state.close(); } else { - setInputValue(''); - handleFilter(); + state.setSelectedKey(null); } - } - - if (!isOpen && event.code === EVENT.KEY.KEYCODE.ENTER || event.code === EVENT.KEY.KEYCODE.ARROW_DOWN || event.code === EVENT.KEY.KEYCODE.ARROW_UP) { - setShouldFocusItem(true); - setIsOpen(true); - } - },[isOpen,handleFilter]); - - const handleMenuKeyDown = useCallback( - (event) => { - if (event.code === EVENT.KEY.KEYCODE.ESCAPE) { - setIsOpen(false); - handleFocusBackToInput(); - }else if(event.code === EVENT.KEY.KEYCODE.TAB){ - // when the focus is on the listItem, prevent focus escape - event.preventDefault(); - } - },[handleFocusBackToInput]) ; - - const handleGetFocusEle = useCallback( - (event)=>{ - setIsFocused(containerRef?.current?.contains(event.target)); - },[containerRef.current]); - - const handleGetPreFocusEle = useCallback( - (event)=>{ - setIsPreFocused(containerRef?.current?.contains(event.target)); - },[containerRef.current]); - - const handleGetInputFocus = useCallback( - (event)=>{ - isInputFocused.current = (inputRef?.current?.contains(event.target)); - },[inputRef.current]); - - const handleInputFocus = useCallback( - ()=>{ - if(!isOpen){ - handleFilter(inputValue); - } - },[handleFilter,inputValue,isOpen]); - - - // effect - - useEffect(()=>{ - if(openStateChangeCallBack){ - openStateChangeCallBack(isOpen); + break; + default: } - },[openStateChangeCallBack,isOpen]); - - useEffect(()=>{ - if(isInit){ - // isInit is used to solve the case where the input is focused by default during initialization. - // Since isInputFocused is used in the logic as the basis for whether to setInputValue, - // special handling is needed if the focus is on the input during initialization. - if(selectedKey){ - // If ‘selected’ exists, a matching item must be found to complete the initialization. - const currentItem = searchItem(selectedKey,originComboBoxGroups); - if(currentItem.label){ - handleFilter(currentItem.label); - setInputValue(currentItem.label); - setIsInit(false); - } - }else{ - setIsInit(false); + onKeyDown(e); + }; + + useEffect(() => { + isFirstOpen.current = !state.isOpen; + isOpen.current = state.isOpen; + }, [state.isOpen]); + + useEffect(() => { + // display all items when listBox first open + const items = !isFirstOpen.current ? filteredItems : defaultItems; + setItems(items); + }, [filteredItems, defaultItems, state.inputValue]); + + const getArrowIcon = (isOpen: boolean) => (isOpen ? ICON.ARROW_UP : ICON.ARROW_DOWN); + + const handleFocusBackOnTrigger = useCallback(() => { + inputRef.current?.focus(); + }, [inputRef]); + + useEffect(() => { + if (popoverInstance) { + if (!state.isOpen) { + setItems(defaultItems); } - }else{ - if(isInputFocused.current){ - // If the focus is on the input, it indicates that the user may be operating the input, - // so here we do not want the inputValue to change spontaneously. - handleFilter(inputValue); - }else { - const currentItem = searchItem(selectedKey,originComboBoxGroups); - handleFilter(currentItem.label); - setInputValue(currentItem.label??''); - } - } - },[originComboBoxGroups,selectedKey,inputValue,isInit,handleFilter,searchItem]); - - useEffect(()=>{ - handleSelectionTranslate(); - handleSelectionContainerMaxHeight(); - },[handleSelectionTranslate,handleSelectionContainerMaxHeight]); - - useEffect(()=>{ - document.addEventListener('focusin',handleGetFocusEle); - containerRef?.current?.addEventListener('focusout', handleGetPreFocusEle); - return()=>{ - document.removeEventListener('focusin',handleGetFocusEle); - containerRef?.current?.removeEventListener('focusout', handleGetPreFocusEle); - }; - },[containerRef.current,handleGetFocusEle,handleGetPreFocusEle]); - - useEffect(()=>{ - // Fix the issue where focusing on the input in certain situations does not correctly filter the expanded items - inputRef?.current?.addEventListener('focus',handleInputFocus); - return()=>{ - inputRef?.current?.removeEventListener('focus',handleInputFocus); - }; - },[inputRef.current,handleInputFocus]); - - useEffect(()=>{ - document.addEventListener('mousedown', handleTriggerOutsideForList); - return()=>{ - document.removeEventListener('mousedown', handleTriggerOutsideForList); - }; - },[handleTriggerOutsideForList]); - - useEffect(()=>{ - document.addEventListener('mousedown', handleTriggerOutsideForInput); - return()=>{ - document.removeEventListener('mousedown', handleTriggerOutsideForInput); - }; - },[handleTriggerOutsideForInput]); - - useEffect(()=>{ - window.addEventListener('mousewheel',handlePreventScroll,{ passive: false }); - return()=>{ - window.removeEventListener('mousewheel',handlePreventScroll); - }; - },[handlePreventScroll]); - - useEffect(()=>{ - containerRef?.current?.addEventListener('keydown',handlerStopPropagation); - return()=>{ - containerRef?.current?.removeEventListener('keydown',handlerStopPropagation); - }; - },[containerRef.current,handlerStopPropagation]); - - useEffect(()=>{ - document.addEventListener('focusin',handleGetInputFocus); - return()=>{ - document.removeEventListener('focusin',handleGetInputFocus); - }; - },[handleGetInputFocus]); - - useEffect(()=>{ - menuRef?.current?.addEventListener('focusin', handleItemFocusChange); - - return()=>{ - menuRef?.current?.removeEventListener('focusin', handleItemFocusChange); - }; - },[menuRef.current,handleItemFocusChange]); - - useEffect(()=>{ - menuRef?.current?.addEventListener('keydown', handleMenuKeyDown); - - return()=>{ - menuRef?.current?.removeEventListener('keydown', handleMenuKeyDown); - }; - },[menuRef.current,handleMenuKeyDown]); - - useEffect(()=>{ - inputRef?.current?.addEventListener('keydown', handleInputKeyDown); - return()=>{ - inputRef?.current?.removeEventListener('keydown', handleInputKeyDown); - }; - }, [inputRef?.current,handleInputKeyDown]); - - useEffect(()=>{ - if(shouldFocusItem && isOpen) { - handleItemFocus(); } - },[shouldFocusItem,isOpen,handleItemFocus]); - - // Used to handle the logic of inputValue when the focus switches from inside the component to outside. - useEffect(()=>{ - if(containerRef?.current){ - if(!isFocused && isPreFocused){ - if(selectedKey){ - const currentItem = searchItem(selectedKey,originComboBoxGroups); - setInputValue(currentItem.label); - handleFilter(currentItem.label); - }else{ - setInputValue(''); - handleFilter(); + }, [state.isOpen, popoverInstance, items]); + + useEffect(() => { + if (popoverInstance) { + if (state.isOpen) { + // show popover once state changes to isOpen = true + popoverInstance.show(); + hasBeenOpened.current = true; + } else { + // hide popover once state changes to isOpen = false + popoverInstance.hide(); + if (hasBeenOpened.current) { + // only do this if it has been opened previously to prevent unexpected focus + handleFocusBackOnTrigger(); } - setIsOpen(false); } } - },[containerRef.current,isPreFocused,isFocused,selectedKey,originComboBoxGroups,searchItem,handleFilter]); - - - // subcomponent event - - const onInputChange = useCallback( - (event)=>{ - const currentInputValue = event.target.value; - if(!isOpen){ - setIsOpen(true); - } - setInputValue(currentInputValue); - handleFilter(currentInputValue); - if(onInputChangeCallback){ - onInputChangeCallback(event); - } - },[isOpen,onInputChangeCallback,handleFilter]); + }, [state.isOpen, popoverInstance]); + + /** + * Handle closeOnComboBox from @react-aria manually + */ + const closePopover = useCallback(() => { + state.close(); + }, []); + + delete buttonProps['aria-label']; + delete listBoxProps['aria-label']; + + if (props['aria-required']) { + inputProps['aria-required'] = inputProps.value ? 'false' : 'true'; + } + + const triggerComponent = ( + + + + + + + ); - const onAction = useCallback( - (key: string) => { - setSelectedKey(key); - const currentItem = searchItem(key,originComboBoxGroups); - setInputValue(currentItem.label); - handleFilter(currentItem.label); - if(onSelectionChangeCallback){ - onSelectionChangeCallback(currentItem); + const { keyboardProps } = useKeyboard({ + onKeyDown: (event) => { + if (event.key === KEY.ESCAPE) { + closePopover(); } - setIsOpen(false); - handleFocusBackToInput(); - },[originComboBoxGroups,handleFocusBackToInput,onSelectionChangeCallback,searchItem,handleFilter]); + }, + }); + // delete color prop which is passed down and used in the ModalContainer + // because it conflicts with the HTML color property + return ( +
+ {label && ( + // eslint-disable-next-line jsx-a11y/label-has-for + + )} + , 'color'>)} + style={{ + maxHeight: listboxMaxHeight || 'none', + display: state.isOpen ? undefined : 'none', + }} + strategy={listboxWidth ? 'fixed' : 'absolute'} + > + + + {description &&
{description}
} +
+ ); +} - const onArrowButtonPress = useCallback( - (event)=>{ - if(!isOpen){ - setShouldFocusItem(true); - if(!shouldFilterOnArrowButton){ - handleFilter(); - }else{ - handleFilter(inputValue); - } - } - if(onArrowButtonPressCallback){ - onArrowButtonPressCallback(event); - } - setIsOpen(!isOpen); - },[isOpen,inputValue,shouldFilterOnArrowButton,handleFilter,onArrowButtonPressCallback]); +/** + * Dropdown / ComboBox Element which displays a listbox with options. + */ +const _ComboBox = forwardRef(ComboBox); - return ( - <> - {label ? (
{label}
) : null} -
-
- -
- - - -
- {isOpen ? ( -
-
- - {groups.length ? children : ( -
{noResultText}
-
)} -
-
-
- ) : null} -
- {description && (
{description}
)} - - ); -}; +_ComboBox.displayName = 'ComboBox'; -export default ComboBox; +export default _ComboBox as (props: Props & { ref?: RefObject }) => ReactElement; diff --git a/src/components/ComboBox/ComboBox.types.ts b/src/components/ComboBox/ComboBox.types.ts index bf6cd533c..aa25fd8ec 100644 --- a/src/components/ComboBox/ComboBox.types.ts +++ b/src/components/ComboBox/ComboBox.types.ts @@ -1,7 +1,6 @@ +import type { ComboBoxProps } from '@react-types/combobox'; import { CollectionChildren } from '@react-types/shared'; -import { PressEvent } from '@react-types/shared/src/events'; -import { CSSProperties, RefObject } from 'react'; - +import { CSSProperties } from 'react'; export type IComboBoxItem = { key: string; @@ -14,84 +13,68 @@ export type IComboBoxGroup = { section?: string; }; -export interface Props { - /** - * Handler that is called when an item is selected in the list. - * If the selected item matches the selectedKey, the parameter is undefined. - */ - onSelectionChange?: (item: IComboBoxItem) => void; - /** - * Handler that is called when the ComboBox input value changes. - */ - onInputChange?: (event: InputEvent) => void; - /** - * Handler that is called when the arrowButton pressed. - */ - onArrowButtonPress?: (event: PressEvent) => void; - /** - * Handler that is called when isOpen state of list chanages. - */ - openStateChange?: (isOpen: boolean) => void; +export type Direction = 'top' | 'bottom'; + +export interface Props extends ComboBoxProps { /** * id: id of help message. */ id?: string; + /** * Custom style for overriding this component's CSS. */ style?: CSSProperties; + /** * Custom class to be able to override the component's CSS. */ className?: string; + /** * Label/message to be displayed with this component. */ label?: string; + /** * Description associated with this component. Appears below the title. */ description?: string; - /** - * Description associated with this component. Appears below the title. - */ - error?: boolean; - /** - * Override the list box width and ComboBox container width. - * defaultValue: 16.25rem - */ - width?: string; - /** - * Text to display inside the input when there is no inputValue. - */ - placeholder?: string; - /** - * This property represents whether to filter based on the input value when click the arrowButton. - */ - shouldFilterOnArrowButton?: boolean; + /** * Text to display inside the list box when there are no items that match the user's input. - * defaultValue: No results found */ - noResultText?: string; + noResultLabel?: string; + /** - * The list of options for this component. + * Direction in which the option list will display + * @default bottom */ - comboBoxGroups: IComboBoxGroup[]; + direction?: Direction; + /** - * The currently disabled keys in the collection. + * To override the list box max height */ - disabledKeys?: string[]; + listboxMaxHeight?: string; + /** - * The currently selected key in the collection. + * Override the list box width to allow for fixed popover strategy + * + * To style the list box without applying fixed popover strategy, pass in className instead + * + * NOTE: if set, the popover strategy will be set to 'fixed' */ - selectedKey?: string; + listboxWidth?: string; + /** - * Used to get the input DOM within the component. + * The list of ComboBox items (uncontrolled). */ - inputRef?: RefObject; + items?: Array; + /** - * Child components of this component. + * The list of ComboBox items (controlled). */ + defaultItems?: Array; + children: CollectionChildren; } diff --git a/src/components/ComboBox/ComboBox.unit.test.tsx b/src/components/ComboBox/ComboBox.unit.test.tsx index d8a78eece..9e15531f9 100644 --- a/src/components/ComboBox/ComboBox.unit.test.tsx +++ b/src/components/ComboBox/ComboBox.unit.test.tsx @@ -1,14 +1,13 @@ import ComboBox from '.'; -import React, { createRef } from 'react'; +import React from 'react'; import { Item, Section } from '@react-stately/collections'; import { STYLE } from './ComboBox.constants'; import { mountAndWait } from '../../../test/utils'; import '@testing-library/jest-dom'; import userEvent from '@testing-library/user-event'; import { render, screen, waitFor } from '@testing-library/react'; -import { IComboBoxGroup } from './ComboBox.types'; +import { IComboBoxGroup, IComboBoxItem } from './ComboBox.types'; import { act } from 'react-dom/test-utils'; -import TextInput from '../TextInput'; jest.mock('@react-aria/utils'); jest.mock('uuid', () => { return { @@ -19,17 +18,13 @@ jest.mock('uuid', () => { describe('ComboBox', () => { let container; - const withoutSection: IComboBoxGroup[] = [ - { - items: [ - { key: 'key1', label: 'item1' }, - { key: 'key2', label: 'item2' }, - { key: 'key3', label: 'item3' }, - { key: 'key4', label: 'menu1' }, - { key: 'key5', label: 'menu2' }, - { key: 'key6', label: 'menu3' }, - ], - }, + const withoutSection: IComboBoxItem[] = [ + { key: 'key1', label: 'item1' }, + { key: 'key2', label: 'item2' }, + { key: 'key3', label: 'item3' }, + { key: 'key4', label: 'listbox1' }, + { key: 'key5', label: 'listbox2' }, + { key: 'key6', label: 'listbox3' }, ]; const withSection: IComboBoxGroup[] = [ @@ -54,27 +49,37 @@ describe('ComboBox', () => { ]; describe('snapshot', () => { - const renderChildren = (group) => { - const itemsEle: any = group?.items?.map((menuItem) => { - return menuItem.popoverText ? ( - -
{menuItem.popoverText}
+ const renderChildren = (itemOrGroup) => { + if ('items' in itemOrGroup) { + const group = itemOrGroup; + const itemsEle = group.items.map((listboxItem: IComboBoxItem) => ( + +
{listboxItem.label}
+ )); + + return group.section ? ( +
+ {itemsEle} +
) : ( - -
{menuItem.label}
+
{itemsEle}
+ ); + } else { + const item = itemOrGroup; + return ( + + {item.label} ); - }); - - return
{itemsEle}
; + } }; it('should match snapshot label', async () => { expect.assertions(1); container = await mountAndWait( - + {renderChildren} ); @@ -86,16 +91,16 @@ describe('ComboBox', () => { expect.assertions(1); container = await mountAndWait( - + {(group) => { - const itemsEle = group?.items?.map((menuItem) => { - return menuItem.popoverText ? ( - -
{menuItem.popoverText}
+ const itemsEle = group?.items?.map((listboxItem) => { + return listboxItem.popoverText ? ( + +
{listboxItem.popoverText}
) : ( - -
{menuItem.label}
+ +
{listboxItem.label}
); }); @@ -118,7 +123,7 @@ describe('ComboBox', () => { const className = 'example-class'; container = await mountAndWait( - + {renderChildren} ); @@ -132,7 +137,7 @@ describe('ComboBox', () => { const style = { color: 'pink' }; container = await mountAndWait( - + {renderChildren} ); @@ -146,7 +151,7 @@ describe('ComboBox', () => { const placeholder = 'ComboBox'; container = await mountAndWait( - + {renderChildren} ); @@ -154,13 +159,13 @@ describe('ComboBox', () => { expect(container).toMatchSnapshot(); }); - it('should match snapshot with noResultText', async () => { + it('should match snapshot with noResultLabel', async () => { expect.assertions(1); - const noResultText = 'No result'; + const noResultLabel = 'No result'; container = await mountAndWait( - + {renderChildren} ); @@ -168,14 +173,13 @@ describe('ComboBox', () => { expect(container).toMatchSnapshot(); }); - - it('should match snapshot with width', async () => { + it('should match snapshot with listboxWidth', async () => { expect.assertions(1); - const width = '16rem'; + const listboxWidth = '16rem'; container = await mountAndWait( - + {renderChildren} ); @@ -186,7 +190,7 @@ describe('ComboBox', () => { describe('attributes', () => { it('should have its wrapper class', async () => { container = await mountAndWait( - {renderChildren} + {renderChildren} ); const element = container.find(ComboBox).getDOMNode(); @@ -198,7 +202,7 @@ describe('ComboBox', () => { const className = 'example-class'; container = await mountAndWait( - + {renderChildren} ); @@ -215,25 +219,23 @@ describe('ComboBox', () => { const styleString = 'color: pink;'; const wrapper = await mountAndWait( - + {renderChildren} ); const element = wrapper.find(ComboBox).getDOMNode(); - expect(element.getAttribute('style')).toBe( - `--local-width: 16.25rem; ${styleString}` - ); + expect(element.getAttribute('style')).toBe(`--local-width: 100%; ${styleString}`); }); - it('should have provided style when style is width', async () => { + it('should have provided style when style is listboxWidth', async () => { expect.assertions(1); - const width = '16rem'; + const listboxWidth = '16rem'; const styleString = '--local-width: 16rem;'; const wrapper = await mountAndWait( - + {renderChildren} ); @@ -242,76 +244,20 @@ describe('ComboBox', () => { expect(element.getAttribute('style')).toBe(`${styleString}`); }); - it('should have provided label when label is provided', async () => { - expect.assertions(1); - - const label = 'ComboBox'; - - const wrapper = await mountAndWait( - - {renderChildren} - - ); - - const labelContainer = wrapper.find('div').filter({ className: 'md-combo-box-label' }); - - expect(labelContainer.props()).toEqual({ - className: 'md-combo-box-label', - children: label, - }); - }); - - it('should have provided description when description is provided', async () => { - expect.assertions(1); + // it('should have provided error style when error is provided', async () => { + // expect.assertions(1); - const description = 'ComboBox description'; + // const error = true; - const wrapper = await mountAndWait( - - {renderChildren} - - ); + // const wrapper = await mountAndWait( + // + // {renderChildren} + // + // ); + // const element = wrapper.find(ComboBox).getDOMNode(); - const descriptionContainer = wrapper - .find('div') - .filter({ className: 'md-combo-box-description' }); - - expect(descriptionContainer.props()).toEqual({ - className: 'md-combo-box-description', - children: description, - }); - }); - - it('should have provided error style when error is provided', async () => { - expect.assertions(1); - - const error = true; - - const wrapper = await mountAndWait( - - {renderChildren} - - ); - const element = wrapper.find(ComboBox).getDOMNode(); - - expect(element.getAttribute('data-error')).toBe(`${error}`); - }); - - it('should have expected props on selectedKey', async () => { - expect.assertions(1); - - const selectedKey = 'key1'; - - const wrapper = await mountAndWait( - - {renderChildren} - - ); - - expect( - wrapper.find('[aria-label="md-combo-box-input"]').at(0).props() - ).toHaveProperty('value', 'item1'); - }); + // expect(element.getAttribute('data-error')).toBe(`${error}`); + // }); it('should have expected props on placeholder', async () => { expect.assertions(1); @@ -319,71 +265,40 @@ describe('ComboBox', () => { const placeholder = 'please select'; const wrapper = await mountAndWait( - + {renderChildren} ); - expect( - wrapper.find('[aria-label="md-combo-box-input"]').at(0).props() - ).toHaveProperty('placeholder', placeholder); - }); - - it('should match inputRef props', async () => { - expect.assertions(1); - - const inputRef = createRef(); - - const wrapper = await mountAndWait( - - {renderChildren} - + expect(wrapper.find('.md-combo-box-input').at(0).props()).toHaveProperty( + 'placeholder', + placeholder ); - - expect( - wrapper.find(TextInput).props()['aria-label'] - ).toEqual(inputRef.current.getAttribute('aria-label')); }); describe('actions', () => { - it('should show menu on click', async () => { + it('should show list on click', async () => { const user = userEvent.setup(); - render({renderChildren}); + render({renderChildren}); - const menuItem = screen.queryByRole('menu'); - expect(menuItem).not.toBeInTheDocument(); + expect(screen.queryByRole('listbox')).not.toBeInTheDocument(); await user.click(screen.getByRole('button')); - expect(screen.getByRole('menu')).toBeVisible(); - }); - - it('should call onArrowButtonPress when click', async () => { - const user = userEvent.setup(); - const onArrowButtonPress = jest.fn(); - - render( - - {renderChildren} - - ); - - await user.click(screen.getByRole('button')); - - expect(onArrowButtonPress).toHaveBeenCalled(); + expect(screen.getByRole('listbox')).toBeVisible(); }); it('should call onInputChange when type on input', async () => { const onInputChange = jest.fn(); render( - + {renderChildren} ); - await userEvent.type(screen.getByLabelText('md-combo-box-input'), 'hello'); + await userEvent.type(screen.getByRole('combobox'), 'hello'); expect(onInputChange).toHaveBeenCalled(); }); @@ -393,62 +308,33 @@ describe('ComboBox', () => { const onSelectionChange = jest.fn(); render( - + {renderChildren} ); const button = screen - .queryAllByRole('button') - .find((button) => button.classList.contains('md-combo-box-button')); + .queryAllByRole('button') + .find((button) => button.classList.contains('md-combo-box-button')); - act(()=>{ + act(() => { button.focus(); }); await user.keyboard('{Enter}'); - expect(screen.getByRole('menu')).toBeVisible(); - - const item = screen.getByText('item1').parentElement; - await waitFor(() => { - expect(item.parentElement).toHaveFocus(); - }); + expect(screen.getByRole('listbox')).toBeVisible(); + expect(onSelectionChange).not.toHaveBeenCalled(); - await user.keyboard('{Enter}'); + await user.click(screen.getAllByRole('option')[0]); expect(onSelectionChange).toHaveBeenCalled(); }); - it('should call openStateChange when list is expanded or collapsed', async () => { - const user = userEvent.setup(); - const openStateChange = jest.fn(); - - render( - - {renderChildren} - - ); - - const button = screen - .queryAllByRole('button') - .find((button) => button.classList.contains('md-combo-box-button')); - - act(()=>{ - button.focus(); - });; - expect(openStateChange).toBeCalledWith(false); - await user.keyboard('{Enter}'); - expect(screen.getByRole('menu')).toBeVisible(); - expect(openStateChange).toBeCalledWith(true); - await user.keyboard('{Escape}'); - expect(openStateChange).toBeCalledWith(false); - }); - it('should show disabledKeys when click', async () => { const user = userEvent.setup(); const disabledKeys = ['key1']; const { container } = render( - + {renderChildren} ); @@ -461,30 +347,30 @@ describe('ComboBox', () => { ); }); - it('should show menu when focused and pressing enter', async () => { + it('should show list when focused and pressing enter', async () => { const user = userEvent.setup(); - render({renderChildren}); + render({renderChildren}); - const menuItem = screen.queryByRole('menu'); - expect(menuItem).not.toBeInTheDocument(); + const list = screen.queryByRole('listbox'); + expect(list).not.toBeInTheDocument(); const button = screen.getByRole('button'); - act(()=>{ + act(() => { button.focus(); - });; + }); expect(button).toHaveFocus(); await user.keyboard('{Enter}'); - expect(screen.getByRole('menu')).toBeVisible(); + expect(screen.getByRole('listbox')).toBeVisible(); }); - it('should hide menu when clicking outside', async () => { + it('should hide list when clicking outside', async () => { const user = userEvent.setup(); render( <> - {renderChildren} + {renderChildren} ); @@ -494,20 +380,20 @@ describe('ComboBox', () => { .find((button) => button.classList.contains('md-combo-box-button')); await user.click(ele); - expect(screen.getByRole('menu')).toBeVisible(); + expect(screen.getByRole('listbox')).toBeVisible(); - await user.click(screen.getByRole('button', { name: 'button-outside' })); + await user.click(screen.getAllByRole('button')[1]); await waitFor(() => { - expect(screen.queryByRole('menu')).not.toBeInTheDocument(); + expect(screen.queryByRole('listbox')).not.toBeInTheDocument(); }); }); }); - it('should have show noResultText when items is empty', async () => { - const noResultText = 'empty result'; + it('should have show noResultLabel when items is empty', async () => { + const noResultLabel = 'empty result'; render( - + {renderChildren} ); @@ -515,34 +401,9 @@ describe('ComboBox', () => { const user = userEvent.setup(); await user.click(screen.getByRole('button')); - await userEvent.type(screen.getByLabelText('md-combo-box-input'), 'hello'); - - expect(screen.getByLabelText('md-combo-box-no-result-text')).toHaveTextContent( - noResultText - ); - }); - - it('if shouldFilterOnArrowButton is false, should not filter when press arrowButton', async () => { - - render( - - {renderChildren} - - ); - - const user = userEvent.setup(); - const input = screen.getByLabelText('md-combo-box-input'); - const button = screen.getByRole('button'); - act(()=>{ - input.focus(); - }); - await user.keyboard('{4}'); - await user.keyboard('{Escape}'); - await user.click(button); - expect(screen.getByRole('menu')).toBeVisible(); + await userEvent.type(screen.getByRole('combobox'), 'hello'); - const item = screen.getByText('item1').parentElement; - expect(item).toBeVisible(); + expect(screen.getByRole('option')).toHaveTextContent(noResultLabel); }); it('When list is hidden, entering text in the input, list will display', async () => { @@ -550,85 +411,63 @@ describe('ComboBox', () => { render( <> - {renderChildren} + {renderChildren} ); - const input = screen.getByLabelText('md-combo-box-input'); - act(()=>{ + const input = screen.getByRole('combobox'); + act(() => { input.focus(); }); - await user.keyboard('{Enter}'); - expect(screen.getByRole('menu')).toBeVisible(); + await user.keyboard('{i}'); + expect(screen.getByRole('listbox')).toBeVisible(); await waitFor(() => { - expect(screen.queryByRole('menu')).toBeInTheDocument(); + expect(screen.queryByRole('listbox')).toBeInTheDocument(); }); }); - it('when input is focused, list is hidden, press Enter, list will display, and item will be focused', async () => { + it('when input is focused, list is hidden, press arrowDown, list will display, and item will be focused', async () => { const user = userEvent.setup(); render( <> - {renderChildren} + + {renderChildren} + ); - const input = screen.getByLabelText('md-combo-box-input'); - act(()=>{ + const input = screen.getByRole('combobox'); + act(() => { input.focus(); }); - await user.keyboard('{Enter}'); - expect(screen.getByRole('menu')).toBeVisible(); + await user.keyboard('{arrowDown}'); + expect(screen.getByRole('listbox')).toBeVisible(); - const item = screen.getByText('item2').parentElement; - await waitFor(() => { - expect(item.parentElement).toHaveFocus(); - }); + const item = screen.getAllByRole('option')[1]; + expect(item.getAttribute('data-focused')).toBe('true'); }); - it('when input is focused, list is hidden, press ArrowDown, list will display, and item will be focused', async () => { - const user = userEvent.setup(); - - render( - <> - {renderChildren} - - ); - - const input = screen.getByLabelText('md-combo-box-input'); - act(()=>{ - input.focus(); - }); - await user.keyboard('{ArrowDown}'); - expect(screen.getByRole('menu')).toBeVisible(); - - const item = screen.getByText('item1').parentElement; - - await waitFor(() => { - expect(item.parentElement).toHaveFocus(); - }); - }); it('when input is focused, list is displayed, press Escape, list will be hidden', async () => { const user = userEvent.setup(); render( <> - {renderChildren} + {renderChildren} ); - const input = screen.getByLabelText('md-combo-box-input'); - act(()=>{ + const input = screen.getByRole('combobox'); + act(() => { input.focus(); }); await user.keyboard('{i}'); - expect(screen.getByRole('menu')).toBeVisible(); + expect(screen.getByRole('listbox')).toBeVisible(); await user.keyboard('{Escape}'); await waitFor(() => { - expect(screen.queryByRole('menu')).not.toBeInTheDocument(); + expect(screen.queryByRole('listbox')).not.toBeInTheDocument(); }); }); @@ -637,18 +476,19 @@ describe('ComboBox', () => { render( <> - {renderChildren} + + {renderChildren} + ); - const input = screen.getByLabelText('md-combo-box-input'); - expect(input).toHaveProperty('value','item1'); - act(()=>{ + const input = screen.getByRole('combobox'); + expect(input).toHaveProperty('value', 'item1'); + act(() => { input.focus(); }); await user.keyboard('{Escape}'); - - expect(input).toHaveProperty('value',''); + expect(input).toHaveProperty('value', ''); }); it('when listitem is focused, press Escape, input will be focused', async () => { @@ -656,20 +496,18 @@ describe('ComboBox', () => { render( <> - {renderChildren} + {renderChildren} ); - const input = screen.getByLabelText('md-combo-box-input'); - act(()=>{ + const input = screen.getByRole('combobox'); + act(() => { input.focus(); }); - await user.keyboard('{Enter}'); - expect(screen.getByRole('menu')).toBeVisible(); + await user.keyboard('{ArrowDown}'); + expect(screen.getByRole('listbox')).toBeVisible(); - const item = screen.getByText('item1').parentElement; - await waitFor(() => { - expect(item.parentElement).toHaveFocus(); - }); + const item = screen.getAllByRole('option')[0]; + expect(item.getAttribute('data-focused')).toBe('true'); await user.keyboard('{Escape}'); await waitFor(() => { @@ -677,119 +515,99 @@ describe('ComboBox', () => { }); }); - it('when listitem is focused, press Tab, The focus will not escape.', async () => { - const user = userEvent.setup(); - - render( - <> - {renderChildren} - - ); - const input = screen.getByLabelText('md-combo-box-input'); - act(()=>{ - input.focus(); - }); - await user.keyboard('{Enter}'); - expect(screen.getByRole('menu')).toBeVisible(); - - const item = screen.getByText('item1').parentElement; - await waitFor(() => { - expect(item.parentElement).toHaveFocus(); - }); - - await user.keyboard('{Tab}'); - await waitFor(() => { - expect(item.parentElement).toHaveFocus(); - }); - }); - it('reset inputValue, when focus shifts from inside the component to outside', async () => { const user = userEvent.setup(); render( <> - {renderChildren} + + {renderChildren} + ); - const input = screen.getByLabelText('md-combo-box-input'); - act(()=>{ + const input = screen.getByRole('combobox'); + act(() => { input.focus(); }); - await user.keyboard('{Escape}'); - expect(input).toHaveProperty('value',''); + await user.keyboard('{i}'); + expect(input).toHaveProperty('value', 'item1i'); const button = screen.getByRole('button', { name: 'button-outside' }); - act(()=>{ + act(() => { button.focus(); }); await waitFor(() => { - expect(input).toHaveProperty('value','item1'); + expect(input).toHaveProperty('value', 'item1'); }); }); - it('reset inputValue, when mousedown outside the component', async () => { + it('reset inputValue, when click outside the component', async () => { const user = userEvent.setup(); render( <> - {renderChildren} + + {renderChildren} + ); - const input = screen.getByLabelText('md-combo-box-input'); - + const input = screen.getByRole('combobox'); await waitFor(() => { - expect(input).toHaveProperty('value','item1'); + expect(input).toHaveProperty('value', 'item1'); }); - act(()=>{ + act(() => { input.focus(); }); await user.keyboard('{1}'); await waitFor(() => { - expect(input).toHaveProperty('value','item11'); + expect(input).toHaveProperty('value', 'item11'); }); const button = screen.getByRole('button', { name: 'button-outside' }); await user.click(button); await waitFor(() => { - expect(input).toHaveProperty('value','item1'); + expect(input).toHaveProperty('value', 'item1'); }); }); - it('filter list when the input is focused', async () => { + it('filter list when input', async () => { const user = userEvent.setup(); render( <> - {renderChildren} + + {renderChildren} + ); - const input = screen.getByLabelText('md-combo-box-input'); - const button = screen - .queryAllByRole('button') - .find((button) => button.classList.contains('md-combo-box-button')); + const input = screen.getByRole('combobox'); await waitFor(() => { - expect(input).toHaveProperty('value','item1'); + expect(input).toHaveProperty('value', 'item1'); }); - await user.click(button); - const menu = screen.getByRole('menu'); - expect(menu).toBeVisible(); - const item2 = screen.getByText('item2').parentElement; - await user.click(button); - await user.click(input); - await user.keyboard('{Enter}'); - expect(input).toHaveProperty('value','item1'); - const item1 = screen.getByText('item1').parentElement; + act(() => { + input.focus(); + }); + await user.keyboard('{ArrowDown}'); + const listbox = screen.getByRole('listbox'); + expect(listbox).toBeVisible(); + const item2 = screen.getAllByRole('option')[1]; + const item1 = screen.getAllByRole('option')[0]; + expect(item1).toBeInTheDocument(); + expect(item2).toBeInTheDocument(); + await user.keyboard('{Backspace}'); + await user.keyboard('{1}'); + expect(input).toHaveProperty('value', 'item1'); await waitFor(() => { - expect(item1.parentElement).toHaveFocus(); + expect(item1).toBeInTheDocument(); expect(item2).not.toBeInTheDocument(); }); }); - }); + }); }); }); diff --git a/src/components/ComboBox/ComboBox.unit.test.tsx.snap b/src/components/ComboBox/ComboBox.unit.test.tsx.snap index 2ce11bf61..726035619 100644 --- a/src/components/ComboBox/ComboBox.unit.test.tsx.snap +++ b/src/components/ComboBox/ComboBox.unit.test.tsx.snap @@ -2,175 +2,406 @@ exports[`ComboBox snapshot should match snapshot label 1`] = ` -
- comboBox_label -
-
- -
+

+ comboBox_label +

+ + + -
+ - -
-
-
-
- -
+ + + + + + + +
+ } + /> + + + +
`; @@ -178,861 +409,1953 @@ exports[`ComboBox snapshot should match snapshot label 1`] = ` exports[`ComboBox snapshot should match snapshot with className 1`] = `
-
- -
-
+ - -
-
-
-
- -
+ + + + + + + +
+ } + /> + + + +
`; -exports[`ComboBox snapshot should match snapshot with noResultText 1`] = ` +exports[`ComboBox snapshot should match snapshot with listboxWidth 1`] = `
-
- -
-
+ - -
-
-
-
- -
+ + + + + + + +
+ } + /> + + + +
`; -exports[`ComboBox snapshot should match snapshot with placeholder 1`] = ` +exports[`ComboBox snapshot should match snapshot with noResultLabel 1`] = `
-
- -
-
+ - -
-
-
-
- -
+ + + + + + + +
+ } + /> + + + +
`; -exports[`ComboBox snapshot should match snapshot with style 1`] = ` +exports[`ComboBox snapshot should match snapshot with placeholder 1`] = `
-
- -
-
+ - -
-
-
-
- -
+ + + + + + + +
+ } + /> + + + +
`; -exports[`ComboBox snapshot should match snapshot with width 1`] = ` +exports[`ComboBox snapshot should match snapshot with style 1`] = `
-
- -
-
+ - -
-
-
-
- -
+ + + + + + + +
+ } + /> + + + +
`; exports[`ComboBox snapshot should match snapshot withSection 1`] = `
-
- -
-
+ - -
-
-
-
- -
+ + + + + + + +
+ } + /> + + + +
`; diff --git a/src/components/ComboBox/ComboBox.utils.test.ts b/src/components/ComboBox/ComboBox.utils.test.ts index 03058b4ed..d20384276 100644 --- a/src/components/ComboBox/ComboBox.utils.test.ts +++ b/src/components/ComboBox/ComboBox.utils.test.ts @@ -1,149 +1,63 @@ -import { handleFilter, searchItem, getSumScrollTop } from './ComboBox.utils'; +import { filterItems } from './ComboBox.utils'; describe('ComboBox utils', () => { - describe('handleFilter', () => { - const comboBoxGroupsWithSection = [ - {section:'secitonA',items:[ - {key:'keyA1',label:'itemA1'}, - {key:'keyA2',label:'itemA2'}, - {key:'keyA3',label:'itemA3'}, - ]}, - {section:'seciontB',items:[ - {key:'keyB1',label:'itemB1'}, - {key:'keyB2',label:'itemB2'}, - {key:'keyB3',label:'itemB3'}, - ]} - ]; - - const comboBoxGroupsWithoutSection = [ - {items:[ - {key:'keyA1',label:'itemA1'}, - {key:'keyA2',label:'itemA2'}, - {key:'keyA3',label:'itemA3'}, - {key:'keyB1',label:'itemB1'}, - {key:'keyB2',label:'itemB2'}, - {key:'keyB3',label:'itemB3'}, - ]} - ]; - - it('test case withSection', () => { - expect(handleFilter(comboBoxGroupsWithSection, '1')).toEqual([ - {section:'secitonA',items:[ - {key:'keyA1',label:'itemA1'}, - ]}, - {section:'seciontB',items:[ - {key:'keyB1',label:'itemB1'}, - ]} - ]); - expect(handleFilter(comboBoxGroupsWithSection, 'A')).toEqual([ - {section:'secitonA',items:[ - {key:'keyA1',label:'itemA1'}, - {key:'keyA2',label:'itemA2'}, - {key:'keyA3',label:'itemA3'}, - ]}, - ]); - }); - - it('test case withoutSection', () => { - expect(handleFilter(comboBoxGroupsWithoutSection, '1')).toEqual([ - {items:[ - {key:'keyA1',label:'itemA1'}, - {key:'keyB1',label:'itemB1'}, - ]}, - ]); - - expect(handleFilter(comboBoxGroupsWithoutSection, 'a')).toEqual([ - {items:[ - {key:'keyA1',label:'itemA1'}, - {key:'keyA2',label:'itemA2'}, - {key:'keyA3',label:'itemA3'}, - ]} - ]); - - expect(handleFilter(comboBoxGroupsWithoutSection, 'A')).toEqual([ - {items:[ - {key:'keyA1',label:'itemA1'}, - {key:'keyA2',label:'itemA2'}, - {key:'keyA3',label:'itemA3'}, - ]} - ]); - }); - - it('test case not match any of the item labels', () => { - expect(handleFilter(comboBoxGroupsWithoutSection, 'c')).toEqual([]); - }); - }); - - describe('searchItem', () => { - const comboBoxGroupsWithSection = [ - {section:'secitonA',items:[ - {key:'keyA1',label:'itemA1'}, - {key:'keyA2',label:'itemA2'}, - {key:'keyA3',label:'itemA3'}, - ]}, - {section:'seciontB',items:[ - {key:'keyB1',label:'itemB1'}, - {key:'keyB2',label:'itemB2'}, - {key:'keyB3',label:'itemB3'}, - ]} - ]; - - const comboBoxGroupsWithoutSection = [ - {items:[ - {key:'keyA1',label:'itemA1'}, - {key:'keyA2',label:'itemA2'}, - {key:'keyA3',label:'itemA3'}, - {key:'keyB1',label:'itemB1'}, - {key:'keyB2',label:'itemB2'}, - {key:'keyB3',label:'itemB3'}, - ]} - ]; - - it('test case withSection', () => { - expect(searchItem('keyA1',comboBoxGroupsWithSection)).toEqual({key:'keyA1',label:'itemA1'}); - }); - - it('test case withoutSection', () => { - expect(searchItem('keyB1',comboBoxGroupsWithoutSection)).toEqual({key:'keyB1',label:'itemB1'}); - }); - - it('test case not match any of the item keys', () => { - expect(searchItem('key1',comboBoxGroupsWithoutSection)).toEqual({key:undefined,label:undefined}); - }); - }); - - describe('getSumScrollTop', () => { - - const sampleElement1 = { - scrollTop:0, - }; - - const sampleElement2 = { - scrollTop:NaN, - parentElement:sampleElement1, - }; - - const sampleElement3 = { - scrollTop:18.5, - parentElement:sampleElement2, - }; - - const sampleElement4 = { - scrollTop:10.5, - parentElement:sampleElement3, - }; - - it.each` - element | expectedSum - ${sampleElement1} | ${0} - ${sampleElement2} | ${0} - ${sampleElement3} | ${0} - ${sampleElement4} | ${18.5} - `( - 'correctly returns $expectedSum for $element', - ({element,expectedSum}) => { - expect(getSumScrollTop(element)).toEqual(expectedSum); - } - ); + describe('filterItems', () => { + const comboBoxGroupsWithSection = [ + { + section: 'secitonA', + items: [ + { key: 'keyA1', label: 'itemA1' }, + { key: 'keyA2', label: 'itemA2' }, + { key: 'keyA3', label: 'itemA3' }, + ], + }, + { + section: 'seciontB', + items: [ + { key: 'keyB1', label: 'itemB1' }, + { key: 'keyB2', label: 'itemB2' }, + { key: 'keyB3', label: 'itemB3' }, + ], + }, + ]; + + const comboBoxGroupsWithoutSection = [ + { key: 'keyA1', label: 'itemA1' }, + { key: 'keyA2', label: 'itemA2' }, + { key: 'keyA3', label: 'itemA3' }, + { key: 'keyB1', label: 'itemB1' }, + { key: 'keyB2', label: 'itemB2' }, + { key: 'keyB3', label: 'itemB3' }, + ]; + + it('test case withSection', () => { + const filterFn = (label: string, input: string): boolean => { + return label.toLowerCase().includes(input.toLowerCase()); + }; + + expect(filterItems(comboBoxGroupsWithSection, '1', filterFn)).toEqual([ + { section: 'secitonA', items: [{ key: 'keyA1', label: 'itemA1' }] }, + { section: 'seciontB', items: [{ key: 'keyB1', label: 'itemB1' }] }, + ]); + expect(filterItems(comboBoxGroupsWithSection, 'A', filterFn)).toEqual([ + { + section: 'secitonA', + items: [ + { key: 'keyA1', label: 'itemA1' }, + { key: 'keyA2', label: 'itemA2' }, + { key: 'keyA3', label: 'itemA3' }, + ], + }, + ]); + expect(filterItems(comboBoxGroupsWithoutSection, '1', filterFn)).toEqual([ + { key: 'keyA1', label: 'itemA1' }, + { key: 'keyB1', label: 'itemB1' }, + ]); + expect(filterItems(comboBoxGroupsWithoutSection, 'A', filterFn)).toEqual([ + { key: 'keyA1', label: 'itemA1' }, + { key: 'keyA2', label: 'itemA2' }, + { key: 'keyA3', label: 'itemA3' }, + ]); }); + }); }); diff --git a/src/components/ComboBox/ComboBox.utils.ts b/src/components/ComboBox/ComboBox.utils.ts index 3f1b029d6..be0397980 100644 --- a/src/components/ComboBox/ComboBox.utils.ts +++ b/src/components/ComboBox/ComboBox.utils.ts @@ -1,38 +1,30 @@ -import {IComboBoxGroup, IComboBoxItem} from './ComboBox.types'; +interface Item { + label: string; + key: string; +} -export const handleFilter = (comboBoxGroup:IComboBoxGroup[],inputValue:string):IComboBoxGroup[] => { - const queryLowerCase = inputValue.toLowerCase().trim(); - const filterItem = Array.prototype.map.call(comboBoxGroup,(group:IComboBoxGroup) => { - return { - ...group, - items: group.items.filter((item) => item.label?.toLowerCase()?.includes(queryLowerCase)), - }; - }).filter((group:IComboBoxGroup) => group.items?.length > 0); +interface ItemGroup { + section?: string; + items: Item[]; +} - return filterItem; -}; - -export const searchItem = (key: string,originComboBoxGroups:IComboBoxGroup[]) : IComboBoxItem | undefined => { - let target: IComboBoxItem | undefined; - key && Array.prototype.some.call(originComboBoxGroups,(group: IComboBoxGroup) => { - const foundItem = group.items.find((item: IComboBoxItem) => item.key === key); - if (foundItem) { - target = foundItem; - return true; - } - return false; - }); - return target ?? {key:undefined,label:undefined}; -}; +type FilterFn = (label: string, inputValue: string) => boolean; -export const getSumScrollTop = (element:Element):number => { - let sum = 0; - while (element) { - element = element.parentElement; - if (element) { - const scrollTop = Number.isNaN(element.scrollTop) ? 0 : element.scrollTop; - sum += scrollTop ; - } +export const filterItems = ( + items: Array, + inputValue: string, + filterFn: FilterFn +): Array => { + const filteredItems = []; + for (const item of items) { + if ((item as ItemGroup).section && (item as ItemGroup).items) { + const filtered = filterItems((item as ItemGroup).items, inputValue, filterFn); + if ([...filtered].length > 0) { + filteredItems.push({ ...item, items: filtered }); + } + } else if (!(item as ItemGroup).section && filterFn((item as Item).label, inputValue)) { + filteredItems.push({ ...item }); } - return sum; + } + return filteredItems; }; diff --git a/src/components/List/List.unit.test.tsx.snap b/src/components/List/List.unit.test.tsx.snap index 3684eca9a..a37669764 100644 --- a/src/components/List/List.unit.test.tsx.snap +++ b/src/components/List/List.unit.test.tsx.snap @@ -27,6 +27,7 @@ exports[` snapshot should match snapshot 1`] = ` className="md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-padded={false} data-shape="rectangle" @@ -69,6 +70,7 @@ exports[` snapshot should match snapshot 1`] = ` className="md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-padded={false} data-shape="rectangle" @@ -128,6 +130,7 @@ exports[` snapshot should match snapshot with className 1`] = ` className="md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-padded={false} data-shape="rectangle" @@ -170,6 +173,7 @@ exports[` snapshot should match snapshot with className 1`] = ` className="md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-padded={false} data-shape="rectangle" @@ -230,6 +234,7 @@ exports[` snapshot should match snapshot with id 1`] = ` className="md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-padded={false} data-shape="rectangle" @@ -272,6 +277,7 @@ exports[` snapshot should match snapshot with id 1`] = ` className="md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-padded={false} data-shape="rectangle" @@ -332,6 +338,7 @@ exports[` snapshot should match snapshot with role 1`] = ` className="md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-padded={false} data-shape="rectangle" @@ -374,6 +381,7 @@ exports[` snapshot should match snapshot with role 1`] = ` className="md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-padded={false} data-shape="rectangle" @@ -442,6 +450,7 @@ exports[` snapshot should match snapshot with style 1`] = ` className="md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-padded={false} data-shape="rectangle" @@ -484,6 +493,7 @@ exports[` snapshot should match snapshot with style 1`] = ` className="md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-padded={false} data-shape="rectangle" diff --git a/src/components/ListBoxBase/ListBoxBase.unit.test.tsx.snap b/src/components/ListBoxBase/ListBoxBase.unit.test.tsx.snap index 6dbe6adc4..86c3b0d25 100644 --- a/src/components/ListBoxBase/ListBoxBase.unit.test.tsx.snap +++ b/src/components/ListBoxBase/ListBoxBase.unit.test.tsx.snap @@ -198,6 +198,7 @@ exports[`ListBoxBase snapshot should match snapshot 1`] = ` data-key="$.0" id="test-ID-option-$.0" isDisabled={false} + isFocused={false} isPadded={true} key="$.0" onClick={[Function]} @@ -231,6 +232,7 @@ exports[`ListBoxBase snapshot should match snapshot 1`] = ` className="md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="$.0" data-padded={true} @@ -305,6 +307,7 @@ exports[`ListBoxBase snapshot should match snapshot 1`] = ` data-key="$.1" id="test-ID-option-$.1" isDisabled={false} + isFocused={false} isPadded={true} key="$.1" onClick={[Function]} @@ -338,6 +341,7 @@ exports[`ListBoxBase snapshot should match snapshot 1`] = ` className="md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="$.1" data-padded={true} @@ -586,6 +590,7 @@ exports[`ListBoxBase snapshot should match snapshot when autoFocus provided 1`] data-key="$.0" id="test-ID-option-$.0" isDisabled={false} + isFocused={false} isPadded={true} key="$.0" onClick={[Function]} @@ -619,6 +624,7 @@ exports[`ListBoxBase snapshot should match snapshot when autoFocus provided 1`] className="md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="$.0" data-padded={true} @@ -693,6 +699,7 @@ exports[`ListBoxBase snapshot should match snapshot when autoFocus provided 1`] data-key="$.1" id="test-ID-option-$.1" isDisabled={false} + isFocused={false} isPadded={true} key="$.1" onClick={[Function]} @@ -726,6 +733,7 @@ exports[`ListBoxBase snapshot should match snapshot when autoFocus provided 1`] className="md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="$.1" data-padded={true} @@ -975,6 +983,7 @@ exports[`ListBoxBase snapshot should match snapshot with className 1`] = ` data-key="$.0" id="test-ID-option-$.0" isDisabled={false} + isFocused={false} isPadded={true} key="$.0" onClick={[Function]} @@ -1008,6 +1017,7 @@ exports[`ListBoxBase snapshot should match snapshot with className 1`] = ` className="md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="$.0" data-padded={true} @@ -1082,6 +1092,7 @@ exports[`ListBoxBase snapshot should match snapshot with className 1`] = ` data-key="$.1" id="test-ID-option-$.1" isDisabled={false} + isFocused={false} isPadded={true} key="$.1" onClick={[Function]} @@ -1115,6 +1126,7 @@ exports[`ListBoxBase snapshot should match snapshot with className 1`] = ` className="md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="$.1" data-padded={true} @@ -1363,6 +1375,7 @@ exports[`ListBoxBase snapshot should match snapshot with id 1`] = ` data-key="$.0" id="test-ID-option-$.0" isDisabled={false} + isFocused={false} isPadded={true} key="$.0" onClick={[Function]} @@ -1396,6 +1409,7 @@ exports[`ListBoxBase snapshot should match snapshot with id 1`] = ` className="md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="$.0" data-padded={true} @@ -1470,6 +1484,7 @@ exports[`ListBoxBase snapshot should match snapshot with id 1`] = ` data-key="$.1" id="test-ID-option-$.1" isDisabled={false} + isFocused={false} isPadded={true} key="$.1" onClick={[Function]} @@ -1503,6 +1518,7 @@ exports[`ListBoxBase snapshot should match snapshot with id 1`] = ` className="md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="$.1" data-padded={true} @@ -1907,6 +1923,7 @@ exports[`ListBoxBase snapshot should match snapshot with sections 1`] = ` data-key="$.0.0" id="test-ID-option-$.0.0" isDisabled={false} + isFocused={false} isPadded={true} key="$.0.0" onClick={[Function]} @@ -1940,6 +1957,7 @@ exports[`ListBoxBase snapshot should match snapshot with sections 1`] = ` className="md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="$.0.0" data-padded={true} @@ -2014,6 +2032,7 @@ exports[`ListBoxBase snapshot should match snapshot with sections 1`] = ` data-key="$.0.1" id="test-ID-option-$.0.1" isDisabled={false} + isFocused={false} isPadded={true} key="$.0.1" onClick={[Function]} @@ -2047,6 +2066,7 @@ exports[`ListBoxBase snapshot should match snapshot with sections 1`] = ` className="md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="$.0.1" data-padded={true} @@ -2162,6 +2182,7 @@ exports[`ListBoxBase snapshot should match snapshot with sections 1`] = ` data-key="$.1.0" id="test-ID-option-$.1.0" isDisabled={false} + isFocused={false} isPadded={true} key="$.1.0" onClick={[Function]} @@ -2195,6 +2216,7 @@ exports[`ListBoxBase snapshot should match snapshot with sections 1`] = ` className="md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="$.1.0" data-padded={true} @@ -2464,6 +2486,7 @@ exports[`ListBoxBase snapshot should match snapshot with style 1`] = ` data-key="$.0" id="test-ID-option-$.0" isDisabled={false} + isFocused={false} isPadded={true} key="$.0" onClick={[Function]} @@ -2497,6 +2520,7 @@ exports[`ListBoxBase snapshot should match snapshot with style 1`] = ` className="md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="$.0" data-padded={true} @@ -2571,6 +2595,7 @@ exports[`ListBoxBase snapshot should match snapshot with style 1`] = ` data-key="$.1" id="test-ID-option-$.1" isDisabled={false} + isFocused={false} isPadded={true} key="$.1" onClick={[Function]} @@ -2604,6 +2629,7 @@ exports[`ListBoxBase snapshot should match snapshot with style 1`] = ` className="md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="$.1" data-padded={true} diff --git a/src/components/ListBoxItem/ListBoxItem.tsx b/src/components/ListBoxItem/ListBoxItem.tsx index 5d2b1bca8..a5f46c161 100644 --- a/src/components/ListBoxItem/ListBoxItem.tsx +++ b/src/components/ListBoxItem/ListBoxItem.tsx @@ -17,6 +17,7 @@ function ListBoxItem(props: Props): ReactElement { const isDisabled = state.disabledKeys.has(item.key); const isSelected = state.selectionManager.isSelected(item.key); + const isFocused = state.selectionManager.focusedKey === item.key; const { optionProps } = useOption( { @@ -32,7 +33,15 @@ function ListBoxItem(props: Props): ReactElement { ); return ( - + {item.rendered} diff --git a/src/components/ListBoxItem/ListBoxItem.unit.test.tsx b/src/components/ListBoxItem/ListBoxItem.unit.test.tsx index e9515e7cf..fa9cafe46 100644 --- a/src/components/ListBoxItem/ListBoxItem.unit.test.tsx +++ b/src/components/ListBoxItem/ListBoxItem.unit.test.tsx @@ -58,6 +58,7 @@ describe('ListBoxItem', () => { expect(base.props()).toEqual({ isPadded: true, isDisabled: false, + isFocused: false, children: expect.any(Object), }); expect(element.innerHTML).toBe(item.rendered); diff --git a/src/components/ListBoxItem/ListBoxItem.unit.test.tsx.snap b/src/components/ListBoxItem/ListBoxItem.unit.test.tsx.snap index 46b51af26..494b0b946 100644 --- a/src/components/ListBoxItem/ListBoxItem.unit.test.tsx.snap +++ b/src/components/ListBoxItem/ListBoxItem.unit.test.tsx.snap @@ -30,6 +30,7 @@ exports[`ListBoxItem snapshot should match snapshot 1`] = ` > @@ -45,6 +46,7 @@ exports[`ListBoxItem snapshot should match snapshot 1`] = ` className="md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-padded={true} data-shape="rectangle" diff --git a/src/components/ListBoxSection/ListBoxSection.unit.test.tsx.snap b/src/components/ListBoxSection/ListBoxSection.unit.test.tsx.snap index 8ca49475c..4b1767bd3 100644 --- a/src/components/ListBoxSection/ListBoxSection.unit.test.tsx.snap +++ b/src/components/ListBoxSection/ListBoxSection.unit.test.tsx.snap @@ -64,6 +64,7 @@ exports[`ListBoxSection snapshot should match snapshot 1`] = ` > @@ -79,6 +80,7 @@ exports[`ListBoxSection snapshot should match snapshot 1`] = ` className="md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-padded={true} data-shape="rectangle" @@ -147,6 +149,7 @@ exports[`ListBoxSection snapshot should match snapshot 1`] = ` > @@ -162,6 +165,7 @@ exports[`ListBoxSection snapshot should match snapshot 1`] = ` className="md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-padded={true} data-shape="rectangle" diff --git a/src/components/ListHeader/ListHeader.unit.test.tsx.snap b/src/components/ListHeader/ListHeader.unit.test.tsx.snap index b40a09a0f..e7916dc10 100644 --- a/src/components/ListHeader/ListHeader.unit.test.tsx.snap +++ b/src/components/ListHeader/ListHeader.unit.test.tsx.snap @@ -28,6 +28,7 @@ exports[` snapshot should match snapshot 1`] = ` className="md-list-header-list-item-base md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={false} data-padded={true} data-shape="rectangle" @@ -88,6 +89,7 @@ exports[` snapshot should match snapshot with bold 1`] = ` className="md-list-header-list-item-base md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={false} data-padded={true} data-shape="rectangle" @@ -151,6 +153,7 @@ exports[` snapshot should match snapshot with className 1`] = ` className="md-list-header-list-item-base md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={false} data-padded={true} data-shape="rectangle" @@ -211,6 +214,7 @@ exports[` snapshot should match snapshot with id 1`] = ` className="md-list-header-list-item-base md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={false} data-padded={true} data-shape="rectangle" @@ -270,6 +274,7 @@ exports[` snapshot should match snapshot with outline 1`] = ` className="md-list-header-list-item-base md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={false} data-padded={true} data-shape="rectangle" @@ -334,6 +339,7 @@ exports[` snapshot should match snapshot with outlineColor 1`] = ` className="md-list-header-list-item-base md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={false} data-padded={true} data-shape="rectangle" @@ -398,6 +404,7 @@ exports[` snapshot should match snapshot with outlinePosition 1`] className="md-list-header-list-item-base md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={false} data-padded={true} data-shape="rectangle" @@ -462,6 +469,7 @@ exports[` snapshot should match snapshot with outlinePosition 2`] className="md-list-header-list-item-base md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={false} data-padded={true} data-shape="rectangle" @@ -534,6 +542,7 @@ exports[` snapshot should match snapshot with style 1`] = ` className="md-list-header-list-item-base md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={false} data-padded={true} data-shape="rectangle" diff --git a/src/components/ListItemBase/ListItemBase.constants.ts b/src/components/ListItemBase/ListItemBase.constants.ts index 99cff3728..8b7e5a287 100644 --- a/src/components/ListItemBase/ListItemBase.constants.ts +++ b/src/components/ListItemBase/ListItemBase.constants.ts @@ -15,6 +15,7 @@ const SHAPES = { const DEFAULTS = { SIZE: (shape: string): number => (shape === SHAPES.isPilled ? SIZES[50] : SIZES[40]), IS_DISABLED: false, + IS_FOCUSED: false, IS_PADDED: false, SHAPE: SHAPES.rectangle, ROLE: 'listitem', diff --git a/src/components/ListItemBase/ListItemBase.style.scss b/src/components/ListItemBase/ListItemBase.style.scss index 181c29f2b..7c1b31dd0 100644 --- a/src/components/ListItemBase/ListItemBase.style.scss +++ b/src/components/ListItemBase/ListItemBase.style.scss @@ -68,6 +68,12 @@ } } + &[data-focused='true'] { + border-color: transparent; + outline: none !important; + box-shadow: var(--md-globals-focus-ring-box-shadow); + } + & > div[data-position='start'] { width: fit-content; margin-right: 0.75rem; @@ -85,6 +91,7 @@ // trim any type of text inside p, span, + div, .md-text-wrapper { overflow: hidden; text-overflow: ellipsis; diff --git a/src/components/ListItemBase/ListItemBase.test.tsx b/src/components/ListItemBase/ListItemBase.test.tsx index e64613cee..4fa7454eb 100644 --- a/src/components/ListItemBase/ListItemBase.test.tsx +++ b/src/components/ListItemBase/ListItemBase.test.tsx @@ -73,6 +73,16 @@ describe('ListItemBase', () => { expect(container).toMatchSnapshot(); }); + it('should match snapshot with isFocused', () => { + expect.assertions(1); + + const isFocused = true; + + container = mount(Test); + + expect(container).toMatchSnapshot(); + }); + it('should match snapshot with lang', () => { expect.assertions(1); @@ -234,6 +244,18 @@ describe('ListItemBase', () => { expect(element.getAttribute('lang')).toBe('en-US'); }); + it('should have provided data-focused when isFocused is provided', () => { + expect.assertions(1); + + const isFocused = true; + + container = mount(Test); + + const element = container.find(ListItemBase).getDOMNode(); + + expect(element.getAttribute('data-focused')).toBe('true'); + }); + it('should have provided data-padding when isPadded is provided', () => { expect.assertions(1); diff --git a/src/components/ListItemBase/ListItemBase.test.tsx.snap b/src/components/ListItemBase/ListItemBase.test.tsx.snap index 8248787bd..a9e2f72d1 100644 --- a/src/components/ListItemBase/ListItemBase.test.tsx.snap +++ b/src/components/ListItemBase/ListItemBase.test.tsx.snap @@ -14,6 +14,7 @@ exports[`ListItemBase snapshot should match snapshot 1`] = ` className="md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-padded={false} data-shape="rectangle" @@ -59,6 +60,7 @@ exports[`ListItemBase snapshot should match snapshot with allowTextSelection=tru className="md-list-item-base-wrapper" data-allow-text-select={true} data-disabled={false} + data-focused={false} data-interactive={true} data-padded={false} data-shape="rectangle" @@ -104,6 +106,7 @@ exports[`ListItemBase snapshot should match snapshot with className 1`] = ` className="example-class md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-padded={false} data-shape="rectangle" @@ -147,6 +150,7 @@ exports[`ListItemBase snapshot should match snapshot with empty list item 1`] = className="md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-padded={false} data-shape="rectangle" @@ -182,6 +186,7 @@ exports[`ListItemBase snapshot should match snapshot with focusChild 1`] = ` className="md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={false} data-padded={false} data-shape="rectangle" @@ -276,6 +281,7 @@ exports[`ListItemBase snapshot should match snapshot with id 1`] = ` className="md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-padded={false} data-shape="rectangle" @@ -322,6 +328,7 @@ exports[`ListItemBase snapshot should match snapshot with interactive=false 1`] className="md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={false} data-padded={false} data-shape="rectangle" @@ -367,6 +374,53 @@ exports[`ListItemBase snapshot should match snapshot with isDisabled 1`] = ` className="md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={true} + data-focused={false} + data-interactive={true} + data-padded={false} + data-shape="rectangle" + data-size={40} + onBlur={[Function]} + onClick={[Function]} + onDragStart={[Function]} + onFocus={[Function]} + onKeyDown={[Function]} + onKeyUp={[Function]} + onMouseDown={[Function]} + onMouseEnter={[Function]} + onMouseLeave={[Function]} + onMouseUp={[Function]} + onPointerDown={[Function]} + onTouchCancel={[Function]} + onTouchEnd={[Function]} + onTouchMove={[Function]} + onTouchStart={[Function]} + role="listitem" + tabIndex={-1} + > + Test + + + + +`; + +exports[`ListItemBase snapshot should match snapshot with isFocused 1`] = ` + + + +
  • { shape = DEFAULTS.SHAPE, size = DEFAULTS.SIZE(shape || DEFAULTS.SHAPE), isDisabled = DEFAULTS.IS_DISABLED, + isFocused = DEFAULTS.IS_FOCUSED, isPadded = DEFAULTS.IS_PADDED, role = DEFAULTS.ROLE, focusChild = DEFAULTS.FOCUS_CHILD, @@ -50,7 +51,6 @@ const ListItemBase = (props: Props, providedRef: RefOrCallbackRef) => { onFocusWithin, ...rest } = props; - let content: ReactNode, start: ReactNode, middle: ReactNode, end: ReactNode; const listContext = useListContext(); @@ -279,7 +279,7 @@ const ListItemBase = (props: Props, providedRef: RefOrCallbackRef) => { return; } updateTabIndexes(); - }, [currentFocus, updateTabIndexes, isFocusedWithin]); + }, [currentFocus, updateTabIndexes, isFocusedWithin, listContext]); useMutationObservable(ref.current, updateTabIndexes); @@ -298,6 +298,7 @@ const ListItemBase = (props: Props, providedRef: RefOrCallbackRef) => { data-disabled={isDisabled} data-padded={isPadded} data-shape={shape} + data-focused={isFocused} data-interactive={interactive && !focusChild} data-allow-text-select={allowTextSelection} className={classnames(className, STYLE.wrapper, { active: isPressed || isSelected })} diff --git a/src/components/ListItemBase/ListItemBase.types.ts b/src/components/ListItemBase/ListItemBase.types.ts index 86a61d123..15c09ea2b 100644 --- a/src/components/ListItemBase/ListItemBase.types.ts +++ b/src/components/ListItemBase/ListItemBase.types.ts @@ -35,6 +35,12 @@ export interface Props */ isDisabled?: boolean; + /** + * Determines if this item is focused + * @default false + */ + isFocused?: boolean; + /** * Determines if this item is selected * @default false diff --git a/src/components/MeetingListItem/MeetingListItem.unit.test.tsx.snap b/src/components/MeetingListItem/MeetingListItem.unit.test.tsx.snap index dd50e7b6d..a965053c5 100644 --- a/src/components/MeetingListItem/MeetingListItem.unit.test.tsx.snap +++ b/src/components/MeetingListItem/MeetingListItem.unit.test.tsx.snap @@ -21,6 +21,7 @@ exports[` snapshot should match snapshot 1`] = ` data-allow-text-select={false} data-color="Transparent" data-disabled={false} + data-focused={false} data-interactive={true} data-padded={true} data-shape="rectangle" @@ -100,6 +101,7 @@ exports[` snapshot should match snapshot with buttonGroup 1`] data-allow-text-select={false} data-color="Transparent" data-disabled={false} + data-focused={false} data-interactive={true} data-padded={true} data-shape="rectangle" @@ -200,6 +202,7 @@ exports[` snapshot should match snapshot with className 1`] = data-allow-text-select={false} data-color="Transparent" data-disabled={false} + data-focused={false} data-interactive={true} data-padded={true} data-shape="rectangle" @@ -279,6 +282,7 @@ exports[` snapshot should match snapshot with color 1`] = ` data-allow-text-select={false} data-color="AcceptedActive" data-disabled={false} + data-focused={false} data-interactive={true} data-padded={true} data-shape="rectangle" @@ -359,6 +363,7 @@ exports[` snapshot should match snapshot with id 1`] = ` data-allow-text-select={false} data-color="Transparent" data-disabled={false} + data-focused={false} data-interactive={true} data-padded={true} data-shape="rectangle" @@ -443,6 +448,7 @@ exports[` snapshot should match snapshot with image 1`] = ` data-allow-text-select={false} data-color="Transparent" data-disabled={false} + data-focused={false} data-interactive={true} data-padded={true} data-shape="rectangle" @@ -557,6 +563,7 @@ exports[` snapshot should match snapshot with isDisabled 1`] data-allow-text-select={false} data-color="Transparent" data-disabled={true} + data-focused={false} data-interactive={true} data-padded={true} data-shape="rectangle" @@ -646,6 +653,7 @@ exports[` snapshot should match snapshot with style 1`] = ` data-allow-text-select={false} data-color="Transparent" data-disabled={false} + data-focused={false} data-interactive={true} data-padded={true} data-shape="rectangle" diff --git a/src/components/Menu/Menu.unit.test.tsx.snap b/src/components/Menu/Menu.unit.test.tsx.snap index b5bd0a1e4..742d3a99b 100644 --- a/src/components/Menu/Menu.unit.test.tsx.snap +++ b/src/components/Menu/Menu.unit.test.tsx.snap @@ -207,6 +207,7 @@ exports[` snapshot should match snapshot 1`] = ` className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="one" data-padded={true} @@ -438,6 +439,7 @@ exports[` snapshot should match snapshot 1`] = ` className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="two" data-padded={true} @@ -689,6 +691,7 @@ exports[` snapshot should match snapshot with className 1`] = ` className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="one" data-padded={true} @@ -920,6 +923,7 @@ exports[` snapshot should match snapshot with className 1`] = ` className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="two" data-padded={true} @@ -1171,6 +1175,7 @@ exports[` snapshot should match snapshot with className 2`] = ` className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="one" data-padded={true} @@ -1402,6 +1407,7 @@ exports[` snapshot should match snapshot with className 2`] = ` className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="two" data-padded={true} @@ -1654,6 +1660,7 @@ exports[` snapshot should match snapshot with id 1`] = ` className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="one" data-padded={true} @@ -1885,6 +1892,7 @@ exports[` snapshot should match snapshot with id 1`] = ` className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="two" data-padded={true} @@ -2137,6 +2145,7 @@ exports[` snapshot should match snapshot with itemShape 1`] = ` className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="one" data-padded={true} @@ -2368,6 +2377,7 @@ exports[` snapshot should match snapshot with itemShape 1`] = ` className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="two" data-padded={true} @@ -2619,6 +2629,7 @@ exports[` snapshot should match snapshot with itemSize 1`] = ` className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="one" data-padded={true} @@ -2850,6 +2861,7 @@ exports[` snapshot should match snapshot with itemSize 1`] = ` className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="two" data-padded={true} @@ -3146,6 +3158,7 @@ exports[` snapshot should match snapshot with seperator between items 1` className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="one" data-padded={true} @@ -3429,6 +3442,7 @@ exports[` snapshot should match snapshot with seperator between items 1` className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="two" data-padded={true} @@ -4448,6 +4462,7 @@ exports[` snapshot should match snapshot with seperator within section 1 className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="1-one" data-padded={true} @@ -4989,6 +5004,7 @@ exports[` snapshot should match snapshot with seperator within section 1 className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="1-two" data-padded={true} @@ -5998,6 +6014,7 @@ exports[` snapshot should match snapshot with seperator within section 1 className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="2-one" data-padded={true} @@ -6539,6 +6556,7 @@ exports[` snapshot should match snapshot with seperator within section 1 className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="2-two" data-padded={true} @@ -7673,6 +7691,7 @@ exports[` snapshot should match snapshot with seperator within selection className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="1-one" data-padded={true} @@ -8264,6 +8283,7 @@ exports[` snapshot should match snapshot with seperator within selection className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="1-two" data-padded={true} @@ -9385,6 +9405,7 @@ exports[` snapshot should match snapshot with seperator within selection className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="2-one" data-padded={true} @@ -9976,6 +9997,7 @@ exports[` snapshot should match snapshot with seperator within selection className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="2-two" data-padded={true} @@ -10239,6 +10261,7 @@ exports[` snapshot should match snapshot with style 1`] = ` className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="one" data-padded={true} @@ -10470,6 +10493,7 @@ exports[` snapshot should match snapshot with style 1`] = ` className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="two" data-padded={true} @@ -10722,6 +10746,7 @@ exports[` snapshot should match snapshot with tickPosition 1`] = ` className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="one" data-padded={true} @@ -10964,6 +10989,7 @@ exports[` snapshot should match snapshot with tickPosition 1`] = ` className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="two" data-padded={true} diff --git a/src/components/MenuItem/MenuItem.unit.test.tsx.snap b/src/components/MenuItem/MenuItem.unit.test.tsx.snap index 1b8c068c7..852c7a42d 100644 --- a/src/components/MenuItem/MenuItem.unit.test.tsx.snap +++ b/src/components/MenuItem/MenuItem.unit.test.tsx.snap @@ -249,6 +249,7 @@ exports[` snapshot should match snapshot 1`] = ` className="md-menu-item-wrapper some-classname md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="$.0" data-padded={true} @@ -554,6 +555,7 @@ exports[` snapshot should match snapshot with tickPosition 1`] = ` className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="$.0" data-padded={true} diff --git a/src/components/MenuSection/MenuSection.unit.test.tsx.snap b/src/components/MenuSection/MenuSection.unit.test.tsx.snap index e1f2efaa4..4da024497 100644 --- a/src/components/MenuSection/MenuSection.unit.test.tsx.snap +++ b/src/components/MenuSection/MenuSection.unit.test.tsx.snap @@ -451,6 +451,7 @@ exports[` snapshot should match snapshot 1`] = ` className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="$.0.0" data-padded={true} @@ -727,6 +728,7 @@ exports[` snapshot should match snapshot 1`] = ` className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="$.0.1" data-padded={true} @@ -1310,6 +1312,7 @@ exports[` snapshot should match snapshot with seperator 1`] = ` className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="$.0.0" data-padded={true} @@ -1636,6 +1639,7 @@ exports[` snapshot should match snapshot with seperator 1`] = ` className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="$.0.1" data-padded={true} diff --git a/src/components/MenuSelectionGroup/MenuSelectionGroup.unit.test.tsx.snap b/src/components/MenuSelectionGroup/MenuSelectionGroup.unit.test.tsx.snap index 580d0f95d..e603ed2be 100644 --- a/src/components/MenuSelectionGroup/MenuSelectionGroup.unit.test.tsx.snap +++ b/src/components/MenuSelectionGroup/MenuSelectionGroup.unit.test.tsx.snap @@ -549,6 +549,7 @@ exports[` snapshot should match snapshot 1`] = ` className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="$.0.0" data-padded={true} @@ -863,6 +864,7 @@ exports[` snapshot should match snapshot 1`] = ` className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="$.0.1" data-padded={true} @@ -1549,6 +1551,7 @@ exports[` snapshot should match snapshot with seperator wi className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="$.0.0" data-padded={true} @@ -1915,6 +1918,7 @@ exports[` snapshot should match snapshot with seperator wi className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="$.0.1" data-padded={true} diff --git a/src/components/MenuTrigger/MenuTrigger.unit.test.tsx.snap b/src/components/MenuTrigger/MenuTrigger.unit.test.tsx.snap index b812646f4..c4a2ce1d3 100644 --- a/src/components/MenuTrigger/MenuTrigger.unit.test.tsx.snap +++ b/src/components/MenuTrigger/MenuTrigger.unit.test.tsx.snap @@ -82,6 +82,7 @@ exports[` - Enzyme snapshot should match snapshot 1`] = ` "strategy": "absolute", } } + removeTippyAriaHidden={false} render={[Function]} setInstance={[Function]} trigger="click" @@ -303,6 +304,7 @@ exports[` - Enzyme snapshot should match snapshot 1`] = ` class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="one" data-padded="true" @@ -324,6 +326,7 @@ exports[` - Enzyme snapshot should match snapshot 1`] = ` class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="two" data-padded="true" @@ -345,6 +348,7 @@ exports[` - Enzyme snapshot should match snapshot 1`] = ` class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="three" data-padded="true" @@ -377,6 +381,7 @@ exports[` - Enzyme snapshot should match snapshot 1`] = ` class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="asd" data-padded="true" @@ -398,6 +403,7 @@ exports[` - Enzyme snapshot should match snapshot 1`] = ` class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="ff" data-padded="true" @@ -419,6 +425,7 @@ exports[` - Enzyme snapshot should match snapshot 1`] = ` class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="d" data-padded="true" @@ -735,6 +742,7 @@ exports[` - Enzyme snapshot should match snapshot 1`] = ` className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="one" data-padded={true} @@ -1012,6 +1020,7 @@ exports[` - Enzyme snapshot should match snapshot 1`] = ` className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="two" data-padded={true} @@ -1289,6 +1298,7 @@ exports[` - Enzyme snapshot should match snapshot 1`] = ` className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="three" data-padded={true} @@ -1591,6 +1601,7 @@ exports[` - Enzyme snapshot should match snapshot 1`] = ` className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="asd" data-padded={true} @@ -1868,6 +1879,7 @@ exports[` - Enzyme snapshot should match snapshot 1`] = ` className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="ff" data-padded={true} @@ -2145,6 +2157,7 @@ exports[` - Enzyme snapshot should match snapshot 1`] = ` className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="d" data-padded={true} @@ -2284,6 +2297,7 @@ exports[` - Enzyme snapshot should match snapshot with className "strategy": "absolute", } } + removeTippyAriaHidden={false} render={[Function]} setInstance={[Function]} trigger="click" @@ -2505,6 +2519,7 @@ exports[` - Enzyme snapshot should match snapshot with className class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="one" data-padded="true" @@ -2526,6 +2541,7 @@ exports[` - Enzyme snapshot should match snapshot with className class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="two" data-padded="true" @@ -2547,6 +2563,7 @@ exports[` - Enzyme snapshot should match snapshot with className class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="three" data-padded="true" @@ -2579,6 +2596,7 @@ exports[` - Enzyme snapshot should match snapshot with className class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="asd" data-padded="true" @@ -2600,6 +2618,7 @@ exports[` - Enzyme snapshot should match snapshot with className class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="ff" data-padded="true" @@ -2621,6 +2640,7 @@ exports[` - Enzyme snapshot should match snapshot with className class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="d" data-padded="true" @@ -2937,6 +2957,7 @@ exports[` - Enzyme snapshot should match snapshot with className className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="one" data-padded={true} @@ -3214,6 +3235,7 @@ exports[` - Enzyme snapshot should match snapshot with className className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="two" data-padded={true} @@ -3491,6 +3513,7 @@ exports[` - Enzyme snapshot should match snapshot with className className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="three" data-padded={true} @@ -3793,6 +3816,7 @@ exports[` - Enzyme snapshot should match snapshot with className className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="asd" data-padded={true} @@ -4070,6 +4094,7 @@ exports[` - Enzyme snapshot should match snapshot with className className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="ff" data-padded={true} @@ -4347,6 +4372,7 @@ exports[` - Enzyme snapshot should match snapshot with className className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="d" data-padded={true} @@ -4486,6 +4512,7 @@ exports[` - Enzyme snapshot should match snapshot with color 1`] "strategy": "absolute", } } + removeTippyAriaHidden={false} render={[Function]} setInstance={[Function]} trigger="click" @@ -4707,6 +4734,7 @@ exports[` - Enzyme snapshot should match snapshot with color 1`] class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="one" data-padded="true" @@ -4728,6 +4756,7 @@ exports[` - Enzyme snapshot should match snapshot with color 1`] class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="two" data-padded="true" @@ -4749,6 +4778,7 @@ exports[` - Enzyme snapshot should match snapshot with color 1`] class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="three" data-padded="true" @@ -4781,6 +4811,7 @@ exports[` - Enzyme snapshot should match snapshot with color 1`] class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="asd" data-padded="true" @@ -4802,6 +4833,7 @@ exports[` - Enzyme snapshot should match snapshot with color 1`] class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="ff" data-padded="true" @@ -4823,6 +4855,7 @@ exports[` - Enzyme snapshot should match snapshot with color 1`] class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="d" data-padded="true" @@ -5139,6 +5172,7 @@ exports[` - Enzyme snapshot should match snapshot with color 1`] className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="one" data-padded={true} @@ -5416,6 +5450,7 @@ exports[` - Enzyme snapshot should match snapshot with color 1`] className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="two" data-padded={true} @@ -5693,6 +5728,7 @@ exports[` - Enzyme snapshot should match snapshot with color 1`] className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="three" data-padded={true} @@ -5995,6 +6031,7 @@ exports[` - Enzyme snapshot should match snapshot with color 1`] className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="asd" data-padded={true} @@ -6272,6 +6309,7 @@ exports[` - Enzyme snapshot should match snapshot with color 1`] className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="ff" data-padded={true} @@ -6549,6 +6587,7 @@ exports[` - Enzyme snapshot should match snapshot with color 1`] className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="d" data-padded={true} @@ -6689,6 +6728,7 @@ exports[` - Enzyme snapshot should match snapshot with id 1`] = ` "strategy": "absolute", } } + removeTippyAriaHidden={false} render={[Function]} setInstance={[Function]} trigger="click" @@ -6911,6 +6951,7 @@ exports[` - Enzyme snapshot should match snapshot with id 1`] = ` class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="one" data-padded="true" @@ -6932,6 +6973,7 @@ exports[` - Enzyme snapshot should match snapshot with id 1`] = ` class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="two" data-padded="true" @@ -6953,6 +6995,7 @@ exports[` - Enzyme snapshot should match snapshot with id 1`] = ` class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="three" data-padded="true" @@ -6985,6 +7028,7 @@ exports[` - Enzyme snapshot should match snapshot with id 1`] = ` class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="asd" data-padded="true" @@ -7006,6 +7050,7 @@ exports[` - Enzyme snapshot should match snapshot with id 1`] = ` class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="ff" data-padded="true" @@ -7027,6 +7072,7 @@ exports[` - Enzyme snapshot should match snapshot with id 1`] = ` class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="d" data-padded="true" @@ -7345,6 +7391,7 @@ exports[` - Enzyme snapshot should match snapshot with id 1`] = ` className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="one" data-padded={true} @@ -7622,6 +7669,7 @@ exports[` - Enzyme snapshot should match snapshot with id 1`] = ` className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="two" data-padded={true} @@ -7899,6 +7947,7 @@ exports[` - Enzyme snapshot should match snapshot with id 1`] = ` className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="three" data-padded={true} @@ -8201,6 +8250,7 @@ exports[` - Enzyme snapshot should match snapshot with id 1`] = ` className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="asd" data-padded={true} @@ -8478,6 +8528,7 @@ exports[` - Enzyme snapshot should match snapshot with id 1`] = ` className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="ff" data-padded={true} @@ -8755,6 +8806,7 @@ exports[` - Enzyme snapshot should match snapshot with id 1`] = ` className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="d" data-padded={true} @@ -8894,6 +8946,7 @@ exports[` - Enzyme snapshot should match snapshot with placement "strategy": "absolute", } } + removeTippyAriaHidden={false} render={[Function]} setInstance={[Function]} trigger="click" @@ -9115,6 +9168,7 @@ exports[` - Enzyme snapshot should match snapshot with placement class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="one" data-padded="true" @@ -9136,6 +9190,7 @@ exports[` - Enzyme snapshot should match snapshot with placement class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="two" data-padded="true" @@ -9157,6 +9212,7 @@ exports[` - Enzyme snapshot should match snapshot with placement class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="three" data-padded="true" @@ -9189,6 +9245,7 @@ exports[` - Enzyme snapshot should match snapshot with placement class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="asd" data-padded="true" @@ -9210,6 +9267,7 @@ exports[` - Enzyme snapshot should match snapshot with placement class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="ff" data-padded="true" @@ -9231,6 +9289,7 @@ exports[` - Enzyme snapshot should match snapshot with placement class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="d" data-padded="true" @@ -9547,6 +9606,7 @@ exports[` - Enzyme snapshot should match snapshot with placement className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="one" data-padded={true} @@ -9824,6 +9884,7 @@ exports[` - Enzyme snapshot should match snapshot with placement className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="two" data-padded={true} @@ -10101,6 +10162,7 @@ exports[` - Enzyme snapshot should match snapshot with placement className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="three" data-padded={true} @@ -10403,6 +10465,7 @@ exports[` - Enzyme snapshot should match snapshot with placement className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="asd" data-padded={true} @@ -10680,6 +10743,7 @@ exports[` - Enzyme snapshot should match snapshot with placement className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="ff" data-padded={true} @@ -10957,6 +11021,7 @@ exports[` - Enzyme snapshot should match snapshot with placement className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="d" data-padded={true} @@ -11096,6 +11161,7 @@ exports[` - Enzyme snapshot should match snapshot with showArrow "strategy": "absolute", } } + removeTippyAriaHidden={false} render={[Function]} setInstance={[Function]} trigger="click" @@ -11317,6 +11383,7 @@ exports[` - Enzyme snapshot should match snapshot with showArrow class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="one" data-padded="true" @@ -11338,6 +11405,7 @@ exports[` - Enzyme snapshot should match snapshot with showArrow class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="two" data-padded="true" @@ -11359,6 +11427,7 @@ exports[` - Enzyme snapshot should match snapshot with showArrow class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="three" data-padded="true" @@ -11391,6 +11460,7 @@ exports[` - Enzyme snapshot should match snapshot with showArrow class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="asd" data-padded="true" @@ -11412,6 +11482,7 @@ exports[` - Enzyme snapshot should match snapshot with showArrow class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="ff" data-padded="true" @@ -11433,6 +11504,7 @@ exports[` - Enzyme snapshot should match snapshot with showArrow class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="d" data-padded="true" @@ -11780,6 +11852,7 @@ exports[` - Enzyme snapshot should match snapshot with showArrow className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="one" data-padded={true} @@ -12057,6 +12130,7 @@ exports[` - Enzyme snapshot should match snapshot with showArrow className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="two" data-padded={true} @@ -12334,6 +12408,7 @@ exports[` - Enzyme snapshot should match snapshot with showArrow className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="three" data-padded={true} @@ -12636,6 +12711,7 @@ exports[` - Enzyme snapshot should match snapshot with showArrow className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="asd" data-padded={true} @@ -12913,6 +12989,7 @@ exports[` - Enzyme snapshot should match snapshot with showArrow className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="ff" data-padded={true} @@ -13190,6 +13267,7 @@ exports[` - Enzyme snapshot should match snapshot with showArrow className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="d" data-padded={true} @@ -13373,6 +13451,7 @@ exports[` - Enzyme snapshot should match snapshot with style 1`] "strategy": "absolute", } } + removeTippyAriaHidden={false} render={[Function]} setInstance={[Function]} trigger="click" @@ -13595,6 +13674,7 @@ exports[` - Enzyme snapshot should match snapshot with style 1`] class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="one" data-padded="true" @@ -13616,6 +13696,7 @@ exports[` - Enzyme snapshot should match snapshot with style 1`] class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="two" data-padded="true" @@ -13637,6 +13718,7 @@ exports[` - Enzyme snapshot should match snapshot with style 1`] class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="three" data-padded="true" @@ -13669,6 +13751,7 @@ exports[` - Enzyme snapshot should match snapshot with style 1`] class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="asd" data-padded="true" @@ -13690,6 +13773,7 @@ exports[` - Enzyme snapshot should match snapshot with style 1`] class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="ff" data-padded="true" @@ -13711,6 +13795,7 @@ exports[` - Enzyme snapshot should match snapshot with style 1`] class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="d" data-padded="true" @@ -14037,6 +14122,7 @@ exports[` - Enzyme snapshot should match snapshot with style 1`] className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="one" data-padded={true} @@ -14314,6 +14400,7 @@ exports[` - Enzyme snapshot should match snapshot with style 1`] className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="two" data-padded={true} @@ -14591,6 +14678,7 @@ exports[` - Enzyme snapshot should match snapshot with style 1`] className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="three" data-padded={true} @@ -14893,6 +14981,7 @@ exports[` - Enzyme snapshot should match snapshot with style 1`] className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="asd" data-padded={true} @@ -15170,6 +15259,7 @@ exports[` - Enzyme snapshot should match snapshot with style 1`] className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="ff" data-padded={true} @@ -15447,6 +15537,7 @@ exports[` - Enzyme snapshot should match snapshot with style 1`] className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="d" data-padded={true} @@ -15586,6 +15677,7 @@ exports[` - Enzyme snapshot should match snapshot with variant 1` "strategy": "absolute", } } + removeTippyAriaHidden={false} render={[Function]} setInstance={[Function]} trigger="click" @@ -15807,6 +15899,7 @@ exports[` - Enzyme snapshot should match snapshot with variant 1` class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="one" data-padded="true" @@ -15828,6 +15921,7 @@ exports[` - Enzyme snapshot should match snapshot with variant 1` class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="two" data-padded="true" @@ -15849,6 +15943,7 @@ exports[` - Enzyme snapshot should match snapshot with variant 1` class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="three" data-padded="true" @@ -15881,6 +15976,7 @@ exports[` - Enzyme snapshot should match snapshot with variant 1` class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="asd" data-padded="true" @@ -15902,6 +15998,7 @@ exports[` - Enzyme snapshot should match snapshot with variant 1` class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="ff" data-padded="true" @@ -15923,6 +16020,7 @@ exports[` - Enzyme snapshot should match snapshot with variant 1` class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="d" data-padded="true" @@ -16239,6 +16337,7 @@ exports[` - Enzyme snapshot should match snapshot with variant 1` className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="one" data-padded={true} @@ -16516,6 +16615,7 @@ exports[` - Enzyme snapshot should match snapshot with variant 1` className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="two" data-padded={true} @@ -16793,6 +16893,7 @@ exports[` - Enzyme snapshot should match snapshot with variant 1` className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="three" data-padded={true} @@ -17095,6 +17196,7 @@ exports[` - Enzyme snapshot should match snapshot with variant 1` className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="asd" data-padded={true} @@ -17372,6 +17474,7 @@ exports[` - Enzyme snapshot should match snapshot with variant 1` className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="ff" data-padded={true} @@ -17649,6 +17752,7 @@ exports[` - Enzyme snapshot should match snapshot with variant 1` className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="d" data-padded={true} @@ -17789,6 +17893,7 @@ exports[` - Enzyme snapshot should match snapshot with zIndex 1`] "strategy": "absolute", } } + removeTippyAriaHidden={false} render={[Function]} setInstance={[Function]} trigger="click" @@ -18013,6 +18118,7 @@ exports[` - Enzyme snapshot should match snapshot with zIndex 1`] class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="one" data-padded="true" @@ -18034,6 +18140,7 @@ exports[` - Enzyme snapshot should match snapshot with zIndex 1`] class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="two" data-padded="true" @@ -18055,6 +18162,7 @@ exports[` - Enzyme snapshot should match snapshot with zIndex 1`] class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="three" data-padded="true" @@ -18087,6 +18195,7 @@ exports[` - Enzyme snapshot should match snapshot with zIndex 1`] class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="asd" data-padded="true" @@ -18108,6 +18217,7 @@ exports[` - Enzyme snapshot should match snapshot with zIndex 1`] class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="ff" data-padded="true" @@ -18129,6 +18239,7 @@ exports[` - Enzyme snapshot should match snapshot with zIndex 1`] class="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="d" data-padded="true" @@ -18445,6 +18556,7 @@ exports[` - Enzyme snapshot should match snapshot with zIndex 1`] className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="one" data-padded={true} @@ -18722,6 +18834,7 @@ exports[` - Enzyme snapshot should match snapshot with zIndex 1`] className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="two" data-padded={true} @@ -18999,6 +19112,7 @@ exports[` - Enzyme snapshot should match snapshot with zIndex 1`] className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="three" data-padded={true} @@ -19301,6 +19415,7 @@ exports[` - Enzyme snapshot should match snapshot with zIndex 1`] className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="asd" data-padded={true} @@ -19578,6 +19693,7 @@ exports[` - Enzyme snapshot should match snapshot with zIndex 1`] className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="ff" data-padded={true} @@ -19855,6 +19971,7 @@ exports[` - Enzyme snapshot should match snapshot with zIndex 1`] className="md-menu-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="d" data-padded={true} diff --git a/src/components/Popover/LazyTippy.tsx b/src/components/Popover/LazyTippy.tsx index 1f8de095c..d3d622ce5 100644 --- a/src/components/Popover/LazyTippy.tsx +++ b/src/components/Popover/LazyTippy.tsx @@ -1,11 +1,11 @@ import React, { FC, useMemo } from 'react'; import type { Instance as TippyInstance } from 'tippy.js'; - import Tippy, { TippyProps } from '@tippyjs/react'; export type LazyTippyProps = TippyProps & { setInstance?: (instance?: TippyInstance) => void; continuePropagationOnTrigger?: boolean; + removeTippyAriaHidden?: boolean; }; /** @@ -15,7 +15,10 @@ export type LazyTippyProps = TippyProps & { * lazified so that it will only be mounted to the DOM, whenever it is triggered to do so. */ export const LazyTippy: FC = React.forwardRef( - ({ setInstance, continuePropagationOnTrigger, ...props }: LazyTippyProps, ref) => { + ( + { setInstance, continuePropagationOnTrigger, removeTippyAriaHidden, ...props }: LazyTippyProps, + ref + ) => { const [mounted, setMounted] = React.useState(false); const stopPropagationPlugin = { @@ -30,7 +33,12 @@ export const LazyTippy: FC = React.forwardRef( const lazyPlugin = { fn: () => ({ - onMount: () => setMounted(true), + onMount: (instance: TippyInstance) => { + if (removeTippyAriaHidden) { + instance.popper.removeAttribute('aria-hidden'); + } + setMounted(true); + }, onHidden: () => setMounted(false), }), }; diff --git a/src/components/Popover/Popover.constants.ts b/src/components/Popover/Popover.constants.ts index 0b69c6b37..9ccf4d72a 100644 --- a/src/components/Popover/Popover.constants.ts +++ b/src/components/Popover/Popover.constants.ts @@ -37,6 +37,7 @@ const DEFAULTS = { STRATEGY: 'absolute' as const, ADD_BACKDROP: true, ROLE: MODAL_CONTAINER_CONSTANTS.DEFAULTS.ROLE, + REMOVE_TIPPY_ARIA_HIDDEN: false, APPEND_TO: 'parent' as const, DISABLE_FOCUS_LOCK: false, }; diff --git a/src/components/Popover/Popover.tsx b/src/components/Popover/Popover.tsx index f421c8445..98db3b3a8 100644 --- a/src/components/Popover/Popover.tsx +++ b/src/components/Popover/Popover.tsx @@ -52,6 +52,7 @@ const Popover = forwardRef((props: Props, ref: ForwardedRef) => { closeButtonProps, strategy = DEFAULTS.STRATEGY, role = DEFAULTS.ROLE, + removeTippyAriaHidden = DEFAULTS.REMOVE_TIPPY_ARIA_HIDDEN, onAfterUpdate, onBeforeUpdate, onCreate, @@ -179,6 +180,7 @@ const Popover = forwardRef((props: Props, ref: ForwardedRef) => { ref={ref} /* needed to prevent the popover from closing when the focus is changed via click events */ hideOnClick={!trigger.includes('manual')} + removeTippyAriaHidden={removeTippyAriaHidden} continuePropagationOnTrigger={continuePropagationOnTrigger} render={(attrs) => ( * @default `false` */ disableFocusLock?: boolean; + + /** + * Used to control whether aria-hidden attribute is retained on tippy. + * Enable it when you need Tippy to support some accessibility features. + * @default `false` + */ + removeTippyAriaHidden?: boolean; } diff --git a/src/components/Select/Select.unit.test.tsx.snap b/src/components/Select/Select.unit.test.tsx.snap index 614945a5b..d77de12f6 100644 --- a/src/components/Select/Select.unit.test.tsx.snap +++ b/src/components/Select/Select.unit.test.tsx.snap @@ -367,6 +367,7 @@ exports[`Select snapshot should match snapshot 1`] = ` "strategy": "absolute", } } + removeTippyAriaHidden={false} render={[Function]} setInstance={[Function]} trigger="manual" @@ -932,6 +933,7 @@ exports[`Select snapshot should match snapshot before and after opening select d "strategy": "absolute", } } + removeTippyAriaHidden={false} render={[Function]} setInstance={[Function]} trigger="manual" @@ -1498,6 +1500,7 @@ exports[`Select snapshot should match snapshot before and after opening select d "strategy": "absolute", } } + removeTippyAriaHidden={false} render={[Function]} setInstance={[Function]} trigger="manual" @@ -1713,6 +1716,7 @@ exports[`Select snapshot should match snapshot before and after opening select d class="md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="true" data-interactive="true" data-key="$.0" data-padded="true" @@ -1735,6 +1739,7 @@ exports[`Select snapshot should match snapshot before and after opening select d class="md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="$.1" data-padded="true" @@ -2023,6 +2028,7 @@ exports[`Select snapshot should match snapshot before and after opening select d data-key="$.0" id="test-ID-option-$.0" isDisabled={false} + isFocused={true} isPadded={true} key="$.0" onClick={[Function]} @@ -2057,6 +2063,7 @@ exports[`Select snapshot should match snapshot before and after opening select d className="md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={true} data-interactive={true} data-key="$.0" data-padded={true} @@ -2132,6 +2139,7 @@ exports[`Select snapshot should match snapshot before and after opening select d data-key="$.1" id="test-ID-option-$.1" isDisabled={false} + isFocused={false} isPadded={true} key="$.1" onClick={[Function]} @@ -2166,6 +2174,7 @@ exports[`Select snapshot should match snapshot before and after opening select d className="md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="$.1" data-padded={true} @@ -2595,6 +2604,7 @@ exports[`Select snapshot should match snapshot with border 1`] = ` "strategy": "absolute", } } + removeTippyAriaHidden={false} render={[Function]} setInstance={[Function]} trigger="manual" @@ -3161,6 +3171,7 @@ exports[`Select snapshot should match snapshot with className 1`] = ` "strategy": "absolute", } } + removeTippyAriaHidden={false} render={[Function]} setInstance={[Function]} trigger="manual" @@ -3727,6 +3738,7 @@ exports[`Select snapshot should match snapshot with direction 1`] = ` "strategy": "absolute", } } + removeTippyAriaHidden={false} render={[Function]} setInstance={[Function]} trigger="manual" @@ -4303,6 +4315,7 @@ exports[`Select snapshot should match snapshot with disabled option 1`] = ` "strategy": "absolute", } } + removeTippyAriaHidden={false} render={[Function]} setInstance={[Function]} trigger="manual" @@ -4518,6 +4531,7 @@ exports[`Select snapshot should match snapshot with disabled option 1`] = ` class="md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="true" + data-focused="false" data-interactive="true" data-key="$.0" data-padded="true" @@ -4540,6 +4554,7 @@ exports[`Select snapshot should match snapshot with disabled option 1`] = ` class="md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="true" data-interactive="true" data-key="$.1" data-padded="true" @@ -4832,6 +4847,7 @@ exports[`Select snapshot should match snapshot with disabled option 1`] = ` data-key="$.0" id="test-ID-option-$.0" isDisabled={true} + isFocused={false} isPadded={true} key="$.0" onClick={[Function]} @@ -4866,6 +4882,7 @@ exports[`Select snapshot should match snapshot with disabled option 1`] = ` className="md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={true} + data-focused={false} data-interactive={true} data-key="$.0" data-padded={true} @@ -4941,6 +4958,7 @@ exports[`Select snapshot should match snapshot with disabled option 1`] = ` data-key="$.1" id="test-ID-option-$.1" isDisabled={false} + isFocused={true} isPadded={true} key="$.1" onClick={[Function]} @@ -4975,6 +4993,7 @@ exports[`Select snapshot should match snapshot with disabled option 1`] = ` className="md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={true} data-interactive={true} data-key="$.1" data-padded={true} @@ -5403,6 +5422,7 @@ exports[`Select snapshot should match snapshot with id 1`] = ` "strategy": "absolute", } } + removeTippyAriaHidden={false} render={[Function]} setInstance={[Function]} trigger="manual" @@ -5733,6 +5753,7 @@ exports[`Select snapshot should match snapshot with isInForm = false 1`] = ` "strategy": "absolute", } } + removeTippyAriaHidden={false} render={[Function]} setInstance={[Function]} trigger="manual" @@ -6299,6 +6320,7 @@ exports[`Select snapshot should match snapshot with listbox opened 1`] = ` "strategy": "absolute", } } + removeTippyAriaHidden={false} render={[Function]} setInstance={[Function]} trigger="manual" @@ -6514,6 +6536,7 @@ exports[`Select snapshot should match snapshot with listbox opened 1`] = ` class="md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="true" data-interactive="true" data-key="$.0" data-padded="true" @@ -6536,6 +6559,7 @@ exports[`Select snapshot should match snapshot with listbox opened 1`] = ` class="md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="$.1" data-padded="true" @@ -6824,6 +6848,7 @@ exports[`Select snapshot should match snapshot with listbox opened 1`] = ` data-key="$.0" id="test-ID-option-$.0" isDisabled={false} + isFocused={true} isPadded={true} key="$.0" onClick={[Function]} @@ -6858,6 +6883,7 @@ exports[`Select snapshot should match snapshot with listbox opened 1`] = ` className="md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={true} data-interactive={true} data-key="$.0" data-padded={true} @@ -6933,6 +6959,7 @@ exports[`Select snapshot should match snapshot with listbox opened 1`] = ` data-key="$.1" id="test-ID-option-$.1" isDisabled={false} + isFocused={false} isPadded={true} key="$.1" onClick={[Function]} @@ -6967,6 +6994,7 @@ exports[`Select snapshot should match snapshot with listbox opened 1`] = ` className="md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="$.1" data-padded={true} @@ -7394,6 +7422,7 @@ exports[`Select snapshot should match snapshot with listboxMaxHeight 1`] = ` "strategy": "absolute", } } + removeTippyAriaHidden={false} render={[Function]} setInstance={[Function]} trigger="manual" @@ -7608,6 +7637,7 @@ exports[`Select snapshot should match snapshot with listboxMaxHeight 1`] = ` class="md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="true" data-interactive="true" data-key="$.0" data-padded="true" @@ -7630,6 +7660,7 @@ exports[`Select snapshot should match snapshot with listboxMaxHeight 1`] = ` class="md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="$.1" data-padded="true" @@ -7918,6 +7949,7 @@ exports[`Select snapshot should match snapshot with listboxMaxHeight 1`] = ` data-key="$.0" id="test-ID-option-$.0" isDisabled={false} + isFocused={true} isPadded={true} key="$.0" onClick={[Function]} @@ -7952,6 +7984,7 @@ exports[`Select snapshot should match snapshot with listboxMaxHeight 1`] = ` className="md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={true} data-interactive={true} data-key="$.0" data-padded={true} @@ -8027,6 +8060,7 @@ exports[`Select snapshot should match snapshot with listboxMaxHeight 1`] = ` data-key="$.1" id="test-ID-option-$.1" isDisabled={false} + isFocused={false} isPadded={true} key="$.1" onClick={[Function]} @@ -8061,6 +8095,7 @@ exports[`Select snapshot should match snapshot with listboxMaxHeight 1`] = ` className="md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="$.1" data-padded={true} @@ -8488,6 +8523,7 @@ exports[`Select snapshot should match snapshot with listboxWidth 1`] = ` "strategy": "fixed", } } + removeTippyAriaHidden={false} render={[Function]} setInstance={[Function]} trigger="manual" @@ -8702,6 +8738,7 @@ exports[`Select snapshot should match snapshot with listboxWidth 1`] = ` class="md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="true" data-interactive="true" data-key="$.0" data-padded="true" @@ -8724,6 +8761,7 @@ exports[`Select snapshot should match snapshot with listboxWidth 1`] = ` class="md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="$.1" data-padded="true" @@ -9012,6 +9050,7 @@ exports[`Select snapshot should match snapshot with listboxWidth 1`] = ` data-key="$.0" id="test-ID-option-$.0" isDisabled={false} + isFocused={true} isPadded={true} key="$.0" onClick={[Function]} @@ -9046,6 +9085,7 @@ exports[`Select snapshot should match snapshot with listboxWidth 1`] = ` className="md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={true} data-interactive={true} data-key="$.0" data-padded={true} @@ -9121,6 +9161,7 @@ exports[`Select snapshot should match snapshot with listboxWidth 1`] = ` data-key="$.1" id="test-ID-option-$.1" isDisabled={false} + isFocused={false} isPadded={true} key="$.1" onClick={[Function]} @@ -9155,6 +9196,7 @@ exports[`Select snapshot should match snapshot with listboxWidth 1`] = ` className="md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="$.1" data-padded={true} @@ -9588,6 +9630,7 @@ exports[`Select snapshot should match snapshot with placeholder 1`] = ` "strategy": "absolute", } } + removeTippyAriaHidden={false} render={[Function]} setInstance={[Function]} trigger="manual" @@ -10185,6 +10228,7 @@ exports[`Select snapshot should match snapshot with selected option and listbox "strategy": "absolute", } } + removeTippyAriaHidden={false} render={[Function]} setInstance={[Function]} trigger="manual" @@ -10785,6 +10829,7 @@ exports[`Select snapshot should match snapshot with selected option and listbox "strategy": "absolute", } } + removeTippyAriaHidden={false} render={[Function]} setInstance={[Function]} trigger="manual" @@ -11003,6 +11048,7 @@ exports[`Select snapshot should match snapshot with selected option and listbox class="md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="true" data-interactive="true" data-key="$.0" data-padded="true" @@ -11047,6 +11093,7 @@ exports[`Select snapshot should match snapshot with selected option and listbox class="md-list-item-base-wrapper" data-allow-text-select="false" data-disabled="false" + data-focused="false" data-interactive="true" data-key="$.1" data-padded="true" @@ -11358,6 +11405,7 @@ exports[`Select snapshot should match snapshot with selected option and listbox data-key="$.0" id="test-ID-option-$.0" isDisabled={false} + isFocused={true} isPadded={true} key="$.0" onClick={[Function]} @@ -11392,6 +11440,7 @@ exports[`Select snapshot should match snapshot with selected option and listbox className="md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={true} data-interactive={true} data-key="$.0" data-padded={true} @@ -11505,6 +11554,7 @@ exports[`Select snapshot should match snapshot with selected option and listbox data-key="$.1" id="test-ID-option-$.1" isDisabled={false} + isFocused={false} isPadded={true} key="$.1" onClick={[Function]} @@ -11539,6 +11589,7 @@ exports[`Select snapshot should match snapshot with selected option and listbox className="md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-key="$.1" data-padded={true} @@ -11968,6 +12019,7 @@ exports[`Select snapshot should match snapshot with shallowDisabled 1`] = ` "strategy": "absolute", } } + removeTippyAriaHidden={false} render={[Function]} setInstance={[Function]} trigger="manual" @@ -12540,6 +12592,7 @@ exports[`Select snapshot should match snapshot with style 1`] = ` "strategy": "absolute", } } + removeTippyAriaHidden={false} render={[Function]} setInstance={[Function]} trigger="manual" @@ -13104,6 +13157,7 @@ exports[`Select snapshot should match snapshot with title 1`] = ` "strategy": "absolute", } } + removeTippyAriaHidden={false} render={[Function]} setInstance={[Function]} trigger="manual" diff --git a/src/components/SpaceListItem/SpaceListItem.unit.test.tsx.snap b/src/components/SpaceListItem/SpaceListItem.unit.test.tsx.snap index 21fd3ac5a..dec98c3f3 100644 --- a/src/components/SpaceListItem/SpaceListItem.unit.test.tsx.snap +++ b/src/components/SpaceListItem/SpaceListItem.unit.test.tsx.snap @@ -24,6 +24,7 @@ exports[` snapshot checks divider dot position in compact mode className="md-space-list-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-padded={false} data-shape="isPilled" @@ -155,6 +156,7 @@ exports[` snapshot should match snapshot 1`] = ` className="md-space-list-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-padded={false} data-shape="isPilled" @@ -252,6 +254,7 @@ exports[` snapshot should match snapshot with action 1`] = ` className="md-space-list-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-padded={false} data-shape="isPilled" @@ -354,6 +357,7 @@ exports[` snapshot should match snapshot with className 1`] = ` className="example-class md-space-list-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-padded={false} data-shape="isPilled" @@ -447,6 +451,7 @@ exports[` snapshot should match snapshot with firstLine 1`] = ` className="md-space-list-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-padded={false} data-shape="isPilled" @@ -544,6 +549,7 @@ exports[` snapshot should match snapshot with id 1`] = ` className="md-space-list-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-padded={false} data-shape="isPilled" @@ -638,6 +644,7 @@ exports[` snapshot should match snapshot with isAlert 1`] = ` className="md-space-list-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-padded={false} data-shape="isPilled" @@ -763,6 +770,7 @@ exports[` snapshot should match snapshot with isAlertMuted 1`] className="md-space-list-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-padded={false} data-shape="isPilled" @@ -888,6 +896,7 @@ exports[` snapshot should match snapshot with isDisabled 1`] = className="md-space-list-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={true} + data-focused={false} data-interactive={true} data-padded={false} data-shape="isPilled" @@ -981,6 +990,7 @@ exports[` snapshot should match snapshot with isEnterRoom 1`] = className="md-space-list-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-padded={false} data-shape="isPilled" @@ -1106,6 +1116,7 @@ exports[` snapshot should match snapshot with isError 1`] = ` className="md-space-list-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-padded={false} data-shape="isPilled" @@ -1231,6 +1242,7 @@ exports[` snapshot should match snapshot with isMention 1`] = ` className="md-space-list-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-padded={false} data-shape="isPilled" @@ -1356,6 +1368,7 @@ exports[` snapshot should match snapshot with isNewActivity 1`] className="md-space-list-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-padded={false} data-shape="isPilled" @@ -1451,6 +1464,7 @@ exports[` snapshot should match snapshot with isSelected 1`] = className="md-space-list-item-wrapper md-list-item-base-wrapper active" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-padded={false} data-shape="isPilled" @@ -1547,6 +1561,7 @@ exports[` snapshot should match snapshot with isSelected and dr className="md-space-list-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-padded={false} data-shape="isPilled" @@ -1673,6 +1688,7 @@ exports[` snapshot should match snapshot with isUnread 1`] = ` className="md-space-list-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-padded={false} data-shape="isPilled" @@ -1804,6 +1820,7 @@ exports[` snapshot should match snapshot with multiple string s className="md-space-list-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-padded={false} data-shape="isPilled" @@ -1959,6 +1976,7 @@ exports[` snapshot should match snapshot with secondLine 1`] = className="md-space-list-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-padded={false} data-shape="isPilled" @@ -2091,6 +2109,7 @@ exports[` snapshot should match snapshot with style 1`] = ` className="md-space-list-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-padded={false} data-shape="isPilled" @@ -2189,6 +2208,7 @@ exports[` snapshot should match snapshot with teamColor 1`] = ` className="md-space-list-item-wrapper md-list-item-base-wrapper" data-allow-text-select={false} data-disabled={false} + data-focused={false} data-interactive={true} data-padded={false} data-shape="isPilled" diff --git a/src/components/SpaceRowContent/SpaceRowContent.unit.test.tsx.snap b/src/components/SpaceRowContent/SpaceRowContent.unit.test.tsx.snap index 581886d7f..110c89f29 100644 --- a/src/components/SpaceRowContent/SpaceRowContent.unit.test.tsx.snap +++ b/src/components/SpaceRowContent/SpaceRowContent.unit.test.tsx.snap @@ -991,6 +991,7 @@ exports[` snapshot should match snapshot with menuItems 1`] = "strategy": "absolute", } } + removeTippyAriaHidden={false} render={[Function]} setInstance={[Function]} trigger="click" diff --git a/src/components/TooltipPopoverCombo/TooltipPopoverCombo.unit.test.tsx.snap b/src/components/TooltipPopoverCombo/TooltipPopoverCombo.unit.test.tsx.snap index ac0af48ea..4988169db 100644 --- a/src/components/TooltipPopoverCombo/TooltipPopoverCombo.unit.test.tsx.snap +++ b/src/components/TooltipPopoverCombo/TooltipPopoverCombo.unit.test.tsx.snap @@ -94,6 +94,7 @@ exports[` snapshot should match snapshot 1`] = ` "strategy": "absolute", } } + removeTippyAriaHidden={false} render={[Function]} setInstance={[Function]} trigger="click" @@ -310,6 +311,7 @@ exports[` snapshot should match snapshot 1`] = ` "strategy": "absolute", } } + removeTippyAriaHidden={false} render={[Function]} setInstance={[Function]} trigger="mouseenter focus" @@ -585,6 +587,7 @@ exports[` snapshot should match snapshot with otherPopove "strategy": "absolute", } } + removeTippyAriaHidden={false} render={[Function]} setInstance={[Function]} trigger="click" @@ -802,6 +805,7 @@ exports[` snapshot should match snapshot with otherPopove "strategy": "absolute", } } + removeTippyAriaHidden={false} render={[Function]} setInstance={[Function]} trigger="mouseenter focus" @@ -1077,6 +1081,7 @@ exports[` snapshot should match snapshot with otherToolti "strategy": "absolute", } } + removeTippyAriaHidden={false} render={[Function]} setInstance={[Function]} trigger="click" @@ -1294,6 +1299,7 @@ exports[` snapshot should match snapshot with otherToolti "strategy": "absolute", } } + removeTippyAriaHidden={false} render={[Function]} setInstance={[Function]} trigger="mouseenter focus" diff --git a/src/legacy/Lightbox/tests/index.spec.js.snap b/src/legacy/Lightbox/tests/index.spec.js.snap index f49e60f05..5e7f27600 100644 --- a/src/legacy/Lightbox/tests/index.spec.js.snap +++ b/src/legacy/Lightbox/tests/index.spec.js.snap @@ -380,6 +380,7 @@ exports[`tests for should match SnapShot 1`] = ` "strategy": "absolute", } } + removeTippyAriaHidden={false} render={[Function]} setInstance={[Function]} trigger="mouseenter focus" @@ -708,6 +709,7 @@ exports[`tests for should match SnapShot 1`] = ` "strategy": "absolute", } } + removeTippyAriaHidden={false} render={[Function]} setInstance={[Function]} trigger="mouseenter focus" @@ -988,6 +990,7 @@ exports[`tests for should match SnapShot 1`] = ` "strategy": "absolute", } } + removeTippyAriaHidden={false} render={[Function]} setInstance={[Function]} trigger="mouseenter focus" @@ -1271,6 +1274,7 @@ exports[`tests for should match SnapShot 1`] = ` "strategy": "absolute", } } + removeTippyAriaHidden={false} render={[Function]} setInstance={[Function]} trigger="mouseenter focus"