Complete linaria migration (#18361)
## Summary
Completes the migration of the frontend styling system from **Emotion**
(`@emotion/styled`, `@emotion/react`) to **Linaria** (`@linaria/react`,
`@linaria/core`), a zero-runtime CSS-in-JS library where styles are
extracted at build time.
This is the final step of the migration — all ~494 files across
`twenty-front`, `twenty-ui`, `twenty-website`, and `twenty-sdk` are now
fully converted.
## Changes
### Styling Migration (across ~480 component files)
- Replaced all `@emotion/styled` imports with `@linaria/react`
- Converted runtime theme access patterns (`({ theme }) => theme.x.y`)
to build-time `themeCssVariables` CSS custom properties
- Replaced `useTheme()` hook (from Emotion) with
`useContext(ThemeContext)` where runtime theme values are still needed
(e.g., passing colors to non-CSS props like icon components)
- Removed `@emotion/react` `css` helper usages in favor of Linaria
template literals
### Dependency & Configuration Changes
- **Removed**: `@emotion/react`, `@emotion/styled` from root
`package.json`
- **Added**: `@wyw-in-js/babel-preset`, `next-with-linaria` (for
twenty-website SSR support)
- Updated Nx generator defaults from `@emotion/styled` to
`@linaria/react` in `nx.json`
- Simplified `vite.config.ts` (removed Emotion-specific configuration)
- Updated `twenty-website/next.config.js` to use `next-with-linaria` for
SSR Linaria support
### Storybook & Testing
- Removed `ThemeProvider` from Emotion in Storybook previews
(`twenty-front`, `twenty-sdk`)
- Now relies solely on `ThemeContextProvider` for theme injection
### Documentation
- Removed the temporary `docs/emotion-to-linaria-migration-plan.md`
(migration complete)
- Updated `CLAUDE.md` and `README.md` to reflect Linaria as the styling
stack
- Updated frontend style guide docs across all locales
## How it works
Linaria extracts styles at build time via the `@wyw-in-js/vite` plugin.
All expressions in `styled` template literals must be **statically
evaluable** — no runtime theme objects or closures over component state.
- **Static styles** use `themeCssVariables` which map to CSS custom
properties (`var(--theme-color-x)`)
- **Runtime theme access** (for non-CSS use cases like icon `color`
props) uses `useContext(ThemeContext)` instead of Emotion's `useTheme()`
This commit is contained in:
+6
-5
@@ -1,11 +1,12 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { styled } from '@linaria/react';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
|
||||
const StyledTitle = styled.h3`
|
||||
color: ${({ theme }) => theme.font.color.extraLight};
|
||||
font-size: ${({ theme }) => theme.font.size.sm};
|
||||
font-weight: ${({ theme }) => theme.font.weight.medium};
|
||||
color: ${themeCssVariables.font.color.extraLight};
|
||||
font-size: ${themeCssVariables.font.size.sm};
|
||||
font-weight: ${themeCssVariables.font.weight.medium};
|
||||
margin: 0;
|
||||
margin-bottom: ${({ theme }) => theme.spacing(4)};
|
||||
margin-bottom: ${themeCssVariables.spacing[4]};
|
||||
`;
|
||||
|
||||
export { StyledTitle as SettingsDataModelCardTitle };
|
||||
|
||||
+14
-27
@@ -3,23 +3,25 @@ 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 { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { styled } from '@linaria/react';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { useContext } from 'react';
|
||||
import { useLocation, useParams, useSearchParams } from 'react-router-dom';
|
||||
import { SettingsPath } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { IconChevronDown } from 'twenty-ui/display';
|
||||
import { Button } from 'twenty-ui/input';
|
||||
import { MenuItem } from 'twenty-ui/navigation';
|
||||
import { ThemeContext } from 'twenty-ui/theme';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
import { useNavigateSettings } from '~/hooks/useNavigateSettings';
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
align-items: center;
|
||||
color: ${({ theme }) => theme.font.color.tertiary};
|
||||
color: ${themeCssVariables.font.color.tertiary};
|
||||
cursor: default;
|
||||
display: flex;
|
||||
font-size: ${({ theme }) => theme.font.size.md};
|
||||
font-size: ${themeCssVariables.font.size.md};
|
||||
`;
|
||||
|
||||
const StyledButtonContainer = styled.div`
|
||||
@@ -28,9 +30,9 @@ const StyledButtonContainer = styled.div`
|
||||
`;
|
||||
|
||||
const StyledDownChevron = styled(IconChevronDown)`
|
||||
color: ${({ theme }) => theme.font.color.primary};
|
||||
color: ${themeCssVariables.font.color.primary};
|
||||
position: absolute;
|
||||
right: ${({ theme }) => theme.spacing(1.5)};
|
||||
right: ${themeCssVariables.spacing['1.5']};
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
`;
|
||||
@@ -40,28 +42,13 @@ const StyledMenuItemWrapper = styled.div<{ disabled?: boolean }>`
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
const StyledMenuItem = styled(MenuItem)<{
|
||||
selected?: boolean;
|
||||
disabled?: boolean;
|
||||
}>`
|
||||
background: ${({ theme, selected }) =>
|
||||
selected ? theme.background.quaternary : 'transparent'};
|
||||
opacity: ${({ disabled }) => (disabled ? 0.5 : 1)};
|
||||
pointer-events: ${({ disabled }) => (disabled ? 'none' : 'auto')};
|
||||
|
||||
&:hover {
|
||||
background: ${({ theme, disabled }) =>
|
||||
disabled ? 'transparent' : theme.background.tertiary};
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledSpan = styled.span`
|
||||
margin-left: ${({ theme }) => theme.spacing(2)};
|
||||
margin-left: ${themeCssVariables.spacing[2]};
|
||||
`;
|
||||
|
||||
const StyledButton = styled(Button)`
|
||||
color: ${({ theme }) => theme.font.color.primary};
|
||||
padding-right: ${({ theme }) => theme.spacing(6)};
|
||||
color: ${themeCssVariables.font.color.primary};
|
||||
padding-right: ${themeCssVariables.spacing[6]};
|
||||
`;
|
||||
|
||||
export const SettingsDataModelNewFieldBreadcrumbDropDown = () => {
|
||||
@@ -71,7 +58,7 @@ export const SettingsDataModelNewFieldBreadcrumbDropDown = () => {
|
||||
const location = useLocation();
|
||||
const { objectNamePlural = '' } = useParams();
|
||||
const [searchParams] = useSearchParams();
|
||||
const theme = useTheme();
|
||||
const { theme } = useContext(ThemeContext);
|
||||
|
||||
const fieldType = searchParams.get('fieldType') as SettingsFieldType;
|
||||
const isConfigureStep = location.pathname.includes('/configure');
|
||||
@@ -113,14 +100,14 @@ export const SettingsDataModelNewFieldBreadcrumbDropDown = () => {
|
||||
<DropdownContent>
|
||||
<DropdownMenuItemsContainer>
|
||||
<StyledMenuItemWrapper>
|
||||
<StyledMenuItem
|
||||
<MenuItem
|
||||
text={t`1. Type`}
|
||||
onClick={() => handleClick('select')}
|
||||
selected={!isConfigureStep}
|
||||
/>
|
||||
</StyledMenuItemWrapper>
|
||||
<StyledMenuItemWrapper disabled={!isDefined(fieldType)}>
|
||||
<StyledMenuItem
|
||||
<MenuItem
|
||||
text={t`2. Configure`}
|
||||
onClick={() => handleClick('configure')}
|
||||
selected={isConfigureStep}
|
||||
|
||||
+3
-2
@@ -1,9 +1,10 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { styled } from '@linaria/react';
|
||||
import { type ReactNode } from 'react';
|
||||
|
||||
import { StyledFormCardTitle } from '@/settings/data-model/fields/components/StyledFormCardTitle';
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
import { Card, CardContent } from 'twenty-ui/layout';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
|
||||
type SettingsDataModelPreviewFormCardProps = {
|
||||
className?: string;
|
||||
@@ -13,7 +14,7 @@ type SettingsDataModelPreviewFormCardProps = {
|
||||
};
|
||||
|
||||
const StyledPreviewContainer = styled(CardContent)`
|
||||
background-color: ${({ theme }) => theme.background.transparent.lighter};
|
||||
background-color: ${themeCssVariables.background.transparent.lighter};
|
||||
`;
|
||||
|
||||
const StyledFormContainer = styled(CardContent)`
|
||||
|
||||
+6
-5
@@ -1,9 +1,10 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { styled } from '@linaria/react';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
|
||||
export const StyledFormCardTitle = styled.h3`
|
||||
color: ${({ theme }) => theme.font.color.extraLight};
|
||||
font-size: ${({ theme }) => theme.font.size.sm};
|
||||
font-weight: ${({ theme }) => theme.font.weight.medium};
|
||||
color: ${themeCssVariables.font.color.extraLight};
|
||||
font-size: ${themeCssVariables.font.size.sm};
|
||||
font-weight: ${themeCssVariables.font.weight.medium};
|
||||
margin: 0;
|
||||
margin-bottom: ${({ theme }) => theme.spacing(4)};
|
||||
margin-bottom: ${themeCssVariables.spacing[4]};
|
||||
`;
|
||||
|
||||
+10
-11
@@ -1,4 +1,4 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { styled } from '@linaria/react';
|
||||
import { Controller, useFormContext } from 'react-hook-form';
|
||||
import { type z } from 'zod';
|
||||
|
||||
@@ -11,8 +11,8 @@ import { DATABASE_IDENTIFIER_MAXIMUM_LENGTH } from '@/settings/data-model/consta
|
||||
import { getErrorMessageFromError } from '@/settings/data-model/fields/forms/utils/errorMessages';
|
||||
import { IconPicker } from '@/ui/input/components/IconPicker';
|
||||
import { SettingsTextInput } from '@/ui/input/components/SettingsTextInput';
|
||||
import { useTheme } from '@emotion/react';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { useContext } from 'react';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import {
|
||||
@@ -22,6 +22,8 @@ import {
|
||||
TooltipDelay,
|
||||
} from 'twenty-ui/display';
|
||||
import { Card } from 'twenty-ui/layout';
|
||||
import { ThemeContext } from 'twenty-ui/theme';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
import { computeMetadataNameFromLabel } from '~/pages/settings/data-model/utils/computeMetadataNameFromLabel';
|
||||
|
||||
export const settingsDataModelFieldIconLabelFormSchema = (
|
||||
@@ -48,26 +50,26 @@ type SettingsDataModelFieldIconLabelFormValues = z.infer<
|
||||
|
||||
const StyledInputsContainer = styled.div`
|
||||
display: flex;
|
||||
gap: ${({ theme }) => theme.spacing(2)};
|
||||
margin-bottom: ${({ theme }) => theme.spacing(1)};
|
||||
gap: ${themeCssVariables.spacing[2]};
|
||||
margin-bottom: ${themeCssVariables.spacing[1]};
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
const StyledAdvancedSettingsSectionInputWrapper = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: ${({ theme }) => theme.spacing(4)};
|
||||
gap: ${themeCssVariables.spacing[4]};
|
||||
width: 100%;
|
||||
flex: 1;
|
||||
`;
|
||||
|
||||
const StyledAdvancedSettingsOuterContainer = styled.div`
|
||||
padding-top: ${({ theme }) => theme.spacing(4)};
|
||||
padding-top: ${themeCssVariables.spacing[4]};
|
||||
`;
|
||||
|
||||
const StyledAdvancedSettingsContainer = styled.div`
|
||||
display: flex;
|
||||
gap: ${({ theme }) => theme.spacing(2)};
|
||||
gap: ${themeCssVariables.spacing[2]};
|
||||
position: relative;
|
||||
width: 100%;
|
||||
`;
|
||||
@@ -93,7 +95,7 @@ export const SettingsDataModelFieldIconLabelForm = ({
|
||||
trigger,
|
||||
} = useFormContext<SettingsDataModelFieldIconLabelFormValues>();
|
||||
|
||||
const theme = useTheme();
|
||||
const { theme } = useContext(ThemeContext);
|
||||
|
||||
const label = watch('label');
|
||||
|
||||
@@ -126,15 +128,12 @@ export const SettingsDataModelFieldIconLabelForm = ({
|
||||
const isCustomButNotRelationField =
|
||||
fieldMetadataItem?.isCustom === true && !isRelation;
|
||||
|
||||
// TODO: remove the custom RELATION edge case, this will result in canToggleSyncLabelWithName = isCustom
|
||||
const canToggleSyncLabelWithName =
|
||||
!isCreationMode && isCustomButNotRelationField;
|
||||
|
||||
// TODO: remove custom RELATION edge case, this will result in isNameEditEnabled = isCustom
|
||||
const isNameEditEnabled =
|
||||
isLabelSyncedWithName === false && isCustomButNotRelationField;
|
||||
|
||||
// TODO: remove custom RELATION edge case, this will result in isLabelEditEnabled = true
|
||||
const isLabelEditEnabled =
|
||||
isCreationMode ||
|
||||
(!isCreationMode &&
|
||||
|
||||
+7
-8
@@ -10,16 +10,17 @@ import { useSelectSettingsFormInitialValues } from '@/settings/data-model/fields
|
||||
import { type FieldType } from '@/settings/data-model/types/FieldType';
|
||||
import { type SettingsFieldType } from '@/settings/data-model/types/SettingsFieldType';
|
||||
import { SettingsTextInput } from '@/ui/input/components/SettingsTextInput';
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { styled } from '@linaria/react';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { Section } from '@react-email/components';
|
||||
import { useState } from 'react';
|
||||
import { useContext, useState } from 'react';
|
||||
import { Controller, useFormContext } from 'react-hook-form';
|
||||
import { SettingsPath } from 'twenty-shared/types';
|
||||
import { getSettingsPath } from 'twenty-shared/utils';
|
||||
import { H2Title, IconSearch } from 'twenty-ui/display';
|
||||
import { UndecoratedLink } from 'twenty-ui/navigation';
|
||||
import { ThemeContext } from 'twenty-ui/theme';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
||||
import { type SettingsDataModelFieldTypeFormValues } from '~/pages/settings/data-model/new-field/SettingsObjectNewFieldSelect';
|
||||
|
||||
@@ -43,7 +44,7 @@ const StyledTypeSelectContainer = styled.div`
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
display: flex;
|
||||
gap: ${({ theme }) => theme.spacing(2)};
|
||||
gap: ${themeCssVariables.spacing[2]};
|
||||
justify-content: flex-start;
|
||||
flex-wrap: wrap;
|
||||
width: 100%;
|
||||
@@ -53,7 +54,7 @@ const StyledCardContainer = styled.div`
|
||||
display: flex;
|
||||
|
||||
position: relative;
|
||||
width: calc(50% - ${({ theme }) => theme.spacing(1)});
|
||||
width: calc(50% - ${themeCssVariables.spacing[1]});
|
||||
`;
|
||||
|
||||
const StyledSearchInput = styled(SettingsTextInput)`
|
||||
@@ -64,7 +65,7 @@ export const SettingsObjectNewFieldSelector = ({
|
||||
excludedFieldTypes = [],
|
||||
objectNamePlural,
|
||||
}: SettingsObjectNewFieldSelectorProps) => {
|
||||
const theme = useTheme();
|
||||
const { theme } = useContext(ThemeContext);
|
||||
const { control, setValue } =
|
||||
useFormContext<SettingsDataModelFieldTypeFormValues>();
|
||||
const [searchQuery, setSearchQuery] = useState('');
|
||||
@@ -132,8 +133,6 @@ export const SettingsObjectNewFieldSelector = ({
|
||||
<StyledContainer>
|
||||
{fieldTypeConfigs
|
||||
.filter(([, config]) => config.category === category)
|
||||
// by default, we hide the relation type and create only the morph relation type
|
||||
// on submit the new field, we choose the relation type based on the amount of target object
|
||||
.filter(([key]) => key !== FieldMetadataType.RELATION)
|
||||
.map(
|
||||
([key, config]) =>
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { styled } from '@linaria/react';
|
||||
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
||||
|
||||
import { FormProviderDecorator } from '~/testing/decorators/FormProviderDecorator';
|
||||
|
||||
+3
-2
@@ -10,10 +10,11 @@ import { useDateSettingsFormInitialValues } from '@/settings/data-model/fields/f
|
||||
import { getDisplayFormatLabel } from '@/settings/data-model/fields/forms/date/utils/getDisplayFormatLabel';
|
||||
import { Select } from '@/ui/input/components/Select';
|
||||
import { SettingsTextInput } from '@/ui/input/components/SettingsTextInput';
|
||||
import styled from '@emotion/styled';
|
||||
import { styled } from '@linaria/react';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { IconSlash } from 'twenty-ui/display';
|
||||
import { AnimatedExpandableContainer } from 'twenty-ui/layout';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
|
||||
const fieldDateSettings = z.discriminatedUnion('displayFormat', [
|
||||
z.object({
|
||||
@@ -33,7 +34,7 @@ export const settingsDataModelFieldDateFormSchema = z.object({
|
||||
});
|
||||
|
||||
const StyledTextInput = styled(SettingsTextInput)`
|
||||
padding: ${({ theme }) => theme.spacing(4)};
|
||||
padding: ${themeCssVariables.spacing[4]};
|
||||
padding-top: 0;
|
||||
`;
|
||||
|
||||
|
||||
+9
-8
@@ -15,28 +15,29 @@ import { IconPicker } from '@/ui/input/components/IconPicker';
|
||||
import { Select } from '@/ui/input/components/Select';
|
||||
import { SettingsTextInput } from '@/ui/input/components/SettingsTextInput';
|
||||
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
|
||||
import styled from '@emotion/styled';
|
||||
import { styled } from '@linaria/react';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
import { RelationType } from '~/generated-metadata/graphql';
|
||||
|
||||
const StyledSelectsContainer = styled.div<{ isMobile: boolean }>`
|
||||
display: grid;
|
||||
gap: ${({ theme }) => theme.spacing(4)};
|
||||
gap: ${themeCssVariables.spacing[4]};
|
||||
grid-template-columns: ${({ isMobile }) => (isMobile ? '1fr' : '1fr 1fr')};
|
||||
margin-bottom: ${({ theme }) => theme.spacing(4)};
|
||||
margin-bottom: ${themeCssVariables.spacing[4]};
|
||||
`;
|
||||
const StyledInputsLabel = styled.span`
|
||||
color: ${({ theme }) => theme.font.color.light};
|
||||
color: ${themeCssVariables.font.color.light};
|
||||
display: block;
|
||||
font-size: ${({ theme }) => theme.font.size.xs};
|
||||
font-weight: ${({ theme }) => theme.font.weight.semiBold};
|
||||
margin-bottom: ${({ theme }) => theme.spacing(1)};
|
||||
font-size: ${themeCssVariables.font.size.xs};
|
||||
font-weight: ${themeCssVariables.font.weight.semiBold};
|
||||
margin-bottom: ${themeCssVariables.spacing[1]};
|
||||
`;
|
||||
|
||||
const StyledInputsContainer = styled.div`
|
||||
display: flex;
|
||||
gap: ${({ theme }) => theme.spacing(2)};
|
||||
gap: ${themeCssVariables.spacing[2]};
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { styled } from '@linaria/react';
|
||||
import { type ReactNode } from 'react';
|
||||
|
||||
const StyledPreviewContent = styled.div<{ isMobile: boolean }>`
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { styled } from '@linaria/react';
|
||||
|
||||
const StyledRelationImage = styled.img<{
|
||||
flip?: boolean;
|
||||
|
||||
+33
-31
@@ -1,4 +1,4 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { styled } from '@linaria/react';
|
||||
import { type DropResult } from '@hello-pangea/dnd';
|
||||
import { Controller, useFormContext } from 'react-hook-form';
|
||||
import { z } from 'zod';
|
||||
@@ -29,9 +29,8 @@ import { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/Gene
|
||||
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
|
||||
import { isAdvancedModeEnabledState } from '@/ui/navigation/navigation-drawer/states/isAdvancedModeEnabledState';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { useTheme } from '@emotion/react';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useContext, useEffect, useState } from 'react';
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import {
|
||||
@@ -44,6 +43,8 @@ import {
|
||||
import { LightButton, LightIconButton } from 'twenty-ui/input';
|
||||
import { CardContent, CardFooter } from 'twenty-ui/layout';
|
||||
import { MenuItem } from 'twenty-ui/navigation';
|
||||
import { ThemeContext } from 'twenty-ui/theme';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
import { SettingsDataModelFieldSelectFormOptionRow } from './SettingsDataModelFieldSelectFormOptionRow';
|
||||
|
||||
export const settingsDataModelFieldSelectFormSchema = z.object({
|
||||
@@ -75,29 +76,30 @@ const StyledOptionsLabel = styled.div<{
|
||||
isAdvancedModeEnabled: boolean;
|
||||
isBulkInputMode: boolean;
|
||||
}>`
|
||||
color: ${({ theme }) => theme.font.color.light};
|
||||
font-size: ${({ theme }) => theme.font.size.xs};
|
||||
font-weight: ${({ theme }) => theme.font.weight.semiBold};
|
||||
margin-bottom: ${({ theme }) => theme.spacing(1.5)};
|
||||
margin-top: ${({ theme }) => theme.spacing(1)};
|
||||
color: ${themeCssVariables.font.color.light};
|
||||
font-size: ${themeCssVariables.font.size.xs};
|
||||
font-weight: ${themeCssVariables.font.weight.semiBold};
|
||||
margin-bottom: ${themeCssVariables.spacing['1.5']};
|
||||
margin-top: ${themeCssVariables.spacing[1]};
|
||||
width: 100%;
|
||||
margin-left: ${({ theme, isAdvancedModeEnabled, isBulkInputMode }) =>
|
||||
theme.spacing(isAdvancedModeEnabled && !isBulkInputMode ? 10 : 0)};
|
||||
};
|
||||
margin-left: ${({ isAdvancedModeEnabled, isBulkInputMode }) =>
|
||||
isAdvancedModeEnabled && !isBulkInputMode
|
||||
? themeCssVariables.spacing[10]
|
||||
: themeCssVariables.spacing[0]};
|
||||
`;
|
||||
|
||||
const StyledApiKeyContainer = styled.div`
|
||||
display: flex;
|
||||
gap: ${({ theme }) => theme.spacing(2)};
|
||||
gap: ${themeCssVariables.spacing[2]};
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
const StyledApiKey = styled.span`
|
||||
color: ${({ theme }) => theme.font.color.light};
|
||||
font-size: ${({ theme }) => theme.font.size.xs};
|
||||
font-weight: ${({ theme }) => theme.font.weight.semiBold};
|
||||
margin-bottom: ${({ theme }) => theme.spacing(1.5)};
|
||||
margin-top: ${({ theme }) => theme.spacing(1)};
|
||||
color: ${themeCssVariables.font.color.light};
|
||||
font-size: ${themeCssVariables.font.size.xs};
|
||||
font-weight: ${themeCssVariables.font.weight.semiBold};
|
||||
margin-bottom: ${themeCssVariables.spacing['1.5']};
|
||||
margin-top: ${themeCssVariables.spacing[1]};
|
||||
width: 100%;
|
||||
|
||||
white-space: nowrap;
|
||||
@@ -111,20 +113,20 @@ const StyledLabelContainer = styled.div`
|
||||
|
||||
const StyledIconContainer = styled.div`
|
||||
align-items: center;
|
||||
border-right: 1px solid ${({ theme }) => theme.color.yellow};
|
||||
border-right: 1px solid ${themeCssVariables.color.yellow};
|
||||
display: flex;
|
||||
|
||||
margin-bottom: ${({ theme }) => theme.spacing(1.5)};
|
||||
margin-top: ${({ theme }) => theme.spacing(1)};
|
||||
margin-bottom: ${themeCssVariables.spacing['1.5']};
|
||||
margin-top: ${themeCssVariables.spacing[1]};
|
||||
`;
|
||||
|
||||
const StyledIconPoint = styled(IconPoint)`
|
||||
margin-right: ${({ theme }) => theme.spacing(0.5)};
|
||||
margin-right: ${themeCssVariables.spacing['0.5']};
|
||||
`;
|
||||
|
||||
const StyledFooter = styled(CardFooter)`
|
||||
background-color: ${({ theme }) => theme.background.secondary};
|
||||
padding: ${({ theme }) => theme.spacing(1)};
|
||||
background-color: ${themeCssVariables.background.secondary};
|
||||
padding: ${themeCssVariables.spacing[1]};
|
||||
`;
|
||||
|
||||
const StyledButton = styled(LightButton)`
|
||||
@@ -136,20 +138,20 @@ const StyledOptionsHeaderContainer = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: ${({ theme }) => theme.spacing(1.5)};
|
||||
margin-top: ${({ theme }) => theme.spacing(1)};
|
||||
margin-bottom: ${themeCssVariables.spacing['1.5']};
|
||||
margin-top: ${themeCssVariables.spacing[1]};
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
const StyledTextAreaContainer = styled.div`
|
||||
margin-bottom: ${({ theme }) => theme.spacing(2)};
|
||||
margin-bottom: ${themeCssVariables.spacing[2]};
|
||||
`;
|
||||
|
||||
const StyledHelpText = styled.div`
|
||||
color: ${({ theme }) => theme.font.color.light};
|
||||
font-size: ${({ theme }) => theme.font.size.xs};
|
||||
margin-top: ${({ theme }) => theme.spacing(1)};
|
||||
margin-bottom: ${({ theme }) => theme.spacing(2)};
|
||||
color: ${themeCssVariables.font.color.light};
|
||||
font-size: ${themeCssVariables.font.size.xs};
|
||||
margin-top: ${themeCssVariables.spacing[1]};
|
||||
margin-bottom: ${themeCssVariables.spacing[2]};
|
||||
`;
|
||||
|
||||
export const SettingsDataModelFieldSelectForm = ({
|
||||
@@ -300,7 +302,7 @@ export const SettingsDataModelFieldSelectForm = ({
|
||||
setFormValue('options', newOptions, { shouldDirty: true });
|
||||
};
|
||||
|
||||
const theme = useTheme();
|
||||
const { theme } = useContext(ThemeContext);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
+50
-44
@@ -6,8 +6,8 @@ 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 { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { useContext } from 'react';
|
||||
import { styled } from '@linaria/react';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import {
|
||||
ColorSample,
|
||||
@@ -23,7 +23,8 @@ import {
|
||||
MenuItem,
|
||||
MenuItemSelectColor,
|
||||
} from 'twenty-ui/navigation';
|
||||
import { MAIN_COLOR_NAMES } from 'twenty-ui/theme';
|
||||
import { MAIN_COLOR_NAMES, ThemeContext } from 'twenty-ui/theme';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
import { computeOptionValueFromLabel } from '~/pages/settings/data-model/utils/computeOptionValueFromLabel';
|
||||
|
||||
const useColorLabels = (): ColorLabels => ({
|
||||
@@ -70,24 +71,25 @@ type SettingsDataModelFieldSelectFormOptionRowProps = {
|
||||
const StyledRow = styled.div`
|
||||
align-items: center;
|
||||
display: flex;
|
||||
height: ${({ theme }) => theme.spacing(6)};
|
||||
padding: ${({ theme }) => theme.spacing(1.5)} 0;
|
||||
height: ${themeCssVariables.spacing[6]};
|
||||
padding: ${themeCssVariables.spacing['1.5']} 0;
|
||||
`;
|
||||
|
||||
const StyledColorSample = styled(ColorSample)`
|
||||
cursor: pointer;
|
||||
margin-top: ${({ theme }) => theme.spacing(1)};
|
||||
margin-bottom: ${({ theme }) => theme.spacing(1)};
|
||||
margin-top: ${themeCssVariables.spacing[1]};
|
||||
margin-bottom: ${themeCssVariables.spacing[1]};
|
||||
|
||||
margin-right: 14px;
|
||||
margin-left: 14px;
|
||||
`;
|
||||
|
||||
const StyledOptionInput = styled(SettingsTextInput)`Chip
|
||||
const StyledOptionInputContainer = styled.div`
|
||||
flex-grow: 1;
|
||||
width: 100%;
|
||||
|
||||
& input {
|
||||
height: ${({ theme }) => theme.spacing(6)};
|
||||
height: ${themeCssVariables.spacing[6]};
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -96,7 +98,7 @@ const StyledIconGripVertical = styled(IconGripVertical)`
|
||||
`;
|
||||
|
||||
const StyledLightIconButton = styled(LightIconButton)`
|
||||
margin-left: ${({ theme }) => theme.spacing(2)};
|
||||
margin-left: ${themeCssVariables.spacing[2]};
|
||||
`;
|
||||
|
||||
export const SettingsDataModelFieldSelectFormOptionRow = ({
|
||||
@@ -111,7 +113,7 @@ export const SettingsDataModelFieldSelectFormOptionRow = ({
|
||||
isNewRow,
|
||||
fieldIsNullable,
|
||||
}: SettingsDataModelFieldSelectFormOptionRowProps) => {
|
||||
const theme = useTheme();
|
||||
const { theme } = useContext(ThemeContext);
|
||||
const colorLabels = useColorLabels();
|
||||
const SELECT_COLOR_DROPDOWN_ID = `select-color-dropdown-${option.id}`;
|
||||
const SELECT_ACTIONS_DROPDOWN_ID = `select-actions-dropdown-${option.id}`;
|
||||
@@ -134,18 +136,20 @@ export const SettingsDataModelFieldSelectFormOptionRow = ({
|
||||
color={theme.font.color.extraLight}
|
||||
/>
|
||||
<AdvancedSettingsWrapper animationDimension="width" hideDot>
|
||||
<StyledOptionInput
|
||||
instanceId={`select-option-value-${option.id}`}
|
||||
value={option.value}
|
||||
onChange={(input) =>
|
||||
onChange({
|
||||
...option,
|
||||
value: computeOptionValueFromLabel(input),
|
||||
})
|
||||
}
|
||||
RightIcon={isDefault ? IconCheck : undefined}
|
||||
maxLength={OPTION_VALUE_MAXIMUM_LENGTH}
|
||||
/>
|
||||
<StyledOptionInputContainer>
|
||||
<SettingsTextInput
|
||||
instanceId={`select-option-value-${option.id}`}
|
||||
value={option.value}
|
||||
onChange={(input) =>
|
||||
onChange({
|
||||
...option,
|
||||
value: computeOptionValueFromLabel(input),
|
||||
})
|
||||
}
|
||||
RightIcon={isDefault ? IconCheck : undefined}
|
||||
maxLength={OPTION_VALUE_MAXIMUM_LENGTH}
|
||||
/>
|
||||
</StyledOptionInputContainer>
|
||||
</AdvancedSettingsWrapper>
|
||||
<Dropdown
|
||||
dropdownId={SELECT_COLOR_DROPDOWN_ID}
|
||||
@@ -170,27 +174,29 @@ export const SettingsDataModelFieldSelectFormOptionRow = ({
|
||||
</DropdownContent>
|
||||
}
|
||||
/>
|
||||
<StyledOptionInput
|
||||
instanceId={`select-option-label-${option.id}`}
|
||||
value={option.label}
|
||||
onChange={(label) => {
|
||||
const optionNameHasBeenEdited = !(
|
||||
option.value === computeOptionValueFromLabel(option.label)
|
||||
);
|
||||
onChange({
|
||||
...option,
|
||||
label,
|
||||
value: optionNameHasBeenEdited
|
||||
? option.value
|
||||
: computeOptionValueFromLabel(label),
|
||||
});
|
||||
}}
|
||||
RightIcon={isDefault ? IconCheck : undefined}
|
||||
maxLength={OPTION_VALUE_MAXIMUM_LENGTH}
|
||||
onInputEnter={handleInputEnter}
|
||||
autoFocusOnMount={isNewRow}
|
||||
autoSelectOnMount={isNewRow}
|
||||
/>
|
||||
<StyledOptionInputContainer>
|
||||
<SettingsTextInput
|
||||
instanceId={`select-option-label-${option.id}`}
|
||||
value={option.label}
|
||||
onChange={(label) => {
|
||||
const optionNameHasBeenEdited = !(
|
||||
option.value === computeOptionValueFromLabel(option.label)
|
||||
);
|
||||
onChange({
|
||||
...option,
|
||||
label,
|
||||
value: optionNameHasBeenEdited
|
||||
? option.value
|
||||
: computeOptionValueFromLabel(label),
|
||||
});
|
||||
}}
|
||||
RightIcon={isDefault ? IconCheck : undefined}
|
||||
maxLength={OPTION_VALUE_MAXIMUM_LENGTH}
|
||||
onInputEnter={handleInputEnter}
|
||||
autoFocusOnMount={isNewRow}
|
||||
autoSelectOnMount={isNewRow}
|
||||
/>
|
||||
</StyledOptionInputContainer>
|
||||
<Dropdown
|
||||
dropdownId={SELECT_ACTIONS_DROPDOWN_ID}
|
||||
dropdownPlacement="right-start"
|
||||
|
||||
+16
-13
@@ -1,5 +1,5 @@
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { useContext } from 'react';
|
||||
import { styled } from '@linaria/react';
|
||||
|
||||
import { useLabelIdentifierFieldMetadataItem } from '@/object-metadata/hooks/useLabelIdentifierFieldMetadataItem';
|
||||
import { type FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
|
||||
@@ -13,6 +13,8 @@ import { SettingsDataModelSetFieldValueEffect } from '@/settings/data-model/fiel
|
||||
import { SettingsDataModelSetLabelIdentifierRecordEffect } from '@/settings/data-model/fields/preview/components/SettingsDataModelSetLabelIdentifierRecordEffect';
|
||||
import { useFieldPreviewValue } from '@/settings/data-model/fields/preview/hooks/useFieldPreviewValue';
|
||||
import { useIcons } from 'twenty-ui/display';
|
||||
import { ThemeContext } from 'twenty-ui/theme';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
||||
|
||||
type SettingsDataModelFieldPreviewProps = {
|
||||
@@ -27,27 +29,28 @@ type SettingsDataModelFieldPreviewProps = {
|
||||
|
||||
const StyledFieldPreview = styled.div<{ shrink?: boolean }>`
|
||||
align-items: center;
|
||||
background-color: ${({ theme }) => theme.background.primary};
|
||||
border: 1px solid ${({ theme }) => theme.border.color.medium};
|
||||
border-radius: ${({ theme }) => theme.border.radius.sm};
|
||||
background-color: ${themeCssVariables.background.primary};
|
||||
border: 1px solid ${themeCssVariables.border.color.medium};
|
||||
border-radius: ${themeCssVariables.border.radius.sm};
|
||||
display: flex;
|
||||
gap: ${({ theme }) => theme.spacing(2)};
|
||||
gap: ${themeCssVariables.spacing[2]};
|
||||
height: fit-content;
|
||||
line-height: 24px;
|
||||
overflow: hidden;
|
||||
padding: 0
|
||||
${({ shrink, theme }) => (shrink ? theme.spacing(1) : theme.spacing(2))};
|
||||
${({ shrink }) =>
|
||||
shrink ? themeCssVariables.spacing[1] : themeCssVariables.spacing[2]};
|
||||
white-space: nowrap;
|
||||
margin-top: ${({ theme }) => theme.spacing(2)};
|
||||
padding-top: ${({ theme }) => theme.spacing(2)};
|
||||
padding-bottom: ${({ theme }) => theme.spacing(2)};
|
||||
margin-top: ${themeCssVariables.spacing[2]};
|
||||
padding-top: ${themeCssVariables.spacing[2]};
|
||||
padding-bottom: ${themeCssVariables.spacing[2]};
|
||||
`;
|
||||
|
||||
const StyledFieldLabel = styled.div`
|
||||
align-items: center;
|
||||
color: ${({ theme }) => theme.font.color.tertiary};
|
||||
color: ${themeCssVariables.font.color.tertiary};
|
||||
display: flex;
|
||||
gap: ${({ theme }) => theme.spacing(1)};
|
||||
gap: ${themeCssVariables.spacing[1]};
|
||||
`;
|
||||
|
||||
export const SettingsDataModelFieldPreview = ({
|
||||
@@ -56,7 +59,7 @@ export const SettingsDataModelFieldPreview = ({
|
||||
shrink,
|
||||
withFieldLabel = true,
|
||||
}: SettingsDataModelFieldPreviewProps) => {
|
||||
const theme = useTheme();
|
||||
const { theme } = useContext(ThemeContext);
|
||||
const { labelIdentifierFieldMetadataItem } =
|
||||
useLabelIdentifierFieldMetadataItem({
|
||||
objectNameSingular: objectNameSingular,
|
||||
|
||||
+5
-4
@@ -1,10 +1,11 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { styled } from '@linaria/react';
|
||||
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { type FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
|
||||
import { SettingsDataModelFieldPreview } from '@/settings/data-model/fields/preview/components/SettingsDataModelFieldPreview';
|
||||
import { SettingsDataModelObjectPreview } from '@/settings/data-model/objects/components/SettingsDataModelObjectSummary';
|
||||
import { Card, CardContent } from 'twenty-ui/layout';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
import { computeMetadataNameFromLabel } from '~/pages/settings/data-model/utils/computeMetadataNameFromLabel';
|
||||
|
||||
type SettingsDataModelFieldPreviewWidgetProps = {
|
||||
@@ -21,12 +22,12 @@ type SettingsDataModelFieldPreviewWidgetProps = {
|
||||
};
|
||||
|
||||
const StyledCard = styled(Card)`
|
||||
border-radius: ${({ theme }) => theme.border.radius.md};
|
||||
color: ${({ theme }) => theme.font.color.primary};
|
||||
border-radius: ${themeCssVariables.border.radius.md};
|
||||
color: ${themeCssVariables.font.color.primary};
|
||||
`;
|
||||
|
||||
const StyledCardContent = styled(CardContent)`
|
||||
padding: ${({ theme }) => theme.spacing(2)};
|
||||
padding: ${themeCssVariables.spacing[2]};
|
||||
`;
|
||||
|
||||
export const SettingsDataModelFieldPreviewWidget = ({
|
||||
|
||||
+16
-13
@@ -1,5 +1,5 @@
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { useContext } from 'react';
|
||||
import { styled } from '@linaria/react';
|
||||
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
@@ -11,6 +11,8 @@ import { RecordFieldComponentInstanceContext } from '@/object-record/record-fiel
|
||||
import { SettingsDataModelSetFieldValueEffect } from '@/settings/data-model/fields/preview/components/SettingsDataModelSetFieldValueEffect';
|
||||
import { useFieldPreviewValue } from '@/settings/data-model/fields/preview/hooks/useFieldPreviewValue';
|
||||
import { useIcons } from 'twenty-ui/display';
|
||||
import { ThemeContext } from 'twenty-ui/theme';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
import { v4 } from 'uuid';
|
||||
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
||||
|
||||
@@ -26,27 +28,28 @@ type SettingsDataModelRelationFieldPreviewProps = {
|
||||
|
||||
const StyledFieldPreview = styled.div<{ shrink?: boolean }>`
|
||||
align-items: center;
|
||||
background-color: ${({ theme }) => theme.background.primary};
|
||||
border: 1px solid ${({ theme }) => theme.border.color.medium};
|
||||
border-radius: ${({ theme }) => theme.border.radius.sm};
|
||||
background-color: ${themeCssVariables.background.primary};
|
||||
border: 1px solid ${themeCssVariables.border.color.medium};
|
||||
border-radius: ${themeCssVariables.border.radius.sm};
|
||||
display: flex;
|
||||
gap: ${({ theme }) => theme.spacing(2)};
|
||||
gap: ${themeCssVariables.spacing[2]};
|
||||
height: fit-content;
|
||||
line-height: 24px;
|
||||
overflow: hidden;
|
||||
padding: 0
|
||||
${({ shrink, theme }) => (shrink ? theme.spacing(1) : theme.spacing(2))};
|
||||
${({ shrink }) =>
|
||||
shrink ? themeCssVariables.spacing[1] : themeCssVariables.spacing[2]};
|
||||
white-space: nowrap;
|
||||
margin-top: ${({ theme }) => theme.spacing(2)};
|
||||
padding-top: ${({ theme }) => theme.spacing(2)};
|
||||
padding-bottom: ${({ theme }) => theme.spacing(2)};
|
||||
margin-top: ${themeCssVariables.spacing[2]};
|
||||
padding-top: ${themeCssVariables.spacing[2]};
|
||||
padding-bottom: ${themeCssVariables.spacing[2]};
|
||||
`;
|
||||
|
||||
const StyledFieldLabel = styled.div`
|
||||
align-items: center;
|
||||
color: ${({ theme }) => theme.font.color.tertiary};
|
||||
color: ${themeCssVariables.font.color.tertiary};
|
||||
display: flex;
|
||||
gap: ${({ theme }) => theme.spacing(1)};
|
||||
gap: ${themeCssVariables.spacing[1]};
|
||||
`;
|
||||
|
||||
export const SettingsDataModelRelationFieldPreview = ({
|
||||
@@ -60,7 +63,7 @@ export const SettingsDataModelRelationFieldPreview = ({
|
||||
objectNameSingular: relationTargetObjectNameSingular,
|
||||
});
|
||||
|
||||
const theme = useTheme();
|
||||
const { theme } = useContext(ThemeContext);
|
||||
|
||||
const { getIcon } = useIcons();
|
||||
const FieldIcon = getIcon(fieldMetadataItem.icon);
|
||||
|
||||
+5
-4
@@ -1,4 +1,4 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { styled } from '@linaria/react';
|
||||
|
||||
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
|
||||
import { type FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
|
||||
@@ -6,6 +6,7 @@ import { SettingsDataModelRelationFieldPreview } from '@/settings/data-model/fie
|
||||
import { SettingsDataModelObjectPreview } from '@/settings/data-model/objects/components/SettingsDataModelObjectSummary';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { Card, CardContent } from 'twenty-ui/layout';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
|
||||
export type SettingsDataModelRelationFieldPreviewSubWidgetProps = {
|
||||
fieldMetadataItem: Pick<
|
||||
@@ -21,13 +22,13 @@ export type SettingsDataModelRelationFieldPreviewSubWidgetProps = {
|
||||
};
|
||||
|
||||
const StyledCard = styled(Card)`
|
||||
border-radius: ${({ theme }) => theme.border.radius.md};
|
||||
color: ${({ theme }) => theme.font.color.primary};
|
||||
border-radius: ${themeCssVariables.border.radius.md};
|
||||
color: ${themeCssVariables.font.color.primary};
|
||||
margin: auto;
|
||||
`;
|
||||
|
||||
const StyledCardContent = styled(CardContent)`
|
||||
padding: ${({ theme }) => theme.spacing(2)};
|
||||
padding: ${themeCssVariables.spacing[2]};
|
||||
`;
|
||||
|
||||
export const SettingsDataModelRelationFieldPreviewSubWidget = ({
|
||||
|
||||
+4
-3
@@ -2,7 +2,7 @@ import { SettingsDataModelOverviewEffect } from '@/settings/data-model/graph-ove
|
||||
import { SettingsDataModelOverviewObject } from '@/settings/data-model/graph-overview/components/SettingsDataModelOverviewObject';
|
||||
import { SettingsDataModelOverviewRelationMarkers } from '@/settings/data-model/graph-overview/components/SettingsDataModelOverviewRelationMarkers';
|
||||
import { calculateHandlePosition } from '@/settings/data-model/graph-overview/utils/calculateHandlePosition';
|
||||
import styled from '@emotion/styled';
|
||||
import { styled } from '@linaria/react';
|
||||
import {
|
||||
Background,
|
||||
type Edge,
|
||||
@@ -31,6 +31,7 @@ import {
|
||||
IconX,
|
||||
} from 'twenty-ui/display';
|
||||
import { Button, IconButtonGroup } from 'twenty-ui/input';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
|
||||
const nodeTypes: NodeTypes = {
|
||||
object: SettingsDataModelOverviewObject,
|
||||
@@ -63,8 +64,8 @@ const StyledContainer = styled.div`
|
||||
|
||||
const StyledCloseButton = styled.div`
|
||||
position: absolute;
|
||||
top: ${({ theme }) => theme.spacing(3)};
|
||||
left: ${({ theme }) => theme.spacing(3)};
|
||||
top: ${themeCssVariables.spacing[3]};
|
||||
left: ${themeCssVariables.spacing[3]};
|
||||
z-index: 5;
|
||||
`;
|
||||
|
||||
|
||||
+3
-3
@@ -1,9 +1,9 @@
|
||||
import { useTheme } from '@emotion/react';
|
||||
import { type Edge, type Node } from '@xyflow/react';
|
||||
import { useEffect } from 'react';
|
||||
import { useContext, useEffect } from 'react';
|
||||
|
||||
import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { ThemeContext } from 'twenty-ui/theme';
|
||||
import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
|
||||
|
||||
type SettingsDataModelOverviewEffectProps = {
|
||||
@@ -15,7 +15,7 @@ export const SettingsDataModelOverviewEffect = ({
|
||||
setEdges,
|
||||
setNodes,
|
||||
}: SettingsDataModelOverviewEffectProps) => {
|
||||
const theme = useTheme();
|
||||
const { theme } = useContext(ThemeContext);
|
||||
const { activeNonSystemObjectMetadataItems: items } =
|
||||
useFilteredObjectMetadataItems();
|
||||
|
||||
|
||||
+8
-6
@@ -1,10 +1,12 @@
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { styled } from '@linaria/react';
|
||||
import { Handle, Position } from '@xyflow/react';
|
||||
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { type FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
|
||||
import { useContext } from 'react';
|
||||
import { useIcons } from 'twenty-ui/display';
|
||||
import { ThemeContext } from 'twenty-ui/theme';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
import { RelationType } from '~/generated-metadata/graphql';
|
||||
|
||||
type ObjectFieldRowProps = {
|
||||
@@ -14,20 +16,20 @@ type ObjectFieldRowProps = {
|
||||
const StyledRow = styled.div`
|
||||
align-items: center;
|
||||
display: flex;
|
||||
gap: ${({ theme }) => theme.spacing(2)};
|
||||
gap: ${themeCssVariables.spacing[2]};
|
||||
position: relative;
|
||||
width: 100%;
|
||||
padding: 0 ${({ theme }) => theme.spacing(2)};
|
||||
padding: 0 ${themeCssVariables.spacing[2]};
|
||||
`;
|
||||
|
||||
const StyledFieldName = styled.div`
|
||||
color: ${({ theme }) => theme.font.color.primary};
|
||||
color: ${themeCssVariables.font.color.primary};
|
||||
`;
|
||||
|
||||
export const ObjectFieldRow = ({ field }: ObjectFieldRowProps) => {
|
||||
const objectMetadataItems = useAtomStateValue(objectMetadataItemsState);
|
||||
const { getIcon } = useIcons();
|
||||
const theme = useTheme();
|
||||
const { theme } = useContext(ThemeContext);
|
||||
|
||||
const relatedObjectId = field.relation?.targetObjectMetadata.id;
|
||||
|
||||
|
||||
+8
-6
@@ -1,8 +1,10 @@
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { useContext } from 'react';
|
||||
import { styled } from '@linaria/react';
|
||||
|
||||
import { type FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
|
||||
import { useIcons } from 'twenty-ui/display';
|
||||
import { ThemeContext } from 'twenty-ui/theme';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
|
||||
type ObjectFieldRowWithoutRelationProps = {
|
||||
field: FieldMetadataItem;
|
||||
@@ -11,21 +13,21 @@ type ObjectFieldRowWithoutRelationProps = {
|
||||
const StyledRow = styled.div`
|
||||
align-items: center;
|
||||
display: flex;
|
||||
gap: ${({ theme }) => theme.spacing(2)};
|
||||
gap: ${themeCssVariables.spacing[2]};
|
||||
position: relative;
|
||||
width: 100%;
|
||||
padding: 0 ${({ theme }) => theme.spacing(2)};
|
||||
padding: 0 ${themeCssVariables.spacing[2]};
|
||||
`;
|
||||
|
||||
const StyledFieldName = styled.div`
|
||||
color: ${({ theme }) => theme.font.color.primary};
|
||||
color: ${themeCssVariables.font.color.primary};
|
||||
`;
|
||||
|
||||
export const ObjectFieldRowWithoutRelation = ({
|
||||
field,
|
||||
}: ObjectFieldRowWithoutRelationProps) => {
|
||||
const { getIcon } = useIcons();
|
||||
const theme = useTheme();
|
||||
const { theme } = useContext(ThemeContext);
|
||||
|
||||
const Icon = getIcon(field?.icon);
|
||||
|
||||
|
||||
+27
-27
@@ -1,5 +1,5 @@
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { useContext, useState } from 'react';
|
||||
import { styled } from '@linaria/react';
|
||||
import { type Node, type NodeProps } from '@xyflow/react';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
@@ -11,26 +11,27 @@ import { FieldMetadataType } from '~/generated-metadata/graphql';
|
||||
|
||||
import { ObjectFieldRowWithoutRelation } from '@/settings/data-model/graph-overview/components/SettingsDataModelOverviewFieldWithoutRelation';
|
||||
import '@xyflow/react/dist/style.css';
|
||||
import { useState } from 'react';
|
||||
import { SettingsPath } from 'twenty-shared/types';
|
||||
import { getSettingsPath } from 'twenty-shared/utils';
|
||||
import { IconChevronDown, IconChevronUp, useIcons } from 'twenty-ui/display';
|
||||
import { SettingsItemTypeTag } from '@/settings/components/SettingsItemTypeTag';
|
||||
import { ThemeContext } from 'twenty-ui/theme';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
|
||||
type SettingsDataModelOverviewObjectNode = Node<ObjectMetadataItem, 'object'>;
|
||||
type SettingsDataModelOverviewObjectProps =
|
||||
NodeProps<SettingsDataModelOverviewObjectNode>;
|
||||
|
||||
const StyledNode = styled.div`
|
||||
background-color: ${({ theme }) => theme.background.secondary};
|
||||
border-radius: ${({ theme }) => theme.border.radius.md};
|
||||
background-color: ${themeCssVariables.background.secondary};
|
||||
border-radius: ${themeCssVariables.border.radius.md};
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 220px;
|
||||
padding: ${({ theme }) => theme.spacing(2)};
|
||||
gap: ${({ theme }) => theme.spacing(2)};
|
||||
border: 1px solid ${({ theme }) => theme.border.color.medium};
|
||||
box-shadow: ${({ theme }) => theme.boxShadow.light};
|
||||
padding: ${themeCssVariables.spacing[2]};
|
||||
gap: ${themeCssVariables.spacing[2]};
|
||||
border: 1px solid ${themeCssVariables.border.color.medium};
|
||||
box-shadow: ${themeCssVariables.boxShadow.light};
|
||||
`;
|
||||
|
||||
const StyledHeader = styled.div`
|
||||
@@ -43,29 +44,28 @@ const StyledObjectName = styled.div`
|
||||
border: 0;
|
||||
border-radius: 4px 4px 0 0;
|
||||
display: flex;
|
||||
font-weight: ${({ theme }) => theme.font.weight.medium};
|
||||
gap: ${({ theme }) => theme.spacing(1)};
|
||||
font-weight: ${themeCssVariables.font.weight.medium};
|
||||
gap: ${themeCssVariables.spacing[1]};
|
||||
position: relative;
|
||||
text-align: center;
|
||||
`;
|
||||
|
||||
const StyledInnerCard = styled.div`
|
||||
border: 1px solid ${({ theme }) => theme.border.color.light};
|
||||
background-color: ${({ theme }) => theme.background.primary};
|
||||
border-radius: ${({ theme }) => theme.border.radius.sm};
|
||||
padding: ${({ theme }) => theme.spacing(2)} 0
|
||||
${({ theme }) => theme.spacing(2)} 0;
|
||||
border: 1px solid ${themeCssVariables.border.color.light};
|
||||
background-color: ${themeCssVariables.background.primary};
|
||||
border-radius: ${themeCssVariables.border.radius.sm};
|
||||
padding: ${themeCssVariables.spacing[2]} 0 ${themeCssVariables.spacing[2]} 0;
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
gap: ${({ theme }) => theme.spacing(0.5)};
|
||||
color: ${({ theme }) => theme.font.color.tertiary};
|
||||
gap: ${themeCssVariables.spacing['0.5']};
|
||||
color: ${themeCssVariables.font.color.tertiary};
|
||||
`;
|
||||
|
||||
const StyledCardRow = styled.div`
|
||||
align-items: center;
|
||||
display: flex;
|
||||
height: 24px;
|
||||
gap: ${({ theme }) => theme.spacing(1)};
|
||||
gap: ${themeCssVariables.spacing[1]};
|
||||
`;
|
||||
|
||||
const StyledCardRowOther = styled.div`
|
||||
@@ -73,36 +73,36 @@ const StyledCardRowOther = styled.div`
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
height: 24px;
|
||||
padding: 0 ${({ theme }) => theme.spacing(2)};
|
||||
gap: ${({ theme }) => theme.spacing(2)};
|
||||
padding: 0 ${themeCssVariables.spacing[2]};
|
||||
gap: ${themeCssVariables.spacing[2]};
|
||||
|
||||
&:hover {
|
||||
background-color: ${({ theme }) => theme.background.tertiary};
|
||||
background-color: ${themeCssVariables.background.tertiary};
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledCardRowText = styled.div``;
|
||||
|
||||
const StyledObjectInstanceCount = styled.div`
|
||||
color: ${({ theme }) => theme.font.color.tertiary};
|
||||
color: ${themeCssVariables.font.color.tertiary};
|
||||
`;
|
||||
|
||||
const StyledObjectLink = styled(Link)`
|
||||
align-items: center;
|
||||
display: flex;
|
||||
gap: ${({ theme }) => theme.spacing(1)};
|
||||
gap: ${themeCssVariables.spacing[1]};
|
||||
text-decoration: none;
|
||||
color: ${({ theme }) => theme.font.color.primary};
|
||||
color: ${themeCssVariables.font.color.primary};
|
||||
|
||||
&:hover {
|
||||
color: ${({ theme }) => theme.font.color.secondary};
|
||||
color: ${themeCssVariables.font.color.secondary};
|
||||
}
|
||||
`;
|
||||
|
||||
export const SettingsDataModelOverviewObject = ({
|
||||
data: objectMetadataItem,
|
||||
}: SettingsDataModelOverviewObjectProps) => {
|
||||
const theme = useTheme();
|
||||
const { theme } = useContext(ThemeContext);
|
||||
const { getIcon } = useIcons();
|
||||
const [otherFieldsExpanded, setOtherFieldsExpanded] = useState(false);
|
||||
|
||||
|
||||
+3
-2
@@ -1,7 +1,8 @@
|
||||
import { useTheme } from '@emotion/react';
|
||||
import { useContext } from 'react';
|
||||
import { ThemeContext } from 'twenty-ui/theme';
|
||||
|
||||
export const SettingsDataModelOverviewRelationMarkers = () => {
|
||||
const theme = useTheme();
|
||||
const { theme } = useContext(ThemeContext);
|
||||
return (
|
||||
<svg style={{ position: 'absolute', top: 0, left: 0 }}>
|
||||
<defs>
|
||||
|
||||
+8
-6
@@ -1,11 +1,13 @@
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { useContext } from 'react';
|
||||
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 { ThemeContext } from 'twenty-ui/theme';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
|
||||
type SettingsAvailableStandardObjectItemTableRowProps = {
|
||||
isSelected?: boolean;
|
||||
@@ -20,12 +22,12 @@ export const StyledAvailableStandardObjectTableRow = styled(TableRow)`
|
||||
const StyledCheckboxTableCell = styled(TableCell)`
|
||||
justify-content: center;
|
||||
padding: 0;
|
||||
padding-left: ${({ theme }) => theme.spacing(1)};
|
||||
padding-left: ${themeCssVariables.spacing[1]};
|
||||
`;
|
||||
|
||||
const StyledNameTableCell = styled(TableCell)`
|
||||
color: ${({ theme }) => theme.font.color.primary};
|
||||
gap: ${({ theme }) => theme.spacing(2)};
|
||||
color: ${themeCssVariables.font.color.primary};
|
||||
gap: ${themeCssVariables.spacing[2]};
|
||||
`;
|
||||
|
||||
const StyledDescription = styled.div`
|
||||
@@ -39,7 +41,7 @@ export const SettingsAvailableStandardObjectItemTableRow = ({
|
||||
objectItem,
|
||||
onClick,
|
||||
}: SettingsAvailableStandardObjectItemTableRowProps) => {
|
||||
const theme = useTheme();
|
||||
const { theme } = useContext(ThemeContext);
|
||||
|
||||
const { getIcon } = useIcons();
|
||||
const Icon = getIcon(objectItem.icon);
|
||||
|
||||
+29
-26
@@ -1,10 +1,12 @@
|
||||
import { css, useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { useContext } from 'react';
|
||||
import { styled } from '@linaria/react';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import { type SettingsFieldType } from '@/settings/data-model/types/SettingsFieldType';
|
||||
import { getSettingsFieldTypeConfig } from '@/settings/data-model/utils/getSettingsFieldTypeConfig';
|
||||
import { type IconComponent, IconTwentyStar } from 'twenty-ui/display';
|
||||
import { ThemeContext } from 'twenty-ui/theme';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
|
||||
type SettingsObjectFieldDataTypeProps = {
|
||||
to?: string;
|
||||
@@ -21,28 +23,26 @@ const StyledDataType = styled.div<{
|
||||
}>`
|
||||
align-items: center;
|
||||
border: 1px solid transparent;
|
||||
border-radius: ${({ theme }) => theme.border.radius.sm};
|
||||
border-radius: ${themeCssVariables.border.radius.sm};
|
||||
color: ${({ to }) =>
|
||||
to
|
||||
? themeCssVariables.font.color.secondary
|
||||
: themeCssVariables.font.color.primary};
|
||||
cursor: ${({ to }) => (to ? 'pointer' : 'default')};
|
||||
display: flex;
|
||||
font-size: ${({ theme }) => theme.font.size.sm};
|
||||
gap: ${({ theme }) => theme.spacing(2)};
|
||||
font-size: ${themeCssVariables.font.size.sm};
|
||||
gap: ${themeCssVariables.spacing[2]};
|
||||
height: 20px;
|
||||
overflow: hidden;
|
||||
text-decoration: none;
|
||||
|
||||
text-decoration: ${({ to }) => (to ? 'underline' : 'none')};
|
||||
user-select: none;
|
||||
|
||||
${({ to, theme }) =>
|
||||
to
|
||||
? css`
|
||||
cursor: pointer;
|
||||
color: ${theme.font.color.secondary};
|
||||
text-decoration: underline;
|
||||
|
||||
&:hover {
|
||||
color: ${theme.font.color.primary};
|
||||
}
|
||||
`
|
||||
: ''}
|
||||
&:hover {
|
||||
color: ${({ to }) =>
|
||||
to
|
||||
? themeCssVariables.font.color.primary
|
||||
: themeCssVariables.font.color.primary};
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledLabelContainer = styled.div`
|
||||
@@ -51,8 +51,13 @@ const StyledLabelContainer = styled.div`
|
||||
white-space: nowrap;
|
||||
`;
|
||||
|
||||
const StyledIconWrapper = styled.div`
|
||||
display: flex;
|
||||
flex: 1 0 auto;
|
||||
`;
|
||||
|
||||
const StyledSpan = styled.span`
|
||||
color: ${({ theme }) => theme.font.color.extraLight};
|
||||
color: ${themeCssVariables.font.color.extraLight};
|
||||
`;
|
||||
export const SettingsObjectFieldDataType = ({
|
||||
to,
|
||||
@@ -62,17 +67,13 @@ export const SettingsObjectFieldDataType = ({
|
||||
labelDetail,
|
||||
onClick,
|
||||
}: SettingsObjectFieldDataTypeProps) => {
|
||||
const theme = useTheme();
|
||||
const { theme } = useContext(ThemeContext);
|
||||
|
||||
const fieldTypeConfig = getSettingsFieldTypeConfig(value);
|
||||
const Icon: IconComponent =
|
||||
IconFromProps ?? fieldTypeConfig?.Icon ?? IconTwentyStar;
|
||||
const label = labelFromProps ?? fieldTypeConfig?.label;
|
||||
|
||||
const StyledIcon = styled(Icon)`
|
||||
flex: 1 0 auto;
|
||||
`;
|
||||
|
||||
return (
|
||||
<StyledDataType
|
||||
as={to ? Link : 'div'}
|
||||
@@ -80,7 +81,9 @@ export const SettingsObjectFieldDataType = ({
|
||||
value={value}
|
||||
onClick={onClick}
|
||||
>
|
||||
<StyledIcon size={theme.icon.size.sm} />
|
||||
<StyledIconWrapper>
|
||||
<Icon size={theme.icon.size.sm} />
|
||||
</StyledIconWrapper>
|
||||
<StyledLabelContainer>
|
||||
{label} <StyledSpan>{labelDetail && `· ${labelDetail}`}</StyledSpan>
|
||||
</StyledLabelContainer>
|
||||
|
||||
+13
-12
@@ -10,11 +10,10 @@ import { settingsObjectFieldsFamilyState } from '@/settings/data-model/object-de
|
||||
import { isFieldTypeSupportedInSettings } from '@/settings/data-model/utils/isFieldTypeSupportedInSettings';
|
||||
import { TableCell } from '@/ui/layout/table/components/TableCell';
|
||||
import { TableRow } from '@/ui/layout/table/components/TableRow';
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { useContext, useMemo } from 'react';
|
||||
import { styled } from '@linaria/react';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { useSetAtomFamilyState } from '@/ui/utilities/state/jotai/hooks/useSetAtomFamilyState';
|
||||
import { useMemo } from 'react';
|
||||
import { FieldMetadataType, SettingsPath } from 'twenty-shared/types';
|
||||
import { getSettingsPath, isDefined } from 'twenty-shared/utils';
|
||||
import {
|
||||
@@ -25,6 +24,8 @@ import {
|
||||
} from 'twenty-ui/display';
|
||||
import { LightIconButton } from 'twenty-ui/input';
|
||||
import { UndecoratedLink } from 'twenty-ui/navigation';
|
||||
import { ThemeContext } from 'twenty-ui/theme';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
import { RelationType } from '~/generated-metadata/graphql';
|
||||
import { useNavigateSettings } from '~/hooks/useNavigateSettings';
|
||||
import { type SettingsObjectDetailTableItem } from '~/pages/settings/data-model/types/SettingsObjectDetailTableItem';
|
||||
@@ -41,8 +42,8 @@ export const StyledObjectFieldTableRow = styled(TableRow)`
|
||||
`;
|
||||
|
||||
const StyledNameTableCell = styled(TableCell)`
|
||||
color: ${({ theme }) => theme.font.color.primary};
|
||||
gap: ${({ theme }) => theme.spacing(2)};
|
||||
color: ${themeCssVariables.font.color.primary};
|
||||
gap: ${themeCssVariables.spacing[2]};
|
||||
`;
|
||||
|
||||
const StyledNameContainer = styled.div`
|
||||
@@ -50,7 +51,7 @@ const StyledNameContainer = styled.div`
|
||||
align-items: center;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
gap: ${({ theme }) => theme.spacing(1)};
|
||||
gap: ${themeCssVariables.spacing[1]};
|
||||
`;
|
||||
|
||||
const StyledNameLabel = styled.div`
|
||||
@@ -60,8 +61,8 @@ const StyledNameLabel = styled.div`
|
||||
`;
|
||||
|
||||
const StyledInactiveLabel = styled.span`
|
||||
color: ${({ theme }) => theme.font.color.extraLight};
|
||||
font-size: ${({ theme }) => theme.font.size.sm};
|
||||
color: ${themeCssVariables.font.color.extraLight};
|
||||
font-size: ${themeCssVariables.font.size.sm};
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
@@ -70,17 +71,17 @@ const StyledInactiveLabel = styled.span`
|
||||
|
||||
&::before {
|
||||
content: '·';
|
||||
margin-right: ${({ theme }) => theme.spacing(1)};
|
||||
margin-right: ${themeCssVariables.spacing[1]};
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledIconTableCell = styled(TableCell)`
|
||||
justify-content: center;
|
||||
padding-right: ${({ theme }) => theme.spacing(1)};
|
||||
padding-right: ${themeCssVariables.spacing[1]};
|
||||
`;
|
||||
|
||||
const StyledIconChevronRight = styled(IconChevronRight)`
|
||||
color: ${({ theme }) => theme.font.color.tertiary};
|
||||
color: ${themeCssVariables.font.color.tertiary};
|
||||
`;
|
||||
|
||||
export const SettingsObjectFieldItemTableRow = ({
|
||||
@@ -98,7 +99,7 @@ export const SettingsObjectFieldItemTableRow = ({
|
||||
|
||||
const navigate = useNavigateSettings();
|
||||
|
||||
const theme = useTheme();
|
||||
const { theme } = useContext(ThemeContext);
|
||||
const { getIcon } = useIcons();
|
||||
const Icon = getIcon(fieldMetadataItem.icon);
|
||||
|
||||
|
||||
+9
-8
@@ -1,7 +1,6 @@
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { useContext, type ReactNode } from 'react';
|
||||
import { styled } from '@linaria/react';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { type ReactNode } from 'react';
|
||||
|
||||
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { isHiddenSystemField } from '@/object-metadata/utils/isHiddenSystemField';
|
||||
@@ -13,6 +12,8 @@ import {
|
||||
} from '@/settings/data-model/object-details/components/SettingsObjectItemTableRowStyledComponents';
|
||||
import { TableCell } from '@/ui/layout/table/components/TableCell';
|
||||
import { useIcons } from 'twenty-ui/display';
|
||||
import { ThemeContext } from 'twenty-ui/theme';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
|
||||
export type SettingsObjectMetadataItemTableRowProps = {
|
||||
action: ReactNode;
|
||||
@@ -26,7 +27,7 @@ const StyledNameContainer = styled.div`
|
||||
align-items: center;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
gap: ${({ theme }) => theme.spacing(1)};
|
||||
gap: ${themeCssVariables.spacing[1]};
|
||||
`;
|
||||
|
||||
const StyledNameLabel = styled.div`
|
||||
@@ -36,8 +37,8 @@ const StyledNameLabel = styled.div`
|
||||
`;
|
||||
|
||||
const StyledInactiveLabel = styled.span`
|
||||
color: ${({ theme }) => theme.font.color.extraLight};
|
||||
font-size: ${({ theme }) => theme.font.size.sm};
|
||||
color: ${themeCssVariables.font.color.extraLight};
|
||||
font-size: ${themeCssVariables.font.size.sm};
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
@@ -46,7 +47,7 @@ const StyledInactiveLabel = styled.span`
|
||||
|
||||
&::before {
|
||||
content: '·';
|
||||
margin-right: ${({ theme }) => theme.spacing(1)};
|
||||
margin-right: ${themeCssVariables.spacing[1]};
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -57,7 +58,7 @@ export const SettingsObjectMetadataItemTableRow = ({
|
||||
totalObjectCount,
|
||||
}: SettingsObjectMetadataItemTableRowProps) => {
|
||||
const { t } = useLingui();
|
||||
const theme = useTheme();
|
||||
const { theme } = useContext(ThemeContext);
|
||||
|
||||
const { getIcon } = useIcons();
|
||||
const Icon = getIcon(objectMetadataItem.icon);
|
||||
|
||||
+5
-4
@@ -1,7 +1,8 @@
|
||||
import styled from '@emotion/styled';
|
||||
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';
|
||||
|
||||
@@ -10,11 +11,11 @@ export const StyledObjectTableRow = styled(TableRow)`
|
||||
`;
|
||||
|
||||
export const StyledNameTableCell = styled(TableCell)`
|
||||
color: ${({ theme }) => theme.font.color.primary};
|
||||
gap: ${({ theme }) => theme.spacing(2)};
|
||||
color: ${themeCssVariables.font.color.primary};
|
||||
gap: ${themeCssVariables.spacing[2]};
|
||||
`;
|
||||
|
||||
export const StyledActionTableCell = styled(TableCell)`
|
||||
justify-content: center;
|
||||
padding-right: ${({ theme }) => theme.spacing(1)};
|
||||
padding-right: ${themeCssVariables.spacing[1]};
|
||||
`;
|
||||
|
||||
+19
-18
@@ -9,15 +9,16 @@ import { RELATION_TYPES } from '@/settings/data-model/constants/RelationTypes';
|
||||
import { SettingsObjectFieldInactiveActionDropdown } from '@/settings/data-model/object-details/components/SettingsObjectFieldDisabledActionDropdown';
|
||||
import { TableCell } from '@/ui/layout/table/components/TableCell';
|
||||
import { TableRow } from '@/ui/layout/table/components/TableRow';
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { styled } from '@linaria/react';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { useMemo } from 'react';
|
||||
import { useContext, useMemo } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { FieldMetadataType, SettingsPath } from 'twenty-shared/types';
|
||||
import { getSettingsPath, isDefined } from 'twenty-shared/utils';
|
||||
import { IconChevronRight, useIcons } from 'twenty-ui/display';
|
||||
import { UndecoratedLink } from 'twenty-ui/navigation';
|
||||
import { ThemeContext } from 'twenty-ui/theme';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
import { useNavigateSettings } from '~/hooks/useNavigateSettings';
|
||||
|
||||
type SettingsObjectRelationItemTableRowProps = {
|
||||
@@ -30,8 +31,8 @@ export const StyledObjectRelationTableRow = styled(TableRow)`
|
||||
`;
|
||||
|
||||
const StyledNameTableCell = styled(TableCell)`
|
||||
color: ${({ theme }) => theme.font.color.primary};
|
||||
gap: ${({ theme }) => theme.spacing(2)};
|
||||
color: ${themeCssVariables.font.color.primary};
|
||||
gap: ${themeCssVariables.spacing[2]};
|
||||
`;
|
||||
|
||||
const StyledNameContainer = styled.div`
|
||||
@@ -39,7 +40,7 @@ const StyledNameContainer = styled.div`
|
||||
align-items: center;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
gap: ${({ theme }) => theme.spacing(1)};
|
||||
gap: ${themeCssVariables.spacing[1]};
|
||||
`;
|
||||
|
||||
const StyledNameLabel = styled.div`
|
||||
@@ -49,8 +50,8 @@ const StyledNameLabel = styled.div`
|
||||
`;
|
||||
|
||||
const StyledInactiveLabel = styled.span`
|
||||
color: ${({ theme }) => theme.font.color.extraLight};
|
||||
font-size: ${({ theme }) => theme.font.size.sm};
|
||||
color: ${themeCssVariables.font.color.extraLight};
|
||||
font-size: ${themeCssVariables.font.size.sm};
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
@@ -59,38 +60,38 @@ const StyledInactiveLabel = styled.span`
|
||||
|
||||
&::before {
|
||||
content: '·';
|
||||
margin-right: ${({ theme }) => theme.spacing(1)};
|
||||
margin-right: ${themeCssVariables.spacing[1]};
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledIconTableCell = styled(TableCell)`
|
||||
justify-content: center;
|
||||
padding-right: ${({ theme }) => theme.spacing(1)};
|
||||
padding-right: ${themeCssVariables.spacing[1]};
|
||||
`;
|
||||
|
||||
const StyledIconChevronRight = styled(IconChevronRight)`
|
||||
color: ${({ theme }) => theme.font.color.tertiary};
|
||||
color: ${themeCssVariables.font.color.tertiary};
|
||||
`;
|
||||
|
||||
const StyledRelationType = styled.div`
|
||||
align-items: center;
|
||||
display: flex;
|
||||
font-size: ${({ theme }) => theme.font.size.sm};
|
||||
gap: ${({ theme }) => theme.spacing(1)};
|
||||
font-size: ${themeCssVariables.font.size.sm};
|
||||
gap: ${themeCssVariables.spacing[1]};
|
||||
`;
|
||||
|
||||
const StyledLink = styled(Link)`
|
||||
color: ${({ theme }) => theme.font.color.primary};
|
||||
color: ${themeCssVariables.font.color.primary};
|
||||
text-decoration: underline;
|
||||
text-decoration-color: ${({ theme }) => theme.border.color.strong};
|
||||
text-decoration-color: ${themeCssVariables.border.color.strong};
|
||||
text-underline-offset: 2px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
|
||||
&:hover {
|
||||
color: ${({ theme }) => theme.color.blue};
|
||||
text-decoration-color: ${({ theme }) => theme.color.blue};
|
||||
color: ${themeCssVariables.color.blue};
|
||||
text-decoration-color: ${themeCssVariables.color.blue};
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -100,7 +101,7 @@ export const SettingsObjectRelationItemTableRow = ({
|
||||
}: SettingsObjectRelationItemTableRowProps) => {
|
||||
const { t } = useLingui();
|
||||
const navigate = useNavigateSettings();
|
||||
const theme = useTheme();
|
||||
const { theme } = useContext(ThemeContext);
|
||||
const { getIcon } = useIcons();
|
||||
|
||||
const Icon = getIcon(fieldMetadataItem.icon);
|
||||
|
||||
+4
-3
@@ -12,7 +12,7 @@ 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 styled from '@emotion/styled';
|
||||
import { styled } from '@linaria/react';
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { useMemo, useState } from 'react';
|
||||
@@ -25,6 +25,7 @@ import {
|
||||
} from 'twenty-ui/display';
|
||||
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 {
|
||||
SettingsObjectRelationItemTableRow,
|
||||
@@ -33,8 +34,8 @@ import {
|
||||
|
||||
const StyledSearchAndFilterContainer = styled.div`
|
||||
display: flex;
|
||||
gap: ${({ theme }) => theme.spacing(2)};
|
||||
padding-bottom: ${({ theme }) => theme.spacing(2)};
|
||||
gap: ${themeCssVariables.spacing[2]};
|
||||
padding-bottom: ${themeCssVariables.spacing[2]};
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
|
||||
+3
-2
@@ -2,7 +2,7 @@ import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataI
|
||||
import { isHiddenSystemField } from '@/object-metadata/utils/isHiddenSystemField';
|
||||
import { isObjectMetadataReadOnly } from '@/object-record/read-only/utils/isObjectMetadataReadOnly';
|
||||
import { SettingsObjectRelationsTable } from '@/settings/data-model/object-details/components/SettingsObjectRelationsTable';
|
||||
import styled from '@emotion/styled';
|
||||
import { styled } from '@linaria/react';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { FieldMetadataType, SettingsPath } from 'twenty-shared/types';
|
||||
import { getSettingsPath } from 'twenty-shared/utils';
|
||||
@@ -10,12 +10,13 @@ import { H2Title, IconPlus } from 'twenty-ui/display';
|
||||
import { Button } from 'twenty-ui/input';
|
||||
import { Section } from 'twenty-ui/layout';
|
||||
import { UndecoratedLink } from 'twenty-ui/navigation';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
import { SettingsObjectFieldTable } from '~/pages/settings/data-model/SettingsObjectFieldTable';
|
||||
|
||||
const StyledButtonContainer = styled.div`
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
padding-top: ${({ theme }) => theme.spacing(2)};
|
||||
padding-top: ${themeCssVariables.spacing[2]};
|
||||
`;
|
||||
|
||||
type ObjectFieldsProps = {
|
||||
|
||||
+4
-3
@@ -8,12 +8,13 @@ import { SettingsDataModelObjectSettingsFormCard } from '@/settings/data-model/o
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal';
|
||||
import { useModal } from '@/ui/layout/modal/hooks/useModal';
|
||||
import styled from '@emotion/styled';
|
||||
import { styled } from '@linaria/react';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { SettingsPath } from 'twenty-shared/types';
|
||||
import { H2Title, IconArchive, IconTrash } from 'twenty-ui/display';
|
||||
import { Button } from 'twenty-ui/input';
|
||||
import { Section } from 'twenty-ui/layout';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
import { useNavigateSettings } from '~/hooks/useNavigateSettings';
|
||||
|
||||
type ObjectSettingsProps = {
|
||||
@@ -25,7 +26,7 @@ type ObjectSettingsProps = {
|
||||
const StyledContentContainer = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: ${({ theme }) => theme.spacing(8)};
|
||||
gap: ${themeCssVariables.spacing[8]};
|
||||
`;
|
||||
|
||||
const StyledFormSection = styled(Section)`
|
||||
@@ -34,7 +35,7 @@ const StyledFormSection = styled(Section)`
|
||||
|
||||
const StyledDangerButtonsContainer = styled.div`
|
||||
display: flex;
|
||||
gap: ${({ theme }) => theme.spacing(2)};
|
||||
gap: ${themeCssVariables.spacing[2]};
|
||||
`;
|
||||
|
||||
const DELETE_OBJECT_MODAL_ID = 'delete-object-confirmation-modal';
|
||||
|
||||
+13
-11
@@ -1,6 +1,6 @@
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { useContext } from 'react';
|
||||
import { styled } from '@linaria/react';
|
||||
|
||||
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import {
|
||||
@@ -9,6 +9,8 @@ import {
|
||||
useIcons,
|
||||
} from 'twenty-ui/display';
|
||||
import { SettingsItemTypeTag } from '@/settings/components/SettingsItemTypeTag';
|
||||
import { ThemeContext } from 'twenty-ui/theme';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
|
||||
export type SettingsDataModelObjectPreviewProps = {
|
||||
className?: string;
|
||||
@@ -27,17 +29,17 @@ const StyledObjectPreview = styled.div`
|
||||
|
||||
const StyledObjectName = styled.div`
|
||||
display: flex;
|
||||
gap: ${({ theme }) => theme.spacing(2)};
|
||||
gap: ${themeCssVariables.spacing[2]};
|
||||
max-width: 60%;
|
||||
`;
|
||||
|
||||
const StyledOverflowingTextWithTooltip = styled.div`
|
||||
color: ${({ theme }) => theme.font.color.tertiary};
|
||||
color: ${themeCssVariables.font.color.tertiary};
|
||||
`;
|
||||
|
||||
const StyledNumber = styled.div`
|
||||
color: ${({ theme }) => theme.font.color.tertiary};
|
||||
padding-right: ${({ theme }) => theme.spacing(2)};
|
||||
color: ${themeCssVariables.font.color.tertiary};
|
||||
padding-right: ${themeCssVariables.spacing[2]};
|
||||
`;
|
||||
|
||||
const StyledIconContainer = styled.div`
|
||||
@@ -46,10 +48,10 @@ const StyledIconContainer = styled.div`
|
||||
|
||||
const StyledSeparator = styled.div`
|
||||
align-self: stretch;
|
||||
background: ${({ theme }) => theme.background.quaternary};
|
||||
background: ${themeCssVariables.background.quaternary};
|
||||
height: 1px;
|
||||
margin-bottom: ${({ theme }) => theme.spacing(2)};
|
||||
margin-top: ${({ theme }) => theme.spacing(2)};
|
||||
margin-bottom: ${themeCssVariables.spacing[2]};
|
||||
margin-top: ${themeCssVariables.spacing[2]};
|
||||
`;
|
||||
|
||||
type SettingsDataModelObjectPreviewItemProps = {
|
||||
@@ -66,7 +68,7 @@ const SettingsDataModelObjectPreviewItem = ({
|
||||
pluralizeLabel = true,
|
||||
index,
|
||||
}: SettingsDataModelObjectPreviewItemProps) => {
|
||||
const theme = useTheme();
|
||||
const { theme } = useContext(ThemeContext);
|
||||
const { getIcon } = useIcons();
|
||||
const ObjectIcon = getIcon(objectMetadataItem.icon);
|
||||
|
||||
@@ -100,7 +102,7 @@ const SettingsDataModelObjectPreviewOtherObjects = ({
|
||||
}: {
|
||||
selected: number;
|
||||
}) => {
|
||||
const theme = useTheme();
|
||||
const { theme } = useContext(ThemeContext);
|
||||
return (
|
||||
<>
|
||||
<StyledSeparator />
|
||||
|
||||
+16
-9
@@ -1,6 +1,7 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { styled } from '@linaria/react';
|
||||
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { useContext } from 'react';
|
||||
import { SettingsPath } from 'twenty-shared/types';
|
||||
import { getSettingsPath } from 'twenty-shared/utils';
|
||||
import { IconEye } from 'twenty-ui/display';
|
||||
@@ -9,30 +10,36 @@ 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 } from 'twenty-ui/theme';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
|
||||
const StyledCoverImageContainer = styled(Card)`
|
||||
align-items: center;
|
||||
background-image: ${({ theme }) =>
|
||||
theme.name === 'light'
|
||||
? `url('${LightCoverImage.toString()}')`
|
||||
: `url('${DarkCoverImage.toString()}')`};
|
||||
background-size: cover;
|
||||
border-radius: ${({ theme }) => theme.border.radius.md};
|
||||
border-radius: ${themeCssVariables.border.radius.md};
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
min-height: 153px;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
margin-bottom: ${({ theme }) => theme.spacing(8)};
|
||||
margin-bottom: ${themeCssVariables.spacing[8]};
|
||||
`;
|
||||
|
||||
const StyledButtonContainer = styled.div`
|
||||
padding-top: ${({ theme }) => theme.spacing(5)};
|
||||
padding-top: ${themeCssVariables.spacing[5]};
|
||||
`;
|
||||
export const SettingsObjectCoverImage = () => {
|
||||
const { t } = useLingui();
|
||||
const { theme } = useContext(ThemeContext);
|
||||
return (
|
||||
<StyledCoverImageContainer>
|
||||
<StyledCoverImageContainer
|
||||
style={{
|
||||
backgroundImage:
|
||||
theme.name === 'light'
|
||||
? `url('${LightCoverImage.toString()}')`
|
||||
: `url('${DarkCoverImage.toString()}')`,
|
||||
}}
|
||||
>
|
||||
<StyledButtonContainer>
|
||||
<FloatingButton
|
||||
Icon={IconEye}
|
||||
|
||||
+25
-23
@@ -6,8 +6,8 @@ import { type SettingsDataModelObjectAboutFormValues } from '@/settings/data-mod
|
||||
import { IconPicker } from '@/ui/input/components/IconPicker';
|
||||
import { SettingsTextInput } from '@/ui/input/components/SettingsTextInput';
|
||||
import { TextArea } from '@/ui/input/components/TextArea';
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { useContext } from 'react';
|
||||
import { styled } from '@linaria/react';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { plural } from 'pluralize';
|
||||
import { Controller, useFormContext } from 'react-hook-form';
|
||||
@@ -22,6 +22,8 @@ import {
|
||||
} from 'twenty-ui/display';
|
||||
import { Button } from 'twenty-ui/input';
|
||||
import { Card } from 'twenty-ui/layout';
|
||||
import { ThemeContext } from 'twenty-ui/theme';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
import { type StringKeyOf } from 'type-fest';
|
||||
import { useNavigateSettings } from '~/hooks/useNavigateSettings';
|
||||
import { computeMetadataNameFromLabel } from '~/pages/settings/data-model/utils/computeMetadataNameFromLabel';
|
||||
@@ -35,8 +37,8 @@ type SettingsDataModelObjectAboutFormProps = {
|
||||
|
||||
const StyledInputsContainer = styled.div`
|
||||
display: flex;
|
||||
gap: ${({ theme }) => theme.spacing(2)};
|
||||
margin-bottom: ${({ theme }) => theme.spacing(2)};
|
||||
gap: ${themeCssVariables.spacing[2]};
|
||||
margin-bottom: ${themeCssVariables.spacing[2]};
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
@@ -48,60 +50,60 @@ const StyledInputContainer = styled.div`
|
||||
const StyledAdvancedSettingsSectionInputWrapper = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: ${({ theme }) => theme.spacing(4)};
|
||||
gap: ${themeCssVariables.spacing[4]};
|
||||
width: 100%;
|
||||
flex: 1;
|
||||
`;
|
||||
|
||||
const StyledAdvancedSettingsOuterContainer = styled.div`
|
||||
padding-top: ${({ theme }) => theme.spacing(4)};
|
||||
padding-top: ${themeCssVariables.spacing[4]};
|
||||
`;
|
||||
|
||||
const StyledAdvancedSettingsContainer = styled.div`
|
||||
display: flex;
|
||||
gap: ${({ theme }) => theme.spacing(2)};
|
||||
gap: ${themeCssVariables.spacing[2]};
|
||||
position: relative;
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
const StyledLabel = styled.span`
|
||||
color: ${({ theme }) => theme.font.color.light};
|
||||
font-size: ${({ theme }) => theme.font.size.xs};
|
||||
font-weight: ${({ theme }) => theme.font.weight.semiBold};
|
||||
margin-bottom: ${({ theme }) => theme.spacing(1)};
|
||||
color: ${themeCssVariables.font.color.light};
|
||||
font-size: ${themeCssVariables.font.size.xs};
|
||||
font-weight: ${themeCssVariables.font.weight.semiBold};
|
||||
margin-bottom: ${themeCssVariables.spacing[1]};
|
||||
`;
|
||||
|
||||
const StyledConflictBanner = styled.div`
|
||||
align-items: center;
|
||||
background-color: ${({ theme }) => theme.accent.secondary};
|
||||
border-radius: ${({ theme }) => theme.border.radius.md};
|
||||
background-color: ${themeCssVariables.accent.secondary};
|
||||
border-radius: ${themeCssVariables.border.radius.md};
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
gap: ${({ theme }) => theme.spacing(2)};
|
||||
margin-bottom: ${({ theme }) => theme.spacing(2)};
|
||||
padding: ${({ theme }) => theme.spacing(2)};
|
||||
gap: ${themeCssVariables.spacing[2]};
|
||||
margin-bottom: ${themeCssVariables.spacing[2]};
|
||||
padding: ${themeCssVariables.spacing[2]};
|
||||
`;
|
||||
|
||||
const StyledBannerContent = styled.div`
|
||||
align-items: center;
|
||||
display: flex;
|
||||
gap: ${({ theme }) => theme.spacing(2)};
|
||||
gap: ${themeCssVariables.spacing[2]};
|
||||
flex: 1;
|
||||
`;
|
||||
|
||||
const StyledBannerText = styled.span`
|
||||
color: ${({ theme }) => theme.color.blue};
|
||||
color: ${themeCssVariables.color.blue};
|
||||
flex: 1;
|
||||
`;
|
||||
|
||||
const StyledConflictButton = styled(Button)`
|
||||
border-color: ${({ theme }) => theme.color.blue};
|
||||
color: ${({ theme }) => theme.color.blue};
|
||||
border-color: ${themeCssVariables.color.blue};
|
||||
color: ${themeCssVariables.color.blue};
|
||||
&:hover {
|
||||
background: ${({ theme }) => theme.accent.secondary};
|
||||
background: ${themeCssVariables.accent.secondary};
|
||||
}
|
||||
&:focus-visible {
|
||||
box-shadow: 0 0 0 3px ${({ theme }) => theme.accent.tertiary};
|
||||
box-shadow: 0 0 0 3px ${themeCssVariables.accent.tertiary};
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -116,7 +118,7 @@ export const SettingsDataModelObjectAboutForm = ({
|
||||
const { control, watch, setValue } =
|
||||
useFormContext<SettingsDataModelObjectAboutFormValues>();
|
||||
const { t } = useLingui();
|
||||
const theme = useTheme();
|
||||
const { theme } = useContext(ThemeContext);
|
||||
const navigateSettings = useNavigateSettings();
|
||||
|
||||
const isLabelSyncedWithName = watch('isLabelSyncedWithName');
|
||||
|
||||
+3
-2
@@ -4,7 +4,7 @@ import { getActiveFieldMetadataItems } from '@/object-metadata/utils/getActiveFi
|
||||
import { objectMetadataItemSchema } from '@/object-metadata/validation-schemas/objectMetadataItemSchema';
|
||||
import { isObjectMetadataReadOnly } from '@/object-record/read-only/utils/isObjectMetadataReadOnly';
|
||||
import { Select } from '@/ui/input/components/Select';
|
||||
import styled from '@emotion/styled';
|
||||
import { styled } from '@linaria/react';
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { useMemo } from 'react';
|
||||
@@ -13,6 +13,7 @@ import { useNavigate } from 'react-router-dom';
|
||||
import { isLabelIdentifierFieldMetadataTypes } from 'twenty-shared/utils';
|
||||
import { IconCircleOff, IconPlus, useIcons } from 'twenty-ui/display';
|
||||
import { type SelectOption } from 'twenty-ui/input';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
import { type z } from 'zod';
|
||||
|
||||
export const settingsDataModelObjectIdentifiersFormSchema =
|
||||
@@ -36,7 +37,7 @@ const IMAGE_IDENTIFIER_FIELD_METADATA_ID: SettingsDataModelObjectIdentifiers =
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
display: flex;
|
||||
gap: ${({ theme }) => theme.spacing(4)};
|
||||
gap: ${themeCssVariables.spacing[4]};
|
||||
`;
|
||||
|
||||
export const SettingsDataModelObjectIdentifiersForm = ({
|
||||
|
||||
+6
-5
@@ -1,4 +1,4 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { styled } from '@linaria/react';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
@@ -9,23 +9,24 @@ import { SettingsDataModelObjectPreview } from '@/settings/data-model/objects/co
|
||||
import { SettingsDataModelObjectIdentifiersForm } from '@/settings/data-model/objects/forms/components/SettingsDataModelObjectIdentifiersForm';
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
import { Card, CardContent } from 'twenty-ui/layout';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
|
||||
type SettingsDataModelObjectSettingsFormCardProps = {
|
||||
objectMetadataItem: ObjectMetadataItem;
|
||||
};
|
||||
|
||||
const StyledTopCardContent = styled(CardContent)`
|
||||
background-color: ${({ theme }) => theme.background.transparent.lighter};
|
||||
background-color: ${themeCssVariables.background.transparent.lighter};
|
||||
`;
|
||||
|
||||
const StyledObjectSummaryCard = styled(Card)`
|
||||
border-radius: ${({ theme }) => theme.border.radius.md};
|
||||
color: ${({ theme }) => theme.font.color.primary};
|
||||
border-radius: ${themeCssVariables.border.radius.md};
|
||||
color: ${themeCssVariables.font.color.primary};
|
||||
max-width: 480px;
|
||||
`;
|
||||
|
||||
const StyledObjectSummaryCardContent = styled(CardContent)`
|
||||
padding: ${({ theme }) => theme.spacing(2)};
|
||||
padding: ${themeCssVariables.spacing[2]};
|
||||
`;
|
||||
|
||||
export const SettingsDataModelObjectSettingsFormCard = ({
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { styled } from '@linaria/react';
|
||||
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
||||
import { FormProviderDecorator } from '~/testing/decorators/FormProviderDecorator';
|
||||
import { IconsProviderDecorator } from '~/testing/decorators/IconsProviderDecorator';
|
||||
|
||||
Reference in New Issue
Block a user