Add a ⏎ shortcut on Select options (#5641)

fixes #5540 

Added onkeyDown to 
1. Create new option and 
2. Move focus to it.

[screen-capture
(6).webm](https://github.com/twentyhq/twenty/assets/69167444/ede54ad8-22db-4b09-9617-4d999c6c08c7)

---------

Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
This commit is contained in:
Ravan
2024-06-19 18:00:26 +05:30
committed by GitHub
parent 64b456912a
commit c7e6d6959f
2 changed files with 60 additions and 6 deletions

View File

@ -1,6 +1,8 @@
import { useState } from 'react';
import { Controller, useFormContext } from 'react-hook-form';
import styled from '@emotion/styled';
import { DropResult } from '@hello-pangea/dnd';
import { Key } from 'ts-key-enum';
import { IconPlus } from 'twenty-ui';
import { z } from 'zod';
@ -19,6 +21,8 @@ import { CardContent } from '@/ui/layout/card/components/CardContent';
import { CardFooter } from '@/ui/layout/card/components/CardFooter';
import { DraggableItem } from '@/ui/layout/draggable-list/components/DraggableItem';
import { DraggableList } from '@/ui/layout/draggable-list/components/DraggableList';
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
import { AppHotkeyScope } from '@/ui/utilities/hotkey/types/AppHotkeyScope';
import { FieldMetadataType } from '~/generated-metadata/graphql';
import { moveArrayItem } from '~/utils/array/moveArrayItem';
import { toSpliced } from '~/utils/array/toSpliced';
@ -78,6 +82,7 @@ const StyledButton = styled(LightButton)`
export const SettingsDataModelFieldSelectForm = ({
fieldMetadataItem,
}: SettingsDataModelFieldSelectFormProps) => {
const [focusedOptionId, setFocusedOptionId] = useState('');
const { initialDefaultValue, initialOptions } =
useSelectSettingsFormInitialValues({ fieldMetadataItem });
@ -167,6 +172,37 @@ export const SettingsDataModelFieldSelectForm = ({
}
};
const getOptionsWithNewOption = () => {
const currentOptions = getValues('options');
const newOptions = [
...currentOptions,
generateNewSelectOption(currentOptions),
];
return newOptions;
};
const handleAddOption = () => {
const newOptions = getOptionsWithNewOption();
setFormValue('options', newOptions);
};
useScopedHotkeys(
Key.Enter,
() => {
const newOptions = getOptionsWithNewOption();
setFormValue('options', newOptions);
const lastOptionId = newOptions[newOptions.length - 1].id;
setFocusedOptionId(lastOptionId);
},
AppHotkeyScope.App,
);
return (
<>
<Controller
@ -197,6 +233,7 @@ export const SettingsDataModelFieldSelectForm = ({
<SettingsDataModelFieldSelectFormOptionRow
key={option.id}
option={option}
focused={focusedOptionId === option.id}
onChange={(nextOption) => {
const nextOptions = toSpliced(
options,
@ -245,9 +282,7 @@ export const SettingsDataModelFieldSelectForm = ({
<StyledButton
title="Add option"
Icon={IconPlus}
onClick={() =>
onChange([...options, generateNewSelectOption(options)])
}
onClick={handleAddOption}
/>
</StyledFooter>
</>

View File

@ -1,4 +1,4 @@
import { useMemo } from 'react';
import { useEffect, useMemo, useRef } from 'react';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import {
@ -31,6 +31,7 @@ type SettingsDataModelFieldSelectFormOptionRowProps = {
onSetAsDefault?: () => void;
onRemoveAsDefault?: () => void;
option: FieldMetadataItemOption;
focused?: boolean;
};
const StyledRow = styled.div`
@ -63,12 +64,18 @@ export const SettingsDataModelFieldSelectFormOptionRow = ({
onSetAsDefault,
onRemoveAsDefault,
option,
focused,
}: SettingsDataModelFieldSelectFormOptionRowProps) => {
const inputRef = useRef<HTMLInputElement>(null);
const theme = useTheme();
const dropdownIds = useMemo(() => {
const baseScopeId = `select-field-option-row-${v4()}`;
return { color: `${baseScopeId}-color`, actions: `${baseScopeId}-actions` };
return {
color: `${baseScopeId}-color`,
actions: `${baseScopeId}-actions`,
};
}, []);
const { closeDropdown: closeColorDropdown } = useDropdown(dropdownIds.color);
@ -76,6 +83,12 @@ export const SettingsDataModelFieldSelectFormOptionRow = ({
dropdownIds.actions,
);
useEffect(() => {
if (focused === true) {
inputRef.current?.focus();
}
}, [focused]);
return (
<StyledRow className={className}>
<IconGripVertical
@ -109,9 +122,15 @@ export const SettingsDataModelFieldSelectFormOptionRow = ({
}
/>
<StyledOptionInput
ref={inputRef}
disableHotkeys
value={option.label}
onChange={(label) =>
onChange({ ...option, label, value: getOptionValueFromLabel(label) })
onChange({
...option,
label,
value: getOptionValueFromLabel(label),
})
}
RightIcon={isDefault ? IconCheck : undefined}
/>