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:
+30
-25
@@ -6,23 +6,10 @@ import { StyledTableRow } from '@/settings/logic-functions/components/SettingsLo
|
||||
import { useContext } from 'react';
|
||||
import { ThemeContext, themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
|
||||
const StyledNameTableCell = styled(TableCell)`
|
||||
color: ${themeCssVariables.font.color.primary};
|
||||
gap: ${themeCssVariables.spacing[2]};
|
||||
`;
|
||||
|
||||
const StyledRuntimeTableCell = styled(TableCell)`
|
||||
color: ${themeCssVariables.font.color.secondary};
|
||||
gap: ${themeCssVariables.spacing[2]};
|
||||
`;
|
||||
|
||||
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 SettingsLogicFunctionsFieldItemTableRow = ({
|
||||
@@ -35,15 +22,33 @@ export const SettingsLogicFunctionsFieldItemTableRow = ({
|
||||
const { theme } = useContext(ThemeContext);
|
||||
return (
|
||||
<StyledTableRow to={to}>
|
||||
<StyledNameTableCell>{logicFunction.name}</StyledNameTableCell>
|
||||
<StyledNameTableCell></StyledNameTableCell>
|
||||
<StyledRuntimeTableCell>{logicFunction.runtime}</StyledRuntimeTableCell>
|
||||
<StyledIconTableCell>
|
||||
<StyledIconChevronRight
|
||||
size={theme.icon.size.md}
|
||||
stroke={theme.icon.stroke.sm}
|
||||
/>
|
||||
</StyledIconTableCell>
|
||||
<TableCell
|
||||
color={themeCssVariables.font.color.primary}
|
||||
gap={themeCssVariables.spacing[2]}
|
||||
>
|
||||
{logicFunction.name}
|
||||
</TableCell>
|
||||
<TableCell
|
||||
color={themeCssVariables.font.color.primary}
|
||||
gap={themeCssVariables.spacing[2]}
|
||||
></TableCell>
|
||||
<TableCell
|
||||
color={themeCssVariables.font.color.secondary}
|
||||
gap={themeCssVariables.spacing[2]}
|
||||
>
|
||||
{logicFunction.runtime}
|
||||
</TableCell>
|
||||
<TableCell
|
||||
align="center"
|
||||
padding={`0 ${themeCssVariables.spacing[1]} 0 ${themeCssVariables.spacing[2]}`}
|
||||
>
|
||||
<StyledIconChevronRightContainer>
|
||||
<IconChevronRight
|
||||
size={theme.icon.size.md}
|
||||
stroke={theme.icon.stroke.sm}
|
||||
/>
|
||||
</StyledIconChevronRightContainer>
|
||||
</TableCell>
|
||||
</StyledTableRow>
|
||||
);
|
||||
};
|
||||
|
||||
+25
-16
@@ -8,14 +8,21 @@ import { SettingsPath } from 'twenty-shared/types';
|
||||
import { getSettingsPath } from 'twenty-shared/utils';
|
||||
import { type LogicFunction } from '~/generated-metadata/graphql';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import React from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
|
||||
export const StyledTableRow = styled(TableRow)`
|
||||
grid-template-columns: 164px 1fr 96px 32px;
|
||||
`;
|
||||
export const StyledTableRow = (
|
||||
props: React.ComponentProps<typeof TableRow>,
|
||||
) => (
|
||||
<TableRow
|
||||
gridTemplateColumns="164px 1fr 96px 32px"
|
||||
// eslint-disable-next-line react/jsx-props-no-spreading
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
|
||||
const StyledTableBody = styled(TableBody)`
|
||||
const StyledTableBodyContainer = styled.div`
|
||||
border-bottom: 1px solid ${themeCssVariables.border.color.light};
|
||||
`;
|
||||
|
||||
@@ -40,18 +47,20 @@ export const SettingsLogicFunctionsTable = ({
|
||||
<TableHeader>{t`Runtime`}</TableHeader>
|
||||
<TableHeader></TableHeader>
|
||||
</StyledTableRow>
|
||||
<StyledTableBody>
|
||||
{logicFunctions.map((logicFunction: LogicFunction) => (
|
||||
<SettingsLogicFunctionsFieldItemTableRow
|
||||
key={logicFunction.id}
|
||||
logicFunction={logicFunction}
|
||||
to={getSettingsPath(SettingsPath.ApplicationLogicFunctionDetail, {
|
||||
applicationId,
|
||||
logicFunctionId: logicFunction.id,
|
||||
})}
|
||||
/>
|
||||
))}
|
||||
</StyledTableBody>
|
||||
<StyledTableBodyContainer>
|
||||
<TableBody>
|
||||
{logicFunctions.map((logicFunction: LogicFunction) => (
|
||||
<SettingsLogicFunctionsFieldItemTableRow
|
||||
key={logicFunction.id}
|
||||
logicFunction={logicFunction}
|
||||
to={getSettingsPath(SettingsPath.ApplicationLogicFunctionDetail, {
|
||||
applicationId,
|
||||
logicFunctionId: logicFunction.id,
|
||||
})}
|
||||
/>
|
||||
))}
|
||||
</TableBody>
|
||||
</StyledTableBodyContainer>
|
||||
</Table>
|
||||
);
|
||||
};
|
||||
|
||||
+12
-8
@@ -12,8 +12,10 @@ import { H2Title, IconPlayerPlay } from 'twenty-ui/display';
|
||||
import { Button, CoreEditorHeader } from 'twenty-ui/input';
|
||||
import { Section } from 'twenty-ui/layout';
|
||||
|
||||
const StyledTabList = styled(TabList)`
|
||||
border-bottom: none;
|
||||
const StyledTabListContainer = styled.div`
|
||||
> * {
|
||||
border-bottom: none;
|
||||
}
|
||||
`;
|
||||
|
||||
export const SettingsLogicFunctionCodeEditorTab = ({
|
||||
@@ -44,12 +46,14 @@ export const SettingsLogicFunctionCodeEditorTab = ({
|
||||
);
|
||||
|
||||
const HeaderTabList = (
|
||||
<StyledTabList
|
||||
tabs={files.map((file) => {
|
||||
return { id: file.path, title: file.path.split('/').at(-1) || '' };
|
||||
})}
|
||||
componentInstanceId={SETTINGS_LOGIC_FUNCTION_TAB_LIST_COMPONENT_ID}
|
||||
/>
|
||||
<StyledTabListContainer>
|
||||
<TabList
|
||||
tabs={files.map((file) => {
|
||||
return { id: file.path, title: file.path.split('/').at(-1) || '' };
|
||||
})}
|
||||
componentInstanceId={SETTINGS_LOGIC_FUNCTION_TAB_LIST_COMPONENT_ID}
|
||||
/>
|
||||
</StyledTabListContainer>
|
||||
);
|
||||
|
||||
return (
|
||||
|
||||
+17
-8
@@ -5,9 +5,8 @@ import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/Drop
|
||||
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
|
||||
import { TableCell } from '@/ui/layout/table/components/TableCell';
|
||||
import { TableRow } from '@/ui/layout/table/components/TableRow';
|
||||
import { styled } from '@linaria/react';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { useState } from 'react';
|
||||
import React, { useState } from 'react';
|
||||
import {
|
||||
IconCheck,
|
||||
IconDotsVertical,
|
||||
@@ -20,13 +19,23 @@ import { LightIconButton } from 'twenty-ui/input';
|
||||
import { MenuItem } from 'twenty-ui/navigation';
|
||||
import type { ApplicationVariable } from '~/generated-metadata/graphql';
|
||||
|
||||
const StyledEditModeTableRow = styled(TableRow)`
|
||||
grid-template-columns: 180px auto 56px;
|
||||
`;
|
||||
const StyledEditModeTableRow = (
|
||||
props: React.ComponentProps<typeof TableRow>,
|
||||
) => (
|
||||
<TableRow
|
||||
gridTemplateColumns="180px auto 56px"
|
||||
// eslint-disable-next-line react/jsx-props-no-spreading
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
|
||||
const StyledTableRow = styled(TableRow)`
|
||||
grid-template-columns: 180px 300px 32px;
|
||||
`;
|
||||
const StyledTableRow = (props: React.ComponentProps<typeof TableRow>) => (
|
||||
<TableRow
|
||||
gridTemplateColumns="180px 300px 32px"
|
||||
// eslint-disable-next-line react/jsx-props-no-spreading
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
|
||||
export const SettingsLogicFunctionTabEnvironmentVariableTableRow = ({
|
||||
envVariable,
|
||||
|
||||
+32
-23
@@ -14,18 +14,9 @@ import { Tag } from 'twenty-ui/components';
|
||||
import { type LogicFunction } from '~/generated-metadata/graphql';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
|
||||
export const StyledRouteTriggerTableRow = styled(TableRow)`
|
||||
grid-template-columns: 1fr 120px 120px;
|
||||
`;
|
||||
const ROUTE_TRIGGER_GRID_TEMPLATE_COLUMNS = '1fr 120px 120px';
|
||||
|
||||
const StyledTableCell = styled(TableCell)`
|
||||
color: ${themeCssVariables.font.color.tertiary};
|
||||
gap: ${themeCssVariables.spacing[2]};
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
`;
|
||||
|
||||
const StyledRouteTriggerTableHeaderRow = styled(StyledRouteTriggerTableRow)`
|
||||
const StyledRouteTriggerTableHeaderRowWrapper = styled.div`
|
||||
margin-bottom: ${themeCssVariables.spacing[2]};
|
||||
`;
|
||||
|
||||
@@ -119,26 +110,44 @@ export const SettingsLogicFunctionTriggersTab = ({
|
||||
description={t`Triggers the function with Http request`}
|
||||
/>
|
||||
<Table>
|
||||
<StyledRouteTriggerTableHeaderRow>
|
||||
<TableHeader>{t`Path`}</TableHeader>
|
||||
<TableHeader>{t`Method`}</TableHeader>
|
||||
<TableHeader>{t`Auth Required`}</TableHeader>
|
||||
</StyledRouteTriggerTableHeaderRow>
|
||||
<StyledRouteTriggerTableRow>
|
||||
<StyledTableCell>
|
||||
<StyledRouteTriggerTableHeaderRowWrapper>
|
||||
<TableRow
|
||||
gridTemplateColumns={ROUTE_TRIGGER_GRID_TEMPLATE_COLUMNS}
|
||||
>
|
||||
<TableHeader>{t`Path`}</TableHeader>
|
||||
<TableHeader>{t`Method`}</TableHeader>
|
||||
<TableHeader>{t`Auth Required`}</TableHeader>
|
||||
</TableRow>
|
||||
</StyledRouteTriggerTableHeaderRowWrapper>
|
||||
<TableRow gridTemplateColumns={ROUTE_TRIGGER_GRID_TEMPLATE_COLUMNS}>
|
||||
<TableCell
|
||||
color={themeCssVariables.font.color.tertiary}
|
||||
gap={themeCssVariables.spacing[2]}
|
||||
overflow="hidden"
|
||||
>
|
||||
<OverflowingTextWithTooltip
|
||||
text={`${REACT_APP_SERVER_BASE_URL}/s${routeTrigger.path}`}
|
||||
/>
|
||||
</StyledTableCell>
|
||||
<StyledTableCell>{routeTrigger.httpMethod}</StyledTableCell>
|
||||
<StyledTableCell>
|
||||
</TableCell>
|
||||
<TableCell
|
||||
color={themeCssVariables.font.color.tertiary}
|
||||
gap={themeCssVariables.spacing[2]}
|
||||
overflow="hidden"
|
||||
>
|
||||
{routeTrigger.httpMethod}
|
||||
</TableCell>
|
||||
<TableCell
|
||||
color={themeCssVariables.font.color.tertiary}
|
||||
gap={themeCssVariables.spacing[2]}
|
||||
overflow="hidden"
|
||||
>
|
||||
<Tag
|
||||
text={routeTrigger.isAuthRequired ? t`True` : t`False`}
|
||||
color={routeTrigger.isAuthRequired ? 'green' : 'orange'}
|
||||
weight="medium"
|
||||
/>
|
||||
</StyledTableCell>
|
||||
</StyledRouteTriggerTableRow>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</Table>
|
||||
</Section>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user