From ebf7688e3d43dc4a6e7e310f088f4d73c4544ef1 Mon Sep 17 00:00:00 2001 From: Thomas Trompette Date: Tue, 9 Jan 2024 17:01:27 +0100 Subject: [PATCH] Migrate tab list to scope map (#3333) * Migrate tab list to scope map * Return state to hook and let client subscribe to state * Run prettier --------- Co-authored-by: Thomas Trompette --- .../tasks/components/TaskGroups.tsx | 11 ++-- .../components/ShowPageRightContainer.tsx | 16 +++--- .../ui/layout/tab/components/TabList.tsx | 53 ++++++++++--------- .../__stories__/Tablist.stories.tsx | 1 + .../tab/hooks/internal/useTabListStates.ts | 20 +++++++ .../modules/ui/layout/tab/hooks/useTabList.ts | 15 ++++++ .../ui/layout/tab/scopes/TabListScope.tsx | 19 +++++++ .../TabListScopeInternalContext.ts | 7 +++ .../tab/states/activeTabIdScopedState.ts | 6 --- .../tab/states/activeTabIdStateScopeMap.ts | 6 +++ .../twenty-front/src/pages/tasks/Tasks.tsx | 2 +- 11 files changed, 108 insertions(+), 48 deletions(-) create mode 100644 packages/twenty-front/src/modules/ui/layout/tab/hooks/internal/useTabListStates.ts create mode 100644 packages/twenty-front/src/modules/ui/layout/tab/hooks/useTabList.ts create mode 100644 packages/twenty-front/src/modules/ui/layout/tab/scopes/TabListScope.tsx create mode 100644 packages/twenty-front/src/modules/ui/layout/tab/scopes/scope-internal-context/TabListScopeInternalContext.ts delete mode 100644 packages/twenty-front/src/modules/ui/layout/tab/states/activeTabIdScopedState.ts create mode 100644 packages/twenty-front/src/modules/ui/layout/tab/states/activeTabIdStateScopeMap.ts diff --git a/packages/twenty-front/src/modules/activities/tasks/components/TaskGroups.tsx b/packages/twenty-front/src/modules/activities/tasks/components/TaskGroups.tsx index c9c8934aa..8ab5c98f8 100644 --- a/packages/twenty-front/src/modules/activities/tasks/components/TaskGroups.tsx +++ b/packages/twenty-front/src/modules/activities/tasks/components/TaskGroups.tsx @@ -1,16 +1,15 @@ import styled from '@emotion/styled'; import { useOpenCreateActivityDrawer } from '@/activities/hooks/useOpenCreateActivityDrawer'; -import { TasksRecoilScopeContext } from '@/activities/states/recoil-scope-contexts/TasksRecoilScopeContext'; import { useTasks } from '@/activities/tasks/hooks/useTasks'; import { ActivityTargetableObject } from '@/activities/types/ActivityTargetableEntity'; import { IconPlus } from '@/ui/display/icon'; import { Button } from '@/ui/input/button/components/Button'; -import { activeTabIdScopedState } from '@/ui/layout/tab/states/activeTabIdScopedState'; -import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState'; import { AddTaskButton } from './AddTaskButton'; import { TaskList } from './TaskList'; +import { useTabList } from '@/ui/layout/tab/hooks/useTabList'; +import { useRecoilValue } from 'recoil'; const StyledTaskGroupEmptyContainer = styled.div` align-items: center; @@ -69,10 +68,8 @@ export const TaskGroups = ({ const openCreateActivity = useOpenCreateActivityDrawer(); - const [activeTabId] = useRecoilScopedState( - activeTabIdScopedState, - TasksRecoilScopeContext, - ); + const { activeTabIdState } = useTabList('task-groups-tab-list'); + const activeTabId = useRecoilValue(activeTabIdState); if ( (activeTabId !== 'done' && diff --git a/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageRightContainer.tsx b/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageRightContainer.tsx index 9de7a4b73..c1b9d0302 100644 --- a/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageRightContainer.tsx +++ b/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageRightContainer.tsx @@ -15,12 +15,11 @@ import { IconTimelineEvent, } from '@/ui/display/icon'; import { TabList } from '@/ui/layout/tab/components/TabList'; -import { activeTabIdScopedState } from '@/ui/layout/tab/states/activeTabIdScopedState'; -import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState'; import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile'; import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled'; -import { ShowPageRecoilScopeContext } from '../../states/ShowPageRecoilScopeContext'; +import { useTabList } from '@/ui/layout/tab/hooks/useTabList'; +import { useRecoilValue } from 'recoil'; const StyledShowPageRightContainer = styled.div` display: flex; @@ -40,6 +39,8 @@ const StyledTabListContainer = styled.div` height: 40px; `; +const TAB_LIST_COMPONENT_ID = 'show-page-right-tab-list'; + type ShowPageRightContainerProps = { targetableObject?: ActivityTargetableObject; timeline?: boolean; @@ -56,10 +57,9 @@ export const ShowPageRightContainer = ({ emails, }: ShowPageRightContainerProps) => { const isMessagingEnabled = useIsFeatureEnabled('IS_MESSAGING_ENABLED'); - const [activeTabId] = useRecoilScopedState( - activeTabIdScopedState, - ShowPageRecoilScopeContext, - ); + + const { activeTabIdState } = useTabList(TAB_LIST_COMPONENT_ID); + const activeTabId = useRecoilValue(activeTabIdState); if (!targetableObject) return <>; @@ -105,7 +105,7 @@ export const ShowPageRightContainer = ({ return ( - + {activeTabId === 'timeline' && ( diff --git a/packages/twenty-front/src/modules/ui/layout/tab/components/TabList.tsx b/packages/twenty-front/src/modules/ui/layout/tab/components/TabList.tsx index 64c675470..6d1baa08b 100644 --- a/packages/twenty-front/src/modules/ui/layout/tab/components/TabList.tsx +++ b/packages/twenty-front/src/modules/ui/layout/tab/components/TabList.tsx @@ -2,11 +2,11 @@ import * as React from 'react'; import styled from '@emotion/styled'; import { IconComponent } from '@/ui/display/icon/types/IconComponent'; -import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState'; - -import { activeTabIdScopedState } from '../states/activeTabIdScopedState'; import { Tab } from './Tab'; +import { useTabList } from '@/ui/layout/tab/hooks/useTabList'; +import { TabListScope } from '@/ui/layout/tab/scopes/TabListScope'; +import { useRecoilValue } from 'recoil'; type SingleTabProps = { title: string; @@ -17,8 +17,8 @@ type SingleTabProps = { }; type TabListProps = { + tabListId: string; tabs: SingleTabProps[]; - context: React.Context; }; const StyledContainer = styled.div` @@ -31,35 +31,36 @@ const StyledContainer = styled.div` user-select: none; `; -export const TabList = ({ tabs, context }: TabListProps) => { +export const TabList = ({ tabs, tabListId }: TabListProps) => { const initialActiveTabId = tabs[0].id; - const [activeTabId, setActiveTabId] = useRecoilScopedState( - activeTabIdScopedState, - context, - ); + const { activeTabIdState, setActiveTabId } = useTabList(tabListId); + + const activeTabId = useRecoilValue(activeTabIdState); React.useEffect(() => { setActiveTabId(initialActiveTabId); }, [initialActiveTabId, setActiveTabId]); return ( - - {tabs - .filter((tab) => !tab.hide) - .map((tab) => ( - { - setActiveTabId(tab.id); - }} - disabled={tab.disabled} - /> - ))} - + + + {tabs + .filter((tab) => !tab.hide) + .map((tab) => ( + { + setActiveTabId(tab.id); + }} + disabled={tab.disabled} + /> + ))} + + ); }; diff --git a/packages/twenty-front/src/modules/ui/layout/tab/components/__stories__/Tablist.stories.tsx b/packages/twenty-front/src/modules/ui/layout/tab/components/__stories__/Tablist.stories.tsx index 33f9358d7..a8eae0e9c 100644 --- a/packages/twenty-front/src/modules/ui/layout/tab/components/__stories__/Tablist.stories.tsx +++ b/packages/twenty-front/src/modules/ui/layout/tab/components/__stories__/Tablist.stories.tsx @@ -40,6 +40,7 @@ const meta: Meta = { title: 'UI/Layout/Tab/TabList', component: TabList, args: { + tabListId: 'tab-list-id', tabs: tabs, }, decorators: [ diff --git a/packages/twenty-front/src/modules/ui/layout/tab/hooks/internal/useTabListStates.ts b/packages/twenty-front/src/modules/ui/layout/tab/hooks/internal/useTabListStates.ts new file mode 100644 index 000000000..95e2586ba --- /dev/null +++ b/packages/twenty-front/src/modules/ui/layout/tab/hooks/internal/useTabListStates.ts @@ -0,0 +1,20 @@ +import { TabListScopeInternalContext } from '@/ui/layout/tab/scopes/scope-internal-context/TabListScopeInternalContext'; +import { activeTabIdStateScopeMap } from '@/ui/layout/tab/states/activeTabIdStateScopeMap'; +import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId'; +import { getState } from '@/ui/utilities/recoil-scope/utils/getState'; + +type useTabListStatesProps = { + tabListScopeId?: string; +}; + +export const useTabListStates = ({ tabListScopeId }: useTabListStatesProps) => { + const scopeId = useAvailableScopeIdOrThrow( + TabListScopeInternalContext, + tabListScopeId, + ); + + return { + scopeId, + activeTabIdState: getState(activeTabIdStateScopeMap, scopeId), + }; +}; diff --git a/packages/twenty-front/src/modules/ui/layout/tab/hooks/useTabList.ts b/packages/twenty-front/src/modules/ui/layout/tab/hooks/useTabList.ts new file mode 100644 index 000000000..aa0809960 --- /dev/null +++ b/packages/twenty-front/src/modules/ui/layout/tab/hooks/useTabList.ts @@ -0,0 +1,15 @@ +import { useTabListStates } from '@/ui/layout/tab/hooks/internal/useTabListStates'; +import { useSetRecoilState } from 'recoil'; + +export const useTabList = (tabListId?: string) => { + const { activeTabIdState } = useTabListStates({ + tabListScopeId: `${tabListId}-scope`, + }); + + const setActiveTabId = useSetRecoilState(activeTabIdState); + + return { + activeTabIdState, + setActiveTabId, + }; +}; diff --git a/packages/twenty-front/src/modules/ui/layout/tab/scopes/TabListScope.tsx b/packages/twenty-front/src/modules/ui/layout/tab/scopes/TabListScope.tsx new file mode 100644 index 000000000..e1f52ef01 --- /dev/null +++ b/packages/twenty-front/src/modules/ui/layout/tab/scopes/TabListScope.tsx @@ -0,0 +1,19 @@ +import { ReactNode } from 'react'; + +import { TabListScopeInternalContext } from './scope-internal-context/TabListScopeInternalContext'; + +type TabListScopeProps = { + children: ReactNode; + tabListScopeId: string; +}; + +export const TabListScope = ({ + children, + tabListScopeId, +}: TabListScopeProps) => { + return ( + + {children} + + ); +}; diff --git a/packages/twenty-front/src/modules/ui/layout/tab/scopes/scope-internal-context/TabListScopeInternalContext.ts b/packages/twenty-front/src/modules/ui/layout/tab/scopes/scope-internal-context/TabListScopeInternalContext.ts new file mode 100644 index 000000000..be207055b --- /dev/null +++ b/packages/twenty-front/src/modules/ui/layout/tab/scopes/scope-internal-context/TabListScopeInternalContext.ts @@ -0,0 +1,7 @@ +import { StateScopeMapKey } from '@/ui/utilities/recoil-scope/scopes-internal/types/StateScopeMapKey'; +import { createScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/utils/createScopeInternalContext'; + +type TabListScopeInternalContextProps = StateScopeMapKey; + +export const TabListScopeInternalContext = + createScopeInternalContext(); diff --git a/packages/twenty-front/src/modules/ui/layout/tab/states/activeTabIdScopedState.ts b/packages/twenty-front/src/modules/ui/layout/tab/states/activeTabIdScopedState.ts deleted file mode 100644 index 232a7a80e..000000000 --- a/packages/twenty-front/src/modules/ui/layout/tab/states/activeTabIdScopedState.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { atomFamily } from 'recoil'; - -export const activeTabIdScopedState = atomFamily({ - key: 'activeTabIdScopedState', - default: null, -}); diff --git a/packages/twenty-front/src/modules/ui/layout/tab/states/activeTabIdStateScopeMap.ts b/packages/twenty-front/src/modules/ui/layout/tab/states/activeTabIdStateScopeMap.ts new file mode 100644 index 000000000..500ccc57a --- /dev/null +++ b/packages/twenty-front/src/modules/ui/layout/tab/states/activeTabIdStateScopeMap.ts @@ -0,0 +1,6 @@ +import { createStateScopeMap } from '@/ui/utilities/recoil-scope/utils/createStateScopeMap'; + +export const activeTabIdStateScopeMap = createStateScopeMap({ + key: 'activeTabIdStateScopeMap', + defaultValue: null, +}); diff --git a/packages/twenty-front/src/pages/tasks/Tasks.tsx b/packages/twenty-front/src/pages/tasks/Tasks.tsx index ebb6a9a29..b5761ebdf 100644 --- a/packages/twenty-front/src/pages/tasks/Tasks.tsx +++ b/packages/twenty-front/src/pages/tasks/Tasks.tsx @@ -58,7 +58,7 @@ export const Tasks = () => { - + } rightComponent={