Migrate twenty ui to jotai (#17900)

## Remove Recoil from twenty-ui

Completely removes the `recoil` dependency from `twenty-ui` by
converting all atoms, hooks, and providers to Jotai equivalents.

### twenty-ui
- `createState` now returns a Jotai `PrimitiveAtom` instead of a Recoil
atom
- `iconsState`, `IconsProvider`, `useIcons` converted to Jotai
(`useSetAtom`, `useAtomValue`)
- `RecoilRootDecorator` now uses Jotai `Provider` (name kept for compat)
- Deleted unused `invalidAvatarUrlsState` (Avatar already uses
`invalidAvatarUrlsAtomV2`)
- Removed `recoil` from `package.json`

### twenty-front
- Created local Recoil `createState` at
`@/ui/utilities/state/utils/createState` for ~112 state files still on
Recoil
- Updated all imports accordingly
- Removed `iconsState` from Recoil snapshot preservation in `useAuth`
(lives in Jotai store now)
This commit is contained in:
Charles Bochet
2026-02-12 16:43:34 +01:00
committed by GitHub
parent 09e48addb2
commit 310d13fd17
139 changed files with 165 additions and 168 deletions
@@ -1,4 +1,4 @@
import { createState } from 'twenty-ui/utilities';
import { createState } from '@/ui/utilities/state/utils/createState';
export const lastShowPageRecordIdState = createState<string | null>({
key: 'lastShowPageRecordIdState',
@@ -1,4 +1,4 @@
import { createState } from 'twenty-ui/utilities';
import { createState } from '@/ui/utilities/state/utils/createState';
export const recordIndexCalendarFieldMetadataIdState = createState<
string | null
@@ -1,4 +1,4 @@
import { createState } from 'twenty-ui/utilities';
import { createState } from '@/ui/utilities/state/utils/createState';
import { ViewCalendarLayout } from '~/generated-metadata/graphql';
export const recordIndexCalendarLayoutState = createState<ViewCalendarLayout>({
@@ -1,6 +1,6 @@
import { type FieldMetadata } from '@/object-record/record-field/ui/types/FieldMetadata';
import { type ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition';
import { createState } from 'twenty-ui/utilities';
import { createState } from '@/ui/utilities/state/utils/createState';
export const recordIndexFieldDefinitionsState = createState<
ColumnDefinition<FieldMetadata>[]
@@ -1,5 +1,5 @@
import { ViewOpenRecordInType } from '@/views/types/ViewOpenRecordInType';
import { createState } from 'twenty-ui/utilities';
import { createState } from '@/ui/utilities/state/utils/createState';
export const recordIndexOpenRecordInState = createState<ViewOpenRecordInType>({
key: 'recordIndexOpenRecordInState',
@@ -1,5 +1,5 @@
import { type ViewType } from '@/views/types/ViewType';
import { createState } from 'twenty-ui/utilities';
import { createState } from '@/ui/utilities/state/utils/createState';
export const recordIndexViewTypeState = createState<ViewType | undefined>({
key: 'recordIndexViewTypeState',
@@ -1,4 +1,4 @@
import { createState } from 'twenty-ui/utilities';
import { createState } from '@/ui/utilities/state/utils/createState';
export const isMergeInProgressState = createState<boolean>({
key: 'isMergeInProgress',
@@ -1,5 +1,5 @@
import { type MergeManySettings } from '@/object-record/hooks/useMergeManyRecords';
import { createState } from 'twenty-ui/utilities';
import { createState } from '@/ui/utilities/state/utils/createState';
export const mergeSettingsState = createState<MergeManySettings>({
key: 'mergeSettingsState',
@@ -1,4 +1,4 @@
import { createState } from 'twenty-ui/utilities';
import { createState } from '@/ui/utilities/state/utils/createState';
export const viewableRecordIdState = createState<string | null>({
key: 'activities/viewable-record-id',
@@ -1,4 +1,4 @@
import { createState } from 'twenty-ui/utilities';
import { createState } from '@/ui/utilities/state/utils/createState';
// TODO: deprecate this state once we remove IS_COMMAND_MENU_V2_ENABLED flag
export const viewableRecordNameSingularState = createState<string | null>({
key: 'activities/viewable-record-name-singular',
@@ -1,4 +1,4 @@
import { createState } from 'twenty-ui/utilities';
import { createState } from '@/ui/utilities/state/utils/createState';
export const tableWidthResizeIsActiveState = createState({
key: 'tableWidthResizeIsActiveState',