diff --git a/packages/twenty-front/src/modules/error-handler/components/AppFullScreenErrorFallback.tsx b/packages/twenty-front/src/modules/error-handler/components/AppFullScreenErrorFallback.tsx
index d0f075c390..5224aa0a7d 100644
--- a/packages/twenty-front/src/modules/error-handler/components/AppFullScreenErrorFallback.tsx
+++ b/packages/twenty-front/src/modules/error-handler/components/AppFullScreenErrorFallback.tsx
@@ -1,6 +1,5 @@
import { AppErrorDisplay } from '@/error-handler/components/internal/AppErrorDisplay';
import { type AppErrorDisplayProps } from '@/error-handler/types/AppErrorDisplayProps';
-import { PageBody } from '@/ui/layout/page/components/PageBody';
import { styled } from '@linaria/react';
import { t } from '@lingui/core/macro';
import { themeCssVariables } from 'twenty-ui-deprecated/theme-constants';
@@ -8,12 +7,10 @@ import { themeCssVariables } from 'twenty-ui-deprecated/theme-constants';
type AppFullScreenErrorFallbackProps = AppErrorDisplayProps;
const StyledContainer = styled.div`
- background: ${themeCssVariables.background.noisy};
+ background: ${themeCssVariables.background.primary};
box-sizing: border-box;
display: flex;
- height: 100vh;
- padding-left: ${themeCssVariables.spacing[3]};
- padding-top: ${themeCssVariables.spacing[3]};
+ height: 100dvh;
width: 100vw;
`;
@@ -24,13 +21,11 @@ export const AppFullScreenErrorFallback = ({
}: AppFullScreenErrorFallbackProps) => {
return (
-
-
-
+
);
};
diff --git a/packages/twenty-front/src/modules/navigation-menu-item/display/components/NavigationMenuItemSkeletonLoader.tsx b/packages/twenty-front/src/modules/navigation-menu-item/display/components/NavigationMenuItemSkeletonLoader.tsx
index e1a354f55b..93cb7f7135 100644
--- a/packages/twenty-front/src/modules/navigation-menu-item/display/components/NavigationMenuItemSkeletonLoader.tsx
+++ b/packages/twenty-front/src/modules/navigation-menu-item/display/components/NavigationMenuItemSkeletonLoader.tsx
@@ -32,7 +32,7 @@ export const NavigationMenuItemSkeletonLoader = () => {
const { theme } = useContext(ThemeContext);
return (
diff --git a/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsMessageFolderIcon.tsx b/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsMessageFolderIcon.tsx
index 375552346c..a055b60baf 100644
--- a/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsMessageFolderIcon.tsx
+++ b/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsMessageFolderIcon.tsx
@@ -9,43 +9,58 @@ type SettingsAccountsMessageFolderIconProps = {
};
const StyledCardMedia = styled.div`
- align-items: stretch;
- border: 2px solid ${themeCssVariables.border.color.medium};
+ align-items: center;
+ background-color: ${themeCssVariables.border.color.medium};
border-radius: ${themeCssVariables.border.radius.sm};
- color: ${themeCssVariables.font.color.light};
+ box-sizing: border-box;
display: flex;
- flex-direction: column;
- gap: ${themeCssVariables.spacing['0.5']};
- height: ${themeCssVariables.spacing[8]};
+ height: 40px;
justify-content: center;
- padding: ${themeCssVariables.spacing['0.5']};
- width: ${themeCssVariables.spacing[6]};
+ padding: 2px;
+ width: 32px;
+`;
+
+const StyledCardMediaContent = styled.div`
+ align-items: stretch;
+ background-color: ${themeCssVariables.background.secondary};
+ border-radius: 2px;
+ box-sizing: border-box;
+ display: flex;
+ flex: 1;
+ flex-direction: column;
+ gap: 2px;
+ height: 100%;
+ justify-content: center;
+ min-width: 0;
+ padding: 2px;
`;
const StyledFolderRow = styled.div`
align-items: center;
display: flex;
+ flex: 1 0 0;
gap: 2px;
+ min-height: 0;
`;
const StyledFolderIcon = styled.div<{ isDisabled?: boolean }>`
background-color: ${({ isDisabled }) =>
isDisabled
- ? themeCssVariables.background.quaternary
- : themeCssVariables.accent.accent4060};
+ ? themeCssVariables.border.color.medium
+ : themeCssVariables.accent.accent7};
border-radius: 1px;
- height: 5px;
- width: 5px;
+ height: 100%;
+ width: 4.8px;
`;
const StyledFolderLabel = styled.div<{ isDisabled?: boolean }>`
background-color: ${({ isDisabled }) =>
isDisabled
- ? themeCssVariables.background.quaternary
- : themeCssVariables.accent.accent4060};
+ ? themeCssVariables.border.color.medium
+ : themeCssVariables.accent.accent7};
border-radius: 1px;
flex: 1;
- height: 5px;
+ height: 100%;
`;
export const SettingsAccountsMessageFolderIcon = ({
@@ -57,26 +72,28 @@ export const SettingsAccountsMessageFolderIcon = ({
return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
);
};
diff --git a/packages/twenty-front/src/modules/settings/components/SettingsCard.tsx b/packages/twenty-front/src/modules/settings/components/SettingsCard.tsx
index da59d90558..441f98cbb2 100644
--- a/packages/twenty-front/src/modules/settings/components/SettingsCard.tsx
+++ b/packages/twenty-front/src/modules/settings/components/SettingsCard.tsx
@@ -16,6 +16,7 @@ type SettingsCardProps = {
disabled?: boolean;
soon?: boolean;
Icon: ReactNode;
+ iconColor?: string;
onClick?: () => void;
title: string;
className?: string;
@@ -82,8 +83,15 @@ const StyledDescription = styled.div`
padding-left: ${themeCssVariables.spacing[7]};
`;
-const StyledIconContainer = styled.div`
+const StyledIconContainer = styled.div<{
+ disabled?: boolean;
+ iconColor?: string;
+}>`
align-items: center;
+ color: ${({ disabled, iconColor }) =>
+ disabled
+ ? themeCssVariables.font.color.extraLight
+ : (iconColor ?? 'inherit')};
display: flex;
height: 24px;
justify-content: center;
@@ -95,6 +103,7 @@ export const SettingsCard = ({
soon,
disabled = soon,
Icon,
+ iconColor,
onClick,
title,
className,
@@ -112,7 +121,9 @@ export const SettingsCard = ({
- {Icon}
+
+ {Icon}
+
{title}
{soon && }
diff --git a/packages/twenty-front/src/modules/settings/components/SettingsDiscoveryHeroCard.tsx b/packages/twenty-front/src/modules/settings/components/SettingsDiscoveryHeroCard.tsx
index 5120af73f2..7b4c9a624d 100644
--- a/packages/twenty-front/src/modules/settings/components/SettingsDiscoveryHeroCard.tsx
+++ b/packages/twenty-front/src/modules/settings/components/SettingsDiscoveryHeroCard.tsx
@@ -7,7 +7,7 @@ import { useModal } from '@/ui/layout/modal/hooks/useModal';
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
import { styled } from '@linaria/react';
import { useLingui } from '@lingui/react/macro';
-import { useContext } from 'react';
+import { type ReactNode, useContext } from 'react';
import { Card } from 'twenty-ui-deprecated/layout';
import {
ThemeContext,
@@ -43,11 +43,17 @@ const StyledOverlay = styled.div`
position: absolute;
`;
+const StyledFooter = styled.div`
+ background: ${themeCssVariables.background.secondary};
+ border-top: 1px solid ${themeCssVariables.border.color.medium};
+`;
+
type SettingsDiscoveryHeroCardProps = {
lightSrc: string;
darkSrc: string;
instanceIdPrefix: string;
tabs: SettingsCustomizeVideoModalTab[];
+ footer?: ReactNode;
playButtonAriaLabel?: string;
};
@@ -56,6 +62,7 @@ export const SettingsDiscoveryHeroCard = ({
darkSrc,
instanceIdPrefix,
tabs,
+ footer,
playButtonAriaLabel,
}: SettingsDiscoveryHeroCardProps) => {
const { t } = useLingui();
@@ -64,6 +71,7 @@ export const SettingsDiscoveryHeroCard = ({
const isDiscoveryVideoEnabled = useIsFeatureEnabled(
FeatureFlagKey.IS_SETTINGS_DISCOVERY_HERO_ENABLED,
);
+ const shouldDisplayVideo = isDiscoveryVideoEnabled && tabs.length > 0;
const modalInstanceId = `${instanceIdPrefix}-modal`;
const tabsInstanceId = `${instanceIdPrefix}-tabs`;
@@ -75,7 +83,7 @@ export const SettingsDiscoveryHeroCard = ({
- {isDiscoveryVideoEnabled && (
+ {shouldDisplayVideo && (
openModal(modalInstanceId)}
@@ -84,8 +92,11 @@ export const SettingsDiscoveryHeroCard = ({
)}
+ {footer !== undefined && footer !== null && (
+ {footer}
+ )}
- {isDiscoveryVideoEnabled && (
+ {shouldDisplayVideo && (
(
+
+
+
+);
diff --git a/packages/twenty-front/src/modules/settings/data-model/fields/forms/components/SettingsObjectNewFieldSelector.tsx b/packages/twenty-front/src/modules/settings/data-model/fields/forms/components/SettingsObjectNewFieldSelector.tsx
index 1f891726a4..6728e50beb 100644
--- a/packages/twenty-front/src/modules/settings/data-model/fields/forms/components/SettingsObjectNewFieldSelector.tsx
+++ b/packages/twenty-front/src/modules/settings/data-model/fields/forms/components/SettingsObjectNewFieldSelector.tsx
@@ -63,6 +63,11 @@ const StyledSearchInputContainer = styled.div`
width: 100%;
`;
+const StyledFieldTypeIconContainer = styled.span`
+ display: flex;
+ opacity: 0.64;
+`;
+
export const SettingsObjectNewFieldSelector = ({
excludedFieldTypes = [],
objectNamePlural,
@@ -164,10 +169,12 @@ export const SettingsObjectNewFieldSelector = ({
+
+
+
}
title={config.label}
/>
diff --git a/packages/twenty-front/src/modules/settings/data-model/object-details/components/SettingsObjectRelationsTable.tsx b/packages/twenty-front/src/modules/settings/data-model/object-details/components/SettingsObjectRelationsTable.tsx
index 530c779407..70ba60a77c 100644
--- a/packages/twenty-front/src/modules/settings/data-model/object-details/components/SettingsObjectRelationsTable.tsx
+++ b/packages/twenty-front/src/modules/settings/data-model/object-details/components/SettingsObjectRelationsTable.tsx
@@ -7,11 +7,13 @@ import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { SortableTableHeader } from '@/ui/layout/table/components/SortableTableHeader';
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 { useSortedArray } from '@/ui/layout/table/hooks/useSortedArray';
import { type TableMetadata } from '@/ui/layout/table/types/TableMetadata';
import { isAdvancedModeEnabledState } from '@/ui/navigation/navigation-drawer/states/isAdvancedModeEnabledState';
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
+import { StyledSettingsDataModelTableBodyContainer } from '@/settings/data-model/components/SettingsDataModelTableBodyContainer';
import { styled } from '@linaria/react';
import { msg } from '@lingui/core/macro';
import { useLingui } from '@lingui/react/macro';
@@ -182,13 +184,17 @@ export const SettingsObjectRelationsTable = ({
))}
- {filteredRelationFields.map((fieldMetadataItem) => (
-
- ))}
+
+
+ {filteredRelationFields.map((fieldMetadataItem) => (
+
+ ))}
+
+
>
);
diff --git a/packages/twenty-front/src/modules/settings/playground/components/SettingsMcpSetup.tsx b/packages/twenty-front/src/modules/settings/playground/components/SettingsMcpSetup.tsx
index 9b0a64d7bb..b28ec8a043 100644
--- a/packages/twenty-front/src/modules/settings/playground/components/SettingsMcpSetup.tsx
+++ b/packages/twenty-front/src/modules/settings/playground/components/SettingsMcpSetup.tsx
@@ -1,17 +1,44 @@
import { styled } from '@linaria/react';
import { useLingui } from '@lingui/react/macro';
+import { type ReactNode } from 'react';
import { H2Title, IconCopy } from 'twenty-ui-deprecated/display';
-import { Button } from 'twenty-ui-deprecated/input';
+import { LightIconButton } from 'twenty-ui-deprecated/input';
import { Card, CardContent, Section } from 'twenty-ui-deprecated/layout';
+import { themeCssVariables } from 'twenty-ui-deprecated/theme-constants';
import { REACT_APP_SERVER_BASE_URL } from '~/config';
import { useCopyToClipboard } from '~/hooks/useCopyToClipboard';
+const StyledMcpConfigContainer = styled.div`
+ position: relative;
+`;
+
+const StyledCopyButtonContainer = styled.div`
+ position: absolute;
+ right: 0;
+ top: 0;
+`;
+
const StyledPre = styled.pre`
+ color: ${themeCssVariables.font.color.secondary};
font-family: monospace;
+ line-height: 1.5;
margin: 0;
+ overflow-x: auto;
white-space: pre;
`;
+const StyledJsonKey = styled.span`
+ color: ${themeCssVariables.color.blue};
+`;
+
+const StyledJsonString = styled.span`
+ color: ${themeCssVariables.color.green};
+`;
+
+const StyledJsonPlaceholder = styled.span`
+ color: ${themeCssVariables.color.orange};
+`;
+
const buildMcpConfig = (serverUrl: string) =>
`{
"mcpServers": {
@@ -24,6 +51,61 @@ const buildMcpConfig = (serverUrl: string) =>
}
}`;
+const renderJsonString = (token: string, key: string) => {
+ const apiKeyPlaceholder = '';
+
+ if (!token.includes(apiKeyPlaceholder)) {
+ return {token};
+ }
+
+ const [beforePlaceholder, afterPlaceholder] = token.split(apiKeyPlaceholder);
+
+ return (
+
+ {beforePlaceholder}
+ {apiKeyPlaceholder}
+ {afterPlaceholder}
+
+ );
+};
+
+const getHighlightedMcpConfig = (mcpConfig: string) => {
+ const jsonStringTokenRegex = /("(?:[^"\\]|\\.)*")(\s*:)?/g;
+ const tokens: ReactNode[] = [];
+ let previousMatchEndIndex = 0;
+ let tokenIndex = 0;
+ let match: RegExpExecArray | null;
+
+ while ((match = jsonStringTokenRegex.exec(mcpConfig)) !== null) {
+ const [fullMatch, quotedString, trailingColon] = match;
+ const matchIndex = match.index;
+
+ if (matchIndex > previousMatchEndIndex) {
+ tokens.push(mcpConfig.slice(previousMatchEndIndex, matchIndex));
+ }
+
+ if (trailingColon) {
+ tokens.push(
+
+ {quotedString}
+ ,
+ );
+ tokens.push(trailingColon);
+ } else {
+ tokens.push(renderJsonString(quotedString, `json-string-${tokenIndex}`));
+ }
+
+ previousMatchEndIndex = matchIndex + fullMatch.length;
+ tokenIndex += 1;
+ }
+
+ if (previousMatchEndIndex < mcpConfig.length) {
+ tokens.push(mcpConfig.slice(previousMatchEndIndex));
+ }
+
+ return tokens;
+};
+
export const SettingsMcpSetup = () => {
const { t } = useLingui();
const { copyToClipboard } = useCopyToClipboard();
@@ -36,19 +118,22 @@ export const SettingsMcpSetup = () => {
description={t`Add Twenty as a Model Context Protocol (MCP) server. Paste this config into Claude Desktop, Cursor, Cline, Continue, Zed, or any other MCP-aware client.`}
/>
-
- {mcpConfig}
-
-
diff --git a/packages/twenty-front/src/modules/settings/roles/role/components/SettingsRoleLabelContainer.tsx b/packages/twenty-front/src/modules/settings/roles/role/components/SettingsRoleLabelContainer.tsx
index 9476a524e7..2a8483452c 100644
--- a/packages/twenty-front/src/modules/settings/roles/role/components/SettingsRoleLabelContainer.tsx
+++ b/packages/twenty-front/src/modules/settings/roles/role/components/SettingsRoleLabelContainer.tsx
@@ -7,11 +7,24 @@ import { t } from '@lingui/core/macro';
import { themeCssVariables } from 'twenty-ui-deprecated/theme-constants';
const StyledHeaderTitle = styled.div`
- color: ${themeCssVariables.font.color.primary};
- font-size: ${themeCssVariables.font.size.lg};
- font-weight: ${themeCssVariables.font.weight.semiBold};
+ border-radius: ${themeCssVariables.border.radius.sm};
max-width: 420px;
+ padding-left: ${themeCssVariables.spacing[1]};
+ padding-right: ${themeCssVariables.spacing[1]};
width: fit-content;
+
+ &:hover {
+ background: ${themeCssVariables.background.transparent.light};
+ }
+
+ & > div:hover {
+ background: transparent;
+ }
+
+ & > div :hover {
+ background: transparent;
+ }
+
& > input:disabled {
color: ${themeCssVariables.font.color.primary};
}
@@ -45,7 +58,7 @@ export const SettingsRoleLabelContainer = ({
{
const { theme } = useContext(ThemeContext);
return (
diff --git a/packages/twenty-front/src/pages/settings/ai/components/SettingsAgentToolsTable.tsx b/packages/twenty-front/src/pages/settings/ai/components/SettingsAgentToolsTable.tsx
index f23d812659..60928f08d5 100644
--- a/packages/twenty-front/src/pages/settings/ai/components/SettingsAgentToolsTable.tsx
+++ b/packages/twenty-front/src/pages/settings/ai/components/SettingsAgentToolsTable.tsx
@@ -97,6 +97,7 @@ export const SettingsAgentToolsTable = ({
}
link={getToolLink(tool)}
diff --git a/packages/twenty-front/src/pages/settings/ai/components/SettingsToolIcon.tsx b/packages/twenty-front/src/pages/settings/ai/components/SettingsToolIcon.tsx
index ecf370bef8..db0a3e4ee8 100644
--- a/packages/twenty-front/src/pages/settings/ai/components/SettingsToolIcon.tsx
+++ b/packages/twenty-front/src/pages/settings/ai/components/SettingsToolIcon.tsx
@@ -151,7 +151,7 @@ export const SettingsToolIcon = ({
@@ -175,5 +175,11 @@ export const SettingsToolIcon = ({
);
}
- return ;
+ return (
+
+ );
};
diff --git a/packages/twenty-front/src/pages/settings/community/SettingsCommunity.tsx b/packages/twenty-front/src/pages/settings/community/SettingsCommunity.tsx
index 0e5d2932d4..a9129e2aca 100644
--- a/packages/twenty-front/src/pages/settings/community/SettingsCommunity.tsx
+++ b/packages/twenty-front/src/pages/settings/community/SettingsCommunity.tsx
@@ -1,4 +1,5 @@
import { SettingsCard } from '@/settings/components/SettingsCard';
+import { SettingsDiscoveryHeroCard } from '@/settings/components/SettingsDiscoveryHeroCard';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { SettingsLabContent } from '@/settings/lab/components/SettingsLabContent';
import { SettingsPageLayout } from '@/settings/components/layout/SettingsPageLayout';
@@ -7,23 +8,50 @@ import { t } from '@lingui/core/macro';
import { useContext } from 'react';
import {
H2Title,
+ IconBrandX,
IconBriefcase,
IconTransform,
type IconComponent,
useIcons,
} from 'twenty-ui-deprecated/display';
import { Section } from 'twenty-ui-deprecated/layout';
-import { ThemeContext } from 'twenty-ui-deprecated/theme-constants';
+import { SettingsPath } from 'twenty-shared/types';
+import { getSettingsPath } from 'twenty-shared/utils';
+import {
+ MOBILE_VIEWPORT,
+ ThemeContext,
+ themeCssVariables,
+} from 'twenty-ui-deprecated/theme-constants';
+import coverDark from '~/pages/settings/community/assets/cover-dark.png';
+import coverLight from '~/pages/settings/community/assets/cover-light.png';
+
+const SETTINGS_COMMUNITY_HERO_INSTANCE_ID_PREFIX = 'settings-community-hero';
const StyledCardLink = styled.a`
+ display: block;
+ min-width: 0;
text-decoration: none;
`;
+const StyledCardsGrid = styled.div`
+ display: grid;
+ gap: ${themeCssVariables.spacing[2]};
+ grid-template-columns: repeat(2, minmax(0, 1fr));
+
+ @media (max-width: ${MOBILE_VIEWPORT}px) {
+ grid-template-columns: 1fr;
+ }
+`;
+
+const StyledFeaturesContent = styled.div`
+ display: grid;
+ gap: ${themeCssVariables.spacing[4]};
+`;
+
type SettingsCommunityLink = {
- title: string;
- description: string;
href: string;
Icon: IconComponent;
+ iconColor: string;
cardTitle: string;
};
@@ -32,63 +60,115 @@ export const SettingsCommunity = () => {
const { getIcon } = useIcons();
const IconBrandDiscord = getIcon('IconBrandDiscord');
- const communityLinks: SettingsCommunityLink[] = [
+ const socialLinks: SettingsCommunityLink[] = [
{
- title: t`Partners`,
- description: t`Hire a partner to help you implement and customize Twenty.`,
- href: 'https://twenty.com/partners/list',
- Icon: IconBriefcase,
- cardTitle: t`Browse partners`,
- },
- {
- title: t`Discord`,
- description: t`Join our community to get help and share feedback.`,
href: 'https://discord.com/invite/cx5n4Jzs57',
Icon: IconBrandDiscord,
+ iconColor: themeCssVariables.color.blue9,
cardTitle: t`Join our Discord`,
},
{
- title: t`Releases`,
- description: t`Check out our latest releases`,
- href: 'https://twenty.com/releases',
- Icon: IconTransform,
- cardTitle: t`Read changelog`,
+ href: 'https://x.com/twentycrm',
+ Icon: IconBrandX,
+ iconColor: themeCssVariables.font.color.primary,
+ cardTitle: t`Follow us on X`,
},
];
return (
- {communityLinks.map(({ title, description, href, Icon, cardTitle }) => (
-
-
+
+
+
+
+
+ {socialLinks.map(({ href, Icon, iconColor, cardTitle }) => (
+
+
+ }
+ iconColor={iconColor}
+ title={cardTitle}
+ />
+
+ ))}
+
+
+
+
+
+
+
+ }
+ title={t`Browse partners`}
+ />
+
+
+
+
+
+
+
}
- title={cardTitle}
+ title={t`Read changelog`}
/>
-
- ))}
-
-
diff --git a/packages/twenty-front/src/pages/settings/community/assets/cover-dark.png b/packages/twenty-front/src/pages/settings/community/assets/cover-dark.png
new file mode 100644
index 0000000000..ae85e10957
Binary files /dev/null and b/packages/twenty-front/src/pages/settings/community/assets/cover-dark.png differ
diff --git a/packages/twenty-front/src/pages/settings/community/assets/cover-light.png b/packages/twenty-front/src/pages/settings/community/assets/cover-light.png
new file mode 100644
index 0000000000..6e159ba82e
Binary files /dev/null and b/packages/twenty-front/src/pages/settings/community/assets/cover-light.png differ
diff --git a/packages/twenty-front/src/pages/settings/data-model/SettingsObjectDetailPage.tsx b/packages/twenty-front/src/pages/settings/data-model/SettingsObjectDetailPage.tsx
index 8a7dbf2d1e..2c03e4425c 100644
--- a/packages/twenty-front/src/pages/settings/data-model/SettingsObjectDetailPage.tsx
+++ b/packages/twenty-front/src/pages/settings/data-model/SettingsObjectDetailPage.tsx
@@ -1,6 +1,7 @@
import { useEffect, useState } from 'react';
import { useParams } from 'react-router-dom';
+import { ObjectMetadataIcon } from '@/object-metadata/components/ObjectMetadataIcon';
import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { ObjectFields } from '@/settings/data-model/object-details/components/tabs/ObjectFields';
@@ -135,6 +136,7 @@ export const SettingsObjectDetailPage = () => {
return (
}
links={[
{
children: t`Workspace`,
diff --git a/packages/twenty-front/src/pages/settings/data-model/SettingsObjectFieldTable.tsx b/packages/twenty-front/src/pages/settings/data-model/SettingsObjectFieldTable.tsx
index cff1c9bb60..60084d7473 100644
--- a/packages/twenty-front/src/pages/settings/data-model/SettingsObjectFieldTable.tsx
+++ b/packages/twenty-front/src/pages/settings/data-model/SettingsObjectFieldTable.tsx
@@ -5,12 +5,14 @@ import {
OBJECT_FIELD_TABLE_ROW_GRID_TEMPLATE_COLUMNS,
SettingsObjectFieldItemTableRow,
} from '@/settings/data-model/object-details/components/SettingsObjectFieldItemTableRow';
+import { StyledSettingsDataModelTableBodyContainer } from '@/settings/data-model/components/SettingsDataModelTableBodyContainer';
import { settingsObjectFieldsFamilyState } from '@/settings/data-model/object-details/states/settingsObjectFieldsFamilyState';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { SortableTableHeader } from '@/ui/layout/table/components/SortableTableHeader';
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 { useSortedArray } from '@/ui/layout/table/hooks/useSortedArray';
import { type TableMetadata } from '@/ui/layout/table/types/TableMetadata';
@@ -204,20 +206,24 @@ export const SettingsObjectFieldTable = ({
))}
- {filteredItems.map((objectSettingsDetailItem) => {
- const status = objectSettingsDetailItem.fieldMetadataItem.isActive
- ? 'active'
- : 'disabled';
+
+
+ {filteredItems.map((objectSettingsDetailItem) => {
+ const status = objectSettingsDetailItem.fieldMetadataItem.isActive
+ ? 'active'
+ : 'disabled';
- return (
-
- );
- })}
+ return (
+
+ );
+ })}
+
+
>
);
diff --git a/packages/twenty-front/src/pages/settings/data-model/SettingsObjectTable.tsx b/packages/twenty-front/src/pages/settings/data-model/SettingsObjectTable.tsx
index af07988177..c1e3592ada 100644
--- a/packages/twenty-front/src/pages/settings/data-model/SettingsObjectTable.tsx
+++ b/packages/twenty-front/src/pages/settings/data-model/SettingsObjectTable.tsx
@@ -5,8 +5,10 @@ import { useUpdateOneObjectMetadataItem } from '@/object-metadata/hooks/useUpdat
import { type EnrichedObjectMetadataItem } from '@/object-metadata/types/EnrichedObjectMetadataItem';
import { isHiddenSystemField } from '@/object-metadata/utils/isHiddenSystemField';
import { useCombinedGetTotalCount } from '@/object-record/multiple-objects/hooks/useCombinedGetTotalCount';
+import { StyledSettingsDataModelTableBodyContainer } from '@/settings/data-model/components/SettingsDataModelTableBodyContainer';
import { SettingsObjectMetadataItemTableRow } from '@/settings/data-model/object-details/components/SettingsObjectItemTableRow';
import { TableRow } from '@/ui/layout/table/components/TableRow';
+import { TableBody } from '@/ui/layout/table/components/TableBody';
import {
SETTINGS_OBJECT_TABLE_ROW_GRID_TEMPLATE_COLUMNS,
SETTINGS_OBJECT_TABLE_ROW_MOBILE_MIN_WIDTH,
@@ -236,56 +238,62 @@ export const SettingsObjectTable = ({
)}
- {filteredObjectSettingsItems.map((objectSettingsItem) => {
- const isActive = objectSettingsItem.objectMetadataItem.isActive;
+
+
+ {filteredObjectSettingsItems.map((objectSettingsItem) => {
+ const isActive =
+ objectSettingsItem.objectMetadataItem.isActive;
- return (
-
-
-
- ) : isDDLLocked ? null : (
-
- updateOneObjectMetadataItem({
- idToUpdate:
- objectSettingsItem.objectMetadataItem.id,
- updatePayload: { isActive: true },
- })
- }
- onDelete={() =>
- deleteOneObjectMetadataItem(
- objectSettingsItem.objectMetadataItem.id,
- )
- }
- />
- )
- }
- link={
- isActive
- ? getSettingsPath(SettingsPath.ObjectDetail, {
- objectNamePlural:
- objectSettingsItem.objectMetadataItem.namePlural,
- })
- : undefined
- }
- />
- );
- })}
+ return (
+
+
+
+ ) : isDDLLocked ? null : (
+
+ updateOneObjectMetadataItem({
+ idToUpdate:
+ objectSettingsItem.objectMetadataItem.id,
+ updatePayload: { isActive: true },
+ })
+ }
+ onDelete={() =>
+ deleteOneObjectMetadataItem(
+ objectSettingsItem.objectMetadataItem.id,
+ )
+ }
+ />
+ )
+ }
+ link={
+ isActive
+ ? getSettingsPath(SettingsPath.ObjectDetail, {
+ objectNamePlural:
+ objectSettingsItem.objectMetadataItem
+ .namePlural,
+ })
+ : undefined
+ }
+ />
+ );
+ })}
+
+
diff --git a/packages/twenty-front/src/pages/settings/data-model/new-field/SettingsObjectNewFieldConfigure.tsx b/packages/twenty-front/src/pages/settings/data-model/new-field/SettingsObjectNewFieldConfigure.tsx
index 951e1439ce..c238babc7e 100644
--- a/packages/twenty-front/src/pages/settings/data-model/new-field/SettingsObjectNewFieldConfigure.tsx
+++ b/packages/twenty-front/src/pages/settings/data-model/new-field/SettingsObjectNewFieldConfigure.tsx
@@ -4,6 +4,7 @@ import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilte
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { SettingsWizardStepBar } from '@/settings/components/layout/SettingsWizardStepBar';
import { FIELD_NAME_MAXIMUM_LENGTH } from '@/settings/data-model/constants/FieldNameMaximumLength';
+import { SettingsObjectNewFieldHeaderIcon } from '@/settings/data-model/fields/components/SettingsObjectNewFieldHeaderIcon';
import { SettingsDataModelFieldIconLabelForm } from '@/settings/data-model/fields/forms/components/SettingsDataModelFieldIconLabelForm';
import { SettingsDataModelFieldSettingsFormCard } from '@/settings/data-model/fields/forms/components/SettingsDataModelFieldSettingsFormCard';
import { settingsFieldFormSchema } from '@/settings/data-model/fields/forms/validation-schemas/settingsFieldFormSchema';
@@ -183,6 +184,11 @@ export const SettingsObjectNewFieldConfigure = () => {
>
+ }
titleColor={themeCssVariables.font.color.tertiary}
links={[
{
diff --git a/packages/twenty-front/src/pages/settings/data-model/new-field/SettingsObjectNewFieldSelect.tsx b/packages/twenty-front/src/pages/settings/data-model/new-field/SettingsObjectNewFieldSelect.tsx
index a94200a6c9..35f77e1507 100644
--- a/packages/twenty-front/src/pages/settings/data-model/new-field/SettingsObjectNewFieldSelect.tsx
+++ b/packages/twenty-front/src/pages/settings/data-model/new-field/SettingsObjectNewFieldSelect.tsx
@@ -3,6 +3,7 @@ import { SettingsPageContainer } from '@/settings/components/SettingsPageContain
import { SettingsPageLayout } from '@/settings/components/layout/SettingsPageLayout';
import { SettingsWizardStepBar } from '@/settings/components/layout/SettingsWizardStepBar';
import { SETTINGS_FIELD_TYPE_CONFIGS } from '@/settings/data-model/constants/SettingsFieldTypeConfigs';
+import { SettingsObjectNewFieldHeaderIcon } from '@/settings/data-model/fields/components/SettingsObjectNewFieldHeaderIcon';
import { SettingsObjectNewFieldSelector } from '@/settings/data-model/fields/forms/components/SettingsObjectNewFieldSelector';
import { type FieldType } from '@/settings/data-model/types/FieldType';
import { type SettingsFieldType } from '@/settings/data-model/types/SettingsFieldType';
@@ -67,6 +68,11 @@ export const SettingsObjectNewFieldSelect = () => {
>
+ }
titleColor={themeCssVariables.font.color.tertiary}
links={[
{
diff --git a/packages/twenty-front/src/pages/settings/layout/SettingsLayout.tsx b/packages/twenty-front/src/pages/settings/layout/SettingsLayout.tsx
index 0adafe8cf4..77a5fef02b 100644
--- a/packages/twenty-front/src/pages/settings/layout/SettingsLayout.tsx
+++ b/packages/twenty-front/src/pages/settings/layout/SettingsLayout.tsx
@@ -1,5 +1,6 @@
import { useEnterLayoutCustomizationMode } from '@/layout-customization/hooks/useEnterLayoutCustomizationMode';
import { SettingsDiscoveryHeroCard } from '@/settings/components/SettingsDiscoveryHeroCard';
+import { SettingsOptionCardContentButton } from '@/settings/components/SettingsOptions/SettingsOptionCardContentButton';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { SettingsLayoutItemsStats } from '@/settings/layout/components/SettingsLayoutItemsStats';
import { SettingsPageLayout } from '@/settings/components/layout/SettingsPageLayout';
@@ -70,16 +71,6 @@ export const SettingsLayout = () => {
return (
- }
links={[
{
children: t`Workspace`,
@@ -96,6 +87,23 @@ export const SettingsLayout = () => {
instanceIdPrefix={SETTINGS_LAYOUT_HERO_INSTANCE_ID_PREFIX}
tabs={heroTabs}
playButtonAriaLabel={t`Watch customization demo`}
+ footer={
+
+ }
+ />
+ }
/>