chore(twenty-front): migrate auth, activities, AI, pages and small modules from Emotion to Linaria (PR 2-3/10) (#18328)

## Summary

- Migrate ~200 files from `@emotion/styled` / `@emotion/react` to
`@linaria/react` + `themeCssVariables`, continuing the zero-runtime
CSS-in-JS migration (PR 2-3 of the [migration
plan](docs/emotion-to-linaria-migration-plan.md))
- Modules covered: **auth** (19), **activities** (53), **ai** (30),
**pages** (70), **action-menu** (3), **object-metadata** (4),
**onboarding** (2), **workspace** (2), **file** (3), **error-handler**
(2), **front-components** (1), **geo-map** (1), **loading** (5),
**testing** (5), plus a `style` prop addition to `TableRow`
- Handles `styled(FunctionComponent)<Props>` incompatibility with
Linaria by using CSS custom properties via `style` + `var()` references

## Test plan

- [x] `npx nx lint:diff-with-main twenty-front` passes
- [x] `npx nx typecheck twenty-front` passes
- [ ] Visual spot-check of auth, onboarding, settings, activities, and
AI chat screens
- [ ] No remaining `@emotion/styled` or `@emotion/react` imports in
migrated files


Made with [Cursor](https://cursor.com)
This commit is contained in:
Charles Bochet
2026-03-03 11:17:47 +01:00
committed by GitHub
parent ae291c99ba
commit 802a5b0af6
209 changed files with 2259 additions and 1825 deletions
@@ -1,12 +1,12 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { motion } from 'framer-motion';
import Skeleton, { SkeletonTheme } from 'react-loading-skeleton';
import { SKELETON_LOADER_HEIGHT_SIZES } from '@/activities/components/SkeletonLoader';
import { NAVIGATION_DRAWER_CONSTRAINTS } from '@/ui/layout/resizable-panel/constants/NavigationDrawerConstraints';
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
import { useTheme } from '@emotion/react';
import { ANIMATION } from 'twenty-ui/theme';
import { useContext } from 'react';
import { ANIMATION, ThemeContext } from 'twenty-ui/theme';
import { MainNavigationDrawerItemsSkeletonLoader } from '~/loading/components/MainNavigationDrawerItemsSkeletonLoader';
const StyledAnimatedContainer = styled(motion.div)`
@@ -48,7 +48,7 @@ const StyledSkeletonTitleContainer = styled.div`
export const LeftPanelSkeletonLoader = () => {
const isMobile = useIsMobile();
const theme = useTheme();
const { theme } = useContext(ThemeContext);
return (
<StyledAnimatedContainer
@@ -1,7 +1,8 @@
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';
const StyledSkeletonContainer = styled.div`
align-items: flex-start;
@@ -20,7 +21,7 @@ export const MainNavigationDrawerItemsSkeletonLoader = ({
title?: boolean;
length: number;
}) => {
const theme = useTheme();
const { theme } = useContext(ThemeContext);
return (
<StyledSkeletonContainer>
@@ -1,17 +1,19 @@
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 StyledRightDrawerContainer = styled.div`
display: flex;
flex-direction: column;
width: 100%;
padding: ${({ theme }) => theme.spacing(4)};
padding: ${themeCssVariables.spacing[4]};
`;
const StyledSkeletonLoader = () => {
const theme = useTheme();
const { theme } = useContext(ThemeContext);
return (
<SkeletonTheme
@@ -1,11 +1,12 @@
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 { BORDER_COMMON, MOBILE_VIEWPORT } from 'twenty-ui/theme';
import { BORDER_COMMON, MOBILE_VIEWPORT, ThemeContext } from 'twenty-ui/theme';
import { themeCssVariables } from 'twenty-ui/theme-constants';
const StyledMainContainer = styled.div`
background: ${({ theme }) => theme.background.noisy};
background: ${themeCssVariables.background.noisy};
box-sizing: border-box;
display: flex;
flex: 1 1 auto;
@@ -22,8 +23,8 @@ const StyledMainContainer = styled.div`
`;
const StyledPanel = styled.div`
background: ${({ theme }) => theme.background.primary};
border: 1px solid ${({ theme }) => theme.border.color.medium};
background: ${themeCssVariables.background.primary};
border: 1px solid ${themeCssVariables.border.color.medium};
border-radius: ${BORDER_COMMON.radius.md};
height: 100%;
overflow: auto;
@@ -49,7 +50,7 @@ const StyledRightPanelFlexContainer = styled.div`
`;
const StyledSkeletonHeaderLoader = () => {
const theme = useTheme();
const { theme } = useContext(ThemeContext);
return (
<StyledHeaderContainer>
@@ -68,7 +69,7 @@ const StyledSkeletonHeaderLoader = () => {
};
const StyledSkeletonAddLoader = () => {
const theme = useTheme();
const { theme } = useContext(ThemeContext);
return (
<SkeletonTheme
@@ -1,14 +1,15 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { useShowAuthModal } from '@/ui/layout/hooks/useShowAuthModal';
import { Modal } from '@/ui/layout/modal/components/Modal';
import { NAVIGATION_DRAWER_CONSTRAINTS } from '@/ui/layout/resizable-panel/constants/NavigationDrawerConstraints';
import { MOBILE_VIEWPORT } from 'twenty-ui/theme';
import { themeCssVariables } from 'twenty-ui/theme-constants';
import { LeftPanelSkeletonLoader } from '~/loading/components/LeftPanelSkeletonLoader';
import { RightPanelSkeletonLoader } from '~/loading/components/RightPanelSkeletonLoader';
const StyledContainer = styled.div`
background: ${({ theme }) => theme.background.noisy};
background: ${themeCssVariables.background.noisy};
box-sizing: border-box;
display: flex;
flex-direction: row;
@@ -1,12 +1,13 @@
import { type ActionDisplayProps } from '@/action-menu/actions/display/components/ActionDisplay';
import { getActionLabel } from '@/action-menu/utils/getActionLabel';
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { isDefined } from 'twenty-shared/utils';
import { AppTooltip, TooltipDelay, TooltipPosition } from 'twenty-ui/display';
import { Button, IconButton } from 'twenty-ui/input';
import { themeCssVariables } from 'twenty-ui/theme-constants';
const StyledWrapper = styled.div`
font-size: ${({ theme }) => theme.font.size.md};
font-size: ${themeCssVariables.font.size.md};
`;
export const ActionButton = ({
@@ -1,9 +1,9 @@
import { ActionComponent } from '@/action-menu/actions/display/components/ActionComponent';
import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { motion } from 'framer-motion';
import { useContext } from 'react';
import { ThemeContext } from 'twenty-ui/theme';
const StyledActionContainer = styled(motion.div)`
display: flex;
@@ -13,7 +13,7 @@ const StyledActionContainer = styled(motion.div)`
export const PageHeaderActionMenuButtons = () => {
const { actions } = useContext(ActionMenuContext);
const theme = useTheme();
const { theme } = useContext(ThemeContext);
const pinnedActions = actions.filter((entry) => entry.isPinned).toReversed();
@@ -16,7 +16,7 @@ import { SelectableListItem } from '@/ui/layout/selectable-list/components/Selec
import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states/selectedItemIdComponentState';
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateValue';
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { useLingui } from '@lingui/react/macro';
import { useContext } from 'react';
import { IconLayoutSidebarRightExpand } from 'twenty-ui/display';
@@ -1,10 +1,12 @@
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { useContext } from 'react';
import { styled } from '@linaria/react';
import { differenceInSeconds, endOfDay, format } from 'date-fns';
import { CalendarEventRow } from '@/activities/calendar/components/CalendarEventRow';
import { getCalendarEventStartDate } from '@/activities/calendar/utils/getCalendarEventStartDate';
import { CardContent } from 'twenty-ui/layout';
import { ThemeContext } from 'twenty-ui/theme';
import { themeCssVariables } from 'twenty-ui/theme-constants';
import { type TimelineCalendarEvent } from '~/generated/graphql';
type CalendarDayCardContentProps = {
@@ -14,26 +16,26 @@ type CalendarDayCardContentProps = {
const StyledCardContent = styled(CardContent)`
align-items: flex-start;
border-color: ${({ theme }) => theme.border.color.light};
border-color: ${themeCssVariables.border.color.light};
display: flex;
flex-direction: row;
gap: ${({ theme }) => theme.spacing(3)};
padding: ${({ theme }) => theme.spacing(2, 3)};
gap: ${themeCssVariables.spacing[3]};
padding: ${themeCssVariables.spacing[2]} ${themeCssVariables.spacing[3]};
`;
const StyledDayContainer = styled.div`
text-align: center;
width: ${({ theme }) => theme.spacing(6)};
width: ${themeCssVariables.spacing[6]};
`;
const StyledWeekDay = styled.div`
color: ${({ theme }) => theme.font.color.tertiary};
font-size: ${({ theme }) => theme.font.size.xxs};
font-weight: ${({ theme }) => theme.font.weight.semiBold};
color: ${themeCssVariables.font.color.tertiary};
font-size: ${themeCssVariables.font.size.xxs};
font-weight: ${themeCssVariables.font.weight.semiBold};
`;
const StyledMonthDay = styled.div`
font-weight: ${({ theme }) => theme.font.weight.medium};
font-weight: ${themeCssVariables.font.weight.medium};
`;
const StyledEvents = styled.div`
@@ -41,7 +43,7 @@ const StyledEvents = styled.div`
display: flex;
flex: 1 0 auto;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(3)};
gap: ${themeCssVariables.spacing[3]};
`;
const StyledEventRow = styled(CalendarEventRow)`
@@ -52,7 +54,7 @@ export const CalendarDayCardContent = ({
calendarEvents,
divider,
}: CalendarDayCardContentProps) => {
const theme = useTheme();
const { theme } = useContext(ThemeContext);
const endOfDayDate = endOfDay(getCalendarEventStartDate(calendarEvents[0]));
const dayEndsIn = differenceInSeconds(endOfDayDate, Date.now());
@@ -1,5 +1,4 @@
import { css } from '@emotion/react';
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { useLingui } from '@lingui/react/macro';
import { useCallback, useState } from 'react';
@@ -33,6 +32,7 @@ import {
ChipVariant,
} from 'twenty-ui/components';
import { IconCalendarEvent } from 'twenty-ui/display';
import { themeCssVariables } from 'twenty-ui/theme-constants';
import { beautifyPastDateRelativeToNow } from '~/utils/date-utils';
type CalendarEventDetailsProps = {
@@ -42,50 +42,47 @@ type CalendarEventDetailsProps = {
const INPUT_ID_PREFIX = 'calendar-event-details';
const StyledContainer = styled.div`
background: ${({ theme }) => theme.background.secondary};
background: ${themeCssVariables.background.secondary};
align-items: flex-start;
border-bottom: 1px solid ${({ theme }) => theme.border.color.medium};
border-bottom: 1px solid ${themeCssVariables.border.color.medium};
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(6)};
padding: ${({ theme }) => theme.spacing(6)};
gap: ${themeCssVariables.spacing[6]};
padding: ${themeCssVariables.spacing[6]};
width: 100%;
box-sizing: border-box;
`;
const StyledEventChip = styled(Chip)`
gap: ${({ theme }) => theme.spacing(2)};
padding-left: ${({ theme }) => theme.spacing(2)};
padding-right: ${({ theme }) => theme.spacing(2)};
gap: ${themeCssVariables.spacing[2]};
padding-left: ${themeCssVariables.spacing[2]};
padding-right: ${themeCssVariables.spacing[2]};
`;
const StyledHeader = styled.header``;
const StyledTitle = styled.h2<{ canceled?: boolean }>`
color: ${({ theme }) => theme.font.color.primary};
font-weight: ${({ theme }) => theme.font.weight.semiBold};
margin: ${({ theme }) => theme.spacing(0, 0, 2)};
color: ${themeCssVariables.font.color.primary};
font-weight: ${themeCssVariables.font.weight.semiBold};
margin: ${themeCssVariables.spacing[0]} ${themeCssVariables.spacing[0]}
${themeCssVariables.spacing[2]};
${({ canceled }) =>
canceled &&
css`
text-decoration: line-through;
`}
${({ canceled }) => (canceled ? 'text-decoration: line-through' : '')}
`;
const StyledCreatedAt = styled.div`
color: ${({ theme }) => theme.font.color.tertiary};
color: ${themeCssVariables.font.color.tertiary};
`;
const StyledFields = styled.div`
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(3)};
gap: ${themeCssVariables.spacing[3]};
width: 100%;
`;
const StyledPropertyBox = styled(PropertyBox)`
height: ${({ theme }) => theme.spacing(6)};
height: ${themeCssVariables.spacing[6]};
padding: 0;
width: 100%;
`;
@@ -1,30 +1,32 @@
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { useContext } from 'react';
import { styled } from '@linaria/react';
import { Trans } from '@lingui/react/macro';
import { IconLock } from 'twenty-ui/display';
import { Card, CardContent } from 'twenty-ui/layout';
import { ThemeContext } from 'twenty-ui/theme';
import { themeCssVariables } from 'twenty-ui/theme-constants';
const StyledVisibilityCard = styled(Card)`
border-color: ${({ theme }) => theme.border.color.light};
color: ${({ theme }) => theme.font.color.light};
border-color: ${themeCssVariables.border.color.light};
color: ${themeCssVariables.font.color.light};
flex: 1;
transition: color ${({ theme }) => theme.animation.duration.normal} ease;
transition: color ${themeCssVariables.animation.duration.normal} ease;
width: 100%;
`;
const StyledVisibilityCardContent = styled(CardContent)`
align-items: center;
font-size: ${({ theme }) => theme.font.size.sm};
font-weight: ${({ theme }) => theme.font.weight.medium};
font-size: ${themeCssVariables.font.size.sm};
font-weight: ${themeCssVariables.font.weight.medium};
display: flex;
gap: ${({ theme }) => theme.spacing(1)};
padding: ${({ theme }) => theme.spacing(0, 1)};
height: ${({ theme }) => theme.spacing(6)};
background-color: ${({ theme }) => theme.background.transparent.lighter};
gap: ${themeCssVariables.spacing[1]};
padding: ${themeCssVariables.spacing[0]} ${themeCssVariables.spacing[1]};
height: ${themeCssVariables.spacing[6]};
background-color: ${themeCssVariables.background.transparent.lighter};
`;
export const CalendarEventNotSharedContent = () => {
const theme = useTheme();
const { theme } = useContext(ThemeContext);
return (
<StyledVisibilityCard>
@@ -1,6 +1,5 @@
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { useRef } from 'react';
import { useContext, useRef } from 'react';
import { styled } from '@linaria/react';
import { type CalendarEventParticipant } from '@/activities/calendar/types/CalendarEventParticipant';
import { ParticipantChip } from '@/activities/components/ParticipantChip';
@@ -8,6 +7,8 @@ import { PropertyBox } from '@/object-record/record-inline-cell/property-box/com
import { EllipsisDisplay } from '@/ui/field/display/components/EllipsisDisplay';
import { ExpandableList } from '@/ui/layout/expandable-list/components/ExpandableList';
import { IconCheck, IconQuestionMark, IconX } from 'twenty-ui/display';
import { ThemeContext } from 'twenty-ui/theme';
import { themeCssVariables } from 'twenty-ui/theme-constants';
const StyledInlineCellBaseContainer = styled.div`
align-items: center;
@@ -15,21 +16,21 @@ const StyledInlineCellBaseContainer = styled.div`
width: 100%;
display: flex;
gap: ${({ theme }) => theme.spacing(1)};
gap: ${themeCssVariables.spacing[1]};
position: relative;
user-select: none;
`;
const StyledPropertyBox = styled(PropertyBox)`
height: ${({ theme }) => theme.spacing(6)};
height: ${themeCssVariables.spacing[6]};
padding: 0;
width: 100%;
`;
const StyledIconContainer = styled.div`
align-items: center;
color: ${({ theme }) => theme.font.color.tertiary};
color: ${themeCssVariables.font.color.tertiary};
display: flex;
width: 16px;
@@ -44,15 +45,15 @@ const StyledIconContainer = styled.div`
const StyledLabelAndIconContainer = styled.div`
align-items: center;
color: ${({ theme }) => theme.font.color.tertiary};
color: ${themeCssVariables.font.color.tertiary};
display: flex;
gap: ${({ theme }) => theme.spacing(1)};
gap: ${themeCssVariables.spacing[1]};
`;
const StyledLabelContainer = styled.div<{ width?: number }>`
color: ${({ theme }) => theme.font.color.tertiary};
font-size: ${({ theme }) => theme.font.size.sm};
width: ${({ width }) => width}px;
color: ${themeCssVariables.font.color.tertiary};
font-size: ${themeCssVariables.font.size.sm};
width: ${({ width }) => (width !== undefined ? `${width}px` : 'auto')};
`;
const StyledDiv = styled.div`
max-width: 70%;
@@ -65,7 +66,7 @@ export const CalendarEventParticipantsResponseStatusField = ({
responseStatus: 'Yes' | 'Maybe' | 'No';
participants: CalendarEventParticipant[];
}) => {
const theme = useTheme();
const { theme } = useContext(ThemeContext);
const Icon = {
Yes: <IconCheck stroke={theme.icon.stroke.sm} />,
@@ -1,5 +1,5 @@
import { css, useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { useContext } from 'react';
import { styled } from '@linaria/react';
import { t } from '@lingui/core/macro';
import { format } from 'date-fns';
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
@@ -16,6 +16,8 @@ import { hasCalendarEventEnded } from '@/activities/calendar/utils/hasCalendarEv
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
import { useOpenCalendarEventInCommandMenu } from '@/command-menu/hooks/useOpenCalendarEventInCommandMenu';
import { IconArrowRight } from 'twenty-ui/display';
import { ThemeContext } from 'twenty-ui/theme';
import { themeCssVariables } from 'twenty-ui/theme-constants';
type CalendarEventRowProps = {
calendarEvent: TimelineCalendarEvent;
@@ -25,39 +27,36 @@ type CalendarEventRowProps = {
const StyledContainer = styled.div<{ showTitle?: boolean }>`
align-items: center;
display: inline-flex;
gap: ${({ theme }) => theme.spacing(3)};
height: ${({ theme }) => theme.spacing(6)};
gap: ${themeCssVariables.spacing[3]};
height: ${themeCssVariables.spacing[6]};
position: relative;
cursor: ${({ showTitle }) => (showTitle ? 'pointer' : 'not-allowed')};
`;
const StyledAttendanceIndicator = styled.div<{ active?: boolean }>`
background-color: ${({ theme }) => theme.tag.background.gray};
background-color: ${themeCssVariables.tag.background.gray};
height: 100%;
width: ${({ theme }) => theme.spacing(1)};
border-radius: ${({ theme }) => theme.border.radius.xs};
width: ${themeCssVariables.spacing[1]};
border-radius: ${themeCssVariables.border.radius.xs};
${({ active, theme }) =>
active &&
css`
background-color: ${theme.tag.background.red};
`}
${({ active }) =>
active ? `background-color: ${themeCssVariables.tag.background.red}` : ''}
`;
const StyledLabels = styled.div`
align-items: center;
display: flex;
color: ${({ theme }) => theme.font.color.primary};
gap: ${({ theme }) => theme.spacing(2)};
color: ${themeCssVariables.font.color.primary};
gap: ${themeCssVariables.spacing[2]};
flex: 1 0 auto;
`;
const StyledTime = styled.div`
align-items: center;
display: flex;
color: ${({ theme }) => theme.font.color.tertiary};
gap: ${({ theme }) => theme.spacing(1)};
width: ${({ theme }) => theme.spacing(26)};
color: ${themeCssVariables.font.color.tertiary};
gap: ${themeCssVariables.spacing[1]};
width: ${themeCssVariables.spacing[26]};
`;
const StyledTitle = styled.div<{ active: boolean; canceled: boolean }>`
@@ -65,26 +64,20 @@ const StyledTitle = styled.div<{ active: boolean; canceled: boolean }>`
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
width: ${({ theme }) => theme.spacing(10)};
${({ theme, active }) =>
active &&
css`
color: ${theme.font.color.primary};
font-weight: ${theme.font.weight.medium};
`}
width: ${themeCssVariables.spacing[10]};
${({ active }) =>
active
? `color: ${themeCssVariables.font.color.primary}; font-weight: ${themeCssVariables.font.weight.medium}`
: ''}
${({ canceled }) =>
canceled &&
css`
text-decoration: line-through;
`}
${({ canceled }) => (canceled ? 'text-decoration: line-through' : '')}
`;
export const CalendarEventRow = ({
calendarEvent,
className,
}: CalendarEventRowProps) => {
const theme = useTheme();
const { theme } = useContext(ThemeContext);
const currentWorkspaceMember = useAtomStateValue(currentWorkspaceMemberState);
const { openCalendarEventInCommandMenu } =
useOpenCalendarEventInCommandMenu();
@@ -1,5 +1,5 @@
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { useLingui } from '@lingui/react/macro';
import { format, getYear } from 'date-fns';
@@ -25,6 +25,7 @@ import {
EMPTY_PLACEHOLDER_TRANSITION_PROPS,
Section,
} from 'twenty-ui/layout';
import { themeCssVariables } from 'twenty-ui/theme-constants';
import { type TimelineCalendarEventsWithTotal } from '~/generated/graphql';
import { dateLocaleState } from '~/localization/states/dateLocaleState';
@@ -32,18 +33,18 @@ const StyledContainer = styled.div`
box-sizing: border-box;
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(8)};
padding: ${({ theme }) => theme.spacing(6)};
gap: ${themeCssVariables.spacing[8]};
padding: ${themeCssVariables.spacing[6]};
width: 100%;
overflow: scroll;
`;
const StyledYear = styled.span`
color: ${({ theme }) => theme.font.color.light};
color: ${themeCssVariables.font.color.light};
`;
const StyledTitleContainer = styled.div`
margin-bottom: ${({ theme }) => theme.spacing(4)};
margin-bottom: ${themeCssVariables.spacing[4]};
`;
export const CalendarEventsCard = () => {
@@ -1,9 +1,10 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { Card } from 'twenty-ui/layout';
import { themeCssVariables } from 'twenty-ui/theme-constants';
const StyledList = styled(Card)`
& > :not(:last-child) {
border-bottom: 1px solid ${({ theme }) => theme.border.color.light};
border-bottom: 1px solid ${themeCssVariables.border.color.light};
}
width: calc(100% - 2px);
@@ -1,16 +1,14 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import React from 'react';
import { CardContent } from 'twenty-ui/layout';
import { themeCssVariables } from 'twenty-ui/theme-constants';
const StyledRowContent = styled(CardContent)<{
clickable?: boolean;
}>`
const StyledRowContent = styled(CardContent)`
align-items: center;
display: flex;
gap: ${({ theme }) => theme.spacing(2)};
height: ${({ theme }) => theme.spacing(12)};
padding: ${({ theme }) => theme.spacing(0, 4)};
cursor: ${({ clickable }) => (clickable === true ? 'pointer' : 'default')};
gap: ${themeCssVariables.spacing[2]};
height: ${themeCssVariables.spacing[12]};
padding: ${themeCssVariables.spacing[0]} ${themeCssVariables.spacing[4]};
`;
export const ActivityRow = ({
@@ -28,7 +26,7 @@ export const ActivityRow = ({
};
return (
<StyledRowContent onClick={handleClick} clickable={disabled !== true}>
<StyledRowContent onClick={handleClick} isClickable={disabled !== true}>
{children}
</StyledRowContent>
);
@@ -1,8 +1,9 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { type ActivityTargetWithTargetRecord } from '@/activities/types/ActivityTargetObject';
import { RecordChip } from '@/object-record/components/RecordChip';
import { ExpandableList } from '@/ui/layout/expandable-list/components/ExpandableList';
import { themeCssVariables } from 'twenty-ui/theme-constants';
type ActivityTargetChipsProps = {
activityTargetObjectRecords: ActivityTargetWithTargetRecord[];
@@ -12,7 +13,7 @@ type ActivityTargetChipsProps = {
const StyledContainer = styled.div<{ maxWidth?: number }>`
display: flex;
flex-wrap: wrap;
gap: ${({ theme }) => theme.spacing(1)};
gap: ${themeCssVariables.spacing[1]};
max-width: ${({ maxWidth }) => (maxWidth ? `${maxWidth}px` : 'none')};
`;
@@ -1,6 +1,7 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { t } from '@lingui/core/macro';
import { useInView } from 'react-intersection-observer';
import { themeCssVariables } from 'twenty-ui/theme-constants';
type CustomResolverFetchMoreLoaderProps = {
loading: boolean;
@@ -14,11 +15,11 @@ const StyledContainer = styled.div`
const StyledText = styled.div`
align-items: center;
box-shadow: none;
color: ${({ theme }) => theme.grayScale.gray9};
color: ${themeCssVariables.grayScale.gray9};
display: flex;
height: 32px;
margin-left: ${({ theme }) => theme.spacing(8)};
padding-left: ${({ theme }) => theme.spacing(2)};
margin-left: ${themeCssVariables.spacing[8]};
padding-left: ${themeCssVariables.spacing[2]};
`;
export const CustomResolverFetchMoreLoader = ({
@@ -1,19 +1,23 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import React from 'react';
import { getDisplayNameFromParticipant } from '@/activities/emails/utils/getDisplayNameFromParticipant';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { RecordChip } from '@/object-record/components/RecordChip';
import { Avatar } from 'twenty-ui/display';
import { themeCssVariables } from 'twenty-ui/theme-constants';
const StyledAvatar = styled(Avatar)`
margin-right: ${({ theme }) => theme.spacing(1)};
margin-right: ${themeCssVariables.spacing[1]};
`;
const StyledSenderName = styled.span<{ variant?: 'default' | 'bold' }>`
color: ${({ theme }) => theme.font.color.primary};
font-size: ${({ theme }) => theme.font.size.md};
font-weight: ${({ theme, variant }) =>
variant === 'bold' ? theme.font.weight.medium : theme.font.weight.regular};
color: ${themeCssVariables.font.color.primary};
font-size: ${themeCssVariables.font.size.md};
font-weight: ${({ variant }) =>
variant === 'bold'
? themeCssVariables.font.weight.medium
: themeCssVariables.font.weight.regular};
overflow: hidden;
text-overflow: ellipsis;
`;
@@ -23,23 +27,14 @@ const StyledContainer = styled.div`
display: flex;
`;
const StyledRecordChip = styled(RecordChip)<{
participantChipVariant: 'default' | 'bold';
}>`
font-weight: ${({ theme, participantChipVariant }) =>
participantChipVariant === 'bold'
? theme.font.weight.medium
: theme.font.weight.regular};
`;
const StyledChip = styled.div`
align-items: center;
display: flex;
padding: ${({ theme }) => theme.spacing(1)};
padding: ${themeCssVariables.spacing[1]};
height: 20px;
box-sizing: border-box;
white-space: nowrap;
gap: ${({ theme }) => theme.spacing(1)};
gap: ${themeCssVariables.spacing[1]};
`;
type ParticipantChipVariant = 'default' | 'bold';
@@ -65,10 +60,10 @@ export const ParticipantChip = ({
return (
<StyledContainer className={className}>
{person ? (
<StyledRecordChip
<RecordChip
objectNameSingular={CoreObjectNameSingular.Person}
record={person}
participantChipVariant={variant}
isBold={variant === 'bold'}
/>
) : (
<StyledChip>
@@ -1,27 +1,29 @@
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { useContext } from 'react';
import { styled } from '@linaria/react';
import Skeleton, { SkeletonTheme } from 'react-loading-skeleton';
import { ThemeContext } from 'twenty-ui/theme';
import { themeCssVariables } from 'twenty-ui/theme-constants';
const StyledSkeletonContainer = styled.div`
align-items: center;
width: 100%;
padding: ${({ theme }) => theme.spacing(8)};
padding: ${themeCssVariables.spacing[8]};
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(4)};
gap: ${themeCssVariables.spacing[4]};
flex-wrap: wrap;
align-content: flex-start;
`;
const StyledSkeletonSubSection = styled.div`
display: flex;
gap: ${({ theme }) => theme.spacing(4)};
gap: ${themeCssVariables.spacing[4]};
`;
const StyledSkeletonSubSectionContent = styled.div`
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(3)};
gap: ${themeCssVariables.spacing[3]};
justify-content: center;
`;
@@ -41,7 +43,7 @@ export const SKELETON_LOADER_HEIGHT_SIZES = {
};
const SkeletonColumnLoader = ({ height }: { height: number }) => {
const theme = useTheme();
const { theme } = useContext(ThemeContext);
return (
<SkeletonTheme
@@ -59,7 +61,7 @@ export const SkeletonLoader = ({
}: {
withSubSections?: boolean;
}) => {
const theme = useTheme();
const { theme } = useContext(ThemeContext);
const skeletonItems = Array.from({ length: 3 }).map((_, index) => ({
id: `skeleton-item-${index}`,
}));
@@ -1,15 +1,16 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { t } from '@lingui/core/macro';
import { IconArrowBackUp, IconUserCircle } from 'twenty-ui/display';
import { Button } from 'twenty-ui/input';
import { themeCssVariables } from 'twenty-ui/theme-constants';
const StyledThreadBottomBar = styled.div`
align-items: center;
display: flex;
gap: ${({ theme }) => theme.spacing(2)};
padding-left: ${({ theme }) => theme.spacing(6)};
padding-right: ${({ theme }) => theme.spacing(6)};
padding-top: ${({ theme }) => theme.spacing(4)};
gap: ${themeCssVariables.spacing[2]};
padding-left: ${themeCssVariables.spacing[6]};
padding-right: ${themeCssVariables.spacing[6]};
padding-top: ${themeCssVariables.spacing[4]};
`;
export const ThreadBottomBar = () => {
@@ -1,7 +1,8 @@
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { t } from '@lingui/core/macro';
import { themeCssVariables } from 'twenty-ui/theme-constants';
import { dateLocaleState } from '~/localization/states/dateLocaleState';
import { beautifyPastDateRelativeToNow } from '~/utils/date-utils';
@@ -14,10 +15,10 @@ const StyledContainer = styled.div`
align-items: flex-start;
display: flex;
flex-direction: column;
padding: ${({ theme }) => theme.spacing(6)};
gap: ${({ theme }) => theme.spacing(6)};
border-bottom: 1px solid ${({ theme }) => theme.border.color.medium};
background: ${({ theme }) => theme.background.secondary};
padding: ${themeCssVariables.spacing[6]};
gap: ${themeCssVariables.spacing[6]};
border-bottom: 1px solid ${themeCssVariables.border.color.medium};
background: ${themeCssVariables.background.secondary};
`;
const StyledHead = styled.div`
@@ -26,16 +27,16 @@ const StyledHead = styled.div`
const StyledHeading = styled.h2`
margin: 0;
margin-bottom: ${({ theme }) => theme.spacing(3)};
margin-bottom: ${themeCssVariables.spacing[3]};
max-width: 100%;
color: ${({ theme }) => theme.font.color.primary};
color: ${themeCssVariables.font.color.primary};
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
`;
const StyledContent = styled.span`
color: ${({ theme }) => theme.font.color.tertiary};
color: ${themeCssVariables.font.color.tertiary};
width: 100%;
`;
@@ -1,4 +1,4 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { useState } from 'react';
import { EmailThreadMessageBody } from '@/activities/emails/components/EmailThreadMessageBody';
@@ -9,13 +9,14 @@ import { EmailThreadNotShared } from '@/activities/emails/components/EmailThread
import { type EmailThreadMessageParticipant } from '@/activities/emails/types/EmailThreadMessageParticipant';
import { FIELD_RESTRICTED_ADDITIONAL_PERMISSIONS_REQUIRED } from 'twenty-shared/constants';
import { MessageParticipantRole } from 'twenty-shared/types';
import { themeCssVariables } from 'twenty-ui/theme-constants';
import { MessageChannelVisibility } from '~/generated/graphql';
const StyledThreadMessage = styled.div`
border-bottom: 1px solid ${({ theme }) => theme.border.color.light};
border-bottom: 1px solid ${themeCssVariables.border.color.light};
display: flex;
flex-direction: column;
padding: ${({ theme }) => theme.spacing(4, 0)};
padding: ${themeCssVariables.spacing[4]} ${themeCssVariables.spacing[0]};
`;
const StyledThreadMessageHeader = styled.div`
@@ -23,12 +24,12 @@ const StyledThreadMessageHeader = styled.div`
cursor: pointer;
flex-direction: column;
justify-content: space-between;
margin-bottom: ${({ theme }) => theme.spacing(2)};
padding: ${({ theme }) => theme.spacing(0, 6)};
margin-bottom: ${themeCssVariables.spacing[2]};
padding: ${themeCssVariables.spacing[0]} ${themeCssVariables.spacing[6]};
`;
const StyledThreadMessageBody = styled.div`
padding: ${({ theme }) => theme.spacing(0, 6)};
padding: ${themeCssVariables.spacing[0]} ${themeCssVariables.spacing[6]};
`;
type EmailThreadMessageProps = {
@@ -1,25 +1,26 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { motion } from 'framer-motion';
import Linkify from 'linkify-react';
import { themeCssVariables } from 'twenty-ui/theme-constants';
import { AnimatedEaseInOut } from 'twenty-ui/utilities';
const StyledThreadMessageBody = styled(motion.div)`
color: ${({ theme }) => theme.font.color.primary};
color: ${themeCssVariables.font.color.primary};
display: flex;
flex-direction: column;
margin-top: ${({ theme }) => theme.spacing(4)};
margin-top: ${themeCssVariables.spacing[4]};
white-space: pre-line;
overflow-wrap: break-word;
a {
color: ${({ theme }) => theme.font.color.primary};
color: ${themeCssVariables.font.color.primary};
text-decoration: underline;
text-decoration-color: ${({ theme }) => theme.font.color.primary};
text-decoration-color: ${themeCssVariables.font.color.primary};
&:hover {
color: ${({ theme }) => theme.font.color.tertiary};
text-decoration-color: ${({ theme }) => theme.border.color.strong};
color: ${themeCssVariables.font.color.tertiary};
text-decoration-color: ${themeCssVariables.border.color.strong};
}
}
`;
@@ -1,12 +1,13 @@
import React from 'react';
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { themeCssVariables } from 'twenty-ui/theme-constants';
const StyledThreadMessageBodyPreview = styled.div`
color: ${({ theme }) => theme.font.color.tertiary};
color: ${themeCssVariables.font.color.tertiary};
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: ${({ theme }) => theme.font.size.sm};
font-size: ${themeCssVariables.font.size.sm};
`;
type EmailThreadMessageBodyPreviewProps = {
@@ -1,18 +1,20 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { type EmailThreadMessageParticipant } from '@/activities/emails/types/EmailThreadMessageParticipant';
import { getDisplayNameFromParticipant } from '@/activities/emails/utils/getDisplayNameFromParticipant';
import { OverflowingTextWithTooltip } from 'twenty-ui/display';
import { themeCssVariables } from 'twenty-ui/theme-constants';
type EmailThreadMessageReceiversProps = {
receivers: EmailThreadMessageParticipant[];
};
const StyledThreadMessageReceivers = styled.span`
color: ${({ theme }) => theme.font.color.tertiary};
color: ${themeCssVariables.font.color.tertiary};
display: flex;
font-size: ${({ theme }) => theme.font.size.xs};
padding: ${({ theme }) => theme.spacing(2, 0, 0, 1)};
font-size: ${themeCssVariables.font.size.xs};
padding: ${themeCssVariables.spacing[2]} ${themeCssVariables.spacing[0]}
${themeCssVariables.spacing[0]} ${themeCssVariables.spacing[1]};
width: 50%;
`;
@@ -1,9 +1,10 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { ParticipantChip } from '@/activities/components/ParticipantChip';
import { type EmailThreadMessageParticipant } from '@/activities/emails/types/EmailThreadMessageParticipant';
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
import { AppTooltip, TooltipPosition } from 'twenty-ui/display';
import { themeCssVariables } from 'twenty-ui/theme-constants';
import { dateLocaleState } from '~/localization/states/dateLocaleState';
import {
beautifyPastDateRelativeToNow,
@@ -18,8 +19,8 @@ const StyledEmailThreadMessageSender = styled.div`
const StyledThreadMessageSentAt = styled.div`
align-items: flex-end;
display: flex;
color: ${({ theme }) => theme.font.color.tertiary};
font-size: ${({ theme }) => theme.font.size.sm};
color: ${themeCssVariables.font.color.tertiary};
font-size: ${themeCssVariables.font.size.sm};
`;
type EmailThreadMessageSenderProps = {
@@ -1,27 +1,29 @@
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { useContext } from 'react';
import { styled } from '@linaria/react';
import { useLingui } from '@lingui/react/macro';
import { AppTooltip, IconLock, TooltipDelay } from 'twenty-ui/display';
import { ThemeContext } from 'twenty-ui/theme';
import { themeCssVariables } from 'twenty-ui/theme-constants';
import { MessageChannelVisibility } from '~/generated/graphql';
const StyledContainer = styled.div<{ isCompact?: boolean }>`
align-items: center;
display: flex;
flex: ${({ isCompact }) => (isCompact ? '0 0 auto' : '1 0 0')};
gap: ${({ theme }) => theme.spacing(1)};
gap: ${themeCssVariables.spacing[1]};
height: 20px;
margin-left: auto;
width: ${({ isCompact }) => (isCompact ? 'auto' : '100%')};
min-width: ${({ theme }) => `${theme.spacing(21)}`};
padding: ${({ theme }) => theme.spacing(0, 1)};
min-width: ${themeCssVariables.spacing[21]};
padding: ${themeCssVariables.spacing[0]} ${themeCssVariables.spacing[1]};
border-radius: 4px;
border: 1px solid ${({ theme }) => theme.border.color.light};
background: ${({ theme }) => theme.background.transparent.lighter};
border: 1px solid ${themeCssVariables.border.color.light};
background: ${themeCssVariables.background.transparent.lighter};
color: ${({ theme }) => theme.font.color.tertiary};
font-weight: ${({ theme }) => theme.font.weight.regular};
font-size: ${({ theme }) => theme.font.size.sm};
color: ${themeCssVariables.font.color.tertiary};
font-weight: ${themeCssVariables.font.weight.regular};
font-size: ${themeCssVariables.font.size.sm};
flex: 1;
`;
@@ -33,7 +35,7 @@ export const EmailThreadNotShared = ({
visibility,
}: EmailThreadNotSharedProps) => {
const { t } = useLingui();
const theme = useTheme();
const { theme } = useContext(ThemeContext);
const containerId = 'email-thread-not-shared';
const isCompact = visibility === MessageChannelVisibility.SUBJECT;
@@ -1,10 +1,12 @@
import styled from '@emotion/styled';
import { useContext } from 'react';
import { styled } from '@linaria/react';
import { ActivityRow } from '@/activities/components/ActivityRow';
import { EmailThreadNotShared } from '@/activities/emails/components/EmailThreadNotShared';
import { useOpenEmailThreadInCommandMenu } from '@/command-menu/hooks/useOpenEmailThreadInCommandMenu';
import { useTheme } from '@emotion/react';
import { Avatar } from 'twenty-ui/display';
import { ThemeContext } from 'twenty-ui/theme';
import { themeCssVariables } from 'twenty-ui/theme-constants';
import {
MessageChannelVisibility,
type TimelineThread,
@@ -24,38 +26,38 @@ const StyledParticipantsContainer = styled.div`
`;
const StyledAvatar = styled(Avatar)`
margin-left: ${({ theme }) => theme.spacing(-1)};
margin-left: calc(-1 * ${themeCssVariables.spacing[1]});
`;
const StyledSenderNames = styled.span`
display: flex;
margin: ${({ theme }) => theme.spacing(0, 1)};
margin: ${themeCssVariables.spacing[0]} ${themeCssVariables.spacing[1]};
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
`;
const StyledThreadCount = styled.span`
color: ${({ theme }) => theme.font.color.tertiary};
color: ${themeCssVariables.font.color.tertiary};
`;
const StyledSubjectAndBody = styled.div`
align-items: center;
display: flex;
flex: 1;
gap: ${({ theme }) => theme.spacing(2)};
gap: ${themeCssVariables.spacing[2]};
overflow: hidden;
`;
const StyledSubject = styled.span`
color: ${({ theme }) => theme.font.color.primary};
color: ${themeCssVariables.font.color.primary};
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
`;
const StyledBody = styled.span`
color: ${({ theme }) => theme.font.color.tertiary};
color: ${themeCssVariables.font.color.tertiary};
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
@@ -63,9 +65,9 @@ const StyledBody = styled.span`
`;
const StyledReceivedAt = styled.div`
font-size: ${({ theme }) => theme.font.size.sm};
font-weight: ${({ theme }) => theme.font.weight.regular};
padding: ${({ theme }) => theme.spacing(0, 1)};
font-size: ${themeCssVariables.font.size.sm};
font-weight: ${themeCssVariables.font.weight.regular};
padding: ${themeCssVariables.spacing[0]} ${themeCssVariables.spacing[1]};
`;
type EmailThreadPreviewProps = {
@@ -105,7 +107,7 @@ export const EmailThreadPreview = ({ thread }: EmailThreadPreviewProps) => {
};
const isDisabled = visibility !== MessageChannelVisibility.SHARE_EVERYTHING;
const theme = useTheme();
const { theme } = useContext(ThemeContext);
return (
<ActivityRow onClick={handleThreadClick} disabled={isDisabled}>
@@ -1,4 +1,4 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { ActivityList } from '@/activities/components/ActivityList';
import { CustomResolverFetchMoreLoader } from '@/activities/components/CustomResolverFetchMoreLoader';
@@ -22,6 +22,7 @@ import {
EMPTY_PLACEHOLDER_TRANSITION_PROPS,
Section,
} from 'twenty-ui/layout';
import { themeCssVariables } from 'twenty-ui/theme-constants';
import {
type TimelineThread,
type TimelineThreadsWithTotal,
@@ -30,19 +31,20 @@ import {
const StyledContainer = styled.div`
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(6)};
padding: ${({ theme }) => theme.spacing(6, 6, 2)};
gap: ${themeCssVariables.spacing[6]};
padding: ${themeCssVariables.spacing[6]} ${themeCssVariables.spacing[6]}
${themeCssVariables.spacing[2]};
height: 100%;
overflow: auto;
`;
const StyledH1Title = styled(H1Title)`
display: flex;
gap: ${({ theme }) => theme.spacing(2)};
gap: ${themeCssVariables.spacing[2]};
`;
const StyledEmailCount = styled.span`
color: ${({ theme }) => theme.font.color.light};
color: ${themeCssVariables.font.color.light};
`;
export const EmailsCard = () => {
@@ -1,4 +1,4 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { t } from '@lingui/core/macro';
import { lazy, type ReactElement, Suspense, useState } from 'react';
import { createPortal } from 'react-dom';
@@ -20,6 +20,7 @@ import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper';
import { assertIsDefinedOrThrow } from 'twenty-shared/utils';
import { IconDownload, IconX } from 'twenty-ui/display';
import { IconButton } from 'twenty-ui/input';
import { themeCssVariables } from 'twenty-ui/theme-constants';
import {
PermissionFlagType,
FeatureFlagKey,
@@ -45,28 +46,29 @@ const StyledContainer = styled.div`
display: flex;
flex-direction: column;
justify-content: center;
padding: ${({ theme }) => theme.spacing(2, 6, 6)};
width: calc(100% - ${({ theme }) => theme.spacing(12)});
padding: ${themeCssVariables.spacing[2]} ${themeCssVariables.spacing[6]}
${themeCssVariables.spacing[6]};
width: calc(100% - ${themeCssVariables.spacing[12]});
height: 100%;
`;
const StyledTitleBar = styled.h3`
display: flex;
justify-content: space-between;
margin-bottom: ${({ theme }) => theme.spacing(4)};
margin-top: ${({ theme }) => theme.spacing(4)};
margin-bottom: ${themeCssVariables.spacing[4]};
margin-top: ${themeCssVariables.spacing[4]};
place-items: center;
width: 100%;
`;
const StyledTitle = styled.span`
color: ${({ theme }) => theme.font.color.primary};
font-weight: ${({ theme }) => theme.font.weight.semiBold};
color: ${themeCssVariables.font.color.primary};
font-weight: ${themeCssVariables.font.weight.semiBold};
`;
const StyledCount = styled.span`
color: ${({ theme }) => theme.font.color.light};
margin-left: ${({ theme }) => theme.spacing(2)};
color: ${themeCssVariables.font.color.light};
margin-left: ${themeCssVariables.spacing[2]};
`;
const StyledDropZoneContainer = styled.div`
@@ -77,7 +79,7 @@ const StyledDropZoneContainer = styled.div`
const StyledLoadingContainer = styled.div`
align-items: center;
background: ${({ theme }) => theme.background.primary};
background: ${themeCssVariables.background.primary};
display: flex;
height: 80vh;
justify-content: center;
@@ -85,9 +87,9 @@ const StyledLoadingContainer = styled.div`
`;
const StyledLoadingText = styled.div`
color: ${({ theme }) => theme.font.color.secondary};
font-size: ${({ theme }) => theme.font.size.lg};
font-weight: ${({ theme }) => theme.font.weight.medium};
color: ${themeCssVariables.font.color.secondary};
font-size: ${themeCssVariables.font.size.lg};
font-weight: ${themeCssVariables.font.weight.medium};
`;
const StyledHeader = styled.div`
@@ -99,7 +101,7 @@ const StyledHeader = styled.div`
`;
const StyledModalTitle = styled.span`
color: ${({ theme }) => theme.font.color.primary};
color: ${themeCssVariables.font.color.primary};
`;
const StyledModalHeader = styled(Modal.Header)`
@@ -112,14 +114,14 @@ const StyledModalContent = styled(Modal.Content)`
`;
const StyledModal = styled(Modal)`
gap: ${({ theme }) => theme.spacing(2)};
padding: ${({ theme }) => theme.spacing(3)};
gap: ${themeCssVariables.spacing[2]};
padding: ${themeCssVariables.spacing[3]};
`;
const StyledButtonContainer = styled.div`
display: flex;
flex-direction: row;
gap: ${({ theme }) => theme.spacing(1)};
gap: ${themeCssVariables.spacing[1]};
`;
export const PREVIEW_MODAL_ID = 'preview-modal';
@@ -12,14 +12,15 @@ import {
import { getFileCategoryFromExtension } from '@/object-record/record-field/ui/utils/getFileCategoryFromExtension';
import { SettingsTextInput } from '@/ui/input/components/SettingsTextInput';
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { useState } from 'react';
import { useContext, useState } from 'react';
import { styled } from '@linaria/react';
import { isDefined } from 'twenty-shared/utils';
import { FileIcon } from '@/file/components/FileIcon';
import { useHasPermissionFlag } from '@/settings/roles/hooks/useHasPermissionFlag';
import { IconCalendar, OverflowingTextWithTooltip } from 'twenty-ui/display';
import { ThemeContext } from 'twenty-ui/theme';
import { themeCssVariables } from 'twenty-ui/theme-constants';
import { isNavigationModifierPressed } from 'twenty-ui/utilities';
import {
FeatureFlagKey,
@@ -31,7 +32,7 @@ import { getFileNameAndExtension } from '~/utils/file/getFileNameAndExtension';
const StyledLeftContent = styled.div`
align-items: center;
display: flex;
gap: ${({ theme }) => theme.spacing(3)};
gap: ${themeCssVariables.spacing[3]};
width: 100%;
overflow: auto;
@@ -41,12 +42,12 @@ const StyledLeftContent = styled.div`
const StyledRightContent = styled.div`
align-items: center;
display: flex;
gap: ${({ theme }) => theme.spacing(0.5)};
gap: ${themeCssVariables.spacing['0.5']};
`;
const StyledCalendarIconContainer = styled.div`
align-items: center;
color: ${({ theme }) => theme.font.color.light};
color: ${themeCssVariables.font.color.light};
display: flex;
`;
@@ -55,7 +56,7 @@ const StyledLink = styled.a`
appearance: none;
background: none;
border: none;
color: ${({ theme }) => theme.font.color.primary};
color: ${themeCssVariables.font.color.primary};
cursor: pointer;
display: flex;
font-family: inherit;
@@ -66,7 +67,7 @@ const StyledLink = styled.a`
width: 100%;
:hover {
color: ${({ theme }) => theme.font.color.secondary};
color: ${themeCssVariables.font.color.secondary};
}
`;
@@ -84,7 +85,7 @@ export const AttachmentRow = ({
attachment,
onPreview,
}: AttachmentRowProps) => {
const theme = useTheme();
const { theme } = useContext(ThemeContext);
const [isEditing, setIsEditing] = useState(false);
const isFilesFieldMigrated = useIsFeatureEnabled(
@@ -7,13 +7,14 @@ import {
import { getFileType } from '@/activities/files/utils/getFileType';
import DocViewer, { DocViewerRenderers } from '@cyntler/react-doc-viewer';
import '@cyntler/react-doc-viewer/dist/index.css';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { Trans, useLingui } from '@lingui/react/macro';
import { useEffect, useState } from 'react';
import { useContext, useEffect, useState } from 'react';
import { isDefined } from 'twenty-shared/utils';
import { IconDownload } from 'twenty-ui/display';
import { Button } from 'twenty-ui/input';
import { ThemeContext } from 'twenty-ui/theme';
import { themeCssVariables } from 'twenty-ui/theme-constants';
import { getFileNameAndExtension } from '~/utils/file/getFileNameAndExtension';
const MS_OFFICE_EXTENSIONS = [
@@ -32,7 +33,7 @@ const StyledDocumentViewerContainer = styled.div`
height: calc(100vh - 200px);
min-height: 500px;
width: 100%;
background: ${({ theme }) => theme.background.secondary};
background: ${themeCssVariables.background.secondary};
#react-doc-viewer #header-bar {
display: none;
@@ -60,58 +61,58 @@ const StyledUnavailablePreviewContainer = styled.div`
align-items: center;
justify-content: center;
height: 100%;
gap: ${({ theme }) => theme.spacing(4)};
padding: ${({ theme }) => theme.spacing(8)};
gap: ${themeCssVariables.spacing[4]};
padding: ${themeCssVariables.spacing[8]};
text-align: center;
`;
const StyledMessage = styled.div`
color: ${({ theme }) => theme.font.color.secondary};
font-size: ${({ theme }) => theme.font.size.lg};
color: ${themeCssVariables.font.color.secondary};
font-size: ${themeCssVariables.font.size.lg};
max-width: 400px;
`;
const StyledLightMessage = styled.div`
color: ${({ theme }) => theme.font.color.tertiary};
font-size: ${({ theme }) => theme.font.size.sm};
color: ${themeCssVariables.font.color.tertiary};
font-size: ${themeCssVariables.font.size.sm};
`;
const StyledTitle = styled.div`
color: ${({ theme }) => theme.font.color.primary};
font-size: ${({ theme }) => theme.font.size.xl};
font-weight: ${({ theme }) => theme.font.weight.semiBold};
color: ${themeCssVariables.font.color.primary};
font-size: ${themeCssVariables.font.size.xl};
font-weight: ${themeCssVariables.font.weight.semiBold};
`;
const StyledCsvTable = styled.table`
border-collapse: collapse;
font-size: ${({ theme }) => theme.font.size.sm};
font-size: ${themeCssVariables.font.size.sm};
text-align: left;
width: 100%;
th {
border-bottom: 1px solid ${({ theme }) => theme.border.color.light};
color: ${({ theme }) => theme.font.color.tertiary};
font-weight: ${({ theme }) => theme.font.weight.medium};
height: ${({ theme }) => theme.spacing(8)};
padding: 0 ${({ theme }) => theme.spacing(2)};
border-bottom: 1px solid ${themeCssVariables.border.color.light};
color: ${themeCssVariables.font.color.tertiary};
font-weight: ${themeCssVariables.font.weight.medium};
height: ${themeCssVariables.spacing[8]};
padding: 0 ${themeCssVariables.spacing[2]};
}
td {
color: ${({ theme }) => theme.font.color.secondary};
height: ${({ theme }) => theme.spacing(8)};
color: ${themeCssVariables.font.color.secondary};
height: ${themeCssVariables.spacing[8]};
max-width: 200px;
overflow: hidden;
padding: 0 ${({ theme }) => theme.spacing(2)};
padding: 0 ${themeCssVariables.spacing[2]};
text-overflow: ellipsis;
white-space: nowrap;
}
tbody tr {
border-bottom: 1px solid ${({ theme }) => theme.border.color.light};
border-bottom: 1px solid ${themeCssVariables.border.color.light};
}
tbody tr:hover {
background-color: ${({ theme }) => theme.background.transparent.light};
background-color: ${themeCssVariables.background.transparent.light};
}
`;
@@ -200,7 +201,7 @@ export const DocumentViewer = ({
documentExtension,
}: DocumentViewerProps) => {
const { t } = useLingui();
const theme = useTheme();
const { theme } = useContext(ThemeContext);
const [csvPreview, setCsvPreview] = useState<CsvPreviewData | undefined>(
undefined,
);
@@ -1,42 +1,43 @@
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { useContext } from 'react';
import { styled } from '@linaria/react';
import { useLingui } from '@lingui/react/macro';
import { useDropzone } from 'react-dropzone';
import { useSpreadsheetImportInternal } from '@/spreadsheet-import/hooks/useSpreadsheetImportInternal';
import { IconUpload } from 'twenty-ui/display';
import { ThemeContext } from 'twenty-ui/theme';
import { themeCssVariables } from 'twenty-ui/theme-constants';
const StyledContainer = styled.div`
align-items: center;
background: ${({ theme }) => theme.background.secondary};
border: ${({ theme }) => `2px dashed ${theme.border.color.strong}`};
border-radius: ${({ theme }) => theme.border.radius.md};
background: ${themeCssVariables.background.secondary};
border: 2px dashed ${themeCssVariables.border.color.strong};
border-radius: ${themeCssVariables.border.radius.sm};
display: flex;
flex-direction: column;
height: 100%;
justify-content: center;
border-radius: ${({ theme }) => theme.border.radius.sm};
text-align: center;
`;
const StyledUploadDragTitle = styled.div`
color: ${({ theme }) => theme.font.color.primary};
font-size: ${({ theme }) => theme.font.size.lg};
font-weight: ${({ theme }) => theme.font.weight.medium};
line-height: ${({ theme }) => theme.text.lineHeight.md};
color: ${themeCssVariables.font.color.primary};
font-size: ${themeCssVariables.font.size.lg};
font-weight: ${themeCssVariables.font.weight.medium};
line-height: ${themeCssVariables.text.lineHeight.md};
margin-bottom: 8px;
`;
const StyledUploadDragSubTitle = styled.div`
color: ${({ theme }) => theme.font.color.tertiary};
font-size: ${({ theme }) => theme.font.size.md};
font-weight: ${({ theme }) => theme.font.weight.regular};
line-height: ${({ theme }) => theme.text.lineHeight.md};
color: ${themeCssVariables.font.color.tertiary};
font-size: ${themeCssVariables.font.size.md};
font-weight: ${themeCssVariables.font.weight.regular};
line-height: ${themeCssVariables.text.lineHeight.md};
`;
const StyledUploadIcon = styled(IconUpload)`
color: ${({ theme }) => theme.font.color.tertiary};
margin-bottom: ${({ theme }) => theme.spacing(3)};
color: ${themeCssVariables.font.color.tertiary};
margin-bottom: ${themeCssVariables.spacing[3]};
`;
type DropZoneProps = {
@@ -49,7 +50,7 @@ export const DropZone = ({
onUploadFiles,
}: DropZoneProps) => {
const { t } = useLingui();
const theme = useTheme();
const { theme } = useContext(ThemeContext);
const { maxFileSize } = useSpreadsheetImportInternal();
const { getRootProps, getInputProps, isDragActive } = useDropzone({
@@ -1,4 +1,4 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { type ChangeEvent, useRef, useState } from 'react';
import { SkeletonLoader } from '@/activities/components/SkeletonLoader';
@@ -1,7 +1,8 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { type ReactElement } from 'react';
import { type Note } from '@/activities/types/Note';
import { themeCssVariables } from 'twenty-ui/theme-constants';
import { NoteTile } from './NoteTile';
@@ -24,25 +25,25 @@ const StyledContainer = styled.div`
const StyledTitleBar = styled.h3`
display: flex;
justify-content: space-between;
margin-bottom: ${({ theme }) => theme.spacing(4)};
margin-top: ${({ theme }) => theme.spacing(4)};
margin-bottom: ${themeCssVariables.spacing[4]};
margin-top: ${themeCssVariables.spacing[4]};
place-items: center;
width: 100%;
`;
const StyledTitle = styled.span`
color: ${({ theme }) => theme.font.color.primary};
font-weight: ${({ theme }) => theme.font.weight.semiBold};
color: ${themeCssVariables.font.color.primary};
font-weight: ${themeCssVariables.font.weight.semiBold};
`;
const StyledCount = styled.span`
color: ${({ theme }) => theme.font.color.light};
margin-left: ${({ theme }) => theme.spacing(2)};
color: ${themeCssVariables.font.color.light};
margin-left: ${themeCssVariables.spacing[2]};
`;
const StyledNoteContainer = styled.div`
display: grid;
gap: ${({ theme }) => theme.spacing(4)};
gap: ${themeCssVariables.spacing[4]};
grid-auto-rows: 1fr;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
width: 100%;
@@ -1,4 +1,4 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { t } from '@lingui/core/macro';
import { ActivityTargetsInlineCell } from '@/activities/inline-cell/components/ActivityTargetsInlineCell';
@@ -9,12 +9,13 @@ import { useOpenRecordInCommandMenu } from '@/command-menu/hooks/useOpenRecordIn
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { RecordFieldsScopeContextProvider } from '@/object-record/record-field-list/contexts/RecordFieldsScopeContext';
import { FieldContextProvider } from '@/object-record/record-field/ui/components/FieldContextProvider';
import { themeCssVariables } from 'twenty-ui/theme-constants';
const StyledCard = styled.div<{ isSingleNote: boolean }>`
align-items: flex-start;
background: ${({ theme }) => theme.background.secondary};
border: 1px solid ${({ theme }) => theme.border.color.medium};
border-radius: ${({ theme }) => theme.border.radius.md};
background: ${themeCssVariables.background.secondary};
border: 1px solid ${themeCssVariables.border.color.medium};
border-radius: ${themeCssVariables.border.radius.md};
display: flex;
flex-direction: column;
height: 300px;
@@ -28,22 +29,22 @@ const StyledCardDetailsContainer = styled.div`
cursor: pointer;
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(2)};
gap: ${themeCssVariables.spacing[2]};
height: calc(100% - 45px);
justify-content: start;
padding: ${({ theme }) => theme.spacing(4)};
width: calc(100% - ${({ theme }) => theme.spacing(8)});
padding: ${themeCssVariables.spacing[4]};
width: calc(100% - ${themeCssVariables.spacing[8]});
box-sizing: border-box;
`;
const StyledNoteTitle = styled.div`
color: ${({ theme }) => theme.font.color.primary};
font-weight: ${({ theme }) => theme.font.weight.medium};
color: ${themeCssVariables.font.color.primary};
font-weight: ${themeCssVariables.font.weight.medium};
`;
const StyledCardContent = styled.div`
align-self: stretch;
color: ${({ theme }) => theme.font.color.secondary};
color: ${themeCssVariables.font.color.secondary};
line-break: anywhere;
overflow: hidden;
text-overflow: ellipsis;
@@ -54,14 +55,14 @@ const StyledCardContent = styled.div`
const StyledFooter = styled.div`
align-items: center;
align-self: stretch;
border-top: 1px solid ${({ theme }) => theme.border.color.light};
color: ${({ theme }) => theme.font.color.primary};
border-top: 1px solid ${themeCssVariables.border.color.light};
color: ${themeCssVariables.font.color.primary};
display: flex;
flex-direction: row;
gap: ${({ theme }) => theme.spacing(1)};
gap: ${themeCssVariables.spacing[1]};
justify-content: center;
padding: ${({ theme }) => theme.spacing(2)};
width: calc(100% - ${({ theme }) => theme.spacing(4)});
padding: ${themeCssVariables.spacing[2]};
width: calc(100% - ${themeCssVariables.spacing[4]});
`;
export const NoteTile = ({
@@ -7,7 +7,7 @@ import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadata
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useObjectPermissionsForObject } from '@/object-record/hooks/useObjectPermissionsForObject';
import { useTargetRecord } from '@/ui/layout/contexts/useTargetRecord';
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { t } from '@lingui/core/macro';
import { IconPlus } from 'twenty-ui/display';
import { Button } from 'twenty-ui/input';
@@ -1,4 +1,4 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { SkeletonLoader } from '@/activities/components/SkeletonLoader';
import { useOpenCreateActivityDrawer } from '@/activities/hooks/useOpenCreateActivityDrawer';
@@ -1,8 +1,9 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { type ReactElement } from 'react';
import { ActivityList } from '@/activities/components/ActivityList';
import { type Task } from '@/activities/types/Task';
import { themeCssVariables } from 'twenty-ui/theme-constants';
import { TaskRow } from './TaskRow';
type TaskListProps = {
@@ -18,28 +19,28 @@ const StyledContainer = styled.div`
display: flex;
flex-direction: column;
justify-content: center;
padding: 8px ${({ theme }) => theme.spacing(6)};
padding: 8px ${themeCssVariables.spacing[6]};
width: calc(100% - ${({ theme }) => theme.spacing(12)});
width: calc(100% - ${themeCssVariables.spacing[12]});
`;
const StyledTitleBar = styled.div`
display: flex;
justify-content: space-between;
margin-bottom: ${({ theme }) => theme.spacing(4)};
margin-top: ${({ theme }) => theme.spacing(4)};
margin-bottom: ${themeCssVariables.spacing[4]};
margin-top: ${themeCssVariables.spacing[4]};
place-items: center;
width: 100%;
`;
const StyledTitle = styled.span`
color: ${({ theme }) => theme.font.color.primary};
font-weight: ${({ theme }) => theme.font.weight.semiBold};
color: ${themeCssVariables.font.color.primary};
font-weight: ${themeCssVariables.font.weight.semiBold};
`;
const StyledCount = styled.span`
color: ${({ theme }) => theme.font.color.light};
margin-left: ${({ theme }) => theme.spacing(2)};
color: ${themeCssVariables.font.color.light};
margin-left: ${themeCssVariables.spacing[2]};
`;
export const TaskList = ({ title, tasks, button }: TaskListProps) => (
@@ -1,5 +1,5 @@
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { useContext } from 'react';
import { styled } from '@linaria/react';
import { t } from '@lingui/core/macro';
import { ActivityTargetsInlineCell } from '@/activities/inline-cell/components/ActivityTargetsInlineCell';
@@ -16,12 +16,14 @@ import { RecordFieldsScopeContextProvider } from '@/object-record/record-field-l
import { FieldContextProvider } from '@/object-record/record-field/ui/components/FieldContextProvider';
import { IconCalendar, OverflowingTextWithTooltip } from 'twenty-ui/display';
import { Checkbox, CheckboxShape } from 'twenty-ui/input';
import { ThemeContext } from 'twenty-ui/theme';
import { themeCssVariables } from 'twenty-ui/theme-constants';
import { useCompleteTask } from '@/activities/tasks/hooks/useCompleteTask';
const StyledTaskBody = styled.div`
color: ${({ theme }) => theme.font.color.tertiary};
color: ${themeCssVariables.font.color.tertiary};
display: flex;
max-width: calc(80% - ${({ theme }) => theme.spacing(2)});
max-width: calc(80% - ${themeCssVariables.spacing[2]});
text-overflow: ellipsis;
overflow: hidden;
padding-bottom: 1px;
@@ -30,9 +32,9 @@ const StyledTaskBody = styled.div`
const StyledTaskTitle = styled.div<{
completed: boolean;
}>`
color: ${({ theme }) => theme.font.color.primary};
font-weight: ${({ theme }) => theme.font.weight.medium};
padding: 0 ${({ theme }) => theme.spacing(2)};
color: ${themeCssVariables.font.color.primary};
font-weight: ${themeCssVariables.font.weight.medium};
padding: 0 ${themeCssVariables.spacing[2]};
padding-bottom: 1px;
text-decoration: ${({ completed }) => (completed ? 'line-through' : 'none')};
white-space: nowrap;
@@ -46,11 +48,13 @@ const StyledDueDate = styled.div<{
isPast: boolean;
}>`
align-items: center;
color: ${({ theme, isPast }) =>
isPast ? theme.font.color.danger : theme.font.color.secondary};
color: ${({ isPast }) =>
isPast
? themeCssVariables.font.color.danger
: themeCssVariables.font.color.secondary};
display: flex;
gap: ${({ theme }) => theme.spacing(1)};
padding-left: ${({ theme }) => theme.spacing(1)};
gap: ${themeCssVariables.spacing[1]};
padding-left: ${themeCssVariables.spacing[1]};
white-space: nowrap;
`;
@@ -66,7 +70,7 @@ const StyledActivityTargetsContainer = styled.div`
`;
const StyledPlaceholder = styled.div`
color: ${({ theme }) => theme.font.color.light};
color: ${themeCssVariables.font.color.light};
`;
const StyledLeftSideContainer = styled.div`
@@ -82,7 +86,7 @@ const StyledCheckboxContainer = styled.div`
`;
export const TaskRow = ({ task }: { task: Task }) => {
const theme = useTheme();
const { theme } = useContext(ThemeContext);
const { openRecordInCommandMenu } = useOpenRecordInCommandMenu();
const body = getActivitySummary(task?.bodyV2?.blocknote ?? null);
@@ -1,4 +1,4 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { TaskGroups } from '@/activities/tasks/components/TaskGroups';
import { ObjectFilterDropdownComponentInstanceContext } from '@/object-record/object-filter-dropdown/states/contexts/ObjectFilterDropdownComponentInstanceContext';
@@ -1,4 +1,4 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { type ReactElement } from 'react';
import { EventsGroup } from '@/activities/timeline-activities/components/EventsGroup';
@@ -9,6 +9,7 @@ import { type ActivityTargetableObject } from '@/activities/types/ActivityTarget
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper';
import { themeCssVariables } from 'twenty-ui/theme-constants';
type EventListProps = {
targetableObject: ActivityTargetableObject;
@@ -24,7 +25,7 @@ const StyledTimelineContainer = styled.div`
display: flex;
flex: 1 0 0;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(1)};
gap: ${themeCssVariables.spacing[1]};
justify-content: flex-start;
`;
@@ -1,4 +1,4 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
import { useContext } from 'react';
@@ -14,15 +14,16 @@ import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataI
import { getObjectRecordIdentifier } from '@/object-metadata/utils/getObjectRecordIdentifier';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
import { useAtomFamilyStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomFamilyStateValue';
import { themeCssVariables } from 'twenty-ui/theme-constants';
import { dateLocaleState } from '~/localization/states/dateLocaleState';
import { beautifyPastDateRelativeToNow } from '~/utils/date-utils';
import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
import { allowRequestsToTwentyIconsState } from '@/client-config/states/allowRequestsToTwentyIcons';
const StyledTimelineItemContainer = styled.div`
color: ${({ theme }) => theme.font.color.primary};
color: ${themeCssVariables.font.color.primary};
display: flex;
gap: ${({ theme }) => theme.spacing(4)};
gap: ${themeCssVariables.spacing[4]};
height: 'auto';
justify-content: space-between;
overflow: hidden;
@@ -38,7 +39,7 @@ const StyledIconContainer = styled.div`
display: flex;
align-items: center;
justify-content: center;
color: ${({ theme }) => theme.font.color.tertiary};
color: ${themeCssVariables.font.color.tertiary};
height: 16px;
width: 16px;
margin: 5px;
@@ -56,7 +57,7 @@ const StyledVerticalLineContainer = styled.div`
`;
const StyledVerticalLine = styled.div`
background: ${({ theme }) => theme.border.color.light};
background: ${themeCssVariables.border.color.light};
width: 2px;
height: 100%;
`;
@@ -66,7 +67,7 @@ const StyledSummary = styled.summary`
display: flex;
flex: 1;
flex-direction: row;
gap: ${({ theme }) => theme.spacing(1)};
gap: ${themeCssVariables.spacing[1]};
width: 100%;
`;
@@ -75,10 +76,10 @@ const StyledItemContainer = styled.div<{ isMarginBottom?: boolean }>`
display: flex;
flex: 1;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(1)};
gap: ${themeCssVariables.spacing[1]};
overflow: hidden;
margin-bottom: ${({ isMarginBottom, theme }) =>
isMarginBottom ? theme.spacing(3) : 0};
margin-bottom: ${({ isMarginBottom }) =>
isMarginBottom ? themeCssVariables.spacing[3] : '0'};
min-height: 26px;
`;
@@ -1,8 +1,9 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { EventRow } from '@/activities/timeline-activities/components/EventRow';
import { type EventGroup } from '@/activities/timeline-activities/utils/groupEventsByMonth';
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { themeCssVariables } from 'twenty-ui/theme-constants';
type EventsGroupProps = {
group: EventGroup;
@@ -14,22 +15,22 @@ type EventsGroupProps = {
const StyledActivityGroup = styled.div`
display: flex;
flex-flow: column;
gap: ${({ theme }) => theme.spacing(4)};
margin-bottom: ${({ theme }) => theme.spacing(4)};
gap: ${themeCssVariables.spacing[4]};
margin-bottom: ${themeCssVariables.spacing[4]};
width: 100%;
`;
const StyledActivityGroupContainer = styled.div`
margin-bottom: ${({ theme }) => theme.spacing(3)};
margin-top: ${({ theme }) => theme.spacing(3)};
margin-bottom: ${themeCssVariables.spacing[3]};
margin-top: ${themeCssVariables.spacing[3]};
position: relative;
`;
const StyledActivityGroupBar = styled.div`
align-items: center;
background: ${({ theme }) => theme.background.secondary};
border: 1px solid ${({ theme }) => theme.border.color.light};
border-radius: ${({ theme }) => theme.border.radius.md};
background: ${themeCssVariables.background.secondary};
border: 1px solid ${themeCssVariables.border.color.light};
border-radius: ${themeCssVariables.border.radius.md};
display: flex;
flex-direction: column;
height: 100%;
@@ -42,14 +43,14 @@ const StyledActivityGroupBar = styled.div`
const StyledMonthSeperator = styled.div`
align-items: center;
align-self: stretch;
color: ${({ theme }) => theme.font.color.light};
color: ${themeCssVariables.font.color.light};
display: flex;
gap: ${({ theme }) => theme.spacing(4)};
font-weight: ${({ theme }) => theme.font.weight.semiBold};
font-size: ${({ theme }) => theme.font.size.xs};
gap: ${themeCssVariables.spacing[4]};
font-weight: ${themeCssVariables.font.weight.semiBold};
font-size: ${themeCssVariables.font.size.xs};
`;
const StyledMonthSeperatorLine = styled.div`
background: ${({ theme }) => theme.border.color.light};
background: ${themeCssVariables.border.color.light};
border-radius: 50px;
flex: 1 0 0;
height: 1px;
@@ -1,4 +1,4 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { CustomResolverFetchMoreLoader } from '@/activities/components/CustomResolverFetchMoreLoader';
import { SkeletonLoader } from '@/activities/components/SkeletonLoader';
@@ -6,7 +6,6 @@ import { EventList } from '@/activities/timeline-activities/components/EventList
import { useTimelineActivities } from '@/activities/timeline-activities/hooks/useTimelineActivities';
import { useLayoutRenderingContext } from '@/ui/layout/contexts/LayoutRenderingContext';
import { useTargetRecord } from '@/ui/layout/contexts/useTargetRecord';
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
import { t } from '@lingui/core/macro';
import {
AnimatedPlaceholder,
@@ -17,25 +16,26 @@ import {
EMPTY_PLACEHOLDER_TRANSITION_PROPS,
} from 'twenty-ui/layout';
import { MOBILE_VIEWPORT } from 'twenty-ui/theme';
import { themeCssVariables } from 'twenty-ui/theme-constants';
const StyledMainContainer = styled.div`
align-items: flex-start;
align-self: stretch;
border-top: ${({ theme }) =>
useIsMobile() ? `1px solid ${theme.border.color.medium}` : 'none'};
border-top: none;
display: flex;
flex-direction: column;
overflow: auto;
justify-content: center;
padding-top: ${({ theme }) => theme.spacing(6)};
padding-right: ${({ theme }) => theme.spacing(6)};
padding-left: ${({ theme }) => theme.spacing(6)};
gap: ${({ theme }) => theme.spacing(4)};
padding-top: ${themeCssVariables.spacing[6]};
padding-right: ${themeCssVariables.spacing[6]};
padding-left: ${themeCssVariables.spacing[6]};
gap: ${themeCssVariables.spacing[4]};
@media (max-width: ${MOBILE_VIEWPORT}px) {
padding-right: ${({ theme }) => theme.spacing(1)};
padding-left: ${({ theme }) => theme.spacing(1)};
border-top: 1px solid ${themeCssVariables.border.color.medium};
padding-right: ${themeCssVariables.spacing[1]};
padding-left: ${themeCssVariables.spacing[1]};
}
`;
@@ -43,7 +43,7 @@ const StyledRightDrawerAnimatedPlaceholderEmptyContainer = styled(
AnimatedPlaceholderEmptyContainer,
)`
height: auto;
padding-top: ${({ theme }) => theme.spacing(8)};
padding-top: ${themeCssVariables.spacing[8]};
`;
export const TimelineCard = () => {
@@ -1,4 +1,4 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { t } from '@lingui/core/macro';
import {
@@ -13,11 +13,12 @@ import { useGetRecordFromCache } from '@/object-record/cache/hooks/useGetRecordF
import { isNonEmptyString } from '@sniptt/guards';
import { OverflowingTextWithTooltip } from 'twenty-ui/display';
import { MOBILE_VIEWPORT } from 'twenty-ui/theme';
import { themeCssVariables } from 'twenty-ui/theme-constants';
type EventRowActivityProps = EventRowDynamicComponentProps;
const StyledLinkedActivity = styled.span`
color: ${({ theme }) => theme.font.color.primary};
color: ${themeCssVariables.font.color.primary};
cursor: pointer;
text-decoration: underline;
width: 100%;
@@ -29,21 +30,21 @@ const StyledLinkedActivity = styled.span`
const StyledRowContainer = styled.div`
align-items: center;
display: flex;
gap: ${({ theme }) => theme.spacing(1)};
gap: ${themeCssVariables.spacing[1]};
justify-content: space-between;
`;
const StyledEventRow = styled.div`
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(1)};
gap: ${themeCssVariables.spacing[1]};
width: 100%;
`;
const StyledRow = styled.div`
align-items: center;
display: flex;
gap: ${({ theme }) => theme.spacing(1)};
gap: ${themeCssVariables.spacing[1]};
overflow: hidden;
`;
@@ -51,12 +52,12 @@ const StyledItemTitleDate = styled.div`
@media (max-width: ${MOBILE_VIEWPORT}px) {
display: none;
}
color: ${({ theme }) => theme.font.color.tertiary};
padding: 0 ${({ theme }) => theme.spacing(1)};
color: ${themeCssVariables.font.color.tertiary};
padding: 0 ${themeCssVariables.spacing[1]};
`;
export const StyledEventRowItemText = styled.span`
color: ${({ theme }) => theme.font.color.primary};
color: ${themeCssVariables.font.color.primary};
`;
export const EventRowActivity = ({
@@ -1,4 +1,4 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { t } from '@lingui/core/macro';
import { isUndefined } from '@sniptt/guards';
@@ -13,6 +13,7 @@ import { UserContext } from '@/users/contexts/UserContext';
import { useContext } from 'react';
import { FIELD_RESTRICTED_ADDITIONAL_PERMISSIONS_REQUIRED } from 'twenty-shared/constants';
import { isDefined } from 'twenty-shared/utils';
import { themeCssVariables } from 'twenty-ui/theme-constants';
import {
formatToHumanReadableDay,
formatToHumanReadableMonth,
@@ -26,14 +27,14 @@ const StyledEventCardCalendarEventContainer = styled.div<{
cursor: ${({ canOpen }) => (canOpen ? 'pointer' : 'not-allowed')};
display: flex;
flex-direction: row;
gap: ${({ theme }) => theme.spacing(2)};
gap: ${themeCssVariables.spacing[2]};
width: 100%;
`;
const StyledCalendarEventContent = styled.div`
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(2)};
gap: ${themeCssVariables.spacing[2]};
justify-content: center;
overflow: hidden;
width: 100%;
@@ -43,13 +44,13 @@ const StyledCalendarEventTop = styled.div`
align-items: center;
display: flex;
width: 100%;
gap: ${({ theme }) => theme.spacing(2)};
gap: ${themeCssVariables.spacing[2]};
justify-content: space-between;
`;
const StyledCalendarEventTitle = styled.div`
color: ${({ theme }) => theme.font.color.primary};
font-weight: ${({ theme }) => theme.font.weight.medium};
color: ${themeCssVariables.font.color.primary};
font-weight: ${themeCssVariables.font.weight.medium};
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
@@ -57,37 +58,37 @@ const StyledCalendarEventTitle = styled.div`
const StyledCalendarEventBody = styled.div`
align-items: flex-start;
color: ${({ theme }) => theme.font.color.tertiary};
color: ${themeCssVariables.font.color.tertiary};
display: flex;
flex: 1 0 0;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(2)};
gap: ${themeCssVariables.spacing[2]};
justify-content: center;
`;
const StyledCalendarEventDateCard = styled.div`
display: flex;
padding: ${({ theme }) => theme.spacing(1)};
padding: ${themeCssVariables.spacing[1]};
flex-direction: column;
justify-content: center;
align-items: center;
gap: ${({ theme }) => theme.spacing(1)};
gap: ${themeCssVariables.spacing[1]};
border-radius: ${({ theme }) => theme.spacing(1)};
border: 1px solid ${({ theme }) => theme.border.color.medium};
border-radius: ${themeCssVariables.spacing[1]};
border: 1px solid ${themeCssVariables.border.color.medium};
`;
const StyledCalendarEventDateCardMonth = styled.div`
color: ${({ theme }) => theme.font.color.danger};
font-size: ${({ theme }) => theme.font.size.xxs};
font-weight: ${({ theme }) => theme.font.weight.semiBold};
color: ${themeCssVariables.font.color.danger};
font-size: ${themeCssVariables.font.size.xxs};
font-weight: ${themeCssVariables.font.weight.semiBold};
`;
const StyledCalendarEventDateCardDay = styled.div`
color: ${({ theme }) => theme.font.color.primary};
font-size: ${({ theme }) => theme.font.size.md};
font-weight: ${({ theme }) => theme.font.weight.medium};
color: ${themeCssVariables.font.color.primary};
font-size: ${themeCssVariables.font.size.md};
font-weight: ${themeCssVariables.font.weight.medium};
`;
export const EventCardCalendarEvent = ({
@@ -1,4 +1,4 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { useLingui } from '@lingui/react/macro';
import { useState } from 'react';
@@ -11,19 +11,20 @@ import {
StyledEventRowItemColumn,
} from '@/activities/timeline-activities/rows/components/EventRowDynamicComponent';
import { isTimelineActivityWithLinkedRecord } from '@/activities/timeline-activities/types/TimelineActivity';
import { themeCssVariables } from 'twenty-ui/theme-constants';
type EventRowCalendarEventProps = EventRowDynamicComponentProps;
const StyledEventRowCalendarEventContainer = styled.div`
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(1)};
gap: ${themeCssVariables.spacing[1]};
`;
const StyledRowContainer = styled.div`
display: flex;
flex-direction: row;
gap: ${({ theme }) => theme.spacing(1)};
gap: ${themeCssVariables.spacing[1]};
`;
export const EventRowCalendarEvent = ({
@@ -1,6 +1,7 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { Card } from 'twenty-ui/layout';
import { MOBILE_VIEWPORT } from 'twenty-ui/theme';
import { themeCssVariables } from 'twenty-ui/theme-constants';
type EventCardProps = {
children: React.ReactNode;
@@ -12,10 +13,10 @@ const StyledCardContainer = styled.div`
display: flex;
flex-direction: column;
flex-grow: 1;
gap: ${({ theme }) => theme.spacing(2)};
gap: ${themeCssVariables.spacing[2]};
width: 400px;
padding: ${({ theme }) => theme.spacing(2)} 0px
${({ theme }) => theme.spacing(1)} 0px;
padding: ${themeCssVariables.spacing[2]} 0px ${themeCssVariables.spacing[1]}
0px;
@media (max-width: ${MOBILE_VIEWPORT}px) {
width: 300px;
@@ -23,15 +24,15 @@ const StyledCardContainer = styled.div`
`;
const StyledCard = styled(Card)`
background: ${({ theme }) => theme.background.secondary};
border: 1px solid ${({ theme }) => theme.border.color.medium};
border-radius: ${({ theme }) => theme.border.radius.md};
background: ${themeCssVariables.background.secondary};
border: 1px solid ${themeCssVariables.border.color.medium};
border-radius: ${themeCssVariables.border.radius.md};
box-sizing: border-box;
display: flex;
padding: ${({ theme }) => theme.spacing(2)};
padding: ${themeCssVariables.spacing[2]};
flex-direction: column;
align-items: flex-start;
gap: ${({ theme }) => theme.spacing(2)};
gap: ${themeCssVariables.spacing[2]};
justify-content: center;
align-self: stretch;
`;
@@ -1,6 +1,7 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { IconButton } from 'twenty-ui/input';
import { IconChevronDown, IconChevronUp } from 'twenty-ui/display';
import { themeCssVariables } from 'twenty-ui/theme-constants';
type EventCardToggleButtonProps = {
isOpen: boolean;
@@ -8,7 +9,7 @@ type EventCardToggleButtonProps = {
};
const StyledButtonContainer = styled.div`
border-radius: ${({ theme }) => theme.border.radius.sm};
border-radius: ${themeCssVariables.border.radius.sm};
`;
export const EventCardToggleButton = ({
@@ -1,4 +1,4 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { EventRowActivity } from '@/activities/timeline-activities/rows/activity/components/EventRowActivity';
import { EventRowCalendarEvent } from '@/activities/timeline-activities/rows/calendar/components/EventRowCalendarEvent';
@@ -7,6 +7,7 @@ import { EventRowMessage } from '@/activities/timeline-activities/rows/message/c
import { type TimelineActivity } from '@/activities/timeline-activities/types/TimelineActivity';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { themeCssVariables } from 'twenty-ui/theme-constants';
export interface EventRowDynamicComponentProps {
labelIdentifierValue: string;
@@ -19,14 +20,14 @@ export interface EventRowDynamicComponentProps {
export const StyledEventRowItemColumn = styled.div`
align-items: center;
color: ${({ theme }) => theme.font.color.primary};
color: ${themeCssVariables.font.color.primary};
display: flex;
flex-direction: row;
gap: ${({ theme }) => theme.spacing(1)};
gap: ${themeCssVariables.spacing[1]};
`;
export const StyledEventRowItemAction = styled(StyledEventRowItemColumn)`
color: ${({ theme }) => theme.font.color.secondary};
color: ${themeCssVariables.font.color.secondary};
`;
export const EventRowDynamicComponent = ({
@@ -1,4 +1,4 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { EventFieldDiffLabel } from '@/activities/timeline-activities/rows/main-object/components/EventFieldDiffLabel';
import { EventFieldDiffValue } from '@/activities/timeline-activities/rows/main-object/components/EventFieldDiffValue';
@@ -6,6 +6,7 @@ import { EventFieldDiffValueEffect } from '@/activities/timeline-activities/rows
import { type FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { Trans } from '@lingui/react/macro';
import { themeCssVariables } from 'twenty-ui/theme-constants';
type EventFieldDiffProps = {
diffRecord: Record<string, any>;
@@ -18,7 +19,7 @@ const StyledEventFieldDiffContainer = styled.div`
align-items: center;
display: flex;
flex-direction: row;
gap: ${({ theme }) => theme.spacing(1)};
gap: ${themeCssVariables.spacing[1]};
height: 24px;
max-width: 100%;
overflow: hidden;
@@ -27,7 +28,7 @@ const StyledEventFieldDiffContainer = styled.div`
`;
const StyledEmptyValue = styled.div`
color: ${({ theme }) => theme.font.color.tertiary};
color: ${themeCssVariables.font.color.tertiary};
`;
export const EventFieldDiff = ({
@@ -1,7 +1,8 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { type FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
import { Icon123, useIcons } from 'twenty-ui/display';
import { themeCssVariables } from 'twenty-ui/theme-constants';
type EventFieldDiffLabelProps = {
fieldMetadataItem: FieldMetadataItem;
@@ -10,8 +11,8 @@ type EventFieldDiffLabelProps = {
const StyledUpdatedFieldContainer = styled.div`
align-items: center;
display: flex;
gap: ${({ theme }) => theme.spacing(1)};
color: ${({ theme }) => theme.font.color.tertiary};
gap: ${themeCssVariables.spacing[1]};
color: ${themeCssVariables.font.color.tertiary};
`;
const StyledUpdatedFieldIconContainer = styled.div`
@@ -1,10 +1,11 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { type FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { FieldDisplay } from '@/object-record/record-field/ui/components/FieldDisplay';
import { FieldContext } from '@/object-record/record-field/ui/contexts/FieldContext';
import { RecordFieldComponentInstanceContext } from '@/object-record/record-field/ui/states/contexts/RecordFieldComponentInstanceContext';
import { themeCssVariables } from 'twenty-ui/theme-constants';
type EventFieldDiffValueProps = {
diffArtificialRecordStoreId: string;
@@ -18,7 +19,7 @@ const StyledEventFieldDiffValue = styled.div`
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
color: ${({ theme }) => theme.font.color.primary};
color: ${themeCssVariables.font.color.primary};
`;
export const EventFieldDiffValue = ({
@@ -4,23 +4,24 @@ import {
StyledEventRowItemColumn,
} from '@/activities/timeline-activities/rows/components/EventRowDynamicComponent';
import { EventRowMainObjectUpdated } from '@/activities/timeline-activities/rows/main-object/components/EventRowMainObjectUpdated';
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { t } from '@lingui/core/macro';
import { MOBILE_VIEWPORT } from 'twenty-ui/theme';
import { themeCssVariables } from 'twenty-ui/theme-constants';
type EventRowMainObjectProps = EventRowDynamicComponentProps;
const StyledMainContainer = styled.div`
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(1)};
gap: ${themeCssVariables.spacing[1]};
width: 100%;
`;
const StyledRowContainer = styled.div`
align-items: center;
display: flex;
gap: ${({ theme }) => theme.spacing(1)};
gap: ${themeCssVariables.spacing[1]};
justify-content: space-between;
`;
@@ -28,14 +29,14 @@ const StyledItemTitleDate = styled.div`
@media (max-width: ${MOBILE_VIEWPORT}px) {
display: none;
}
color: ${({ theme }) => theme.font.color.tertiary};
padding: 0 ${({ theme }) => theme.spacing(1)};
color: ${themeCssVariables.font.color.tertiary};
padding: 0 ${themeCssVariables.spacing[1]};
`;
const StyledRow = styled.div`
align-items: center;
display: flex;
gap: ${({ theme }) => theme.spacing(1)};
gap: ${themeCssVariables.spacing[1]};
overflow: hidden;
`;
@@ -1,4 +1,4 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { useLingui } from '@lingui/react/macro';
import { useState } from 'react';
@@ -10,6 +10,7 @@ import { type TimelineActivity } from '@/activities/timeline-activities/types/Ti
import { type FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { MOBILE_VIEWPORT } from 'twenty-ui/theme';
import { themeCssVariables } from 'twenty-ui/theme-constants';
type EventRowMainObjectUpdatedProps = {
mainObjectMetadataItem: ObjectMetadataItem;
@@ -22,7 +23,7 @@ type EventRowMainObjectUpdatedProps = {
const StyledRowContainer = styled.div`
align-items: center;
display: flex;
gap: ${({ theme }) => theme.spacing(1)};
gap: ${themeCssVariables.spacing[1]};
justify-content: space-between;
`;
@@ -30,21 +31,21 @@ const StyledItemTitleDate = styled.div`
@media (max-width: ${MOBILE_VIEWPORT}px) {
display: none;
}
color: ${({ theme }) => theme.font.color.tertiary};
padding: 0 ${({ theme }) => theme.spacing(1)};
color: ${themeCssVariables.font.color.tertiary};
padding: 0 ${themeCssVariables.spacing[1]};
`;
const StyledRow = styled.div`
align-items: center;
display: flex;
gap: ${({ theme }) => theme.spacing(1)};
gap: ${themeCssVariables.spacing[1]};
overflow: hidden;
`;
const StyledEventRowMainObjectUpdatedContainer = styled.div`
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(1)};
gap: ${themeCssVariables.spacing[1]};
width: 100%;
`;
@@ -1,4 +1,4 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { type EmailThreadMessage } from '@/activities/emails/types/EmailThreadMessage';
import { EventCardMessageBodyNotShared } from '@/activities/timeline-activities/rows/message/components/EventCardMessageBodyNotShared';
@@ -11,6 +11,7 @@ import { Trans, useLingui } from '@lingui/react/macro';
import { FIELD_RESTRICTED_ADDITIONAL_PERMISSIONS_REQUIRED } from 'twenty-shared/constants';
import { isDefined } from 'twenty-shared/utils';
import { OverflowingTextWithTooltip } from 'twenty-ui/display';
import { themeCssVariables } from 'twenty-ui/theme-constants';
const StyledEventCardMessageContainer = styled.div<{ canOpen?: boolean }>`
cursor: ${({ canOpen }) => (canOpen ? 'pointer' : 'not-allowed')};
@@ -22,27 +23,27 @@ const StyledEventCardMessageContainer = styled.div<{ canOpen?: boolean }>`
const StyledEmailContent = styled.div`
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(4)};
gap: ${themeCssVariables.spacing[4]};
justify-content: center;
`;
const StyledEmailTop = styled.div`
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(2)};
gap: ${themeCssVariables.spacing[2]};
`;
const StyledEmailTitle = styled.div`
color: ${({ theme }) => theme.font.color.primary};
font-weight: ${({ theme }) => theme.font.weight.medium};
color: ${themeCssVariables.font.color.primary};
font-weight: ${themeCssVariables.font.weight.medium};
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
`;
const StyledEmailParticipants = styled.div`
color: ${({ theme }) => theme.font.color.tertiary};
font-size: ${({ theme }) => theme.font.size.sm};
color: ${themeCssVariables.font.color.tertiary};
font-size: ${themeCssVariables.font.size.sm};
`;
const StyledEmailBody = styled.div`
@@ -1,29 +1,30 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { Trans } from '@lingui/react/macro';
import { IconLock } from 'twenty-ui/display';
import { themeCssVariables } from 'twenty-ui/theme-constants';
const StyledEmailBodyNotSharedContainer = styled.div`
align-items: center;
background: ${({ theme }) => theme.background.transparent.lighter};
border: 1px solid ${({ theme }) => theme.border.color.light};
border-radius: ${({ theme }) => theme.spacing(1)};
background: ${themeCssVariables.background.transparent.lighter};
border: 1px solid ${themeCssVariables.border.color.light};
border-radius: ${themeCssVariables.spacing[1]};
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(3)};
gap: ${themeCssVariables.spacing[3]};
height: 80px;
justify-content: center;
color: ${({ theme }) => theme.font.color.light};
font-size: ${({ theme }) => theme.font.size.sm};
font-weight: ${({ theme }) => theme.font.weight.medium};
color: ${themeCssVariables.font.color.light};
font-size: ${themeCssVariables.font.size.sm};
font-weight: ${themeCssVariables.font.weight.medium};
width: 100%;
`;
const StyledEmailBodyNotSharedIconContainer = styled.div`
display: flex;
width: ${({ theme }) => theme.icon.size.sm}px;
height: ${({ theme }) => theme.icon.size.sm}px;
width: calc(${themeCssVariables.icon.size.sm} * 1px);
height: calc(${themeCssVariables.icon.size.sm} * 1px);
justify-content: center;
align-items: center;
`;
@@ -31,7 +32,7 @@ const StyledEmailBodyNotSharedIconContainer = styled.div`
const StyledEmailBodyNotShared = styled.div`
align-items: center;
display: flex;
gap: ${({ theme }) => theme.spacing(1)};
gap: ${themeCssVariables.spacing[1]};
`;
export const EventCardMessageBodyNotShared = ({
@@ -1,6 +1,8 @@
import { EventCardMessageBodyNotShared } from '@/activities/timeline-activities/rows/message/components/EventCardMessageBodyNotShared';
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { Trans } from '@lingui/react/macro';
import { themeCssVariables } from 'twenty-ui/theme-constants';
const StyledEventCardMessageContainer = styled.div`
display: flex;
flex-direction: column;
@@ -10,17 +12,17 @@ const StyledEventCardMessageContainer = styled.div`
const StyledEmailContent = styled.div`
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(4)};
gap: ${themeCssVariables.spacing[4]};
justify-content: center;
width: 100%;
`;
const StyledEmailTitle = styled.div`
color: ${({ theme }) => theme.font.color.primary};
font-weight: ${({ theme }) => theme.font.weight.medium};
color: ${themeCssVariables.font.color.primary};
font-weight: ${themeCssVariables.font.weight.medium};
display: flex;
flex-direction: column;
margin-top: ${({ theme }) => theme.spacing(2)};
margin-top: ${themeCssVariables.spacing[2]};
`;
export const EventCardMessageForbidden = ({
@@ -1,4 +1,4 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { t } from '@lingui/core/macro';
import { useState } from 'react';
@@ -11,19 +11,20 @@ import {
} from '@/activities/timeline-activities/rows/components/EventRowDynamicComponent';
import { EventCardMessage } from '@/activities/timeline-activities/rows/message/components/EventCardMessage';
import { isTimelineActivityWithLinkedRecord } from '@/activities/timeline-activities/types/TimelineActivity';
import { themeCssVariables } from 'twenty-ui/theme-constants';
type EventRowMessageProps = EventRowDynamicComponentProps;
const StyledEventRowMessageContainer = styled.div`
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(1)};
gap: ${themeCssVariables.spacing[1]};
`;
const StyledRowContainer = styled.div`
display: flex;
flex-direction: row;
gap: ${({ theme }) => theme.spacing(1)};
gap: ${themeCssVariables.spacing[1]};
`;
export const EventRowMessage = ({
@@ -6,33 +6,35 @@ import { IconDotsVertical } from 'twenty-ui/display';
import { LazyMarkdownRenderer } from '@/ai/components/LazyMarkdownRenderer';
import { ToolStepRenderer } from '@/ai/components/ToolStepRenderer';
import { groupContiguousThinkingStepParts } from '@/ai/utils/groupContiguousThinkingStepParts';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { useContext } from 'react';
import { isToolUIPart, type ToolUIPart } from 'ai';
import { type ExtendedUIMessagePart } from 'twenty-shared/ai';
import { ThemeContext } from 'twenty-ui/theme';
import { themeCssVariables } from 'twenty-ui/theme-constants';
const StyledMessagePartsContainer = styled.div`
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(1)};
gap: ${themeCssVariables.spacing[1]};
`;
const StyledLoadingIconContainer = styled.div`
align-items: center;
border: ${({ theme }) => `1px solid ${theme.border.color.light}`};
border-radius: ${({ theme }) => theme.border.radius.md};
border: 1px solid ${themeCssVariables.border.color.light};
border-radius: ${themeCssVariables.border.radius.md};
display: flex;
justify-content: center;
padding-inline: ${({ theme }) => theme.spacing(1)};
padding-inline: ${themeCssVariables.spacing[1]};
`;
const StyledLoadingIcon = styled(IconDotsVertical)`
color: ${({ theme }) => theme.font.color.light};
color: ${themeCssVariables.font.color.light};
transform: rotate(90deg);
`;
const InitialLoadingIndicator = () => {
const theme = useTheme();
const { theme } = useContext(ThemeContext);
return (
<StyledLoadingIconContainer>
@@ -1,4 +1,4 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { isDefined } from 'twenty-shared/utils';
import {
AppTooltip,
@@ -7,27 +7,30 @@ import {
IconInfoCircle,
} from 'twenty-ui/display';
import { Button } from 'twenty-ui/input';
import { themeCssVariables } from 'twenty-ui/theme-constants';
type AIChatBannerVariant = 'default' | 'warning';
const StyledBanner = styled.div<{ variant: AIChatBannerVariant }>`
align-items: center;
background-color: ${({ theme, variant }) =>
background-color: ${({ variant }) =>
variant === 'warning'
? theme.background.transparent.orange
: theme.accent.secondary};
border-radius: ${({ theme }) => theme.border.radius.md};
? themeCssVariables.background.transparent.orange
: themeCssVariables.accent.secondary};
border-radius: ${themeCssVariables.border.radius.md};
box-sizing: border-box;
display: flex;
gap: ${({ theme }) => theme.spacing(2)};
padding: ${({ theme }) => theme.spacing(2)};
gap: ${themeCssVariables.spacing[2]};
padding: ${themeCssVariables.spacing[2]};
width: 100%;
`;
const StyledIconContainer = styled.div<{ variant: AIChatBannerVariant }>`
align-items: center;
color: ${({ theme, variant }) =>
variant === 'warning' ? theme.color.orange : theme.color.blue};
color: ${({ variant }) =>
variant === 'warning'
? themeCssVariables.color.orange
: themeCssVariables.color.blue};
display: flex;
flex-shrink: 0;
height: 16px;
@@ -36,13 +39,15 @@ const StyledIconContainer = styled.div<{ variant: AIChatBannerVariant }>`
`;
const StyledMessage = styled.p<{ variant: AIChatBannerVariant }>`
color: ${({ theme, variant }) =>
variant === 'warning' ? theme.color.orange : theme.color.blue};
color: ${({ variant }) =>
variant === 'warning'
? themeCssVariables.color.orange
: themeCssVariables.color.blue};
flex-grow: 1;
font-family: ${({ theme }) => theme.font.family};
font-size: ${({ theme }) => theme.font.size.sm};
font-family: ${themeCssVariables.font.family};
font-size: ${themeCssVariables.font.size.sm};
font-style: normal;
font-weight: ${({ theme }) => theme.font.weight.medium};
font-weight: ${themeCssVariables.font.weight.medium};
line-height: 1.4;
margin: 0;
min-width: 0;
@@ -1,4 +1,4 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { type Editor } from '@tiptap/react';
import { AIChatSuggestedPrompts } from '@/ai/components/suggested-prompts/AIChatSuggestedPrompts';
@@ -1,42 +1,44 @@
import { useAgentChatContextOrThrow } from '@/ai/hooks/useAgentChatContextOrThrow';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { t } from '@lingui/core/macro';
import { useContext } from 'react';
import { IconAlertCircle, IconRefresh } from 'twenty-ui/display';
import { Button } from 'twenty-ui/input';
import { ThemeContext } from 'twenty-ui/theme';
import { themeCssVariables } from 'twenty-ui/theme-constants';
const StyledErrorContainer = styled.div`
align-items: center;
background: ${({ theme }) => theme.background.danger};
border: 1px solid ${({ theme }) => theme.border.color.danger};
border-radius: ${({ theme }) => theme.border.radius.md};
background: ${themeCssVariables.background.danger};
border: 1px solid ${themeCssVariables.border.color.danger};
border-radius: ${themeCssVariables.border.radius.md};
display: flex;
gap: ${({ theme }) => theme.spacing(2)};
padding: ${({ theme }) => theme.spacing(2, 3)};
gap: ${themeCssVariables.spacing[2]};
padding: ${themeCssVariables.spacing[2]} ${themeCssVariables.spacing[3]};
`;
const StyledErrorIcon = styled.div`
align-items: center;
color: ${({ theme }) => theme.color.red};
color: ${themeCssVariables.color.red};
display: flex;
`;
const StyledErrorContent = styled.div`
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(0.5)};
gap: ${themeCssVariables.spacing['0.5']};
flex: 1;
`;
const StyledErrorTitle = styled.div`
color: ${({ theme }) => theme.font.color.primary};
font-size: ${({ theme }) => theme.font.size.sm};
font-weight: ${({ theme }) => theme.font.weight.medium};
color: ${themeCssVariables.font.color.primary};
font-size: ${themeCssVariables.font.size.sm};
font-weight: ${themeCssVariables.font.weight.medium};
`;
const StyledErrorMessage = styled.div`
color: ${({ theme }) => theme.font.color.secondary};
font-size: ${({ theme }) => theme.font.size.xs};
color: ${themeCssVariables.font.color.secondary};
font-size: ${themeCssVariables.font.size.xs};
word-break: break-word;
`;
@@ -45,7 +47,7 @@ type AIChatErrorMessageProps = {
};
export const AIChatErrorMessage = ({ error }: AIChatErrorMessageProps) => {
const theme = useTheme();
const { theme } = useContext(ThemeContext);
const { handleRetry, isStreaming } = useAgentChatContextOrThrow();
return (
@@ -1,4 +1,4 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { AgentChatFilePreview } from '@/ai/components/internal/AgentChatFilePreview';
import { AgentMessageRole } from '@/ai/constants/AgentMessageRole';
@@ -9,6 +9,7 @@ import { LightCopyIconButton } from '@/object-record/record-field/ui/components/
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
import { type ExtendedUIMessage } from 'twenty-shared/ai';
import { isDefined } from 'twenty-shared/utils';
import { themeCssVariables } from 'twenty-ui/theme-constants';
import { dateLocaleState } from '~/localization/states/dateLocaleState';
import { beautifyPastDateRelativeToNow } from '~/utils/date-utils';
@@ -26,16 +27,19 @@ const StyledMessageBubble = styled.div<{ isUser?: boolean }>`
`;
const StyledMessageText = styled.div<{ isUser?: boolean }>`
background: ${({ theme, isUser }) =>
isUser ? theme.background.tertiary : theme.background.transparent};
border-radius: ${({ theme, isUser }) =>
isUser ? theme.border.radius.sm : '0'};
color: ${({ theme, isUser }) =>
isUser ? theme.font.color.secondary : theme.font.color.primary};
background: ${({ isUser }) =>
isUser ? themeCssVariables.background.tertiary : 'transparent'};
border-radius: ${({ isUser }) =>
isUser ? themeCssVariables.border.radius.sm : '0'};
color: ${({ isUser }) =>
isUser
? themeCssVariables.font.color.secondary
: themeCssVariables.font.color.primary};
font-weight: ${({ isUser }) => (isUser ? 500 : 400)};
line-height: 1.4em;
max-width: 100%;
padding: ${({ theme, isUser }) => (isUser ? `0 ${theme.spacing(2)}` : 0)};
padding: ${({ isUser }) =>
isUser ? `0 ${themeCssVariables.spacing[2]}` : '0'};
width: fit-content;
word-wrap: break-word;
overflow-wrap: break-word;
@@ -50,14 +54,14 @@ const StyledMessageText = styled.div<{ isUser?: boolean }>`
max-width: 100%;
line-height: 1.4;
padding: 1px 3px;
border-radius: ${({ theme }) => theme.border.radius.sm};
background: ${({ theme }) => theme.background.tertiary};
border-radius: ${themeCssVariables.border.radius.sm};
background: ${themeCssVariables.background.tertiary};
}
pre {
background: ${({ theme }) => theme.background.tertiary};
padding: ${({ theme }) => theme.spacing(2)};
border-radius: ${({ theme }) => theme.border.radius.sm};
background: ${themeCssVariables.background.tertiary};
padding: ${themeCssVariables.spacing[2]};
border-radius: ${themeCssVariables.border.radius.sm};
overflow-x: auto;
max-width: 100%;
@@ -69,16 +73,16 @@ const StyledMessageText = styled.div<{ isUser?: boolean }>`
}
p {
margin-block: ${({ isUser, theme }) =>
isUser ? '0' : `${theme.spacing(1)}`};
margin-block: ${({ isUser }) =>
isUser ? '0' : themeCssVariables.spacing[1]};
line-height: 1.4em;
}
ul,
ol {
line-height: 1.4em;
margin: ${({ theme }) => theme.spacing(1)} 0;
padding-left: ${({ theme }) => theme.spacing(4)};
margin: ${themeCssVariables.spacing[1]} 0;
padding-left: ${themeCssVariables.spacing[4]};
}
ul {
@@ -87,35 +91,35 @@ const StyledMessageText = styled.div<{ isUser?: boolean }>`
li {
line-height: 1.4em;
margin: ${({ theme }) => theme.spacing(0.5)} 0;
padding-bottom: ${({ theme }) => theme.spacing(0.5)};
padding-top: ${({ theme }) => theme.spacing(0.5)};
margin: ${themeCssVariables.spacing['0.5']} 0;
padding-bottom: ${themeCssVariables.spacing['0.5']};
padding-top: ${themeCssVariables.spacing['0.5']};
}
blockquote {
border-left: 3px solid ${({ theme }) => theme.border.color.medium};
margin: ${({ theme }) => theme.spacing(2)} 0;
padding-left: ${({ theme }) => theme.spacing(2)};
color: ${({ theme }) => theme.font.color.secondary};
border-left: 3px solid ${themeCssVariables.border.color.medium};
margin: ${themeCssVariables.spacing[2]} 0;
padding-left: ${themeCssVariables.spacing[2]};
color: ${themeCssVariables.font.color.secondary};
}
`;
const StyledMessageFooter = styled.div`
align-items: center;
color: ${({ theme }) => theme.font.color.secondary};
color: ${themeCssVariables.font.color.secondary};
display: flex;
font-size: ${({ theme }) => theme.font.size.sm};
font-size: ${themeCssVariables.font.size.sm};
justify-content: space-between;
margin-top: ${({ theme }) => theme.spacing(1)};
margin-top: ${themeCssVariables.spacing[1]};
opacity: 0;
pointer-events: none;
transition: opacity ${({ theme }) => theme.animation.duration.normal}s
transition: opacity calc(${themeCssVariables.animation.duration.normal} * 1s)
ease-in-out;
width: 100%;
`;
const StyledMessageTimestamp = styled.span`
color: ${({ theme }) => theme.font.color.light};
color: ${themeCssVariables.font.color.light};
`;
const StyledMessageContainer = styled.div<{ isUser?: boolean }>`
@@ -127,9 +131,9 @@ const StyledMessageContainer = styled.div<{ isUser?: boolean }>`
const StyledFilesContainer = styled.div`
display: flex;
flex-direction: row;
gap: ${({ theme }) => theme.spacing(2)};
gap: ${themeCssVariables.spacing[2]};
flex-wrap: wrap;
margin-top: ${({ theme }) => theme.spacing(2)};
margin-top: ${themeCssVariables.spacing[2]};
`;
export const AIChatMessage = ({
@@ -1,4 +1,4 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { AIChatErrorRenderer } from '@/ai/components/AIChatErrorRenderer';
@@ -1,7 +1,8 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { EditorContent } from '@tiptap/react';
import { useState } from 'react';
import { LightButton } from 'twenty-ui/input';
import { themeCssVariables } from 'twenty-ui/theme-constants';
import { DropZone } from '@/activities/files/components/DropZone';
import { AgentChatFileUploadButton } from '@/ai/components/internal/AgentChatFileUploadButton';
@@ -25,11 +26,11 @@ import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
const StyledContainer = styled.div<{ isDraggingFile: boolean }>`
background: ${({ theme }) => theme.background.primary};
background: ${themeCssVariables.background.primary};
height: ${({ isDraggingFile }) =>
isDraggingFile ? `calc(100% - 24px)` : '100%'};
padding: ${({ isDraggingFile, theme }) =>
isDraggingFile ? theme.spacing(3) : '0'};
padding: ${({ isDraggingFile }) =>
isDraggingFile ? themeCssVariables.spacing[3] : '0'};
display: flex;
flex-direction: column;
`;
@@ -38,27 +39,28 @@ const StyledInputArea = styled.div<{ isMobile: boolean }>`
align-items: flex-end;
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(2)};
padding-inline: ${({ theme }) => theme.spacing(3)};
padding-block: ${({ theme, isMobile }) => (isMobile ? 0 : theme.spacing(3))};
background: ${({ theme }) => theme.background.primary};
gap: ${themeCssVariables.spacing[2]};
padding-inline: ${themeCssVariables.spacing[3]};
padding-block: ${({ isMobile }) =>
isMobile ? '0' : themeCssVariables.spacing[3]};
background: ${themeCssVariables.background.primary};
`;
const StyledInputBox = styled.div`
background-color: ${({ theme }) => theme.background.transparent.lighter};
border: 1px solid ${({ theme }) => theme.border.color.medium};
border-radius: ${({ theme }) => theme.border.radius.sm};
background-color: ${themeCssVariables.background.transparent.lighter};
border: 1px solid ${themeCssVariables.border.color.medium};
border-radius: ${themeCssVariables.border.radius.sm};
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(2)};
gap: ${themeCssVariables.spacing[2]};
min-height: 140px;
padding: ${({ theme }) => theme.spacing(2)};
padding: ${themeCssVariables.spacing[2]};
width: 100%;
box-sizing: border-box;
&:focus-within {
border-color: ${({ theme }) => theme.color.blue};
box-shadow: 0px 0px 0px 3px ${({ theme }) => theme.color.transparent.blue2};
border-color: ${themeCssVariables.color.blue};
box-shadow: 0px 0px 0px 3px ${themeCssVariables.color.transparent.blue2};
}
`;
@@ -72,10 +74,10 @@ const StyledEditorWrapper = styled.div`
background: transparent;
border: none;
box-shadow: none;
color: ${({ theme }) => theme.font.color.primary};
color: ${themeCssVariables.font.color.primary};
font-family: inherit;
font-size: ${({ theme }) => theme.font.size.md};
font-weight: ${({ theme }) => theme.font.weight.regular};
font-size: ${themeCssVariables.font.size.md};
font-weight: ${themeCssVariables.font.weight.regular};
line-height: 16px;
outline: none;
padding: 0;
@@ -88,10 +90,10 @@ const StyledEditorWrapper = styled.div`
}
p.is-editor-empty:first-of-type::before {
color: ${({ theme }) => theme.font.color.light};
color: ${themeCssVariables.font.color.light};
content: attr(data-placeholder);
float: left;
font-weight: ${({ theme }) => theme.font.weight.regular};
font-weight: ${themeCssVariables.font.weight.regular};
height: 0;
pointer-events: none;
}
@@ -102,9 +104,9 @@ const StyledScrollWrapper = styled(ScrollWrapper)`
display: flex;
flex: 1;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(2)};
gap: ${themeCssVariables.spacing[2]};
overflow-y: auto;
padding: ${({ theme }) => theme.spacing(3)};
padding: ${themeCssVariables.spacing[3]};
width: calc(100% - 24px);
`;
@@ -118,13 +120,13 @@ const StyledButtonsContainer = styled.div`
const StyledLeftButtonsContainer = styled.div`
align-items: center;
display: flex;
gap: ${({ theme }) => theme.spacing(0.5)};
gap: ${themeCssVariables.spacing['0.5']};
`;
const StyledRightButtonsContainer = styled.div`
align-items: center;
display: flex;
gap: ${({ theme }) => theme.spacing(1)};
gap: ${themeCssVariables.spacing[1]};
`;
const StyledReadOnlyModelButton = styled(LightButton)`
@@ -1,52 +1,54 @@
import { useAIChatThreadClick } from '@/ai/hooks/useAIChatThreadClick';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { useContext } from 'react';
import { useLingui } from '@lingui/react/macro';
import { IconSparkles } from 'twenty-ui/display';
import { ThemeContext } from 'twenty-ui/theme';
import { themeCssVariables } from 'twenty-ui/theme-constants';
import { type AgentChatThread } from '~/generated-metadata/graphql';
const StyledThreadsList = styled.div`
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(1)};
gap: ${themeCssVariables.spacing[1]};
`;
const StyledDateGroup = styled.div`
margin-bottom: ${({ theme }) => theme.spacing(4)};
margin-bottom: ${themeCssVariables.spacing[4]};
`;
const StyledDateHeader = styled.div`
color: ${({ theme }) => theme.font.color.light};
font-size: ${({ theme }) => theme.font.size.xs};
font-weight: ${({ theme }) => theme.font.weight.medium};
margin-bottom: ${({ theme }) => theme.spacing(1)};
color: ${themeCssVariables.font.color.light};
font-size: ${themeCssVariables.font.size.xs};
font-weight: ${themeCssVariables.font.weight.medium};
margin-bottom: ${themeCssVariables.spacing[1]};
`;
const StyledThreadItem = styled.div<{ isSelected?: boolean }>`
display: flex;
align-items: center;
gap: ${({ theme }) => theme.spacing(2)};
border-radius: ${({ theme }) => theme.border.radius.sm};
gap: ${themeCssVariables.spacing[2]};
border-radius: ${themeCssVariables.border.radius.sm};
transition: all 0.2s ease;
margin-bottom: ${({ theme }) => theme.spacing(1)};
margin-bottom: ${themeCssVariables.spacing[1]};
border-left: 3px solid transparent;
cursor: pointer;
padding: ${({ theme }) => theme.spacing(1)} 1px;
padding: ${themeCssVariables.spacing[1]} 1px;
right: 3px;
position: relative;
width: calc(100% + 1px);
&:hover {
background: ${({ theme }) => theme.background.transparent.light};
background: ${themeCssVariables.background.transparent.light};
}
`;
const StyledSparkleIcon = styled.div`
align-items: center;
background: ${({ theme }) => theme.background.transparent.blue};
border-radius: ${({ theme }) => theme.border.radius.sm};
background: ${themeCssVariables.background.transparent.blue};
border-radius: ${themeCssVariables.border.radius.sm};
display: flex;
padding: ${({ theme }) => theme.spacing(1)};
padding: ${themeCssVariables.spacing[1]};
justify-content: center;
`;
@@ -56,8 +58,8 @@ const StyledThreadContent = styled.div`
`;
const StyledThreadTitle = styled.div`
color: ${({ theme }) => theme.font.color.secondary};
font-size: ${({ theme }) => theme.font.size.md};
color: ${themeCssVariables.font.color.secondary};
font-size: ${themeCssVariables.font.size.md};
font-weight: 500;
overflow: hidden;
text-overflow: ellipsis;
@@ -72,7 +74,7 @@ export const AIChatThreadGroup = ({
title: string;
}) => {
const { t } = useLingui();
const theme = useTheme();
const { theme } = useContext(ThemeContext);
const { handleThreadClick } = useAIChatThreadClick();
if (threads.length === 0) {
@@ -1,4 +1,4 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { AIChatThreadGroup } from '@/ai/components/AIChatThreadGroup';
import { AIChatThreadsListEffect } from '@/ai/components/AIChatThreadsListEffect';
@@ -10,12 +10,13 @@ import { t } from '@lingui/core/macro';
import { Key } from 'ts-key-enum';
import { capitalize } from 'twenty-shared/utils';
import { Button } from 'twenty-ui/input';
import { themeCssVariables } from 'twenty-ui/theme-constants';
import { getOsControlSymbol } from 'twenty-ui/utilities';
import { useGetChatThreadsQuery } from '~/generated-metadata/graphql';
const StyledContainer = styled.div`
background: ${({ theme }) => theme.background.secondary};
border-right: 1px solid ${({ theme }) => theme.border.color.light};
background: ${themeCssVariables.background.secondary};
border-right: 1px solid ${themeCssVariables.border.color.light};
display: flex;
flex-direction: column;
height: 100%;
@@ -24,14 +25,14 @@ const StyledContainer = styled.div`
const StyledThreadsContainer = styled.div`
flex: 1;
overflow-y: auto;
padding: ${({ theme }) => theme.spacing(3)};
padding: ${themeCssVariables.spacing[3]};
`;
const StyledButtonsContainer = styled.div`
display: flex;
padding: ${({ theme }) => theme.spacing(2, 2.5)};
padding: ${themeCssVariables.spacing[2]} 10px;
justify-content: flex-end;
border-top: 1px solid ${({ theme }) => theme.border.color.medium};
border-top: 1px solid ${themeCssVariables.border.color.medium};
`;
export const AIChatThreadsList = () => {
@@ -1,8 +1,7 @@
import { TerminalOutput } from '@/ai/components/TerminalOutput';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { useContext, useState } from 'react';
import { useLingui } from '@lingui/react/macro';
import { useState } from 'react';
import {
IconChevronDown,
IconChevronUp,
@@ -16,96 +15,97 @@ import {
} from 'twenty-ui/display';
import { CodeEditor, LightIconButton } from 'twenty-ui/input';
import { AnimatedExpandableContainer } from 'twenty-ui/layout';
import { ThemeContext } from 'twenty-ui/theme';
import { themeCssVariables } from 'twenty-ui/theme-constants';
import { useCopyToClipboard } from '~/hooks/useCopyToClipboard';
const StyledContainer = styled.div`
border: 1px solid ${({ theme }) => theme.border.color.medium};
border-radius: ${({ theme }) => theme.border.radius.md};
border: 1px solid ${themeCssVariables.border.color.medium};
border-radius: ${themeCssVariables.border.radius.md};
display: flex;
flex-direction: column;
margin: ${({ theme }) => theme.spacing(2)} 0;
margin: ${themeCssVariables.spacing[2]} 0;
overflow: hidden;
`;
const StyledHeader = styled.div<{ status: 'success' | 'error' | 'running' }>`
align-items: center;
background: ${({ theme }) => theme.background.secondary};
border-bottom: 1px solid ${({ theme }) => theme.border.color.light};
background: ${themeCssVariables.background.secondary};
border-bottom: 1px solid ${themeCssVariables.border.color.light};
display: flex;
gap: ${({ theme }) => theme.spacing(2)};
gap: ${themeCssVariables.spacing[2]};
justify-content: space-between;
padding: ${({ theme }) => theme.spacing(2)} ${({ theme }) => theme.spacing(3)};
padding: ${themeCssVariables.spacing[2]} ${themeCssVariables.spacing[3]};
`;
const StyledHeaderLeft = styled.div`
align-items: center;
display: flex;
gap: ${({ theme }) => theme.spacing(2)};
gap: ${themeCssVariables.spacing[2]};
`;
const StyledHeaderRight = styled.div`
align-items: center;
display: flex;
gap: ${({ theme }) => theme.spacing(1)};
gap: ${themeCssVariables.spacing[1]};
`;
const StyledStatusBadge = styled.div<{
status: 'success' | 'error' | 'running';
}>`
align-items: center;
background: ${({ status, theme }) =>
background: ${({ status }) =>
status === 'success'
? theme.background.transparent.success
? themeCssVariables.background.transparent.success
: status === 'error'
? theme.background.transparent.danger
: theme.background.transparent.medium};
border-radius: ${({ theme }) => theme.border.radius.pill};
color: ${({ status, theme }) =>
? themeCssVariables.background.transparent.danger
: themeCssVariables.background.transparent.medium};
border-radius: ${themeCssVariables.border.radius.pill};
color: ${({ status }) =>
status === 'success'
? theme.color.turquoise
? themeCssVariables.color.turquoise
: status === 'error'
? theme.color.red
: theme.font.color.secondary};
? themeCssVariables.color.red
: themeCssVariables.font.color.secondary};
display: flex;
font-size: ${({ theme }) => theme.font.size.xs};
font-weight: ${({ theme }) => theme.font.weight.medium};
gap: ${({ theme }) => theme.spacing(1)};
padding: ${({ theme }) => theme.spacing(0.5)}
${({ theme }) => theme.spacing(2)};
font-size: ${themeCssVariables.font.size.xs};
font-weight: ${themeCssVariables.font.weight.medium};
gap: ${themeCssVariables.spacing[1]};
padding: ${themeCssVariables.spacing['0.5']} ${themeCssVariables.spacing[2]};
`;
const StyledTitle = styled.span`
color: ${({ theme }) => theme.font.color.primary};
font-size: ${({ theme }) => theme.font.size.md};
font-weight: ${({ theme }) => theme.font.weight.medium};
color: ${themeCssVariables.font.color.primary};
font-size: ${themeCssVariables.font.size.md};
font-weight: ${themeCssVariables.font.weight.medium};
`;
const StyledSection = styled.div`
border-top: 1px solid ${({ theme }) => theme.border.color.light};
border-top: 1px solid ${themeCssVariables.border.color.light};
`;
const StyledSectionHeader = styled.div`
align-items: center;
background: ${({ theme }) => theme.background.secondary};
background: ${themeCssVariables.background.secondary};
cursor: pointer;
display: flex;
gap: ${({ theme }) => theme.spacing(2)};
gap: ${themeCssVariables.spacing[2]};
justify-content: space-between;
padding: ${({ theme }) => theme.spacing(2)} ${({ theme }) => theme.spacing(3)};
transition: background ${({ theme }) => theme.animation.duration.fast}s;
padding: ${themeCssVariables.spacing[2]} ${themeCssVariables.spacing[3]};
transition: background calc(${themeCssVariables.animation.duration.fast} * 1s);
&:hover {
background: ${({ theme }) => theme.background.tertiary};
background: ${themeCssVariables.background.tertiary};
}
`;
const StyledSectionHeaderLeft = styled.div`
align-items: center;
color: ${({ theme }) => theme.font.color.secondary};
color: ${themeCssVariables.font.color.secondary};
display: flex;
font-size: ${({ theme }) => theme.font.size.sm};
font-weight: ${({ theme }) => theme.font.weight.medium};
gap: ${({ theme }) => theme.spacing(1)};
font-size: ${themeCssVariables.font.size.sm};
font-weight: ${themeCssVariables.font.weight.medium};
gap: ${themeCssVariables.spacing[1]};
`;
const StyledCodeEditorContainer = styled.div`
@@ -115,14 +115,14 @@ const StyledCodeEditorContainer = styled.div`
const StyledFilesGrid = styled.div`
display: grid;
gap: ${({ theme }) => theme.spacing(2)};
gap: ${themeCssVariables.spacing[2]};
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
padding: ${({ theme }) => theme.spacing(3)};
padding: ${themeCssVariables.spacing[3]};
`;
const StyledFileCard = styled.div`
border: 1px solid ${({ theme }) => theme.border.color.light};
border-radius: ${({ theme }) => theme.border.radius.sm};
border: 1px solid ${themeCssVariables.border.color.light};
border-radius: ${themeCssVariables.border.radius.sm};
display: flex;
flex-direction: column;
overflow: hidden;
@@ -131,7 +131,7 @@ const StyledFileCard = styled.div`
const StyledFilePreview = styled.div`
align-items: center;
aspect-ratio: 16 / 9;
background: ${({ theme }) => theme.background.tertiary};
background: ${themeCssVariables.background.tertiary};
display: flex;
justify-content: center;
overflow: hidden;
@@ -145,17 +145,16 @@ const StyledPreviewImage = styled.img`
const StyledFileInfo = styled.div`
align-items: center;
background: ${({ theme }) => theme.background.secondary};
background: ${themeCssVariables.background.secondary};
display: flex;
gap: ${({ theme }) => theme.spacing(2)};
gap: ${themeCssVariables.spacing[2]};
justify-content: space-between;
padding: ${({ theme }) => theme.spacing(1.5)}
${({ theme }) => theme.spacing(2)};
padding: ${themeCssVariables.spacing['1.5']} ${themeCssVariables.spacing[2]};
`;
const StyledFileName = styled.span`
color: ${({ theme }) => theme.font.color.primary};
font-size: ${({ theme }) => theme.font.size.sm};
color: ${themeCssVariables.font.color.primary};
font-size: ${themeCssVariables.font.size.sm};
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
@@ -163,11 +162,11 @@ const StyledFileName = styled.span`
const StyledDownloadLink = styled.a`
align-items: center;
color: ${({ theme }) => theme.font.color.secondary};
color: ${themeCssVariables.font.color.secondary};
display: flex;
&:hover {
color: ${({ theme }) => theme.font.color.primary};
color: ${themeCssVariables.font.color.primary};
}
`;
@@ -203,7 +202,7 @@ export const CodeExecutionDisplay = ({
isRunning = false,
}: CodeExecutionDisplayProps) => {
const { t } = useLingui();
const theme = useTheme();
const { theme } = useContext(ThemeContext);
const { copyToClipboard } = useCopyToClipboard();
const [isCodeExpanded, setIsCodeExpanded] = useState(false);
const [isOutputExpanded, setIsOutputExpanded] = useState(true);
@@ -4,11 +4,16 @@ import {
RECORD_REFERENCE_REGEX,
RecordLink,
} from '@/ai/components/RecordLink';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { lazy, Suspense } from 'react';
import {
StyledMarkdownContainer,
StyledParagraph,
StyledSkeletonContainer,
StyledTableScrollContainer,
} from '@/ai/components/LazyMarkdownRendererStyledComponents';
import { lazy, Suspense, useContext } from 'react';
import Skeleton, { SkeletonTheme } from 'react-loading-skeleton';
import { isDefined } from 'twenty-shared/utils';
import { ThemeContext } from 'twenty-ui/theme';
const TextWithRecordLinks = ({ text }: { text: string }) => {
const parts: React.ReactNode[] = [];
@@ -72,11 +77,11 @@ const MarkdownRenderer = lazy(async () => {
default: ({
children,
TableScrollContainer,
StyledParagraph,
ParagraphComponent,
}: {
children: string;
TableScrollContainer: React.ComponentType<{ children: React.ReactNode }>;
StyledParagraph: React.ComponentType<{ children: React.ReactNode }>;
ParagraphComponent: React.ComponentType<{ children: React.ReactNode }>;
}) => (
<Markdown
remarkPlugins={[remarkGfm]}
@@ -87,9 +92,9 @@ const MarkdownRenderer = lazy(async () => {
</TableScrollContainer>
),
p: ({ children }) => (
<StyledParagraph>
<ParagraphComponent>
{processChildrenForRecordLinks(children)}
</StyledParagraph>
</ParagraphComponent>
),
li: ({ children }) => (
<li>{processChildrenForRecordLinks(children)}</li>
@@ -125,194 +130,8 @@ const MarkdownRenderer = lazy(async () => {
};
});
const StyledMarkdownContainer = styled.div`
border-radius: ${({ theme }) => theme.border.radius.sm};
line-height: 150%;
margin: ${({ theme }) => `${theme.spacing(1.5)} 0`};
position: relative;
scroll-margin-top: ${({ theme }) => theme.spacing(10)};
scroll-margin-bottom: ${({ theme }) => theme.spacing(10)};
&:empty {
display: none;
}
.markdown-link {
color: ${({ theme }) => theme.accent.accent11};
text-decoration: none;
-webkit-text-decoration: none;
}
.markdown-link:visited {
color: ${({ theme }) => theme.accent.accent11};
}
.markdown-link:hover {
text-decoration: underline !important;
}
strong,
b {
font-weight: ${({ theme }) => theme.font.weight.semiBold};
}
h1,
h2,
h3 {
font-weight: ${({ theme }) => theme.font.weight.semiBold} !important;
}
h1 {
font-size: 1.6em;
line-height: 1.25;
margin-bottom: 12px;
margin-top: 24px;
}
h2 {
font-size: 1.3em;
line-height: 1.25;
margin-bottom: 10px;
margin-top: 20px;
}
h3 {
font-size: 1.15em;
line-height: 1.25;
margin-bottom: 8px;
margin-top: 18px;
}
h4 {
font-size: 1.05em;
line-height: 1.25;
margin-bottom: 8px;
margin-top: 16px;
}
h5 {
font-size: 0.95em;
line-height: 1.25;
margin-bottom: 6px;
margin-top: 14px;
}
h6 {
font-size: 0.85em;
line-height: 1.25;
margin-bottom: 6px;
margin-top: 12px;
}
hr {
background-color: ${({ theme }) => theme.border.color.light} !important;
border: none;
height: 1px;
margin: ${({ theme }) => theme.spacing(4)} 0;
}
ol:first-of-type:not(.nested),
ul:first-of-type:not(.nested) {
margin-top: ${({ theme }) => theme.spacing(1)} !important;
}
ol:last-of-type:not(.nested),
ul:last-of-type:not(.nested) {
margin-bottom: ${({ theme }) => theme.spacing(1)} !important;
}
li {
line-height: 150%;
margin-bottom: ${({ theme }) => theme.spacing(0.5)} !important;
margin-top: ${({ theme }) => theme.spacing(0.5)} !important;
padding-bottom: ${({ theme }) => theme.spacing(0.5)} !important;
padding-top: ${({ theme }) => theme.spacing(0.5)} !important;
}
:not(pre) > code {
background-color: ${({ theme }) => theme.background.tertiary};
border-radius: ${({ theme }) => theme.border.radius.sm};
color: ${({ theme }) => theme.font.color.primary};
font-family: ${({ theme }) => `${theme.code.font.family}, monospace`};
font-size: 0.9em;
padding: 1.5px 3px;
transition: all ${({ theme }) => theme.animation.duration.fast}s ease;
}
:not(pre) > code[style*='cursor: pointer'] {
background-color: ${({ theme }) => theme.background.secondary};
border: ${({ theme }) => `1px solid ${theme.accent.accent10}`};
color: ${({ theme }) => theme.accent.accent10};
}
:not(pre) > code[style*='cursor: pointer']:hover {
background-color: ${({ theme }) => theme.background.transparent.blue};
}
.markdown-code-outer-container {
border-radius: ${({ theme }) => theme.border.radius.md} !important;
overflow: hidden;
}
.markdown-block-code {
background-color: ${({ theme }) => theme.background.secondary};
border: 1px solid ${({ theme }) => theme.border.color.medium};
border-radius: ${({ theme }) => theme.border.radius.md} !important;
}
.markdown-block-code * {
animation: none !important;
}
img {
height: auto;
max-width: 100%;
}
`;
// Using div instead of p to allow RecordLink (which contains div elements) as children
const StyledParagraph = styled.div`
line-height: inherit;
margin-block: ${({ theme }) => theme.spacing(2)};
&:first-child {
margin-block-start: 0;
}
&:last-child {
margin-block-end: 0;
}
`;
const StyledSkeletonContainer = styled.div`
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(2)};
width: 100%;
`;
const StyledTableScrollContainer = styled.div`
overflow-x: auto;
table {
border-collapse: collapse;
margin-block: ${({ theme }) => theme.spacing(2)};
}
th,
td {
border: ${({ theme }) => `1px solid ${theme.border.color.light}`};
padding: ${({ theme }) => theme.spacing(2)};
}
th {
background-color: ${({ theme }) => theme.background.secondary};
font-weight: ${({ theme }) => theme.font.weight.medium};
}
`;
const LoadingSkeleton = () => {
const theme = useTheme();
const { theme } = useContext(ThemeContext);
return (
<SkeletonTheme
@@ -352,7 +171,7 @@ export const LazyMarkdownRenderer = ({ text }: { text: string }) => {
<Suspense fallback={<LoadingSkeleton />}>
<MarkdownRenderer
TableScrollContainer={StyledTableScrollContainer}
StyledParagraph={StyledParagraph}
ParagraphComponent={StyledParagraph}
>
{text}
</MarkdownRenderer>
@@ -0,0 +1,187 @@
import { styled } from '@linaria/react';
import { themeCssVariables } from 'twenty-ui/theme-constants';
export const StyledMarkdownContainer = styled.div`
border-radius: ${themeCssVariables.border.radius.sm};
line-height: 150%;
margin: ${themeCssVariables.spacing['1.5']} 0;
position: relative;
scroll-margin-top: ${themeCssVariables.spacing[10]};
scroll-margin-bottom: ${themeCssVariables.spacing[10]};
&:empty {
display: none;
}
.markdown-link {
color: ${themeCssVariables.accent.accent11};
text-decoration: none;
-webkit-text-decoration: none;
}
.markdown-link:visited {
color: ${themeCssVariables.accent.accent11};
}
.markdown-link:hover {
text-decoration: underline !important;
}
strong,
b {
font-weight: ${themeCssVariables.font.weight.semiBold};
}
h1,
h2,
h3 {
font-weight: ${themeCssVariables.font.weight.semiBold} !important;
}
h1 {
font-size: 1.6em;
line-height: 1.25;
margin-bottom: 12px;
margin-top: 24px;
}
h2 {
font-size: 1.3em;
line-height: 1.25;
margin-bottom: 10px;
margin-top: 20px;
}
h3 {
font-size: 1.15em;
line-height: 1.25;
margin-bottom: 8px;
margin-top: 18px;
}
h4 {
font-size: 1.05em;
line-height: 1.25;
margin-bottom: 8px;
margin-top: 16px;
}
h5 {
font-size: 0.95em;
line-height: 1.25;
margin-bottom: 6px;
margin-top: 14px;
}
h6 {
font-size: 0.85em;
line-height: 1.25;
margin-bottom: 6px;
margin-top: 12px;
}
hr {
background-color: ${themeCssVariables.border.color.light} !important;
border: none;
height: 1px;
margin: ${themeCssVariables.spacing[4]} 0;
}
ol:first-of-type:not(.nested),
ul:first-of-type:not(.nested) {
margin-top: ${themeCssVariables.spacing[1]} !important;
}
ol:last-of-type:not(.nested),
ul:last-of-type:not(.nested) {
margin-bottom: ${themeCssVariables.spacing[1]} !important;
}
li {
line-height: 150%;
margin-bottom: ${themeCssVariables.spacing['0.5']} !important;
margin-top: ${themeCssVariables.spacing['0.5']} !important;
padding-bottom: ${themeCssVariables.spacing['0.5']} !important;
padding-top: ${themeCssVariables.spacing['0.5']} !important;
}
:not(pre) > code {
background-color: ${themeCssVariables.background.tertiary};
border-radius: ${themeCssVariables.border.radius.sm};
color: ${themeCssVariables.font.color.primary};
font-family: ${themeCssVariables.code.font.family}, monospace;
font-size: 0.9em;
padding: 1.5px 3px;
transition: all calc(${themeCssVariables.animation.duration.fast} * 1s) ease;
}
:not(pre) > code[style*='cursor: pointer'] {
background-color: ${themeCssVariables.background.secondary};
border: 1px solid ${themeCssVariables.accent.accent10};
color: ${themeCssVariables.accent.accent10};
}
:not(pre) > code[style*='cursor: pointer']:hover {
background-color: ${themeCssVariables.background.transparent.blue};
}
.markdown-code-outer-container {
border-radius: ${themeCssVariables.border.radius.md} !important;
overflow: hidden;
}
.markdown-block-code {
background-color: ${themeCssVariables.background.secondary};
border: 1px solid ${themeCssVariables.border.color.medium};
border-radius: ${themeCssVariables.border.radius.md} !important;
}
.markdown-block-code * {
animation: none !important;
}
img {
height: auto;
max-width: 100%;
}
`;
export const StyledParagraph = styled.div`
line-height: inherit;
margin-block: ${themeCssVariables.spacing[2]};
&:first-child {
margin-block-start: 0;
}
&:last-child {
margin-block-end: 0;
}
`;
export const StyledSkeletonContainer = styled.div`
display: flex;
flex-direction: column;
gap: ${themeCssVariables.spacing[2]};
width: 100%;
`;
export const StyledTableScrollContainer = styled.div`
overflow-x: auto;
table {
border-collapse: collapse;
margin-block: ${themeCssVariables.spacing[2]};
}
th,
td {
border: 1px solid ${themeCssVariables.border.color.light};
padding: ${themeCssVariables.spacing[2]};
}
th {
background-color: ${themeCssVariables.background.secondary};
font-weight: ${themeCssVariables.font.weight.medium};
}
`;
@@ -1,34 +1,35 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { useLingui } from '@lingui/react/macro';
import { IconComment } from 'twenty-ui/display';
import { themeCssVariables } from 'twenty-ui/theme-constants';
import { NavigationDrawerItem } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerItem';
import { type AgentChatThread } from '~/generated-metadata/graphql';
import { beautifyPastDateRelativeToNowShort } from '~/utils/date-utils';
const StyledDateSection = styled.section`
margin-bottom: ${({ theme }) => theme.spacing(4)};
margin-bottom: ${themeCssVariables.spacing[4]};
`;
const StyledThreadList = styled.div`
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(0.5)};
gap: ${themeCssVariables.spacing['0.5']};
`;
const StyledDateHeader = styled.div`
color: ${({ theme }) => theme.font.color.light};
font-size: ${({ theme }) => theme.font.size.xs};
font-weight: ${({ theme }) => theme.font.weight.medium};
margin-bottom: ${({ theme }) => theme.spacing(1)};
padding: ${({ theme }) => theme.spacing(0, 2)};
color: ${themeCssVariables.font.color.light};
font-size: ${themeCssVariables.font.size.xs};
font-weight: ${themeCssVariables.font.weight.medium};
margin-bottom: ${themeCssVariables.spacing[1]};
padding: ${themeCssVariables.spacing[0]} ${themeCssVariables.spacing[2]};
`;
const StyledThreadTimestamp = styled.span`
color: ${({ theme }) => theme.font.color.light};
font-size: ${({ theme }) => theme.font.size.xs};
font-weight: ${({ theme }) => theme.font.weight.regular};
padding-right: ${({ theme }) => theme.spacing(0.5)};
color: ${themeCssVariables.font.color.light};
font-size: ${themeCssVariables.font.size.xs};
font-weight: ${themeCssVariables.font.weight.regular};
padding-right: ${themeCssVariables.spacing['0.5']};
`;
export type NavigationDrawerAIChatThreadDateSectionProps = {
@@ -1,4 +1,4 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { NavigationDrawerAIChatThreadDateSection } from '@/ai/components/NavigationDrawerAIChatThreadDateSection';
import { AIChatSkeletonLoader } from '@/ai/components/internal/AIChatSkeletonLoader';
@@ -9,6 +9,7 @@ import { type DateGroupKey } from '@/ai/utils/dateGroupKey';
import { DATE_GROUP_KEYS } from '@/ai/utils/dateGroupKeys';
import { getDateGroupTitle } from '@/ai/utils/getDateGroupTitle';
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
import { themeCssVariables } from 'twenty-ui/theme-constants';
import { useGetChatThreadsQuery } from '~/generated-metadata/graphql';
const StyledScrollableList = styled.div`
@@ -17,8 +18,8 @@ const StyledScrollableList = styled.div`
flex: 1;
min-height: 0;
overflow-y: auto;
padding: ${({ theme }) => theme.spacing(2, 0)};
width: ${({ theme }) => `calc(100% - ${theme.spacing(2)})`};
padding: ${themeCssVariables.spacing[2]} ${themeCssVariables.spacing[0]};
width: calc(100% - ${themeCssVariables.spacing[2]});
`;
export const NavigationDrawerAIChatThreadsList = () => {
@@ -1,9 +1,10 @@
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { useState } from 'react';
import { styled } from '@linaria/react';
import { useContext, useState } from 'react';
import { IconBrain, IconChevronDown, IconChevronUp } from 'twenty-ui/display';
import { AnimatedExpandableContainer } from 'twenty-ui/layout';
import { ThemeContext } from 'twenty-ui/theme';
import { themeCssVariables } from 'twenty-ui/theme-constants';
import { ShimmeringText } from '@/ai/components/ShimmeringText';
import { t } from '@lingui/core/macro';
@@ -11,27 +12,27 @@ import { t } from '@lingui/core/macro';
const StyledContainer = styled.div`
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(2)};
margin-bottom: ${({ theme }) => theme.spacing(2)};
gap: ${themeCssVariables.spacing[2]};
margin-bottom: ${themeCssVariables.spacing[2]};
`;
const StyledThinkingText = styled.div`
color: ${({ theme }) => theme.font.color.tertiary};
font-size: ${({ theme }) => theme.font.size.md};
font-weight: ${({ theme }) => theme.font.weight.medium};
color: ${themeCssVariables.font.color.tertiary};
font-size: ${themeCssVariables.font.size.md};
font-weight: ${themeCssVariables.font.weight.medium};
`;
const StyledReasoningContainer = styled.div`
background: ${({ theme }) => theme.background.transparent.lighter};
border-radius: ${({ theme }) => theme.border.radius.sm};
padding: ${({ theme }) => theme.spacing(3)};
border: 1px solid ${({ theme }) => theme.border.color.light};
background: ${themeCssVariables.background.transparent.lighter};
border-radius: ${themeCssVariables.border.radius.sm};
padding: ${themeCssVariables.spacing[3]};
border: 1px solid ${themeCssVariables.border.color.light};
`;
const StyledReasoningText = styled.div`
color: ${({ theme }) => theme.font.color.secondary};
font-size: ${({ theme }) => theme.font.size.sm};
line-height: ${({ theme }) => theme.text.lineHeight.lg};
color: ${themeCssVariables.font.color.secondary};
font-size: ${themeCssVariables.font.size.sm};
line-height: ${themeCssVariables.text.lineHeight.lg};
white-space: pre-wrap;
`;
@@ -39,24 +40,24 @@ const StyledToggleButton = styled.div`
align-items: center;
background: none;
border: none;
color: ${({ theme }) => theme.font.color.tertiary};
color: ${themeCssVariables.font.color.tertiary};
cursor: pointer;
display: flex;
font-size: ${({ theme }) => theme.font.size.md};
font-weight: ${({ theme }) => theme.font.weight.medium};
gap: ${({ theme }) => theme.spacing(1)};
padding: ${({ theme }) => theme.spacing(1)} 0;
transition: color ${({ theme }) => theme.animation.duration.normal}s;
font-size: ${themeCssVariables.font.size.md};
font-weight: ${themeCssVariables.font.weight.medium};
gap: ${themeCssVariables.spacing[1]};
padding: ${themeCssVariables.spacing[1]} 0;
transition: color calc(${themeCssVariables.animation.duration.normal} * 1s);
&:hover {
color: ${({ theme }) => theme.font.color.secondary};
color: ${themeCssVariables.font.color.secondary};
}
`;
const StyledIconContainer = styled.div`
display: flex;
align-items: center;
gap: ${({ theme }) => theme.spacing(1)};
gap: ${themeCssVariables.spacing[1]};
`;
export const ReasoningSummaryDisplay = ({
@@ -66,7 +67,7 @@ export const ReasoningSummaryDisplay = ({
content: string;
isThinking?: boolean;
}) => {
const theme = useTheme();
const { theme } = useContext(ThemeContext);
const [isExpanded, setIsExpanded] = useState(false);
const hasContent = content.trim().length > 0;
@@ -1,10 +1,11 @@
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { useState } from 'react';
import { styled } from '@linaria/react';
import { useContext, useState } from 'react';
import { IconChevronDown, IconChevronUp } from 'twenty-ui/display';
import { JsonTree } from 'twenty-ui/json-visualizer';
import { AnimatedExpandableContainer } from 'twenty-ui/layout';
import { ThemeContext } from 'twenty-ui/theme';
import { themeCssVariables } from 'twenty-ui/theme-constants';
import { useLingui } from '@lingui/react/macro';
import { type DataMessagePart } from 'twenty-shared/ai';
@@ -14,8 +15,8 @@ import { useCopyToClipboard } from '~/hooks/useCopyToClipboard';
const StyledContainer = styled.div`
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(2)};
margin-top: ${({ theme }) => theme.spacing(2)};
gap: ${themeCssVariables.spacing[2]};
margin-top: ${themeCssVariables.spacing[2]};
`;
const StyledToggleButton = styled.div`
@@ -24,23 +25,23 @@ const StyledToggleButton = styled.div`
border: none;
cursor: pointer;
display: flex;
color: ${({ theme }) => theme.font.color.tertiary};
gap: ${({ theme }) => theme.spacing(1)};
padding: ${({ theme }) => theme.spacing(1)} 0;
transition: color ${({ theme }) => theme.animation.duration.normal}s;
font-size: ${({ theme }) => theme.font.size.sm};
color: ${themeCssVariables.font.color.tertiary};
gap: ${themeCssVariables.spacing[1]};
padding: ${themeCssVariables.spacing[1]} 0;
transition: color calc(${themeCssVariables.animation.duration.normal} * 1s);
font-size: ${themeCssVariables.font.size.sm};
&:hover {
color: ${({ theme }) => theme.font.color.secondary};
color: ${themeCssVariables.font.color.secondary};
}
`;
const StyledContentContainer = styled.div`
background: ${({ theme }) => theme.background.transparent.lighter};
border: 1px solid ${({ theme }) => theme.border.color.light};
border-radius: ${({ theme }) => theme.border.radius.sm};
background: ${themeCssVariables.background.transparent.lighter};
border: 1px solid ${themeCssVariables.border.color.light};
border-radius: ${themeCssVariables.border.radius.sm};
min-width: 0;
padding: ${({ theme }) => theme.spacing(3)};
padding: ${themeCssVariables.spacing[3]};
`;
const StyledJsonTreeContainer = styled.div`
@@ -52,48 +53,52 @@ const StyledJsonTreeContainer = styled.div`
`;
const StyledTabContainer = styled.div`
border-bottom: 1px solid ${({ theme }) => theme.border.color.light};
border-bottom: 1px solid ${themeCssVariables.border.color.light};
display: flex;
gap: ${({ theme }) => theme.spacing(3)};
margin-bottom: ${({ theme }) => theme.spacing(3)};
gap: ${themeCssVariables.spacing[3]};
margin-bottom: ${themeCssVariables.spacing[3]};
`;
const StyledTab = styled.div<{ isActive: boolean }>`
color: ${({ theme, isActive }) =>
isActive ? theme.font.color.primary : theme.font.color.tertiary};
font-size: ${({ theme }) => theme.font.size.sm};
font-weight: ${({ theme, isActive }) =>
isActive ? theme.font.weight.medium : theme.font.weight.regular};
color: ${({ isActive }) =>
isActive
? themeCssVariables.font.color.primary
: themeCssVariables.font.color.tertiary};
font-size: ${themeCssVariables.font.size.sm};
font-weight: ${({ isActive }) =>
isActive
? themeCssVariables.font.weight.medium
: themeCssVariables.font.weight.regular};
cursor: pointer;
transition: color ${({ theme }) => theme.animation.duration.normal}s;
padding-bottom: ${({ theme }) => theme.spacing(2)};
transition: color calc(${themeCssVariables.animation.duration.normal} * 1s);
padding-bottom: ${themeCssVariables.spacing[2]};
&:hover {
color: ${({ theme }) => theme.font.color.secondary};
color: ${themeCssVariables.font.color.secondary};
}
`;
const StyledTimingSection = styled.div`
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(2)};
gap: ${themeCssVariables.spacing[2]};
`;
const StyledTimingRow = styled.div`
align-items: center;
display: flex;
font-size: ${({ theme }) => theme.font.size.sm};
font-size: ${themeCssVariables.font.size.sm};
justify-content: space-between;
padding: ${({ theme }) => theme.spacing(1)} 0;
padding: ${themeCssVariables.spacing[1]} 0;
`;
const StyledTimingLabel = styled.span`
color: ${({ theme }) => theme.font.color.secondary};
color: ${themeCssVariables.font.color.secondary};
`;
const StyledTimingValue = styled.span`
color: ${({ theme }) => theme.font.color.primary};
font-weight: ${({ theme }) => theme.font.weight.medium};
color: ${themeCssVariables.font.color.primary};
font-weight: ${themeCssVariables.font.weight.medium};
`;
type TabType = 'timing' | 'details' | 'context';
@@ -319,7 +324,7 @@ type RoutingDebugDisplayProps = {
export const RoutingDebugDisplay = ({ debug }: RoutingDebugDisplayProps) => {
const { t } = useLingui();
const theme = useTheme();
const { theme } = useContext(ThemeContext);
const { copyToClipboard } = useCopyToClipboard();
const [isExpanded, setIsExpanded] = useState(false);
const [activeTab, setActiveTab] = useState<TabType>('timing');
@@ -1,16 +1,17 @@
import { RoutingDebugDisplay } from '@/ai/components/RoutingDebugDisplay';
import { ShimmeringText } from '@/ai/components/ShimmeringText';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { useState } from 'react';
import { styled } from '@linaria/react';
import { useContext, useState } from 'react';
import { type DataMessagePart } from 'twenty-shared/ai';
import { IconChevronDown, IconChevronUp, IconCpu } from 'twenty-ui/display';
import { AnimatedExpandableContainer } from 'twenty-ui/layout';
import { ThemeContext } from 'twenty-ui/theme';
import { themeCssVariables } from 'twenty-ui/theme-constants';
const StyledContainer = styled.div`
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(2)};
gap: ${themeCssVariables.spacing[2]};
`;
const StyledToggleButton = styled.div<{ isExpandable: boolean }>`
@@ -19,39 +20,41 @@ const StyledToggleButton = styled.div<{ isExpandable: boolean }>`
border: none;
cursor: ${({ isExpandable }) => (isExpandable ? 'pointer' : 'auto')};
display: flex;
color: ${({ theme }) => theme.font.color.tertiary};
gap: ${({ theme }) => theme.spacing(1)};
padding: ${({ theme }) => theme.spacing(1)} 0;
transition: color ${({ theme }) => theme.animation.duration.normal}s;
color: ${themeCssVariables.font.color.tertiary};
gap: ${themeCssVariables.spacing[1]};
padding: ${themeCssVariables.spacing[1]} 0;
transition: color calc(${themeCssVariables.animation.duration.normal} * 1s);
&:hover {
color: ${({ isExpandable, theme }) =>
isExpandable ? theme.font.color.secondary : theme.font.color.tertiary};
color: ${({ isExpandable }) =>
isExpandable
? themeCssVariables.font.color.secondary
: themeCssVariables.font.color.tertiary};
}
`;
const StyledDisplayMessage = styled.span`
color: ${({ theme }) => theme.font.color.tertiary};
font-size: ${({ theme }) => theme.font.size.md};
font-weight: ${({ theme }) => theme.font.weight.medium};
color: ${themeCssVariables.font.color.tertiary};
font-size: ${themeCssVariables.font.size.md};
font-weight: ${themeCssVariables.font.weight.medium};
`;
const StyledIconTextContainer = styled.div`
display: flex;
align-items: center;
gap: ${({ theme }) => theme.spacing(1)};
gap: ${themeCssVariables.spacing[1]};
svg {
min-width: ${({ theme }) => theme.icon.size.sm}px;
min-width: calc(${themeCssVariables.icon.size.sm} * 1px);
}
`;
const StyledContentContainer = styled.div`
background: ${({ theme }) => theme.background.transparent.lighter};
border: 1px solid ${({ theme }) => theme.border.color.light};
border-radius: ${({ theme }) => theme.border.radius.sm};
background: ${themeCssVariables.background.transparent.lighter};
border: 1px solid ${themeCssVariables.border.color.light};
border-radius: ${themeCssVariables.border.radius.sm};
min-width: 0;
padding: ${({ theme }) => theme.spacing(3)};
padding: ${themeCssVariables.spacing[3]};
`;
export const RoutingStatusDisplay = ({
@@ -59,7 +62,7 @@ export const RoutingStatusDisplay = ({
}: {
data: DataMessagePart['routing-status'];
}) => {
const theme = useTheme();
const { theme } = useContext(ThemeContext);
const [isExpanded, setIsExpanded] = useState(false);
const isLoading = data.state === 'loading';
const isDebugMode = process.env.IS_DEBUG_MODE === 'true';
@@ -1,12 +1,13 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { themeCssVariables } from 'twenty-ui/theme-constants';
const StyledShimmeringText = styled.div`
background: ${({ theme }) => theme.font.color.light}
background: ${themeCssVariables.font.color.light}
linear-gradient(
90deg,
${({ theme }) => theme.font.color.light} 0%,
${({ theme }) => theme.font.color.primary} 50%,
${({ theme }) => theme.font.color.light} 100%
${themeCssVariables.font.color.light} 0%,
${themeCssVariables.font.color.primary} 50%,
${themeCssVariables.font.color.light} 100%
);
background-size: 200% 100%;
background-position: -200% top;
@@ -1,88 +1,94 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { useLingui } from '@lingui/react/macro';
import { useState } from 'react';
import { IconCopy, IconTerminal } from 'twenty-ui/display';
import { LightIconButton } from 'twenty-ui/input';
import { themeCssVariables } from 'twenty-ui/theme-constants';
import { useCopyToClipboard } from '~/hooks/useCopyToClipboard';
const StyledContainer = styled.div`
display: flex;
flex-direction: column;
border-radius: ${({ theme }) => theme.border.radius.sm};
border-radius: ${themeCssVariables.border.radius.sm};
overflow: hidden;
`;
const StyledHeader = styled.div`
align-items: center;
background: ${({ theme }) => theme.background.tertiary};
border-bottom: 1px solid ${({ theme }) => theme.border.color.medium};
background: ${themeCssVariables.background.tertiary};
border-bottom: 1px solid ${themeCssVariables.border.color.medium};
display: flex;
gap: ${({ theme }) => theme.spacing(2)};
gap: ${themeCssVariables.spacing[2]};
justify-content: space-between;
padding: ${({ theme }) => theme.spacing(1)} ${({ theme }) => theme.spacing(2)};
padding: ${themeCssVariables.spacing[1]} ${themeCssVariables.spacing[2]};
`;
const StyledHeaderLeft = styled.div`
align-items: center;
color: ${({ theme }) => theme.font.color.secondary};
color: ${themeCssVariables.font.color.secondary};
display: flex;
font-size: ${({ theme }) => theme.font.size.sm};
gap: ${({ theme }) => theme.spacing(1)};
font-size: ${themeCssVariables.font.size.sm};
gap: ${themeCssVariables.spacing[1]};
`;
const StyledTabContainer = styled.div`
display: flex;
gap: ${({ theme }) => theme.spacing(1)};
gap: ${themeCssVariables.spacing[1]};
`;
const StyledTab = styled.button<{ isActive: boolean; hasError?: boolean }>`
background: ${({ isActive, theme }) =>
isActive ? theme.background.secondary : 'transparent'};
background: ${({ isActive }) =>
isActive ? themeCssVariables.background.secondary : 'transparent'};
border: none;
border-radius: ${({ theme }) => theme.border.radius.xs};
color: ${({ isActive, hasError, theme }) =>
border-radius: ${themeCssVariables.border.radius.xs};
color: ${({ isActive, hasError }) =>
hasError
? theme.color.red
? themeCssVariables.color.red
: isActive
? theme.font.color.primary
: theme.font.color.tertiary};
? themeCssVariables.font.color.primary
: themeCssVariables.font.color.tertiary};
cursor: pointer;
font-size: ${({ theme }) => theme.font.size.xs};
font-weight: ${({ isActive, theme }) =>
isActive ? theme.font.weight.medium : theme.font.weight.regular};
padding: ${({ theme }) => theme.spacing(0.5)}
${({ theme }) => theme.spacing(1)};
font-size: ${themeCssVariables.font.size.xs};
font-weight: ${({ isActive }) =>
isActive
? themeCssVariables.font.weight.medium
: themeCssVariables.font.weight.regular};
padding: ${themeCssVariables.spacing['0.5']} ${themeCssVariables.spacing[1]};
&:hover {
background: ${({ theme }) => theme.background.secondary};
color: ${({ hasError, theme }) =>
hasError ? theme.color.red : theme.font.color.primary};
background: ${themeCssVariables.background.secondary};
color: ${({ hasError }) =>
hasError
? themeCssVariables.color.red
: themeCssVariables.font.color.primary};
}
`;
const StyledOutputArea = styled.div<{ isError?: boolean }>`
background: ${({ theme }) => theme.background.tertiary};
color: ${({ isError, theme }) =>
isError ? theme.color.red : theme.font.color.primary};
background: ${themeCssVariables.background.tertiary};
color: ${({ isError }) =>
isError
? themeCssVariables.color.red
: themeCssVariables.font.color.primary};
font-family: 'SF Mono', 'Monaco', 'Inconsolata', 'Roboto Mono', monospace;
font-size: ${({ theme }) => theme.font.size.sm};
font-size: ${themeCssVariables.font.size.sm};
line-height: 1.5;
max-height: 300px;
min-height: 100px;
overflow-y: auto;
padding: ${({ theme }) => theme.spacing(2)};
padding: ${themeCssVariables.spacing[2]};
white-space: pre-wrap;
word-break: break-word;
`;
const StyledEmptyMessage = styled.div`
color: ${({ theme }) => theme.font.color.tertiary};
color: ${themeCssVariables.font.color.tertiary};
font-style: italic;
`;
const StyledCursor = styled.span`
animation: blink 1s step-end infinite;
background: ${({ theme }) => theme.font.color.primary};
background: ${themeCssVariables.font.color.primary};
display: inline-block;
height: 1em;
margin-left: 2px;
@@ -1,4 +1,4 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { plural, t } from '@lingui/core/macro';
import { useState } from 'react';
import { type ToolUIPart } from 'ai';
@@ -12,6 +12,7 @@ import {
} from 'twenty-ui/display';
import { JsonTree } from 'twenty-ui/json-visualizer';
import { AnimatedExpandableContainer } from 'twenty-ui/layout';
import { themeCssVariables } from 'twenty-ui/theme-constants';
import { type JsonValue } from 'type-fest';
import { ToolOutputResultSchema } from '@/ai/schemas/toolOutputResultSchema';
@@ -32,184 +33,190 @@ import { useCopyToClipboard } from '~/hooks/useCopyToClipboard';
const StyledContainer = styled.div`
display: flex;
flex-direction: column;
font-family: ${({ theme }) => theme.font.family};
gap: ${({ theme }) => theme.spacing(1)};
font-family: ${themeCssVariables.font.family};
gap: ${themeCssVariables.spacing[1]};
`;
const StyledStepsContentContainer = styled.div`
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(1)};
padding-top: ${({ theme }) => theme.spacing(1)};
padding-bottom: ${({ theme }) => theme.spacing(2)};
gap: ${themeCssVariables.spacing[1]};
padding-top: ${themeCssVariables.spacing[1]};
padding-bottom: ${themeCssVariables.spacing[2]};
`;
const StyledSummaryText = styled.span`
color: inherit;
font-size: ${({ theme }) => theme.font.size.md};
font-weight: ${({ theme }) => theme.font.weight.regular};
line-height: ${({ theme }) => theme.text.lineHeight.md};
transition: color ${({ theme }) => theme.animation.duration.fast}s ease-in-out;
font-size: ${themeCssVariables.font.size.md};
font-weight: ${themeCssVariables.font.weight.regular};
line-height: ${themeCssVariables.text.lineHeight.md};
transition: color calc(${themeCssVariables.animation.duration.fast} * 1s)
ease-in-out;
`;
const StyledSummaryButton = styled.button`
align-items: center;
background: none;
border: none;
border-radius: ${({ theme }) => theme.border.radius.sm};
color: ${({ theme }) => theme.font.color.tertiary};
border-radius: ${themeCssVariables.border.radius.sm};
color: ${themeCssVariables.font.color.tertiary};
cursor: pointer;
display: flex;
font-family: inherit;
gap: ${({ theme }) => theme.spacing(2)};
gap: ${themeCssVariables.spacing[2]};
min-height: 24px;
padding: 0;
width: fit-content;
&:hover {
color: ${({ theme }) => theme.font.color.primary};
color: ${themeCssVariables.font.color.primary};
}
&:focus-visible {
outline: 2px solid ${({ theme }) => theme.color.blue};
outline: 2px solid ${themeCssVariables.color.blue};
outline-offset: 2px;
}
`;
const StyledSummaryChevronContainer = styled.div<{ isExpanded: boolean }>`
align-items: center;
color: ${({ theme }) => theme.font.color.light};
color: ${themeCssVariables.font.color.light};
display: flex;
justify-content: center;
transform: rotate(${({ isExpanded }) => (isExpanded ? '90deg' : '0deg')});
transition: transform ${({ theme }) => theme.animation.duration.fast}s
transition: transform calc(${themeCssVariables.animation.duration.fast} * 1s)
ease-in-out;
`;
const StyledRowsContainer = styled.div`
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(1)};
gap: ${themeCssVariables.spacing[1]};
`;
const StyledRow = styled.div`
align-items: center;
color: ${({ theme }) => theme.font.color.tertiary};
color: ${themeCssVariables.font.color.tertiary};
display: flex;
gap: ${({ theme }) => theme.spacing(2)};
gap: ${themeCssVariables.spacing[2]};
min-height: 24px;
`;
const StyledRowLabel = styled.span`
color: inherit;
font-size: ${({ theme }) => theme.font.size.md};
font-weight: ${({ theme }) => theme.font.weight.regular};
line-height: ${({ theme }) => theme.text.lineHeight.md};
transition: color ${({ theme }) => theme.animation.duration.fast}s ease-in-out;
font-size: ${themeCssVariables.font.size.md};
font-weight: ${themeCssVariables.font.weight.regular};
line-height: ${themeCssVariables.text.lineHeight.md};
transition: color calc(${themeCssVariables.animation.duration.fast} * 1s)
ease-in-out;
`;
const StyledToolRowLabel = styled.div`
color: inherit;
font-size: ${({ theme }) => theme.font.size.md};
font-weight: ${({ theme }) => theme.font.weight.regular};
line-height: ${({ theme }) => theme.text.lineHeight.md};
font-size: ${themeCssVariables.font.size.md};
font-weight: ${themeCssVariables.font.weight.regular};
line-height: ${themeCssVariables.text.lineHeight.md};
max-width: 100%;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
transition: color ${({ theme }) => theme.animation.duration.fast}s ease-in-out;
transition: color calc(${themeCssVariables.animation.duration.fast} * 1s)
ease-in-out;
white-space: nowrap;
`;
const StyledReasoningContainer = styled.div`
padding-left: calc(
${({ theme }) => theme.icon.size.sm}px + ${({ theme }) => theme.spacing(2)}
${themeCssVariables.icon.size.sm} * 1px + ${themeCssVariables.spacing[2]}
);
`;
const StyledReasoningText = styled.p`
color: ${({ theme }) => theme.font.color.tertiary};
font-size: ${({ theme }) => theme.font.size.md};
font-weight: ${({ theme }) => theme.font.weight.regular};
line-height: ${({ theme }) => theme.text.lineHeight.lg};
color: ${themeCssVariables.font.color.tertiary};
font-size: ${themeCssVariables.font.size.md};
font-weight: ${themeCssVariables.font.weight.regular};
line-height: ${themeCssVariables.text.lineHeight.lg};
margin: 0;
white-space: pre-wrap;
`;
const StyledOrbitLoaderIcon = styled(ThinkingOrbitLoaderIcon)`
color: ${({ theme }) => theme.font.color.tertiary};
color: ${themeCssVariables.font.color.tertiary};
`;
const StyledIconContainer = styled.div`
align-items: center;
color: ${({ theme }) => theme.font.color.light};
color: ${themeCssVariables.font.color.light};
display: flex;
justify-content: center;
min-width: ${({ theme }) => theme.icon.size.sm}px;
min-width: calc(${themeCssVariables.icon.size.sm} * 1px);
`;
const StyledRowLabelContainer = styled.div`
align-items: center;
display: flex;
flex: 1;
gap: ${({ theme }) => theme.spacing(1)};
gap: ${themeCssVariables.spacing[1]};
min-width: 0;
`;
const StyledChevronContainer = styled.div<{ isExpanded: boolean }>`
align-items: center;
color: ${({ theme }) => theme.font.color.light};
color: ${themeCssVariables.font.color.light};
display: flex;
justify-content: center;
transform: rotate(${({ isExpanded }) => (isExpanded ? '90deg' : '0deg')});
transition: transform ${({ theme }) => theme.animation.duration.fast}s
transition: transform calc(${themeCssVariables.animation.duration.fast} * 1s)
ease-in-out;
`;
const StyledToolRowContainer = styled.div`
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(1)};
gap: ${themeCssVariables.spacing[1]};
`;
const StyledToolRowButton = styled.button<{ isExpandable: boolean }>`
align-items: center;
background: none;
border: none;
color: ${({ theme }) => theme.font.color.tertiary};
color: ${themeCssVariables.font.color.tertiary};
cursor: ${({ isExpandable }) => (isExpandable ? 'pointer' : 'default')};
display: flex;
font-family: inherit;
gap: ${({ theme }) => theme.spacing(2)};
gap: ${themeCssVariables.spacing[2]};
min-height: 24px;
padding: 0;
text-align: left;
transition: color ${({ theme }) => theme.animation.duration.fast}s ease-in-out;
transition: color calc(${themeCssVariables.animation.duration.fast} * 1s)
ease-in-out;
width: 100%;
&:hover {
color: ${({ theme, isExpandable }) =>
isExpandable ? theme.font.color.primary : theme.font.color.tertiary};
color: ${({ isExpandable }) =>
isExpandable
? themeCssVariables.font.color.primary
: themeCssVariables.font.color.tertiary};
}
&:focus-visible {
outline: 2px solid ${({ theme }) => theme.color.blue};
outline: 2px solid ${themeCssVariables.color.blue};
outline-offset: 2px;
}
`;
const StyledToolDetailsContainer = styled.div`
background: ${({ theme }) => theme.background.transparent.lighter};
border: 1px solid ${({ theme }) => theme.border.color.light};
border-radius: ${({ theme }) => theme.border.radius.sm};
margin-left: ${({ theme }) => theme.spacing(3)};
background: ${themeCssVariables.background.transparent.lighter};
border: 1px solid ${themeCssVariables.border.color.light};
border-radius: ${themeCssVariables.border.radius.sm};
margin-left: ${themeCssVariables.spacing[3]};
min-width: 0;
overflow: hidden;
`;
const StyledToolTabList = styled(TabList)`
background-color: ${({ theme }) => theme.background.secondary};
padding-left: ${({ theme }) => theme.spacing(1)};
background-color: ${themeCssVariables.background.secondary};
padding-left: ${themeCssVariables.spacing[1]};
`;
const StyledToolDetailsContent = styled.div`
@@ -217,11 +224,11 @@ const StyledToolDetailsContent = styled.div`
`;
const StyledToolJsonContent = styled.div`
padding: ${({ theme }) => theme.spacing(1)};
padding: ${themeCssVariables.spacing[1]};
`;
const StyledJsonTreeContainer = styled.div`
font-size: ${({ theme }) => theme.font.size.md};
font-size: ${themeCssVariables.font.size.md};
overflow-x: auto;
li,
@@ -235,10 +242,10 @@ const StyledJsonTreeContainer = styled.div`
`;
const StyledToolErrorText = styled.p`
color: ${({ theme }) => theme.font.color.tertiary};
font-size: ${({ theme }) => theme.font.size.md};
font-weight: ${({ theme }) => theme.font.weight.regular};
line-height: ${({ theme }) => theme.text.lineHeight.lg};
color: ${themeCssVariables.font.color.tertiary};
font-size: ${themeCssVariables.font.size.md};
font-weight: ${themeCssVariables.font.weight.regular};
line-height: ${themeCssVariables.text.lineHeight.lg};
margin: 0;
white-space: pre-wrap;
`;
@@ -1,10 +1,11 @@
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { useState } from 'react';
import { styled } from '@linaria/react';
import { useContext, useState } from 'react';
import { IconChevronDown, IconChevronUp } from 'twenty-ui/display';
import { JsonTree } from 'twenty-ui/json-visualizer';
import { AnimatedExpandableContainer } from 'twenty-ui/layout';
import { ThemeContext } from 'twenty-ui/theme';
import { themeCssVariables } from 'twenty-ui/theme-constants';
import { CodeExecutionDisplay } from '@/ai/components/CodeExecutionDisplay';
import { ShimmeringText } from '@/ai/components/ShimmeringText';
@@ -24,16 +25,16 @@ import { useCopyToClipboard } from '~/hooks/useCopyToClipboard';
const StyledContainer = styled.div`
display: flex;
flex-direction: column;
font-family: ${({ theme }) => theme.font.family};
gap: ${({ theme }) => theme.spacing(2)};
font-family: ${themeCssVariables.font.family};
gap: ${themeCssVariables.spacing[2]};
`;
const StyledContentContainer = styled.div`
background: ${({ theme }) => theme.background.transparent.lighter};
border: 1px solid ${({ theme }) => theme.border.color.light};
border-radius: ${({ theme }) => theme.border.radius.sm};
background: ${themeCssVariables.background.transparent.lighter};
border: 1px solid ${themeCssVariables.border.color.light};
border-radius: ${themeCssVariables.border.radius.sm};
min-width: 0;
padding: ${({ theme }) => theme.spacing(3)};
padding: ${themeCssVariables.spacing[3]};
`;
const StyledJsonTreeContainer = styled.div`
@@ -50,75 +51,80 @@ const StyledToggleButton = styled.div<{ isExpandable: boolean }>`
border: none;
cursor: ${({ isExpandable }) => (isExpandable ? 'pointer' : 'auto')};
display: flex;
color: ${({ theme }) => theme.font.color.tertiary};
gap: ${({ theme }) => theme.spacing(1)};
padding: ${({ theme }) => theme.spacing(1)} 0;
transition: color ${({ theme }) => theme.animation.duration.fast}s ease-in-out;
color: ${themeCssVariables.font.color.tertiary};
gap: ${themeCssVariables.spacing[1]};
padding: ${themeCssVariables.spacing[1]} 0;
transition: color calc(${themeCssVariables.animation.duration.fast} * 1s)
ease-in-out;
justify-content: space-between;
width: 100%;
&:hover {
color: ${({ theme }) => theme.font.color.primary};
color: ${themeCssVariables.font.color.primary};
}
`;
const StyledToolName = styled.span`
background: ${({ theme }) => theme.background.transparent.light};
border-radius: ${({ theme }) => theme.border.radius.xs};
color: ${({ theme }) => theme.font.color.light};
font-family: ${({ theme }) => theme.font.family};
font-size: ${({ theme }) => theme.font.size.xs};
padding: ${({ theme }) => theme.spacing(0.5)}
${({ theme }) => theme.spacing(1)};
background: ${themeCssVariables.background.transparent.light};
border-radius: ${themeCssVariables.border.radius.xs};
color: ${themeCssVariables.font.color.light};
font-family: ${themeCssVariables.font.family};
font-size: ${themeCssVariables.font.size.xs};
padding: ${themeCssVariables.spacing['0.5']} ${themeCssVariables.spacing[1]};
`;
const StyledLeftContent = styled.div`
display: flex;
align-items: center;
gap: ${({ theme }) => theme.spacing(1)};
gap: ${themeCssVariables.spacing[1]};
`;
const StyledRightContent = styled.div`
display: flex;
align-items: center;
gap: ${({ theme }) => theme.spacing(2)};
gap: ${themeCssVariables.spacing[2]};
`;
const StyledDisplayMessage = styled.span`
color: ${({ theme }) => theme.font.color.tertiary};
font-size: ${({ theme }) => theme.font.size.md};
font-weight: ${({ theme }) => theme.font.weight.medium};
color: ${themeCssVariables.font.color.tertiary};
font-size: ${themeCssVariables.font.size.md};
font-weight: ${themeCssVariables.font.weight.medium};
`;
const StyledIconTextContainer = styled.div`
display: flex;
align-items: center;
gap: ${({ theme }) => theme.spacing(1)};
gap: ${themeCssVariables.spacing[1]};
svg {
min-width: ${({ theme }) => theme.icon.size.sm}px;
min-width: calc(${themeCssVariables.icon.size.sm} * 1px);
}
`;
const StyledTabContainer = styled.div`
border-bottom: 1px solid ${({ theme }) => theme.border.color.light};
border-bottom: 1px solid ${themeCssVariables.border.color.light};
display: flex;
gap: ${({ theme }) => theme.spacing(3)};
margin-bottom: ${({ theme }) => theme.spacing(3)};
gap: ${themeCssVariables.spacing[3]};
margin-bottom: ${themeCssVariables.spacing[3]};
`;
const StyledTab = styled.div<{ isActive: boolean }>`
color: ${({ theme, isActive }) =>
isActive ? theme.font.color.primary : theme.font.color.tertiary};
font-size: ${({ theme }) => theme.font.size.sm};
font-weight: ${({ theme, isActive }) =>
isActive ? theme.font.weight.medium : theme.font.weight.regular};
color: ${({ isActive }) =>
isActive
? themeCssVariables.font.color.primary
: themeCssVariables.font.color.tertiary};
font-size: ${themeCssVariables.font.size.sm};
font-weight: ${({ isActive }) =>
isActive
? themeCssVariables.font.weight.medium
: themeCssVariables.font.weight.regular};
cursor: pointer;
transition: color ${({ theme }) => theme.animation.duration.fast}s ease-in-out;
padding-bottom: ${({ theme }) => theme.spacing(2)};
transition: color calc(${themeCssVariables.animation.duration.fast} * 1s)
ease-in-out;
padding-bottom: ${themeCssVariables.spacing[2]};
&:hover {
color: ${({ theme }) => theme.font.color.primary};
color: ${themeCssVariables.font.color.primary};
}
`;
@@ -132,7 +138,7 @@ export const ToolStepRenderer = ({
isStreaming: boolean;
}) => {
const { t } = useLingui();
const theme = useTheme();
const { theme } = useContext(ThemeContext);
const { copyToClipboard } = useCopyToClipboard();
const [isExpanded, setIsExpanded] = useState(false);
const [activeTab, setActiveTab] = useState<TabType>('output');
@@ -200,7 +206,6 @@ export const ToolStepRenderer = ({
);
}
// For execute_tool, the actual result is nested inside output.result
const outputResult = ToolOutputResultSchema.safeParse(output);
const unwrappedOutput =
rawToolName === 'execute_tool' && outputResult.success
@@ -1,4 +1,4 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { type Meta, type StoryObj } from '@storybook/react-vite';
import { userEvent, within } from 'storybook/test';
import { type ExtendedUIMessage } from 'twenty-shared/ai';
@@ -1,4 +1,3 @@
import { ThemeProvider as EmotionThemeProvider } from '@emotion/react';
import { render, screen } from '@testing-library/react';
import { THEME_LIGHT, ThemeContextProvider } from 'twenty-ui/theme';
import { type ExtendedUIMessagePart } from 'twenty-shared/ai';
@@ -43,14 +42,12 @@ jest.mock('@/ai/components/CodeExecutionDisplay', () => ({
const renderAssistantRenderer = (messageParts: ExtendedUIMessagePart[]) => {
return render(
<EmotionThemeProvider theme={THEME_LIGHT}>
<ThemeContextProvider theme={THEME_LIGHT}>
<AIChatAssistantMessageRenderer
messageParts={messageParts}
isLastMessageStreaming={false}
/>
</ThemeContextProvider>
</EmotionThemeProvider>,
<ThemeContextProvider theme={THEME_LIGHT}>
<AIChatAssistantMessageRenderer
messageParts={messageParts}
isLastMessageStreaming={false}
/>
</ThemeContextProvider>,
);
};
@@ -1,4 +1,3 @@
import { ThemeProvider as EmotionThemeProvider } from '@emotion/react';
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { THEME_LIGHT, ThemeContextProvider } from 'twenty-ui/theme';
@@ -81,15 +80,13 @@ const renderThinkingStepsDisplay = ({
hasAssistantTextResponseStarted?: boolean;
}) => {
return render(
<EmotionThemeProvider theme={THEME_LIGHT}>
<ThemeContextProvider theme={THEME_LIGHT}>
<ThinkingStepsDisplay
parts={parts}
isLastMessageStreaming={isLastMessageStreaming}
hasAssistantTextResponseStarted={hasAssistantTextResponseStarted}
/>
</ThemeContextProvider>
</EmotionThemeProvider>,
<ThemeContextProvider theme={THEME_LIGHT}>
<ThinkingStepsDisplay
parts={parts}
isLastMessageStreaming={isLastMessageStreaming}
hasAssistantTextResponseStarted={hasAssistantTextResponseStarted}
/>
</ThemeContextProvider>,
);
};
@@ -1,11 +1,12 @@
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { t } from '@lingui/core/macro';
import { useLingui } from '@lingui/react/macro';
import { useState } from 'react';
import { useContext, useState } from 'react';
import { isDefined } from 'twenty-shared/utils';
import { HorizontalSeparator } from 'twenty-ui/display';
import { ProgressBar } from 'twenty-ui/feedback';
import { ThemeContext } from 'twenty-ui/theme';
import { themeCssVariables } from 'twenty-ui/theme-constants';
import { ContextUsageProgressRing } from '@/ai/components/internal/ContextUsageProgressRing';
import { SettingsBillingLabelValueItem } from '@/billing/components/internal/SettingsBillingLabelValueItem';
@@ -26,31 +27,34 @@ const StyledTrigger = styled.div<{ hasUsage: boolean }>`
height: 24px;
justify-content: center;
min-width: 24px;
transition: background ${({ theme }) => theme.animation.duration.fast}s ease;
transition: background calc(${themeCssVariables.animation.duration.fast} * 1s)
ease;
&:hover {
background: ${({ theme, hasUsage }) =>
hasUsage ? theme.background.transparent.light : 'transparent'};
background: ${({ hasUsage }) =>
hasUsage
? themeCssVariables.background.transparent.light
: 'transparent'};
}
`;
const StyledHoverCard = styled.div`
background: ${({ theme }) => theme.background.primary};
border: 1px solid ${({ theme }) => theme.border.color.medium};
border-radius: ${({ theme }) => theme.border.radius.md};
box-shadow: ${({ theme }) => theme.boxShadow.strong};
background: ${themeCssVariables.background.primary};
border: 1px solid ${themeCssVariables.border.color.medium};
border-radius: ${themeCssVariables.border.radius.md};
box-shadow: ${themeCssVariables.boxShadow.strong};
min-width: 280px;
position: absolute;
left: 0;
bottom: calc(100% + 8px);
z-index: ${({ theme }) => theme.lastLayerZIndex};
z-index: ${themeCssVariables.lastLayerZIndex};
`;
const StyledSection = styled.div`
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(2)};
padding: ${({ theme }) => theme.spacing(3)};
gap: ${themeCssVariables.spacing[2]};
padding: ${themeCssVariables.spacing[3]};
`;
const StyledRow = styled.div`
@@ -60,16 +64,16 @@ const StyledRow = styled.div`
`;
const StyledContextWindowValue = styled.span`
color: ${({ theme }) => theme.font.color.secondary};
font-size: ${({ theme }) => theme.font.size.sm};
font-weight: ${({ theme }) => theme.font.weight.medium};
color: ${themeCssVariables.font.color.secondary};
font-size: ${themeCssVariables.font.size.sm};
font-weight: ${themeCssVariables.font.weight.medium};
`;
const StyledSectionTitle = styled.span`
color: ${({ theme }) => theme.font.color.primary};
font-size: ${({ theme }) => theme.font.size.xs};
font-weight: ${({ theme }) => theme.font.weight.semiBold};
padding-bottom: ${({ theme }) => theme.spacing(2)};
color: ${themeCssVariables.font.color.primary};
font-size: ${themeCssVariables.font.size.xs};
font-weight: ${themeCssVariables.font.weight.semiBold};
padding-bottom: ${themeCssVariables.spacing[2]};
`;
const formatTokenCount = (count: number): string => {
@@ -86,8 +90,6 @@ const formatTokenCount = (count: number): string => {
};
const formatCredits = (credits: number): string => {
// Credits are already in display units from the API (internal / 1000)
// Show up to 1 decimal for fractional values, none for whole numbers
if (Number.isInteger(credits)) {
return credits.toLocaleString();
}
@@ -112,7 +114,7 @@ const getCachedLabel = (lastMessage: AgentChatLastMessageUsage): string => {
export const AIChatContextUsageButton = () => {
const { t } = useLingui();
const theme = useTheme();
const { theme } = useContext(ThemeContext);
const [isHovered, setIsHovered] = useState(false);
const agentChatUsage = useAtomStateValue(agentChatUsageState);
@@ -1,19 +1,21 @@
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 StyledSkeletonContainer = styled.div`
display: flex;
flex: 1;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(6)};
padding: ${({ theme }) => theme.spacing(3)};
gap: ${themeCssVariables.spacing[6]};
padding: ${themeCssVariables.spacing[3]};
`;
const StyledMessageBubble = styled.div`
align-items: center;
display: flex;
gap: ${({ theme }) => theme.spacing(3)};
gap: ${themeCssVariables.spacing[3]};
`;
const StyledMessageSkeleton = styled.div`
@@ -23,7 +25,7 @@ const StyledMessageSkeleton = styled.div`
const NUMBER_OF_SKELETONS = 6;
export const AIChatSkeletonLoader = () => {
const theme = useTheme();
const { theme } = useContext(ThemeContext);
return (
<SkeletonTheme
@@ -1,13 +1,14 @@
import { agentChatSelectedFilesState } from '@/ai/states/agentChatSelectedFilesState';
import { agentChatUploadedFilesState } from '@/ai/states/agentChatUploadedFilesState';
import { useAtomState } from '@/ui/utilities/state/jotai/hooks/useAtomState';
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { themeCssVariables } from 'twenty-ui/theme-constants';
import { AgentChatFilePreview } from './AgentChatFilePreview';
const StyledContainer = styled.div`
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(1)};
gap: ${themeCssVariables.spacing[1]};
width: 100%;
`;
@@ -15,7 +16,7 @@ const StyledPreviewsContainer = styled.div`
display: flex;
flex-direction: row;
flex-wrap: wrap;
gap: ${({ theme }) => theme.spacing(1)};
gap: ${themeCssVariables.spacing[1]};
`;
export const AgentChatContextPreview = () => {
@@ -2,8 +2,8 @@ import { type AttachmentFileCategory } from '@/activities/files/types/Attachment
import { getFileType } from '@/activities/files/utils/getFileType';
import { useFileCategoryColors } from '@/file/hooks/useFileCategoryColors';
import { IconMapping } from '@/file/utils/fileIconMappings';
import { useTheme } from '@emotion/react';
import { t } from '@lingui/core/macro';
import { useContext } from 'react';
import { type FileUIPart } from 'ai';
import { isDefined } from 'twenty-shared/utils';
import {
@@ -14,6 +14,7 @@ import {
} from 'twenty-ui/components';
import { type IconComponent, IconX } from 'twenty-ui/display';
import { Loader } from 'twenty-ui/feedback';
import { ThemeContext } from 'twenty-ui/theme';
export const AgentChatFilePreview = ({
file,
@@ -24,7 +25,7 @@ export const AgentChatFilePreview = ({
onRemove?: () => void;
isUploading?: boolean;
}) => {
const theme = useTheme();
const { theme } = useContext(ThemeContext);
const iconColors: Record<AttachmentFileCategory, string> =
useFileCategoryColors();
@@ -1,16 +1,17 @@
import { useAIChatFileUpload } from '@/ai/hooks/useAIChatFileUpload';
import { agentChatSelectedFilesState } from '@/ai/states/agentChatSelectedFilesState';
import { useSetAtomState } from '@/ui/utilities/state/jotai/hooks/useSetAtomState';
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { t } from '@lingui/core/macro';
import React, { useRef } from 'react';
import { IconPlus } from 'twenty-ui/display';
import { IconButton } from 'twenty-ui/input';
import { themeCssVariables } from 'twenty-ui/theme-constants';
const StyledFileUploadContainer = styled.div`
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(2)};
gap: ${themeCssVariables.spacing[2]};
`;
const StyledFileInput = styled.input`
@@ -1,5 +1,7 @@
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { useContext } from 'react';
import { ThemeContext } from 'twenty-ui/theme';
import { themeCssVariables } from 'twenty-ui/theme-constants';
type ContextUsageProgressRingProps = {
percentage: number;
@@ -15,8 +17,8 @@ const StyledBackgroundCircle = styled.circle`
fill: none;
stroke: color-mix(
in srgb,
${({ theme }) => theme.border.color.strong} 50%,
${({ theme }) => theme.background.quaternary} 50%
${themeCssVariables.border.color.strong} 50%,
${themeCssVariables.background.quaternary} 50%
);
`;
@@ -30,7 +32,7 @@ export const ContextUsageProgressRing = ({
size = 16,
strokeWidth = 2,
}: ContextUsageProgressRingProps) => {
const theme = useTheme();
const { theme } = useContext(ThemeContext);
const normalizedPercentage = Math.min(Math.max(percentage, 0), 100);
const radius = (size - strokeWidth) / 2;
@@ -1,8 +1,9 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { t } from '@lingui/core/macro';
import { useLingui } from '@lingui/react/macro';
import { type Editor } from '@tiptap/react';
import { LightButton } from 'twenty-ui/input';
import { themeCssVariables } from 'twenty-ui/theme-constants';
import {
DEFAULT_SUGGESTED_PROMPTS,
@@ -14,18 +15,18 @@ import { useSetAtomState } from '@/ui/utilities/state/jotai/hooks/useSetAtomStat
const StyledContainer = styled.div`
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(2)};
padding: ${({ theme }) => theme.spacing(2)};
gap: ${themeCssVariables.spacing[2]};
padding: ${themeCssVariables.spacing[2]};
`;
const StyledTitle = styled.div`
align-content: center;
color: ${({ theme }) => theme.font.color.primary};
color: ${themeCssVariables.font.color.primary};
display: grid;
font-size: ${({ theme }) => theme.font.size.sm};
font-weight: ${({ theme }) => theme.font.weight.medium};
font-size: ${themeCssVariables.font.size.sm};
font-weight: ${themeCssVariables.font.weight.medium};
height: 24px;
padding: ${({ theme }) => `0 ${theme.spacing(2)}`};
padding: 0 ${themeCssVariables.spacing[2]};
`;
const StyledSuggestedPromptButton = styled(LightButton)`
@@ -3,7 +3,7 @@ import { AUTH_MODAL_ID } from '@/auth/constants/AuthModalId';
import { getAuthModalConfig } from '@/auth/utils/getAuthModalConfig';
import { Modal } from '@/ui/layout/modal/components/Modal';
import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper';
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import React from 'react';
import { useLocation } from 'react-router-dom';
@@ -1,9 +1,10 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { isNonEmptyString } from '@sniptt/guards';
import { AppPath } from 'twenty-shared/types';
import { getImageAbsoluteURI, isDefined } from 'twenty-shared/utils';
import { Avatar } from 'twenty-ui/display';
import { UndecoratedLink } from 'twenty-ui/navigation';
import { themeCssVariables } from 'twenty-ui/theme-constants';
import { REACT_APP_SERVER_BASE_URL } from '~/config';
import { useRedirectToDefaultDomain } from '~/modules/domain-manager/hooks/useRedirectToDefaultDomain';
@@ -15,32 +16,32 @@ type LogoProps = {
};
const StyledContainer = styled.div`
height: ${({ theme }) => theme.spacing(12)};
margin-bottom: ${({ theme }) => theme.spacing(4)};
margin-top: ${({ theme }) => theme.spacing(4)};
height: ${themeCssVariables.spacing[12]};
margin-bottom: ${themeCssVariables.spacing[4]};
margin-top: ${themeCssVariables.spacing[4]};
position: relative;
width: ${({ theme }) => theme.spacing(12)};
width: ${themeCssVariables.spacing[12]};
`;
const StyledSecondaryLogo = styled.img`
border-radius: ${({ theme }) => theme.border.radius.xs};
height: ${({ theme }) => theme.spacing(6)};
width: ${({ theme }) => theme.spacing(6)};
border-radius: ${themeCssVariables.border.radius.xs};
height: ${themeCssVariables.spacing[6]};
width: ${themeCssVariables.spacing[6]};
`;
const StyledSecondaryLogoContainer = styled.div`
align-items: center;
background-color: ${({ theme }) => theme.background.primary};
border-radius: ${({ theme }) => theme.border.radius.sm};
bottom: ${({ theme }) => `-${theme.spacing(3)}`};
background-color: ${themeCssVariables.background.primary};
border-radius: ${themeCssVariables.border.radius.sm};
bottom: calc(-1 * ${themeCssVariables.spacing[3]});
display: flex;
height: ${({ theme }) => theme.spacing(7)};
height: ${themeCssVariables.spacing[7]};
justify-content: center;
position: absolute;
right: ${({ theme }) => `-${theme.spacing(3)}`};
width: ${({ theme }) => theme.spacing(7)};
right: calc(-1 * ${themeCssVariables.spacing[3]});
width: ${themeCssVariables.spacing[7]};
`;
const StyledPrimaryLogo = styled.div<{ src: string }>`
@@ -1,7 +1,8 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { themeCssVariables } from 'twenty-ui/theme-constants';
const StyledSubTitle = styled.div`
color: ${({ theme }) => theme.font.color.secondary};
color: ${themeCssVariables.font.color.secondary};
text-align: center;
`;
@@ -1,5 +1,6 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import React from 'react';
import { themeCssVariables } from 'twenty-ui/theme-constants';
import { AnimatedEaseIn } from 'twenty-ui/utilities';
type TitleProps = React.PropsWithChildren & {
@@ -8,12 +9,12 @@ type TitleProps = React.PropsWithChildren & {
};
const StyledTitle = styled.div<Pick<TitleProps, 'noMarginTop'>>`
color: ${({ theme }) => theme.font.color.primary};
font-size: ${({ theme }) => theme.font.size.xl};
font-weight: ${({ theme }) => theme.font.weight.semiBold};
margin-bottom: ${({ theme }) => theme.spacing(4)};
margin-top: ${({ theme, noMarginTop }) =>
!noMarginTop ? theme.spacing(4) : 0};
color: ${themeCssVariables.font.color.primary};
font-size: ${themeCssVariables.font.size.xl};
font-weight: ${themeCssVariables.font.weight.semiBold};
margin-bottom: ${themeCssVariables.spacing[4]};
margin-top: ${({ noMarginTop }) =>
!noMarginTop ? themeCssVariables.spacing[4] : '0'};
`;
export const Title = ({
@@ -1,4 +1,4 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { SubTitle } from '@/auth/components/SubTitle';
import { Title } from '@/auth/components/Title';
@@ -17,13 +17,14 @@ import {
IconMicrosoft,
} from 'twenty-ui/display';
import { MainButton } from 'twenty-ui/input';
import { themeCssVariables } from 'twenty-ui/theme-constants';
import { AnimatedEaseIn } from 'twenty-ui/utilities';
const StyledContainer = styled.div`
display: flex;
flex-direction: column;
align-items: center;
gap: ${({ theme }) => theme.spacing(8)};
gap: ${themeCssVariables.spacing[8]};
width: 100%;
`;
@@ -35,14 +36,14 @@ const StyledTextContainer = styled.div`
`;
const StyledEmail = styled.span`
font-weight: ${({ theme }) => theme.font.weight.medium};
font-weight: ${themeCssVariables.font.weight.medium};
`;
const StyledButtonsContainer = styled.div`
display: flex;
flex-direction: column;
align-items: center;
gap: ${({ theme }) => theme.spacing(3)};
gap: ${themeCssVariables.spacing[3]};
width: 100%;
max-width: 240px;
`;
@@ -51,22 +52,22 @@ const StyledBottomLinks = styled.div`
align-items: center;
display: flex;
flex-direction: row;
gap: ${({ theme }) => theme.spacing(2)};
gap: ${themeCssVariables.spacing[2]};
justify-content: center;
`;
const StyledLinkButton = styled.button`
background: none;
border: none;
font-family: ${({ theme }) => theme.font.family};
font-size: ${({ theme }) => theme.font.size.xs};
font-weight: ${({ theme }) => theme.font.weight.regular};
font-family: ${themeCssVariables.font.family};
font-size: ${themeCssVariables.font.size.xs};
font-weight: ${themeCssVariables.font.weight.regular};
line-height: 140%;
color: ${({ theme }) => theme.font.color.tertiary};
color: ${themeCssVariables.font.color.tertiary};
cursor: pointer;
&:hover {
color: ${({ theme }) => theme.font.color.secondary};
color: ${themeCssVariables.font.color.secondary};
}
&:disabled {
@@ -76,7 +77,7 @@ const StyledLinkButton = styled.button`
`;
const StyledDot = styled.div`
background: ${({ theme }) => theme.font.color.light};
background: ${themeCssVariables.font.color.light};
border-radius: 50%;
height: 2px;
width: 2px;
@@ -1,18 +1,19 @@
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { Trans } from '@lingui/react/macro';
import { useWorkspaceBypass } from '@/auth/sign-in-up/hooks/useWorkspaceBypass';
import { useIsCurrentLocationOnAWorkspace } from '@/domain-manager/hooks/useIsCurrentLocationOnAWorkspace';
import { themeCssVariables } from 'twenty-ui/theme-constants';
const StyledCopyContainer = styled.div`
align-items: center;
color: ${({ theme }) => theme.font.color.tertiary};
font-size: ${({ theme }) => theme.font.size.sm};
color: ${themeCssVariables.font.color.tertiary};
font-size: ${themeCssVariables.font.size.sm};
max-width: 280px;
text-align: center;
& > a {
color: ${({ theme }) => theme.font.color.tertiary};
color: ${themeCssVariables.font.color.tertiary};
text-decoration: none;
&:hover {
@@ -23,11 +24,11 @@ const StyledCopyContainer = styled.div`
const StyledLinksContainer = styled.div`
align-items: center;
color: ${({ theme }) => theme.font.color.tertiary};
color: ${themeCssVariables.font.color.tertiary};
display: flex;
flex-wrap: nowrap;
font-size: ${({ theme }) => theme.font.size.sm};
gap: ${({ theme }) => theme.spacing(2)};
font-size: ${themeCssVariables.font.size.sm};
gap: ${themeCssVariables.spacing[2]};
justify-content: center;
max-width: 100%;
text-align: center;
@@ -37,7 +38,7 @@ const StyledLinksContainer = styled.div`
& > button {
background: none;
border: none;
color: ${({ theme }) => theme.font.color.tertiary};
color: ${themeCssVariables.font.color.tertiary};
cursor: pointer;
font: inherit;
padding: 0;
@@ -50,7 +51,7 @@ const StyledLinksContainer = styled.div`
`;
const StyledSeparator = styled.span`
color: ${({ theme }) => theme.font.color.tertiary};
color: ${themeCssVariables.font.color.tertiary};
`;
export const FooterNote = () => {
@@ -1,10 +1,10 @@
import { availableWorkspacesState } from '@/auth/states/availableWorkspacesState';
import { returnToPathState } from '@/auth/states/returnToPathState';
import { useBuildWorkspaceUrl } from '@/domain-manager/hooks/useBuildWorkspaceUrl';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { Trans, useLingui } from '@lingui/react/macro';
import { motion } from 'framer-motion';
import { useContext } from 'react';
import { FormProvider } from 'react-hook-form';
import { ClickToActionLink, UndecoratedLink } from 'twenty-ui/navigation';
@@ -27,30 +27,32 @@ import {
IconChevronRight,
IconPlus,
} from 'twenty-ui/display';
import { ThemeContext } from 'twenty-ui/theme';
import { themeCssVariables } from 'twenty-ui/theme-constants';
import { type AvailableWorkspace } from '~/generated-metadata/graphql';
import { getWorkspaceUrl } from '~/utils/getWorkspaceUrl';
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
import { isNonEmptyString } from '@sniptt/guards';
const StyledContentContainer = styled(motion.div)`
margin-bottom: ${({ theme }) => theme.spacing(8)};
margin-top: ${({ theme }) => theme.spacing(4)};
margin-bottom: ${themeCssVariables.spacing[8]};
margin-top: ${themeCssVariables.spacing[4]};
min-width: 200px;
`;
const StyledWorkspaceContainer = styled.div`
background-color: ${({ theme }) => theme.background.secondary};
border: 1px solid ${({ theme }) => theme.border.color.light};
border-radius: ${({ theme }) => theme.border.radius.md};
background-color: ${themeCssVariables.background.secondary};
border: 1px solid ${themeCssVariables.border.color.light};
border-radius: ${themeCssVariables.border.radius.md};
display: flex;
flex-direction: column;
margin-bottom: ${({ theme }) => theme.spacing(8)};
margin-top: ${({ theme }) => theme.spacing(4)};
margin-bottom: ${themeCssVariables.spacing[8]};
margin-top: ${themeCssVariables.spacing[4]};
overflow: hidden;
width: 100%;
> * {
border-bottom: 1px solid ${({ theme }) => theme.border.color.medium};
border-bottom: 1px solid ${themeCssVariables.border.color.medium};
&:last-child {
border-bottom: none;
@@ -63,7 +65,7 @@ const StyledWorkspaceItem = styled.div`
flex-direction: row;
align-items: center;
width: 100%;
height: ${({ theme }) => theme.spacing(15)};
height: ${themeCssVariables.spacing[15]};
padding: 0;
overflow: hidden;
@@ -71,7 +73,7 @@ const StyledWorkspaceItem = styled.div`
justify-content: space-between;
&:hover {
background-color: ${({ theme }) => theme.background.transparent.light};
background-color: ${themeCssVariables.background.transparent.light};
}
&:last-child {
@@ -82,9 +84,9 @@ const StyledWorkspaceItem = styled.div`
const StyledWorkspaceContent = styled.div`
align-items: center;
display: flex;
gap: ${({ theme }) => theme.spacing(4)};
gap: ${themeCssVariables.spacing[4]};
width: 100%;
padding: 0 ${({ theme }) => theme.spacing(4)};
padding: 0 ${themeCssVariables.spacing[4]};
`;
const StyledWorkspaceTextContainer = styled.div`
@@ -94,29 +96,29 @@ const StyledWorkspaceTextContainer = styled.div`
`;
const StyledWorkspaceLogo = styled.div`
border-radius: ${({ theme }) => theme.border.radius.sm};
height: ${({ theme }) => theme.spacing(6)};
width: ${({ theme }) => theme.spacing(6)};
background-color: ${({ theme }) => theme.background.transparent.light};
border-radius: ${themeCssVariables.border.radius.sm};
height: ${themeCssVariables.spacing[6]};
width: ${themeCssVariables.spacing[6]};
background-color: ${themeCssVariables.background.transparent.light};
display: flex;
justify-content: center;
align-items: center;
`;
const StyledWorkspaceName = styled.div`
color: ${({ theme }) => theme.font.color.primary};
font-weight: ${({ theme }) => theme.font.weight.medium};
padding-bottom: ${({ theme }) => theme.spacing(1)};
color: ${themeCssVariables.font.color.primary};
font-weight: ${themeCssVariables.font.weight.medium};
padding-bottom: ${themeCssVariables.spacing[1]};
`;
const StyledWorkspaceUrl = styled.div`
color: ${({ theme }) => theme.font.color.tertiary};
font-size: ${({ theme }) => theme.font.size.xs};
color: ${themeCssVariables.font.color.tertiary};
font-size: ${themeCssVariables.font.size.xs};
`;
const StyledChevronIcon = styled.div`
align-items: center;
color: ${({ theme }) => theme.font.color.tertiary};
color: ${themeCssVariables.font.color.tertiary};
display: flex;
`;
@@ -133,7 +135,7 @@ export const SignInUpGlobalScopeForm = () => {
const { createWorkspace } = useSignUpInNewWorkspace();
const availableWorkspaces = useAtomStateValue(availableWorkspacesState);
const theme = useTheme();
const { theme } = useContext(ThemeContext);
const { t } = useLingui();
const { form } = useSignInUpForm();
@@ -9,16 +9,17 @@ import { useWorkspaceBypass } from '@/auth/sign-in-up/hooks/useWorkspaceBypass';
import { SignInUpStep } from '@/auth/states/signInUpStepState';
import { workspaceAuthBypassProvidersState } from '@/workspace/states/workspaceAuthBypassProvidersState';
import { workspaceAuthProvidersState } from '@/workspace/states/workspaceAuthProvidersState';
import styled from '@emotion/styled';
import { styled } from '@linaria/react';
import { Trans } from '@lingui/react/macro';
import { FormProvider } from 'react-hook-form';
import { HorizontalSeparator } from 'twenty-ui/display';
import { ClickToActionLink } from 'twenty-ui/navigation';
import { themeCssVariables } from 'twenty-ui/theme-constants';
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
const StyledContentContainer = styled.div`
margin-bottom: ${({ theme }) => theme.spacing(8)};
margin-top: ${({ theme }) => theme.spacing(4)};
margin-bottom: ${themeCssVariables.spacing[8]};
margin-top: ${themeCssVariables.spacing[4]};
min-width: 200px;
`;

Some files were not shown because too many files have changed in this diff Show More