diff --git a/packages/twenty-front/src/modules/activities/calendar/components/CalendarEventDetails.tsx b/packages/twenty-front/src/modules/activities/calendar/components/CalendarEventDetails.tsx
index 608e4cbc7..19d2e151f 100644
--- a/packages/twenty-front/src/modules/activities/calendar/components/CalendarEventDetails.tsx
+++ b/packages/twenty-front/src/modules/activities/calendar/components/CalendarEventDetails.tsx
@@ -127,7 +127,7 @@ export const CalendarEventDetails = ({
size={ChipSize.Large}
variant={ChipVariant.Highlighted}
clickable={false}
- leftComponent={() => }
+ leftComponent={}
label="Event"
/>
diff --git a/packages/twenty-front/src/modules/activities/emails/components/MessageThreadSubscribersChip.tsx b/packages/twenty-front/src/modules/activities/emails/components/MessageThreadSubscribersChip.tsx
index 47c575a80..e78e29159 100644
--- a/packages/twenty-front/src/modules/activities/emails/components/MessageThreadSubscribersChip.tsx
+++ b/packages/twenty-front/src/modules/activities/emails/components/MessageThreadSubscribersChip.tsx
@@ -1,8 +1,8 @@
import { MessageThreadSubscriber } from '@/activities/emails/types/MessageThreadSubscriber';
import { isNonEmptyString } from '@sniptt/guards';
import { useContext } from 'react';
-import { Avatar, AvatarGroup, IconChevronDown } from 'twenty-ui/display';
import { Chip, ChipVariant } from 'twenty-ui/components';
+import { Avatar, AvatarGroup, IconChevronDown } from 'twenty-ui/display';
import { ThemeContext } from 'twenty-ui/theme';
const MAX_NUMBER_OF_AVATARS = 3;
@@ -46,20 +46,16 @@ export const MessageThreadSubscribersChip = ({
{
- if (isOnlyOneSubscriber) {
- return (
-
- );
- }
-
- return (
+ leftComponent={
+ isOnlyOneSubscriber ? (
+
+ ) : (
(
))}
/>
- );
- }}
+ )
+ }
rightComponent={() => }
clickable
/>
diff --git a/packages/twenty-front/src/modules/apollo/hooks/useApolloFactory.ts b/packages/twenty-front/src/modules/apollo/hooks/useApolloFactory.ts
index ab47e4e81..8303dab65 100644
--- a/packages/twenty-front/src/modules/apollo/hooks/useApolloFactory.ts
+++ b/packages/twenty-front/src/modules/apollo/hooks/useApolloFactory.ts
@@ -16,8 +16,8 @@ import { useUpdateEffect } from '~/hooks/useUpdateEffect';
import { currentUserWorkspaceState } from '@/auth/states/currentUserWorkspaceState';
import { AppPath } from '@/types/AppPath';
-import { ApolloFactory, Options } from '../services/apollo.factory';
import { isDefined } from 'twenty-shared/utils';
+import { ApolloFactory, Options } from '../services/apollo.factory';
export const useApolloFactory = (options: Partial> = {}) => {
// eslint-disable-next-line @nx/workspace-no-state-useref
@@ -26,7 +26,7 @@ export const useApolloFactory = (options: Partial> = {}) => {
const navigate = useNavigate();
const { isMatchingLocation } = useIsMatchingLocation();
- const [tokenPair, setTokenPair] = useRecoilState(tokenPairState);
+ const setTokenPair = useSetRecoilState(tokenPairState);
const [currentWorkspace, setCurrentWorkspace] = useRecoilState(
currentWorkspaceState,
);
@@ -62,8 +62,6 @@ export const useApolloFactory = (options: Partial> = {}) => {
},
},
connectToDevTools: isDebugMode,
- // We don't want to re-create the client on token change or it will cause infinite loop
- initialTokenPair: tokenPair,
currentWorkspaceMember: currentWorkspaceMember,
onTokenPairChange: (tokenPair) => {
setTokenPair(tokenPair);
@@ -104,12 +102,6 @@ export const useApolloFactory = (options: Partial> = {}) => {
setPreviousUrl,
]);
- useUpdateEffect(() => {
- if (isDefined(apolloRef.current)) {
- apolloRef.current.updateTokenPair(tokenPair);
- }
- }, [tokenPair]);
-
useUpdateEffect(() => {
if (isDefined(apolloRef.current)) {
apolloRef.current.updateWorkspaceMember(currentWorkspaceMember);
diff --git a/packages/twenty-front/src/modules/apollo/services/__tests__/apollo.factory.test.ts b/packages/twenty-front/src/modules/apollo/services/__tests__/apollo.factory.test.ts
index c5daf63c7..60d49ac58 100644
--- a/packages/twenty-front/src/modules/apollo/services/__tests__/apollo.factory.test.ts
+++ b/packages/twenty-front/src/modules/apollo/services/__tests__/apollo.factory.test.ts
@@ -33,10 +33,6 @@ const mockWorkspaceMember = {
const createMockOptions = (): Options => ({
uri: 'http://localhost:3000',
- initialTokenPair: {
- accessToken: { token: 'mockAccessToken', expiresAt: '' },
- refreshToken: { token: 'mockRefreshToken', expiresAt: '' },
- },
currentWorkspaceMember: mockWorkspaceMember,
cache: new InMemoryCache(),
isDebugMode: true,
diff --git a/packages/twenty-front/src/modules/apollo/services/apollo.factory.ts b/packages/twenty-front/src/modules/apollo/services/apollo.factory.ts
index cc425813f..97192aa9c 100644
--- a/packages/twenty-front/src/modules/apollo/services/apollo.factory.ts
+++ b/packages/twenty-front/src/modules/apollo/services/apollo.factory.ts
@@ -18,9 +18,11 @@ import { logDebug } from '~/utils/logDebug';
import { i18n } from '@lingui/core';
import { GraphQLFormattedError } from 'graphql';
+import { isDefined } from 'twenty-shared/utils';
+import { cookieStorage } from '~/utils/cookie-storage';
+import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
import { ApolloManager } from '../types/apolloManager.interface';
import { loggerLink } from '../utils/loggerLink';
-import { isDefined } from 'twenty-shared/utils';
const logger = loggerLink(() => 'Twenty');
@@ -29,7 +31,6 @@ export interface Options extends ApolloClientOptions {
onNetworkError?: (err: Error | ServerParseError | ServerError) => void;
onTokenPairChange?: (tokenPair: AuthTokenPair) => void;
onUnauthenticatedError?: () => void;
- initialTokenPair: AuthTokenPair | null;
currentWorkspaceMember: CurrentWorkspaceMember | null;
extraLinks?: ApolloLink[];
isDebugMode?: boolean;
@@ -37,7 +38,6 @@ export interface Options extends ApolloClientOptions {
export class ApolloFactory implements ApolloManager {
private client: ApolloClient;
- private tokenPair: AuthTokenPair | null = null;
private currentWorkspaceMember: CurrentWorkspaceMember | null = null;
constructor(opts: Options) {
@@ -47,28 +47,45 @@ export class ApolloFactory implements ApolloManager {
onNetworkError,
onTokenPairChange,
onUnauthenticatedError,
- initialTokenPair,
currentWorkspaceMember,
extraLinks,
isDebugMode,
...options
} = opts;
- this.tokenPair = initialTokenPair;
this.currentWorkspaceMember = currentWorkspaceMember;
+ const getTokenPair = () => {
+ const stringTokenPair = cookieStorage.getItem('tokenPair');
+ const tokenPair = isDefined(stringTokenPair)
+ ? (JSON.parse(stringTokenPair) as AuthTokenPair)
+ : undefined;
+ return tokenPair;
+ };
+
const buildApolloLink = (): ApolloLink => {
const httpLink = createUploadLink({
uri,
});
const authLink = setContext(async (_, { headers }) => {
+ const tokenPair = getTokenPair();
+
+ if (isUndefinedOrNull(tokenPair)) {
+ return {
+ headers: {
+ ...headers,
+ ...options.headers,
+ },
+ };
+ }
+
return {
headers: {
...headers,
...options.headers,
- authorization: this.tokenPair?.accessToken.token
- ? `Bearer ${this.tokenPair?.accessToken.token}`
+ authorization: tokenPair.accessToken.token
+ ? `Bearer ${tokenPair.accessToken.token}`
: '',
...(this.currentWorkspaceMember?.locale
? { 'x-locale': this.currentWorkspaceMember.locale }
@@ -93,7 +110,7 @@ export class ApolloFactory implements ApolloManager {
for (const graphQLError of graphQLErrors) {
if (graphQLError.message === 'Unauthorized') {
return fromPromise(
- renewToken(uri, this.tokenPair)
+ renewToken(uri, getTokenPair())
.then((tokens) => {
if (isDefined(tokens)) {
onTokenPairChange?.(tokens);
@@ -108,10 +125,14 @@ export class ApolloFactory implements ApolloManager {
switch (graphQLError?.extensions?.code) {
case 'UNAUTHENTICATED': {
return fromPromise(
- renewToken(uri, this.tokenPair)
+ renewToken(uri, getTokenPair())
.then((tokens) => {
if (isDefined(tokens)) {
onTokenPairChange?.(tokens);
+ cookieStorage.setItem(
+ 'tokenPair',
+ JSON.stringify(tokens),
+ );
}
})
.catch(() => {
@@ -162,10 +183,6 @@ export class ApolloFactory implements ApolloManager {
});
}
- updateTokenPair(tokenPair: AuthTokenPair | null) {
- this.tokenPair = tokenPair;
- }
-
updateWorkspaceMember(workspaceMember: CurrentWorkspaceMember | null) {
this.currentWorkspaceMember = workspaceMember;
}
diff --git a/packages/twenty-front/src/modules/apollo/types/apolloManager.interface.ts b/packages/twenty-front/src/modules/apollo/types/apolloManager.interface.ts
index 1f033c8c3..8f34289d1 100644
--- a/packages/twenty-front/src/modules/apollo/types/apolloManager.interface.ts
+++ b/packages/twenty-front/src/modules/apollo/types/apolloManager.interface.ts
@@ -1,10 +1,8 @@
import { ApolloClient } from '@apollo/client';
import { CurrentWorkspaceMember } from '@/auth/states/currentWorkspaceMemberState';
-import { AuthTokenPair } from '~/generated/graphql';
export interface ApolloManager {
getClient(): ApolloClient;
- updateTokenPair(tokenPair: AuthTokenPair | null): void;
updateWorkspaceMember(workspaceMember: CurrentWorkspaceMember | null): void;
}
diff --git a/packages/twenty-front/src/modules/auth/hooks/useAuth.ts b/packages/twenty-front/src/modules/auth/hooks/useAuth.ts
index 5a4a3891a..8d970c2fd 100644
--- a/packages/twenty-front/src/modules/auth/hooks/useAuth.ts
+++ b/packages/twenty-front/src/modules/auth/hooks/useAuth.ts
@@ -63,6 +63,7 @@ import { useSearchParams } from 'react-router-dom';
import { APP_LOCALES } from 'twenty-shared/translations';
import { isDefined } from 'twenty-shared/utils';
import { iconsState } from 'twenty-ui/display';
+import { cookieStorage } from '~/utils/cookie-storage';
import { getWorkspaceUrl } from '~/utils/getWorkspaceUrl';
import { dynamicActivate } from '~/utils/i18n/dynamicActivate';
@@ -348,6 +349,12 @@ export const useAuth = () => {
setTokenPair(
getAuthTokensResult.data?.getAuthTokensFromLoginToken.tokens,
);
+ cookieStorage.setItem(
+ 'tokenPair',
+ JSON.stringify(
+ getAuthTokensResult.data?.getAuthTokensFromLoginToken.tokens,
+ ),
+ );
await refreshObjectMetadataItems();
await loadCurrentUser();
diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/EmailsFieldDisplay.tsx b/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/EmailsFieldDisplay.tsx
index b2a6fc724..e0d22664c 100644
--- a/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/EmailsFieldDisplay.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/EmailsFieldDisplay.tsx
@@ -1,8 +1,8 @@
-import { useEmailsField } from '@/object-record/record-field/meta-types/hooks/useEmailsField';
+import { useEmailsFieldDisplay } from '@/object-record/record-field/meta-types/hooks/useEmailsFieldDisplay';
import { EmailsDisplay } from '@/ui/field/display/components/EmailsDisplay';
export const EmailsFieldDisplay = () => {
- const { fieldValue } = useEmailsField();
+ const { fieldValue } = useEmailsFieldDisplay();
return ;
};
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellDisplayContainer.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellDisplayContainer.tsx
index a648e9350..4f0f2c342 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellDisplayContainer.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellDisplayContainer.tsx
@@ -2,9 +2,7 @@ import { Theme, withTheme } from '@emotion/react';
import { styled } from '@linaria/react';
import { Ref } from 'react';
-const StyledOuterContainer = styled.div<{
- hasSoftFocus?: boolean;
-}>`
+const StyledOuterContainer = styled.div`
align-items: center;
display: flex;
height: 100%;
@@ -50,7 +48,6 @@ export const RecordTableCellDisplayContainer = ({
}
onClick={onClick}
ref={scrollRef}
- hasSoftFocus={softFocus}
onContextMenu={onContextMenu}
>
{placeholderForEmptyCell ? (
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellWrapper.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellWrapper.tsx
index 59c8600bd..81f2ea988 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellWrapper.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellWrapper.tsx
@@ -1,5 +1,3 @@
-import { useMemo } from 'react';
-
import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata';
import { RecordTableCellContext } from '@/object-record/record-table/contexts/RecordTableCellContext';
import { useRecordTableRowContextOrThrow } from '@/object-record/record-table/contexts/RecordTableRowContext';
@@ -9,6 +7,7 @@ import { isTableCellInEditModeComponentFamilyState } from '@/object-record/recor
import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition';
import { TableCellPosition } from '@/object-record/record-table/types/TableCellPosition';
import { useRecoilComponentFamilyValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValueV2';
+import { useMemo } from 'react';
export const RecordTableCellWrapper = ({
children,
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableTd.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableTd.tsx
index b85d0276a..20e590e07 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableTd.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableTd.tsx
@@ -18,25 +18,19 @@ const StyledTd = styled.td<{
width?: number;
}>`
border-bottom: 1px solid
- ${({ borderColor, hasBottomBorder }) =>
- hasBottomBorder ? borderColor : 'transparent'};
+ ${({ borderColor, hasBottomBorder, isDragging }) =>
+ hasBottomBorder && !isDragging ? borderColor : 'transparent'};
color: ${({ fontColor }) => fontColor};
- border-right: ${({ borderColor, hasRightBorder }) =>
- hasRightBorder ? `1px solid ${borderColor}` : 'none'};
+ border-right: ${({ borderColor, hasRightBorder, isDragging }) =>
+ hasRightBorder && !isDragging ? `1px solid ${borderColor}` : 'none'};
padding: 0;
transition: 0.3s ease;
text-align: left;
- background: ${({ backgroundColor }) => backgroundColor};
- ${({ isDragging }) =>
- isDragging
- ? `
- background-color: transparent;
- border-color: transparent;
- `
- : ''}
+ background: ${({ backgroundColor, isDragging }) =>
+ isDragging ? 'transparent' : backgroundColor};
${({ freezeFirstColumns }) =>
freezeFirstColumns
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-header/components/RecordTableColumnHeadDropdownMenu.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-header/components/RecordTableColumnHeadDropdownMenu.tsx
index 09f6ea9c8..083467c79 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/record-table-header/components/RecordTableColumnHeadDropdownMenu.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-header/components/RecordTableColumnHeadDropdownMenu.tsx
@@ -6,10 +6,9 @@ import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
import { onToggleColumnFilterComponentState } from '@/object-record/record-table/states/onToggleColumnFilterComponentState';
import { onToggleColumnSortComponentState } from '@/object-record/record-table/states/onToggleColumnSortComponentState';
import { visibleTableColumnsComponentSelector } from '@/object-record/record-table/states/selectors/visibleTableColumnsComponentSelector';
+import { useToggleScrollWrapper } from '@/ui/utilities/scroll/hooks/useToggleScrollWrapper';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useLingui } from '@lingui/react/macro';
-import { useTableColumns } from '../../hooks/useTableColumns';
-import { ColumnDefinition } from '../../types/ColumnDefinition';
import {
IconArrowLeft,
IconArrowRight,
@@ -18,6 +17,8 @@ import {
IconSortDescending,
} from 'twenty-ui/display';
import { MenuItem } from 'twenty-ui/navigation';
+import { useTableColumns } from '../../hooks/useTableColumns';
+import { ColumnDefinition } from '../../types/ColumnDefinition';
export type RecordTableColumnHeadDropdownMenuProps = {
column: ColumnDefinition;
@@ -28,6 +29,9 @@ export const RecordTableColumnHeadDropdownMenu = ({
}: RecordTableColumnHeadDropdownMenuProps) => {
const { t } = useLingui();
+ const { toggleScrollXWrapper, toggleScrollYWrapper } =
+ useToggleScrollWrapper();
+
const visibleTableColumns = useRecoilComponentValueV2(
visibleTableColumnsComponentSelector,
);
@@ -46,16 +50,21 @@ export const RecordTableColumnHeadDropdownMenu = ({
const { closeDropdown } = useDropdown(column.fieldMetadataId + '-header');
- const handleColumnMoveLeft = () => {
+ const closeDropdownAndToggleScroll = () => {
closeDropdown();
+ toggleScrollXWrapper(true);
+ toggleScrollYWrapper(false);
+ };
+ const handleColumnMoveLeft = () => {
+ closeDropdownAndToggleScroll();
if (!canMoveLeft) return;
handleMoveTableColumn('left', column);
};
const handleColumnMoveRight = () => {
- closeDropdown();
+ closeDropdownAndToggleScroll();
if (!canMoveRight) return;
@@ -63,7 +72,7 @@ export const RecordTableColumnHeadDropdownMenu = ({
};
const handleColumnVisibility = () => {
- closeDropdown();
+ closeDropdownAndToggleScroll();
handleColumnVisibilityChange(column);
};
@@ -75,13 +84,13 @@ export const RecordTableColumnHeadDropdownMenu = ({
);
const handleSortClick = () => {
- closeDropdown();
+ closeDropdownAndToggleScroll();
onToggleColumnSort?.(column.fieldMetadataId);
};
const handleFilterClick = () => {
- closeDropdown();
+ closeDropdownAndToggleScroll();
onToggleColumnFilter?.(column.fieldMetadataId);
};
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-row/components/RecordTableTrEffect.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-row/components/RecordTableTrEffect.tsx
index 3fbe22e7b..c1d02cc0a 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/record-table-row/components/RecordTableTrEffect.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-row/components/RecordTableTrEffect.tsx
@@ -1,4 +1,3 @@
-import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext';
import { isRowVisibleComponentFamilyState } from '@/object-record/record-table/record-table-row/states/isRowVisibleComponentFamilyState';
import { useScrollWrapperElement } from '@/ui/utilities/scroll/hooks/useScrollWrapperElement';
import { useSetRecoilComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentFamilyStateV2';
@@ -9,7 +8,6 @@ type RecordTableTrEffectProps = {
};
export const RecordTableTrEffect = ({ recordId }: RecordTableTrEffectProps) => {
- const { onIndexRecordsLoaded } = useRecordIndexContextOrThrow();
const { scrollWrapperHTMLElement } = useScrollWrapperElement();
const setIsRowVisible = useSetRecoilComponentFamilyStateV2(
@@ -29,7 +27,6 @@ export const RecordTableTrEffect = ({ recordId }: RecordTableTrEffectProps) => {
const isIntersecting = entry.isIntersecting;
if (isIntersecting) {
- onIndexRecordsLoaded?.();
setIsRowVisible(true);
}
@@ -50,12 +47,7 @@ export const RecordTableTrEffect = ({ recordId }: RecordTableTrEffectProps) => {
return () => {
observer.disconnect();
};
- }, [
- onIndexRecordsLoaded,
- recordId,
- scrollWrapperHTMLElement,
- setIsRowVisible,
- ]);
+ }, [recordId, scrollWrapperHTMLElement, setIsRowVisible]);
return <>>;
};
diff --git a/packages/twenty-front/src/modules/ui/field/display/components/EmailsDisplay.tsx b/packages/twenty-front/src/modules/ui/field/display/components/EmailsDisplay.tsx
index d98c14b19..9e39e0ecd 100644
--- a/packages/twenty-front/src/modules/ui/field/display/components/EmailsDisplay.tsx
+++ b/packages/twenty-front/src/modules/ui/field/display/components/EmailsDisplay.tsx
@@ -2,7 +2,7 @@ import { useMemo } from 'react';
import { FieldEmailsValue } from '@/object-record/record-field/types/FieldMetadata';
import { ExpandableList } from '@/ui/layout/expandable-list/components/ExpandableList';
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
import { isDefined } from 'twenty-shared/utils';
import { RoundedLink } from 'twenty-ui/navigation';
import { THEME_COMMON } from 'twenty-ui/theme';
diff --git a/packages/twenty-front/src/modules/ui/field/display/components/MultiSelectDisplay.tsx b/packages/twenty-front/src/modules/ui/field/display/components/MultiSelectDisplay.tsx
index 6e2169246..d56fab1e1 100644
--- a/packages/twenty-front/src/modules/ui/field/display/components/MultiSelectDisplay.tsx
+++ b/packages/twenty-front/src/modules/ui/field/display/components/MultiSelectDisplay.tsx
@@ -1,7 +1,7 @@
import { FieldMultiSelectValue } from '@/object-record/record-field/types/FieldMetadata';
-import styled from '@emotion/styled';
-import { SelectOption } from 'twenty-ui/input';
+import { styled } from '@linaria/react';
import { Tag } from 'twenty-ui/components';
+import { SelectOption } from 'twenty-ui/input';
import { THEME_COMMON } from 'twenty-ui/theme';
const spacing1 = THEME_COMMON.spacing(1);
diff --git a/packages/twenty-front/src/modules/ui/field/display/components/PhonesDisplay.tsx b/packages/twenty-front/src/modules/ui/field/display/components/PhonesDisplay.tsx
index 5f62b0345..bf801bd67 100644
--- a/packages/twenty-front/src/modules/ui/field/display/components/PhonesDisplay.tsx
+++ b/packages/twenty-front/src/modules/ui/field/display/components/PhonesDisplay.tsx
@@ -1,15 +1,15 @@
-import styled from '@emotion/styled';
import React, { useMemo } from 'react';
import { FieldPhonesValue } from '@/object-record/record-field/types/FieldMetadata';
import { ExpandableList } from '@/ui/layout/expandable-list/components/ExpandableList';
import { DEFAULT_PHONE_CALLING_CODE } from '@/object-record/record-field/meta-types/input/components/PhonesFieldInput';
+import { styled } from '@linaria/react';
import { parsePhoneNumber } from 'libphonenumber-js';
-import { logError } from '~/utils/logError';
import { isDefined } from 'twenty-shared/utils';
import { RoundedLink } from 'twenty-ui/navigation';
import { THEME_COMMON } from 'twenty-ui/theme';
+import { logError } from '~/utils/logError';
type PhonesDisplayProps = {
value?: FieldPhonesValue;
diff --git a/packages/twenty-front/src/modules/ui/field/display/components/TextDisplay.tsx b/packages/twenty-front/src/modules/ui/field/display/components/TextDisplay.tsx
index a795e5e39..0a0ffa8f9 100644
--- a/packages/twenty-front/src/modules/ui/field/display/components/TextDisplay.tsx
+++ b/packages/twenty-front/src/modules/ui/field/display/components/TextDisplay.tsx
@@ -1,4 +1,3 @@
-import { useInlineCell } from '@/object-record/record-inline-cell/hooks/useInlineCell';
import { OverflowingTextWithTooltip } from 'twenty-ui/display';
type TextDisplayProps = {
@@ -7,13 +6,11 @@ type TextDisplayProps = {
};
export const TextDisplay = ({ text, displayedMaxRows }: TextDisplayProps) => {
- const { isInlineCellInEditMode } = useInlineCell();
return (
);
};
diff --git a/packages/twenty-front/src/modules/ui/field/display/components/URLDisplay.tsx b/packages/twenty-front/src/modules/ui/field/display/components/URLDisplay.tsx
index 35f61f94c..21e33989e 100644
--- a/packages/twenty-front/src/modules/ui/field/display/components/URLDisplay.tsx
+++ b/packages/twenty-front/src/modules/ui/field/display/components/URLDisplay.tsx
@@ -1,19 +1,8 @@
-import styled from '@emotion/styled';
import { MouseEvent } from 'react';
+import { LinkType, RoundedLink, SocialLink } from 'twenty-ui/navigation';
import { checkUrlType } from '~/utils/checkUrlType';
import { EllipsisDisplay } from './EllipsisDisplay';
-import { LinkType, RoundedLink, SocialLink } from 'twenty-ui/navigation';
-
-const StyledRawLink = styled(RoundedLink)`
- overflow: hidden;
-
- a {
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- }
-`;
type URLDisplayProps = {
value: string | null;
@@ -48,7 +37,7 @@ export const URLDisplay = ({ value }: URLDisplayProps) => {
}
return (
- theme.spacing(2)};
z-index: 1;
`;
@@ -195,51 +195,56 @@ export const ViewBarDetails = ({
return (
-
- {isDefined(softDeleteFilter) && (
-
- )}
- {isDefined(softDeleteFilter) && (
-
-
-
- )}
- {currentRecordSorts.map((recordSort) => (
-
- ))}
- {isNonEmptyArray(recordFilters) &&
- isNonEmptyArray(currentRecordSorts) && (
+
+
+ {isDefined(softDeleteFilter) && (
+
+ )}
+ {isDefined(softDeleteFilter) && (
)}
- {shouldShowAdvancedFilterDropdownButton && (
-
- )}
- {recordFilters.map((recordFilter) => (
-
-
-
-
-
-
- ))}
-
+ {currentRecordSorts.map((recordSort) => (
+
+ ))}
+ {isNonEmptyArray(recordFilters) &&
+ isNonEmptyArray(currentRecordSorts) && (
+
+
+
+ )}
+ {shouldShowAdvancedFilterDropdownButton && (
+
+ )}
+ {recordFilters.map((recordFilter) => (
+
+
+
+
+
+
+ ))}
+
+
{hasFilterButton && (
{
'**/RecordTableHeaderDragDropColumn.tsx',
'**/ActorDisplay.tsx',
'**/AvatarChip.tsx',
+ '**/URLDisplay.tsx',
+ '**/EmailsDisplay.tsx',
+ '**/PhonesDisplay.tsx',
+ '**/MultiSelectDisplay.tsx',
+
],
babelOptions: {
presets: ['@babel/preset-typescript', '@babel/preset-react'],
diff --git a/packages/twenty-ui/src/components/avatar-chip/AvatarChip.tsx b/packages/twenty-ui/src/components/avatar-chip/AvatarChip.tsx
index b957ba427..8b2e96047 100644
--- a/packages/twenty-ui/src/components/avatar-chip/AvatarChip.tsx
+++ b/packages/twenty-ui/src/components/avatar-chip/AvatarChip.tsx
@@ -19,7 +19,7 @@ export const AvatarChip = ({
label={name}
variant={ChipVariant.Transparent}
size={size}
- leftComponent={() => (
+ leftComponent={
- )}
+ }
clickable={false}
className={className}
maxWidth={maxWidth}
diff --git a/packages/twenty-ui/src/components/avatar-chip/AvatarChipLeftComponent.tsx b/packages/twenty-ui/src/components/avatar-chip/AvatarChipLeftComponent.tsx
index 1543c9950..efe08146e 100644
--- a/packages/twenty-ui/src/components/avatar-chip/AvatarChipLeftComponent.tsx
+++ b/packages/twenty-ui/src/components/avatar-chip/AvatarChipLeftComponent.tsx
@@ -1,5 +1,5 @@
import { useTheme } from '@emotion/react';
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
import { Avatar } from '@ui/display/avatar/components/Avatar';
import { AvatarType } from '@ui/display/avatar/types/AvatarType';
import { IconComponent } from '@ui/display/icon/types/IconComponent';
diff --git a/packages/twenty-ui/src/components/avatar-chip/LinkAvatarChip.tsx b/packages/twenty-ui/src/components/avatar-chip/LinkAvatarChip.tsx
index ca1001803..f291dd8ac 100644
--- a/packages/twenty-ui/src/components/avatar-chip/LinkAvatarChip.tsx
+++ b/packages/twenty-ui/src/components/avatar-chip/LinkAvatarChip.tsx
@@ -39,7 +39,7 @@ export const LinkAvatarChip = ({
: ChipVariant.Regular
}
size={size}
- leftComponent={() => (
+ leftComponent={
- )}
+ }
className={className}
maxWidth={maxWidth}
/>
diff --git a/packages/twenty-ui/src/components/chip/Chip.tsx b/packages/twenty-ui/src/components/chip/Chip.tsx
index 4f471479e..4b65715eb 100644
--- a/packages/twenty-ui/src/components/chip/Chip.tsx
+++ b/packages/twenty-ui/src/components/chip/Chip.tsx
@@ -30,7 +30,7 @@ export type ChipProps = {
maxWidth?: number;
variant?: ChipVariant;
accent?: ChipAccent;
- leftComponent?: (() => ReactNode) | null;
+ leftComponent?: ReactNode | null;
rightComponent?: (() => ReactNode) | null;
className?: string;
};
@@ -146,7 +146,7 @@ export const Chip = ({
className={className}
maxWidth={maxWidth}
>
- {leftComponent?.()}
+ {leftComponent}
{!isLabelHidden && (
)}
diff --git a/packages/twenty-ui/src/components/chip/LinkChip.tsx b/packages/twenty-ui/src/components/chip/LinkChip.tsx
index 5076ec3b3..a7a4bc937 100644
--- a/packages/twenty-ui/src/components/chip/LinkChip.tsx
+++ b/packages/twenty-ui/src/components/chip/LinkChip.tsx
@@ -1,4 +1,4 @@
-import styled from '@emotion/styled';
+import { styled } from '@linaria/react';
import {
Chip,
ChipAccent,
@@ -17,8 +17,6 @@ export type LinkChipProps = Omit<
onClick?: (event: MouseEvent) => void;
};
-// Ideally we would use the UndecoratedLink component from @ui/navigation
-// but it led to a bug probably linked to circular dependencies, which was hard to solve
const StyledLink = styled(Link)`
text-decoration: none;
`;
diff --git a/packages/twenty-ui/src/display/avatar/components/Avatar.tsx b/packages/twenty-ui/src/display/avatar/components/Avatar.tsx
index f33d76bff..92cb2963b 100644
--- a/packages/twenty-ui/src/display/avatar/components/Avatar.tsx
+++ b/packages/twenty-ui/src/display/avatar/components/Avatar.tsx
@@ -1,7 +1,6 @@
import { styled } from '@linaria/react';
import { isNonEmptyString, isNull, isUndefined } from '@sniptt/guards';
import { useContext } from 'react';
-import { useRecoilState } from 'recoil';
import { invalidAvatarUrlsState } from '@ui/display/avatar/components/states/isInvalidAvatarUrlState';
import { AVATAR_PROPERTIES_BY_SIZE } from '@ui/display/avatar/constants/AvatarPropertiesBySize';
@@ -11,6 +10,7 @@ import { IconComponent } from '@ui/display/icon/types/IconComponent';
import { ThemeContext } from '@ui/theme';
import { Nullable, stringToHslColor } from '@ui/utilities';
import { REACT_APP_SERVER_BASE_URL } from '@ui/utilities/config';
+import { useRecoilState } from 'recoil';
import { getImageAbsoluteURI } from 'twenty-shared/utils';
const StyledAvatar = styled.div<{
diff --git a/packages/twenty-ui/src/navigation/link/components/RoundedLink.tsx b/packages/twenty-ui/src/navigation/link/components/RoundedLink.tsx
index ef3b05953..808e316e9 100644
--- a/packages/twenty-ui/src/navigation/link/components/RoundedLink.tsx
+++ b/packages/twenty-ui/src/navigation/link/components/RoundedLink.tsx
@@ -7,6 +7,7 @@ type RoundedLinkProps = {
href: string;
label?: string;
onClick?: (event: React.MouseEvent) => void;
+ className?: string;
};
const fontSizeMd = FONT_COMMON.size.md;
@@ -59,7 +60,12 @@ const StyledLink = styled.a<{
}
`;
-export const RoundedLink = ({ label, href, onClick }: RoundedLinkProps) => {
+export const RoundedLink = ({
+ label,
+ href,
+ onClick,
+ className,
+}: RoundedLinkProps) => {
const { theme } = useContext(ThemeContext);
const background = theme.background.transparent.lighter;
@@ -89,6 +95,7 @@ export const RoundedLink = ({ label, href, onClick }: RoundedLinkProps) => {
backgroundHover={backgroundHover}
backgroundActive={backgroundActive}
border={border}
+ className={className}
>
{label}
diff --git a/packages/twenty-ui/vite.config.ts b/packages/twenty-ui/vite.config.ts
index f1239a9f4..d14c84510 100644
--- a/packages/twenty-ui/vite.config.ts
+++ b/packages/twenty-ui/vite.config.ts
@@ -84,6 +84,9 @@ export default defineConfig(({ command }) => {
'**/Tag.tsx',
'**/Avatar.tsx',
'**/Chip.tsx',
+ '**/LinkChip.tsx',
+ '**/Avatar.tsx',
+ '**/AvatarChipLeftComponent.tsx',
'**/ContactLink.tsx',
'**/RoundedLink.tsx',
],