Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
cd15d10
feat(settings): move settings chrome into a single rounded card
FelixMalfait Jun 2, 2026
abf0a4e
feat(settings): move Security into a tab of the General page
FelixMalfait Jun 2, 2026
f408a59
refactor(settings): align settings IA — General naming + foldered pages
FelixMalfait Jun 2, 2026
c189cc9
fix(settings): point seeded command-menu items at consolidated settin…
FelixMalfait Jun 2, 2026
49a3475
fix(settings): keep header/step-bar title centered; wizard Finish in …
FelixMalfait Jun 2, 2026
6cd8c60
fix(settings): sit the active tab underline on the secondary bar's bo…
FelixMalfait Jun 2, 2026
fa5f79f
feat(settings): rename Updates page to Community with partner + Disco…
FelixMalfait Jun 2, 2026
36bf99c
refactor(settings): drop dead layout props and collapse community lin…
FelixMalfait Jun 2, 2026
78fa82e
fix(settings): make the Emails/Calendar tabs the connected accounts
FelixMalfait Jun 2, 2026
50273f0
chore(settings): trim PR comments to the essential
FelixMalfait Jun 2, 2026
fb31b72
fix(settings): align the page header with the side panel top bar
FelixMalfait Jun 2, 2026
aa6a3db
fix(settings): address PR review — tab resolution, security redirect,…
FelixMalfait Jun 2, 2026
d2a0f17
refactor(settings): make SettingsTabBar presentational, drop the eage…
FelixMalfait Jun 2, 2026
5781298
fix(settings): put the body scrollbar at the card edge, not the conte…
FelixMalfait Jun 2, 2026
99036ef
fix(settings): prefer URL hash in tab resolver, memoize account channels
FelixMalfait Jun 2, 2026
b3c9ae5
fix(settings): drop the self-referencing Workspace breadcrumb link on…
FelixMalfait Jun 2, 2026
6b5a516
fix(settings): use the tab resolver on the remaining tabbed pages
FelixMalfait Jun 2, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 16 additions & 43 deletions packages/twenty-front/src/modules/app/components/SettingsRoutes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,6 @@ const SettingsRestPlayground = lazy(() =>
),
);

const SettingsAccountsCalendars = lazy(() =>
import('~/pages/settings/accounts/SettingsAccountsCalendars').then(
(module) => ({
default: module.SettingsAccountsCalendars,
}),
),
);

const SettingsAccountsEmails = lazy(() =>
import('~/pages/settings/accounts/SettingsAccountsEmails').then((module) => ({
default: module.SettingsAccountsEmails,
})),
);

const SettingsAccountsConfiguration = lazy(() =>
import('~/pages/settings/accounts/SettingsAccountsConfiguration').then(
(module) => ({
Expand Down Expand Up @@ -122,20 +108,20 @@ const SettingsLogicFunctionDetail = lazy(() =>
),
);

const SettingsWorkspace = lazy(() =>
import('~/pages/settings/SettingsWorkspace').then((module) => ({
default: module.SettingsWorkspace,
const SettingsGeneral = lazy(() =>
import('~/pages/settings/general/SettingsGeneral').then((module) => ({
default: module.SettingsGeneral,
})),
);

const SettingsWorkspaceEmail = lazy(() =>
import('~/pages/settings/SettingsWorkspaceEmail').then((module) => ({
import('~/pages/settings/email/SettingsWorkspaceEmail').then((module) => ({
default: module.SettingsWorkspaceEmail,
})),
);

const SettingsWorkspaceEmailGroupChannelDetail = lazy(() =>
import('~/pages/settings/workspace/SettingsWorkspaceEmailGroupChannelDetail').then(
import('~/pages/settings/email/SettingsWorkspaceEmailGroupChannelDetail').then(
(module) => ({
default: module.SettingsWorkspaceEmailGroupChannelDetail,
}),
Expand All @@ -157,9 +143,11 @@ const SettingsCustomDomainPage = lazy(() =>
);

const SettingsApiWebhooks = lazy(() =>
import('~/pages/settings/workspace/SettingsApiWebhooks').then((module) => ({
default: module.SettingsApiWebhooks,
})),
import('~/pages/settings/api-webhooks/SettingsApiWebhooks').then(
(module) => ({
default: module.SettingsApiWebhooks,
}),
),
);

const SettingsAI = lazy(() =>
Expand Down Expand Up @@ -319,13 +307,13 @@ const SettingsWorkspaceMember = lazy(() =>
);

const SettingsProfile = lazy(() =>
import('~/pages/settings/SettingsProfile').then((module) => ({
import('~/pages/settings/profile/SettingsProfile').then((module) => ({
default: module.SettingsProfile,
})),
);

const SettingsTwoFactorAuthenticationMethod = lazy(() =>
import('~/pages/settings/SettingsTwoFactorAuthenticationMethod').then(
import('~/pages/settings/profile/SettingsTwoFactorAuthenticationMethod').then(
(module) => ({
default: module.SettingsTwoFactorAuthenticationMethod,
}),
Expand All @@ -347,19 +335,19 @@ const SettingsAccounts = lazy(() =>
);

const SettingsBilling = lazy(() =>
import('~/pages/settings/SettingsBilling').then((module) => ({
import('~/pages/settings/billing/SettingsBilling').then((module) => ({
default: module.SettingsBilling,
})),
);

const SettingsUsage = lazy(() =>
import('~/pages/settings/SettingsUsage').then((module) => ({
import('~/pages/settings/billing/SettingsUsage').then((module) => ({
default: module.SettingsUsage,
})),
);

const SettingsUsageUserDetail = lazy(() =>
import('~/pages/settings/SettingsUsageUserDetail').then((module) => ({
import('~/pages/settings/billing/SettingsUsageUserDetail').then((module) => ({
default: module.SettingsUsageUserDetail,
})),
);
Expand Down Expand Up @@ -417,12 +405,6 @@ const SettingsObjectFieldEdit = lazy(() =>
),
);

const SettingsSecurity = lazy(() =>
import('~/pages/settings/security/SettingsSecurity').then((module) => ({
default: module.SettingsSecurity,
})),
);

const SettingsSecuritySSOIdentifyProvider = lazy(() =>
import('~/pages/settings/security/SettingsSecuritySSOIdentifyProvider').then(
(module) => ({
Expand Down Expand Up @@ -631,14 +613,6 @@ export const SettingsRoutes = ({ isAdminPageEnabled }: SettingsRoutesProps) => (
path={SettingsPath.AccountsConfiguration}
element={<SettingsAccountsConfiguration />}
/>
<Route
path={SettingsPath.AccountsCalendars}
element={<SettingsAccountsCalendars />}
/>
<Route
path={SettingsPath.AccountsEmails}
element={<SettingsAccountsEmails />}
/>
<Route
path={SettingsPath.NewImapSmtpCaldavConnection}
element={<SettingsNewImapSmtpCaldavConnection />}
Expand All @@ -655,7 +629,7 @@ export const SettingsRoutes = ({ isAdminPageEnabled }: SettingsRoutesProps) => (
/>
}
>
<Route path={SettingsPath.Workspace} element={<SettingsWorkspace />} />
<Route path={SettingsPath.General} element={<SettingsGeneral />} />
<Route
path={SettingsPath.WorkspaceEmail}
element={<SettingsWorkspaceEmail />}
Expand Down Expand Up @@ -923,7 +897,6 @@ export const SettingsRoutes = ({ isAdminPageEnabled }: SettingsRoutesProps) => (
/>
}
>
<Route path={SettingsPath.Security} element={<SettingsSecurity />} />
<Route
path={SettingsPath.NewSSOIdentityProvider}
element={<SettingsSecuritySSOIdentifyProvider />}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { useParams } from 'react-router-dom';

import { SaveAndCancelButtons } from '@/settings/components/SaveAndCancelButtons/SaveAndCancelButtons';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer';
import { SettingsPageLayout } from '@/settings/components/layout/SettingsPageLayout';
import { SettingsPath } from 'twenty-shared/types';

import { Loader } from 'twenty-ui/feedback';
Expand Down Expand Up @@ -64,7 +64,7 @@ export const SettingsAccountsEditImapSmtpCaldavConnection = () => {
const renderForm = () => (
// oxlint-disable-next-line react/jsx-props-no-spreading
<FormProvider {...formMethods}>
<SubMenuTopBarContainer
<SettingsPageLayout
title={t`Edit Account`}
links={[
{
Expand Down Expand Up @@ -94,7 +94,7 @@ export const SettingsAccountsEditImapSmtpCaldavConnection = () => {
existingProtocols={existingProtocols}
/>
</SettingsPageContainer>
</SubMenuTopBarContainer>
</SettingsPageLayout>
</FormProvider>
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { SaveAndCancelButtons } from '@/settings/components/SaveAndCancelButtons
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
import { SettingsTextInput } from '@/ui/input/components/SettingsTextInput';
import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer';
import { SettingsPageLayout } from '@/settings/components/layout/SettingsPageLayout';
import { useNavigateSettings } from '~/hooks/useNavigateSettings';

export const SettingsAccountsNewEmailGroupChannel = () => {
Expand Down Expand Up @@ -45,12 +45,12 @@ export const SettingsAccountsNewEmailGroupChannel = () => {
}, [createEmailGroupChannel, handle, navigate, enqueueErrorSnackBar, t]);

return (
<SubMenuTopBarContainer
<SettingsPageLayout
title={t`New Email Handle`}
links={[
{
children: t`Workspace`,
href: getSettingsPath(SettingsPath.Workspace),
href: getSettingsPath(SettingsPath.General),
},
{
children: t`Email`,
Expand Down Expand Up @@ -84,6 +84,6 @@ export const SettingsAccountsNewEmailGroupChannel = () => {
/>
</Section>
</SettingsPageContainer>
</SubMenuTopBarContainer>
</SettingsPageLayout>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { FormProvider } from 'react-hook-form';

import { SaveAndCancelButtons } from '@/settings/components/SaveAndCancelButtons/SaveAndCancelButtons';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer';
import { SettingsPageLayout } from '@/settings/components/layout/SettingsPageLayout';
import { SettingsPath } from 'twenty-shared/types';

import { getSettingsPath } from 'twenty-shared/utils';
Expand All @@ -30,7 +30,7 @@ export const SettingsAccountsNewImapSmtpCaldavConnection = () => {
return (
// oxlint-disable-next-line react/jsx-props-no-spreading
<FormProvider {...formMethods}>
<SubMenuTopBarContainer
<SettingsPageLayout
title={t`New Account`}
links={[
{
Expand All @@ -56,7 +56,7 @@ export const SettingsAccountsNewImapSmtpCaldavConnection = () => {
<SettingsPageContainer>
<SettingsAccountsConnectionForm control={control} isEditing={false} />
</SettingsPageContainer>
</SubMenuTopBarContainer>
</SettingsPageLayout>
</FormProvider>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import { useNavigationDrawerExpanded } from '@/navigation/hooks/useNavigationDrawerExpanded';
import {
Breadcrumb,
type BreadcrumbProps,
} from '@/ui/navigation/bread-crumb/components/Breadcrumb';
import { NavigationDrawerCollapseButton } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerCollapseButton';
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
import { styled } from '@linaria/react';
import { type ReactNode } from 'react';
import { isDefined } from 'twenty-shared/utils';
import { themeCssVariables } from 'twenty-ui/theme-constants';

type SettingsPageHeaderProps = {
links: BreadcrumbProps['links'];
title?: ReactNode;
tag?: ReactNode;
actionButton?: ReactNode;
};

// Header row inside the settings card. The side cells fill equal minmax(0, 1fr)
// tracks and clip overflow, so the centered title stays on the same vertical axis
// as the tabs and body even when the breadcrumb is long — the breadcrumb truncates
// instead of pushing or overlapping the title. Plain `1fr` (= minmax(auto, 1fr))
// would let a long breadcrumb grow its track and shove the title off-center.
const StyledHeader = styled.div`
align-items: center;
box-sizing: border-box;
display: grid;
gap: ${themeCssVariables.spacing[2]};
grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
padding: ${themeCssVariables.spacing[3]};
width: 100%;
`;

const StyledLeft = styled.div`
align-items: center;
display: flex;
gap: ${themeCssVariables.spacing[1]};
min-width: 0;
overflow: hidden;
`;

const StyledTitle = styled.div`
align-items: center;
color: ${themeCssVariables.font.color.primary};
display: flex;
font-size: ${themeCssVariables.font.size.md};
font-weight: ${themeCssVariables.font.weight.semiBold};
gap: ${themeCssVariables.spacing[2]};
min-width: 0;
text-align: center;
`;

const StyledRight = styled.div`
align-items: center;
display: flex;
gap: ${themeCssVariables.spacing[2]};
justify-content: flex-end;
min-width: 0;
`;

export const SettingsPageHeader = ({
links,
title,
tag,
actionButton,
}: SettingsPageHeaderProps) => {
const isMobile = useIsMobile();
const isNavigationDrawerExpanded = useNavigationDrawerExpanded();

return (
<StyledHeader>
<StyledLeft>
{!isNavigationDrawerExpanded && (
<NavigationDrawerCollapseButton direction="right" />
)}
Comment thread
FelixMalfait marked this conversation as resolved.
<Breadcrumb links={links} />
</StyledLeft>
<StyledTitle>
{!isMobile && isDefined(title) && title}
{!isMobile && tag}
</StyledTitle>
<StyledRight>{actionButton}</StyledRight>
</StyledHeader>
);
};
Loading
Loading