Skip to content

Commit 23001ac

Browse files
Settings Advanced Mode (#7130)
### Description - We implemented the Advanced Mode state and used this on a section of the settings sidebar - in DefaultLayout.tsx, was updated because of the 64 + 16(container size of IconTool + the margins) ### <https://jam.dev/c/29bcec70-0b7f-4afa-98e6-9755657cf09d> ### Refs #6147 Fixes #6147 --------- Co-authored-by: gitstart-twenty <[email protected]> Co-authored-by: gitstart-twenty <[email protected]>
1 parent 57eaa01 commit 23001ac

File tree

11 files changed

+221
-30
lines changed

11 files changed

+221
-30
lines changed

packages/twenty-front/src/modules/navigation/components/AppNavigationDrawer.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import { useRecoilValue, useSetRecoilState } from 'recoil';
44
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
55
import { SettingsNavigationDrawerItems } from '@/settings/components/SettingsNavigationDrawerItems';
66
import { SupportDropdown } from '@/support/components/SupportDropdown';
7-
import { GithubVersionLink } from '@/ui/navigation/link/components/GithubVersionLink';
87
import {
98
NavigationDrawer,
109
NavigationDrawerProps,
@@ -16,6 +15,7 @@ import { getImageAbsoluteURI } from '~/utils/image/getImageAbsoluteURI';
1615
import { useIsSettingsPage } from '../hooks/useIsSettingsPage';
1716
import { currentMobileNavigationDrawerState } from '../states/currentMobileNavigationDrawerState';
1817

18+
import { AdvancedSettingsToggle } from '@/ui/navigation/link/components/AdvancedSettingsToggle';
1919
import { MainNavigationDrawerItems } from './MainNavigationDrawerItems';
2020

2121
export type AppNavigationDrawerProps = {
@@ -44,7 +44,7 @@ export const AppNavigationDrawer = ({
4444
isSubMenu: true,
4545
title: 'Exit Settings',
4646
children: <SettingsNavigationDrawerItems />,
47-
footer: <GithubVersionLink />,
47+
footer: <AdvancedSettingsToggle />,
4848
}
4949
: {
5050
logo:

packages/twenty-front/src/modules/settings/components/SettingsNavigationDrawerItems.tsx

+73-18
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,16 @@ import {
1313
IconMail,
1414
IconRocket,
1515
IconSettings,
16+
IconTool,
1617
IconUserCircle,
1718
IconUsers,
19+
MAIN_COLORS,
1820
} from 'twenty-ui';
1921

2022
import { useAuth } from '@/auth/hooks/useAuth';
2123
import { billingState } from '@/client-config/states/billingState';
2224
import { SettingsNavigationDrawerItem } from '@/settings/components/SettingsNavigationDrawerItem';
25+
import { useExpandedHeightAnimation } from '@/settings/hooks/useExpandedHeightAnimation';
2326
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
2427
import { SettingsPath } from '@/types/SettingsPath';
2528
import {
@@ -29,10 +32,38 @@ import {
2932
import { NavigationDrawerItemGroup } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerItemGroup';
3033
import { NavigationDrawerSection } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerSection';
3134
import { NavigationDrawerSectionTitle } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerSectionTitle';
35+
import { isAdvancedModeEnabledState } from '@/ui/navigation/navigation-drawer/states/isAdvancedModeEnabledState';
3236
import { getNavigationSubItemState } from '@/ui/navigation/navigation-drawer/utils/getNavigationSubItemState';
3337
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
38+
import styled from '@emotion/styled';
39+
import { AnimatePresence, motion } from 'framer-motion';
3440
import { matchPath, resolvePath, useLocation } from 'react-router-dom';
3541

42+
const StyledNavigationDrawerSection = styled(NavigationDrawerSection)<{
43+
withLeftMargin?: boolean;
44+
}>`
45+
margin-left: ${({ withLeftMargin, theme }) =>
46+
withLeftMargin && theme.spacing(5)};
47+
margin-top: ${({ theme }) => theme.spacing(3)};
48+
`;
49+
50+
const StyledIconContainer = styled.div`
51+
border-right: 1px solid ${MAIN_COLORS.yellow};
52+
display: flex;
53+
margin-top: ${({ theme }) => theme.spacing(5)};
54+
width: 16px;
55+
`;
56+
57+
const StyledDeveloperSection = styled.div`
58+
display: flex;
59+
width: 100%;
60+
gap: ${({ theme }) => theme.spacing(1)};
61+
`;
62+
63+
const StyledIconTool = styled(IconTool)`
64+
margin-right: ${({ theme }) => theme.spacing(0.5)};
65+
`;
66+
3667
type SettingsNavigationItem = {
3768
label: string;
3869
path: SettingsPath;
@@ -42,6 +73,10 @@ type SettingsNavigationItem = {
4273
};
4374

4475
export const SettingsNavigationDrawerItems = () => {
76+
const isAdvancedModeEnabled = useRecoilValue(isAdvancedModeEnabledState);
77+
const { contentRef, motionAnimationVariants } = useExpandedHeightAnimation(
78+
isAdvancedModeEnabled,
79+
);
4580
const { signOut } = useAuth();
4681

4782
const billing = useRecoilValue(billingState);
@@ -88,7 +123,7 @@ export const SettingsNavigationDrawerItems = () => {
88123

89124
return (
90125
<>
91-
<NavigationDrawerSection>
126+
<StyledNavigationDrawerSection withLeftMargin>
92127
<NavigationDrawerSectionTitle label="User" />
93128
<SettingsNavigationDrawerItem
94129
label="Profile"
@@ -121,8 +156,8 @@ export const SettingsNavigationDrawerItems = () => {
121156
/>
122157
))}
123158
</NavigationDrawerItemGroup>
124-
</NavigationDrawerSection>
125-
<NavigationDrawerSection>
159+
</StyledNavigationDrawerSection>
160+
<StyledNavigationDrawerSection withLeftMargin>
126161
<NavigationDrawerSectionTitle label="Workspace" />
127162
<SettingsNavigationDrawerItem
128163
label="General"
@@ -147,18 +182,6 @@ export const SettingsNavigationDrawerItems = () => {
147182
Icon={IconHierarchy2}
148183
matchSubPages
149184
/>
150-
<SettingsNavigationDrawerItem
151-
label="Developers"
152-
path={SettingsPath.Developers}
153-
Icon={IconCode}
154-
/>
155-
{isFunctionSettingsEnabled && (
156-
<SettingsNavigationDrawerItem
157-
label="Functions"
158-
path={SettingsPath.ServerlessFunctions}
159-
Icon={IconFunction}
160-
/>
161-
)}
162185
<SettingsNavigationDrawerItem
163186
label="Integrations"
164187
path={SettingsPath.Integrations}
@@ -171,8 +194,40 @@ export const SettingsNavigationDrawerItems = () => {
171194
Icon={IconCode}
172195
/>
173196
)}
174-
</NavigationDrawerSection>
175-
<NavigationDrawerSection>
197+
</StyledNavigationDrawerSection>
198+
<AnimatePresence>
199+
{isAdvancedModeEnabled && (
200+
<motion.div
201+
ref={contentRef}
202+
initial="initial"
203+
animate="animate"
204+
exit="exit"
205+
variants={motionAnimationVariants}
206+
>
207+
<StyledDeveloperSection>
208+
<StyledIconContainer>
209+
<StyledIconTool size={12} color={MAIN_COLORS.yellow} />
210+
</StyledIconContainer>
211+
<StyledNavigationDrawerSection>
212+
<NavigationDrawerSectionTitle label="Developers" />
213+
<SettingsNavigationDrawerItem
214+
label="API & Webhooks"
215+
path={SettingsPath.Developers}
216+
Icon={IconCode}
217+
/>
218+
{isFunctionSettingsEnabled && (
219+
<SettingsNavigationDrawerItem
220+
label="Functions"
221+
path={SettingsPath.ServerlessFunctions}
222+
Icon={IconFunction}
223+
/>
224+
)}
225+
</StyledNavigationDrawerSection>
226+
</StyledDeveloperSection>
227+
</motion.div>
228+
)}
229+
</AnimatePresence>
230+
<StyledNavigationDrawerSection withLeftMargin>
176231
<NavigationDrawerSectionTitle label="Other" />
177232
<SettingsNavigationDrawerItem
178233
label="Releases"
@@ -184,7 +239,7 @@ export const SettingsNavigationDrawerItems = () => {
184239
onClick={signOut}
185240
Icon={IconDoorEnter}
186241
/>
187-
</NavigationDrawerSection>
242+
</StyledNavigationDrawerSection>
188243
</>
189244
);
190245
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import { useEffect, useRef, useState } from 'react';
2+
import { isDefined } from 'twenty-ui';
3+
4+
const transitionValues = {
5+
transition: {
6+
opactity: { duration: 0.2 },
7+
height: { duration: 0.4 },
8+
},
9+
transitionEnd: {
10+
overflow: 'visible',
11+
},
12+
};
13+
14+
const commonStyles = {
15+
opacity: 0,
16+
height: 0,
17+
overflow: 'hidden',
18+
...transitionValues,
19+
};
20+
21+
const advancedSectionAnimationConfig = (
22+
isExpanded: boolean,
23+
measuredHeight: number,
24+
) => ({
25+
initial: {
26+
...commonStyles,
27+
},
28+
animate: {
29+
opacity: 1,
30+
height: isExpanded ? measuredHeight : 0,
31+
...transitionValues,
32+
overflow: 'hidden',
33+
},
34+
exit: {
35+
...commonStyles,
36+
},
37+
});
38+
39+
export const useExpandedHeightAnimation = (isExpanded: boolean) => {
40+
const contentRef = useRef<HTMLDivElement>(null);
41+
const [measuredHeight, setMeasuredHeight] = useState(0);
42+
43+
useEffect(() => {
44+
if (isDefined(contentRef.current)) {
45+
setMeasuredHeight(contentRef.current.scrollHeight);
46+
}
47+
}, [isExpanded]);
48+
49+
return {
50+
contentRef,
51+
measuredHeight,
52+
motionAnimationVariants: advancedSectionAnimationConfig(
53+
isExpanded,
54+
measuredHeight,
55+
),
56+
};
57+
};

packages/twenty-front/src/modules/ui/layout/page/DefaultLayout.tsx

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
1-
import { css, Global, useTheme } from '@emotion/react';
2-
import styled from '@emotion/styled';
3-
import { AnimatePresence, LayoutGroup, motion } from 'framer-motion';
4-
import { Outlet } from 'react-router-dom';
1+
import { AuthModal } from '@/auth/components/AuthModal';
52
import { CommandMenu } from '@/command-menu/components/CommandMenu';
63
import { AppErrorBoundary } from '@/error-handler/components/AppErrorBoundary';
74
import { KeyboardShortcutMenu } from '@/keyboard-shortcut-menu/components/KeyboardShortcutMenu';
@@ -14,7 +11,10 @@ import { useShowAuthModal } from '@/ui/layout/hooks/useShowAuthModal';
1411
import { DESKTOP_NAV_DRAWER_WIDTHS } from '@/ui/navigation/navigation-drawer/constants/DesktopNavDrawerWidths';
1512
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
1613
import { useScreenSize } from '@/ui/utilities/screen-size/hooks/useScreenSize';
17-
import { AuthModal } from '@/auth/components/AuthModal';
14+
import { css, Global, useTheme } from '@emotion/react';
15+
import styled from '@emotion/styled';
16+
import { AnimatePresence, LayoutGroup, motion } from 'framer-motion';
17+
import { Outlet } from 'react-router-dom';
1818

1919
const StyledLayout = styled.div`
2020
background: ${({ theme }) => theme.background.noisy};
@@ -85,7 +85,7 @@ export const DefaultLayout = () => {
8585
? (windowsWidth -
8686
(OBJECT_SETTINGS_WIDTH +
8787
DESKTOP_NAV_DRAWER_WIDTHS.menu +
88-
64)) /
88+
88)) /
8989
2
9090
: 0,
9191
}}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import { Toggle } from '@/ui/input/components/Toggle';
2+
import { isAdvancedModeEnabledState } from '@/ui/navigation/navigation-drawer/states/isAdvancedModeEnabledState';
3+
import styled from '@emotion/styled';
4+
import { useRecoilState } from 'recoil';
5+
import { IconTool, MAIN_COLORS } from 'twenty-ui';
6+
7+
const StyledContainer = styled.div`
8+
align-items: center;
9+
display: flex;
10+
width: 100%;
11+
gap: ${({ theme }) => theme.spacing(2)};
12+
`;
13+
14+
const StyledText = styled.span`
15+
color: ${({ theme }) => theme.font.color.secondary};
16+
font-size: ${({ theme }) => theme.font.size.sm};
17+
font-weight: ${({ theme }) => theme.font.weight.medium};
18+
padding: ${({ theme }) => theme.spacing(1)};
19+
`;
20+
21+
const StyledIconContainer = styled.div`
22+
border-right: 1px solid ${MAIN_COLORS.yellow};
23+
display: flex;
24+
height: 16px;
25+
`;
26+
27+
const StyledToggleContainer = styled.div`
28+
display: flex;
29+
align-items: center;
30+
justify-content: space-between;
31+
width: 100%;
32+
`;
33+
34+
const StyledIconTool = styled(IconTool)`
35+
margin-right: ${({ theme }) => theme.spacing(0.5)};
36+
`;
37+
38+
export const AdvancedSettingsToggle = () => {
39+
const [isAdvancedModeEnabled, setIsAdvancedModeEnabled] = useRecoilState(
40+
isAdvancedModeEnabledState,
41+
);
42+
43+
const onChange = (newValue: boolean) => {
44+
setIsAdvancedModeEnabled(newValue);
45+
};
46+
47+
return (
48+
<StyledContainer>
49+
<StyledIconContainer>
50+
<StyledIconTool size={12} color={MAIN_COLORS.yellow} />
51+
</StyledIconContainer>
52+
<StyledToggleContainer>
53+
<StyledText>Advanced</StyledText>
54+
<Toggle
55+
onChange={onChange}
56+
color={MAIN_COLORS.yellow}
57+
value={isAdvancedModeEnabled}
58+
/>
59+
</StyledToggleContainer>
60+
</StyledContainer>
61+
);
62+
};

packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawer.tsx

+6-4
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ const StyledContainer = styled.div<{ isSubMenu?: boolean }>`
4040
${({ isSubMenu, theme }) =>
4141
isSubMenu
4242
? css`
43+
padding-left: ${theme.spacing(0)};
4344
padding-right: ${theme.spacing(8)};
4445
`
4546
: ''}
@@ -48,13 +49,12 @@ const StyledContainer = styled.div<{ isSubMenu?: boolean }>`
4849
width: 100%;
4950
}
5051
`;
51-
52-
const StyledItemsContainer = styled.div`
52+
const StyledItemsContainer = styled.div<{ isSubMenu?: boolean }>`
5353
display: flex;
5454
flex-direction: column;
55-
gap: ${({ theme }) => theme.spacing(3)};
5655
margin-bottom: auto;
5756
overflow-y: auto;
57+
${({ isSubMenu, theme }) => !isSubMenu && `gap: ${theme.spacing(3)}`}
5858
`;
5959

6060
export const NavigationDrawer = ({
@@ -111,7 +111,9 @@ export const NavigationDrawer = ({
111111
showCollapseButton={isHovered}
112112
/>
113113
)}
114-
<StyledItemsContainer>{children}</StyledItemsContainer>
114+
<StyledItemsContainer isSubMenu={isSubMenu}>
115+
{children}
116+
</StyledItemsContainer>
115117
{footer}
116118
</StyledContainer>
117119
</StyledAnimatedContainer>

packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerBackButton.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ const StyledContainer = styled.div`
3535
flex-direction: row;
3636
height: ${({ theme }) => theme.spacing(8)};
3737
justify-content: space-between;
38+
margin-left: ${({ theme }) => theme.spacing(5)};
3839
`;
3940

4041
export const NavigationDrawerBackButton = ({

packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerSection.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const StyledSection = styled.div`
44
display: flex;
55
flex-direction: column;
66
gap: ${({ theme }) => theme.betweenSiblingsGap};
7+
width: 100%;
78
`;
89

910
export { StyledSection as NavigationDrawerSection };
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { atom } from 'recoil';
2+
import { localStorageEffect } from '~/utils/recoil-effects';
3+
4+
export const isAdvancedModeEnabledState = atom<boolean>({
5+
key: 'isAdvancedModeEnabledAtom',
6+
default: false,
7+
effects: [localStorageEffect()],
8+
});

0 commit comments

Comments
 (0)