diff --git a/packages/twenty-front/src/modules/ui/input/components/ImageInput.tsx b/packages/twenty-front/src/modules/ui/input/components/ImageInput.tsx
index bbfe072272..d0fe1f8e84 100644
--- a/packages/twenty-front/src/modules/ui/input/components/ImageInput.tsx
+++ b/packages/twenty-front/src/modules/ui/input/components/ImageInput.tsx
@@ -44,17 +44,12 @@ const StyledPicture = styled.button<{ withPicture: boolean }>`
color: ${themeCssVariables.font.color.tertiary};
}
- ${({ withPicture, disabled }) => {
- if ((withPicture || disabled) === true) {
- return '';
- }
-
- return `
- &:hover {
- background: ${themeCssVariables.background.transparent.medium};
- }
- `;
- }};
+ &:hover {
+ background: ${({ withPicture, disabled }) =>
+ withPicture || disabled
+ ? 'transparent'
+ : themeCssVariables.background.transparent.medium};
+ }
`;
const StyledContent = styled.div`
diff --git a/packages/twenty-front/src/modules/ui/layout/dropdown/components/DropdownMenuInput.tsx b/packages/twenty-front/src/modules/ui/layout/dropdown/components/DropdownMenuInput.tsx
index 0303f62e4d..fcbd9e39ad 100644
--- a/packages/twenty-front/src/modules/ui/layout/dropdown/components/DropdownMenuInput.tsx
+++ b/packages/twenty-front/src/modules/ui/layout/dropdown/components/DropdownMenuInput.tsx
@@ -8,7 +8,6 @@ import {
import 'react-phone-number-input/style.css';
import { useRegisterInputEvents } from '@/object-record/record-field/ui/meta-types/input/hooks/useRegisterInputEvents';
-import { TEXT_INPUT_STYLE } from 'twenty-ui/theme';
import { useCombinedRefs } from '~/hooks/useCombinedRefs';
import { themeCssVariables } from 'twenty-ui/theme-constants';
@@ -16,7 +15,21 @@ const StyledInput = styled.input<{
withRightComponent?: boolean;
hasError?: boolean;
}>`
- ${TEXT_INPUT_STYLE}
+ background-color: transparent;
+ border: none;
+ color: ${themeCssVariables.font.color.primary};
+ font-family: ${themeCssVariables.font.family};
+ font-size: inherit;
+ font-weight: inherit;
+ outline: none;
+ padding: ${themeCssVariables.spacing[0]} ${themeCssVariables.spacing[2]};
+
+ &::placeholder,
+ &::-webkit-input-placeholder {
+ color: ${themeCssVariables.font.color.light};
+ font-family: ${themeCssVariables.font.family};
+ font-weight: ${themeCssVariables.font.weight.medium};
+ }
box-sizing: border-box;
font-weight: ${themeCssVariables.font.weight.medium};
diff --git a/packages/twenty-front/src/modules/ui/layout/dropdown/components/DropdownMenuSearchInput.tsx b/packages/twenty-front/src/modules/ui/layout/dropdown/components/DropdownMenuSearchInput.tsx
index ba51cb32ed..61463f5909 100644
--- a/packages/twenty-front/src/modules/ui/layout/dropdown/components/DropdownMenuSearchInput.tsx
+++ b/packages/twenty-front/src/modules/ui/layout/dropdown/components/DropdownMenuSearchInput.tsx
@@ -3,7 +3,6 @@ import { useLingui } from '@lingui/react/macro';
import { useInputFocusWithoutScrollOnMount } from '@/ui/input/hooks/useInputFocusWithoutScrollOnMount';
import { styled } from '@linaria/react';
import { forwardRef, type InputHTMLAttributes } from 'react';
-import { TEXT_INPUT_STYLE } from 'twenty-ui/theme';
import { themeCssVariables } from 'twenty-ui/theme-constants';
const StyledDropdownMenuSearchInputContainer = styled.div`
@@ -18,7 +17,21 @@ const StyledDropdownMenuSearchInputContainer = styled.div`
`;
const StyledInput = styled.input`
- ${TEXT_INPUT_STYLE}
+ background-color: transparent;
+ border: none;
+ color: ${themeCssVariables.font.color.primary};
+ font-family: ${themeCssVariables.font.family};
+ font-size: inherit;
+ font-weight: inherit;
+ outline: none;
+ padding: ${themeCssVariables.spacing[0]} ${themeCssVariables.spacing[2]};
+
+ &::placeholder,
+ &::-webkit-input-placeholder {
+ color: ${themeCssVariables.font.color.light};
+ font-family: ${themeCssVariables.font.family};
+ font-weight: ${themeCssVariables.font.weight.medium};
+ }
font-size: ${themeCssVariables.font.size.sm};
background-color: transparent;
diff --git a/packages/twenty-front/src/modules/ui/layout/fullscreen/components/FullScreenModal.tsx b/packages/twenty-front/src/modules/ui/layout/fullscreen/components/FullScreenModal.tsx
new file mode 100644
index 0000000000..2253ace892
--- /dev/null
+++ b/packages/twenty-front/src/modules/ui/layout/fullscreen/components/FullScreenModal.tsx
@@ -0,0 +1,71 @@
+import { RootStackingContextZIndices } from '@/ui/layout/constants/RootStackingContextZIndices';
+import { PageHeader } from '@/ui/layout/page/components/PageHeader';
+import {
+ Breadcrumb,
+ type BreadcrumbProps,
+} from '@/ui/navigation/bread-crumb/components/Breadcrumb';
+import { styled } from '@linaria/react';
+import { forwardRef } from 'react';
+import { themeCssVariables } from 'twenty-ui/theme-constants';
+
+const StyledFullScreenOverlay = styled.div`
+ background: ${themeCssVariables.background.noisy};
+ bottom: 0;
+ display: flex;
+ flex-direction: column;
+ height: 100vh;
+ left: 0;
+ position: fixed;
+ right: 0;
+ top: 0;
+ width: 100%;
+ z-index: ${RootStackingContextZIndices.RootModal};
+`;
+
+const StyledFullScreenHeader = styled(PageHeader)`
+ padding-left: ${themeCssVariables.spacing[3]};
+`;
+
+const StyledFullScreenContent = styled.div`
+ display: flex;
+ flex: 1;
+ flex-direction: column;
+ gap: ${themeCssVariables.spacing[3]};
+ min-height: 0;
+ padding: 0 ${themeCssVariables.spacing[3]} ${themeCssVariables.spacing[3]}
+ ${themeCssVariables.spacing[3]};
+
+ > * {
+ display: flex;
+ flex: 1;
+ flex-direction: column;
+ min-height: 0;
+ row-gap: ${themeCssVariables.spacing[5]};
+ }
+`;
+
+type FullScreenModalProps = {
+ children: React.ReactNode;
+ links: BreadcrumbProps['links'];
+ onClose: () => void;
+ hasClosePageButton?: boolean;
+};
+
+export const FullScreenModal = forwardRef
(
+ ({ children, links, onClose, hasClosePageButton = true }, ref) => {
+ return (
+
+ }
+ hasClosePageButton={hasClosePageButton}
+ onClosePage={onClose}
+ />
+ {children}
+
+ );
+ },
+);
diff --git a/packages/twenty-front/src/modules/ui/layout/fullscreen/hooks/useFullScreenModal.tsx b/packages/twenty-front/src/modules/ui/layout/fullscreen/hooks/useFullScreenModal.tsx
index df6338a0f4..5e1b83f154 100644
--- a/packages/twenty-front/src/modules/ui/layout/fullscreen/hooks/useFullScreenModal.tsx
+++ b/packages/twenty-front/src/modules/ui/layout/fullscreen/hooks/useFullScreenModal.tsx
@@ -1,51 +1,7 @@
-import { RootStackingContextZIndices } from '@/ui/layout/constants/RootStackingContextZIndices';
-import { PageHeader } from '@/ui/layout/page/components/PageHeader';
-import {
- Breadcrumb,
- type BreadcrumbProps,
-} from '@/ui/navigation/bread-crumb/components/Breadcrumb';
-import { styled } from '@linaria/react';
+import { FullScreenModal } from '@/ui/layout/fullscreen/components/FullScreenModal';
+import { type BreadcrumbProps } from '@/ui/navigation/bread-crumb/components/Breadcrumb';
import { useRef } from 'react';
import { createPortal } from 'react-dom';
-import { themeCssVariables } from 'twenty-ui/theme-constants';
-
-const StyledFullScreenOverlay = styled.div`
- position: fixed;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- background: ${themeCssVariables.background.noisy};
- display: flex;
- flex-direction: column;
- width: 100%;
- height: 100vh;
- z-index: ${RootStackingContextZIndices.RootModal};
-`;
-
-const StyledFullScreenHeader = styled(PageHeader)`
- padding-left: ${themeCssVariables.spacing[3]};
-`;
-
-const StyledFullScreenContent = styled.div`
- display: flex;
- flex-direction: column;
- gap: ${themeCssVariables.spacing[3]};
- flex: 1;
- min-height: 0;
- padding: 0 ${themeCssVariables.spacing[3]} ${themeCssVariables.spacing[3]}
- ${themeCssVariables.spacing[3]};
-
- // Make the immediate child a flex column that grows, so nested components
- // with height="100%" (e.g., editors) can size correctly.
- > * {
- display: flex;
- flex-direction: column;
- flex: 1;
- min-height: 0;
- row-gap: ${themeCssVariables.spacing[5]};
- }
-`;
type UseFullScreenModalProps = {
links: BreadcrumbProps['links'];
@@ -67,18 +23,14 @@ export const useFullScreenModal = ({
if (!isOpen) return null;
return createPortal(
-
- }
- hasClosePageButton={hasClosePageButton}
- onClosePage={onClose}
- />
- {children}
- ,
+ {children}
+ ,
document.body,
);
};
diff --git a/packages/twenty-front/src/modules/ui/layout/page/components/PageHeader.tsx b/packages/twenty-front/src/modules/ui/layout/page/components/PageHeader.tsx
index 7524c55783..b6c02cdd51 100644
--- a/packages/twenty-front/src/modules/ui/layout/page/components/PageHeader.tsx
+++ b/packages/twenty-front/src/modules/ui/layout/page/components/PageHeader.tsx
@@ -15,8 +15,8 @@ import {
OverflowingTextWithTooltip,
} from 'twenty-ui/display';
import { LightIconButton } from 'twenty-ui/input';
-import { MOBILE_VIEWPORT, ThemeContext } from 'twenty-ui/theme';
-import { themeCssVariables } from 'twenty-ui/theme-constants';
+import { ThemeContext } from 'twenty-ui/theme';
+import { MOBILE_VIEWPORT, themeCssVariables } from 'twenty-ui/theme-constants';
const StyledTopBarContainer = styled.div<{ isMobile: boolean }>`
align-items: center;
diff --git a/packages/twenty-front/src/modules/ui/layout/selectable-list/components/SelectableListItem.tsx b/packages/twenty-front/src/modules/ui/layout/selectable-list/components/SelectableListItem.tsx
index 8d0b697356..9738d72420 100644
--- a/packages/twenty-front/src/modules/ui/layout/selectable-list/components/SelectableListItem.tsx
+++ b/packages/twenty-front/src/modules/ui/layout/selectable-list/components/SelectableListItem.tsx
@@ -3,7 +3,7 @@ import { type ReactNode, useEffect, useRef } from 'react';
import { SelectableListItemHotkeyEffect } from '@/ui/layout/selectable-list/components/SelectableListItemHotkeyEffect';
import { isSelectedItemIdComponentFamilyState } from '@/ui/layout/selectable-list/states/isSelectedItemIdComponentFamilyState';
import { useAtomComponentFamilyStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentFamilyStateValue';
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
import { isDefined } from 'twenty-shared/utils';
const StyledListItemContainer = styled.div`
@@ -18,12 +18,14 @@ export type SelectableListItemProps = {
itemId: string;
children: ReactNode;
onEnter?: () => void;
+ className?: string;
};
export const SelectableListItem = ({
itemId,
children,
onEnter,
+ className,
}: SelectableListItemProps) => {
const isSelectedItemId = useAtomComponentFamilyStateValue(
isSelectedItemIdComponentFamilyState,
@@ -56,7 +58,7 @@ export const SelectableListItem = ({
{isSelectedItemId && isDefined(onEnter) && (
)}
-
+
{children}
>
diff --git a/packages/twenty-front/src/modules/ui/layout/show-page/components/FieldRichTextCard.tsx b/packages/twenty-front/src/modules/ui/layout/show-page/components/FieldRichTextCard.tsx
index 7aff409cc8..01226399aa 100644
--- a/packages/twenty-front/src/modules/ui/layout/show-page/components/FieldRichTextCard.tsx
+++ b/packages/twenty-front/src/modules/ui/layout/show-page/components/FieldRichTextCard.tsx
@@ -3,12 +3,13 @@ import { type CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectN
import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector';
import { useTargetRecord } from '@/ui/layout/contexts/useTargetRecord';
import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper';
-import { useTheme } from '@emotion/react';
-import styled from '@emotion/styled';
-import { lazy, Suspense } from 'react';
+import { styled } from '@linaria/react';
+import { lazy, Suspense, useContext } from 'react';
import Skeleton, { SkeletonTheme } from 'react-loading-skeleton';
import { useAtomFamilySelectorValue } from '@/ui/utilities/state/jotai/hooks/useAtomFamilySelectorValue';
import { isDefined } from 'twenty-shared/utils';
+import { ThemeContext } from 'twenty-ui/theme';
+import { themeCssVariables } from 'twenty-ui/theme-constants';
const ActivityRichTextEditor = lazy(() =>
import('@/activities/components/ActivityRichTextEditor').then((module) => ({
@@ -17,7 +18,7 @@ const ActivityRichTextEditor = lazy(() =>
);
const StyledShowPageActivityContainer = styled.div`
- margin-top: ${({ theme }) => theme.spacing(6)};
+ margin-top: ${themeCssVariables.spacing[6]};
width: 100%;
padding-inline: 44px;
box-sizing: border-box;
@@ -27,11 +28,11 @@ const StyledSkeletonContainer = styled.div`
display: flex;
flex-direction: column;
justify-content: center;
- padding: ${({ theme }) => theme.spacing(0, 4)};
+ padding: 0 ${themeCssVariables.spacing[4]};
`;
const LoadingSkeleton = () => {
- const theme = useTheme();
+ const { theme } = useContext(ThemeContext);
return (
diff --git a/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageSummaryCard.tsx b/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageSummaryCard.tsx
index 6d59551818..aeaf765e7b 100644
--- a/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageSummaryCard.tsx
+++ b/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageSummaryCard.tsx
@@ -1,8 +1,7 @@
import { SKELETON_LOADER_HEIGHT_SIZES } from '@/activities/components/SkeletonLoader';
-import { useTheme } from '@emotion/react';
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
import { Trans } from '@lingui/react/macro';
-import { type ChangeEvent, type ReactNode, useRef } from 'react';
+import { type ChangeEvent, type ReactNode, useContext, useRef } from 'react';
import Skeleton, { SkeletonTheme } from 'react-loading-skeleton';
import { isDefined } from 'twenty-shared/utils';
import {
@@ -12,6 +11,8 @@ import {
type IconComponent,
} from 'twenty-ui/display';
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
+import { ThemeContext } from 'twenty-ui/theme';
+import { themeCssVariables } from 'twenty-ui/theme-constants';
import { v4 as uuidV4 } from 'uuid';
import { dateLocaleState } from '~/localization/states/dateLocaleState';
import {
@@ -39,11 +40,11 @@ export const StyledShowPageSummaryCard = styled.div<{
align-items: center;
display: flex;
flex-direction: ${({ isMobile }) => (isMobile ? 'row' : 'column')};
- gap: ${({ theme, isMobile }) =>
- isMobile ? theme.spacing(2) : theme.spacing(3)};
+ gap: ${({ isMobile }) =>
+ isMobile ? themeCssVariables.spacing[2] : themeCssVariables.spacing[3]};
justify-content: ${({ isMobile }) => (isMobile ? 'flex-start' : 'center')};
- padding: ${({ theme }) => theme.spacing(4)};
- border-bottom: 1px solid ${({ theme }) => theme.border.color.light};
+ padding: ${themeCssVariables.spacing[4]};
+ border-bottom: 1px solid ${themeCssVariables.border.color.light};
height: ${({ isMobile }) => (isMobile ? '77px' : '127px')};
box-sizing: border-box;
`;
@@ -52,21 +53,21 @@ const StyledInfoContainer = styled.div<{ isMobile: boolean }>`
align-items: ${({ isMobile }) => (isMobile ? 'flex-start' : 'center')};
display: flex;
flex-direction: column;
- gap: ${({ theme }) => theme.spacing(1)};
+ gap: ${themeCssVariables.spacing[1]};
width: 100%;
`;
const StyledDate = styled.div<{ isMobile: boolean }>`
- color: ${({ theme }) => theme.font.color.tertiary};
+ color: ${themeCssVariables.font.color.tertiary};
cursor: pointer;
- padding-left: ${({ theme }) => theme.spacing(1)};
+ padding-left: ${themeCssVariables.spacing[1]};
`;
const StyledTitle = styled.div<{ isMobile: boolean }>`
- color: ${({ theme }) => theme.font.color.primary};
+ color: ${themeCssVariables.font.color.primary};
display: flex;
- font-size: ${({ theme }) => theme.font.size.xl};
- font-weight: ${({ theme }) => theme.font.weight.semiBold};
+ font-size: ${themeCssVariables.font.size.xl};
+ font-weight: ${themeCssVariables.font.weight.semiBold};
justify-content: ${({ isMobile }) => (isMobile ? 'flex-start' : 'center')};
width: 90%;
`;
@@ -75,9 +76,9 @@ const StyledAvatarWrapper = styled.div<{
isAvatarEditable: boolean;
hasIcon: boolean;
}>`
- background-color: ${({ theme, hasIcon }) =>
- hasIcon ? theme.background.transparent.light : 'unset'};
- border-radius: ${({ theme }) => theme.border.radius.sm};
+ background-color: ${({ hasIcon }) =>
+ hasIcon ? themeCssVariables.background.transparent.light : 'unset'};
+ border-radius: ${themeCssVariables.border.radius.sm};
cursor: ${({ isAvatarEditable }) =>
isAvatarEditable ? 'pointer' : 'default'};
`;
@@ -95,7 +96,7 @@ const StyledSubSkeleton = styled.div`
`;
const StyledShowPageSummaryCardSkeletonLoader = () => {
- const theme = useTheme();
+ const { theme } = useContext(ThemeContext);
return (
{
- const theme = useTheme();
+ const { theme } = useContext(ThemeContext);
if (isDefined(tab.logo)) {
return ;
diff --git a/packages/twenty-front/src/modules/ui/layout/tab-list/components/TabList.tsx b/packages/twenty-front/src/modules/ui/layout/tab-list/components/TabList.tsx
index 536354b52f..5f25f35579 100644
--- a/packages/twenty-front/src/modules/ui/layout/tab-list/components/TabList.tsx
+++ b/packages/twenty-front/src/modules/ui/layout/tab-list/components/TabList.tsx
@@ -7,23 +7,24 @@ import { NodeDimension } from '@/ui/utilities/dimensions/components/NodeDimensio
import { TabListHiddenMeasurements } from '@/ui/layout/tab-list/components/TabListHiddenMeasurements';
import { useTabListMeasurements } from '@/ui/layout/tab-list/hooks/useTabListMeasurements';
import { useAtomComponentState } from '@/ui/utilities/state/jotai/hooks/useAtomComponentState';
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
import { useCallback, useEffect, useMemo } from 'react';
import { useNavigate } from 'react-router-dom';
import { TabButton } from 'twenty-ui/input';
+import { themeCssVariables } from 'twenty-ui/theme-constants';
import { TabListDropdown } from './TabListDropdown';
import { TabListFromUrlOptionalEffect } from './TabListFromUrlOptionalEffect';
const StyledContainer = styled.div`
box-sizing: border-box;
display: flex;
- height: ${({ theme }) => theme.spacing(10)};
+ height: ${themeCssVariables.spacing[10]};
position: relative;
user-select: none;
width: 100%;
&::after {
- background-color: ${({ theme }) => theme.border.color.light};
+ background-color: ${themeCssVariables.border.color.light};
bottom: 0;
content: '';
height: 1px;
diff --git a/packages/twenty-front/src/modules/ui/layout/tab-list/components/TabListHiddenMeasurements.tsx b/packages/twenty-front/src/modules/ui/layout/tab-list/components/TabListHiddenMeasurements.tsx
index 4023b5d136..f4ff6a3654 100644
--- a/packages/twenty-front/src/modules/ui/layout/tab-list/components/TabListHiddenMeasurements.tsx
+++ b/packages/twenty-front/src/modules/ui/layout/tab-list/components/TabListHiddenMeasurements.tsx
@@ -3,7 +3,7 @@ import type { ReactNode } from 'react';
import { TAB_LIST_GAP } from '@/ui/layout/tab-list/constants/TabListGap';
import { type SingleTabProps } from '@/ui/layout/tab-list/types/SingleTabProps';
import { NodeDimension } from '@/ui/utilities/dimensions/components/NodeDimension';
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
import { IconPlus } from 'twenty-ui/display';
import { TabButton } from 'twenty-ui/input';
diff --git a/packages/twenty-front/src/modules/ui/layout/tab-list/components/TabMoreButton.tsx b/packages/twenty-front/src/modules/ui/layout/tab-list/components/TabMoreButton.tsx
index fbeef1587a..723eefe841 100644
--- a/packages/twenty-front/src/modules/ui/layout/tab-list/components/TabMoreButton.tsx
+++ b/packages/twenty-front/src/modules/ui/layout/tab-list/components/TabMoreButton.tsx
@@ -1,10 +1,11 @@
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
import { t } from '@lingui/core/macro';
import { IconChevronDown } from 'twenty-ui/display';
import { TabButton } from 'twenty-ui/input';
+import { themeCssVariables } from 'twenty-ui/theme-constants';
const StyledTabMoreButton = styled(TabButton)`
- height: ${({ theme }) => theme.spacing(10)};
+ height: ${themeCssVariables.spacing[10]};
`;
export const TabMoreButton = ({
diff --git a/packages/twenty-front/src/modules/ui/layout/tab-list/components/__stories__/Tablist.stories.tsx b/packages/twenty-front/src/modules/ui/layout/tab-list/components/__stories__/Tablist.stories.tsx
index 706e3ab3ae..5612ec9496 100644
--- a/packages/twenty-front/src/modules/ui/layout/tab-list/components/__stories__/Tablist.stories.tsx
+++ b/packages/twenty-front/src/modules/ui/layout/tab-list/components/__stories__/Tablist.stories.tsx
@@ -1,5 +1,5 @@
import { TabList } from '@/ui/layout/tab-list/components/TabList';
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
import { type Meta, type StoryObj } from '@storybook/react-vite';
import {
IconCalendar,
@@ -35,12 +35,14 @@ const tabs = [
{ id: 'reports', title: 'Reports', Icon: IconCheckbox },
];
+import { themeCssVariables } from 'twenty-ui/theme-constants';
+
const StyledInteractiveContainer = styled.div`
- border: 1px solid ${({ theme }) => theme.border.color.strong};
+ border: 1px solid ${themeCssVariables.border.color.strong};
max-width: 100%;
min-width: 300px;
overflow: auto;
- padding: ${({ theme }) => theme.spacing(5)};
+ padding: ${themeCssVariables.spacing[5]};
resize: horizontal;
width: 600px;
`;
diff --git a/packages/twenty-front/src/modules/ui/layout/table/components/Table.tsx b/packages/twenty-front/src/modules/ui/layout/table/components/Table.tsx
index a03874fccd..22da2959e6 100644
--- a/packages/twenty-front/src/modules/ui/layout/table/components/Table.tsx
+++ b/packages/twenty-front/src/modules/ui/layout/table/components/Table.tsx
@@ -1,4 +1,4 @@
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
const StyledTable = styled.div``;
diff --git a/packages/twenty-front/src/modules/ui/layout/table/components/TableBody.tsx b/packages/twenty-front/src/modules/ui/layout/table/components/TableBody.tsx
index 7c9f99e54b..00165ca04d 100644
--- a/packages/twenty-front/src/modules/ui/layout/table/components/TableBody.tsx
+++ b/packages/twenty-front/src/modules/ui/layout/table/components/TableBody.tsx
@@ -1,10 +1,11 @@
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
+import { themeCssVariables } from 'twenty-ui/theme-constants';
const StyledTableBody = styled.div`
display: flex;
flex-direction: column;
gap: 2px;
- padding: ${({ theme }) => theme.spacing(2)} 0;
+ padding: ${themeCssVariables.spacing[2]} 0;
`;
export { StyledTableBody as TableBody };
diff --git a/packages/twenty-front/src/modules/ui/layout/table/components/TableCell.tsx b/packages/twenty-front/src/modules/ui/layout/table/components/TableCell.tsx
index 26fd9fa15c..17391ce758 100644
--- a/packages/twenty-front/src/modules/ui/layout/table/components/TableCell.tsx
+++ b/packages/twenty-front/src/modules/ui/layout/table/components/TableCell.tsx
@@ -1,4 +1,5 @@
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
+import { themeCssVariables } from 'twenty-ui/theme-constants';
type TableCellProps = {
align?: 'left' | 'center' | 'right';
@@ -7,16 +8,16 @@ type TableCellProps = {
const StyledTableCell = styled.div`
align-items: center;
- color: ${({ color, theme }) => color || theme.font.color.secondary};
+ color: ${({ color }) => color || themeCssVariables.font.color.secondary};
display: flex;
- height: ${({ theme }) => theme.spacing(8)};
+ height: ${themeCssVariables.spacing[8]};
justify-content: ${({ align }) =>
align === 'right'
? 'flex-end'
: align === 'center'
? 'center'
: 'flex-start'};
- padding: 0 ${({ theme }) => theme.spacing(2)};
+ padding: 0 ${themeCssVariables.spacing[2]};
text-align: ${({ align }) => align ?? 'left'};
`;
diff --git a/packages/twenty-front/src/modules/ui/layout/table/components/TableHeader.tsx b/packages/twenty-front/src/modules/ui/layout/table/components/TableHeader.tsx
index 09e07b924b..7d9f130179 100644
--- a/packages/twenty-front/src/modules/ui/layout/table/components/TableHeader.tsx
+++ b/packages/twenty-front/src/modules/ui/layout/table/components/TableHeader.tsx
@@ -1,23 +1,24 @@
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
+import { themeCssVariables } from 'twenty-ui/theme-constants';
const StyledTableHeader = styled.div<{
align?: 'left' | 'center' | 'right';
onClick?: () => void;
}>`
- gap: ${({ theme }) => theme.spacing(1)};
+ gap: ${themeCssVariables.spacing[1]};
align-items: center;
- border-bottom: 1px solid ${({ theme }) => theme.border.color.light};
- color: ${({ theme }) => theme.font.color.tertiary};
+ border-bottom: 1px solid ${themeCssVariables.border.color.light};
+ color: ${themeCssVariables.font.color.tertiary};
display: flex;
- font-weight: ${({ theme }) => theme.font.weight.medium};
- height: ${({ theme }) => theme.spacing(8)};
+ font-weight: ${themeCssVariables.font.weight.medium};
+ height: ${themeCssVariables.spacing[8]};
justify-content: ${({ align }) =>
align === 'right'
? 'flex-end'
: align === 'center'
? 'center'
: 'flex-start'};
- padding: 0 ${({ theme }) => theme.spacing(2)};
+ padding: 0 ${themeCssVariables.spacing[2]};
text-align: ${({ align }) => align ?? 'left'};
cursor: ${({ onClick }) => (onClick ? 'pointer' : 'default')};
`;
diff --git a/packages/twenty-front/src/modules/ui/layout/table/components/TableHeaderText.tsx b/packages/twenty-front/src/modules/ui/layout/table/components/TableHeaderText.tsx
index 9d4b690d6a..3a06f6da63 100644
--- a/packages/twenty-front/src/modules/ui/layout/table/components/TableHeaderText.tsx
+++ b/packages/twenty-front/src/modules/ui/layout/table/components/TableHeaderText.tsx
@@ -1,7 +1,8 @@
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
+import { themeCssVariables } from 'twenty-ui/theme-constants';
const StyledTableHeaderText = styled.div`
- padding-bottom: ${({ theme }) => theme.spacing(0.5)};
+ padding-bottom: ${themeCssVariables.spacing['0.5']};
`;
export { StyledTableHeaderText as TableHeaderText };
diff --git a/packages/twenty-front/src/modules/ui/layout/table/components/TableRow.tsx b/packages/twenty-front/src/modules/ui/layout/table/components/TableRow.tsx
index 7270bd6e3a..813e7085db 100644
--- a/packages/twenty-front/src/modules/ui/layout/table/components/TableRow.tsx
+++ b/packages/twenty-front/src/modules/ui/layout/table/components/TableRow.tsx
@@ -1,12 +1,8 @@
-import isPropValid from '@emotion/is-prop-valid';
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
import { Link } from 'react-router-dom';
-import { MOBILE_VIEWPORT } from 'twenty-ui/theme';
+import { MOBILE_VIEWPORT, themeCssVariables } from 'twenty-ui/theme-constants';
-const StyledTableRow = styled('div', {
- shouldForwardProp: (prop) =>
- !['isSelected'].includes(prop) && isPropValid(prop),
-})<{
+const StyledTableRow = styled.div<{
isSelected?: boolean;
onClick?: () => void;
to?: string;
@@ -14,15 +10,13 @@ const StyledTableRow = styled('div', {
gridTemplateColumns?: string;
mobileGridAutoColumns?: string;
}>`
- background-color: ${({ isSelected, theme }) =>
- isSelected ? theme.accent.quaternary : 'transparent'};
- border-radius: ${({ theme }) => theme.border.radius.sm};
+ background-color: ${({ isSelected }) =>
+ isSelected ? themeCssVariables.accent.quaternary : 'transparent'};
+ border-radius: ${themeCssVariables.border.radius.sm};
display: grid;
grid-auto-columns: ${({ gridAutoColumns }) => gridAutoColumns ?? '1fr'};
- ${({ gridTemplateColumns }) =>
- gridTemplateColumns
- ? `grid-template-columns: ${gridTemplateColumns};`
- : ''};
+ grid-template-columns: ${({ gridTemplateColumns }) =>
+ gridTemplateColumns ?? 'none'};
@media (max-width: ${MOBILE_VIEWPORT}px) {
grid-auto-columns: ${({ mobileGridAutoColumns, gridAutoColumns }) =>
@@ -31,13 +25,15 @@ const StyledTableRow = styled('div', {
grid-auto-flow: column;
transition: background-color
- ${({ theme }) => theme.animation.duration.normal}s;
+ calc(${themeCssVariables.animation.duration.normal} * 1s);
width: 100%;
text-decoration: none;
&:hover {
- background-color: ${({ onClick, to, theme }) =>
- onClick || to ? theme.background.transparent.light : 'transparent'};
+ background-color: ${({ onClick, to }) =>
+ onClick || to
+ ? themeCssVariables.background.transparent.light
+ : 'transparent'};
cursor: ${({ onClick, to }) => (onClick || to ? 'pointer' : 'default')};
}
diff --git a/packages/twenty-front/src/modules/ui/layout/table/components/TableSection.tsx b/packages/twenty-front/src/modules/ui/layout/table/components/TableSection.tsx
index 96ea13eae0..ab78c9e496 100644
--- a/packages/twenty-front/src/modules/ui/layout/table/components/TableSection.tsx
+++ b/packages/twenty-front/src/modules/ui/layout/table/components/TableSection.tsx
@@ -1,8 +1,9 @@
-import { useTheme } from '@emotion/react';
-import styled from '@emotion/styled';
-import { type ReactNode, useState } from 'react';
+import { styled } from '@linaria/react';
+import { type ReactNode, useContext, useState } from 'react';
import { TableBody } from './TableBody';
import { IconChevronDown, IconChevronUp, Label } from 'twenty-ui/display';
+import { ThemeContext } from 'twenty-ui/theme';
+import { themeCssVariables } from 'twenty-ui/theme-constants';
type TableSectionProps = {
children: ReactNode;
@@ -12,27 +13,27 @@ type TableSectionProps = {
const StyledSectionHeader = styled.div<{ isExpanded: boolean }>`
align-items: center;
- background-color: ${({ theme }) => theme.background.transparent.lighter};
- border-bottom: 1px solid ${({ theme }) => theme.border.color.light};
+ background-color: ${themeCssVariables.background.transparent.lighter};
+ border-bottom: 1px solid ${themeCssVariables.border.color.light};
cursor: pointer;
display: flex;
- height: ${({ theme }) => theme.spacing(6)};
+ height: ${themeCssVariables.spacing[6]};
justify-content: space-between;
- padding: 0 ${({ theme }) => theme.spacing(2)};
+ padding: 0 ${themeCssVariables.spacing[2]};
text-align: left;
`;
const StyledSection = styled.div<{ isExpanded: boolean }>`
- max-height: ${({ isExpanded }) => (isExpanded ? 'fit-content' : 0)};
+ max-height: ${({ isExpanded }) => (isExpanded ? 'fit-content' : '0')};
opacity: ${({ isExpanded }) => (isExpanded ? 1 : 0)};
overflow: hidden;
transition:
- max-height ${({ theme }) => theme.animation.duration.normal}s,
- opacity ${({ theme }) => theme.animation.duration.normal}s;
+ max-height calc(${themeCssVariables.animation.duration.normal} * 1s),
+ opacity calc(${themeCssVariables.animation.duration.normal} * 1s);
`;
const StyledSectionContent = styled(TableBody)`
- border-bottom: 1px solid ${({ theme }) => theme.border.color.light};
+ border-bottom: 1px solid ${themeCssVariables.border.color.light};
`;
export const TableSection = ({
@@ -41,7 +42,7 @@ export const TableSection = ({
title,
}: TableSectionProps) => {
const [isExpanded, setIsExpanded] = useState(isInitiallyExpanded);
- const theme = useTheme();
+ const { theme } = useContext(ThemeContext);
const handleToggleSection = () =>
setIsExpanded((previousIsExpanded) => !previousIsExpanded);
diff --git a/packages/twenty-front/src/modules/ui/layout/table/components/TableSubRow.tsx b/packages/twenty-front/src/modules/ui/layout/table/components/TableSubRow.tsx
index 517f3546cb..481d4a8081 100644
--- a/packages/twenty-front/src/modules/ui/layout/table/components/TableSubRow.tsx
+++ b/packages/twenty-front/src/modules/ui/layout/table/components/TableSubRow.tsx
@@ -1,9 +1,10 @@
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
+import { themeCssVariables } from 'twenty-ui/theme-constants';
import { TableRow } from '@/ui/layout/table/components/TableRow';
const StyledTableSubRow = styled(TableRow)`
- padding-left: ${({ theme }) => theme.spacing(4)};
+ padding-left: ${themeCssVariables.spacing[4]};
`;
export const TableSubRow = StyledTableSubRow;
diff --git a/packages/twenty-front/src/modules/ui/layout/table/components/__stories__/Table.stories.tsx b/packages/twenty-front/src/modules/ui/layout/table/components/__stories__/Table.stories.tsx
index f66b4bb4fd..a4ab60eb1f 100644
--- a/packages/twenty-front/src/modules/ui/layout/table/components/__stories__/Table.stories.tsx
+++ b/packages/twenty-front/src/modules/ui/layout/table/components/__stories__/Table.stories.tsx
@@ -13,7 +13,6 @@ const meta: Meta = {
decorators: [ComponentDecorator],
argTypes: {
as: { table: { disable: true } },
- theme: { table: { disable: true } },
},
};
diff --git a/packages/twenty-front/src/modules/ui/layout/top-bar/components/TopBar.tsx b/packages/twenty-front/src/modules/ui/layout/top-bar/components/TopBar.tsx
index 7ae9ddac47..59db9a4642 100644
--- a/packages/twenty-front/src/modules/ui/layout/top-bar/components/TopBar.tsx
+++ b/packages/twenty-front/src/modules/ui/layout/top-bar/components/TopBar.tsx
@@ -1,5 +1,6 @@
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
import { type ReactNode } from 'react';
+import { themeCssVariables } from 'twenty-ui/theme-constants';
type TopBarProps = {
className?: string;
@@ -10,9 +11,9 @@ type TopBarProps = {
};
const StyledContainer = styled.div`
- border-bottom: ${({ theme }) => `1px solid ${theme.border.color.light}`};
+ border-bottom: 1px solid ${themeCssVariables.border.color.light};
display: flex;
- margin-left: ${({ theme }) => theme.spacing(3)};
+ margin-left: ${themeCssVariables.spacing[3]};
flex-direction: column;
`;
@@ -21,13 +22,13 @@ const StyledTopBar = styled.div`
align-items: center;
box-sizing: border-box;
- color: ${({ theme }) => theme.font.color.secondary};
+ color: ${themeCssVariables.font.color.secondary};
display: flex;
flex-direction: row;
- font-weight: ${({ theme }) => theme.font.weight.medium};
+ font-weight: ${themeCssVariables.font.weight.medium};
height: 39px;
justify-content: space-between;
- padding-right: ${({ theme }) => theme.spacing(2)};
+ padding-right: ${themeCssVariables.spacing[2]};
z-index: 7;
`;
@@ -38,8 +39,8 @@ const StyledLeftSection = styled.div`
const StyledRightSection = styled.div`
display: flex;
- font-weight: ${({ theme }) => theme.font.weight.regular};
- gap: ${({ theme }) => theme.betweenSiblingsGap};
+ font-weight: ${themeCssVariables.font.weight.regular};
+ gap: ${themeCssVariables.betweenSiblingsGap};
`;
export const TopBar = ({
diff --git a/packages/twenty-front/src/modules/ui/navigation/bread-crumb/components/Breadcrumb.tsx b/packages/twenty-front/src/modules/ui/navigation/bread-crumb/components/Breadcrumb.tsx
index 0f7923c81c..077ffa4e5e 100644
--- a/packages/twenty-front/src/modules/ui/navigation/bread-crumb/components/Breadcrumb.tsx
+++ b/packages/twenty-front/src/modules/ui/navigation/bread-crumb/components/Breadcrumb.tsx
@@ -1,8 +1,9 @@
import { MobileBreadcrumb } from '@/ui/navigation/bread-crumb/components/MobileBreadcrumb';
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
import { Fragment, type ReactNode } from 'react';
import { Link } from 'react-router-dom';
+import { themeCssVariables } from 'twenty-ui/theme-constants';
export type BreadcrumbProps = {
className?: string;
@@ -11,14 +12,14 @@ export type BreadcrumbProps = {
const StyledWrapper = styled.nav`
align-items: center;
- color: ${({ theme }) => theme.font.color.tertiary};
+ color: ${themeCssVariables.font.color.tertiary};
display: grid;
- font-size: ${({ theme }) => theme.font.size.md};
+ font-size: ${themeCssVariables.font.size.md};
grid-auto-flow: column;
- grid-column-gap: ${({ theme }) => theme.spacing(1)};
+ grid-column-gap: ${themeCssVariables.spacing[1]};
max-width: 100%;
min-width: 0;
- height: ${({ theme }) => theme.spacing(8)};
+ height: ${themeCssVariables.spacing[8]};
`;
const StyledLink = styled(Link)`
@@ -30,14 +31,14 @@ const StyledLink = styled(Link)`
`;
const StyledText = styled.span`
- color: ${({ theme }) => theme.font.color.primary};
+ color: ${themeCssVariables.font.color.primary};
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
`;
const StyledDivider = styled.span`
- width: ${({ theme }) => theme.spacing(2)};
+ width: ${themeCssVariables.spacing[2]};
`;
export const Breadcrumb = ({ className, links }: BreadcrumbProps) => {
diff --git a/packages/twenty-front/src/modules/ui/navigation/bread-crumb/components/MobileBreadcrumb.tsx b/packages/twenty-front/src/modules/ui/navigation/bread-crumb/components/MobileBreadcrumb.tsx
index adcf74afbb..6f050f93d0 100644
--- a/packages/twenty-front/src/modules/ui/navigation/bread-crumb/components/MobileBreadcrumb.tsx
+++ b/packages/twenty-front/src/modules/ui/navigation/bread-crumb/components/MobileBreadcrumb.tsx
@@ -1,11 +1,12 @@
import { t } from '@lingui/core/macro';
import { useOpenSettingsMenu } from '@/navigation/hooks/useOpenSettings';
-import { useTheme } from '@emotion/react';
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
import { isNonEmptyString } from '@sniptt/guards';
-import { type ReactNode } from 'react';
+import { type ReactNode, useContext } from 'react';
import { Link } from 'react-router-dom';
import { IconChevronLeft } from 'twenty-ui/display';
+import { ThemeContext } from 'twenty-ui/theme';
+import { themeCssVariables } from 'twenty-ui/theme-constants';
export type MobileBreadcrumbProps = {
className?: string;
@@ -14,14 +15,14 @@ export type MobileBreadcrumbProps = {
const StyledWrapper = styled.nav`
align-items: center;
- color: ${({ theme }) => theme.font.color.tertiary};
+ color: ${themeCssVariables.font.color.tertiary};
display: grid;
- font-size: ${({ theme }) => theme.font.size.md};
+ font-size: ${themeCssVariables.font.size.md};
grid-auto-flow: column;
- grid-column-gap: ${({ theme }) => theme.spacing(1)};
+ grid-column-gap: ${themeCssVariables.spacing[1]};
max-width: 100%;
min-width: 0;
- height: ${({ theme }) => theme.spacing(8)};
+ height: ${themeCssVariables.spacing[8]};
`;
const StyledLink = styled(Link)`
@@ -43,7 +44,7 @@ export const MobileBreadcrumb = ({
className,
links,
}: MobileBreadcrumbProps) => {
- const theme = useTheme();
+ const { theme } = useContext(ThemeContext);
const { openSettingsMenu } = useOpenSettingsMenu();
diff --git a/packages/twenty-front/src/modules/ui/navigation/menu-item/components/MenuItemWithOptionDropdown.tsx b/packages/twenty-front/src/modules/ui/navigation/menu-item/components/MenuItemWithOptionDropdown.tsx
index 2fa97a7453..582c1f9b52 100644
--- a/packages/twenty-front/src/modules/ui/navigation/menu-item/components/MenuItemWithOptionDropdown.tsx
+++ b/packages/twenty-front/src/modules/ui/navigation/menu-item/components/MenuItemWithOptionDropdown.tsx
@@ -1,12 +1,13 @@
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
-import { useTheme } from '@emotion/react';
import { type Placement } from '@floating-ui/react';
import {
type FunctionComponent,
type MouseEvent,
type ReactElement,
type ReactNode,
+ useContext,
} from 'react';
+import { ThemeContext } from 'twenty-ui/theme';
import {
IconChevronRight,
type IconComponent,
@@ -62,7 +63,7 @@ export const MenuItemWithOptionDropdown = ({
hasSubMenu = false,
dropdownPlacement = 'bottom-end',
}: MenuItemWithOptionDropdownProps) => {
- const theme = useTheme();
+ const { theme } = useContext(ThemeContext);
const handleMenuItemClick = (event: MouseEvent) => {
if (!onClick) return;
diff --git a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/MultiWorkspaceDropdown/internal/MultiWorkspaceDropdownClickableComponent.tsx b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/MultiWorkspaceDropdown/internal/MultiWorkspaceDropdownClickableComponent.tsx
index e5ecd8d4b4..7f1d91d547 100644
--- a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/MultiWorkspaceDropdown/internal/MultiWorkspaceDropdownClickableComponent.tsx
+++ b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/MultiWorkspaceDropdown/internal/MultiWorkspaceDropdownClickableComponent.tsx
@@ -7,13 +7,14 @@ import {
} from '@/ui/navigation/navigation-drawer/components/MultiWorkspaceDropdown/internal/MultiWorkspacesDropdownStyles';
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
-import { useTheme } from '@emotion/react';
+import { useContext } from 'react';
import { isNavigationDrawerExpandedState } from '@/ui/navigation/states/isNavigationDrawerExpanded';
import { Avatar } from 'twenty-ui/display';
+import { ThemeContext } from 'twenty-ui/theme';
export const MultiWorkspaceDropdownClickableComponent = () => {
const currentWorkspace = useAtomStateValue(currentWorkspaceState);
- const theme = useTheme();
+ const { theme } = useContext(ThemeContext);
const isNavigationDrawerExpanded = useAtomStateValue(
isNavigationDrawerExpandedState,
diff --git a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/MultiWorkspaceDropdown/internal/MultiWorkspaceDropdownDefaultComponents.tsx b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/MultiWorkspaceDropdown/internal/MultiWorkspaceDropdownDefaultComponents.tsx
index 1db4f45d4c..2e223d80e3 100644
--- a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/MultiWorkspaceDropdown/internal/MultiWorkspaceDropdownDefaultComponents.tsx
+++ b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/MultiWorkspaceDropdown/internal/MultiWorkspaceDropdownDefaultComponents.tsx
@@ -25,8 +25,9 @@ import { useAtomState } from '@/ui/utilities/state/jotai/hooks/useAtomState';
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
import { useSetAtomState } from '@/ui/utilities/state/jotai/hooks/useSetAtomState';
import { type ApolloError } from '@apollo/client';
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
import { useLingui } from '@lingui/react/macro';
+import { themeCssVariables } from 'twenty-ui/theme-constants';
import { isNonEmptyString } from '@sniptt/guards';
import { useLocation } from 'react-router-dom';
import { AppPath, SettingsPath } from 'twenty-shared/types';
@@ -54,8 +55,8 @@ import {
import { getWorkspaceUrl } from '~/utils/getWorkspaceUrl';
const StyledDescription = styled.div`
- color: ${({ theme }) => theme.font.color.light};
- padding-left: ${({ theme }) => theme.spacing(1)};
+ color: ${themeCssVariables.font.color.light};
+ padding-left: ${themeCssVariables.spacing[1]};
`;
export const MultiWorkspaceDropdownDefaultComponents = () => {
diff --git a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/MultiWorkspaceDropdown/internal/MultiWorkspacesDropdownStyles.tsx b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/MultiWorkspaceDropdown/internal/MultiWorkspacesDropdownStyles.tsx
index c882126f5a..4d33e550c8 100644
--- a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/MultiWorkspaceDropdown/internal/MultiWorkspacesDropdownStyles.tsx
+++ b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/MultiWorkspaceDropdown/internal/MultiWorkspacesDropdownStyles.tsx
@@ -1,39 +1,42 @@
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
import { IconChevronDown } from 'twenty-ui/display';
+import { themeCssVariables } from 'twenty-ui/theme-constants';
export const StyledContainer = styled.div<{
isNavigationDrawerExpanded: boolean;
}>`
align-items: center;
cursor: pointer;
- color: ${({ theme }) => theme.font.color.primary};
- border-radius: ${({ theme }) => theme.border.radius.sm};
+ color: ${themeCssVariables.font.color.primary};
+ border-radius: ${themeCssVariables.border.radius.sm};
border: 1px solid transparent;
display: flex;
justify-content: space-between;
- height: ${({ theme }) => theme.spacing(5)};
- padding: calc(${({ theme }) => theme.spacing(1)} - 1px);
+ height: ${themeCssVariables.spacing[5]};
+ padding: calc(${themeCssVariables.spacing[1]} - 1px);
width: ${({ isNavigationDrawerExpanded }) =>
isNavigationDrawerExpanded ? '100%' : 'auto'};
- gap: ${({ theme, isNavigationDrawerExpanded }) =>
- isNavigationDrawerExpanded ? theme.spacing(1) : '0'};
+ gap: ${({ isNavigationDrawerExpanded }) =>
+ isNavigationDrawerExpanded ? themeCssVariables.spacing[1] : '0'};
&:hover {
- background-color: ${({ theme }) => theme.background.transparent.lighter};
- border: 1px solid ${({ theme }) => theme.border.color.medium};
+ background-color: ${themeCssVariables.background.transparent.lighter};
+ border: 1px solid ${themeCssVariables.border.color.medium};
}
`;
export const StyledLabel = styled.div`
align-items: center;
display: flex;
- font-weight: ${({ theme }) => theme.font.weight.medium};
+ font-weight: ${themeCssVariables.font.weight.medium};
`;
export const StyledIconChevronDown = styled(IconChevronDown)<{
disabled?: boolean;
}>`
align-items: center;
- color: ${({ disabled, theme }) =>
- disabled ? theme.font.color.extraLight : theme.font.color.tertiary};
+ color: ${({ disabled }) =>
+ disabled
+ ? themeCssVariables.font.color.extraLight
+ : themeCssVariables.font.color.tertiary};
display: flex;
`;
diff --git a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawer.tsx b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawer.tsx
index 4d9ee5bc98..4fbe2dfbdb 100644
--- a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawer.tsx
+++ b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawer.tsx
@@ -1,4 +1,4 @@
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
import { type ReactNode, useState } from 'react';
import { useIsSettingsDrawer } from '@/navigation/hooks/useIsSettingsDrawer';
@@ -18,7 +18,7 @@ import {
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
import { useAtomState } from '@/ui/utilities/state/jotai/hooks/useAtomState';
import { useSetAtomState } from '@/ui/utilities/state/jotai/hooks/useSetAtomState';
-import { MOBILE_VIEWPORT } from 'twenty-ui/theme';
+import { MOBILE_VIEWPORT, themeCssVariables } from 'twenty-ui/theme-constants';
import { NavigationDrawerBackButton } from './NavigationDrawerBackButton';
import { NavigationDrawerHeader } from './NavigationDrawerHeader';
@@ -39,8 +39,10 @@ const StyledAnimatedContainer = styled.div<{
isExpanded
? `var(${NAVIGATION_DRAWER_WIDTH_VAR})`
: `${NAVIGATION_DRAWER_COLLAPSED_WIDTH}px`};
- transition: ${({ isResizing, theme }) =>
- isResizing ? 'none' : `width ${theme.animation.duration.normal}s`};
+ transition: ${({ isResizing }) =>
+ isResizing
+ ? 'none'
+ : `width calc(${themeCssVariables.animation.duration.normal} * 1s)`};
@media (max-width: ${MOBILE_VIEWPORT}px) {
width: ${({ isExpanded }) => (isExpanded ? '100%' : '0')};
@@ -57,18 +59,18 @@ const StyledContainer = styled.div<{
flex-direction: column;
width: ${({ isExpanded }) =>
isExpanded ? `var(${NAVIGATION_DRAWER_WIDTH_VAR})` : '100%'};
- gap: ${({ theme }) => theme.spacing(3)};
+ gap: ${themeCssVariables.spacing[3]};
height: 100%;
- padding: ${({ theme, isSettings, isMobile }) =>
+ padding: ${({ isSettings, isMobile }) =>
isSettings
? isMobile
- ? theme.spacing(3, 0, 0, 8)
- : theme.spacing(3, 0, 4, 0)
- : theme.spacing(3, 0, 4, 2)};
+ ? `${themeCssVariables.spacing[3]} 0 0 ${themeCssVariables.spacing[8]}`
+ : `${themeCssVariables.spacing[3]} 0 ${themeCssVariables.spacing[4]} 0`
+ : `${themeCssVariables.spacing[3]} 0 ${themeCssVariables.spacing[4]} ${themeCssVariables.spacing[2]}`};
@media (max-width: ${MOBILE_VIEWPORT}px) {
width: 100%;
- padding-left: ${({ theme }) => theme.spacing(5)};
- padding-right: ${({ theme }) => theme.spacing(5)};
+ padding-left: ${themeCssVariables.spacing[5]};
+ padding-right: ${themeCssVariables.spacing[5]};
}
`;
diff --git a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerAnimatedCollapseWrapper.tsx b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerAnimatedCollapseWrapper.tsx
index 0828630aea..5e480784d5 100644
--- a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerAnimatedCollapseWrapper.tsx
+++ b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerAnimatedCollapseWrapper.tsx
@@ -1,24 +1,27 @@
import { useIsSettingsPage } from '@/navigation/hooks/useIsSettingsPage';
import { isNavigationDrawerExpandedState } from '@/ui/navigation/states/isNavigationDrawerExpanded';
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
-import { useTheme } from '@emotion/react';
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
+import { useContext } from 'react';
import {
type AnimationControls,
motion,
type TargetAndTransition,
} from 'framer-motion';
+import { ThemeContext } from 'twenty-ui/theme';
-const StyledAnimatedContainer = styled(motion.span)`
+const StyledAnimatedContainerBase = styled.span`
display: block;
`;
+const StyledAnimatedContainer = motion.create(StyledAnimatedContainerBase);
+
export const NavigationDrawerAnimatedCollapseWrapper = ({
children,
}: {
children: React.ReactNode;
}) => {
- const theme = useTheme();
+ const { theme } = useContext(ThemeContext);
const isSettingsPage = useIsSettingsPage();
const isNavigationDrawerExpanded = useAtomStateValue(
isNavigationDrawerExpandedState,
diff --git a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerBackButton.tsx b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerBackButton.tsx
index f900005172..7a9c5531a9 100644
--- a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerBackButton.tsx
+++ b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerBackButton.tsx
@@ -1,5 +1,5 @@
-import { useTheme } from '@emotion/react';
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
+import { useContext } from 'react';
import { isNavigationDrawerExpandedState } from '@/ui/navigation/states/isNavigationDrawerExpanded';
import { navigationDrawerExpandedMemorizedState } from '@/ui/navigation/states/navigationDrawerExpandedMemorizedState';
@@ -10,6 +10,8 @@ import { useIsWorkspaceActivationStatusEqualsTo } from '@/workspace/hooks/useIsW
import { WorkspaceActivationStatus } from 'twenty-shared/workspace';
import { IconX } from 'twenty-ui/display';
import { UndecoratedLink } from 'twenty-ui/navigation';
+import { ThemeContext } from 'twenty-ui/theme';
+import { themeCssVariables } from 'twenty-ui/theme-constants';
type NavigationDrawerBackButtonProps = {
title: string;
@@ -19,18 +21,18 @@ const StyledIconAndButtonContainer = styled.button`
align-items: center;
background: inherit;
border: none;
- color: ${({ theme }) => theme.font.color.secondary};
+ color: ${themeCssVariables.font.color.secondary};
cursor: pointer;
display: flex;
flex-direction: row;
- font-weight: ${({ theme }) => theme.font.weight.medium};
- gap: ${({ theme }) => theme.spacing(2)};
- padding: ${({ theme }) => theme.spacing(1.5, 1)};
+ font-weight: ${themeCssVariables.font.weight.medium};
+ gap: ${themeCssVariables.spacing[2]};
+ padding: ${themeCssVariables.spacing['1.5']} ${themeCssVariables.spacing[1]};
width: 100%;
- font-family: ${({ theme }) => theme.font.family};
+ font-family: ${themeCssVariables.font.family};
&:hover {
- background: ${({ theme }) => theme.background.transparent.light};
- border-radius: ${({ theme }) => theme.border.radius.sm};
+ background: ${themeCssVariables.background.transparent.light};
+ border-radius: ${themeCssVariables.border.radius.sm};
}
`;
@@ -38,15 +40,15 @@ const StyledContainer = styled.div`
align-items: center;
display: flex;
flex-direction: row;
- height: ${({ theme }) => theme.spacing(8)};
+ height: ${themeCssVariables.spacing[8]};
justify-content: space-between;
- padding-left: ${({ theme }) => theme.spacing(5)};
+ padding-left: ${themeCssVariables.spacing[5]};
`;
export const NavigationDrawerBackButton = ({
title,
}: NavigationDrawerBackButtonProps) => {
- const theme = useTheme();
+ const { theme } = useContext(ThemeContext);
const navigationMemorizedUrl = useAtomStateValue(navigationMemorizedUrlState);
const setIsNavigationDrawerExpanded = useSetAtomState(
diff --git a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerCollapseButton.tsx b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerCollapseButton.tsx
index d4d880f208..94f2cb08d8 100644
--- a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerCollapseButton.tsx
+++ b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerCollapseButton.tsx
@@ -3,17 +3,18 @@ import { navigationDrawerActiveTabState } from '@/ui/navigation/states/navigatio
import { NAVIGATION_DRAWER_TABS } from '@/ui/navigation/states/navigationDrawerTabs';
import { useAtomState } from '@/ui/utilities/state/jotai/hooks/useAtomState';
import { useSetAtomState } from '@/ui/utilities/state/jotai/hooks/useSetAtomState';
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
import {
IconLayoutSidebarLeftCollapse,
IconLayoutSidebarRightCollapse,
} from 'twenty-ui/display';
import { LightIconButton } from 'twenty-ui/input';
+import { themeCssVariables } from 'twenty-ui/theme-constants';
const StyledCollapseButton = styled.div`
align-items: center;
- border-radius: ${({ theme }) => theme.border.radius.md};
- color: ${({ theme }) => theme.font.color.light};
+ border-radius: ${themeCssVariables.border.radius.md};
+ color: ${themeCssVariables.font.color.light};
cursor: pointer;
display: flex;
justify-content: center;
diff --git a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerFixedContent.tsx b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerFixedContent.tsx
index a1bbfad045..51a46b2137 100644
--- a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerFixedContent.tsx
+++ b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerFixedContent.tsx
@@ -2,20 +2,22 @@ import { type ReactNode } from 'react';
import { useIsSettingsDrawer } from '@/navigation/hooks/useIsSettingsDrawer';
import { NavigationDrawerSection } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerSection';
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
import { useIsMobile } from 'twenty-ui/utilities';
+import { themeCssVariables } from 'twenty-ui/theme-constants';
const StyledFixedContainer = styled.div<{
isSettings?: boolean;
isMobile?: boolean;
}>`
- ${({ isSettings, theme, isMobile }) =>
+ padding-left: ${({ isSettings }) =>
+ isSettings ? themeCssVariables.spacing[5] : '0'};
+ padding-right: ${({ isSettings, isMobile }) =>
isSettings
- ? `
- padding-left: ${theme.spacing(5)};
- padding-right: ${isMobile ? theme.spacing(5) : theme.spacing(8)};
-`
- : ''}
+ ? isMobile
+ ? themeCssVariables.spacing[5]
+ : themeCssVariables.spacing[8]
+ : '0'};
`;
export const NavigationDrawerFixedContent = ({
children,
diff --git a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerHeader.tsx b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerHeader.tsx
index 5dbfcf00f3..fb47aa1617 100644
--- a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerHeader.tsx
+++ b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerHeader.tsx
@@ -1,7 +1,8 @@
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
import { t } from '@lingui/core/macro';
import { IconSearch } from 'twenty-ui/display';
import { LightIconButton } from 'twenty-ui/input';
+import { themeCssVariables } from 'twenty-ui/theme-constants';
import { useOpenRecordsSearchPageInCommandMenu } from '@/command-menu/hooks/useOpenRecordsSearchPageInCommandMenu';
import { PAGE_BAR_MIN_HEIGHT } from '@/ui/layout/page/constants/PageBarMinHeight';
@@ -15,28 +16,28 @@ const StyledContainer = styled.div<{ isExpanded: boolean }>`
align-items: center;
display: flex;
flex-direction: ${({ isExpanded }) => (isExpanded ? 'row' : 'column')};
- gap: ${({ theme, isExpanded }) => (isExpanded ? 0 : theme.spacing(4))};
+ gap: ${({ isExpanded }) => (isExpanded ? '0' : themeCssVariables.spacing[4])};
user-select: none;
- padding-right: ${({ theme }) => theme.spacing(2)};
+ padding-right: ${themeCssVariables.spacing[2]};
min-height: ${PAGE_BAR_MIN_HEIGHT}px;
- transition: gap ${({ theme }) => theme.animation.duration.normal}s ease;
+ transition: gap calc(${themeCssVariables.animation.duration.normal} * 1s) ease;
`;
const StyledRightActions = styled.div<{ isExpanded: boolean }>`
align-items: center;
display: flex;
flex-direction: ${({ isExpanded }) => (isExpanded ? 'row' : 'column')};
- gap: ${({ theme, isExpanded }) => (isExpanded ? 0 : theme.spacing(1))};
- margin-left: ${({ isExpanded }) => (isExpanded ? 'auto' : 0)};
- transition: gap ${({ theme }) => theme.animation.duration.normal}s ease;
+ gap: ${({ isExpanded }) => (isExpanded ? '0' : themeCssVariables.spacing[1])};
+ margin-left: ${({ isExpanded }) => (isExpanded ? 'auto' : '0')};
+ transition: gap calc(${themeCssVariables.animation.duration.normal} * 1s) ease;
`;
const StyledNavigationDrawerCollapseButton = styled(
NavigationDrawerCollapseButton,
)`
- height: ${({ theme }) => theme.spacing(6)};
- padding-right: ${({ theme }) => theme.spacing(1)};
- width: ${({ theme }) => theme.spacing(6)};
+ height: ${themeCssVariables.spacing[6]};
+ padding-right: ${themeCssVariables.spacing[1]};
+ width: ${themeCssVariables.spacing[6]};
`;
type NavigationDrawerHeaderProps = {
diff --git a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerItem.tsx b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerItem.tsx
index 05087d8824..3d2baf6fc2 100644
--- a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerItem.tsx
+++ b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerItem.tsx
@@ -9,12 +9,10 @@ import { isNavigationDrawerExpandedState } from '@/ui/navigation/states/isNaviga
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
import { useAtomState } from '@/ui/utilities/state/jotai/hooks/useAtomState';
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
-import isPropValid from '@emotion/is-prop-valid';
-import { css, useTheme } from '@emotion/react';
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
import { t } from '@lingui/core/macro';
import { isNonEmptyString } from '@sniptt/guards';
-import { type ReactNode } from 'react';
+import { type ReactNode, useContext } from 'react';
import { Link } from 'react-router-dom';
import { isDefined } from 'twenty-shared/utils';
import { Pill } from 'twenty-ui/components';
@@ -27,7 +25,8 @@ import {
TooltipDelay,
TooltipPosition,
} from 'twenty-ui/display';
-import { MOBILE_VIEWPORT } from 'twenty-ui/theme';
+import { ThemeContext } from 'twenty-ui/theme';
+import { MOBILE_VIEWPORT, themeCssVariables } from 'twenty-ui/theme-constants';
import {
type TriggerEventType,
useMouseDownNavigation,
@@ -81,80 +80,70 @@ type StyledItemProps = Pick<
rel?: string;
};
-const StyledItem = styled('button', {
- shouldForwardProp: (prop) =>
- ![
- 'active',
- 'danger',
- 'soon',
- 'isDragging',
- 'isSelectedInEditMode',
- ].includes(prop) && isPropValid(prop),
-})`
+const StyledItem = styled.button`
box-sizing: border-box;
align-items: center;
- background: ${(props) =>
- props.active ? props.theme.background.transparent.light : 'inherit'};
- height: ${({ theme }) => theme.spacing(7)};
- border: ${({ theme, isSelectedInEditMode }) =>
+ background: ${({ active }) =>
+ active ? themeCssVariables.background.transparent.light : 'transparent'};
+ height: ${themeCssVariables.spacing[7]};
+ border: ${({ isSelectedInEditMode }) =>
isSelectedInEditMode
- ? `1px solid ${theme.color.blue}`
+ ? `1px solid ${themeCssVariables.color.blue}`
: '1px solid transparent'};
- border-radius: ${({ theme }) => theme.border.radius.sm};
+ border-radius: ${themeCssVariables.border.radius.sm};
text-decoration: none;
- color: ${(props) => {
- if (props.active === true) {
- return props.theme.font.color.primary;
+ color: ${({ active, danger, soon }) => {
+ if (active === true) {
+ return themeCssVariables.font.color.primary;
}
- if (props.danger === true) {
- return props.theme.color.red;
+ if (danger === true) {
+ return themeCssVariables.color.red;
}
- if (props.soon === true) {
- return props.theme.font.color.light;
+ if (soon === true) {
+ return themeCssVariables.font.color.light;
}
- return props.theme.font.color.secondary;
+ return themeCssVariables.font.color.secondary;
}};
- cursor: ${(props) => (props.soon ? 'default' : 'pointer')};
+ cursor: ${({ soon, isDragging }) =>
+ isDragging ? 'grabbing' : soon ? 'default' : 'pointer'};
display: flex;
- font-family: ${({ theme }) => theme.font.family};
- font-size: ${({ theme }) => theme.font.size.md};
+ font-family: ${themeCssVariables.font.family};
+ font-size: ${themeCssVariables.font.size.md};
- padding-bottom: ${({ theme }) => theme.spacing(1)};
- padding-left: ${({ theme }) => theme.spacing(1)};
- padding-right: ${({ theme, hasRightOptions }) =>
- hasRightOptions ? theme.spacing(0.5) : theme.spacing(1)};
- padding-top: ${({ theme }) => theme.spacing(1)};
+ padding-bottom: ${themeCssVariables.spacing[1]};
+ padding-left: ${themeCssVariables.spacing[1]};
+ padding-right: ${({ hasRightOptions }) =>
+ hasRightOptions
+ ? themeCssVariables.spacing['0.5']
+ : themeCssVariables.spacing[1]};
+ padding-top: ${themeCssVariables.spacing[1]};
margin-top: ${({ indentationLevel }) =>
indentationLevel === 2 ? '2px' : '0'};
- pointer-events: ${(props) => (props.soon ? 'none' : 'auto')};
+ pointer-events: ${({ soon }) => (soon ? 'none' : 'auto')};
- width: ${(props) =>
- !props.isNavigationDrawerExpanded
- ? `calc(${NAVIGATION_DRAWER_COLLAPSED_WIDTH}px - ${props.theme.spacing(6)} + ${props.theme.spacing(1)} + ${props.hasRightOptions ? props.theme.spacing(0.5) : props.theme.spacing(1)})`
- : `calc(100% - ${props.theme.spacing(1.5)} + ${props.theme.spacing(1)} + ${props.hasRightOptions ? props.theme.spacing(0.5) : props.theme.spacing(1)})`};
+ width: ${({ isNavigationDrawerExpanded, hasRightOptions }) =>
+ !isNavigationDrawerExpanded
+ ? `calc(${NAVIGATION_DRAWER_COLLAPSED_WIDTH}px - ${themeCssVariables.spacing[6]} + ${themeCssVariables.spacing[1]} + ${hasRightOptions ? themeCssVariables.spacing['0.5'] : themeCssVariables.spacing[1]})`
+ : `calc(100% - ${themeCssVariables.spacing['1.5']} + ${themeCssVariables.spacing[1]} + ${hasRightOptions ? themeCssVariables.spacing['0.5'] : themeCssVariables.spacing[1]})`};
- ${({ isDragging }) =>
- isDragging &&
- `
- cursor: grabbing;
- `}
-
- :hover {
- background: ${({ theme }) => theme.background.transparent.light};
- color: ${(props) =>
- props.danger ? props.theme.color.red : props.theme.font.color.primary};
+ &:hover {
+ background: ${themeCssVariables.background.transparent.light};
+ color: ${({ danger }) =>
+ danger
+ ? themeCssVariables.color.red
+ : themeCssVariables.font.color.primary};
}
- :hover .keyboard-shortcuts {
+ &:hover .keyboard-shortcuts {
visibility: visible;
}
user-select: none;
@media (max-width: ${MOBILE_VIEWPORT}px) {
- font-size: ${({ theme }) => theme.font.size.lg};
+ font-size: ${themeCssVariables.font.size.lg};
}
`;
@@ -175,22 +164,22 @@ const StyledLabelParent = styled.div`
`;
const StyledItemLabel = styled.span`
- font-weight: ${({ theme }) => theme.font.weight.medium};
+ font-weight: ${themeCssVariables.font.weight.medium};
`;
const StyledItemSecondaryLabel = styled.span`
- color: ${({ theme }) => theme.font.color.light};
- font-weight: ${({ theme }) => theme.font.weight.regular};
+ color: ${themeCssVariables.font.color.light};
+ font-weight: ${themeCssVariables.font.weight.regular};
`;
const StyledItemCount = styled.span`
align-items: center;
- background-color: ${({ theme }) => theme.color.blue};
- border-radius: ${({ theme }) => theme.border.radius.rounded};
- color: ${({ theme }) => theme.grayScale.gray1};
+ background-color: ${themeCssVariables.color.blue};
+ border-radius: ${themeCssVariables.border.radius.rounded};
+ color: ${themeCssVariables.grayScale.gray1};
display: flex;
- font-size: ${({ theme }) => theme.font.size.xs};
- font-weight: ${({ theme }) => theme.font.weight.semiBold};
+ font-size: ${themeCssVariables.font.size.xs};
+ font-weight: ${themeCssVariables.font.weight.semiBold};
height: 16px;
justify-content: center;
margin-left: auto;
@@ -201,15 +190,15 @@ const StyledKeyBoardShortcut = styled.span`
align-items: center;
display: flex;
flex-direction: column;
- gap: ${({ theme }) => theme.spacing(2)};
- height: ${({ theme }) => theme.spacing(4)};
+ gap: ${themeCssVariables.spacing[2]};
+ height: ${themeCssVariables.spacing[4]};
justify-content: center;
- width: ${({ theme }) => theme.spacing(4)};
+ width: ${themeCssVariables.spacing[4]};
box-sizing: border-box;
- border-radius: ${({ theme }) => theme.border.radius.sm};
- border: 1px solid ${({ theme }) => theme.border.color.strong};
- background: ${({ theme }) => theme.background.transparent.lighter};
+ border-radius: ${themeCssVariables.border.radius.sm};
+ border: 1px solid ${themeCssVariables.border.color.strong};
+ background: ${themeCssVariables.background.transparent.lighter};
`;
const StyledNavigationDrawerItemContainer = styled.div`
@@ -230,18 +219,18 @@ const StyledIcon = styled.div<{
flex-grow: 0;
flex-shrink: 0;
justify-content: center;
- margin-right: ${({ theme }) => theme.spacing(2)};
-
- ${({ theme, $backgroundColor, $borderColor }) =>
- $backgroundColor &&
- css`
- background-color: ${$backgroundColor};
- border-radius: 4px;
- box-sizing: border-box;
- height: ${theme.spacing(4)};
- width: ${theme.spacing(4)};
- ${$borderColor ? `border: 1px solid ${$borderColor};` : ''}
- `}
+ margin-right: ${themeCssVariables.spacing[2]};
+ background-color: ${({ $backgroundColor }) =>
+ $backgroundColor || 'transparent'};
+ border-radius: ${({ $backgroundColor }) => ($backgroundColor ? '4px' : '0')};
+ box-sizing: ${({ $backgroundColor }) =>
+ $backgroundColor ? 'border-box' : 'content-box'};
+ height: ${({ $backgroundColor }) =>
+ $backgroundColor ? themeCssVariables.spacing[4] : 'auto'};
+ width: ${({ $backgroundColor }) =>
+ $backgroundColor ? themeCssVariables.spacing[4] : 'auto'};
+ border: ${({ $backgroundColor, $borderColor }) =>
+ $backgroundColor && $borderColor ? `1px solid ${$borderColor}` : 'none'};
`;
const StyledRightOptionsContainer = styled.div`
@@ -250,42 +239,31 @@ const StyledRightOptionsContainer = styled.div`
justify-content: center;
flex-shrink: 0;
flex-grow: 0;
- height: ${({ theme }) => theme.spacing(6)};
- border-radius: ${({ theme }) => theme.border.radius.sm};
+ height: ${themeCssVariables.spacing[6]};
+ border-radius: ${themeCssVariables.border.radius.sm};
`;
-const visibleStateStyles = css`
- clip-path: unset;
- display: flex;
- height: unset;
- opacity: 1;
- overflow: unset;
- position: unset;
- width: unset;
-`;
-
-const StyledRightOptionsVisbility = styled.div<{
- isMobile: boolean;
- isRightOptionsDropdownOpen?: boolean;
- alwaysVisible?: boolean;
-}>`
+const StyledRightOptionsVisbility = styled.div`
display: block;
opacity: 0;
transition: opacity 150ms;
position: absolute;
- padding-left: ${({ theme }) => theme.spacing(2)};
+ padding-left: ${themeCssVariables.spacing[2]};
overflow: hidden;
clip-path: inset(1px);
white-space: nowrap;
height: 1px;
width: 1px;
- ${({ isMobile, isRightOptionsDropdownOpen, alwaysVisible }) =>
- (isMobile || isRightOptionsDropdownOpen || alwaysVisible) &&
- visibleStateStyles}
-
+ &[data-visible='true'],
.navigation-drawer-item:hover & {
- ${visibleStateStyles}
+ clip-path: unset;
+ display: flex;
+ height: unset;
+ opacity: 1;
+ overflow: unset;
+ position: unset;
+ width: unset;
}
`;
@@ -314,7 +292,7 @@ export const NavigationDrawerItem = ({
preventCollapseOnMobile = false,
isSelectedInEditMode = false,
}: NavigationDrawerItemProps) => {
- const theme = useTheme();
+ const { theme } = useContext(ThemeContext);
const isMobile = useIsMobile();
const isSettingsPage = useIsSettingsPage();
const isNavigationMenuItemEditingEnabled = useIsFeatureEnabled(
@@ -472,10 +450,12 @@ export const NavigationDrawerItem = ({
}}
>
{rightOptions}
diff --git a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerItemBreadcrumb.tsx b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerItemBreadcrumb.tsx
index 3d8602e4ac..798d3ac934 100644
--- a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerItemBreadcrumb.tsx
+++ b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerItemBreadcrumb.tsx
@@ -1,5 +1,6 @@
import { type NavigationDrawerSubItemState } from '@/ui/navigation/navigation-drawer/types/NavigationDrawerSubItemState';
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
+import { themeCssVariables } from 'twenty-ui/theme-constants';
export type NavigationDrawerItemBreadcrumbProps = {
state?: NavigationDrawerSubItemState;
@@ -9,13 +10,15 @@ const StyledNavigationDrawerItemBreadcrumbContainer = styled.div`
height: 28px;
margin-left: 7.5px;
- margin-right: ${({ theme }) => theme.spacing(2)};
+ margin-right: ${themeCssVariables.spacing[2]};
width: 9px;
`;
const StyledGapVerticalLine = styled.div<{ darker: boolean }>`
- background: ${({ theme, darker }) =>
- darker ? theme.font.color.tertiary : theme.border.color.strong};
+ background: ${({ darker }) =>
+ darker
+ ? themeCssVariables.font.color.tertiary
+ : themeCssVariables.border.color.strong};
position: relative;
top: -2px;
@@ -25,8 +28,10 @@ const StyledGapVerticalLine = styled.div<{ darker: boolean }>`
`;
const StyledSecondaryFullVerticalBar = styled.div<{ darker: boolean }>`
- background: ${({ theme, darker }) =>
- darker ? theme.font.color.tertiary : theme.border.color.strong};
+ background: ${({ darker }) =>
+ darker
+ ? themeCssVariables.font.color.tertiary
+ : themeCssVariables.border.color.strong};
position: relative;
top: -17px;
@@ -35,21 +40,23 @@ const StyledSecondaryFullVerticalBar = styled.div<{ darker: boolean }>`
`;
const StyledRoundedProtrusion = styled.div<{ darker: boolean }>`
- position: relative;
- top: -2px;
-
+ border: 1px solid
+ ${({ darker }) =>
+ darker
+ ? themeCssVariables.font.color.tertiary
+ : themeCssVariables.border.color.strong};
border-bottom-left-radius: 4px;
- border: 1px solid
- ${({ theme, darker }) =>
- darker ? theme.font.color.tertiary : theme.border.color.strong};
-
- ${({ darker }) => (darker ? 'z-index: 1;' : '')}
+ border-right: none;
border-top: none;
- border-right: none;
+
height: 14px;
+
+ position: relative;
+ top: -2px;
width: 8px;
+ z-index: ${({ darker }) => (darker ? '1' : 'auto')};
`;
export const NavigationDrawerItemBreadcrumb = ({
diff --git a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerItemGroup.tsx b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerItemGroup.tsx
index dfb9b5f7c6..904c947dab 100644
--- a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerItemGroup.tsx
+++ b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerItemGroup.tsx
@@ -1,4 +1,4 @@
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
const StyledGroup = styled.div`
display: flex;
diff --git a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerItemsCollapsableContainer.tsx b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerItemsCollapsableContainer.tsx
index fffb551155..9dd2dd83f5 100644
--- a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerItemsCollapsableContainer.tsx
+++ b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerItemsCollapsableContainer.tsx
@@ -1,16 +1,20 @@
import { useIsSettingsPage } from '@/navigation/hooks/useIsSettingsPage';
import { isNavigationDrawerExpandedState } from '@/ui/navigation/states/isNavigationDrawerExpanded';
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
-import { useTheme } from '@emotion/react';
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
+import { useContext, type ReactNode } from 'react';
import {
type AnimationControls,
motion,
type TargetAndTransition,
} from 'framer-motion';
-import { type ReactNode } from 'react';
+import { ThemeContext } from 'twenty-ui/theme';
-const StyledAnimationGroupContainer = styled(motion.div)``;
+const StyledAnimationGroupContainerBase = styled.div``;
+
+const StyledAnimationGroupContainer = motion.create(
+ StyledAnimationGroupContainerBase,
+);
type NavigationDrawerItemsCollapsableContainerProps = {
isGroup?: boolean;
@@ -21,7 +25,7 @@ export const NavigationDrawerItemsCollapsableContainer = ({
isGroup = false,
children,
}: NavigationDrawerItemsCollapsableContainerProps) => {
- const theme = useTheme();
+ const { theme } = useContext(ThemeContext);
const isSettingsPage = useIsSettingsPage();
const isNavigationDrawerExpanded = useAtomStateValue(
isNavigationDrawerExpandedState,
diff --git a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerScrollableContent.tsx b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerScrollableContent.tsx
index 6ec5905fed..47ca1d27d7 100644
--- a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerScrollableContent.tsx
+++ b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerScrollableContent.tsx
@@ -1,8 +1,9 @@
import { useIsSettingsDrawer } from '@/navigation/hooks/useIsSettingsDrawer';
import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper';
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
import { type ReactNode } from 'react';
import { useIsMobile } from 'twenty-ui/utilities';
+import { themeCssVariables } from 'twenty-ui/theme-constants';
const StyledItemsContainer = styled.div`
display: flex;
@@ -14,9 +15,9 @@ const StyledItemsContainer = styled.div`
const StyledScrollableInnerContainer = styled.div<{ isMobile?: boolean }>`
height: 100%;
- padding-left: ${({ theme }) => theme.spacing(5)};
- padding-right: ${({ theme, isMobile }) =>
- isMobile ? theme.spacing(5) : theme.spacing(8)};
+ padding-left: ${themeCssVariables.spacing[5]};
+ padding-right: ${({ isMobile }) =>
+ isMobile ? themeCssVariables.spacing[5] : themeCssVariables.spacing[8]};
`;
export const NavigationDrawerScrollableContent = ({
diff --git a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerSection.tsx b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerSection.tsx
index 3e535e3271..782436a3af 100644
--- a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerSection.tsx
+++ b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerSection.tsx
@@ -1,10 +1,11 @@
import { useIsSettingsDrawer } from '@/navigation/hooks/useIsSettingsDrawer';
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
import { useIsMobile } from 'twenty-ui/utilities';
+import { themeCssVariables } from 'twenty-ui/theme-constants';
const StyledSection = styled.div<{ isSettingsDrawer?: boolean }>`
- margin-bottom: ${({ theme, isSettingsDrawer }) =>
- isSettingsDrawer ? theme.spacing(3) : 0};
+ margin-bottom: ${({ isSettingsDrawer }) =>
+ isSettingsDrawer ? themeCssVariables.spacing[3] : '0'};
width: 100%;
`;
@@ -14,9 +15,11 @@ const StyledSectionInnerContainerMinusScrollPadding = styled.div<{
}>`
display: flex;
flex-direction: column;
- gap: ${({ theme }) => theme.betweenSiblingsGap};
- width: ${({ isMobile, theme, isSettingsDrawer }) =>
- `calc(100% - ${isMobile || isSettingsDrawer ? 0 : theme.spacing(2)})`};
+ gap: ${themeCssVariables.betweenSiblingsGap};
+ width: ${({ isMobile, isSettingsDrawer }) =>
+ isMobile || isSettingsDrawer
+ ? '100%'
+ : `calc(100% - ${themeCssVariables.spacing[2]})`};
`;
export const NavigationDrawerSection = ({
diff --git a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerSectionTitle.tsx b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerSectionTitle.tsx
index 4880266cc2..c106c5c702 100644
--- a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerSectionTitle.tsx
+++ b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerSectionTitle.tsx
@@ -5,25 +5,26 @@ import { NavigationDrawerSectionTitleSkeletonLoader } from '@/ui/navigation/navi
import { isNavigationDrawerExpandedState } from '@/ui/navigation/states/isNavigationDrawerExpanded';
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
import React from 'react';
import { isDefined } from 'twenty-shared/utils';
import { Label } from 'twenty-ui/display';
+import { themeCssVariables } from 'twenty-ui/theme-constants';
const StyledTitle = styled.div`
align-items: center;
- border-radius: ${({ theme }) => theme.border.radius.sm};
+ border-radius: ${themeCssVariables.border.radius.sm};
display: flex;
- height: ${({ theme }) => theme.spacing(5)};
- padding-left: ${({ theme }) => theme.spacing(1)};
- padding-right: ${({ theme }) => theme.spacing(0.5)};
- padding-top: ${({ theme }) => theme.spacing(1)};
- padding-bottom: ${({ theme }) => theme.spacing(1)};
+ height: ${themeCssVariables.spacing[5]};
+ padding-left: ${themeCssVariables.spacing[1]};
+ padding-right: ${themeCssVariables.spacing['0.5']};
+ padding-top: ${themeCssVariables.spacing[1]};
+ padding-bottom: ${themeCssVariables.spacing[1]};
justify-content: space-between;
&:hover {
cursor: pointer;
- background-color: ${({ theme }) => theme.background.transparent.light};
+ background-color: ${themeCssVariables.background.transparent.light};
}
`;
diff --git a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerSectionTitleSkeletonLoader.tsx b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerSectionTitleSkeletonLoader.tsx
index 5391ea3e32..051caf7dd0 100644
--- a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerSectionTitleSkeletonLoader.tsx
+++ b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerSectionTitleSkeletonLoader.tsx
@@ -1,15 +1,17 @@
import { SKELETON_LOADER_HEIGHT_SIZES } from '@/activities/components/SkeletonLoader';
-import { useTheme } from '@emotion/react';
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
+import { useContext } from 'react';
import Skeleton, { SkeletonTheme } from 'react-loading-skeleton';
+import { ThemeContext } from 'twenty-ui/theme';
+import { themeCssVariables } from 'twenty-ui/theme-constants';
const StyledSkeletonTitle = styled.div`
- margin-bottom: ${(props) => props.theme.spacing(2)};
- padding-left: ${({ theme }) => theme.spacing(1)};
+ margin-bottom: ${themeCssVariables.spacing[2]};
+ padding-left: ${themeCssVariables.spacing[1]};
`;
export const NavigationDrawerSectionTitleSkeletonLoader = () => {
- const theme = useTheme();
+ const { theme } = useContext(ThemeContext);
return (
`
align-items: center;
@@ -15,15 +16,15 @@ const StyledContainer = styled.div<{ isLast: boolean }>`
}
`;
-const StyledStepCircle = styled(motion.div)<{ isInNextSteps: boolean }>`
+const StyledStepCircleBase = styled.div<{ isInNextSteps: boolean }>`
align-items: center;
border-radius: 50%;
border-style: solid;
border-width: 1px;
- border-color: ${({ theme, isInNextSteps }) =>
+ border-color: ${({ isInNextSteps }) =>
isInNextSteps
- ? theme.border.color.medium
- : theme.border.color.inverted} !important;
+ ? themeCssVariables.border.color.medium
+ : themeCssVariables.border.color.inverted} !important;
display: flex;
flex-basis: auto;
flex-shrink: 0;
@@ -34,30 +35,38 @@ const StyledStepCircle = styled(motion.div)<{ isInNextSteps: boolean }>`
width: 20px;
`;
+const StyledStepCircle = motion.create(StyledStepCircleBase);
+
const StyledStepIndex = styled.span<{ isCurrentStep: boolean }>`
- color: ${({ theme, isCurrentStep }) =>
- isCurrentStep ? theme.font.color.inverted : theme.font.color.tertiary};
- font-size: ${({ theme }) => theme.font.size.md};
- font-weight: ${({ theme }) => theme.font.weight.medium};
+ color: ${({ isCurrentStep }) =>
+ isCurrentStep
+ ? themeCssVariables.font.color.inverted
+ : themeCssVariables.font.color.tertiary};
+ font-size: ${themeCssVariables.font.size.md};
+ font-weight: ${themeCssVariables.font.weight.medium};
`;
const StyledStepLabel = styled.span<{ isInNextSteps: boolean }>`
- color: ${({ theme, isInNextSteps }) =>
- isInNextSteps ? theme.font.color.tertiary : theme.font.color.primary};
- font-size: ${({ theme }) => theme.font.size.md};
- font-weight: ${({ theme }) => theme.font.weight.semiBold};
- margin-left: ${({ theme }) => theme.spacing(2)};
+ color: ${({ isInNextSteps }) =>
+ isInNextSteps
+ ? themeCssVariables.font.color.tertiary
+ : themeCssVariables.font.color.primary};
+ font-size: ${themeCssVariables.font.size.md};
+ font-weight: ${themeCssVariables.font.weight.semiBold};
+ margin-left: ${themeCssVariables.spacing[2]};
white-space: nowrap;
`;
-const StyledStepLine = styled(motion.div)`
+const StyledStepLineBase = styled.div`
height: 2px;
- margin-left: ${({ theme }) => theme.spacing(2)};
- margin-right: ${({ theme }) => theme.spacing(2)};
+ margin-left: ${themeCssVariables.spacing[2]};
+ margin-right: ${themeCssVariables.spacing[2]};
overflow: hidden;
width: 100%;
`;
+const StyledStepLine = motion.create(StyledStepLineBase);
+
export type StepProps = React.PropsWithChildren &
React.ComponentProps<'div'> & {
isLast?: boolean;
@@ -73,7 +82,7 @@ export const Step = ({
children,
activeStep = 0,
}: StepProps) => {
- const theme = useTheme();
+ const { theme } = useContext(ThemeContext);
const isMobile = useIsMobile();
const variantsLine = {
diff --git a/packages/twenty-front/src/modules/ui/navigation/step-bar/components/StepBar.tsx b/packages/twenty-front/src/modules/ui/navigation/step-bar/components/StepBar.tsx
index b9d777fdb0..970417bc0e 100644
--- a/packages/twenty-front/src/modules/ui/navigation/step-bar/components/StepBar.tsx
+++ b/packages/twenty-front/src/modules/ui/navigation/step-bar/components/StepBar.tsx
@@ -1,9 +1,9 @@
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
import React from 'react';
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
-import { MOBILE_VIEWPORT } from 'twenty-ui/theme';
+import { MOBILE_VIEWPORT } from 'twenty-ui/theme-constants';
import { Step, type StepProps } from './Step';
const StyledContainer = styled.div`
diff --git a/packages/twenty-front/src/modules/ui/theme/components/BaseThemeProvider.tsx b/packages/twenty-front/src/modules/ui/theme/components/BaseThemeProvider.tsx
index aae5d745bd..cf469d1494 100644
--- a/packages/twenty-front/src/modules/ui/theme/components/BaseThemeProvider.tsx
+++ b/packages/twenty-front/src/modules/ui/theme/components/BaseThemeProvider.tsx
@@ -1,4 +1,3 @@
-import { ThemeProvider } from '@emotion/react';
import { createContext } from 'react';
import { useSystemColorScheme } from '@/ui/theme/hooks/useSystemColorScheme';
@@ -32,9 +31,7 @@ export const BaseThemeProvider = ({ children }: BaseThemeProviderProps) => {
return (
-
- {children}
-
+ {children}
);
};
diff --git a/packages/twenty-front/src/modules/ui/utilities/drag-select/components/DragSelect.tsx b/packages/twenty-front/src/modules/ui/utilities/drag-select/components/DragSelect.tsx
index 9c75af260e..cd894b2a1a 100644
--- a/packages/twenty-front/src/modules/ui/utilities/drag-select/components/DragSelect.tsx
+++ b/packages/twenty-front/src/modules/ui/utilities/drag-select/components/DragSelect.tsx
@@ -1,4 +1,4 @@
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
import { type RefObject, useCallback, useState } from 'react';
import { useDragSelect } from '@/ui/utilities/drag-select/hooks/useDragSelect';
@@ -23,12 +23,14 @@ type Position = {
y: number;
};
+import { themeCssVariables } from 'twenty-ui/theme-constants';
+
const StyledDragSelection = styled.div`
position: absolute;
z-index: 99;
opacity: 0.2;
- border: 1px solid ${({ theme }) => theme.color.blue3};
- background: ${({ theme }) => theme.color.blue7};
+ border: 1px solid ${themeCssVariables.color.blue3};
+ background: ${themeCssVariables.color.blue7};
top: ${({ top }) => top}px;
left: ${({ left }) => left}px;
width: ${({ width }) => width}px;
diff --git a/packages/twenty-front/src/modules/ui/utilities/drag-select/components/__stories__/DragSelect.stories.tsx b/packages/twenty-front/src/modules/ui/utilities/drag-select/components/__stories__/DragSelect.stories.tsx
index 6c59f6ea1f..71cbd6b92f 100644
--- a/packages/twenty-front/src/modules/ui/utilities/drag-select/components/__stories__/DragSelect.stories.tsx
+++ b/packages/twenty-front/src/modules/ui/utilities/drag-select/components/__stories__/DragSelect.stories.tsx
@@ -1,4 +1,4 @@
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
import { type Meta, type StoryObj } from '@storybook/react-vite';
import { useRef, useState } from 'react';
import { userEvent, within } from 'storybook/test';
@@ -7,13 +7,14 @@ import { DragSelect } from '@/ui/utilities/drag-select/components/DragSelect';
import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper';
import { isDefined } from 'twenty-shared/utils';
import { ComponentDecorator } from 'twenty-ui/testing';
+import { themeCssVariables } from 'twenty-ui/theme-constants';
const StyledContainer = styled.div`
- border: 1px solid ${({ theme }) => theme.border.color.light};
- border-radius: ${({ theme }) => theme.border.radius.md};
+ border: 1px solid ${themeCssVariables.border.color.light};
+ border-radius: ${themeCssVariables.border.radius.md};
height: 400px;
overflow: hidden;
- padding: ${({ theme }) => theme.spacing(4)};
+ padding: ${themeCssVariables.spacing[4]};
position: relative;
width: 600px;
`;
@@ -21,27 +22,31 @@ const StyledContainer = styled.div`
const StyledSelectableItem = styled.div<{ selected?: boolean }>`
width: 100px;
height: 80px;
- border: 1px solid ${({ theme }) => theme.border.color.medium};
- border-radius: ${({ theme }) => theme.border.radius.sm};
- background: ${({ theme, selected }) =>
- selected ? theme.color.blue3 : theme.background.secondary};
+ border: 1px solid ${themeCssVariables.border.color.medium};
+ border-radius: ${themeCssVariables.border.radius.sm};
+ background: ${({ selected }) =>
+ selected
+ ? themeCssVariables.color.blue3
+ : themeCssVariables.background.secondary};
display: flex;
align-items: center;
justify-content: center;
- margin: ${({ theme }) => theme.spacing(1)};
+ margin: ${themeCssVariables.spacing[1]};
user-select: none;
cursor: pointer;
&:hover {
- background: ${({ theme, selected }) =>
- selected ? theme.color.blue5 : theme.background.tertiary};
+ background: ${({ selected }) =>
+ selected
+ ? themeCssVariables.color.blue5
+ : themeCssVariables.background.tertiary};
}
`;
const StyledGrid = styled.div`
display: grid;
grid-template-columns: repeat(4, 1fr);
- gap: ${({ theme }) => theme.spacing(2)};
+ gap: ${themeCssVariables.spacing[2]};
width: 100%;
height: 100%;
`;
@@ -49,15 +54,15 @@ const StyledGrid = styled.div`
const StyledLargeGrid = styled.div`
display: grid;
grid-template-columns: repeat(6, 1fr);
- gap: ${({ theme }) => theme.spacing(2)};
- padding: ${({ theme }) => theme.spacing(4)};
+ gap: ${themeCssVariables.spacing[2]};
+ padding: ${themeCssVariables.spacing[4]};
width: 900px;
height: 600px;
`;
const StyledScrollableWrapper = styled(ScrollWrapper)`
- border: 1px solid ${({ theme }) => theme.border.color.light};
- border-radius: ${({ theme }) => theme.border.radius.md};
+ border: 1px solid ${themeCssVariables.border.color.light};
+ border-radius: ${themeCssVariables.border.radius.md};
height: 300px;
width: 600px;
`;
diff --git a/packages/twenty-front/src/modules/ui/utilities/responsive/hooks/useIsMobile.ts b/packages/twenty-front/src/modules/ui/utilities/responsive/hooks/useIsMobile.ts
index 6b51d75e2e..6cc69d0321 100644
--- a/packages/twenty-front/src/modules/ui/utilities/responsive/hooks/useIsMobile.ts
+++ b/packages/twenty-front/src/modules/ui/utilities/responsive/hooks/useIsMobile.ts
@@ -1,5 +1,5 @@
import { useMediaQuery } from 'react-responsive';
-import { MOBILE_VIEWPORT } from 'twenty-ui/theme';
+import { MOBILE_VIEWPORT } from 'twenty-ui/theme-constants';
export const useIsMobile = () =>
useMediaQuery({ query: `(max-width: ${MOBILE_VIEWPORT}px)` });
diff --git a/packages/twenty-front/src/modules/ui/utilities/scroll/components/ScrollWrapper.tsx b/packages/twenty-front/src/modules/ui/utilities/scroll/components/ScrollWrapper.tsx
index 3925b4b8cd..290cf10d99 100644
--- a/packages/twenty-front/src/modules/ui/utilities/scroll/components/ScrollWrapper.tsx
+++ b/packages/twenty-front/src/modules/ui/utilities/scroll/components/ScrollWrapper.tsx
@@ -1,4 +1,4 @@
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
import { ScrollWrapperInitEffect } from '@/ui/utilities/scroll/components/internal/ScrollWrapperInitEffect';
import { ScrollWrapperComponentInstanceContext } from '@/ui/utilities/scroll/states/contexts/ScrollWrapperComponentInstanceContext';
diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-edges/components/WorkflowDiagramEdgeButtonGroup.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-edges/components/WorkflowDiagramEdgeButtonGroup.tsx
index 13e67bbf86..4e34b10b0d 100644
--- a/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-edges/components/WorkflowDiagramEdgeButtonGroup.tsx
+++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-edges/components/WorkflowDiagramEdgeButtonGroup.tsx
@@ -1,18 +1,14 @@
-import { getWorkflowDiagramColors } from '@/workflow/workflow-diagram/utils/getWorkflowDiagramColors';
-import { css } from '@linaria/core';
import { styled } from '@linaria/react';
-import { useContext, useMemo, type CSSProperties } from 'react';
import { IconButtonGroup, type IconButtonGroupProps } from 'twenty-ui/input';
-import { ThemeContext } from 'twenty-ui/theme';
+import { themeCssVariables } from 'twenty-ui/theme-constants';
-const iconButtonGroupStyle = css`
- background-color: var(--edge-btn-bg, transparent);
- border: var(--edge-btn-border, none);
+const StyledIconButtonGroup = styled(IconButtonGroup)`
pointer-events: all;
`;
-const StyledWrapper = styled.div`
- display: contents;
+const StyledSelectedIconButtonGroup = styled(StyledIconButtonGroup)`
+ background-color: ${themeCssVariables.color.blue2};
+ border-color: ${themeCssVariables.color.blue};
`;
type WorkflowDiagramEdgeButtonGroupProps = IconButtonGroupProps & {
@@ -23,24 +19,9 @@ export const WorkflowDiagramEdgeButtonGroup = ({
selected = false,
iconButtons,
}: WorkflowDiagramEdgeButtonGroupProps) => {
- const { theme } = useContext(ThemeContext);
+ const ButtonGroup = selected
+ ? StyledSelectedIconButtonGroup
+ : StyledIconButtonGroup;
- const dynamicStyles = useMemo(() => {
- if (!selected) return {};
- const colors = getWorkflowDiagramColors({ theme });
- return {
- '--edge-btn-bg': colors.selected.background,
- // eslint-disable-next-line lingui/no-unlocalized-strings
- '--edge-btn-border': `1px solid ${colors.selected.borderColor}`,
- } as CSSProperties;
- }, [selected, theme]);
-
- return (
-
-
-
- );
+ return ;
};
diff --git a/packages/twenty-front/src/modules/workspace/components/WorkspaceInviteTeam.tsx b/packages/twenty-front/src/modules/workspace/components/WorkspaceInviteTeam.tsx
index 9108eb78ed..026f56c6e7 100644
--- a/packages/twenty-front/src/modules/workspace/components/WorkspaceInviteTeam.tsx
+++ b/packages/twenty-front/src/modules/workspace/components/WorkspaceInviteTeam.tsx
@@ -22,8 +22,7 @@ import {
type IconComponent,
} from 'twenty-ui/display';
import { Button } from 'twenty-ui/input';
-import { MOBILE_VIEWPORT } from 'twenty-ui/theme';
-import { themeCssVariables } from 'twenty-ui/theme-constants';
+import { MOBILE_VIEWPORT, themeCssVariables } from 'twenty-ui/theme-constants';
const StyledContainer = styled.div`
display: flex;
diff --git a/packages/twenty-front/src/pages/settings/developers/api-keys/SettingsApiKeys.tsx b/packages/twenty-front/src/pages/settings/developers/api-keys/SettingsApiKeys.tsx
index c5575ed5d1..0cf0975dda 100644
--- a/packages/twenty-front/src/pages/settings/developers/api-keys/SettingsApiKeys.tsx
+++ b/packages/twenty-front/src/pages/settings/developers/api-keys/SettingsApiKeys.tsx
@@ -10,8 +10,7 @@ import { getSettingsPath } from 'twenty-shared/utils';
import { H2Title, IconPlus } from 'twenty-ui/display';
import { Button } from 'twenty-ui/input';
import { Section } from 'twenty-ui/layout';
-import { MOBILE_VIEWPORT } from 'twenty-ui/theme';
-import { themeCssVariables } from 'twenty-ui/theme-constants';
+import { MOBILE_VIEWPORT, themeCssVariables } from 'twenty-ui/theme-constants';
const StyledButtonContainer = styled.div`
display: flex;
diff --git a/packages/twenty-front/src/pages/settings/developers/webhooks/components/SettingsWebhooks.tsx b/packages/twenty-front/src/pages/settings/developers/webhooks/components/SettingsWebhooks.tsx
index f911714ee9..9b3973b08f 100644
--- a/packages/twenty-front/src/pages/settings/developers/webhooks/components/SettingsWebhooks.tsx
+++ b/packages/twenty-front/src/pages/settings/developers/webhooks/components/SettingsWebhooks.tsx
@@ -9,8 +9,7 @@ import { getSettingsPath } from 'twenty-shared/utils';
import { H2Title, IconPlus } from 'twenty-ui/display';
import { Button } from 'twenty-ui/input';
import { Section } from 'twenty-ui/layout';
-import { MOBILE_VIEWPORT } from 'twenty-ui/theme';
-import { themeCssVariables } from 'twenty-ui/theme-constants';
+import { MOBILE_VIEWPORT, themeCssVariables } from 'twenty-ui/theme-constants';
const StyledButtonContainer = styled.div`
display: flex;
diff --git a/packages/twenty-front/src/pages/settings/workspace/SettingsApiWebhooks.tsx b/packages/twenty-front/src/pages/settings/workspace/SettingsApiWebhooks.tsx
index eb16d61215..460bb5d331 100644
--- a/packages/twenty-front/src/pages/settings/workspace/SettingsApiWebhooks.tsx
+++ b/packages/twenty-front/src/pages/settings/workspace/SettingsApiWebhooks.tsx
@@ -12,8 +12,7 @@ import { getSettingsPath } from 'twenty-shared/utils';
import { H2Title, IconPlus } from 'twenty-ui/display';
import { Button } from 'twenty-ui/input';
import { Section } from 'twenty-ui/layout';
-import { MOBILE_VIEWPORT } from 'twenty-ui/theme';
-import { themeCssVariables } from 'twenty-ui/theme-constants';
+import { MOBILE_VIEWPORT, themeCssVariables } from 'twenty-ui/theme-constants';
const StyledButtonContainer = styled.div`
display: flex;
diff --git a/packages/twenty-front/vite.config.ts b/packages/twenty-front/vite.config.ts
index 81f4c9dc22..91c9916c23 100644
--- a/packages/twenty-front/vite.config.ts
+++ b/packages/twenty-front/vite.config.ts
@@ -96,7 +96,6 @@ export default defineConfig(({ command, mode }) => {
plugins: [
react({
- jsxImportSource: '@emotion/react',
plugins: [['@lingui/swc-plugin', {}]],
}),
tsconfigPaths({
@@ -110,570 +109,26 @@ export default defineConfig(({ command, mode }) => {
checker(checkers),
{
...wyw({
- include: [
- '**/twenty-ui/src/**/*.{ts,tsx}',
- '**/AdvancedTextEditor.tsx',
- '**/FileUploadProvider.tsx',
- '**/MultiSelectControl.tsx',
- '**/FormNumberFieldInput.tsx',
- '**/FormUuidFieldInput.tsx',
- '**/KeyboardShortcutMenuStyles.tsx',
- '**/BubbleMenuIconButton.tsx',
- '**/TextBubbleMenu.tsx',
- '**/TurnIntoBlockDropdown.tsx',
- '**/WorkflowAttachmentChip.tsx',
- '**/WorkflowSendEmailAttachments.tsx',
- '**/ResizableImageView.tsx',
- '**/SettingsBillingSubscriptionInfo.tsx',
- '**/SubscriptionBenefit.tsx',
- '**/SubscriptionInfoContainer.tsx',
- '**/SubscriptionPrice.tsx',
- '**/TrialCard.tsx',
- '**/MeteredPriceSelector.tsx',
- '**/PlansTags.tsx',
- '**/SettingsBillingLabelValueItem.tsx',
- '**/SubscriptionInfoRowContainer.tsx',
- '**/FileBlock.tsx',
- '**/MentionInlineContent.tsx',
- '**/BlockEditor.tsx',
- '**/CustomMentionMenu.tsx',
- '**/CustomSideMenu.tsx',
- '**/CustomSideMenuOptions.tsx',
- '**/CustomSlashMenu.tsx',
- '**/CurrentWorkspaceMemberOrphanFavorites.tsx',
- '**/FavoritesBackButton.tsx',
- '**/FavoritesDroppable.tsx',
- '**/FavoritesSkeletonLoader.tsx',
- '**/FavoriteFolderPickerList.tsx',
- '**/InformationBanner.tsx',
- '**/InformationBannerWrapper.tsx',
- '**/InformationBannerDeletedRecord.tsx',
- '**/AddToNavigationDragHandle.tsx',
- '**/CurrentWorkspaceMemberOrphanNavigationMenuItems.tsx',
- '**/NavigationItemDropTarget.tsx',
- '**/NavigationMenuEditModeBar.tsx',
- '**/NavigationMenuItemBackButton.tsx',
- '**/NavigationMenuItemDroppable.tsx',
- '**/NavigationMenuItemIconContainer.tsx',
- '**/NavigationMenuItemSkeletonLoader.tsx',
- '**/ObjectIconWithViewOverlay.tsx',
- '**/WorkspaceNavigationMenuItems.tsx',
- '**/WorkspaceNavigationMenuItemsFolder.tsx',
- '**/MainNavigationDrawerAIChatContent.tsx',
- '**/MainNavigationDrawerNavigationContent.tsx',
- '**/MainNavigationDrawerScrollableItems.tsx',
- '**/MainNavigationDrawerTabsRow.tsx',
- '**/RecordTableCellBaseContainer.tsx',
- '**/RecordTableCellDisplayContainer.tsx',
- '**/RecordTableCellFirstRowFirstColumn.tsx',
- '**/RecordTableCellLoading.tsx',
- '**/RecordTableCellStyleWrapper.tsx',
- '**/RecordTableDragAndDropPlaceholderCell.tsx',
- '**/RecordTableAggregateFooterCell.tsx',
- '**/RecordTableHeaderAddColumnButton.tsx',
- '**/RecordTableHeaderCell.tsx',
- '**/RecordTableHeaderCheckboxColumn.tsx',
- '**/RecordTableHeaderDragDropColumn.tsx',
- '**/RecordTableHeaderFirstCell.tsx',
- '**/RecordTableHeaderFirstScrollableCell.tsx',
- '**/RecordTableHeaderLastEmptyColumn.tsx',
- '**/RecordTableAddButtonPlaceholderCell.tsx',
- '**/RecordTableGroupSectionLastDynamicFillingCell.tsx',
- '**/RecordTableLastDynamicFillingCell.tsx',
- '**/RecordTableRowVirtualizedContainer.tsx',
- '**/RecordTableVirtualizedBodyPlaceholder.tsx',
- '**/SignInAppNavigationDrawerMock.tsx',
- '**/SignInBackgroundMockContainer.tsx',
- '**/SignInBackgroundMockPage.tsx',
- '**/Heading.tsx',
- '**/MatchColumnSelectFieldSelectDropdownContent.tsx',
- '**/MatchColumnToFieldSelect.tsx',
- '**/SpreadSheetImportModalCloseButton.tsx',
- '**/SpreadSheetImportModalWrapper.tsx',
- '**/SpreadsheetImportTable.tsx',
- '**/StepNavigationButton.tsx',
- '**/ImportDataStep.tsx',
- '**/MatchColumnsStep.tsx',
- '**/ColumnGrid.tsx',
- '**/SubMatchingSelectControlContainer.tsx',
- '**/SubMatchingSelectDropdownButton.tsx',
- '**/SubMatchingSelectRow.tsx',
- '**/SubMatchingSelectRowLeftSelect.tsx',
- '**/SubMatchingSelectRowRightDropdown.tsx',
- '**/TemplateColumn.tsx',
- '**/UnmatchColumn.tsx',
- '**/UnmatchColumnBanner.tsx',
- '**/UserTableColumn.tsx',
- '**/SelectHeaderStep.tsx',
- '**/SelectSheetStep.tsx',
- '**/SpreadsheetImportStepper.tsx',
- '**/SpreadsheetImportStepperContainer.tsx',
- '**/UploadStep.tsx',
- '**/DropZone.tsx',
- '**/ValidationStep.tsx',
- '**/columns.tsx',
- '**/BooleanDisplay.tsx',
- '**/EllipsisDisplay.tsx',
- '**/EmailsDisplay.tsx',
- '**/MultiSelectDisplay.tsx',
- '**/PhonesDisplay.tsx',
- '**/TextDisplay.tsx',
- '**/RatingInput.tsx',
- '**/SortOrFilterChip.tsx',
- '**/UpdateViewButtonGroup.tsx',
- '**/ViewBarDetails.tsx',
- '**/ViewBarFilterDropdownAdvancedFilterButton.tsx',
- '**/ViewBarFilterDropdownAnyFieldSearchButtonMenuItem.tsx',
- '**/ViewBarFilterDropdownBottomMenu.tsx',
- '**/ViewBarFilterDropdownFieldSelectMenu.tsx',
- '**/ViewPickerContentCreateMode.tsx',
- '**/ViewPickerDropdown.tsx',
- '**/ViewPickerIconAndNameContainer.tsx',
- '**/ViewPickerListContent.tsx',
- '**/ViewPickerSaveButtonContainer.tsx',
- '**/ViewPickerSelectContainer.tsx',
- '**/AIChatAssistantMessageRenderer.tsx',
- '**/AIChatBanner.tsx',
- '**/AIChatContextUsageButton.tsx',
- '**/AIChatEmptyState.tsx',
- '**/AIChatErrorMessage.tsx',
- '**/AIChatMessage.stories.tsx',
- '**/AIChatMessage.tsx',
- '**/AIChatSkeletonLoader.tsx',
- '**/AIChatStandaloneError.tsx',
- '**/AIChatSuggestedPrompts.tsx',
- '**/AIChatTab.tsx',
- '**/AIChatThreadGroup.tsx',
- '**/AIChatThreadsList.tsx',
- '**/ActionButton.tsx',
- '**/ActivityList.tsx',
- '**/ActivityRow.tsx',
- '**/ActivityTargetChips.tsx',
- '**/AgentChatContextPreview.tsx',
- '**/AgentChatFileUploadButton.tsx',
- '**/AppFullScreenErrorFallback.tsx',
- '**/AppRootErrorFallback.tsx',
- '**/AttachmentList.tsx',
- '**/AttachmentRow.tsx',
- '**/AuthModal.tsx',
- '**/Authorize.tsx',
- '**/BookCall.tsx',
- '**/BookCallDecision.tsx',
- '**/CalendarDayCardContent.tsx',
- '**/CalendarEventDetails.tsx',
- '**/CalendarEventNotSharedContent.tsx',
- '**/CalendarEventParticipantsResponseStatusField.tsx',
- '**/CalendarEventRow.tsx',
- '**/CalendarEventsCard.tsx',
- '**/ChooseYourPlan.tsx',
- '**/ChooseYourPlanContent.tsx',
- '**/CodeExecutionDisplay.tsx',
- '**/ComponentStorybookLayout.tsx',
- '**/ContextUsageProgressRing.tsx',
- '**/CreateProfile.tsx',
- '**/CreateWorkspace.tsx',
- '**/CustomResolverFetchMoreLoader.tsx',
- '**/DocumentViewer.tsx',
- '**/EmailThreadBottomBar.tsx',
- '**/EmailThreadHeader.tsx',
- '**/EmailThreadMessage.tsx',
- '**/EmailThreadMessageBody.tsx',
- '**/EmailThreadMessageBodyPreview.tsx',
- '**/EmailThreadMessageReceivers.tsx',
- '**/EmailThreadMessageSender.tsx',
- '**/EmailThreadNotShared.tsx',
- '**/EmailThreadPreview.tsx',
- '**/EmailVerificationSent.tsx',
- '**/EmailsCard.tsx',
- '**/EventCard.tsx',
- '**/EventCardCalendarEvent.tsx',
- '**/EventCardMessage.tsx',
- '**/EventCardMessageBodyNotShared.tsx',
- '**/EventCardMessageForbidden.tsx',
- '**/EventCardToggleButton.tsx',
- '**/EventFieldDiff.tsx',
- '**/EventFieldDiffLabel.tsx',
- '**/EventFieldDiffValue.tsx',
- '**/EventList.tsx',
- '**/EventLogDatePickerInput.tsx',
- '**/EventLogFilters.tsx',
- '**/EventLogJsonCell.tsx',
- '**/EventLogResultsTable.tsx',
- '**/EventRow.tsx',
- '**/EventRowActivity.tsx',
- '**/EventRowCalendarEvent.tsx',
- '**/EventRowDynamicComponent.tsx',
- '**/EventRowMainObject.tsx',
- '**/EventRowMainObjectUpdated.tsx',
- '**/EventRowMessage.tsx',
- '**/EventsGroup.tsx',
- '**/FileIcon.tsx',
- '**/FilesCard.tsx',
- '**/FooterNote.tsx',
- '**/FullHeightStorybookLayout.tsx',
- '**/FullScreenDecorator.tsx',
- '**/InviteTeam.tsx',
- '**/LastUsedPill.tsx',
- '**/LazyMarkdownRendererStyledComponents.tsx',
- '**/LeftPanelSkeletonLoader.tsx',
- '**/LocalePicker.tsx',
- '**/Logo.tsx',
- '**/MainNavigationDrawerItemsSkeletonLoader.tsx',
- '**/NavigationDrawerAIChatThreadDateSection.tsx',
- '**/NavigationDrawerAIChatThreadsList.tsx',
- '**/NavigationDrawerSectionForObjectMetadataItemsSkeletonLoader.tsx',
- '**/NavigationDrawerSectionForWorkspaceItems.tsx',
- '**/NotFound.tsx',
- '**/NoteList.tsx',
- '**/NoteTile.tsx',
- '**/NotesCard.tsx',
- '**/OnboardingModalCircularIcon.tsx',
- '**/OnboardingSyncEmailsSettingsCard.tsx',
- '**/PageHeaderActionMenuButtons.tsx',
- '**/ParticipantChip.tsx',
- '**/PasswordReset.tsx',
- '**/PaymentSuccess.tsx',
- '**/PlaceAutocompleteSelect.tsx',
- '**/ProfilingReporter.tsx',
- '**/ReasoningSummaryDisplay.tsx',
- '**/RecordIndexActionMenuDropdown.tsx',
- '**/RightDrawerSkeletonLoader.tsx',
- '**/RightPanelSkeletonLoader.tsx',
- '**/RoutingDebugDisplay.tsx',
- '**/RoutingStatusDisplay.tsx',
- '**/SettingsAI.tsx',
- '**/SettingsAIAgentForm.tsx',
- '**/SettingsAIAgentTableRow.tsx',
- '**/SettingsAIAgentsTable.tsx',
- '**/SettingsAIMCP.tsx',
- '**/SettingsAIModelsTab.tsx',
- '**/SettingsAIPrompts.tsx',
- '**/SettingsAdminConfigVariableDetails.tsx',
- '**/SettingsAdminIndicatorHealthStatus.tsx',
- '**/SettingsAgentDetailSkeletonLoader.tsx',
- '**/SettingsAgentEvalsTab.tsx',
- '**/SettingsAgentForm.tsx',
- '**/SettingsAgentLogsTab.tsx',
- '**/SettingsAgentModelCapabilities.tsx',
- '**/SettingsAgentResponseFormat.tsx',
- '**/SettingsAgentRoleTab.tsx',
- '**/SettingsAgentSettingsTab.tsx',
- '**/SettingsAgentTurnDetail.tsx',
- '**/SettingsApiKeys.tsx',
- '**/SettingsApiWebhooks.tsx',
- '**/SettingsApplicationCustomTab.tsx',
- '**/SettingsApplicationDataTable.tsx',
- '**/SettingsApplicationDataTableRow.tsx',
- '**/SettingsApplicationDetailEnvironmentVariablesTable.tsx',
- '**/SettingsApplicationDetailSkeletonLoader.tsx',
- '**/SettingsApplicationNameDescriptionTable.tsx',
- '**/SettingsApplicationRegistrationDetails.tsx',
- '**/SettingsApplicationTableRow.tsx',
- '**/SettingsApplicationsAvailableTab.tsx',
- '**/SettingsApplicationsDeveloperTab.tsx',
- '**/SettingsApplicationsTable.tsx',
- '**/SettingsAvailableApplicationCard.tsx',
- '**/SettingsAvailableApplicationDetails.tsx',
- '**/SettingsDevelopersApiKeyDetail.tsx',
- '**/SettingsDomains.tsx',
- '**/SettingsEmailingDomains.tsx',
- '**/SettingsEventLogs.tsx',
- '**/SettingsObjectDetailPage.tsx',
- '**/SettingsObjectFieldEdit.tsx',
- '**/SettingsObjectFieldTable.tsx',
- '**/SettingsObjectIndexTable.tsx',
- '**/SettingsObjectTable.tsx',
- '**/SettingsSecurity.tsx',
- '**/SettingsSkillForm.tsx',
- '**/SettingsSkillTableRow.tsx',
- '**/SettingsSkillsTable.tsx',
- '**/SettingsSystemToolTableRow.tsx',
- '**/SettingsToolTableRow.tsx',
- '**/SettingsToolsTable.tsx',
- '**/SettingsTwoFactorAuthenticationMethod.tsx',
- '**/SettingsUpdates.tsx',
- '**/SettingsWebhooks.tsx',
- '**/SettingsWorkspaceMembers.tsx',
- '**/ShimmeringText.tsx',
- '**/SignInUp.tsx',
- '**/SignInUpEmailField.tsx',
- '**/SignInUpGlobalScopeForm.tsx',
- '**/SignInUpPasswordField.tsx',
- '**/SignInUpSSOButtonStyles.ts',
- '**/SignInUpSSOIdentityProviderSelection.tsx',
- '**/SignInUpTwoFactorAuthenticationProvision.tsx',
- '**/SignInUpTwoFactorAuthenticationVerification.tsx',
- '**/SignInUpWithCredentials.tsx',
- '**/SignInUpWorkspaceScopeForm.tsx',
- '**/SkeletonLoader.tsx',
- '**/SubTitle.tsx',
- '**/SyncEmails.tsx',
- '**/TaskGroups.tsx',
- '**/TaskList.tsx',
- '**/TaskRow.tsx',
- '**/TasksCard.tsx',
- '**/TerminalOutput.tsx',
- '**/ThinkingStepsDisplay.tsx',
- '**/TimelineCard.tsx',
- '**/Title.tsx',
- '**/ToolStepRenderer.tsx',
- '**/UserOrMetadataLoader.tsx',
- '**/WorkflowStepActionDrawerDecorator.tsx',
- '**/WorkspaceInviteLink.tsx',
- '**/WorkspaceInviteTeam.tsx',
- '**/AddressInput.tsx',
- '**/AxisLayer.tsx',
- '**/BarChart.tsx',
- '**/BarChartBaseLayer.tsx',
- '**/BarChartHoverLayer.tsx',
- '**/BarChartLayers.tsx',
- '**/BarChartTotalsLayer.tsx',
- '**/BlankLayout.tsx',
- '**/BodyInput.tsx',
- '**/BooleanInput.tsx',
- '**/CalendarWidget.tsx',
- '**/ChartColorGradientOption.tsx',
- '**/ChartColorPaletteOption.tsx',
- '**/ChartFiltersSettings.tsx',
- '**/ChartSettings.tsx',
- '**/ChartTypeSelectionSection.tsx',
- '**/CommandGroup.tsx',
- '**/CommandMenuAIChatThreadsPage.tsx',
- '**/CommandMenuAskAIInfo.tsx',
- '**/CommandMenuAskAIPage.tsx',
- '**/CommandMenuBackButton.tsx',
- '**/CommandMenuContainer.tsx',
- '**/CommandMenuContextChip.tsx',
- '**/CommandMenuContextRecordChipAvatars.tsx',
- '**/CommandMenuEditColorOption.tsx',
- '**/CommandMenuEditRichTextPage.tsx',
- '**/CommandMenuFolderInfo.tsx',
- '**/CommandMenuForMobile.tsx',
- '**/CommandMenuItemNumberInput.tsx',
- '**/CommandMenuItemTextInput.tsx',
- '**/CommandMenuItemWithAddToNavigationDrag.tsx',
- '**/CommandMenuList.tsx',
- '**/CommandMenuMergeRecordPage.tsx',
- '**/CommandMenuMessageThreadIntermediaryMessages.tsx',
- '**/CommandMenuMessageThreadPage.tsx',
- '**/CommandMenuNavigationMenuItemEditPage.tsx',
- '**/CommandMenuOpenContainer.tsx',
- '**/CommandMenuPageInfo.tsx',
- '**/CommandMenuPageInfoLayout.tsx',
- '**/CommandMenuPageLayoutChartSettings.tsx',
- '**/CommandMenuPageLayoutFieldsLayout.tsx',
- '**/CommandMenuPageLayoutFieldsSettings.tsx',
- '**/CommandMenuPageLayoutIframeSettings.tsx',
- '**/CommandMenuRecordPage.tsx',
- '**/CommandMenuRouter.tsx',
- '**/CommandMenuSidePanelForDesktop.tsx',
- '**/CommandMenuSubViewWithSearch.tsx',
- '**/CommandMenuTopBar.tsx',
- '**/CommandMenuTopBarRightCornerIcon.tsx',
- '**/CommandMenuUpdateMultipleRecords.tsx',
- '**/CommandMenuWorkflowEditStepContent.tsx',
- '**/CommandMenuWorkflowRunViewStepContent.tsx',
- '**/CommandMenuWorkflowViewStepContent.tsx',
- '**/ConfirmationModal.tsx',
- '**/CreateNewButton.tsx',
- '**/CronExpressionHelper.tsx',
- '**/CurrencyInput.tsx',
- '**/CurrencyPickerDropdownButton.tsx',
- '**/DashboardColorIcon.tsx',
- '**/DashboardColorSelectionMenu.tsx',
- '**/DashboardEditorSideMenu.tsx',
- '**/DashboardFormattingToolbar.tsx',
- '**/DashboardFormattingToolbarColorButton.tsx',
- '**/DashboardsBlockEditor.tsx',
- '**/DatePicker.tsx',
- '**/DatePickerHeader.tsx',
- '**/DatePickerInput.tsx',
- '**/DatePickerWithoutCalendar.tsx',
- '**/DateTimeDisplay.tsx',
- '**/DateTimePicker.tsx',
- '**/DateTimePickerHeader.tsx',
- '**/DateTimePickerInput.tsx',
- '**/DefaultLayout.tsx',
- '**/Dialog.tsx',
- '**/DoubleTextInput.tsx',
- '**/DraggableList.tsx',
- '**/Dropdown.stories.tsx',
- '**/Dropdown.tsx',
- '**/DropdownContent.tsx',
- '**/DropdownInternalContainer.tsx',
- '**/DropdownMenuHeader.tsx',
- '**/DropdownMenuHeaderLeftComponent.tsx',
- '**/DropdownMenuInnerSelect.tsx',
- '**/DropdownMenuInput.tsx',
- '**/DropdownMenuItemsContainer.tsx',
- '**/DropdownMenuSearchInput.tsx',
- '**/DropdownMenuSectionLabel.tsx',
- '**/DropdownMenuSeparator.tsx',
- '**/DropdownMenuSkeletonItem.tsx',
- '**/EmailWidget.tsx',
- '**/ExpandableList.stories.tsx',
- '**/ExpandableList.tsx',
- '**/ExpandedFieldDisplay.tsx',
- '**/ExpandedListDropdown.tsx',
- '**/FieldInputContainer.tsx',
- '**/FieldRichTextWidget.tsx',
- '**/FieldWidget.tsx',
- '**/FieldWidgetDisplay.tsx',
- '**/FieldWidgetEditAction.tsx',
- '**/FieldWidgetInlineCellContainer.tsx',
- '**/FieldWidgetMorphRelationCard.tsx',
- '**/FieldWidgetMorphRelationField.tsx',
- '**/FieldWidgetRelationCard.tsx',
- '**/FieldWidgetRelationEditAction.tsx',
- '**/FieldWidgetRelationField.tsx',
- '**/FieldWidgetShowMoreButton.tsx',
- '**/FieldsConfigurationEditor.tsx',
- '**/FieldsConfigurationGroupEditor.tsx',
- '**/FieldsConfigurationGroupRenameInput.tsx',
- '**/FieldsWidget.tsx',
- '**/FieldsWidgetGroupContainer.tsx',
- '**/FileChip.tsx',
- '**/FileWidget.tsx',
- '**/FrontComponentWidgetRenderer.tsx',
- '**/FullScreenContainer.stories.tsx',
- '**/FullScreenContainer.tsx',
- '**/GlobalFilePreviewModal.tsx',
- '**/GraphWidgetAggregateChart.tsx',
- '**/GraphWidgetBarChart.tsx',
- '**/GraphWidgetChartContainer.tsx',
- '**/GraphWidgetGaugeChart.tsx',
- '**/GraphWidgetLegend.tsx',
- '**/GraphWidgetLegendDot.tsx',
- '**/GraphWidgetLineChart.tsx',
- '**/GraphWidgetPieChart.tsx',
- '**/GraphWidgetTooltip.tsx',
- '**/HttpRequestTestVariableInput.tsx',
- '**/IconPicker.tsx',
- '**/IframeWidget.tsx',
- '**/ImageInput.tsx',
- '**/InputErrorHelper.tsx',
- '**/InputHint.tsx',
- '**/InputLabel.tsx',
- '**/KeyValuePairInput.tsx',
- '**/Modal.tsx',
- '**/NoteWidget.tsx',
- '**/OverlayContainer.tsx',
- '**/PageBody.tsx',
- '**/PageContainer.tsx',
- '**/PageHeader.tsx',
- '**/PageHeaderToggleCommandMenuButton.tsx',
- '**/PageLayoutCanvasViewer.tsx',
- '**/PageLayoutGridLayout.tsx',
- '**/PageLayoutGridOverlay.tsx',
- '**/PageLayoutGridResizeHandle.tsx',
- '**/PageLayoutLeftPanel.tsx',
- '**/PageLayoutRendererContent.tsx',
- '**/PageLayoutTabList.stories.tsx',
- '**/PageLayoutTabList.tsx',
- '**/PageLayoutTabListDroppableMoreButton.tsx',
- '**/PageLayoutTabListReorderableOverflowDropdown.tsx',
- '**/PageLayoutTabListReorderableTab.tsx',
- '**/PageLayoutTabListVisibleTabs.tsx',
- '**/PageLayoutTabMenuItemSelectAvatar.tsx',
- '**/PageLayoutTabRenderClone.tsx',
- '**/PageLayoutVerticalListEditor.tsx',
- '**/PageLayoutVerticalListViewer.tsx',
- '**/PageLayoutWidgetInvalidConfigDisplay.tsx',
- '**/PageLayoutWidgetNoDataDisplay.tsx',
- '**/PagePanel.tsx',
- '**/PhoneCountryPickerDropdownButton.tsx',
- '**/PhoneCountryPickerDropdownSelect.tsx',
- '**/PieChartCenterMetricLayer.tsx',
- '**/RelativeDatePickerHeader.tsx',
- '**/ResizablePanelEdge.tsx',
- '**/ResizablePanelGap.tsx',
- '**/RightDrawerFooter.tsx',
- '**/RightDrawerWorkflowSelectStepContainer.tsx',
- '**/RightDrawerWorkflowSelectStepTitle.tsx',
- '**/Select.tsx',
- '**/SelectControl.tsx',
- '**/ShowPageContainer.tsx',
- '**/SidePanelSubPageNavigationHeader.tsx',
- '**/SnackBar.tsx',
- '**/SnackBarProvider.tsx',
- '**/StandaloneRichTextWidget.tsx',
- '**/StyledDropdownButtonContainer.tsx',
- '**/StyledDropdownMenuSubheader.tsx',
- '**/StyledHeaderDropdownButton.tsx',
- '**/SubMenuTopBarContainer.tsx',
- '**/TaskWidget.tsx',
- '**/TextArea.tsx',
- '**/TextAreaInput.tsx',
- '**/TextInput.tsx',
- '**/TimeZoneAbbreviation.tsx',
- '**/TimelineWidget.tsx',
- '**/TitleInput.tsx',
- '**/UploadFileChip.tsx',
- '**/WidgetActionFieldSeeAll.tsx',
- '**/WidgetCard.tsx',
- '**/WidgetCardContent.tsx',
- '**/WidgetCardHeader.tsx',
- '**/WidgetGrip.tsx',
- '**/WidgetRenderer.tsx',
- '**/WidgetSkeletonLoader.tsx',
- '**/WorkflowAiAgentPermissionsStyles.ts',
- '**/WorkflowAiAgentPermissionsTab.tsx',
- '**/WorkflowCodeEditor.tsx',
- '**/WorkflowDiagramCanvasBase.tsx',
- '**/WorkflowDiagramCreateStepElement.tsx',
- '**/WorkflowDiagramEdgeButtonGroup.tsx',
- '**/WorkflowDiagramEdgeLabel.tsx',
- '**/WorkflowDiagramEdgeLabelContainer.tsx',
- '**/WorkflowDiagramEdgeV2Container.tsx',
- '**/WorkflowDiagramEdgeV2VisibilityContainer.tsx',
- '**/WorkflowDiagramHandleSource.tsx',
- '**/WorkflowDiagramHandleTarget.tsx',
- '**/WorkflowDiagramRightClickCommandMenu.tsx',
- '**/WorkflowDiagramStepNodeEditableContent.tsx',
- '**/WorkflowEditActionAiAgent.tsx',
- '**/WorkflowEditActionCode.tsx',
- '**/WorkflowEditActionCodeFields.tsx',
- '**/WorkflowEditActionFilterBody.tsx',
- '**/WorkflowEditActionFindRecords.tsx',
- '**/WorkflowEditActionFormBuilder.tsx',
- '**/WorkflowEditActionFormFieldSettings.tsx',
- '**/WorkflowEditActionHttpRequest.tsx',
- '**/WorkflowEditActionIfElseBody.tsx',
- '**/WorkflowEditActionLogicFunction.tsx',
- '**/WorkflowEditTriggerDatabaseEventForm.tsx',
- '**/WorkflowEditTriggerManual.tsx',
- '**/WorkflowFindRecordsSorts.tsx',
- '**/WorkflowFormFieldSettingsNumber.tsx',
- '**/WorkflowFormFieldSettingsRecordPicker.tsx',
- '**/WorkflowFormFieldSettingsSelect.tsx',
- '**/WorkflowFormFieldSettingsText.tsx',
- '**/WorkflowIfElseBranchEditor.tsx',
- '**/WorkflowIteratorSubStepSwitcher.tsx',
- '**/WorkflowNodeContainer.tsx',
- '**/WorkflowNodeIconContainer.tsx',
- '**/WorkflowNodeLabel.tsx',
- '**/WorkflowNodeLabelWithCounterPart.tsx',
- '**/WorkflowNodeRightPart.tsx',
- '**/WorkflowNodeTitle.tsx',
- '**/WorkflowOutputSchemaBuilder.tsx',
- '**/WorkflowReadonlyActionCode.tsx',
- '**/WorkflowRunCard.tsx',
- '**/WorkflowRunDiagramStepNode.tsx',
- '**/WorkflowRunStepJsonContainer.tsx',
- '**/WorkflowStepBody.tsx',
- '**/WorkflowStepExecutionResult.tsx',
- '**/WorkflowStepFilterAddRootStepFilterButton.tsx',
- '**/WorkflowStepFilterColumn.tsx',
- '**/WorkflowStepFilterGroupChildren.tsx',
- '**/WorkflowStepFilterGroupColumn.tsx',
- '**/WorkflowStepFilterLogicalOperatorCell.tsx',
- '**/WorkflowTextEditorTextChip.tsx',
- '**/WorkflowTextEditorVariableChip.tsx',
- '**/WorkflowVariablePicker.tsx',
- '**/WorkflowVariablesDropdown.tsx',
- '**/WorkflowVersionCard.tsx',
- '**/useCommandMenuContextChips.tsx',
- '**/useFullScreenModal.tsx',
+ include: ['**/*.{ts,tsx}'],
+ exclude: [
+ '**/generated-metadata/**',
+ '**/testing/mock-data/generated/**',
+ '**/*.test.{ts,tsx}',
+ '**/*.spec.{ts,tsx}',
+ '**/types/**',
+ '**/constants/**',
+ '**/states/**',
+ '**/selectors/**',
+ '**/guards/**',
+ '**/schemas/**',
+ '**/utils/**',
+ '**/contexts/**',
+ '**/hooks/**',
+ '**/enums/**',
+ '**/queries/**',
+ '**/mutations/**',
+ '**/fragments/**',
+ '**/graphql/**',
],
babelOptions: {
presets: ['@babel/preset-typescript', '@babel/preset-react'],
diff --git a/packages/twenty-sdk/.storybook/preview.tsx b/packages/twenty-sdk/.storybook/preview.tsx
index 33a0c0165c..acfa65702f 100644
--- a/packages/twenty-sdk/.storybook/preview.tsx
+++ b/packages/twenty-sdk/.storybook/preview.tsx
@@ -1,4 +1,3 @@
-import { ThemeProvider } from '@emotion/react';
import { type Preview } from '@storybook/react-vite';
import { THEME_LIGHT, ThemeContextProvider } from 'twenty-ui/theme';
@@ -9,11 +8,9 @@ const preview: Preview = {
const theme = THEME_LIGHT;
return (
-
-
-
-
-
+
+
+
);
},
],
diff --git a/packages/twenty-sdk/package.json b/packages/twenty-sdk/package.json
index ed936d99a4..07747f84b6 100644
--- a/packages/twenty-sdk/package.json
+++ b/packages/twenty-sdk/package.json
@@ -97,6 +97,7 @@
"zod": "^4.1.11"
},
"devDependencies": {
+ "@emotion/styled": "^11.14.0",
"@mui/material": "^7.3.8",
"@prettier/sync": "^0.5.2",
"@storybook/addon-vitest": "^10.2.13",
diff --git a/packages/twenty-sdk/src/front-component-renderer/host/components/FrontComponentRenderer.tsx b/packages/twenty-sdk/src/front-component-renderer/host/components/FrontComponentRenderer.tsx
index e929f504ae..1e0e6dce93 100644
--- a/packages/twenty-sdk/src/front-component-renderer/host/components/FrontComponentRenderer.tsx
+++ b/packages/twenty-sdk/src/front-component-renderer/host/components/FrontComponentRenderer.tsx
@@ -12,8 +12,7 @@ import {
import { useMemo, useState } from 'react';
import { isDefined } from 'twenty-shared/utils';
-import { ThemeProvider } from '@emotion/react';
-import { type ThemeType } from 'twenty-ui/theme';
+import { type ThemeType, ThemeContextProvider } from 'twenty-ui/theme';
import { FrontComponentWorkerEffect } from '../../remote/components/FrontComponentWorkerEffect';
import { componentRegistry } from '../generated/host-component-registry';
@@ -108,12 +107,12 @@ export const FrontComponentRenderer = ({
)}
{isDefined(receiver) && isExecutionContextInitialized && (
-
+
-
+
)}
>
);
diff --git a/packages/twenty-sdk/src/ui/index.ts b/packages/twenty-sdk/src/ui/index.ts
index 3e05bbfb24..d35fd14e73 100644
--- a/packages/twenty-sdk/src/ui/index.ts
+++ b/packages/twenty-sdk/src/ui/index.ts
@@ -9,7 +9,3 @@ export * from 'twenty-ui/layout';
export * from 'twenty-ui/navigation';
export * from 'twenty-ui/theme';
export * from 'twenty-ui/utilities';
-
-// Re-export Emotion's ThemeProvider so front components can wrap
-// their content with the Twenty UI theme without a direct @emotion/react dependency
-export { ThemeProvider } from '@emotion/react';
diff --git a/packages/twenty-ui/src/display/color/components/ColorSample.tsx b/packages/twenty-ui/src/display/color/components/ColorSample.tsx
index dd0602f44f..d8dead77c9 100644
--- a/packages/twenty-ui/src/display/color/components/ColorSample.tsx
+++ b/packages/twenty-ui/src/display/color/components/ColorSample.tsx
@@ -12,7 +12,9 @@ type StyledColorSampleProps = {
variant?: ColorSampleVariant;
};
-export type ColorSampleProps = StyledColorSampleProps;
+export type ColorSampleProps = StyledColorSampleProps & {
+ className?: string;
+};
const getColor = (colorName: ThemeColor, color?: string) => {
if (isDefined(color)) {
@@ -57,8 +59,14 @@ export const ColorSample = ({
colorName,
color,
variant,
+ className,
}: ColorSampleProps) => {
return (
-
+
);
};
diff --git a/packages/twenty-ui/src/individual-entry.ts b/packages/twenty-ui/src/individual-entry.ts
index 034b27cedc..d762a51893 100644
--- a/packages/twenty-ui/src/individual-entry.ts
+++ b/packages/twenty-ui/src/individual-entry.ts
@@ -1,6 +1,6 @@
// Entry point for the individual/self-contained build (vite.config.individual.ts).
// This re-exports all public modules so a single .mjs bundle contains
-// every component with internal deps bundled, while React and Emotion
+// every component with internal deps bundled, while React
// remain external for the consumer's bundler to resolve.
export * from './accessibility';
@@ -13,3 +13,4 @@ export * from './layout';
export * from './navigation';
export * from './theme';
export * from './utilities';
+
diff --git a/packages/twenty-ui/src/input/components/Toggle.tsx b/packages/twenty-ui/src/input/components/Toggle.tsx
index 44ad6b73ad..099dca5cf4 100644
--- a/packages/twenty-ui/src/input/components/Toggle.tsx
+++ b/packages/twenty-ui/src/input/components/Toggle.tsx
@@ -9,10 +9,12 @@ type ContainerProps = {
isOn: boolean;
color?: string;
toggleSize: ToggleSize;
+ centered?: boolean;
'data-disabled'?: boolean;
};
const StyledContainer = styled.label`
+ align-self: ${({ centered }) => (centered ? 'center' : 'flex-start')};
align-items: center;
background-color: ${({ isOn, color }) =>
isOn
@@ -52,6 +54,7 @@ export type ToggleProps = {
color?: string;
toggleSize?: ToggleSize;
className?: string;
+ centered?: boolean;
disabled?: boolean;
};
@@ -62,6 +65,7 @@ export const Toggle = ({
color,
toggleSize = 'medium',
className,
+ centered,
disabled,
}: ToggleProps) => {
const circleVariants = {
@@ -75,6 +79,7 @@ export const Toggle = ({
color={color}
toggleSize={toggleSize}
className={className}
+ centered={centered}
data-disabled={disabled}
>
& {
children?: ReactNode;
className?: string;
+ width?: number;
};
export const AnimatedPlaceholderEmptyContainer = ({
children,
className,
+ width,
initial,
animate,
transition,
@@ -34,6 +37,7 @@ export const AnimatedPlaceholderEmptyContainer = ({
return (
`
background-color: ${themeCssVariables.background.secondary};
padding: ${themeCssVariables.spacing[4]};
@@ -12,8 +14,13 @@ const StyledCardContentBase = styled.div<{
border-bottom: ${({ divider }) =>
divider ? `1px solid ${themeCssVariables.border.color.medium}` : 'none'};
- &[data-clickable='true'] {
- cursor: pointer;
+ cursor: ${({ isClickable }) => (isClickable ? 'pointer' : 'default')};
+
+ &:hover {
+ background: ${({ hasHoverHighlight }) =>
+ hasHoverHighlight
+ ? themeCssVariables.background.transparent.light
+ : 'transparent'};
}
`;
@@ -24,6 +31,7 @@ type CardContentProps = {
className?: string;
divider?: boolean;
isClickable?: boolean;
+ hasHoverHighlight?: boolean;
} & Omit, 'theme'>;
export const CardContent = ({
@@ -31,13 +39,15 @@ export const CardContent = ({
className,
divider,
isClickable,
+ hasHoverHighlight,
...rest
}: CardContentProps) => {
return (
diff --git a/packages/twenty-ui/src/navigation/menu/menu-item/components/MenuItem.tsx b/packages/twenty-ui/src/navigation/menu/menu-item/components/MenuItem.tsx
index d2ce59ab41..3ff01db3e8 100644
--- a/packages/twenty-ui/src/navigation/menu/menu-item/components/MenuItem.tsx
+++ b/packages/twenty-ui/src/navigation/menu/menu-item/components/MenuItem.tsx
@@ -50,6 +50,7 @@ export type MenuItemProps = {
contextualText?: ReactNode;
hasSubMenu?: boolean;
focused?: boolean;
+ selected?: boolean;
hotKeys?: string[];
isSubMenuOpened?: boolean;
};
@@ -80,6 +81,7 @@ export const MenuItem = ({
hasSubMenu = false,
disabled = false,
focused = false,
+ selected = false,
hotKeys,
isSubMenuOpened = false,
}: MenuItemProps) => {
@@ -104,7 +106,7 @@ export const MenuItem = ({
isIconDisplayedOnHoverOnly={isIconDisplayedOnHoverOnly}
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
- focused={focused}
+ focused={focused || selected}
>
- selected ? themeCssVariables.background.transparent.medium : ''};
+ selected ? themeCssVariables.background.transparent.medium : 'transparent'};
color: ${themeCssVariables.font.color.secondary};
transition: background 0.1s ease;
diff --git a/packages/twenty-ui/src/navigation/menu/menu-item/internals/components/StyledMenuItemBase.tsx b/packages/twenty-ui/src/navigation/menu/menu-item/internals/components/StyledMenuItemBase.tsx
index b291c45ee3..8e432e3488 100644
--- a/packages/twenty-ui/src/navigation/menu/menu-item/internals/components/StyledMenuItemBase.tsx
+++ b/packages/twenty-ui/src/navigation/menu/menu-item/internals/components/StyledMenuItemBase.tsx
@@ -39,7 +39,7 @@ export const StyledMenuItemBase = styled.div`
background: ${({ isKeySelected, focused }) =>
isKeySelected || focused
? themeCssVariables.background.transparent.light
- : ''};
+ : 'transparent'};
transition: ${({ isHoverBackgroundDisabled, disabled }) =>
disabled || isHoverBackgroundDisabled ? 'none' : 'background 0.1s ease'};
@@ -60,8 +60,17 @@ export const StyledMenuItemBase = styled.div`
}};
&:hover {
- background: ${({ accent, disabled, isHoverBackgroundDisabled }) => {
- if (disabled === true) return '';
+ background: ${({
+ accent,
+ disabled,
+ isHoverBackgroundDisabled,
+ isKeySelected,
+ focused,
+ }) => {
+ if (disabled === true)
+ return isKeySelected || focused
+ ? themeCssVariables.background.transparent.light
+ : 'transparent';
if (accent === 'danger')
return themeCssVariables.background.transparent.danger;
if (isHoverBackgroundDisabled === true) return 'transparent';
diff --git a/packages/twenty-website/next.config.js b/packages/twenty-website/next.config.js
index 8ff063c0f2..d5436e3abd 100644
--- a/packages/twenty-website/next.config.js
+++ b/packages/twenty-website/next.config.js
@@ -1,4 +1,5 @@
/** @type {import('next').NextConfig} */
+const withLinaria = require('next-with-linaria');
const nextConfig = {
images: {
@@ -72,4 +73,4 @@ const nextConfig = {
},
};
-module.exports = nextConfig;
+module.exports = withLinaria(nextConfig);
diff --git a/packages/twenty-website/src/app/(public)/layout.tsx b/packages/twenty-website/src/app/(public)/layout.tsx
index 77a432df29..475fb2acb9 100644
--- a/packages/twenty-website/src/app/(public)/layout.tsx
+++ b/packages/twenty-website/src/app/(public)/layout.tsx
@@ -5,7 +5,6 @@ import { Gabarito, Inter } from 'next/font/google';
import { AppHeader } from '@/app/_components/ui/layout/header';
import { FooterDesktop } from '../_components/ui/layout/FooterDesktop';
-import EmotionRootStyleRegistry from '../emotion-root-style-registry';
import './layout.css';
@@ -42,11 +41,9 @@ export default function RootLayout({
-
-
- {children}
-
-
+
+ {children}
+
);
diff --git a/packages/twenty-website/src/app/_components/contributors/ActivityLog.tsx b/packages/twenty-website/src/app/_components/contributors/ActivityLog.tsx
index 764f945d23..4eed880cf5 100644
--- a/packages/twenty-website/src/app/_components/contributors/ActivityLog.tsx
+++ b/packages/twenty-website/src/app/_components/contributors/ActivityLog.tsx
@@ -1,6 +1,6 @@
'use client';
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
import { TimeRange } from '@nivo/calendar';
import { getActivityEndDate } from '@/app/(public)/contributors/utils/get-activity-end-date';
diff --git a/packages/twenty-website/src/app/_components/contributors/AnimatedFigures.tsx b/packages/twenty-website/src/app/_components/contributors/AnimatedFigures.tsx
index 91e962b222..0b5ccbab35 100644
--- a/packages/twenty-website/src/app/_components/contributors/AnimatedFigures.tsx
+++ b/packages/twenty-website/src/app/_components/contributors/AnimatedFigures.tsx
@@ -1,5 +1,5 @@
import { useEffect, useRef } from 'react';
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
import {
animate,
motion,
diff --git a/packages/twenty-website/src/app/_components/contributors/AvatarGrid.tsx b/packages/twenty-website/src/app/_components/contributors/AvatarGrid.tsx
index f50b1a6aa3..679a2aabee 100644
--- a/packages/twenty-website/src/app/_components/contributors/AvatarGrid.tsx
+++ b/packages/twenty-website/src/app/_components/contributors/AvatarGrid.tsx
@@ -1,6 +1,6 @@
'use client';
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
import Link from 'next/link';
import MotionContainer from '@/app/_components/ui/layout/LoaderAnimation';
diff --git a/packages/twenty-website/src/app/_components/contributors/CardContainer.tsx b/packages/twenty-website/src/app/_components/contributors/CardContainer.tsx
index 87b00e940b..02cfa4c245 100644
--- a/packages/twenty-website/src/app/_components/contributors/CardContainer.tsx
+++ b/packages/twenty-website/src/app/_components/contributors/CardContainer.tsx
@@ -1,4 +1,4 @@
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
export const CardContainer = styled.div`
border: 3px solid #141414;
diff --git a/packages/twenty-website/src/app/_components/contributors/ContentContainer.tsx b/packages/twenty-website/src/app/_components/contributors/ContentContainer.tsx
index 27b27f33c7..7857db23e3 100644
--- a/packages/twenty-website/src/app/_components/contributors/ContentContainer.tsx
+++ b/packages/twenty-website/src/app/_components/contributors/ContentContainer.tsx
@@ -1,6 +1,6 @@
'use client';
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
import MotionContainer from '@/app/_components/ui/layout/LoaderAnimation';
diff --git a/packages/twenty-website/src/app/_components/contributors/Header.tsx b/packages/twenty-website/src/app/_components/contributors/Header.tsx
index fee0514676..21941b8095 100644
--- a/packages/twenty-website/src/app/_components/contributors/Header.tsx
+++ b/packages/twenty-website/src/app/_components/contributors/Header.tsx
@@ -1,6 +1,6 @@
'use client';
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
import { motion } from 'framer-motion';
const Title = styled.h2`
diff --git a/packages/twenty-website/src/app/_components/contributors/ProfileCard.tsx b/packages/twenty-website/src/app/_components/contributors/ProfileCard.tsx
index 0df5a06ca1..aea911c1b2 100644
--- a/packages/twenty-website/src/app/_components/contributors/ProfileCard.tsx
+++ b/packages/twenty-website/src/app/_components/contributors/ProfileCard.tsx
@@ -1,6 +1,6 @@
'use client';
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
import { format } from 'date-fns';
import { GithubIcon } from '@/app/_components/ui/icons/SvgIcons';
diff --git a/packages/twenty-website/src/app/_components/contributors/ProfileInfo.tsx b/packages/twenty-website/src/app/_components/contributors/ProfileInfo.tsx
index 731959cdf2..48a116639f 100644
--- a/packages/twenty-website/src/app/_components/contributors/ProfileInfo.tsx
+++ b/packages/twenty-website/src/app/_components/contributors/ProfileInfo.tsx
@@ -1,7 +1,7 @@
'use client';
import React from 'react';
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
import { AnimatedFigures } from '@/app/_components/contributors/AnimatedFigures';
import { CardContainer } from '@/app/_components/contributors/CardContainer';
diff --git a/packages/twenty-website/src/app/_components/contributors/ProfileSharing.tsx b/packages/twenty-website/src/app/_components/contributors/ProfileSharing.tsx
index fcca7a3719..a06c4b5ab4 100644
--- a/packages/twenty-website/src/app/_components/contributors/ProfileSharing.tsx
+++ b/packages/twenty-website/src/app/_components/contributors/ProfileSharing.tsx
@@ -1,7 +1,7 @@
'use client';
import { useState } from 'react';
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
import { IconDownload } from '@tabler/icons-react';
import { CardContainer } from '@/app/_components/contributors/CardContainer';
diff --git a/packages/twenty-website/src/app/_components/contributors/PullRequestItem.tsx b/packages/twenty-website/src/app/_components/contributors/PullRequestItem.tsx
index a559180d0a..6ae3cb2674 100644
--- a/packages/twenty-website/src/app/_components/contributors/PullRequestItem.tsx
+++ b/packages/twenty-website/src/app/_components/contributors/PullRequestItem.tsx
@@ -1,4 +1,4 @@
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
import { format } from 'date-fns';
import { Tooltip } from 'react-tooltip';
diff --git a/packages/twenty-website/src/app/_components/contributors/PullRequests.tsx b/packages/twenty-website/src/app/_components/contributors/PullRequests.tsx
index c8367fc0b4..bd276fdfc3 100644
--- a/packages/twenty-website/src/app/_components/contributors/PullRequests.tsx
+++ b/packages/twenty-website/src/app/_components/contributors/PullRequests.tsx
@@ -1,6 +1,6 @@
'use client';
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
import { CardContainer } from '@/app/_components/contributors/CardContainer';
import { PullRequestItem } from '@/app/_components/contributors/PullRequestItem';
diff --git a/packages/twenty-website/src/app/_components/contributors/Spinner.tsx b/packages/twenty-website/src/app/_components/contributors/Spinner.tsx
index cec0a6763b..c659867478 100644
--- a/packages/twenty-website/src/app/_components/contributors/Spinner.tsx
+++ b/packages/twenty-website/src/app/_components/contributors/Spinner.tsx
@@ -1,15 +1,5 @@
import React from 'react';
-import { keyframes } from '@emotion/react';
-import styled from '@emotion/styled';
-
-const spin = keyframes`
- from {
- transform: rotate(0deg);
- }
- to {
- transform: rotate(360deg);
- }
-`;
+import { styled } from '@linaria/react';
const SpinnerWrapper = styled.div`
width: 24px;
@@ -17,7 +7,16 @@ const SpinnerWrapper = styled.div`
border: 4px solid rgba(0, 0, 0, 0.1);
border-top: 4px solid black;
border-radius: 50%;
- animation: ${spin} 1s linear infinite;
+ animation: spin 1s linear infinite;
+
+ @keyframes spin {
+ from {
+ transform: rotate(0deg);
+ }
+ to {
+ transform: rotate(360deg);
+ }
+ }
`;
const Spinner = () => ;
diff --git a/packages/twenty-website/src/app/_components/contributors/ThankYou.tsx b/packages/twenty-website/src/app/_components/contributors/ThankYou.tsx
index 141ba036c5..987f8d5ca8 100644
--- a/packages/twenty-website/src/app/_components/contributors/ThankYou.tsx
+++ b/packages/twenty-website/src/app/_components/contributors/ThankYou.tsx
@@ -1,6 +1,6 @@
'use client';
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
import { CardContainer } from '@/app/_components/contributors/CardContainer';
import { HeartIcon } from '@/app/_components/ui/icons/SvgIcons';
diff --git a/packages/twenty-website/src/app/_components/contributors/Title.tsx b/packages/twenty-website/src/app/_components/contributors/Title.tsx
index 8e15d06546..bf4b5223aa 100644
--- a/packages/twenty-website/src/app/_components/contributors/Title.tsx
+++ b/packages/twenty-website/src/app/_components/contributors/Title.tsx
@@ -1,4 +1,4 @@
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
export const Title = styled.h3`
margin: 0;
diff --git a/packages/twenty-website/src/app/_components/oss-friends/Background.tsx b/packages/twenty-website/src/app/_components/oss-friends/Background.tsx
index 88ec71610d..1fa61b405f 100644
--- a/packages/twenty-website/src/app/_components/oss-friends/Background.tsx
+++ b/packages/twenty-website/src/app/_components/oss-friends/Background.tsx
@@ -1,6 +1,6 @@
'use client';
import React from 'react';
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
const BACKGROUND_ROTATION = -5;
diff --git a/packages/twenty-website/src/app/_components/oss-friends/Card.tsx b/packages/twenty-website/src/app/_components/oss-friends/Card.tsx
index 599d3d93ff..097cf36cc6 100644
--- a/packages/twenty-website/src/app/_components/oss-friends/Card.tsx
+++ b/packages/twenty-website/src/app/_components/oss-friends/Card.tsx
@@ -1,6 +1,6 @@
'use client';
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
import { Gabarito } from 'next/font/google';
import { Theme } from '@/app/_components/ui/theme/theme';
diff --git a/packages/twenty-website/src/app/_components/oss-friends/CardContainer.tsx b/packages/twenty-website/src/app/_components/oss-friends/CardContainer.tsx
index 71ed1ded49..d8e2f0ef46 100644
--- a/packages/twenty-website/src/app/_components/oss-friends/CardContainer.tsx
+++ b/packages/twenty-website/src/app/_components/oss-friends/CardContainer.tsx
@@ -1,6 +1,6 @@
'use client';
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
const Container = styled.div`
display: flex;
diff --git a/packages/twenty-website/src/app/_components/oss-friends/ContentContainer.tsx b/packages/twenty-website/src/app/_components/oss-friends/ContentContainer.tsx
index 075b4fd1db..48c7eaa643 100644
--- a/packages/twenty-website/src/app/_components/oss-friends/ContentContainer.tsx
+++ b/packages/twenty-website/src/app/_components/oss-friends/ContentContainer.tsx
@@ -1,6 +1,6 @@
'use client';
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
const Container = styled.div`
display: flex;
diff --git a/packages/twenty-website/src/app/_components/oss-friends/Header.tsx b/packages/twenty-website/src/app/_components/oss-friends/Header.tsx
index 32260eac4b..fcdf9972a7 100644
--- a/packages/twenty-website/src/app/_components/oss-friends/Header.tsx
+++ b/packages/twenty-website/src/app/_components/oss-friends/Header.tsx
@@ -1,6 +1,6 @@
'use client';
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
import { motion } from 'framer-motion';
import { Theme } from '@/app/_components/ui/theme/theme';
diff --git a/packages/twenty-website/src/app/_components/releases/Line.tsx b/packages/twenty-website/src/app/_components/releases/Line.tsx
index 3b9267c0b6..b99a916ecc 100644
--- a/packages/twenty-website/src/app/_components/releases/Line.tsx
+++ b/packages/twenty-website/src/app/_components/releases/Line.tsx
@@ -1,6 +1,6 @@
'use client';
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
const StyledLineContainer = styled.div`
width: 810px;
diff --git a/packages/twenty-website/src/app/_components/releases/Release.tsx b/packages/twenty-website/src/app/_components/releases/Release.tsx
index 0c7e0b35fd..d28a1a7be0 100644
--- a/packages/twenty-website/src/app/_components/releases/Release.tsx
+++ b/packages/twenty-website/src/app/_components/releases/Release.tsx
@@ -1,6 +1,6 @@
'use client';
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
import { Gabarito } from 'next/font/google';
import { type JSXElementConstructor, type ReactElement } from 'react';
diff --git a/packages/twenty-website/src/app/_components/releases/StyledTitle.tsx b/packages/twenty-website/src/app/_components/releases/StyledTitle.tsx
index 32a84c482e..3f7348c627 100644
--- a/packages/twenty-website/src/app/_components/releases/StyledTitle.tsx
+++ b/packages/twenty-website/src/app/_components/releases/StyledTitle.tsx
@@ -1,6 +1,6 @@
'use client';
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
import { motion } from 'framer-motion';
const StyledTitle = styled.div`
diff --git a/packages/twenty-website/src/app/_components/ui/icons/SvgIcons.tsx b/packages/twenty-website/src/app/_components/ui/icons/SvgIcons.tsx
index e8498ebf04..99c6ee2586 100644
--- a/packages/twenty-website/src/app/_components/ui/icons/SvgIcons.tsx
+++ b/packages/twenty-website/src/app/_components/ui/icons/SvgIcons.tsx
@@ -11,10 +11,18 @@ const getSize = (size: string) => {
}
};
-export const GithubIcon = ({ size = 'S', color = 'rgb(179, 179, 179)' }) => {
+export const GithubIcon = ({
+ size = 'S',
+ color = 'rgb(179, 179, 179)',
+ className,
+}: {
+ size?: string;
+ color?: string;
+ className?: string;
+}) => {
const dimension = getSize(size);
return (
-
+