From 612f7c37a5d0cd88b46bc3b0f18ed39cfbc563d1 Mon Sep 17 00:00:00 2001 From: Thomas des Francs Date: Wed, 18 Feb 2026 22:33:37 +0100 Subject: [PATCH] Improve security settings card grouping and description overflow (#17928) # After - Added a separtor between the two audit logs cards - Rename the audit log card to avoid repetition - Grouped "Invite by link" and "2 factor auth" in one group - Changed the card component description to always be one line max with truncation & tooltips CleanShot 2026-02-13 at 17 02 36 b49f2eb043b6712d013618bb0a4ef7f011cf2316e1163fbdee4c293bed036ac9 --------- Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com> Co-authored-by: Charles Bochet Co-authored-by: Charles Bochet --- .../SettingsCardContentBase.tsx | 5 ++++ .../SettingsOptionCardContentButton.tsx | 21 ++++++++++----- .../SettingsOptionCardContentCounter.tsx | 12 ++++++--- .../SettingsOptionCardContentSelect.tsx | 21 ++++++++++----- .../SettingsOptionCardContentToggle.tsx | 21 ++++++++++----- .../SettingsDataModelFieldDateForm.tsx | 5 ++-- .../getDisplayFormatSelectDescription.tsx | 24 ----------------- ...ingsDataModelFieldRelationJunctionForm.tsx | 25 ++---------------- ...ttingsSecurityAuthProvidersOptionsList.tsx | 3 +-- .../settings/security/SettingsSecurity.tsx | 26 +++++++++++-------- 10 files changed, 76 insertions(+), 87 deletions(-) delete mode 100644 packages/twenty-front/src/modules/settings/data-model/fields/forms/date/utils/getDisplayFormatSelectDescription.tsx diff --git a/packages/twenty-front/src/modules/settings/components/SettingsOptions/SettingsCardContentBase.tsx b/packages/twenty-front/src/modules/settings/components/SettingsOptions/SettingsCardContentBase.tsx index 68938b8183..87014ec321 100644 --- a/packages/twenty-front/src/modules/settings/components/SettingsOptions/SettingsCardContentBase.tsx +++ b/packages/twenty-front/src/modules/settings/components/SettingsOptions/SettingsCardContentBase.tsx @@ -32,6 +32,11 @@ export const StyledSettingsCardTitle = styled.div` margin-bottom: ${({ theme }) => theme.spacing(1)}; `; +export const StyledSettingsCardTextContainer = styled.div` + flex: 1; + min-width: 0; +`; + export const StyledSettingsCardDescription = styled.div` color: ${({ theme }) => theme.font.color.secondary}; font-size: ${({ theme }) => theme.font.size.sm}; diff --git a/packages/twenty-front/src/modules/settings/components/SettingsOptions/SettingsOptionCardContentButton.tsx b/packages/twenty-front/src/modules/settings/components/SettingsOptions/SettingsOptionCardContentButton.tsx index 2fd576d013..a34e547875 100644 --- a/packages/twenty-front/src/modules/settings/components/SettingsOptions/SettingsOptionCardContentButton.tsx +++ b/packages/twenty-front/src/modules/settings/components/SettingsOptions/SettingsOptionCardContentButton.tsx @@ -2,21 +2,26 @@ import { StyledSettingsCardContent, StyledSettingsCardDescription, StyledSettingsCardIcon, + StyledSettingsCardTextContainer, StyledSettingsCardTitle, } from '@/settings/components/SettingsOptions/SettingsCardContentBase'; import { SettingsOptionIconCustomizer } from '@/settings/components/SettingsOptions/SettingsOptionIconCustomizer'; import styled from '@emotion/styled'; -import { type IconComponent } from 'twenty-ui/display'; +import { + type IconComponent, + OverflowingTextWithTooltip, +} from 'twenty-ui/display'; type SettingsOptionCardContentButtonProps = { Icon?: IconComponent; title: React.ReactNode; - description?: string | React.ReactNode; + description?: string; disabled?: boolean; Button?: React.ReactNode; }; const StyledButtonContainer = styled.div` + flex-shrink: 0; margin-left: auto; `; @@ -34,12 +39,14 @@ export const SettingsOptionCardContentButton = ({ )} -
+ {title} - - {description} - -
+ {description && ( + + + + )} + {Button && {Button}} ); diff --git a/packages/twenty-front/src/modules/settings/components/SettingsOptions/SettingsOptionCardContentCounter.tsx b/packages/twenty-front/src/modules/settings/components/SettingsOptions/SettingsOptionCardContentCounter.tsx index b84d01e2c6..22bd767d71 100644 --- a/packages/twenty-front/src/modules/settings/components/SettingsOptions/SettingsOptionCardContentCounter.tsx +++ b/packages/twenty-front/src/modules/settings/components/SettingsOptions/SettingsOptionCardContentCounter.tsx @@ -3,10 +3,14 @@ import { StyledSettingsCardContent, StyledSettingsCardDescription, StyledSettingsCardIcon, + StyledSettingsCardTextContainer, StyledSettingsCardTitle, } from '@/settings/components/SettingsOptions/SettingsCardContentBase'; import { SettingsOptionIconCustomizer } from '@/settings/components/SettingsOptions/SettingsOptionIconCustomizer'; -import { type IconComponent } from 'twenty-ui/display'; +import { + type IconComponent, + OverflowingTextWithTooltip, +} from 'twenty-ui/display'; type SettingsOptionCardContentCounterProps = { Icon?: IconComponent; @@ -38,14 +42,14 @@ export const SettingsOptionCardContentCounter = ({ )} -
+ {title} {description && ( - {description} + )} -
+ )} -
+ {title} - - {description} - -
+ {description && ( + + + + )} + {children} ); diff --git a/packages/twenty-front/src/modules/settings/components/SettingsOptions/SettingsOptionCardContentToggle.tsx b/packages/twenty-front/src/modules/settings/components/SettingsOptions/SettingsOptionCardContentToggle.tsx index dc2dfd9988..fbdee0cd6b 100644 --- a/packages/twenty-front/src/modules/settings/components/SettingsOptions/SettingsOptionCardContentToggle.tsx +++ b/packages/twenty-front/src/modules/settings/components/SettingsOptions/SettingsOptionCardContentToggle.tsx @@ -3,13 +3,17 @@ import { StyledSettingsCardContent, StyledSettingsCardDescription, StyledSettingsCardIcon, + StyledSettingsCardTextContainer, StyledSettingsCardTitle, } from '@/settings/components/SettingsOptions/SettingsCardContentBase'; import { SettingsOptionIconCustomizer } from '@/settings/components/SettingsOptions/SettingsOptionIconCustomizer'; import { useTheme } from '@emotion/react'; import styled from '@emotion/styled'; import { useId } from 'react'; -import { type IconComponent } from 'twenty-ui/display'; +import { + type IconComponent, + OverflowingTextWithTooltip, +} from 'twenty-ui/display'; import { Toggle } from 'twenty-ui/input'; const StyledSettingsCardToggleContent = styled(StyledSettingsCardContent)` @@ -27,6 +31,7 @@ const StyledSettingsCardToggleButton = styled(Toggle)<{ }>` align-self: ${({ toggleCentered }) => toggleCentered ? 'center' : 'flex-start'}; + flex-shrink: 0; margin-left: auto; `; @@ -39,7 +44,7 @@ const StyledSettingsCardToggleCover = styled.span` type SettingsOptionCardContentToggleProps = { Icon?: IconComponent; title: React.ReactNode; - description?: React.ReactNode; + description?: string; divider?: boolean; disabled?: boolean; advancedMode?: boolean; @@ -70,17 +75,19 @@ export const SettingsOptionCardContentToggle = ({ )} -
+ - - {description} - -
+ {description && ( + + + + )} + diff --git a/packages/twenty-front/src/modules/settings/data-model/fields/forms/date/utils/getDisplayFormatSelectDescription.tsx b/packages/twenty-front/src/modules/settings/data-model/fields/forms/date/utils/getDisplayFormatSelectDescription.tsx deleted file mode 100644 index 29d6eca286..0000000000 --- a/packages/twenty-front/src/modules/settings/data-model/fields/forms/date/utils/getDisplayFormatSelectDescription.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import { FieldDateDisplayFormat } from '@/object-record/record-field/ui/types/FieldMetadata'; -import { Trans } from '@lingui/react/macro'; - -export const getDisplayFormatSelectDescription = ( - selectedDisplayFormat: FieldDateDisplayFormat, -) => { - if (selectedDisplayFormat === FieldDateDisplayFormat.CUSTOM) { - return ( - - Enter in{' '} - - Unicode - {' '} - format - - ); - } - return Choose the format used to display date value; -}; diff --git a/packages/twenty-front/src/modules/settings/data-model/fields/forms/morph-relation/components/SettingsDataModelFieldRelationJunctionForm.tsx b/packages/twenty-front/src/modules/settings/data-model/fields/forms/morph-relation/components/SettingsDataModelFieldRelationJunctionForm.tsx index b06e1ccbf0..1b10bb31bb 100644 --- a/packages/twenty-front/src/modules/settings/data-model/fields/forms/morph-relation/components/SettingsDataModelFieldRelationJunctionForm.tsx +++ b/packages/twenty-front/src/modules/settings/data-model/fields/forms/morph-relation/components/SettingsDataModelFieldRelationJunctionForm.tsx @@ -1,17 +1,14 @@ -import { Trans, useLingui } from '@lingui/react/macro'; +import { useLingui } from '@lingui/react/macro'; import { useFormContext } from 'react-hook-form'; import { useRecoilValue } from 'recoil'; -import { DOCUMENTATION_PATHS } from 'twenty-shared/constants'; import { FieldMetadataType } from 'twenty-shared/types'; import { isDefined } from 'twenty-shared/utils'; import { IconLink } from 'twenty-ui/display'; -import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState'; import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems'; import { SettingsOptionCardContentSelect } from '@/settings/components/SettingsOptions/SettingsOptionCardContentSelect'; import { SettingsOptionCardContentToggle } from '@/settings/components/SettingsOptions/SettingsOptionCardContentToggle'; -import { getDocumentationUrl } from '@/support/utils/getDocumentationUrl'; import { Select } from '@/ui/input/components/Select'; import { isAdvancedModeEnabledState } from '@/ui/navigation/navigation-drawer/states/isAdvancedModeEnabledState'; import { RelationType } from '~/generated-metadata/graphql'; @@ -29,12 +26,6 @@ export const SettingsDataModelFieldRelationJunctionForm = ({ useFormContext(); const isAdvancedModeEnabled = useRecoilValue(isAdvancedModeEnabledState); - const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState); - - const documentationUrl = getDocumentationUrl({ - locale: currentWorkspaceMember?.locale, - path: DOCUMENTATION_PATHS.USER_GUIDE_DATA_MODEL_HOW_TOS_CREATE_MANY_TO_MANY_RELATIONS, - }); const { objectMetadataItem: sourceObjectMetadataItem } = useObjectMetadataItem({ objectNameSingular }); @@ -163,19 +154,7 @@ export const SettingsDataModelFieldRelationJunctionForm = ({ - Build many-to-many relations.{' '} - - Learn more - - - } + description={t`Build many-to-many relations`} checked={isJunctionConfigEnabled} onChange={handleJunctionToggle} divider={isJunctionConfigEnabled} diff --git a/packages/twenty-front/src/modules/settings/security/components/SettingsSecurityAuthProvidersOptionsList.tsx b/packages/twenty-front/src/modules/settings/security/components/SettingsSecurityAuthProvidersOptionsList.tsx index 5c50391788..ba6a70a8e4 100644 --- a/packages/twenty-front/src/modules/settings/security/components/SettingsSecurityAuthProvidersOptionsList.tsx +++ b/packages/twenty-front/src/modules/settings/security/components/SettingsSecurityAuthProvidersOptionsList.tsx @@ -175,12 +175,11 @@ export const SettingsSecurityAuthProvidersOptionsList = () => { description={t`Allow the invitation of new users by sharing an invite link.`} checked={currentWorkspace.isPublicInviteLinkEnabled} advancedMode + divider onChange={() => handleChange(!currentWorkspace.isPublicInviteLinkEnabled) } /> - - diff --git a/packages/twenty-front/src/pages/settings/security/SettingsSecurity.tsx b/packages/twenty-front/src/pages/settings/security/SettingsSecurity.tsx index c41ec88961..5d0c80fc70 100644 --- a/packages/twenty-front/src/pages/settings/security/SettingsSecurity.tsx +++ b/packages/twenty-front/src/pages/settings/security/SettingsSecurity.tsx @@ -10,6 +10,7 @@ import { isClickHouseConfiguredState } from '@/client-config/states/isClickHouse import { isMultiWorkspaceEnabledState } from '@/client-config/states/isMultiWorkspaceEnabledState'; import { SettingsOptionCardContentButton } from '@/settings/components/SettingsOptions/SettingsOptionCardContentButton'; import { SettingsOptionCardContentCounter } from '@/settings/components/SettingsOptions/SettingsOptionCardContentCounter'; +import { Separator } from '@/settings/components/Separator'; import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer'; import { SettingsSSOIdentitiesProvidersListCard } from '@/settings/security/components/SSO/SettingsSSOIdentitiesProvidersListCard'; import { SettingsSecurityAuthBypassOptionsList } from '@/settings/security/components/SettingsSecurityAuthBypassOptionsList'; @@ -237,7 +238,7 @@ export const SettingsSecurity = () => { { } /> {isEventLogsEnabled && ( - + <> + + + )}