0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-02-17 22:04:19 -05:00

refactor(console): support using keyboard to remove option (#4824)

* refactor(console): support using keyboard to remove option

* refactor(console): update multi-select option focused color
This commit is contained in:
Gao Sun 2023-11-09 12:35:35 +08:00 committed by GitHub
parent c9db7b2ed9
commit e07dbcf05c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 33 additions and 4 deletions

View file

@ -30,7 +30,8 @@
}
}
&:active {
&:active,
&:focus {
background: var(--color-pressed);
}

View file

@ -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<T extends string>({
const selectRef = useRef<HTMLDivElement>(null);
const [keyword, setKeyword] = useState('');
const [isInputFocused, setIsInputFocused] = useState(false);
// Used to focus on the last tag to perform deletion
const [focusedValue, setFocusedValue] = useState<Nullable<T>>(null);
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
// Search on keyword changes
@ -76,7 +78,7 @@ function MultiSelect<T extends string>({
}
}, []);
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<T extends string>({
<Tag
key={option.value}
variant="cell"
className={styles.tag}
className={classNames(styles.tag, option.value === focusedValue && styles.focused)}
onClick={(event) => {
event.stopPropagation();
}}
@ -122,6 +124,9 @@ function MultiSelect<T extends string>({
onClick={() => {
handleDelete(option);
}}
onKeyDown={onKeyDownHandler(() => {
handleDelete(option);
})}
>
<Close className={styles.close} />
</IconButton>
@ -133,14 +138,27 @@ function MultiSelect<T extends string>({
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);
}}
/>
<Dropdown

View file

@ -28,6 +28,14 @@
display: flex;
align-items: center;
gap: _.unit(1);
position: relative;
&.focused::after {
content: '';
position: absolute;
inset: 0;
background: var(--color-overlay-default-focused);
}
}
.close {

View file

@ -175,6 +175,7 @@
--color-tooltip-background: #34353f; // dark theme Surface-4
--color-tooltip-text: var(--color-neutral-99);
--color-overlay: rgba(0, 0, 0, 30%);
--color-overlay-default-focused: rgba(25, 28, 29, 16%);
--color-drawer-overlay: rgba(0, 0, 0, 40%);
--color-guide-dropdown-background: var(--color-white);
--color-guide-dropdown-border: var(--color-border);
@ -375,6 +376,7 @@
--color-tooltip-background: var(--color-surface-4);
--color-tooltip-text: var(--color-neutral-10);
--color-overlay: rgba(0, 0, 0, 70%); // 70% Neutral-100
--color-overlay-default-focused: rgba(247, 248, 248, 16%);
--color-drawer-overlay: rgba(0, 0, 0, 60%);
--color-guide-dropdown-background: var(--color-neutral-variant-80);
--color-guide-dropdown-border: var(--color-neutral-variant-70);