Commit Graph

9 Commits

Author SHA1 Message Date
eba997be98 Replace hotkey scopes by focus stack (Part 6 - Remove Hotkey scopes 🫳🎤) (#13127)
# Replace hotkey scopes by focus stack (Part 6 - Remove Hotkey scopes)

This PR is the last part of a refactoring aiming to deprecate the hotkey
scopes api in favor of the new focus stack api which is more robust.
Part 1: https://github.com/twentyhq/twenty/pull/12673
Part 2: https://github.com/twentyhq/twenty/pull/12798
Part 3: https://github.com/twentyhq/twenty/pull/12910
Part 4: https://github.com/twentyhq/twenty/pull/12933
Part 5: https://github.com/twentyhq/twenty/pull/13106

In this part, we completely remove the hotkey scopes.
2025-07-09 17:21:14 +02:00
22b4595b0b Refactor useDropdownV2 (#12875)
# What this PR does

This PR introduces what’s needed to progressively refactor the
useDropdown hooks we have.

It removes useDropdownV2 and renames useDropdown used for multi-page
dropdowns to useDropdownContextStateManagement

## The 3 useDropdown hooks

There are currently 3 useDropdown hooks : 

One is used for managing states in some dropdowns that have multiple
inner pages with contexts and without recoil. It is limited and would
need a separate refactoring, thus I just renamed it.

Then we have useDropdown and useDropdownV2, which followed our multiple
versions of recoil state management wrappers.

Now that the state management has been stabilized, we can merge
everything on the last version.

## What this refactor will allow next

This refactor will allow to refactor the legacy recoil state management,
because useDropdown is depending on legacy recoil states with scopeId.

Because there are only a dozen of those legacy states left, and the
dropdown’s ones are the harder to refactor, because swapping them as-is
causes a big QA, and if we have a big QA to do on all dropdowns, better
refactor the whole dropdown management and have everything clean.

After this refactor, we will be able to delete the legacy dropdown
states, and proceed with the other legacy states, then removing all the
legacy recoil state mangament.

## How do we allow progressive refactoring ?

There are many places where useDropdown is used.

To have an easier refactoring process, we want to merge multiple small
pull requests so that it is easier to QA and review.

For this we will maintain both legacy component state and component
state V2 in parallel for isDropdownOpen, so that the new hooks
`useOpenDropdown` , `useCloseDropdown` are doing the same thing than
`useDropdown` and `useDropdownV2` .

Thus for the moment, whether we use the legacy hooks or the new ones,
the effects are the same.

And we can have dropdowns operating on the old states and the new states
living side by side in the app.

## QA

Component | Status | Comments
-- | -- | --
CommandMenuActionMenuDropdown | Ok |  
RecordIndexActionMenuDropdown | Ok |  
RecordShowRightDrawerOpenRecordButton | Ok |  
useCloseActionMenu | Ok |  
CommandMenuContextChipGroups | Ok |  
useCommandMenuCloseAnimationCompleteCleanup | Ok |  
ObjectOptionsDropdown | Ok |  
ObjectOptionsDropdownContent | Ok |  
ObjectOptionsDropdownFieldsContent | Ok |  
ObjectOptionsDropdownHiddenFieldsContent | Ok |  
ObjectOptionsDropdownHiddenRecordGroupsContent | Ok |  
ObjectOptionsDropdownLayoutContent | Ok |  
ObjectOptionsDropdownLayoutOpenInContent | Ok |  
ObjectOptionsDropdownMenuContent | Ok |  
ObjectOptionsDropdownRecordGroupFieldsContent | Ok |  
ObjectOptionsDropdownRecordGroupsContent | Ok |  
ObjectOptionsDropdownRecordGroupSortContent | Ok |  
RecordBoardColumnHeaderAggregateDropdown | Ok |  
AggregateDropdownContent | Ok |  
RecordBoardColumnHeaderAggregateDropdownFieldsContent | Ok |  
RecordBoardColumnHeaderAggregateDropdownMenuContent | Ok |  
RecordBoardColumnHeaderAggregateDropdownMenuContent | Ok |  
RecordBoardColumnHeaderAggregateDropdownOptionsContent | Ok |  
RecordBoard | Ok | Used closeAnyOpenDropdown instead for a better UX
RecordBoardCard | Ok |  
useRecordBoardSelection | Ok |  
RecordTableColumnAggregateFooterDropdownContent | Ok |  
RecordTableColumnFooterWithDropdown | Ok |  
useOpenRecordFilterChipFromTableHeader | Ok |  
useCloseAnyOpenDropdown | Ok |  
useCloseDropdownFromOutside | Removed | Removed because unused
useDropdownV2 | Removed | Removed because all calls have been removed
useOpenDropdownFromOutside | Removed | Removed because unused
useCloseAndResetViewPicker | Ok |  
WorkflowVariablesDropdown | Ok |
2025-06-25 17:16:56 +02:00
cbc0d06a2f Replace hotkey scopes by focus stack (Part 1 - Dropdowns and Side Panel) (#12673)
This PR is the first part of a refactoring aiming to deprecate the
hotkey scopes api in favor of the new focus stack api which is more
robust.

The refactored components in this PR are the dropdowns and the side
panel/command menu.

- Replaced `useScopedHotkeys` by `useHotkeysOnFocusedElement` for all
dropdown components, selectable lists and the command menu
- Introduced `focusId` for all dropdowns and created a common hotkey
scope `DropdownHotkeyScope` for backward compatibility
- Replaced `setHotkeyScopeAndMemorizePreviousScope` occurrences with
`usePushFocusItemToFocusStack` and `goBackToPreviousHotkeyScope` with
`removeFocusItemFromFocusStack`

Note: Test that the shorcuts and arrow key navigation still work
properly when interacting with dropdowns and the command menu.

Bugs that I have spotted during the QA but which are already present on
main:
- Icon picker select with arrow keys doesn’t work inside dropdowns
- Some dropdowns are not selectable with arrow keys (no selectable list)
- Dropdowns in dropdowns don’t reset the hotkey scope correctly when
closing
- The table click outside is not triggered after closing a table cell
and clicking outside of the table
2025-06-19 14:53:18 +02:00
01b40e173b Refactored dropdown content and fixed all dropdown width bugs (#12334)
This PR refactors all the dropdown content wrapping mechanism across the
entire app.

It refactors the internals of the `Dropdown` component and introduces a
new generic `DropdownContent` component that is a generic wrapper used
for each dropdown.

## Why this PR ?

Because we’ve been experiencing continuous regressions for months on the
dropdown content width, with weird scrolling behaviors in some and not
in others, and every time a solution was found for a particular set of
dropdowns, it broke another set of dropdowns, which wasn’t noticed
because doing the QA of all dropdowns of the app is very difficult for
fixing an apparently small bug.

## Don’t we already have a `DropdownMenu` component ?

Indeed, this new `DropdownContent` is almost like `DropdownMenu` and
took inspiration from it but `DropdownContent` acts as a generic content
container that sets the width of the whole dropdown, whether we have a
menu or not.

## Why don’t we put it directly in Dropdown internals ?

Because the Dropdown component is using a complex logic with floating-ui
middleware to compute its position and size, and for this logic to work
correctly, it cannot be responsible for the “wanted” width of its
content, because the children components, which the dropdown is not
aware of, can request different widths after the dropdown has been
mounted.

A good example with multiple use cases inside the same dropdown can be
found in `AdvancedFilterDropdownFilterInput`

Thus, it is the responsibility of the content of the dropdown to
determine the width it wants to have.

## What is the difference with DropdownMenuItemsContainer ?

We can have multiple `DropdownMenuItemsContainer` in a dropdown,
alongside other components like `DropdownMenuSeparator` or
`DropdownMenuHeader`, and each of those components behaves differently
regarding to its width, paddings, etc. Therefore it is logical that the
`DropdownMenuItemsContainer` cannot be responsible for the whole
dropdown content width, and trying to do so has been the cause of many
regressions for months.

Now `DropdownMenuItemsContainer` is taking a width of `auto` by default,
which is the best to adapt to a parent which has a defined width.

## How do I set the width of my dropdown now ?

By passing a pixel width to the props `widthInPixels` of
`DropdownContent`, which only accepts numbers to avoid any confusion
with `auto` , `100%` or `160px` and other specific width variables.

The `dropdownWidth` props has been removed from `<Dropdown>` to avoid
any confusion.

Also the `DropdownMenuItemsContainer` is now using `auto` as its default
width to fill the available space inside `DropdownContent` .

It is highly recommended to use the enum `GenericDropdownContentWidt` to
define your width.

## Where to use this new `DropdownContent` component ?

There are two main use cases.

If the dropdown content is defined directly inline in the Dropdown
props, then it is recommended to use it here too.

On the other hand if the dropdown content is abstracted in another
component, it’s recommended to use this new component alongside the
others components like `DropdownMenuItemsContainer`.

A good rule of thumb is to place `DropdownContent` where
`DropdownMenuItemsContainer`, `DropdownMenuSearchInput`, etc. are
placed.

## What if I have a custom width ?

Just define a constant like `ICON_PICKER_DROPDOWN_CONTENT_WIDTH` and use
it with the props `widthInPixels` .

Otherwise there’s a `GenericDropdownContentWidth` enum. The default
value being `GenericDropdownContentWidth.Medium` (or 200px), which most
dropdowns use.

## QA 


Component | Comment
-- | --
AttachmentDropdown | Fixed overflowing (thanks to DropdownContent)
RecordIndexActionMenuDropdown |  
CommandMenuActionMenuDropdown |  
SupportDropdown | Fixed overflowing (thanks to DropdownContent)
MessageThreadSubscribersDropdownButton | Removed because unused
FavoriteFolderNavigationDrawerItemDropdown | Set width at Narrow
FavoriteFolderPicker |  
ViewPickerOptionDropdown |  
PageFavoriteFolderDropdown | Removed because unused
AdvancedFilterAddFilterRuleSelect |  
AdvancedFilterAddFilterRuleSelect |  
AdvancedFilterFieldSelectMenu |  
AdvancedFilterRecordFilterGroupOptionsDropdown |  
AdvancedFilterRecordFilterOperanceSelect | Set width at Narrow
AdvancedFilterLogicalOperatorDropdown | Set width at Narrow
AdvancedFilterRecordFilterOptionsDropdown |  
AdvancedFilterRootRecordFilterGroup | Fixed broken horizontal scrolling
behavior
AdvancedFilterSubFieldSelectMenu |  
AdvancedFilterDropdownFilterInput |  
ObjectFilterDropdownBooleanSelect |  
ObjectFilterDropdownCountrySelect | Fixed broken menu items container
ObjectFilterDropdownCurrencySelect | Set width to Large
ObjectFilterDropdownFilterInput |  
ObjectFilterDropdownOperandDropdown | Fixed width that was not fixed
ObjectFilterDropdownFilterInput | Fixed width that wasn’t the same for
EditableFilterChip
ObjectFilterDropdownOperandSelect | Refactored
ObjectOptionsDropdownRecordGroupFieldsContent | Added missing separator
ObjectOptionDropdownFieldsContent |  
ObjectOptionsDropdownHiddenFieldsContent |  
ObjectOptionsDropdownLayoutContent |  
ObjectOptionsDropdownLayoutOpenInContent |  
ObjectOptionsDropdownMenuContent |  
ObjectOptionsDropdownRecordGroupFieldsContent |  
ObjectOptionsDropdownRecordGroupsContent |  
ObjectOptionsDropdownRecordGroupSortContent |  
ObjectOptionsDropdownHiddenRecordGroupsContent | Removed unnecessary
DropdownMenuItemsContainer
RecordBoardColumnHeaderAggregateDropdown | Fixed overflowing (thanks to
DropdownContent)
RecordBoardColumnHeaderAggregateDropdownFieldsContent | Fixed
overflowing (thanks to DropdownContent)
RecordBoardColumnHeaderAggregateDropdownMenuContent | Fixed overflowing
(thanks to DropdownContent)
RecordBoardColumnHeaderAggregateDropdownOptionsContent | Fixed
overflowing (thanks to DropdownContent)
MultiItemFieldInput | Fixed overflowing (thanks to DropdownContent)
MultiItemFieldMenuItem |  
MultipleRecordPicker | Fixed overflowing (thanks to DropdownContent)
SingleRecordPicker |  
RecordTableColumnAggregateDropdownSubmenuContent |  
RecordTableColumnAggregateFooterMenuContent |  
RecordTableColumnHeadDropdownMenu | Fixed overflowing (thanks to
DropdownContent)
RecordTableHeaderPlusButtonContent |  
MultipleSelectDropdown | Broken width fixed
ObjectSortDropdownButton |  
RecordDetailRelationRecordsListItem |  
ConfigVariableDatabaseInput |  
ConfigVariableOptionsDropdownContent |  
SettingsObjectFieldActiveActionDropdown | Fixed overflowing (thanks to
DropdownContent)
SettingsObjectFieldDisabledActionDropdown | Set width at Narrow
SettingsObjectSummaryCard | Removed because unused
SettingsDataModelFieldSelectFormOptionRow |  
SettingsDataModelNewFieldBreadcrumbDropdown |  
SettingsObjectInactiveMenuDropDown |  
SettingsRoleAssignementWorkspaceMemberPickerDropdown |  
SettingsRolePermissionObjectLevelObjectPickerDropdownContent |  
SettingsSecurityApprovedAccessDomainRowDropdownMenu | Couldn’t test
SettingsSecuritySSORowDropdownMenu | Couldn’t test
SettingsAccountsRowDropdownMenu | Fixed overflowing (thanks to
DropdownContent)
SettingsIntegrationDatabaseConnectionSummaryCard | Couldn’t test
SettingsServerlessFunctionTablEnvironmentVariableTableRow | Deactivated
scope
MatchColumnSelectFieldSelectDropdownContent | Removed now unnecessary
width on DropdownMenuItemsContainer
MatchColumnSelectSubFieldSelectDropdownContent |  
SubMatchingSelectInput |  
CurrencyPickerDropdownSelect |  
IconPicker | Fixed overflowing (thanks to DropdownContent)
PhoneCountryPickerDropdownSelect |  
Select | Refactored to drilldown wanted width of content, in this case
it’s intended
ExpandedListDropdown |  
ShowPageAddButton | Removed because unused
MultiWorkspaceDropdownDefaultComponent |  
MultiWorkspaceDropdownThemesComponent |  
MultiWorkspaceDropdownWorkspacesListComponent |  
AdvancedFilterDropdownButton |  
EditableFilterChip |  
EditableFilterDropdownButton |  
UpdateViewButtonGroup |  
ViewBarFilterDropdown |  
ViewBarFilterDropdownFieldSelectMenu |  
ViewPickerContentCreateMode |  
ViewPickerContentEditMode |  
ViewPickerListContent |  
WorkflowEditTriggerDatabaseEventForm |  
WorkflowVariablesDropdownFieldItems |  
WorkflowVariablesDropdownObjectItems |  
WorkflowVariablesDropdownWorkflowStepItems |  
CommandMenuContextChipGroups |  
RecordBoardColumnDropdownMenu |  
MultiSelectInput |  
SelectInput |  
CustomSlashMenu |  
DropdownMenu | Removed and replaced by DropdownContent
OverlayContainer and around |  


<!-- notionvc: 1e23bdb8-2dda-4f8d-a64d-ecc829a768a2 -->

## Miscellaneous 

Side notes : 

- The `Select` component is now wrapping the `DropdownContent` because
it computes a dynamic width.
- The advanced filter dropdown has been fixed, it was broken when
resizing the window horizontally, we couldn’t scroll. This specific edge
case was taken into account when refactoring the whole dropdown content
system
- As discussed with Nitin, data-select-disable will probably be removed
entirely, so I let it as is, because right now it is not used by the
refactored d&d selection.
- Duplicate separators under DropdownMenuHeader have been removed.

Fixes : https://github.com/twentyhq/twenty/issues/12327
Fixes : https://github.com/twentyhq/core-team-issues/issues/951
2025-05-27 19:44:13 +02:00
f201091c68 512 Ability to navigate dropdown menus with keyboard (#11735)
# Ability to navigate dropdown menus with keyboard

The aim of this PR is to improve accessibility by allowing the user to
navigate inside the dropdown menus with the keyboard.
This PR refactors the `SelectableList` and `SelectableListItem`
components to move the Enter event handling responsibility from
`SelectableList` to the individual `SelectableListItem` components.
Closes [512](https://github.com/twentyhq/core-team-issues/issues/512)

## Key Changes:
- All dropdowns are now navigable with arrow keys

## Technical Implementation:
- Each `SelectableListItem` now has direct access to its own `Enter` key
handler, improving component encapsulation
- Removed the central `Enter` key handler logic from `SelectableList`
- Added `SelectableList` and `SelectableListItem` to all `Dropdown`
components inside the app
- Updated all component implementations to adapt to the new pattern:
  - Action menu components (`ActionDropdownItem`, `ActionListItem`)
  - Command menu components
  - Object filter, sort and options dropdowns
  - Record picker components
  - Select components

---------

Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
2025-04-25 18:55:39 +02:00
9e0402e691 Action menu refactoring (#11454)
# Description

Closes [#696](https://github.com/twentyhq/core-team-issues/issues/696)

- `useAction` hooks have been removed for all actions
- Every action can now declare a react component
- Some standard action components have been introduced: `Action`,
`ActionLink` and `ActionModal`
- The `ActionDisplay` component uses the new `displayType` prop of the
`ActionMenuContext` to render the right component for the action
according to its container: `ActionButton`, `ActionDropdownItem` or
`ActionListItem`
- The `ActionDisplayer` wraps the action component inside a context
which gives it all the information about the action
-`actionMenuEntriesComponenState` has been removed and now all actions
are computed directly using `useRegisteredAction`
- This computation is done inside `ActionMenuContextProvider` and the
actions are passed inside a context
- `actionMenuType` gives information about the container of the action,
so the action can know wether or not to close this container upon
execution
2025-04-09 13:12:49 +00:00
4a4e65fe4a [REFACTOR] Twenty UI multi barrel (#11301)
# Introduction
closes https://github.com/twentyhq/core-team-issues/issues/591
Same than for `twenty-shared` made in
https://github.com/twentyhq/twenty/pull/11083.

## TODO
- [x] Manual migrate twenty-website twenty-ui imports

## What's next:
- Generate barrel and migration script factorization within own package
+ tests
- Refactoring using preconstruct ? TimeBox
- Lint circular dependencies
- Lint import from barrel and forbid them

### Preconstruct
We need custom rollup plugins addition, but preconstruct does not expose
its rollup configuration. It might be possible to handle this using the
babel overrides. But was a big tunnel.
We could give it a try afterwards ! ( allowing cjs interop and stuff
like that )
Stuck to vite lib app

Closed related PRs:
- https://github.com/twentyhq/twenty/pull/11294
- https://github.com/twentyhq/twenty/pull/11203
2025-04-03 09:47:55 +00:00
0084946b76 608 fix hotkey scope and dropdown issues in the command menu (#11121)
Closes https://github.com/twentyhq/core-team-issues/issues/608

- Introduces a new hotkey scope `CommandMenuFocused`
- Fixes hotkey scopes issues in the side panel
2025-03-24 14:34:09 +00:00
9f9302136f Fix command O delete action on record page (#10820)
There were two issues, the hotkey scope wasn't set properly when opening
the dropdown with the shortcut and we didn't close the command menu upon
completion of the delete action.

Before:


https://github.com/user-attachments/assets/817442ae-6db4-4fc5-a637-4e2e3d9b9b70


After:


https://github.com/user-attachments/assets/b6fd07f6-6c2f-4b29-9162-f29b661ad358
2025-03-13 08:09:49 +01:00