diff --git a/.changeset/odd-socks-hunt.md b/.changeset/odd-socks-hunt.md new file mode 100644 index 00000000000..7843ed2f006 --- /dev/null +++ b/.changeset/odd-socks-hunt.md @@ -0,0 +1,5 @@ +--- +'@primer/react': major +--- + +The Autocomplete component no longer uses the deprecated ActionList component. There have been minor API updates, but it's largely the same. diff --git a/docs/content/Autocomplete.mdx b/docs/content/Autocomplete.mdx index 84b943a1c56..630d031f8bf 100644 --- a/docs/content/Autocomplete.mdx +++ b/docs/content/Autocomplete.mdx @@ -63,14 +63,14 @@ A function may be passed to the `filterFn` prop if this default filtering behavi { - const [tokens, setTokens] = React.useState([{text: 'zero', id: 0}]) + const [tokens, setTokens] = React.useState([{text: 'zero', id: '0'}]) const selectedTokenIds = tokens.map(token => token.id) const [selectedItemIds, setSelectedItemIds] = React.useState(selectedTokenIds) const onTokenRemove = tokenId => { @@ -122,14 +122,14 @@ const CustomTextInputExample = () => { ) { const [tokens, setTokens] = React.useState([ - {text: 'enhancement', id: 1, fillColor: '#a2eeef'}, - {text: 'bug', id: 2, fillColor: '#d73a4a'}, - {text: 'good first issue', id: 3, fillColor: '#0cf478'}, + {text: 'enhancement', id: '1', fillColor: '#a2eeef'}, + {text: 'bug', id: '2', fillColor: '#d73a4a'}, + {text: 'good first issue', id: '3', fillColor: '#0cf478'}, ]) const selectedTokenIds = tokens.map(token => token.id) const [selectedItemIds, setSelectedItemIds] = React.useState(selectedTokenIds) @@ -236,18 +236,23 @@ const CustomRenderedItemExample = () => { { { { ) ```javascript live noinline const MultiSelect = () => { const items = [ - {text: 'main', id: 0}, - {text: 'autocomplete-tests', id: 1}, - {text: 'a11y-improvements', id: 22}, - {text: 'button-bug-fixes', id: 3}, - {text: 'radio-input-component', id: 4}, - {text: 'release-1.0.0', id: 5}, - {text: 'text-input-implementation', id: 6}, - {text: 'visual-design-tweaks', id: 7}, + {text: 'main', id: '0'}, + {text: 'autocomplete-tests', id: '1'}, + {text: 'a11y-improvements', id: '2'}, + {text: 'button-bug-fixes', id: '3'}, + {text: 'radio-input-component', id: '4'}, + {text: 'release-1.0.0', id: '5'}, + {text: 'text-input-implementation', id: '6'}, + {text: 'visual-design-tweaks', id: '7'}, ] const [selectedItemIds, setSelectedItemIds] = React.useState([]) const onSelectedChange = newlySelectedItems => { @@ -514,14 +519,14 @@ const MultiSelectAddNewItem = () => { } const [localItemsState, setLocalItemsState] = React.useState([ - {text: 'main', id: 0}, - {text: 'autocomplete-tests', id: 1}, - {text: 'a11y-improvements', id: 22}, - {text: 'button-bug-fixes', id: 3}, - {text: 'radio-input-component', id: 4}, - {text: 'release-1.0.0', id: 5}, - {text: 'text-input-implementation', id: 6}, - {text: 'visual-design-tweaks', id: 7}, + {text: 'main', id: '0'}, + {text: 'autocomplete-tests', id: '1'}, + {text: 'a11y-improvements', id: '2'}, + {text: 'button-bug-fixes', id: '3'}, + {text: 'radio-input-component', id: '4'}, + {text: 'release-1.0.0', id: '5'}, + {text: 'text-input-implementation', id: '6'}, + {text: 'visual-design-tweaks', id: '7'}, ]) const getItemById = id => localItemsState.find(item => item.id === id) const [filterVal, setFilterVal] = React.useState('') @@ -625,14 +630,14 @@ export function AutocompleteWithContextInternal() { = (item: T | T[]) => void -type AutocompleteMenuItem = MandateProps +export type AutocompleteMenuItem = MandateProps & { + leadingVisual?: React.FunctionComponent> + text?: string + trailingVisual?: React.FunctionComponent> +} -const getDefaultSortFn = - (isItemSelectedFn: (itemId: string | number) => boolean) => (itemIdA: string | number, itemIdB: string | number) => - isItemSelectedFn(itemIdA) === isItemSelectedFn(itemIdB) ? 0 : isItemSelectedFn(itemIdA) ? -1 : 1 +const getDefaultSortFn = (isItemSelectedFn: (itemId: string) => boolean) => (itemIdA: string, itemIdB: string) => + isItemSelectedFn(itemIdA) === isItemSelectedFn(itemIdB) ? 0 : isItemSelectedFn(itemIdA) ? -1 : 1 const menuScrollMargins: ScrollIntoViewOptions = {startMargin: 0, endMargin: 8} function getDefaultItemFilter(filterValue: string) { @@ -34,23 +37,21 @@ function getdefaultCheckedSelectionChange( } } -const isItemSelected = (itemId: string | number, selectedItemIds: Array) => - selectedItemIds.includes(itemId) +const isItemSelected = (itemId: string, selectedItemIds: Array) => selectedItemIds.includes(itemId) -function getItemById(itemId: string | number, items: T[]) { +function getItemById(itemId: string, items: T[]) { return items.find(item => item.id === itemId) } // eslint-disable-next-line @typescript-eslint/no-explicit-any type AutocompleteItemProps> = AutocompleteMenuItem & {metadata?: T} -// TODO: we should make `aria-labelledby` required for a11y export type AutocompleteMenuInternalProps = { /** * A menu item that is used to allow users make a selection that is not available in the array passed to the `items` prop. * This menu item gets appended to the end of the list of options. */ - addNewItem?: Omit & { + addNewItem?: T & { handleAddItem: (item: Omit) => void } @@ -80,13 +81,13 @@ export type AutocompleteMenuInternalProps = { * The IDs of the selected items */ // NOTE: this diverges from the SelectPanel component API, where we pass an array of objects to the `selected` prop - selectedItemIds: Array + selectedItemIds: string[] /** * The sort function that is applied to the options in the array passed to the `items` prop after the user closes the menu. * By default, selected items are sorted to the top after the user closes the menu. */ - sortOnCloseFn?: (itemIdA: string | number, itemIdB: string | number) => number + sortOnCloseFn?: (itemIdA: string, itemIdB: string) => number /** * Whether there can be one item selected from the menu or multiple items selected from the menu @@ -109,7 +110,9 @@ export type AutocompleteMenuInternalProps = { * scrolls when the user highlights an item in the menu that is outside the scroll container */ customScrollContainerRef?: React.MutableRefObject -} & Pick + // TODO: instead of making this required, maybe we can infer aria-labelledby from the ID of the text input somehow? + ['aria-labelledby']: string +} function AutocompleteMenu(props: AutocompleteMenuInternalProps) { const autocompleteContext = useContext(AutocompleteContext) @@ -144,8 +147,9 @@ function AutocompleteMenu(props: AutocompleteMe customScrollContainerRef, } = props const listContainerRef = useRef(null) + const allItemsToRenderRef = useRef([]) const [highlightedItem, setHighlightedItem] = useState() - const [sortedItemIds, setSortedItemIds] = useState>(items.map(({id: itemId}) => itemId)) + const [sortedItemIds, setSortedItemIds] = useState>(items.map(({id: itemId}) => itemId)) const generatedUniqueId = useSSRSafeId(id) const selectableItems = useMemo( @@ -155,6 +159,7 @@ function AutocompleteMenu(props: AutocompleteMe ...selectableItem, role: 'option', id: selectableItem.id, + active: highlightedItem?.id === selectableItem.id, selected: selectionVariant === 'multiple' ? selectedItemIds.includes(selectableItem.id) : undefined, onAction: (item: T) => { const otherSelectedItemIds = selectedItemIds.filter(selectedItemId => selectedItemId !== item.id) @@ -180,6 +185,7 @@ function AutocompleteMenu(props: AutocompleteMe } }), [ + highlightedItem, items, selectedItemIds, inputRef, @@ -193,7 +199,7 @@ function AutocompleteMenu(props: AutocompleteMe const itemSortOrderData = useMemo( () => - sortedItemIds.reduce>((acc, curr, i) => { + sortedItemIds.reduce>((acc, curr, i) => { acc[curr] = i return acc @@ -219,6 +225,10 @@ function AutocompleteMenu(props: AutocompleteMe ? [ { ...addNewItem, + role: 'option', + key: addNewItem.id, + active: highlightedItem?.id === addNewItem.id, + selected: selectionVariant === 'multiple' ? selectedItemIds.includes(addNewItem.id) : undefined, leadingVisual: () => , onAction: (item: T) => { // TODO: make it possible to pass a leadingVisual when using `addNewItem` @@ -240,9 +250,15 @@ function AutocompleteMenu(props: AutocompleteMe selectionVariant, setInputValue, generatedUniqueId, + highlightedItem, + selectedItemIds, ], ) + React.useEffect(() => { + allItemsToRenderRef.current = allItemsToRender + }) + useFocusZone( { containerRef: listContainerRef, @@ -254,7 +270,9 @@ function AutocompleteMenu(props: AutocompleteMe onActiveDescendantChanged: (current, _previous, directlyActivated) => { activeDescendantRef.current = current || null if (current) { - const selectedItem = selectableItems.find(item => item.id.toString() === current.getAttribute('data-id')) + const selectedItem = allItemsToRenderRef.current.find(item => { + return item.id === current.closest('li')?.getAttribute('data-id') + }) setHighlightedItem(selectedItem) setIsMenuDirectlyActivated(directlyActivated) @@ -299,6 +317,10 @@ function AutocompleteMenu(props: AutocompleteMe } }, [selectedItemIds, setSelectedItemLength]) + if (selectionVariant === 'single' && selectedItemIds.length > 1) { + throw new Error('Autocomplete: selectionVariant "single" cannot be used with multiple selected items') + } + return ( {loading ? ( @@ -309,14 +331,37 @@ function AutocompleteMenu(props: AutocompleteMe
{allItemsToRender.length ? ( + > + {allItemsToRender.map(item => { + const { + id, + onAction, + text, + leadingVisual: LeadingVisual, + trailingVisual: TrailingVisual, + ...itemProps + } = item + return ( + onAction(item)} {...itemProps} id={id} data-id={id}> + {LeadingVisual && ( + + + + )} + {text} + {TrailingVisual && ( + + + + )} + + ) + })} + ) : ( {emptyStateText} )} diff --git a/src/__tests__/Autocomplete.test.tsx b/src/__tests__/Autocomplete.test.tsx index 4644690c15e..79a066b56df 100644 --- a/src/__tests__/Autocomplete.test.tsx +++ b/src/__tests__/Autocomplete.test.tsx @@ -2,40 +2,35 @@ import {render as HTMLRender, fireEvent, waitFor} from '@testing-library/react' import userEvent from '@testing-library/user-event' import React from 'react' import Autocomplete, {AutocompleteInputProps} from '../Autocomplete' -import {AutocompleteMenuInternalProps} from '../Autocomplete/AutocompleteMenu' +import {AutocompleteMenuInternalProps, AutocompleteMenuItem} from '../Autocomplete/AutocompleteMenu' import BaseStyles from '../BaseStyles' import theme from '../theme' import {ThemeProvider} from '../ThemeProvider' -import {ItemProps} from '../deprecated/ActionList' import {SSRProvider} from '../utils/ssr' import {render} from '../utils/testing' -import {MandateProps} from '../utils/types' const mockItems = [ - {text: 'zero', id: 0}, - {text: 'one', id: 1}, - {text: 'two', id: 2}, - {text: 'three', id: 3}, - {text: 'four', id: 4}, - {text: 'five', id: 5}, - {text: 'six', id: 6}, - {text: 'seven', id: 7}, - {text: 'twenty', id: 20}, - {text: 'twentyone', id: 21}, + {text: 'zero', id: '0'}, + {text: 'one', id: '1'}, + {text: 'two', id: '2'}, + {text: 'three', id: '3'}, + {text: 'four', id: '4'}, + {text: 'five', id: '5'}, + {text: 'six', id: '6'}, + {text: 'seven', id: '7'}, + {text: 'twenty', id: '20'}, + {text: 'twentyone', id: '21'}, ] -// eslint-disable-next-line @typescript-eslint/no-explicit-any -type AutocompleteItemProps> = MandateProps & {metadata?: T} - const AUTOCOMPLETE_LABEL = 'Autocomplete field' -const LabelledAutocomplete = ({ +const LabelledAutocomplete = ({ inputProps = {}, menuProps, }: { inputProps?: AutocompleteInputProps menuProps: AutocompleteMenuInternalProps }) => { - const {['aria-labelledby']: ariaLabelledBy = 'autocompleteLabel', ...menuPropsRest} = menuProps + const {['aria-labelledby']: ariaLabelledBy, ...menuPropsRest} = menuProps const {id = 'autocompleteInput', ...inputPropsRest} = inputProps return ( @@ -64,7 +59,7 @@ describe('Autocomplete', () => { const {container} = HTMLRender( , ) const inputNode = container.querySelector('#autocompleteInput') @@ -78,7 +73,7 @@ describe('Autocomplete', () => { const {container} = HTMLRender( , ) const inputNode = container.querySelector('#autocompleteInput') @@ -91,7 +86,10 @@ describe('Autocomplete', () => { it('calls onKeyDown', () => { const onKeyDownMock = jest.fn() const {getByLabelText} = HTMLRender( - , + , ) const inputNode = getByLabelText(AUTOCOMPLETE_LABEL) @@ -103,7 +101,10 @@ describe('Autocomplete', () => { it('calls onKeyUp', () => { const onKeyUpMock = jest.fn() const {getByLabelText} = HTMLRender( - , + , ) const inputNode = getByLabelText(AUTOCOMPLETE_LABEL) @@ -116,7 +117,10 @@ describe('Autocomplete', () => { const user = userEvent.setup() const onKeyPressMock = jest.fn() const {getByLabelText} = HTMLRender( - , + , ) const inputNode = getByLabelText(AUTOCOMPLETE_LABEL) @@ -126,7 +130,9 @@ describe('Autocomplete', () => { }) it('opens the menu when the input is focused', () => { - const {getByLabelText} = HTMLRender() + const {getByLabelText} = HTMLRender( + , + ) const inputNode = getByLabelText(AUTOCOMPLETE_LABEL) expect(inputNode.getAttribute('aria-expanded')).not.toBe('true') @@ -135,7 +141,9 @@ describe('Autocomplete', () => { }) it('closes the menu when the input is blurred', async () => { - const {getByLabelText} = HTMLRender() + const {getByLabelText} = HTMLRender( + , + ) const inputNode = getByLabelText(AUTOCOMPLETE_LABEL) expect(inputNode.getAttribute('aria-expanded')).not.toBe('true') @@ -151,7 +159,9 @@ describe('Autocomplete', () => { it('sets the input value to the suggested item text and highlights the untyped part of the word', async () => { const user = userEvent.setup() const {container, getByDisplayValue} = HTMLRender( - , + , ) const inputNode = container.querySelector('#autocompleteInput') @@ -162,7 +172,9 @@ describe('Autocomplete', () => { it('does not show or highlight suggestion text after the user hits Backspace until they hit another key', async () => { const user = userEvent.setup() const {container, getByDisplayValue} = HTMLRender( - , + , ) const inputNode = container.querySelector('#autocompleteInput') @@ -182,7 +194,11 @@ describe('Autocomplete', () => { it('clears the input value when the user hits Escape', async () => { const user = userEvent.setup() - const {container} = HTMLRender() + const {container} = HTMLRender( + , + ) const inputNode = container.querySelector('#autocompleteInput') expect(inputNode?.getAttribute('aria-expanded')).not.toBe('true') @@ -194,7 +210,10 @@ describe('Autocomplete', () => { it('allows the value to be 0', () => { const {getByDisplayValue} = HTMLRender( - , + , ) expect(getByDisplayValue('0')).toBeDefined() @@ -206,7 +225,14 @@ describe('Autocomplete', () => { const user = userEvent.setup() const filterFnMock = jest.fn() const {container} = HTMLRender( - , + , ) const inputNode = container.querySelector('#autocompleteInput') @@ -218,7 +244,14 @@ describe('Autocomplete', () => { const user = userEvent.setup() const sortOnCloseFnMock = jest.fn() const {container} = HTMLRender( - , + , ) const inputNode = container.querySelector('#autocompleteInput') @@ -239,7 +272,14 @@ describe('Autocomplete', () => { const user = userEvent.setup() const onOpenChangeMock = jest.fn() const {container} = HTMLRender( - , + , ) const inputNode = container.querySelector('#autocompleteInput') @@ -252,7 +292,12 @@ describe('Autocomplete', () => { const onSelectedChangeMock = jest.fn() const {container} = HTMLRender( , ) const inputNode = container.querySelector('#autocompleteInput') @@ -269,7 +314,14 @@ describe('Autocomplete', () => { it('does not close the menu when clicking an item in the menu if selectionVariant=multiple', async () => { const user = userEvent.setup() const {getByText, container} = HTMLRender( - , + , ) const inputNode = container.querySelector('#autocompleteInput') const itemToClickNode = getByText(mockItems[1].text) @@ -284,7 +336,14 @@ describe('Autocomplete', () => { it('closes the menu when clicking an item in the menu if selectionVariant=single', () => { const {getByText, container} = HTMLRender( - , + , ) const inputNode = container.querySelector('#autocompleteInput') const itemToClickNode = getByText(mockItems[1].text) @@ -305,9 +364,11 @@ describe('Autocomplete', () => { selectedItemIds: [], selectionVariant: 'multiple', addNewItem: { + id: 'add-new-item', text: 'Add new item', handleAddItem: handleAddItemMock, }, + ['aria-labelledby']: 'autocompleteLabel', }} />, ) @@ -318,6 +379,25 @@ describe('Autocomplete', () => { fireEvent.click(addNewItemNode) expect(handleAddItemMock).toHaveBeenCalled() }) + + it('throws an error when passing multiple items when selection="single"', () => { + const spy = jest.spyOn(console, 'error').mockImplementation(() => {}) + + expect(() => { + HTMLRender( + + + , + ) + }).toThrow('Autocomplete: selectionVariant "single" cannot be used with multiple selected items') + + spy.mockRestore() + }) }) describe('null context', () => { @@ -326,9 +406,9 @@ describe('Autocomplete', () => { expect(() => HTMLRender()).toThrow('AutocompleteContext returned null values') expect(() => HTMLRender()).toThrow('AutocompleteContext returned null values') - expect(() => HTMLRender()).toThrow( - 'AutocompleteContext returned null values', - ) + expect(() => + HTMLRender(), + ).toThrow('AutocompleteContext returned null values') spy.mockRestore() }) @@ -376,7 +456,7 @@ describe('snapshots', () => { @@ -398,6 +478,7 @@ describe('snapshots', () => { selectionVariant="multiple" selectedItemIds={[]} addNewItem={{ + id: 'add-new-item', text: 'Add new item', handleAddItem: handleAddItemMock, }} diff --git a/src/__tests__/__snapshots__/Autocomplete.test.tsx.snap b/src/__tests__/__snapshots__/Autocomplete.test.tsx.snap index 263505f77a8..96b6a0c497a 100644 --- a/src/__tests__/__snapshots__/Autocomplete.test.tsx.snap +++ b/src/__tests__/__snapshots__/Autocomplete.test.tsx.snap @@ -481,119 +481,33 @@ exports[`snapshots renders a menu that contains an item to add to the menu 1`] = type="text" /> , - .c0 { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - -webkit-clip: rect(0,0,0,0); - clip: rect(0,0,0,0); - white-space: nowrap; - border-width: 0; -} - -.c2 { - margin-top: 8px; - margin-bottom: 8px; -} - -.c8 { + .c5 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; - min-width: 0; - position: relative; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; -webkit-box-flex: 1; -webkit-flex-grow: 1; -ms-flex-positive: 1; flex-grow: 1; + min-width: 0; } -.c9 { - -webkit-align-items: baseline; - -webkit-box-align: baseline; - -ms-flex-align: baseline; - align-items: baseline; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - min-width: 0; - -webkit-flex-direction: var(--main-content-flex-direction); - -ms-flex-direction: var(--main-content-flex-direction); - flex-direction: var(--main-content-flex-direction); +.c6 { -webkit-box-flex: 1; -webkit-flex-grow: 1; -ms-flex-positive: 1; flex-grow: 1; + font-weight: 400; } .c4 { - padding: 6px 8px; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - border-radius: 6px; - color: #1F2328; - -webkit-transition: background 33.333ms linear; - transition: background 33.333ms linear; - -webkit-text-decoration: none; - text-decoration: none; - margin-left: 8px; - margin-right: 8px; -} - -.c4:not(:first-of-type):not(.c12 + .c3):not(.c11 + .c3) { - margin-top: 0; -} - -.c4:not(:first-of-type):not(.c12 + .c3):not(.c11 + .c3) .c7::before { - content: ' '; - display: block; - position: absolute; - width: 100%; - top: -7px; - border: 0 solid hsla(210,18%,87%,1); - border-top-width: 0; -} - -.c4:hover .c7::before, -.c4:hover + * .c7::before { - border-color: var(--item-hover-divider-border-color-override,transparent) !important; -} - -.c4:focus .c7::before, -.c4:focus + * .c7::before, -.c4[data-is-active-descendant] .c7::before, -[data-is-active-descendant] + .c4 .c7::before { - border-color: transparent !important; -} - -.c4[data-is-active-descendant='activated-directly'] { - background: rgba(208,215,222,0.48); -} - -.c4[data-is-active-descendant='activated-indirectly'] { - background: rgba(208,215,222,0.32); -} - -.c4:focus { - background: rgba(208,215,222,0.48); - outline: none; -} - -.c4:active { - background: rgba(208,215,222,0.48); -} - -.c5 { height: 20px; - width: 16px; - margin-right: 8px; + min-width: 16px; + max-width: 20px; display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -609,12 +523,25 @@ exports[`snapshots renders a menu that contains an item to add to the menu 1`] = -webkit-flex-shrink: 0; -ms-flex-negative: 0; flex-shrink: 0; + margin-right: 8px; +} + +.c4 rect { + fill: #ffffff; + stroke: #d0d7de; + shape-rendering: auto; } -.c10 { +.c4 path { + fill: #ffffff; + box-shadow: 0 1px 0 rgba(31,35,40,0.04); + opacity: 0; +} + +.c7 { height: 20px; - width: 16px; - margin-right: 8px; + min-width: 16px; + max-width: 20px; display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -630,50 +557,133 @@ exports[`snapshots renders a menu that contains an item to add to the menu 1`] = -webkit-flex-shrink: 0; -ms-flex-negative: 0; flex-shrink: 0; + margin-right: 8px; + color: #656d76; +} + +.c7 svg { + font-size: 12px; +} + +.c0 { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + -webkit-clip: rect(0,0,0,0); + clip: rect(0,0,0,0); + white-space: nowrap; + border-width: 0; +} + +.c1 { + margin: 0; + padding-inline-start: 0; + padding-top: 8px; + padding-bottom: 8px; +} + +.c3 { + position: relative; display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; - -webkit-flex-direction: column; - -ms-flex-direction: column; - flex-direction: column; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; + padding-left: 8px; + padding-right: 8px; + font-size: 14px; + padding-top: 6px; + padding-bottom: 6px; + line-height: 20px; + min-height: 5px; + margin-left: 8px; + margin-right: 8px; + border-radius: 6px; + -webkit-transition: background 33.333ms linear; + transition: background 33.333ms linear; + color: #1F2328; + cursor: pointer; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + background: unset; + border: unset; + width: calc(100% - 16px); + font-family: unset; + text-align: unset; + margin-top: unset; + margin-bottom: unset; } -.c10 svg { - fill: #656d76; - font-size: 12px; +.c3[aria-disabled] { + cursor: not-allowed; } -.c6 rect { - fill: #ffffff; - stroke: #d0d7de; - shape-rendering: auto; +.c3 [data-component="ActionList.Item--DividerContainer"] { + position: relative; } -.c6 path { - fill: #ffffff; - opacity: 0; +.c3 [data-component="ActionList.Item--DividerContainer"]::before { + content: " "; + display: block; + position: absolute; + width: 100%; + top: -7px; + border: 0 solid; + border-top-width: 0; + border-color: var(--divider-color,transparent); } -.c1 { - font-size: 14px; - line-height: 20px; +.c3:not(:first-of-type) { + --divider-color: rgba(208,215,222,0.48); } -.c1[data-has-active-descendant], -.c1:focus-within { - --item-hover-bg-override: none; - --item-hover-divider-border-color-override: hsla(210,18%,87%,1); +[data-component="ActionList.Divider"] + .c3 { + --divider-color: transparent !important; +} + +.c3:hover:not([aria-disabled]), +.c3:focus:not([aria-disabled]), +.c3[data-focus-visible-added]:not([aria-disabled]) { + --divider-color: transparent; +} + +.c3:hover:not([aria-disabled]) + .c2, +.c3:focus:not([aria-disabled]) + .c3, +.c3[data-focus-visible-added] + li { + --divider-color: transparent; +} + +.c8:hover:not([aria-disabled]) + .c2, +.c8:focus:not([aria-disabled]) + .c8, +.c8[data-focus-visible-added] + li { + --divider-color: transparent; } @media (hover:hover) and (pointer:fine) { - .c4:hover { - background: var( --item-hover-bg-override,rgba(208,215,222,0.32) ); - cursor: pointer; + .c3:hover:not([aria-disabled]) { + background-color: rgba(208,215,222,0.32); + color: #1F2328; + } + + .c3:focus-visible, + .c3 > a:focus-visible { + outline: none; + border: 2 solid; + box-shadow: 0 0 0 2px #0969da; + } + + .c3:active:not([aria-disabled]) { + background-color: rgba(208,215,222,0.48); + color: #1F2328; + } +} + +@media (forced-colors:active) { + .c3:focus { + outline: solid 1px transparent !important; } } @@ -681,630 +691,534 @@ exports[`snapshots renders a menu that contains an item to add to the menu 1`] = className="c0" >
-
-
+ + +
-
- -
-
-
- - zero - -
-
+ zero +
+ +
  • + + +
    -
    - -
    -
    -
    - - one - -
    -
    + one +
    +
  • +
  • + + +
    -
    - -
    -
    -
    - - two - -
    -
    + two +
    +
  • +
  • + + +
    -
    - -
    -
    -
    - - three - -
    -
    + three +
    +
  • +
  • + + +
    -
    - -
    -
    -
    - - four - -
    -
    + four +
    +
  • +
  • + + +
    -
    - -
    -
    -
    - - five - -
    -
    + five +
    +
  • +
  • + + +
    -
    - -
    -
    -
    - - six - -
    -
    + six +
    +
  • +
  • + + +
    -
    - -
    -
    -
    - - seven - -
    -
    + seven +
    +
  • +
  • + + +
    -
    - -
    -
    -
    - - twenty - -
    -
    + twenty +
    +
  • +
  • + + +
    -
    - -
    -
    -
    - - twentyone - -
    -
    + twentyone +
    -
    +
  • + -
    - + + + -
    -
    + + + +
    + -
    - - Add new item - -
    -
    + Add new item +
    -
  • -
    + +
    , ] @@ -1438,119 +1352,33 @@ exports[`snapshots renders a multiselect input 1`] = ` type="text" /> , - .c0 { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - -webkit-clip: rect(0,0,0,0); - clip: rect(0,0,0,0); - white-space: nowrap; - border-width: 0; -} - -.c2 { - margin-top: 8px; - margin-bottom: 8px; -} - -.c8 { + .c5 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; - min-width: 0; - position: relative; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; -webkit-box-flex: 1; -webkit-flex-grow: 1; -ms-flex-positive: 1; flex-grow: 1; + min-width: 0; } -.c9 { - -webkit-align-items: baseline; - -webkit-box-align: baseline; - -ms-flex-align: baseline; - align-items: baseline; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - min-width: 0; - -webkit-flex-direction: var(--main-content-flex-direction); - -ms-flex-direction: var(--main-content-flex-direction); - flex-direction: var(--main-content-flex-direction); +.c6 { -webkit-box-flex: 1; -webkit-flex-grow: 1; -ms-flex-positive: 1; flex-grow: 1; + font-weight: 400; } .c4 { - padding: 6px 8px; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - border-radius: 6px; - color: #1F2328; - -webkit-transition: background 33.333ms linear; - transition: background 33.333ms linear; - -webkit-text-decoration: none; - text-decoration: none; - margin-left: 8px; - margin-right: 8px; -} - -.c4:not(:first-of-type):not(.c11 + .c3):not(.c10 + .c3) { - margin-top: 0; -} - -.c4:not(:first-of-type):not(.c11 + .c3):not(.c10 + .c3) .c7::before { - content: ' '; - display: block; - position: absolute; - width: 100%; - top: -7px; - border: 0 solid hsla(210,18%,87%,1); - border-top-width: 0; -} - -.c4:hover .c7::before, -.c4:hover + * .c7::before { - border-color: var(--item-hover-divider-border-color-override,transparent) !important; -} - -.c4:focus .c7::before, -.c4:focus + * .c7::before, -.c4[data-is-active-descendant] .c7::before, -[data-is-active-descendant] + .c4 .c7::before { - border-color: transparent !important; -} - -.c4[data-is-active-descendant='activated-directly'] { - background: rgba(208,215,222,0.48); -} - -.c4[data-is-active-descendant='activated-indirectly'] { - background: rgba(208,215,222,0.32); -} - -.c4:focus { - background: rgba(208,215,222,0.48); - outline: none; -} - -.c4:active { - background: rgba(208,215,222,0.48); -} - -.c5 { height: 20px; - width: 16px; - margin-right: 8px; + min-width: 16px; + max-width: 20px; display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -1566,34 +1394,140 @@ exports[`snapshots renders a multiselect input 1`] = ` -webkit-flex-shrink: 0; -ms-flex-negative: 0; flex-shrink: 0; + margin-right: 8px; } -.c6 rect { +.c4 rect { fill: #ffffff; stroke: #d0d7de; shape-rendering: auto; } -.c6 path { +.c4 path { fill: #ffffff; + box-shadow: 0 1px 0 rgba(31,35,40,0.04); opacity: 0; } +.c0 { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + -webkit-clip: rect(0,0,0,0); + clip: rect(0,0,0,0); + white-space: nowrap; + border-width: 0; +} + .c1 { + margin: 0; + padding-inline-start: 0; + padding-top: 8px; + padding-bottom: 8px; +} + +.c3 { + position: relative; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding-left: 8px; + padding-right: 8px; font-size: 14px; + padding-top: 6px; + padding-bottom: 6px; line-height: 20px; + min-height: 5px; + margin-left: 8px; + margin-right: 8px; + border-radius: 6px; + -webkit-transition: background 33.333ms linear; + transition: background 33.333ms linear; + color: #1F2328; + cursor: pointer; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + background: unset; + border: unset; + width: calc(100% - 16px); + font-family: unset; + text-align: unset; + margin-top: unset; + margin-bottom: unset; +} + +.c3[aria-disabled] { + cursor: not-allowed; } -.c1[data-has-active-descendant], -.c1:focus-within { - --item-hover-bg-override: none; - --item-hover-divider-border-color-override: hsla(210,18%,87%,1); +.c3 [data-component="ActionList.Item--DividerContainer"] { + position: relative; +} + +.c3 [data-component="ActionList.Item--DividerContainer"]::before { + content: " "; + display: block; + position: absolute; + width: 100%; + top: -7px; + border: 0 solid; + border-top-width: 0; + border-color: var(--divider-color,transparent); +} + +.c3:not(:first-of-type) { + --divider-color: rgba(208,215,222,0.48); +} + +[data-component="ActionList.Divider"] + .c3 { + --divider-color: transparent !important; +} + +.c3:hover:not([aria-disabled]), +.c3:focus:not([aria-disabled]), +.c3[data-focus-visible-added]:not([aria-disabled]) { + --divider-color: transparent; +} + +.c3:hover:not([aria-disabled]) + .c2, +.c3:focus:not([aria-disabled]) + .c3, +.c3[data-focus-visible-added] + li { + --divider-color: transparent; +} + +.c7:hover:not([aria-disabled]) + .c2, +.c7:focus:not([aria-disabled]) + .c7, +.c7[data-focus-visible-added] + li { + --divider-color: transparent; } @media (hover:hover) and (pointer:fine) { - .c4:hover { - background: var( --item-hover-bg-override,rgba(208,215,222,0.32) ); - cursor: pointer; + .c3:hover:not([aria-disabled]) { + background-color: rgba(208,215,222,0.32); + color: #1F2328; + } + + .c3:focus-visible, + .c3 > a:focus-visible { + outline: none; + border: 2 solid; + box-shadow: 0 0 0 2px #0969da; + } + + .c3:active:not([aria-disabled]) { + background-color: rgba(208,215,222,0.48); + color: #1F2328; + } +} + +@media (forced-colors:active) { + .c3:focus { + outline: solid 1px transparent !important; } } @@ -1601,577 +1535,463 @@ exports[`snapshots renders a multiselect input 1`] = ` className="c0" >
    -
    -
    + + +
    -
    - -
    -
    -
    - - zero - -
    -
    + zero +
    + +
  • + + +
    -
    - -
    -
    -
    - - one - -
    -
    + one +
    +
  • +
  • + + +
    -
    - -
    -
    -
    - - two - -
    -
    + two +
    +
  • +
  • + + +
    -
    - -
    -
    -
    - - three - -
    -
    + three +
    +
  • +
  • + + +
    -
    - -
    -
    -
    - - four - -
    -
    + four +
    +
  • +
  • + + +
    -
    - -
    -
    -
    - - five - -
    -
    + five +
    +
  • +
  • + + +
    -
    - -
    -
    -
    - - six - -
    -
    + six +
    +
  • +
  • + + +
    -
    - -
    -
    -
    - - seven - -
    -
    + seven +
    +
  • +
  • + + +
    -
    - -
    -
    -
    - - twenty - -
    -
    + twenty +
    +
  • +
  • + + +
    -
    - -
    -
    -
    - - twentyone - -
    -
    + twentyone +
    -
  • -
    + +
    , ] @@ -2305,119 +2125,67 @@ exports[`snapshots renders a multiselect input with selected menu items 1`] = ` type="text" /> , - .c0 { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - -webkit-clip: rect(0,0,0,0); - clip: rect(0,0,0,0); - white-space: nowrap; - border-width: 0; -} - -.c2 { - margin-top: 8px; - margin-bottom: 8px; -} - -.c8 { + .c5 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; - min-width: 0; - position: relative; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; -webkit-box-flex: 1; -webkit-flex-grow: 1; -ms-flex-positive: 1; flex-grow: 1; + min-width: 0; } -.c9 { - -webkit-align-items: baseline; - -webkit-box-align: baseline; - -ms-flex-align: baseline; - align-items: baseline; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - min-width: 0; - -webkit-flex-direction: var(--main-content-flex-direction); - -ms-flex-direction: var(--main-content-flex-direction); - flex-direction: var(--main-content-flex-direction); +.c6 { -webkit-box-flex: 1; -webkit-flex-grow: 1; -ms-flex-positive: 1; flex-grow: 1; + font-weight: 400; } -.c4 { - padding: 6px 8px; +.c7 { + height: 20px; + min-width: 16px; + max-width: 20px; display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; - border-radius: 6px; - color: #1F2328; - -webkit-transition: background 33.333ms linear; - transition: background 33.333ms linear; - -webkit-text-decoration: none; - text-decoration: none; - margin-left: 8px; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; margin-right: 8px; } -.c4:not(:first-of-type):not(.c12 + .c3):not(.c11 + .c3) { - margin-top: 0; -} - -.c4:not(:first-of-type):not(.c12 + .c3):not(.c11 + .c3) .c7::before { - content: ' '; - display: block; - position: absolute; - width: 100%; - top: -7px; - border: 0 solid hsla(210,18%,87%,1); - border-top-width: 0; -} - -.c4:hover .c7::before, -.c4:hover + * .c7::before { - border-color: var(--item-hover-divider-border-color-override,transparent) !important; -} - -.c4:focus .c7::before, -.c4:focus + * .c7::before, -.c4[data-is-active-descendant] .c7::before, -[data-is-active-descendant] + .c4 .c7::before { - border-color: transparent !important; -} - -.c4[data-is-active-descendant='activated-directly'] { - background: rgba(208,215,222,0.48); -} - -.c4[data-is-active-descendant='activated-indirectly'] { - background: rgba(208,215,222,0.32); -} - -.c4:focus { - background: rgba(208,215,222,0.48); - outline: none; +.c7 rect { + fill: #ffffff; + stroke: #d0d7de; + shape-rendering: auto; } -.c4:active { - background: rgba(208,215,222,0.48); +.c7 path { + fill: #ffffff; + box-shadow: 0 1px 0 rgba(31,35,40,0.04); + opacity: 0; } -.c5 { +.c4 { height: 20px; - width: 16px; - margin-right: 8px; + min-width: 16px; + max-width: 20px; display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -2433,45 +2201,140 @@ exports[`snapshots renders a multiselect input with selected menu items 1`] = ` -webkit-flex-shrink: 0; -ms-flex-negative: 0; flex-shrink: 0; + margin-right: 8px; } -.c10 rect { - fill: #ffffff; - stroke: #d0d7de; - shape-rendering: auto; -} - -.c10 path { - fill: #ffffff; - opacity: 0; -} - -.c6 rect { +.c4 rect { fill: #0969da; stroke: #0969da; shape-rendering: auto; } -.c6 path { +.c4 path { fill: #ffffff; + box-shadow: 0 1px 0 rgba(31,35,40,0.04); opacity: 1; } +.c0 { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + -webkit-clip: rect(0,0,0,0); + clip: rect(0,0,0,0); + white-space: nowrap; + border-width: 0; +} + .c1 { + margin: 0; + padding-inline-start: 0; + padding-top: 8px; + padding-bottom: 8px; +} + +.c3 { + position: relative; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding-left: 8px; + padding-right: 8px; font-size: 14px; + padding-top: 6px; + padding-bottom: 6px; line-height: 20px; + min-height: 5px; + margin-left: 8px; + margin-right: 8px; + border-radius: 6px; + -webkit-transition: background 33.333ms linear; + transition: background 33.333ms linear; + color: #1F2328; + cursor: pointer; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + background: unset; + border: unset; + width: calc(100% - 16px); + font-family: unset; + text-align: unset; + margin-top: unset; + margin-bottom: unset; } -.c1[data-has-active-descendant], -.c1:focus-within { - --item-hover-bg-override: none; - --item-hover-divider-border-color-override: hsla(210,18%,87%,1); +.c3[aria-disabled] { + cursor: not-allowed; +} + +.c3 [data-component="ActionList.Item--DividerContainer"] { + position: relative; +} + +.c3 [data-component="ActionList.Item--DividerContainer"]::before { + content: " "; + display: block; + position: absolute; + width: 100%; + top: -7px; + border: 0 solid; + border-top-width: 0; + border-color: var(--divider-color,transparent); +} + +.c3:not(:first-of-type) { + --divider-color: rgba(208,215,222,0.48); +} + +[data-component="ActionList.Divider"] + .c3 { + --divider-color: transparent !important; +} + +.c3:hover:not([aria-disabled]), +.c3:focus:not([aria-disabled]), +.c3[data-focus-visible-added]:not([aria-disabled]) { + --divider-color: transparent; +} + +.c3:hover:not([aria-disabled]) + .c2, +.c3:focus:not([aria-disabled]) + .c3, +.c3[data-focus-visible-added] + li { + --divider-color: transparent; +} + +.c8:hover:not([aria-disabled]) + .c2, +.c8:focus:not([aria-disabled]) + .c8, +.c8[data-focus-visible-added] + li { + --divider-color: transparent; } @media (hover:hover) and (pointer:fine) { - .c4:hover { - background: var( --item-hover-bg-override,rgba(208,215,222,0.32) ); - cursor: pointer; + .c3:hover:not([aria-disabled]) { + background-color: rgba(208,215,222,0.32); + color: #1F2328; + } + + .c3:focus-visible, + .c3 > a:focus-visible { + outline: none; + border: 2 solid; + box-shadow: 0 0 0 2px #0969da; + } + + .c3:active:not([aria-disabled]) { + background-color: rgba(208,215,222,0.48); + color: #1F2328; + } +} + +@media (forced-colors:active) { + .c3:focus { + outline: solid 1px transparent !important; } } @@ -2479,577 +2342,463 @@ exports[`snapshots renders a multiselect input with selected menu items 1`] = ` className="c0" >
    -
    -
    + + +
    -
    - -
    -
    -
    - - zero - -
    -
    + zero +
    + +
  • + + +
    -
    - -
    -
    -
    - - one - -
    -
    + one +
    +
  • +
  • + + +
    -
    - -
    -
    -
    - - two - -
    -
    + two +
    +
  • +
  • + + +
    -
    - -
    -
    -
    - - three - -
    -
    + three +
    +
  • +
  • + + +
    -
    - -
    -
    -
    - - four - -
    -
    + four +
    +
  • +
  • + + +
    -
    - -
    -
    -
    - - five - -
    -
    + five +
    +
  • +
  • + + +
    -
    - -
    -
    -
    - - six - -
    -
    + six +
    +
  • +
  • + + +
    -
    - -
    -
    -
    - - seven - -
    -
    + seven +
    +
  • +
  • + + +
    -
    - -
    -
    -
    - - twenty - -
    -
    + twenty +
    +
  • +
  • + + +
    -
    - -
    -
    -
    - - twentyone - -
    -
    + twentyone +
    -
  • -
    + +
    , ] @@ -3183,130 +2932,170 @@ exports[`snapshots renders a single select input 1`] = ` type="text" /> , - .c0 { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - -webkit-clip: rect(0,0,0,0); - clip: rect(0,0,0,0); - white-space: nowrap; - border-width: 0; -} - -.c2 { - margin-top: 8px; - margin-bottom: 8px; + .c4 { + height: 20px; + min-width: 16px; + max-width: 20px; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; + margin-right: 8px; } -.c6 { +.c5 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; - min-width: 0; - position: relative; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; -webkit-box-flex: 1; -webkit-flex-grow: 1; -ms-flex-positive: 1; flex-grow: 1; + min-width: 0; } -.c7 { - -webkit-align-items: baseline; - -webkit-box-align: baseline; - -ms-flex-align: baseline; - align-items: baseline; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - min-width: 0; - -webkit-flex-direction: var(--main-content-flex-direction); - -ms-flex-direction: var(--main-content-flex-direction); - flex-direction: var(--main-content-flex-direction); +.c6 { -webkit-box-flex: 1; -webkit-flex-grow: 1; -ms-flex-positive: 1; flex-grow: 1; + font-weight: 400; } -.c4 { - padding: 6px 8px; +.c0 { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + -webkit-clip: rect(0,0,0,0); + clip: rect(0,0,0,0); + white-space: nowrap; + border-width: 0; +} + +.c1 { + margin: 0; + padding-inline-start: 0; + padding-top: 8px; + padding-bottom: 8px; +} + +.c3 { + position: relative; display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; + padding-left: 8px; + padding-right: 8px; + font-size: 14px; + padding-top: 6px; + padding-bottom: 6px; + line-height: 20px; + min-height: 5px; + margin-left: 8px; + margin-right: 8px; border-radius: 6px; - color: #1F2328; -webkit-transition: background 33.333ms linear; transition: background 33.333ms linear; - -webkit-text-decoration: none; - text-decoration: none; - margin-left: 8px; - margin-right: 8px; + color: #1F2328; + cursor: pointer; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + background: unset; + border: unset; + width: calc(100% - 16px); + font-family: unset; + text-align: unset; + margin-top: unset; + margin-bottom: unset; } -.c4:not(:first-of-type):not(.c9 + .c3):not(.c8 + .c3) { - margin-top: 0; +.c3[aria-disabled] { + cursor: not-allowed; } -.c4:not(:first-of-type):not(.c9 + .c3):not(.c8 + .c3) .c5::before { - content: ' '; +.c3 [data-component="ActionList.Item--DividerContainer"] { + position: relative; +} + +.c3 [data-component="ActionList.Item--DividerContainer"]::before { + content: " "; display: block; position: absolute; width: 100%; top: -7px; - border: 0 solid hsla(210,18%,87%,1); + border: 0 solid; border-top-width: 0; + border-color: var(--divider-color,transparent); } -.c4:hover .c5::before, -.c4:hover + * .c5::before { - border-color: var(--item-hover-divider-border-color-override,transparent) !important; +.c3:not(:first-of-type) { + --divider-color: rgba(208,215,222,0.48); } -.c4:focus .c5::before, -.c4:focus + * .c5::before, -.c4[data-is-active-descendant] .c5::before, -[data-is-active-descendant] + .c4 .c5::before { - border-color: transparent !important; +[data-component="ActionList.Divider"] + .c3 { + --divider-color: transparent !important; } -.c4[data-is-active-descendant='activated-directly'] { - background: rgba(208,215,222,0.48); +.c3:hover:not([aria-disabled]), +.c3:focus:not([aria-disabled]), +.c3[data-focus-visible-added]:not([aria-disabled]) { + --divider-color: transparent; } -.c4[data-is-active-descendant='activated-indirectly'] { - background: rgba(208,215,222,0.32); +.c3:hover:not([aria-disabled]) + .c2, +.c3:focus:not([aria-disabled]) + .c3, +.c3[data-focus-visible-added] + li { + --divider-color: transparent; } -.c4:focus { - background: rgba(208,215,222,0.48); - outline: none; +.c7:hover:not([aria-disabled]) + .c2, +.c7:focus:not([aria-disabled]) + .c7, +.c7[data-focus-visible-added] + li { + --divider-color: transparent; } -.c4:active { - background: rgba(208,215,222,0.48); -} +@media (hover:hover) and (pointer:fine) { + .c3:hover:not([aria-disabled]) { + background-color: rgba(208,215,222,0.32); + color: #1F2328; + } -.c1 { - font-size: 14px; - line-height: 20px; -} + .c3:focus-visible, + .c3 > a:focus-visible { + outline: none; + border: 2 solid; + box-shadow: 0 0 0 2px #0969da; + } -.c1[data-has-active-descendant], -.c1:focus-within { - --item-hover-bg-override: none; - --item-hover-divider-border-color-override: hsla(210,18%,87%,1); + .c3:active:not([aria-disabled]) { + background-color: rgba(208,215,222,0.48); + color: #1F2328; + } } -@media (hover:hover) and (pointer:fine) { - .c4:hover { - background: var( --item-hover-bg-override,rgba(208,215,222,0.32) ); - cursor: pointer; +@media (forced-colors:active) { + .c3:focus { + outline: solid 1px transparent !important; } } @@ -3314,307 +3103,253 @@ exports[`snapshots renders a single select input 1`] = ` className="c0" >
    -
    -
    +
    -
    -
    - - zero - -
    -
    + zero +
    + +
  • +
    -
    -
    - - one - -
    -
    + one +
    +
  • +
  • +
    -
    -
    - - two - -
    -
    + two +
    +
  • +
  • +
    -
    -
    - - three - -
    -
    + three +
    +
  • +
  • +
    -
    -
    - - four - -
    -
    + four +
    +
  • +
  • +
    -
    -
    - - five - -
    -
    + five +
    +
  • +
  • +
    -
    -
    - - six - -
    -
    + six +
    +
  • +
  • +
    -
    -
    - - seven - -
    -
    + seven +
    +
  • +
  • +
    -
    -
    - - twenty - -
    -
    + twenty +
    +
  • +
  • +
    -
    -
    - - twentyone - -
    -
    + twentyone +
    -
  • -
    + +
    , ] @@ -3626,130 +3361,170 @@ exports[`snapshots renders with a custom text input component 1`] = ` id="customInput" type="text" />, - .c0 { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - -webkit-clip: rect(0,0,0,0); - clip: rect(0,0,0,0); - white-space: nowrap; - border-width: 0; -} - -.c2 { - margin-top: 8px; - margin-bottom: 8px; + .c4 { + height: 20px; + min-width: 16px; + max-width: 20px; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; + margin-right: 8px; } -.c6 { +.c5 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; - min-width: 0; - position: relative; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; -webkit-box-flex: 1; -webkit-flex-grow: 1; -ms-flex-positive: 1; flex-grow: 1; + min-width: 0; } -.c7 { - -webkit-align-items: baseline; - -webkit-box-align: baseline; - -ms-flex-align: baseline; - align-items: baseline; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - min-width: 0; - -webkit-flex-direction: var(--main-content-flex-direction); - -ms-flex-direction: var(--main-content-flex-direction); - flex-direction: var(--main-content-flex-direction); +.c6 { -webkit-box-flex: 1; -webkit-flex-grow: 1; -ms-flex-positive: 1; flex-grow: 1; + font-weight: 400; } -.c4 { - padding: 6px 8px; +.c0 { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + -webkit-clip: rect(0,0,0,0); + clip: rect(0,0,0,0); + white-space: nowrap; + border-width: 0; +} + +.c1 { + margin: 0; + padding-inline-start: 0; + padding-top: 8px; + padding-bottom: 8px; +} + +.c3 { + position: relative; display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; + padding-left: 8px; + padding-right: 8px; + font-size: 14px; + padding-top: 6px; + padding-bottom: 6px; + line-height: 20px; + min-height: 5px; + margin-left: 8px; + margin-right: 8px; border-radius: 6px; - color: #1F2328; -webkit-transition: background 33.333ms linear; transition: background 33.333ms linear; - -webkit-text-decoration: none; - text-decoration: none; - margin-left: 8px; - margin-right: 8px; + color: #1F2328; + cursor: pointer; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + background: unset; + border: unset; + width: calc(100% - 16px); + font-family: unset; + text-align: unset; + margin-top: unset; + margin-bottom: unset; +} + +.c3[aria-disabled] { + cursor: not-allowed; } -.c4:not(:first-of-type):not(.c9 + .c3):not(.c8 + .c3) { - margin-top: 0; +.c3 [data-component="ActionList.Item--DividerContainer"] { + position: relative; } -.c4:not(:first-of-type):not(.c9 + .c3):not(.c8 + .c3) .c5::before { - content: ' '; +.c3 [data-component="ActionList.Item--DividerContainer"]::before { + content: " "; display: block; position: absolute; width: 100%; top: -7px; - border: 0 solid hsla(210,18%,87%,1); + border: 0 solid; border-top-width: 0; + border-color: var(--divider-color,transparent); } -.c4:hover .c5::before, -.c4:hover + * .c5::before { - border-color: var(--item-hover-divider-border-color-override,transparent) !important; +.c3:not(:first-of-type) { + --divider-color: rgba(208,215,222,0.48); } -.c4:focus .c5::before, -.c4:focus + * .c5::before, -.c4[data-is-active-descendant] .c5::before, -[data-is-active-descendant] + .c4 .c5::before { - border-color: transparent !important; +[data-component="ActionList.Divider"] + .c3 { + --divider-color: transparent !important; } -.c4[data-is-active-descendant='activated-directly'] { - background: rgba(208,215,222,0.48); +.c3:hover:not([aria-disabled]), +.c3:focus:not([aria-disabled]), +.c3[data-focus-visible-added]:not([aria-disabled]) { + --divider-color: transparent; } -.c4[data-is-active-descendant='activated-indirectly'] { - background: rgba(208,215,222,0.32); +.c3:hover:not([aria-disabled]) + .c2, +.c3:focus:not([aria-disabled]) + .c3, +.c3[data-focus-visible-added] + li { + --divider-color: transparent; } -.c4:focus { - background: rgba(208,215,222,0.48); - outline: none; +.c7:hover:not([aria-disabled]) + .c2, +.c7:focus:not([aria-disabled]) + .c7, +.c7[data-focus-visible-added] + li { + --divider-color: transparent; } -.c4:active { - background: rgba(208,215,222,0.48); -} +@media (hover:hover) and (pointer:fine) { + .c3:hover:not([aria-disabled]) { + background-color: rgba(208,215,222,0.32); + color: #1F2328; + } -.c1 { - font-size: 14px; - line-height: 20px; -} + .c3:focus-visible, + .c3 > a:focus-visible { + outline: none; + border: 2 solid; + box-shadow: 0 0 0 2px #0969da; + } -.c1[data-has-active-descendant], -.c1:focus-within { - --item-hover-bg-override: none; - --item-hover-divider-border-color-override: hsla(210,18%,87%,1); + .c3:active:not([aria-disabled]) { + background-color: rgba(208,215,222,0.48); + color: #1F2328; + } } -@media (hover:hover) and (pointer:fine) { - .c4:hover { - background: var( --item-hover-bg-override,rgba(208,215,222,0.32) ); - cursor: pointer; +@media (forced-colors:active) { + .c3:focus { + outline: solid 1px transparent !important; } } @@ -3757,307 +3532,253 @@ exports[`snapshots renders with a custom text input component 1`] = ` className="c0" >
    -
    -
    +
    -
    -
    - - zero - -
    -
    + zero +
    + +
  • +
    -
    -
    - - one - -
    -
    + one +
    +
  • +
  • +
    -
    -
    - - two - -
    -
    + two +
    +
  • +
  • +
    -
    -
    - - three - -
    -
    + three +
    +
  • +
  • +
    -
    -
    - - four - -
    -
    + four +
    +
  • +
  • +
    -
    -
    - - five - -
    -
    + five +
    +
  • +
  • +
    -
    -
    - - six - -
    -
    + six +
    +
  • +
  • +
    -
    -
    - - seven - -
    -
    + seven +
    +
  • +
  • +
    -
    -
    - - twenty - -
    -
    + twenty +
    +
  • +
  • +
    -
    -
    - - twentyone - -
    -
    + twentyone +
    -
  • -
    + +
    , ] diff --git a/src/stories/Autocomplete.stories.tsx b/src/stories/Autocomplete.stories.tsx index a369136f850..31c0a40818f 100644 --- a/src/stories/Autocomplete.stories.tsx +++ b/src/stories/Autocomplete.stories.tsx @@ -86,20 +86,20 @@ type ItemMetadata = { } type Datum = { - id: string | number + id: string text: string selected?: boolean metadata?: ItemMetadata } const items: Datum[] = [ - {text: 'css', id: 0}, - {text: 'css-in-js', id: 1}, - {text: 'styled-system', id: 2}, - {text: 'javascript', id: 3}, - {text: 'typescript', id: 4}, - {text: 'react', id: 5}, - {text: 'design-systems', id: 6}, + {text: 'css', id: '0'}, + {text: 'css-in-js', id: '1'}, + {text: 'styled-system', id: '2'}, + {text: 'javascript', id: '3'}, + {text: 'typescript', id: '4'}, + {text: 'react', id: '5'}, + {text: 'design-systems', id: '6'}, ] const mockTokens: Datum[] = [...items].slice(0, 3) @@ -223,7 +223,7 @@ export const Default = (args: FormControlArgs) => { const {parentArgs, labelArgs, captionArgs, validationArgs} = getFormControlArgsByChildComponent(args) const {menuArgs, overlayArgs, textInputArgs} = getArgsByChildComponent(args) const isMultiselect = menuArgs.selectionVariant === 'multiple' - const [selectedItemIds, setSelectedItemIds] = useState>([]) + const [selectedItemIds, setSelectedItemIds] = useState>([]) const onSelectedChange = (newlySelectedItems: Datum | Datum[]) => { if (!Array.isArray(newlySelectedItems)) { return @@ -270,9 +270,9 @@ Default.play = async ({canvasElement}: {canvasElement: HTMLElement}) => { export const WithTokenInput = (args: FormControlArgs) => { const {parentArgs, labelArgs, captionArgs, validationArgs} = getFormControlArgsByChildComponent(args) const {menuArgs, overlayArgs, textInputWithTokensArgs} = getArgsByChildComponent(args) - const [tokens, setTokens] = useState([]) // [items[0], items[2]] + const [tokens, setTokens] = useState([]) const selectedTokenIds = tokens.map(token => token.id) - const [selectedItemIds, setSelectedItemIds] = useState>(selectedTokenIds) + const [selectedItemIds, setSelectedItemIds] = useState>(selectedTokenIds) const onTokenRemove: (tokenId: string | number) => void = tokenId => { setTokens(tokens.filter(token => token.id !== tokenId)) setSelectedItemIds(selectedItemIds.filter(id => id !== tokenId)) @@ -345,12 +345,12 @@ WithTokenInput.parameters = { export const AddNewItem = (args: FormControlArgs) => { const {parentArgs, labelArgs, captionArgs, validationArgs} = getFormControlArgsByChildComponent(args) - const {menuArgs, overlayArgs, textInputArgs} = getArgsByChildComponent(args) + const {menuArgs, overlayArgs, textInputWithTokensArgs} = getArgsByChildComponent(args) const [localItemsState, setLocalItemsState] = useState(items) const [filterVal, setFilterVal] = useState('') const [tokens, setTokens] = useState(mockTokens) const selectedTokenIds = tokens.map(token => token.id) - const [selectedItemIds, setSelectedItemIds] = useState>(selectedTokenIds) + const [selectedItemIds, setSelectedItemIds] = useState>(selectedTokenIds) const onTokenRemove: (tokenId: string | number) => void = tokenId => { setTokens(tokens.filter(token => token.id !== tokenId)) setSelectedItemIds(selectedItemIds.filter(id => id !== tokenId)) @@ -395,16 +395,17 @@ export const AddNewItem = (args: FormControlArgs) => { localItem.text).includes(filterVal) ? { + id: filterVal, text: `Add '${filterVal}'`, handleAddItem: item => { onItemSelect({ @@ -488,8 +489,8 @@ CustomSearchFilterFn.args = { export const CustomSortAfterMenuClose = (args: FormControlArgs) => { const {parentArgs, labelArgs, captionArgs, validationArgs} = getFormControlArgsByChildComponent(args) const {menuArgs, overlayArgs, textInputArgs} = getArgsByChildComponent(args) - const [selectedItemIds, setSelectedItemIds] = useState>([]) - const isItemSelected = (itemId: string | number) => selectedItemIds.includes(itemId) + const [selectedItemIds, setSelectedItemIds] = useState>([]) + const isItemSelected = (itemId: string) => selectedItemIds.includes(itemId) const onSelectedChange = (newlySelectedItems: Datum | Datum[]) => { if (!Array.isArray(newlySelectedItems)) { return @@ -497,7 +498,7 @@ export const CustomSortAfterMenuClose = (args: FormControlArgs setSelectedItemIds(newlySelectedItems.map(item => item.id)) } - const customSortFn = (itemIdA: string | number, itemIdB: string | number) => + const customSortFn = (itemIdA: string, itemIdB: string) => isItemSelected(itemIdA) === isItemSelected(itemIdB) ? 0 : isItemSelected(itemIdA) ? 1 : -1 return (