Compare commits

...

3 Commits

Author SHA1 Message Date
Lucas Bordeau 0dbe14f213 Fixes for production (#13164)
This PR fixes two bugs : 
- Some important push item to focus stack calls were setting global
hotkey conflicting keys to true (like open dropdown)
- Icon picker matrix items were broken
2025-07-10 18:13:48 +02:00
Raphaël Bosi 8ec4971021 Fix backspace shortcut preventing text deletion in command menu search bar (#13157)
Before:


https://github.com/user-attachments/assets/4d3ba0fb-9655-4f06-af14-2a4cab737a4a


After:


https://github.com/user-attachments/assets/f1bbf360-a09f-4440-9d05-2c9dc1f41f1f
2025-07-10 18:13:40 +02:00
Raphaël Bosi fa120b8581 Fix record table click outside (#13149)
Fixes https://github.com/twentyhq/twenty/issues/13139 introduced by
https://github.com/twentyhq/twenty/pull/13127

The record table click outside was triggered when it shouldn't have been
(clicking inside a dropdown in the side panel).
This PR fixes it by checking the type of the focused element before
triggering the click outside.
Before, we had a check on the current hotkey scope but I removed this
part during the refactoring and I didn't replace it thinking that it
wasn't useful anymore.

Video QA:



https://github.com/user-attachments/assets/68baa9e6-2593-4840-923b-d631c806d9ea
2025-07-10 18:13:24 +02:00
6 changed files with 66 additions and 13 deletions
@@ -117,5 +117,8 @@ export const useCommandMenuHotKeys = () => {
goBackFromCommandMenu,
setGlobalCommandMenuContext,
],
options: {
preventDefault: false,
},
});
};
@@ -5,7 +5,10 @@ import { useRecordTableContextOrThrow } from '@/object-record/record-table/conte
import { useLeaveTableFocus } from '@/object-record/record-table/hooks/internal/useLeaveTableFocus';
import { MODAL_BACKDROP_CLICK_OUTSIDE_ID } from '@/ui/layout/modal/constants/ModalBackdropClickOutsideId';
import { PAGE_ACTION_CONTAINER_CLICK_OUTSIDE_ID } from '@/ui/layout/page/constants/PageActionContainerClickOutsideId';
import { currentFocusedItemSelector } from '@/ui/utilities/focus/states/currentFocusedItemSelector';
import { FocusComponentType } from '@/ui/utilities/focus/types/FocusComponentType';
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
import { useRecoilValue } from 'recoil';
type RecordTableBodyFocusClickOutsideEffectProps = {
tableBodyRef: React.RefObject<HTMLDivElement>;
};
@@ -17,6 +20,10 @@ export const RecordTableBodyFocusClickOutsideEffect = ({
const leaveTableFocus = useLeaveTableFocus(recordTableId);
const currentFocusedItem = useRecoilValue(currentFocusedItemSelector);
const componentType = currentFocusedItem?.componentInstance.componentType;
useListenClickOutside({
excludedClickOutsideIds: [
ACTION_MENU_DROPDOWN_CLICK_OUTSIDE_ID,
@@ -27,6 +34,15 @@ export const RecordTableBodyFocusClickOutsideEffect = ({
listenerId: RECORD_TABLE_CLICK_OUTSIDE_LISTENER_ID,
refs: [tableBodyRef],
callback: () => {
if (
componentType !== FocusComponentType.PAGE &&
componentType !== FocusComponentType.RECORD_TABLE &&
componentType !== FocusComponentType.RECORD_TABLE_ROW &&
componentType !== FocusComponentType.RECORD_TABLE_CELL
) {
return;
}
leaveTableFocus();
},
});
@@ -79,6 +79,10 @@ export const useRecordTitleCell = () => {
prefix: containerType,
}),
},
globalHotkeysConfig: {
enableGlobalHotkeysConflictingWithKeyboard: false,
enableGlobalHotkeysWithModifiers: false,
},
});
const recordTitleCellId = getRecordFieldInputInstanceId({
@@ -60,6 +60,15 @@ const StyledLightIconButton = styled(LightIconButton)<{
: 'transparent'};
`;
const StyledMatrixItem = styled.div`
width: 32px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
`;
const convertIconKeyToLabel = (iconKey: string) =>
iconKey.replace(/[A-Z]/g, (letter) => ` ${letter}`).trim();
@@ -84,18 +93,20 @@ const IconPickerIcon = ({
);
return (
<SelectableListItem itemId={iconKey} onEnter={onClick}>
<StyledLightIconButton
key={iconKey}
aria-label={convertIconKeyToLabel(iconKey)}
size="medium"
title={iconKey}
isSelected={iconKey === selectedIconKey || !!isSelectedItemId}
isFocused={iconKey === focusedIconKey}
Icon={Icon}
onClick={onClick}
/>
</SelectableListItem>
<StyledMatrixItem>
<SelectableListItem itemId={iconKey} onEnter={onClick}>
<StyledLightIconButton
key={iconKey}
aria-label={convertIconKeyToLabel(iconKey)}
size="medium"
title={iconKey}
isSelected={iconKey === selectedIconKey || !!isSelectedItemId}
isFocused={iconKey === focusedIconKey}
Icon={Icon}
onClick={onClick}
/>
</SelectableListItem>
</StyledMatrixItem>
);
};
@@ -50,7 +50,14 @@ export const useOpenDropdown = () => {
type: FocusComponentType.DROPDOWN,
instanceId: dropdownComponentInstanceId,
},
globalHotkeysConfig: args?.globalHotkeysConfig ?? undefined,
globalHotkeysConfig: {
enableGlobalHotkeysConflictingWithKeyboard:
args?.globalHotkeysConfig
?.enableGlobalHotkeysConflictingWithKeyboard ?? false,
enableGlobalHotkeysWithModifiers:
args?.globalHotkeysConfig?.enableGlobalHotkeysWithModifiers ??
false,
},
});
},
[
@@ -0,0 +1,12 @@
import { FocusStackItem } from '@/ui/utilities/focus/types/FocusStackItem';
import { selector } from 'recoil';
import { focusStackState } from './focusStackState';
export const currentFocusedItemSelector = selector<FocusStackItem | undefined>({
key: 'currentFocusedItemSelector',
get: ({ get }) => {
const focusStack = get(focusStackState);
return focusStack.at(-1);
},
});