In this PR:
- Refactored the page layout renderer
- Converted all the states to component states
- Removed the page layout edition in settings
TODOs in next PRs:
- Fix bug with the drag selector not taking the scroll into account to
display the dragged area
- Readd the tab edition in edit mode
## Problem
**CRITICAL:** Two PRs were accidentally reverted when PR #14347 "Prevent
csv export injections" was merged:
1. **PR #14348** "[Page Layout] - Review Refactor" - ✅ **RESTORED**
2. **PR #14352** "Fix wrong path used by backend" - ✅ **RESTORED**
## Root Cause Analysis
During the merge of PR #14347, there was a complex merge conflict with
PR #14352 "Fix wrong path used by backend". The merge commit
`324d7204bb` in the PR #14347 branch brought in changes from PR #14352,
but during the conflict resolution, **BOTH PR #14348 and PR #14352's
changes were accidentally overwritten**.
## What This PR Restores
This PR restores **BOTH** PRs by cherry-picking their commits:
### ✅ PR #14348 Changes Restored:
- `GraphWidgetRenderer.tsx` - was deleted, now restored
- `WidgetRenderer.tsx` - was missing, now restored
- `SettingsPageLayoutTabsInstanceId.ts` - was deleted, now restored
- `useUpdatePageLayoutWidget.ts` - was renamed back, now restored with
correct name
- Multiple test files that were deleted
- Several hook files that were renamed/reverted
- File renames: `usePageLayoutWidgetUpdate.ts` →
`useUpdatePageLayoutWidget.ts`
- Hook refactoring and test file organization
- Page layout component improvements
### ✅ PR #14352 Changes Restored:
- **Types moved to twenty-shared:**
- `packages/twenty-shared/src/types/AppBasePath.ts` ✅ RESTORED
- `packages/twenty-shared/src/types/AppPath.ts` ✅ RESTORED
- `packages/twenty-shared/src/types/SettingsPath.ts` ✅ RESTORED
- **Navigation utilities moved to twenty-shared:**
- `packages/twenty-shared/src/utils/navigation/getAppPath.ts` ✅ RESTORED
- `packages/twenty-shared/src/utils/navigation/getSettingsPath.ts` ✅
RESTORED
- **200+ import statements updated** across the codebase to use
twenty-shared
- **Old type files deleted** from twenty-front/src/modules/types/
## Evidence of Complete Restoration
**Before (reverted state):**
- ❌ Types were in `packages/twenty-front/src/modules/types/`
- ❌ Page layout files missing
- ❌ Hook files incorrectly named
**After (this PR):**
- ✅ Types correctly in `packages/twenty-shared/src/types/`
- ✅ All page layout files restored
- ✅ Hook files correctly named
- ✅ All import statements updated
## Verification
**Total changes:**
- PR #14348: 36 files changed, 863 insertions(+), 442 deletions(-)
- PR #14352: 243 files changed, 492 insertions(+), 461 deletions(-)
- **Combined: 279 files changed, 1355 insertions(+), 903 deletions(-)**
## Impact
This completely restores both PRs that were accidentally lost, ensuring:
1. Page layout refactoring work is back
2. Type organization and path utilities are correctly in twenty-shared
3. Backend email paths work correctly again
4. No functionality is lost
Fixes the reversion caused by the merge conflict in PR #14347.
---------
Co-authored-by: nitin <142569587+ehconitin@users.noreply.github.com>
**Small Security Issue:** CSV exports were vulnerable to formula
injection attacks when users entered values starting with =, +, -, or @.
(only happens if a logged-in user injects corrupted data)
Solution:
- Added ZWJ (Zero-Width Joiner) protection that prefixes dangerous
values with invisible Unicode character
- This is the best way to preserve original data while preventing Excel
from executing formulas
- Added import cleanup to restore original values when re-importing
Changes:
- New sanitizeValueForCSVExport() function for security
- Updated all CSV export paths to use both security + formatting
functions
- Added comprehensive tests covering attack vectors and international
characters
- Also added cursor rules for better code consistency
---------
Co-authored-by: Charles Bochet <charlesBochet@users.noreply.github.com>
After moving a section on the frontend, this broke the path that was
sent by email on the backend.
This kind of error comes back every ~2-3 month under different forms so
we need a more robust solution: I moved routes to the shared folder,
that way we will share one common source of truth between the frontend
and the backend.
Fixes#14343
The goal of this PR is to test if Twenty can support a large number of
members, a question which was raised by a large company that is
considering moving away from Salesforce.
I was expecting the currentWorkspaceMembersState to cause a lot more
issue. It would be very hard to get rid of it in the context of actors,
I think that would require a big refactoring. I thought we'd have to do
it but it turns out the perf are pretty good. One thing we need to
improve is the pagination on the roles page, we'll wait for @Bonapara to
update that
## Summary
- Fixes#12893 - Workspace switcher button now aligns properly with
record index headers when navigation drawer is collapsed
- Maintains consistent button height in both expanded and collapsed
states
- Simple CSS fix that improves visual consistency
## Fix Details
The issue was caused by the workspace switcher button changing height
from 20px (expanded) to 16px (collapsed). This created misalignment with
the page headers.
Changed in `MultiWorkspacesDropdownStyles.tsx`:
```tsx
// Before - height changed based on drawer state
height: ${({ theme, isNavigationDrawerExpanded }) =>
isNavigationDrawerExpanded ? theme.spacing(5) : theme.spacing(4)};
// After - consistent height
height: ${({ theme }) => theme.spacing(5)};
```
## Visual Alignment
- Workspace switcher button: 20px height (theme.spacing(5))
- Maintains alignment with record index headers in collapsed state
- Consistent with Figma design requirements
## Test Plan
- [x] Collapsed navigation drawer - workspace switcher aligns with
headers
- [x] Expanded navigation drawer - no visual regression
- [x] Button functionality remains unchanged
---
🤖 This fix was implemented using [Claude Code](https://claude.ai/code)
by Jez (Jeremy Dawes) and Claude working together\!
Thanks to the Twenty team for the great project\! 🚀
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: ehconitin <nitinkoche03@gmail.com>
Co-authored-by: nitin <142569587+ehconitin@users.noreply.github.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
We previously used classnames to exclude elements from the click outside
listener.
With this PR we can now use `data-click-outside-id` instead of
`classNames` to target the elements we want to exclude from the click
outside listener.
We can also add `data-globally-prevent-click-outside` to a component to
globally prevent triggering click outside listeners for other
components. This attribute is especially useful for confirmation modals
and snackbar items.
Fixes#11785:
https://github.com/user-attachments/assets/318baa7e-0f82-4e3a-a447-bf981328462d
Recoil-sync was causing issues with Firefox, replacing it with a simpler
mechanism to hydrate variables on page load
---------
Co-authored-by: etiennejouan <jouan.etienne@gmail.com>
closes#11195closes#11199
### Context
The yellow dots in the Settings Navigation Drawer (used to indicate
advanced settings) were being hidden due to ScrollWrapper's overflow
handling. This required both a fix for the visibility issue and an
improvement to the component structure.
### Changes
1. Keep scrolling logic of the MainNavigationDrawer and
SettingsNavigationDrawer in one place, and conditionally apply
`<StyledScrollableInnerContainer>` when isSettingsDrawer is true.
2. Fixed Yellow Dots Visibility
Added specific padding in NavigationDrawerScrollableContent to
accommodate yellow dots:
```
padding-left: ${theme.spacing(5)}; // Space for yellow dots
padding-right: ${theme.spacing(8)}; // Space for no-padding scroll
```
This ensures the yellow dots are visible while maintaining proper scroll behavior
3. Improved Component Composition
Using proper component composition instead of passing components as props
Components are now composed in a more React-idiomatic way:
```
<NavigationDrawer>
<NavigationDrawerScrollableContent>
<SettingsNavigationDrawerItems />
</NavigationDrawerScrollableContent>
<NavigationDrawerFixedContent>
<AdvancedSettingsToggle />
</NavigationDrawerFixedContent>
</NavigationDrawer>
```
---------
Co-authored-by: Charles Bochet <charles@twenty.com>
#11414
Conditionally render MobileNavigationBar based on user authentication
status
- Added useIsLogged hook to check if the user is authenticated.
- Updated MobileNavigationBar component to render only when the user is
logged in.

---------
Co-authored-by: Charles Bochet <charles@twenty.com>
After investiagting the different options ([see related
issue](https://github.com/twentyhq/core-team-issues/issues/660#issuecomment-2766030972))
I decided to add a "Verify Component" and a to build a custom Layout for
this route.
Reason I cannot use the default one is to have all preloaded once the
user changes website and lands on the verify route.
Reason I did not modify the DefaultLayout to match our need is that is
would require many changes in order to avoid preloading states for our
specific usecase.
Fixes https://github.com/twentyhq/core-team-issues/issues/660
---------
Co-authored-by: Charles Bochet <charles@twenty.com>
## What
- Deprecate overlayscrollbars as we decided to follow the native
behavior
- rework on performances (avoid calling recoil states too much at field
level which is quite expensive)
- Also implements:
https://github.com/twentyhq/core-team-issues/issues/569
---------
Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
# 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
## What
This PR aims to make sure all application exceptions are captured
through react-error-boundaries
Once merged we will have:
- Root Level: AppErrorBoundary at the highest level (full screen) ==>
this one needs to be working in any case, not relying on Theme, was not
working
- Route Level: AppErrorBoundary in DefaultLayout (full screen) ==> this
was missing and it seems that error are not propagated outside of the
router, making errors triggered in CommandMenu or NavigationDrawer
missing
- Page Level: AppErrorBoundary in DefaultLayout write around the Page
itself (lower than CommandMenu + NavigationDrawer)
- Manually triggered: example in ClientConfigProvider
## Screenshots
App level (ex throw in IconsProvider)
<img width="1512" alt="image"
src="https://github.com/user-attachments/assets/18a14815-a203-4edf-b931-43068c3436ec"
/>
Route level (ex throw in CommandMenu)
<img width="1512" alt="image"
src="https://github.com/user-attachments/assets/ca066627-14c7-438e-a432-f0999a1f3b84"
/>
Page level (ex throw in RecordTable)
<img width="1512" alt="image"
src="https://github.com/user-attachments/assets/ffeaa935-02af-4762-8859-7a0ccf8b77e1"
/>
Manually Triggered (clientConfig, ex when backend is not up)
<img width="1512" alt="image"
src="https://github.com/user-attachments/assets/062d6d84-097a-4ed9-b6ce-763b8c27c659"
/>
Closes https://github.com/twentyhq/core-team-issues/issues/271
This PR
- Removes the feature flag IS_COMMAND_MENU_V2_ENABLED
- Removes all old Right drawer components
- Removes the Action menu bar
- Removes unused Copilot page
- Created an new component state
`isRecordEditableNameRenamingComponentState`
- Updated `useCreateNewTableRecord` to open the ShowPage on workflow
creation
- Refactored `RecordEditableName` and its components to remove the
useEffect (This was causing the recordName state to be updated after the
focus on `NavigationDrawerInput`, but we want the text so be selected
after the update).
- Introduced a new component `EditableBreadcrumbItem`
- Created an autosizing text input: This is done by a hack using a span
inside a div and the input position is set to absolute and takes the
size of the div. There are two problems that I didn't manage to fix:
If the text is too long, the title overflows, and the letter spacing is
different between the span and the input creating a small offset.
https://github.com/user-attachments/assets/4aa1e177-7458-4691-b0c8-96567b482206
New text input component:
https://github.com/user-attachments/assets/94565546-fe2b-457d-a1d8-907007e0e2ce
The DX is not great when you need to do a lot of database
resets/command.
Should we disable Typescript validation to speed things up? With this
and caching database:reset takes 1min instead of 2 on my machine.
See also: https://github.com/typeorm/typeorm/issues/4136
And #9291 / #9293
---------
Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
Refactored the `CommandMenu` component to make it more readable and
easier to refactor.
The file was way too big so I introduced a few hooks and eliminated code
duplication.
Introduced:
- `useMatchCommands` hook to match commands with the search
- `useCommandMenuCommands` which returns all command menu commands
- `useMatchingCommandMenuCommands` to return the commands matched with
the search
- `CommandMenuContainer` to simplify the `DefaultLayout`
- Unmounted the `CommandMenu` when it wasn't opened to improve
performances
I also introduced a new behavior: Automatically select the first item
when opening the command menu:
https://github.com/user-attachments/assets/4b683d49-570e-47c9-8939-99f42ed8691c
Closes#8978
- Added new options in the actions config files: `shortLabel`,
`availableOn`
- Added two actions: Navigate to previous records and Navigate to next
records
- Modified `useRecordShowPagePagination` to loop on records when we are
on first record and we hit previous or when we are on last record and we
hit next
- Introduced a new component state
`contextStoreCurrentViewTypeComponentState`
Fixes: #7999
1. Summary
I am not 100% sure why it's happening, but it seems `justify-content:
center` conflicts with `overflow-y: auto` and that's why the modal
content becomes unscrollable and cut off.
2. Solution
To preserve the styling that centers the content inside the modal even
when the content height is less than the modal, I moved
`justify-content: center` from the content to the modal container. When
the content overflows the modal, it seems `justify-content: center` does
nothing, though.
3. Screen Recording
https://github.com/user-attachments/assets/17d8ddbd-7fe8-46ce-b8d0-82d817ee7025
---------
Co-authored-by: Félix Malfait <felix@twenty.com>
Closes#8929
Users with the feature flag `IS_PAGE_HEADER_V2_ENABLED` set to false
will still have the old behavior with the action bar.
To test the PR, test with and without the feature flag.
Fixes two bugs:
- The command menu contains hooks which were trying to execute queries
even when the user was logged out
- The command menu could be opened with the command + K shortcut even
when the user was logged out
Closes#8737
- Refactored actions by creating hooks to add the possibility to
register actions programatically.
- Small fixes from #8610 review
- Fixed shortcuts display inside the command menu
- Removed `actionMenuEntriesComponentState` and introduced
`actionMenuEntriesComponentSelector`
Something changed, which affected the Favorite folder picker checkbox
styles -- fixed it!
Cleaned up code in `CurrentWorkspaceMemberFavoritesFolders` - removed
redundant filtering since favorites are already filtered in
`usePrefetchedFavoritesData`.
Regarding issue #8569 - I am not sure what to do in this case. Since
Folders data is gated by a feature flag, we can't use it in
`CurrentWorkspaceMemberFavoritesFolders` to ensure the favorite section
renders with empty folders. Currently, the section only appears when at
least one favorite exists - may be leave this section open at all times
or fix this bug after removal of the feature flag?
---------
Co-authored-by: Nitin Koche <nitinkoche@Nitins-MacBook-Pro.local>
Co-authored-by: Charles Bochet <charles@twenty.com>