[DASHBOARDS] Select title input upon tab or widget creation (#17010)

Video QA:


https://github.com/user-attachments/assets/334bbac8-03a5-4eb2-98b7-78bab7abfccf
This commit is contained in:
Raphaël Bosi
2026-01-08 13:37:36 +01:00
committed by GitHub
parent 7fff8c8234
commit 22573ccf03
3 changed files with 29 additions and 14 deletions
@@ -1,7 +1,9 @@
import { usePageLayoutHeaderInfo } from '@/command-menu/components/hooks/usePageLayoutHeaderInfo';
import { useUpdateCommandMenuPageInfo } from '@/command-menu/hooks/useUpdateCommandMenuPageInfo';
import { usePageLayoutIdFromContextStoreTargetedRecord } from '@/command-menu/pages/page-layout/hooks/usePageLayoutFromContextStoreTargetedRecord';
import { commandMenuPageInfoState } from '@/command-menu/states/commandMenuPageInfoState';
import { commandMenuPageState } from '@/command-menu/states/commandMenuPageState';
import { commandMenuShouldFocusTitleInputComponentState } from '@/command-menu/states/commandMenuShouldFocusTitleInputComponentState';
import { CommandMenuPages } from '@/command-menu/types/CommandMenuPages';
import { useUpdatePageLayoutTab } from '@/page-layout/hooks/useUpdatePageLayoutTab';
import { useUpdatePageLayoutWidget } from '@/page-layout/hooks/useUpdatePageLayoutWidget';
@@ -23,8 +25,19 @@ export const CommandMenuPageLayoutInfo = () => {
const theme = useTheme();
const { getIcon } = useIcons();
const commandMenuPage = useRecoilValue(commandMenuPageState);
const commandMenuPageInfo = useRecoilValue(commandMenuPageInfoState);
const { pageLayoutId } = usePageLayoutIdFromContextStoreTargetedRecord();
const [shouldFocusTitleInput, setShouldFocusTitleInput] =
useRecoilComponentState(
commandMenuShouldFocusTitleInputComponentState,
commandMenuPageInfo.instanceId,
);
const handleTitleInputOpen = () => {
setShouldFocusTitleInput(false);
};
const draftPageLayout = useRecoilComponentValue(
pageLayoutDraftComponentState,
pageLayoutId,
@@ -121,6 +134,8 @@ export const CommandMenuPageLayoutInfo = () => {
onClickOutside={saveTitle}
onTab={saveTitle}
onShiftTab={saveTitle}
shouldFocus={shouldFocusTitleInput}
onFocus={handleTitleInputOpen}
/>
}
label={headerType}
@@ -25,8 +25,8 @@ type InputProps = {
export type TitleInputProps = {
disabled?: boolean;
shouldOpen?: boolean;
onOpen?: () => void;
shouldFocus?: boolean;
onFocus?: () => void;
} & InputProps;
const StyledDiv = styled.div<{
@@ -145,8 +145,8 @@ export const TitleInput = ({
onClickOutside,
onTab,
onShiftTab,
shouldOpen,
onOpen,
shouldFocus,
onFocus,
}: TitleInputProps) => {
const [isOpened, setIsOpened] = useState(false);
@@ -155,11 +155,11 @@ export const TitleInput = ({
return (
<>
<TitleInputAutoOpenEffect
shouldOpen={shouldOpen}
shouldFocus={shouldFocus}
isOpened={isOpened}
disabled={disabled}
instanceId={instanceId}
onOpen={onOpen}
onFocus={onFocus}
setIsOpened={setIsOpened}
/>
{isOpened ? (
@@ -5,26 +5,26 @@ import { FocusComponentType } from '@/ui/utilities/focus/types/FocusComponentTyp
import { isDefined } from 'twenty-shared/utils';
type TitleInputAutoOpenEffectProps = {
shouldOpen?: boolean;
shouldFocus?: boolean;
isOpened: boolean;
disabled?: boolean;
instanceId: string;
onOpen?: () => void;
onFocus?: () => void;
setIsOpened: (isOpened: boolean) => void;
};
export const TitleInputAutoOpenEffect = ({
shouldOpen,
shouldFocus,
isOpened,
disabled,
instanceId,
onOpen,
onFocus,
setIsOpened,
}: TitleInputAutoOpenEffectProps) => {
const { pushFocusItemToFocusStack } = usePushFocusItemToFocusStack();
useEffect(() => {
if (isDefined(shouldOpen) && shouldOpen && !isOpened && !disabled) {
if (isDefined(shouldFocus) && shouldFocus && !isOpened && !disabled) {
setIsOpened(true);
pushFocusItemToFocusStack({
focusId: instanceId,
@@ -36,15 +36,15 @@ export const TitleInputAutoOpenEffect = ({
enableGlobalHotkeysConflictingWithKeyboard: false,
},
});
onOpen?.();
onFocus?.();
}
}, [
shouldOpen,
shouldFocus,
isOpened,
disabled,
instanceId,
pushFocusItemToFocusStack,
onOpen,
onFocus,
setIsOpened,
]);