Remove all styled(Component) patterns in favor of parent wrappers and props (#18430)

## Summary

Eliminates all ~350 `styled(Component)` usages across `twenty-front` and
`twenty-ui` (212 files changed). Each was replaced following these
rules:

- **Margin/layout CSS** (margin, padding, flex, align-self, width) →
wrapped in a `styled.div`/`styled.span` parent container
- **Third-party components** (Link, TextareaAutosize,
ReactPhoneNumberInput, Handle, etc.) → parent container with child CSS
selectors (`> a`, `> textarea`, `> input`, etc.)
- **Intrinsic behavior via existing props** (TableRow
`gridTemplateColumns`, TableCell `color`/`align`) → replaced
`styled(TableRow)` / `styled(TableCell)` with direct prop usage
- **Other visual overrides on twenty-ui components** (Card, Section,
TabList, Button, MenuItem, ScrollWrapper, etc.) → parent wrappers with
`> div` / `> *` child selectors
- **Extending styled.div/span** → merged all CSS into a single
`styled.div`/`styled.span`

Also adds `overflow: hidden` to parent containers wrapping
`ScrollWrapper` so scroll activates correctly with the new wrapper
structure.

### Migration patterns

| Before | After |
|--------|-------|
| `styled(Avatar)` with `margin-right` | `<StyledAvatarContainer><Avatar
/></StyledAvatarContainer>` |
| `styled(Link)` with `text-decoration: none` |
`<StyledLinkContainer><Link /></StyledLinkContainer>` with `> a { ... }`
|
| `styled(TableRow)` with `grid-template-columns` | `<TableRow
gridTemplateColumns="..." />` |
| `styled(TableCell)` with `color` / `align` | `<TableCell color={...}
align="right" />` |
| `styled(Card)` with `margin-top` | `<StyledCardContainer><Card
/></StyledCardContainer>` |
| `styled(TabList)` with `background` |
`<StyledTabListContainer><TabList /></StyledTabListContainer>` with `>
div { ... }` |
| `styled(StyledBase)` extending a `styled.div` | Single merged
`styled.div` with all styles inlined |
This commit is contained in:
Charles Bochet
2026-03-05 18:16:25 +01:00
committed by GitHub
parent e5e3132ddd
commit c53a13417e
224 changed files with 4765 additions and 3837 deletions
@@ -28,8 +28,10 @@ const StyledButtonContainer = styled.div`
width: 100%;
`;
const StyledDownChevron = styled(IconChevronDown)`
const StyledDownChevronContainer = styled.span`
align-items: center;
color: ${themeCssVariables.font.color.primary};
display: flex;
position: absolute;
right: ${themeCssVariables.spacing['1.5']};
top: 50%;
@@ -45,9 +47,11 @@ const StyledSpan = styled.span`
margin-left: ${themeCssVariables.spacing[2]};
`;
const StyledButton = styled(Button)`
color: ${themeCssVariables.font.color.primary};
padding-right: ${themeCssVariables.spacing[6]};
const StyledButtonWrapper = styled.div`
> button {
color: ${themeCssVariables.font.color.primary};
padding-right: ${themeCssVariables.spacing[6]};
}
`;
export const SettingsDataModelNewFieldBreadcrumbDropDown = () => {
@@ -87,11 +91,17 @@ export const SettingsDataModelNewFieldBreadcrumbDropDown = () => {
dropdownId={dropdownId}
clickableComponent={
<StyledButtonContainer>
<StyledDownChevron size={theme.icon.size.md} />
<StyledDownChevronContainer>
<IconChevronDown size={theme.icon.size.md} />
</StyledDownChevronContainer>
{isConfigureStep ? (
<StyledButton variant="tertiary" title={t`2. Configure`} />
<StyledButtonWrapper>
<Button variant="tertiary" title={t`2. Configure`} />
</StyledButtonWrapper>
) : (
<StyledButton variant="tertiary" title={t`1. Type`} />
<StyledButtonWrapper>
<Button variant="tertiary" title={t`1. Type`} />
</StyledButtonWrapper>
)}
</StyledButtonContainer>
}
@@ -13,12 +13,16 @@ type SettingsDataModelPreviewFormCardProps = {
disabled?: boolean;
};
const StyledPreviewContainer = styled(CardContent)`
background-color: ${themeCssVariables.background.transparent.lighter};
const StyledPreviewContainerWrapper = styled.div`
> * {
background-color: ${themeCssVariables.background.transparent.lighter};
}
`;
const StyledFormContainer = styled(CardContent)`
padding: 0;
const StyledFormContainerWrapper = styled.div`
> * {
padding: 0;
}
`;
export const SettingsDataModelPreviewFormCard = ({
@@ -27,12 +31,18 @@ export const SettingsDataModelPreviewFormCard = ({
form,
}: SettingsDataModelPreviewFormCardProps) => (
<Card className={className} fullWidth rounded>
<StyledPreviewContainer divider={!!form}>
<StyledFormCardTitle>
<Trans>Preview</Trans>
</StyledFormCardTitle>
{preview}
</StyledPreviewContainer>
{!!form && <StyledFormContainer>{form}</StyledFormContainer>}
<StyledPreviewContainerWrapper>
<CardContent divider={!!form}>
<StyledFormCardTitle>
<Trans>Preview</Trans>
</StyledFormCardTitle>
{preview}
</CardContent>
</StyledPreviewContainerWrapper>
{!!form && (
<StyledFormContainerWrapper>
<CardContent>{form}</CardContent>
</StyledFormContainerWrapper>
)}
</Card>
);
@@ -56,7 +56,7 @@ const StyledCardContainer = styled.div`
width: calc(50% - ${themeCssVariables.spacing[1]});
`;
const StyledSearchInput = styled(SettingsTextInput)`
const StyledSearchInputContainer = styled.div`
width: 100%;
`;
@@ -108,13 +108,15 @@ export const SettingsObjectNewFieldSelector = ({
<>
{' '}
<Section>
<StyledSearchInput
instanceId="new-field-type-search"
LeftIcon={IconSearch}
placeholder={t`Search a type`}
value={searchQuery}
onChange={setSearchQuery}
/>
<StyledSearchInputContainer>
<SettingsTextInput
instanceId="new-field-type-search"
LeftIcon={IconSearch}
placeholder={t`Search a type`}
value={searchQuery}
onChange={setSearchQuery}
/>
</StyledSearchInputContainer>
</Section>
<Controller
name="type"
@@ -33,7 +33,7 @@ export const settingsDataModelFieldDateFormSchema = z.object({
settings: fieldDateSettings.optional(),
});
const StyledTextInput = styled(SettingsTextInput)`
const StyledTextInputContainer = styled.div`
padding: ${themeCssVariables.spacing[4]};
padding-top: 0;
`;
@@ -117,14 +117,16 @@ export const SettingsDataModelFieldDateForm = ({
control={control}
defaultValue={initialCustomUnicodeDateFormat}
render={({ field: { onChange, value } }) => (
<StyledTextInput
instanceId="custom-date-format-input"
placeholder={t`Format e.g. d-MMM-y (qqq''yy)`}
value={value}
onChange={(value) => onChange(value)}
disabled={false}
fullWidth
/>
<StyledTextInputContainer>
<SettingsTextInput
instanceId="custom-date-format-input"
placeholder={t`Format e.g. d-MMM-y (qqq''yy)`}
value={value}
onChange={(value) => onChange(value)}
disabled={false}
fullWidth
/>
</StyledTextInputContainer>
)}
/>
</AnimatedExpandableContainer>
@@ -67,8 +67,10 @@ type SettingsDataModelFieldSelectFormProps = {
disabled?: boolean;
};
const StyledContainer = styled(CardContent)`
padding-bottom: 14px;
const StyledContainerWrapper = styled.div`
> * {
padding-bottom: 14px;
}
`;
const StyledOptionsLabel = styled.div<{
@@ -119,18 +121,24 @@ const StyledIconContainer = styled.div`
margin-top: ${themeCssVariables.spacing[1]};
`;
const StyledIconPoint = styled(IconPoint)`
const StyledIconPointContainer = styled.span`
margin-right: ${themeCssVariables.spacing['0.5']};
display: flex;
align-items: center;
`;
const StyledFooter = styled(CardFooter)`
background-color: ${themeCssVariables.background.secondary};
padding: ${themeCssVariables.spacing[1]};
const StyledFooterContainer = styled.div`
> * {
background-color: ${themeCssVariables.background.secondary};
padding: ${themeCssVariables.spacing[1]};
}
`;
const StyledButton = styled(LightButton)`
justify-content: center;
width: 100%;
const StyledButtonContainer = styled.div`
> button {
justify-content: center;
width: 100%;
}
`;
const StyledOptionsHeaderContainer = styled.div`
@@ -316,199 +324,212 @@ export const SettingsDataModelFieldSelectForm = ({
defaultValue={initialOptions}
render={({ field: { onChange, value: options } }) => (
<>
<StyledContainer>
<StyledOptionsHeaderContainer>
<StyledLabelContainer>
{!isBulkInputMode && (
<AdvancedSettingsWrapper animationDimension="width" hideDot>
<StyledApiKeyContainer>
<StyledIconContainer>
<StyledIconPoint
size={12}
color={theme.color.yellow}
fill={theme.color.yellow}
/>
</StyledIconContainer>
<StyledApiKey>{t`API values`}</StyledApiKey>
</StyledApiKeyContainer>
</AdvancedSettingsWrapper>
)}
<StyledOptionsLabel
isAdvancedModeEnabled={isAdvancedModeEnabled}
isBulkInputMode={isBulkInputMode}
>
{t`Options`}
</StyledOptionsLabel>
</StyledLabelContainer>
{!disabled && (
<Dropdown
dropdownId={OPTIONS_DROPDOWN_ID}
clickableComponent={
<LightIconButton
Icon={IconDotsVertical}
accent="tertiary"
/>
}
dropdownComponents={
<DropdownContent
widthInPixels={GenericDropdownContentWidth.Narrow}
<StyledContainerWrapper>
<CardContent>
<StyledOptionsHeaderContainer>
<StyledLabelContainer>
{!isBulkInputMode && (
<AdvancedSettingsWrapper
animationDimension="width"
hideDot
>
<DropdownMenuItemsContainer>
<MenuItem
text={
isBulkInputMode ? t`Single edit` : t`Bulk edit`
}
LeftIcon={IconPencil}
onClick={() => {
if (!isBulkInputMode) {
setBulkInputText(
convertOptionsToBulkText(options),
);
}
setIsBulkInputMode(
(currentInputMode) => !currentInputMode,
);
closeOptionsDropdown(OPTIONS_DROPDOWN_ID);
}}
/>
<MenuItem
text={t`Remove all`}
accent="danger"
LeftIcon={IconTrash}
onClick={() => {
onChange([]);
closeOptionsDropdown(OPTIONS_DROPDOWN_ID);
}}
/>
</DropdownMenuItemsContainer>
</DropdownContent>
}
/>
)}
</StyledOptionsHeaderContainer>
{isBulkInputMode ? (
<StyledTextAreaContainer>
<TextArea
textAreaId="bulk-options-input"
placeholder={t`Enter one option per line`}
value={bulkInputText}
onChange={(nextOptionAsText) => {
if (disabled) {
return;
}
const nextOptions = convertBulkTextToOptions(
nextOptionAsText,
options,
);
onChange(nextOptions);
setBulkInputText(nextOptionAsText);
}}
minRows={5}
maxRows={15}
disabled={disabled}
/>
<StyledHelpText>
{t`Enter one option per line. Each line will become a new option.`}
</StyledHelpText>
</StyledTextAreaContainer>
) : (
<>
<DraggableList
onDragEnd={(result) =>
!disabled
? handleDragEnd(options, result, onChange)
: undefined
}
draggableItems={
<>
{options.map((option, index) => (
<DraggableItem
isInsideScrollableContainer
key={option.id}
draggableId={option.id}
index={index}
isDragDisabled={options.length === 1}
itemComponent={
<SettingsDataModelFieldSelectFormOptionRow
key={option.id}
option={option}
isNewRow={index === options.length - 1}
onChange={(nextOption) => {
if (disabled) {
return;
}
const nextOptions = toSpliced(
options,
index,
1,
nextOption,
);
onChange(nextOptions);
// Update option value in defaultValue if value has changed
if (
nextOption.value !== option.value &&
isOptionDefaultValue(option.value)
) {
handleRemoveOptionAsDefault(option.value);
handleSetOptionAsDefault(nextOption.value);
}
}}
onRemove={() => {
if (disabled) {
return;
}
const nextOptions = toSpliced(
options,
index,
1,
).map((option, nextOptionIndex) => ({
...option,
position: nextOptionIndex,
}));
onChange(nextOptions);
}}
isDefault={isOptionDefaultValue(option.value)}
fieldIsNullable={!!isNullable}
onSetAsDefault={() => {
if (disabled) {
return;
}
handleSetOptionAsDefault(option.value);
}}
onRemoveAsDefault={() => {
if (disabled) {
return;
}
handleRemoveOptionAsDefault(option.value);
}}
onInputEnter={() => {
if (disabled) {
return;
}
handleInputEnter();
}}
<StyledApiKeyContainer>
<StyledIconContainer>
<StyledIconPointContainer>
<IconPoint
size={12}
color={theme.color.yellow}
fill={theme.color.yellow}
/>
}
/>
))}
</>
}
/>
</>
)}
</StyledContainer>
</StyledIconPointContainer>
</StyledIconContainer>
<StyledApiKey>{t`API values`}</StyledApiKey>
</StyledApiKeyContainer>
</AdvancedSettingsWrapper>
)}
<StyledOptionsLabel
isAdvancedModeEnabled={isAdvancedModeEnabled}
isBulkInputMode={isBulkInputMode}
>
{t`Options`}
</StyledOptionsLabel>
</StyledLabelContainer>
{!disabled && (
<Dropdown
dropdownId={OPTIONS_DROPDOWN_ID}
clickableComponent={
<LightIconButton
Icon={IconDotsVertical}
accent="tertiary"
/>
}
dropdownComponents={
<DropdownContent
widthInPixels={GenericDropdownContentWidth.Narrow}
>
<DropdownMenuItemsContainer>
<MenuItem
text={
isBulkInputMode ? t`Single edit` : t`Bulk edit`
}
LeftIcon={IconPencil}
onClick={() => {
if (!isBulkInputMode) {
setBulkInputText(
convertOptionsToBulkText(options),
);
}
setIsBulkInputMode(
(currentInputMode) => !currentInputMode,
);
closeOptionsDropdown(OPTIONS_DROPDOWN_ID);
}}
/>
<MenuItem
text={t`Remove all`}
accent="danger"
LeftIcon={IconTrash}
onClick={() => {
onChange([]);
closeOptionsDropdown(OPTIONS_DROPDOWN_ID);
}}
/>
</DropdownMenuItemsContainer>
</DropdownContent>
}
/>
)}
</StyledOptionsHeaderContainer>
{isBulkInputMode ? (
<StyledTextAreaContainer>
<TextArea
textAreaId="bulk-options-input"
placeholder={t`Enter one option per line`}
value={bulkInputText}
onChange={(nextOptionAsText) => {
if (disabled) {
return;
}
const nextOptions = convertBulkTextToOptions(
nextOptionAsText,
options,
);
onChange(nextOptions);
setBulkInputText(nextOptionAsText);
}}
minRows={5}
maxRows={15}
disabled={disabled}
/>
<StyledHelpText>
{t`Enter one option per line. Each line will become a new option.`}
</StyledHelpText>
</StyledTextAreaContainer>
) : (
<>
<DraggableList
onDragEnd={(result) =>
!disabled
? handleDragEnd(options, result, onChange)
: undefined
}
draggableItems={
<>
{options.map((option, index) => (
<DraggableItem
isInsideScrollableContainer
key={option.id}
draggableId={option.id}
index={index}
isDragDisabled={options.length === 1}
itemComponent={
<SettingsDataModelFieldSelectFormOptionRow
key={option.id}
option={option}
isNewRow={index === options.length - 1}
onChange={(nextOption) => {
if (disabled) {
return;
}
const nextOptions = toSpliced(
options,
index,
1,
nextOption,
);
onChange(nextOptions);
// Update option value in defaultValue if value has changed
if (
nextOption.value !== option.value &&
isOptionDefaultValue(option.value)
) {
handleRemoveOptionAsDefault(option.value);
handleSetOptionAsDefault(
nextOption.value,
);
}
}}
onRemove={() => {
if (disabled) {
return;
}
const nextOptions = toSpliced(
options,
index,
1,
).map((option, nextOptionIndex) => ({
...option,
position: nextOptionIndex,
}));
onChange(nextOptions);
}}
isDefault={isOptionDefaultValue(option.value)}
fieldIsNullable={!!isNullable}
onSetAsDefault={() => {
if (disabled) {
return;
}
handleSetOptionAsDefault(option.value);
}}
onRemoveAsDefault={() => {
if (disabled) {
return;
}
handleRemoveOptionAsDefault(option.value);
}}
onInputEnter={() => {
if (disabled) {
return;
}
handleInputEnter();
}}
/>
}
/>
))}
</>
}
/>
</>
)}
</CardContent>
</StyledContainerWrapper>
{!disabled && !isBulkInputMode && (
<StyledFooter>
<StyledButton
title={t`Add option`}
Icon={IconPlus}
onClick={handleAddOption}
/>
</StyledFooter>
<StyledFooterContainer>
<CardFooter>
<StyledButtonContainer>
<LightButton
title={t`Add option`}
Icon={IconPlus}
onClick={handleAddOption}
/>
</StyledButtonContainer>
</CardFooter>
</StyledFooterContainer>
)}
</>
)}
@@ -75,13 +75,14 @@ const StyledRow = styled.div`
padding: ${themeCssVariables.spacing['1.5']} 0;
`;
const StyledColorSample = styled(ColorSample)`
const StyledColorSampleContainer = styled.span`
cursor: pointer;
margin-top: ${themeCssVariables.spacing[1]};
margin-bottom: ${themeCssVariables.spacing[1]};
margin-right: 14px;
margin-left: 14px;
display: flex;
align-items: center;
`;
const StyledOptionInputContainer = styled.div`
@@ -93,12 +94,16 @@ const StyledOptionInputContainer = styled.div`
}
`;
const StyledIconGripVertical = styled(IconGripVertical)`
const StyledIconGripVerticalContainer = styled.span`
margin-right: 3px;
display: flex;
align-items: center;
`;
const StyledLightIconButton = styled(LightIconButton)`
const StyledLightIconButtonContainer = styled.span`
margin-left: ${themeCssVariables.spacing[2]};
display: flex;
align-items: center;
`;
export const SettingsDataModelFieldSelectFormOptionRow = ({
@@ -129,14 +134,16 @@ export const SettingsDataModelFieldSelectFormOptionRow = ({
return (
<StyledRow className={className}>
<StyledIconGripVertical
style={{
minWidth: theme.icon.size.md,
}}
size={theme.icon.size.md}
stroke={theme.icon.stroke.sm}
color={theme.font.color.extraLight}
/>
<StyledIconGripVerticalContainer>
<IconGripVertical
style={{
minWidth: theme.icon.size.md,
}}
size={theme.icon.size.md}
stroke={theme.icon.stroke.sm}
color={theme.font.color.extraLight}
/>
</StyledIconGripVerticalContainer>
<AdvancedSettingsWrapper animationDimension="width" hideDot>
<StyledOptionInputContainer>
<SettingsTextInput
@@ -156,7 +163,11 @@ export const SettingsDataModelFieldSelectFormOptionRow = ({
<Dropdown
dropdownId={SELECT_COLOR_DROPDOWN_ID}
dropdownPlacement="bottom-start"
clickableComponent={<StyledColorSample colorName={option.color} />}
clickableComponent={
<StyledColorSampleContainer>
<ColorSample colorName={option.color} />
</StyledColorSampleContainer>
}
dropdownComponents={
<DropdownContent>
<DropdownMenuItemsContainer>
@@ -203,11 +214,13 @@ export const SettingsDataModelFieldSelectFormOptionRow = ({
dropdownId={SELECT_ACTIONS_DROPDOWN_ID}
dropdownPlacement="right-start"
clickableComponent={
<StyledLightIconButton
accent="tertiary"
Icon={IconDotsVertical}
disabled={shouldForbidRemoveAsDefault}
/>
<StyledLightIconButtonContainer>
<LightIconButton
accent="tertiary"
Icon={IconDotsVertical}
disabled={shouldForbidRemoveAsDefault}
/>
</StyledLightIconButtonContainer>
}
dropdownComponents={
shouldForbidRemoveAsDefault ? null : (
@@ -21,13 +21,17 @@ type SettingsDataModelFieldPreviewWidgetProps = {
fullWidth?: boolean;
};
const StyledCard = styled(Card)`
border-radius: ${themeCssVariables.border.radius.md};
color: ${themeCssVariables.font.color.primary};
const StyledCardContainer = styled.div`
> * {
border-radius: ${themeCssVariables.border.radius.md};
color: ${themeCssVariables.font.color.primary};
}
`;
const StyledCardContent = styled(CardContent)`
padding: ${themeCssVariables.spacing[2]};
const StyledCardContentContainer = styled.div`
> * {
padding: ${themeCssVariables.spacing[2]};
}
`;
export const SettingsDataModelFieldPreviewWidget = ({
@@ -43,27 +47,31 @@ export const SettingsDataModelFieldPreviewWidget = ({
});
return (
<StyledCard className={className} fullWidth>
<StyledCardContent>
<SettingsDataModelObjectPreview
objectMetadataItems={[objectMetadataItem]}
pluralizeLabel={pluralizeLabel}
/>
<SettingsDataModelFieldPreview
objectNameSingular={objectNameSingular}
fieldMetadataItem={{
label: fieldMetadataItem.label,
icon: fieldMetadataItem.icon,
defaultValue: fieldMetadataItem.defaultValue,
options: fieldMetadataItem.options,
settings: fieldMetadataItem.settings,
type: fieldMetadataItem.type,
name: computeMetadataNameFromLabel(fieldMetadataItem.label),
}}
shrink={shrink}
withFieldLabel={withFieldLabel}
/>
</StyledCardContent>
</StyledCard>
<StyledCardContainer className={className}>
<Card fullWidth>
<StyledCardContentContainer>
<CardContent>
<SettingsDataModelObjectPreview
objectMetadataItems={[objectMetadataItem]}
pluralizeLabel={pluralizeLabel}
/>
<SettingsDataModelFieldPreview
objectNameSingular={objectNameSingular}
fieldMetadataItem={{
label: fieldMetadataItem.label,
icon: fieldMetadataItem.icon,
defaultValue: fieldMetadataItem.defaultValue,
options: fieldMetadataItem.options,
settings: fieldMetadataItem.settings,
type: fieldMetadataItem.type,
name: computeMetadataNameFromLabel(fieldMetadataItem.label),
}}
shrink={shrink}
withFieldLabel={withFieldLabel}
/>
</CardContent>
</StyledCardContentContainer>
</Card>
</StyledCardContainer>
);
};
@@ -21,14 +21,19 @@ export type SettingsDataModelRelationFieldPreviewSubWidgetProps = {
pluralizeLabel?: boolean;
};
const StyledCard = styled(Card)`
border-radius: ${themeCssVariables.border.radius.md};
color: ${themeCssVariables.font.color.primary};
const StyledCardContainer = styled.div`
margin: auto;
> * {
border-radius: ${themeCssVariables.border.radius.md};
color: ${themeCssVariables.font.color.primary};
}
`;
const StyledCardContent = styled(CardContent)`
padding: ${themeCssVariables.spacing[2]};
const StyledCardContentContainer = styled.div`
> * {
padding: ${themeCssVariables.spacing[2]};
}
`;
export const SettingsDataModelRelationFieldPreviewSubWidget = ({
@@ -49,21 +54,25 @@ export const SettingsDataModelRelationFieldPreviewSubWidget = ({
.filter(isDefined);
return (
<StyledCard className={className} fullWidth>
<StyledCardContent>
<SettingsDataModelObjectPreview
objectMetadataItems={targetObjectMetadataItems}
pluralizeLabel={pluralizeLabel}
/>
<SettingsDataModelRelationFieldPreview
fieldMetadataItem={fieldMetadataItem}
relationTargetObjectNameSingular={
fieldPreviewTargetObjectNameSingular
}
shrink={shrink}
withFieldLabel={withFieldLabel}
/>
</StyledCardContent>
</StyledCard>
<StyledCardContainer className={className}>
<Card fullWidth>
<StyledCardContentContainer>
<CardContent>
<SettingsDataModelObjectPreview
objectMetadataItems={targetObjectMetadataItems}
pluralizeLabel={pluralizeLabel}
/>
<SettingsDataModelRelationFieldPreview
fieldMetadataItem={fieldMetadataItem}
relationTargetObjectNameSingular={
fieldPreviewTargetObjectNameSingular
}
shrink={shrink}
withFieldLabel={withFieldLabel}
/>
</CardContent>
</StyledCardContentContainer>
</Card>
</StyledCardContainer>
);
};
@@ -86,15 +86,17 @@ const StyledObjectInstanceCount = styled.div`
color: ${themeCssVariables.font.color.tertiary};
`;
const StyledObjectLink = styled(Link)`
align-items: center;
display: flex;
gap: ${themeCssVariables.spacing[1]};
text-decoration: none;
color: ${themeCssVariables.font.color.primary};
const StyledObjectLinkContainer = styled.div`
> a {
align-items: center;
display: flex;
gap: ${themeCssVariables.spacing[1]};
text-decoration: none;
color: ${themeCssVariables.font.color.primary};
&:hover {
color: ${themeCssVariables.font.color.secondary};
&:hover {
color: ${themeCssVariables.font.color.secondary};
}
}
`;
@@ -123,14 +125,16 @@ export const SettingsDataModelOverviewObject = ({
<StyledNode>
<StyledHeader>
<StyledObjectName onMouseEnter={() => {}} onMouseLeave={() => {}}>
<StyledObjectLink
to={getSettingsPath(SettingsPath.Objects, {
objectNamePlural: objectMetadataItem.namePlural,
})}
>
{Icon && <Icon size={theme.icon.size.md} />}
{objectMetadataItem.labelPlural}
</StyledObjectLink>
<StyledObjectLinkContainer>
<Link
to={getSettingsPath(SettingsPath.Objects, {
objectNamePlural: objectMetadataItem.namePlural,
})}
>
{Icon && <Icon size={theme.icon.size.md} />}
{objectMetadataItem.labelPlural}
</Link>
</StyledObjectLinkContainer>
<StyledObjectInstanceCount> · {totalCount}</StyledObjectInstanceCount>
</StyledObjectName>
<SettingsItemTypeTag item={objectMetadataItem} />
@@ -1,34 +1,21 @@
import { styled } from '@linaria/react';
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { TableCell } from '@/ui/layout/table/components/TableCell';
import { TableRow } from '@/ui/layout/table/components/TableRow';
import { Checkbox } from 'twenty-ui/input';
import { useIcons } from 'twenty-ui/display';
import { styled } from '@linaria/react';
import { useContext } from 'react';
import { ThemeContext, themeCssVariables } from 'twenty-ui/theme-constants';
export const AVAILABLE_STANDARD_OBJECTS_GRID_TEMPLATE_COLUMNS =
'28px 148px 256px 80px';
type SettingsAvailableStandardObjectItemTableRowProps = {
isSelected?: boolean;
objectItem: ObjectMetadataItem;
onClick?: () => void;
};
export const StyledAvailableStandardObjectTableRow = styled(TableRow)`
grid-template-columns: 28px 148px 256px 80px;
`;
const StyledCheckboxTableCell = styled(TableCell)`
justify-content: center;
padding: 0;
padding-left: ${themeCssVariables.spacing[1]};
`;
const StyledNameTableCell = styled(TableCell)`
color: ${themeCssVariables.font.color.primary};
gap: ${themeCssVariables.spacing[2]};
`;
const StyledDescription = styled.div`
overflow: hidden;
text-overflow: ellipsis;
@@ -45,22 +32,29 @@ export const SettingsAvailableStandardObjectItemTableRow = ({
const Icon = getIcon(objectItem.icon);
return (
<StyledAvailableStandardObjectTableRow
<TableRow
gridTemplateColumns={AVAILABLE_STANDARD_OBJECTS_GRID_TEMPLATE_COLUMNS}
key={objectItem.namePlural}
isSelected={isSelected}
onClick={onClick}
>
<StyledCheckboxTableCell>
<TableCell
align="center"
padding={`0 0 0 ${themeCssVariables.spacing[1]}`}
>
<Checkbox checked={!!isSelected} />
</StyledCheckboxTableCell>
<StyledNameTableCell>
</TableCell>
<TableCell
color={themeCssVariables.font.color.primary}
gap={themeCssVariables.spacing[2]}
>
{!!Icon && <Icon size={theme.icon.size.md} />}
{objectItem.labelPlural}
</StyledNameTableCell>
</TableCell>
<TableCell>
<StyledDescription>{objectItem.description}</StyledDescription>
</TableCell>
<TableCell align="right">{objectItem.fields.length}</TableCell>
</StyledAvailableStandardObjectTableRow>
</TableRow>
);
};
@@ -6,9 +6,10 @@ import { TableHeader } from '@/ui/layout/table/components/TableHeader';
import { t } from '@lingui/core/macro';
import { H2Title } from 'twenty-ui/display';
import { Section } from 'twenty-ui/layout';
import { TableRow } from '@/ui/layout/table/components/TableRow';
import {
AVAILABLE_STANDARD_OBJECTS_GRID_TEMPLATE_COLUMNS,
SettingsAvailableStandardObjectItemTableRow,
StyledAvailableStandardObjectTableRow,
} from './SettingsAvailableStandardObjectItemTableRow';
type SettingsAvailableStandardObjectsSectionProps = {
@@ -28,12 +29,14 @@ export const SettingsAvailableStandardObjectsSection = ({
description={t`Select one or several standard objects to activate below`}
/>
<Table>
<StyledAvailableStandardObjectTableRow>
<TableRow
gridTemplateColumns={AVAILABLE_STANDARD_OBJECTS_GRID_TEMPLATE_COLUMNS}
>
<TableHeader></TableHeader>
<TableHeader>{t`Name`}</TableHeader>
<TableHeader>{t`Description`}</TableHeader>
<TableHeader align="right">{t`Fields`}</TableHeader>
</StyledAvailableStandardObjectTableRow>
</TableRow>
<TableBody>
{objectItems.map((objectItem) => (
<SettingsAvailableStandardObjectItemTableRow
@@ -36,14 +36,8 @@ type SettingsObjectFieldItemTableRowProps = {
mode: 'view' | 'new-field';
};
export const StyledObjectFieldTableRow = styled(TableRow)`
grid-template-columns: minmax(0, 1fr) 148px 148px 36px;
`;
const StyledNameTableCell = styled(TableCell)`
color: ${themeCssVariables.font.color.primary};
gap: ${themeCssVariables.spacing[2]};
`;
export const OBJECT_FIELD_TABLE_ROW_GRID_TEMPLATE_COLUMNS =
'minmax(0, 1fr) 148px 148px 36px';
const StyledNameContainer = styled.div`
display: flex;
@@ -74,13 +68,10 @@ const StyledInactiveLabel = styled.span`
}
`;
const StyledIconTableCell = styled(TableCell)`
justify-content: center;
padding-right: ${themeCssVariables.spacing[1]};
`;
const StyledIconChevronRight = styled(IconChevronRight)`
const StyledIconChevronRightContainer = styled.span`
align-items: center;
color: ${themeCssVariables.font.color.tertiary};
display: flex;
`;
export const SettingsObjectFieldItemTableRow = ({
@@ -177,11 +168,15 @@ export const SettingsObjectFieldItemTableRow = ({
: relationObjectMetadataItem?.labelPlural;
return (
<StyledObjectFieldTableRow
<TableRow
gridTemplateColumns={OBJECT_FIELD_TABLE_ROW_GRID_TEMPLATE_COLUMNS}
onClick={mode === 'view' ? navigateToFieldEdit : undefined}
>
<UndecoratedLink to={linkToNavigate}>
<StyledNameTableCell>
<TableCell
color={themeCssVariables.font.color.primary}
gap={themeCssVariables.spacing[2]}
>
{!!Icon && (
<Icon
style={{
@@ -199,7 +194,7 @@ export const SettingsObjectFieldItemTableRow = ({
<StyledInactiveLabel>{t`Deactivated`}</StyledInactiveLabel>
)}
</StyledNameContainer>
</StyledNameTableCell>
</TableCell>
</UndecoratedLink>
<TableCell>
@@ -232,14 +227,19 @@ export const SettingsObjectFieldItemTableRow = ({
}}
/>
</TableCell>
<StyledIconTableCell>
<TableCell
align="center"
padding={`0 ${themeCssVariables.spacing[1]} 0 ${themeCssVariables.spacing[2]}`}
>
{status === 'active' ? (
mode === 'view' ? (
<UndecoratedLink to={linkToNavigate}>
<StyledIconChevronRight
size={theme.icon.size.md}
stroke={theme.icon.stroke.sm}
/>
<StyledIconChevronRightContainer>
<IconChevronRight
size={theme.icon.size.md}
stroke={theme.icon.stroke.sm}
/>
</StyledIconChevronRightContainer>
</UndecoratedLink>
) : (
canToggleField && (
@@ -273,7 +273,7 @@ export const SettingsObjectFieldItemTableRow = ({
onClick={handleToggleField}
/>
)}
</StyledIconTableCell>
</StyledObjectFieldTableRow>
</TableCell>
</TableRow>
);
};
@@ -5,10 +5,11 @@ import { useLingui } from '@lingui/react/macro';
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { isHiddenSystemField } from '@/object-metadata/utils/isHiddenSystemField';
import { SettingsItemTypeTag } from '@/settings/components/SettingsItemTypeTag';
import { TableRow } from '@/ui/layout/table/components/TableRow';
import {
SETTINGS_OBJECT_TABLE_ROW_GRID_TEMPLATE_COLUMNS,
StyledActionTableCell,
StyledNameTableCell,
StyledObjectTableRow,
} from '@/settings/data-model/object-details/components/SettingsObjectItemTableRowStyledComponents';
import { TableCell } from '@/ui/layout/table/components/TableCell';
import { useIcons } from 'twenty-ui/display';
@@ -63,7 +64,11 @@ export const SettingsObjectMetadataItemTableRow = ({
const Icon = getIcon(objectMetadataItem.icon);
return (
<StyledObjectTableRow key={objectMetadataItem.namePlural} to={link}>
<TableRow
gridTemplateColumns={SETTINGS_OBJECT_TABLE_ROW_GRID_TEMPLATE_COLUMNS}
key={objectMetadataItem.namePlural}
to={link}
>
<StyledNameTableCell>
{!!Icon && (
<Icon
@@ -95,6 +100,6 @@ export const SettingsObjectMetadataItemTableRow = ({
</TableCell>
<TableCell align="right">{totalObjectCount}</TableCell>
<StyledActionTableCell>{action}</StyledActionTableCell>
</StyledObjectTableRow>
</TableRow>
);
};
@@ -1,21 +0,0 @@
import { styled } from '@linaria/react';
import { TableCell } from '@/ui/layout/table/components/TableCell';
import { TableRow } from '@/ui/layout/table/components/TableRow';
import { themeCssVariables } from 'twenty-ui/theme-constants';
export const SETTINGS_OBJECT_TABLE_COLUMN_WIDTH = '98.7px';
export const StyledObjectTableRow = styled(TableRow)`
grid-template-columns: 180px ${SETTINGS_OBJECT_TABLE_COLUMN_WIDTH} ${SETTINGS_OBJECT_TABLE_COLUMN_WIDTH} ${SETTINGS_OBJECT_TABLE_COLUMN_WIDTH} 36px;
`;
export const StyledNameTableCell = styled(TableCell)`
color: ${themeCssVariables.font.color.primary};
gap: ${themeCssVariables.spacing[2]};
`;
export const StyledActionTableCell = styled(TableCell)`
justify-content: center;
padding-right: ${themeCssVariables.spacing[1]};
`;
@@ -0,0 +1,29 @@
import { TableCell } from '@/ui/layout/table/components/TableCell';
import { themeCssVariables } from 'twenty-ui/theme-constants';
import React from 'react';
export const SETTINGS_OBJECT_TABLE_COLUMN_WIDTH = '98.7px';
export const SETTINGS_OBJECT_TABLE_ROW_GRID_TEMPLATE_COLUMNS = `180px ${SETTINGS_OBJECT_TABLE_COLUMN_WIDTH} ${SETTINGS_OBJECT_TABLE_COLUMN_WIDTH} ${SETTINGS_OBJECT_TABLE_COLUMN_WIDTH} 36px`;
export const StyledNameTableCell = (
props: React.ComponentProps<typeof TableCell>,
) => (
<TableCell
color={themeCssVariables.font.color.primary}
gap={themeCssVariables.spacing[2]}
// eslint-disable-next-line react/jsx-props-no-spreading
{...props}
/>
);
export const StyledActionTableCell = (
props: React.ComponentProps<typeof TableCell>,
) => (
<TableCell
align="center"
padding={`0 ${themeCssVariables.spacing[1]} 0 ${themeCssVariables.spacing[2]}`}
// eslint-disable-next-line react/jsx-props-no-spreading
{...props}
/>
);
@@ -25,14 +25,8 @@ type SettingsObjectRelationItemTableRowProps = {
objectMetadataItem: ObjectMetadataItem;
};
export const StyledObjectRelationTableRow = styled(TableRow)`
grid-template-columns: minmax(0, 1fr) 148px 148px 36px;
`;
const StyledNameTableCell = styled(TableCell)`
color: ${themeCssVariables.font.color.primary};
gap: ${themeCssVariables.spacing[2]};
`;
export const OBJECT_RELATION_TABLE_ROW_GRID_TEMPLATE_COLUMNS =
'minmax(0, 1fr) 148px 148px 36px';
const StyledNameContainer = styled.div`
display: flex;
@@ -63,13 +57,10 @@ const StyledInactiveLabel = styled.span`
}
`;
const StyledIconTableCell = styled(TableCell)`
justify-content: center;
padding-right: ${themeCssVariables.spacing[1]};
`;
const StyledIconChevronRight = styled(IconChevronRight)`
const StyledIconChevronRightContainer = styled.span`
align-items: center;
color: ${themeCssVariables.font.color.tertiary};
display: flex;
`;
const StyledRelationType = styled.div`
@@ -79,18 +70,24 @@ const StyledRelationType = styled.div`
gap: ${themeCssVariables.spacing[1]};
`;
const StyledLink = styled(Link)`
color: ${themeCssVariables.font.color.primary};
text-decoration: underline;
text-decoration-color: ${themeCssVariables.border.color.strong};
text-underline-offset: 2px;
const StyledLinkContainer = styled.div`
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
&:hover {
color: ${themeCssVariables.color.blue};
text-decoration-color: ${themeCssVariables.color.blue};
> a {
color: ${themeCssVariables.font.color.primary};
text-decoration: underline;
text-decoration-color: ${themeCssVariables.border.color.strong};
text-underline-offset: 2px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
&:hover {
color: ${themeCssVariables.color.blue};
text-decoration-color: ${themeCssVariables.color.blue};
}
}
`;
@@ -157,9 +154,14 @@ export const SettingsObjectRelationItemTableRow = ({
: fieldMetadataItem.label;
return (
// eslint-disable-next-line twenty/no-navigate-prefer-link
<StyledObjectRelationTableRow onClick={navigateToFieldEdit}>
<StyledNameTableCell>
<TableRow
gridTemplateColumns={OBJECT_RELATION_TABLE_ROW_GRID_TEMPLATE_COLUMNS}
to={linkToNavigate}
>
<TableCell
color={themeCssVariables.font.color.primary}
gap={themeCssVariables.spacing[2]}
>
{!!Icon && (
<Icon
style={{
@@ -171,15 +173,17 @@ export const SettingsObjectRelationItemTableRow = ({
)}
<StyledNameContainer>
{isRelatedObjectLinkable ? (
<StyledLink
to={getSettingsPath(SettingsPath.ObjectDetail, {
objectNamePlural: relationObjectMetadataItem.namePlural,
})}
onClick={(event) => event.stopPropagation()}
title={targetObjectLabel}
>
{targetObjectLabel}
</StyledLink>
<StyledLinkContainer>
<Link
to={getSettingsPath(SettingsPath.ObjectDetail, {
objectNamePlural: relationObjectMetadataItem.namePlural,
})}
onClick={(event) => event.stopPropagation()}
title={targetObjectLabel}
>
{targetObjectLabel}
</Link>
</StyledLinkContainer>
) : (
<StyledNameLabel title={targetObjectLabel}>
{targetObjectLabel}
@@ -189,7 +193,7 @@ export const SettingsObjectRelationItemTableRow = ({
<StyledInactiveLabel>{t`Deactivated`}</StyledInactiveLabel>
)}
</StyledNameContainer>
</StyledNameTableCell>
</TableCell>
<TableCell>
<SettingsItemTypeTag
@@ -213,13 +217,18 @@ export const SettingsObjectRelationItemTableRow = ({
</StyledRelationType>
</TableCell>
<StyledIconTableCell>
<TableCell
align="center"
padding={`0 ${themeCssVariables.spacing[1]} 0 ${themeCssVariables.spacing[2]}`}
>
{fieldMetadataItem.isActive ? (
<UndecoratedLink to={linkToNavigate}>
<StyledIconChevronRight
size={theme.icon.size.md}
stroke={theme.icon.stroke.sm}
/>
<StyledIconChevronRightContainer>
<IconChevronRight
size={theme.icon.size.md}
stroke={theme.icon.stroke.sm}
/>
</StyledIconChevronRightContainer>
</UndecoratedLink>
) : (
<SettingsObjectFieldInactiveActionDropdown
@@ -238,7 +247,7 @@ export const SettingsObjectRelationItemTableRow = ({
}
/>
)}
</StyledIconTableCell>
</StyledObjectRelationTableRow>
</TableCell>
</TableRow>
);
};
@@ -27,9 +27,10 @@ import { Button } from 'twenty-ui/input';
import { MenuItemToggle } from 'twenty-ui/navigation';
import { themeCssVariables } from 'twenty-ui/theme-constants';
import { normalizeSearchText } from '~/utils/normalizeSearchText';
import { TableRow } from '@/ui/layout/table/components/TableRow';
import {
OBJECT_RELATION_TABLE_ROW_GRID_TEMPLATE_COLUMNS,
SettingsObjectRelationItemTableRow,
StyledObjectRelationTableRow,
} from './SettingsObjectRelationItemTableRow';
const StyledSearchAndFilterContainer = styled.div`
@@ -39,7 +40,7 @@ const StyledSearchAndFilterContainer = styled.div`
width: 100%;
`;
const StyledSearchInput = styled(SettingsTextInput)`
const StyledSearchInputContainer = styled.div`
flex: 1;
`;
@@ -118,13 +119,15 @@ export const SettingsObjectRelationsTable = ({
return (
<>
<StyledSearchAndFilterContainer>
<StyledSearchInput
instanceId="object-relation-table-search"
LeftIcon={IconSearch}
placeholder={t`Search a field...`}
value={searchTerm}
onChange={setSearchTerm}
/>
<StyledSearchInputContainer>
<SettingsTextInput
instanceId="object-relation-table-search"
LeftIcon={IconSearch}
placeholder={t`Search a field...`}
value={searchTerm}
onChange={setSearchTerm}
/>
</StyledSearchInputContainer>
<Dropdown
dropdownId="settings-relations-filter-dropdown"
dropdownPlacement="bottom-end"
@@ -165,7 +168,9 @@ export const SettingsObjectRelationsTable = ({
/>
</StyledSearchAndFilterContainer>
<Table>
<StyledObjectRelationTableRow>
<TableRow
gridTemplateColumns={OBJECT_RELATION_TABLE_ROW_GRID_TEMPLATE_COLUMNS}
>
{tableMetadata.fields.map((item) => (
<SortableTableHeader
key={item.fieldName}
@@ -176,7 +181,7 @@ export const SettingsObjectRelationsTable = ({
/>
))}
<TableHeader></TableHeader>
</StyledObjectRelationTableRow>
</TableRow>
{filteredRelationFields.map((fieldMetadataItem) => (
<SettingsObjectRelationItemTableRow
key={fieldMetadataItem.id}
@@ -29,8 +29,10 @@ const StyledContentContainer = styled.div`
gap: ${themeCssVariables.spacing[8]};
`;
const StyledFormSection = styled(Section)`
padding-left: 0 !important;
const StyledFormSectionContainer = styled.div`
> * {
padding-left: 0 !important;
}
`;
const StyledDangerButtonsContainer = styled.div`
@@ -90,16 +92,18 @@ export const ObjectSettings = ({
return (
<StyledContentContainer>
<StyledFormSection>
<H2Title
title={t`About`}
description={t`Name in both singular (e.g., 'Invoice') and plural (e.g., 'Invoices') forms.`}
/>
<SettingsUpdateDataModelObjectAboutForm
objectMetadataItem={objectMetadataItem}
/>
</StyledFormSection>
<StyledFormSection>
<StyledFormSectionContainer>
<Section>
<H2Title
title={t`About`}
description={t`Name in both singular (e.g., 'Invoice') and plural (e.g., 'Invoices') forms.`}
/>
<SettingsUpdateDataModelObjectAboutForm
objectMetadataItem={objectMetadataItem}
/>
</Section>
</StyledFormSectionContainer>
<StyledFormSectionContainer>
<Section>
<H2Title
title={t`Options`}
@@ -109,9 +113,9 @@ export const ObjectSettings = ({
objectMetadataItem={objectMetadataItem}
/>
</Section>
</StyledFormSection>
</StyledFormSectionContainer>
{!isReadOnly && (
<StyledFormSection>
<StyledFormSectionContainer>
<Section>
<H2Title
title={t`Danger zone`}
@@ -136,7 +140,7 @@ export const ObjectSettings = ({
)}
</StyledDangerButtonsContainer>
</Section>
</StyledFormSection>
</StyledFormSectionContainer>
)}
<ConfirmationModal
modalInstanceId={DELETE_OBJECT_MODAL_ID}
@@ -6,12 +6,12 @@ import { SettingsPath } from 'twenty-shared/types';
import { getSettingsPath } from 'twenty-shared/utils';
import { IconEye } from 'twenty-ui/display';
import { FloatingButton } from 'twenty-ui/input';
import { Card } from 'twenty-ui/layout';
import DarkCoverImage from '@/settings/data-model/assets/cover-dark.png';
import LightCoverImage from '@/settings/data-model/assets/cover-light.png';
import { ThemeContext, themeCssVariables } from 'twenty-ui/theme-constants';
const StyledCoverImageContainer = styled(Card)`
const StyledCoverImageContainer = styled.div`
align-items: center;
background-size: cover;
border-radius: ${themeCssVariables.border.radius.md};
@@ -95,14 +95,16 @@ const StyledBannerText = styled.span`
flex: 1;
`;
const StyledConflictButton = styled(Button)`
border-color: ${themeCssVariables.color.blue};
color: ${themeCssVariables.color.blue};
&:hover {
background: ${themeCssVariables.accent.secondary};
}
&:focus-visible {
box-shadow: 0 0 0 3px ${themeCssVariables.accent.tertiary};
const StyledConflictButtonContainer = styled.div`
> button {
border-color: ${themeCssVariables.color.blue};
color: ${themeCssVariables.color.blue};
&:hover {
background: ${themeCssVariables.accent.secondary};
}
&:focus-visible {
box-shadow: 0 0 0 3px ${themeCssVariables.accent.tertiary};
}
}
`;
@@ -281,18 +283,20 @@ export const SettingsDataModelObjectAboutForm = ({
{t`An object with this name already exists`}
</StyledBannerText>
</StyledBannerContent>
<StyledConflictButton
size="small"
variant="secondary"
accent="blue"
title={t`Open`}
onClick={() =>
navigateSettings(SettingsPath.ObjectDetail, {
objectNamePlural:
conflictingObjectMetadataItem.namePlural,
})
}
/>
<StyledConflictButtonContainer>
<Button
size="small"
variant="secondary"
accent="blue"
title={t`Open`}
onClick={() =>
navigateSettings(SettingsPath.ObjectDetail, {
objectNamePlural:
conflictingObjectMetadataItem.namePlural,
})
}
/>
</StyledConflictButtonContainer>
</StyledConflictBanner>
)}
{[
@@ -15,18 +15,25 @@ type SettingsDataModelObjectSettingsFormCardProps = {
objectMetadataItem: ObjectMetadataItem;
};
const StyledTopCardContent = styled(CardContent)`
background-color: ${themeCssVariables.background.transparent.lighter};
const StyledTopCardContentContainer = styled.div`
> * {
background-color: ${themeCssVariables.background.transparent.lighter};
}
`;
const StyledObjectSummaryCard = styled(Card)`
border-radius: ${themeCssVariables.border.radius.md};
color: ${themeCssVariables.font.color.primary};
const StyledObjectSummaryCardContainer = styled.div`
max-width: 480px;
> * {
border-radius: ${themeCssVariables.border.radius.md};
color: ${themeCssVariables.font.color.primary};
}
`;
const StyledObjectSummaryCardContent = styled(CardContent)`
padding: ${themeCssVariables.spacing[2]};
const StyledObjectSummaryCardContentContainer = styled.div`
> * {
padding: ${themeCssVariables.spacing[2]};
}
`;
export const SettingsDataModelObjectSettingsFormCard = ({
@@ -42,26 +49,32 @@ export const SettingsDataModelObjectSettingsFormCard = ({
return (
<Card fullWidth>
<StyledTopCardContent divider>
<SettingsDataModelCardTitle>
<Trans>Preview</Trans>
</SettingsDataModelCardTitle>
{labelIdentifierFieldMetadataItem ? (
<SettingsDataModelFieldPreviewWidget
objectNameSingular={objectMetadataItem.nameSingular}
fieldMetadataItem={labelIdentifierFieldMetadataItem}
withFieldLabel={false}
/>
) : (
<StyledObjectSummaryCard>
<StyledObjectSummaryCardContent>
<SettingsDataModelObjectPreview
objectMetadataItems={[objectMetadataItem]}
/>
</StyledObjectSummaryCardContent>
</StyledObjectSummaryCard>
)}
</StyledTopCardContent>
<StyledTopCardContentContainer>
<CardContent divider>
<SettingsDataModelCardTitle>
<Trans>Preview</Trans>
</SettingsDataModelCardTitle>
{labelIdentifierFieldMetadataItem ? (
<SettingsDataModelFieldPreviewWidget
objectNameSingular={objectMetadataItem.nameSingular}
fieldMetadataItem={labelIdentifierFieldMetadataItem}
withFieldLabel={false}
/>
) : (
<StyledObjectSummaryCardContainer>
<Card>
<StyledObjectSummaryCardContentContainer>
<CardContent>
<SettingsDataModelObjectPreview
objectMetadataItems={[objectMetadataItem]}
/>
</CardContent>
</StyledObjectSummaryCardContentContainer>
</Card>
</StyledObjectSummaryCardContainer>
)}
</CardContent>
</StyledTopCardContentContainer>
<CardContent>
<SettingsDataModelObjectIdentifiersForm
objectMetadataItem={objectMetadataItem}