Fix settings navigation active state for sub-pages (#12318)

Changes the default behavior for settings navigation items to stay
active when navigating to sub-pages.

**Problem:**
- Navigation items like "Data Model" and "Webhooks" were not staying
highlighted when navigating to detail pages
- This was because `matchSubPages` defaulted to requiring exact path
matches

**Solution:**
- Updated logic to make sub-page matching the default behavior (`end:
item.matchSubPages === false`)
- Only "Accounts" explicitly sets `matchSubPages: false` for its custom
sub-item navigation
- Removed redundant `matchSubPages: true` declarations throughout the
codebase

**URL Changes:** -- checked with @Bonapara 
- `/settings/workspace` → `/settings/general`
- `/settings/workspace-members` → `/settings/members`
- `/settings/api-keys` → `/settings/apis`
- `/settings/developers/webhooks` → `/settings/webhooks`

before: 


https://github.com/user-attachments/assets/56b94a49-9c31-4bb5-9875-ec24f4bc4d1e

after:


https://github.com/user-attachments/assets/38742599-c045-44d1-8020-56f3eacca779

---------

Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
This commit is contained in:
nitin
2025-05-30 11:49:20 +05:30
committed by GitHub
parent dc0401edb5
commit da00dee8a1
22 changed files with 57 additions and 51 deletions

View File

@ -431,15 +431,15 @@ export const SettingsRoutes = ({
element={<SettingsRestPlayground />}
/>
<Route
path={SettingsPath.DevelopersNewApiKey}
path={SettingsPath.NewApiKey}
element={<SettingsDevelopersApiKeysNew />}
/>
<Route
path={SettingsPath.DevelopersApiKeyDetail}
path={SettingsPath.ApiKeyDetail}
element={<SettingsDevelopersApiKeyDetail />}
/>
<Route
path={SettingsPath.DevelopersNewWebhookDetail}
path={SettingsPath.WebhookDetail}
element={<SettingsDevelopersWebhooksDetail />}
/>
<Route

View File

@ -4,8 +4,8 @@ import { AdvancedSettingsWrapper } from '@/settings/components/AdvancedSettingsW
import { SettingsNavigationItem } from '@/settings/hooks/useSettingsNavigationItems';
import { NavigationDrawerItem } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerItem';
import { NavigationDrawerSubItemState } from '@/ui/navigation/navigation-drawer/types/NavigationDrawerSubItemState';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
import { isDefined } from 'twenty-shared/utils';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
type SettingsNavigationDrawerItemProps = {
item: SettingsNavigationItem;
@ -20,7 +20,7 @@ export const SettingsNavigationDrawerItem = ({
const pathName = useResolvedPath(href).pathname;
const isActive = !!useMatch({
path: pathName,
end: !item.matchSubPages,
end: item.matchSubPages === false,
});
if (isDefined(item.isHidden) && item.isHidden) {

View File

@ -11,8 +11,8 @@ import { TableHeader } from '@/ui/layout/table/components/TableHeader';
import { TableRow } from '@/ui/layout/table/components/TableRow';
import styled from '@emotion/styled';
import { Trans } from '@lingui/react/macro';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
import { MOBILE_VIEWPORT } from 'twenty-ui/theme';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
const StyledTableBody = styled(TableBody)`
border-bottom: 1px solid ${({ theme }) => theme.border.color.light};
@ -55,7 +55,7 @@ export const SettingsApiKeysTable = () => {
<SettingsApiKeysFieldItemTableRow
key={fieldItem.id}
fieldItem={fieldItem as ApiFieldItem}
to={getSettingsPath(SettingsPath.DevelopersApiKeyDetail, {
to={getSettingsPath(SettingsPath.ApiKeyDetail, {
apiKeyId: fieldItem.id,
})}
/>

View File

@ -4,10 +4,12 @@ import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSi
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
import { SettingsDevelopersWebhookTableRow } from '@/settings/developers/components/SettingsDevelopersWebhookTableRow';
import { Webhook } from '@/settings/developers/types/webhook/Webhook';
import { SettingsPath } from '@/types/SettingsPath';
import { Table } from '@/ui/layout/table/components/Table';
import { TableBody } from '@/ui/layout/table/components/TableBody';
import { TableHeader } from '@/ui/layout/table/components/TableHeader';
import { TableRow } from '@/ui/layout/table/components/TableRow';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
const StyledTableBody = styled(TableBody)`
border-bottom: 1px solid ${({ theme }) => theme.border.color.light};
@ -36,7 +38,9 @@ export const SettingsWebhooksTable = () => {
<SettingsDevelopersWebhookTableRow
key={webhookFieldItem.id}
fieldItem={webhookFieldItem}
to={`/settings/developers/webhooks/${webhookFieldItem.id}`}
to={getSettingsPath(SettingsPath.WebhookDetail, {
webhookId: webhookFieldItem.id,
})}
/>
))}
</StyledTableBody>

View File

@ -8,7 +8,6 @@ import { useSettingsPermissionMap } from '@/settings/roles/hooks/useSettingsPerm
import { NavigationDrawerItemIndentationLevel } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerItem';
import { t } from '@lingui/core/macro';
import { useRecoilValue } from 'recoil';
import { SettingPermissionType } from '~/generated/graphql';
import {
IconApi,
IconApps,
@ -31,6 +30,7 @@ import {
IconUsers,
IconWebhook,
} from 'twenty-ui/display';
import { SettingPermissionType } from '~/generated/graphql';
export type SettingsNavigationSection = {
label: string;
@ -203,6 +203,7 @@ const useSettingsNavigationItems = (): SettingsNavigationSection[] => {
label: t`Logout`,
onClick: signOut,
Icon: IconDoorEnter,
matchSubPages: false,
},
],
},

View File

@ -16,14 +16,14 @@ export enum SettingsPath {
ServerlessFunctions = 'functions',
NewServerlessFunction = 'functions/new',
ServerlessFunctionDetail = 'functions/:serverlessFunctionId',
WorkspaceMembersPage = 'workspace-members',
Workspace = 'workspace',
Domain = 'domain',
APIs = 'api-keys',
WorkspaceMembersPage = 'members',
Workspace = 'general',
Domain = 'general/domain',
APIs = 'apis',
RestPlayground = 'playground/rest/:schema',
GraphQLPlayground = 'playground/graphql/:schema',
DevelopersNewApiKey = 'api-keys/new',
DevelopersApiKeyDetail = 'api-keys/:apiKeyId',
NewApiKey = 'apis/new',
ApiKeyDetail = 'apis/:apiKeyId',
Integrations = 'integrations',
IntegrationDatabase = 'integrations/:databaseKey',
IntegrationDatabaseConnection = 'integrations/:databaseKey/:connectionId',
@ -33,8 +33,7 @@ export enum SettingsPath {
NewSSOIdentityProvider = 'security/sso/new',
NewApprovedAccessDomain = 'security/approved-access-domain/new',
Webhooks = 'webhooks',
DevelopersNewWebhook = 'developers/webhooks/new',
DevelopersNewWebhookDetail = 'developers/webhooks/:webhookId',
WebhookDetail = 'webhooks/:webhookId',
Releases = 'releases',
AdminPanel = 'admin-panel',
AdminPanelHealthStatus = 'admin-panel#health-status',