diff --git a/packages/console/src/ds-components/IconButton/index.module.scss b/packages/console/src/ds-components/IconButton/index.module.scss index 659dd073a..f1090aea6 100644 --- a/packages/console/src/ds-components/IconButton/index.module.scss +++ b/packages/console/src/ds-components/IconButton/index.module.scss @@ -30,7 +30,8 @@ } } - &:active { + &:active, + &:focus { background: var(--color-pressed); } diff --git a/packages/console/src/ds-components/Select/MultiSelect.tsx b/packages/console/src/ds-components/Select/MultiSelect.tsx index e60591e08..8655d985d 100644 --- a/packages/console/src/ds-components/Select/MultiSelect.tsx +++ b/packages/console/src/ds-components/Select/MultiSelect.tsx @@ -1,5 +1,5 @@ import { type AdminConsoleKey } from '@logto/phrases'; -import { cond } from '@silverhand/essentials'; +import { type Nullable, cond } from '@silverhand/essentials'; import classNames from 'classnames'; import { useEffect, useRef, useState } from 'react'; import { useTranslation } from 'react-i18next'; @@ -48,6 +48,8 @@ function MultiSelect({ const selectRef = useRef(null); const [keyword, setKeyword] = useState(''); const [isInputFocused, setIsInputFocused] = useState(false); + // Used to focus on the last tag to perform deletion + const [focusedValue, setFocusedValue] = useState>(null); const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' }); // Search on keyword changes @@ -76,7 +78,7 @@ function MultiSelect({ } }, []); - const isOpen = !isReadOnly && isInputFocused; + const isOpen = !isReadOnly && isInputFocused && !focusedValue; const filteredOptions = options.filter(({ value: current }) => { return !value.some(({ value }) => value === current); }); @@ -110,7 +112,7 @@ function MultiSelect({ { event.stopPropagation(); }} @@ -122,6 +124,9 @@ function MultiSelect({ onClick={() => { handleDelete(option); }} + onKeyDown={onKeyDownHandler(() => { + handleDelete(option); + })} > @@ -133,14 +138,27 @@ function MultiSelect({ type="text" placeholder={cond(value.length === 0 && placeholder && String(t(placeholder)))} value={keyword} + onKeyDown={(event) => { + if (event.key === 'Backspace' && keyword === '') { + if (focusedValue) { + onChange(value.filter(({ value }) => value !== focusedValue)); + setFocusedValue(null); + } else { + setFocusedValue(value.at(-1)?.value ?? null); + } + event.stopPropagation(); + } + }} onChange={({ currentTarget: { value } }) => { setKeyword(value); + setFocusedValue(null); }} onFocus={() => { setIsInputFocused(true); }} onBlur={() => { setIsInputFocused(false); + setFocusedValue(null); }} />