diff --git a/packages/twenty-front/src/modules/object-record/record-field/hooks/useClearField.ts b/packages/twenty-front/src/modules/object-record/record-field/hooks/useClearField.ts index 548e212f9..305774422 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/hooks/useClearField.ts +++ b/packages/twenty-front/src/modules/object-record/record-field/hooks/useClearField.ts @@ -2,6 +2,7 @@ import { useContext } from 'react'; import { useRecoilCallback } from 'recoil'; import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; +import { useSetRecordFieldValue } from '@/object-record/record-store/contexts/RecordFieldValueSelectorContext'; import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector'; import { generateEmptyFieldValue } from '@/object-record/utils/generateEmptyFieldValue'; @@ -16,6 +17,8 @@ export const useClearField = () => { const [updateRecord] = useUpdateRecord(); + const setRecordFieldValue = useSetRecordFieldValue(); + const clearField = useRecoilCallback( ({ snapshot, set }) => () => { @@ -46,6 +49,8 @@ export const useClearField = () => { emptyFieldValue, ); + setRecordFieldValue(entityId, fieldName, emptyFieldValue); + updateRecord?.({ variables: { where: { id: entityId }, @@ -55,7 +60,7 @@ export const useClearField = () => { }, }); }, - [entityId, fieldDefinition, updateRecord], + [entityId, fieldDefinition, updateRecord, setRecordFieldValue], ); return clearField; diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/SelectFieldInput.tsx b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/SelectFieldInput.tsx index 0f745de75..53461b39f 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/SelectFieldInput.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/SelectFieldInput.tsx @@ -2,6 +2,7 @@ import React, { useRef, useState } from 'react'; import styled from '@emotion/styled'; import { Key } from 'ts-key-enum'; +import { useClearField } from '@/object-record/record-field/hooks/useClearField'; import { useSelectField } from '@/object-record/record-field/meta-types/hooks/useSelectField'; import { FieldInputEvent } from '@/object-record/record-field/types/FieldInputEvent'; import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu'; @@ -30,12 +31,15 @@ export const SelectFieldInput = ({ }: SelectFieldInputProps) => { const { persistField, fieldDefinition, fieldValue, hotkeyScope } = useSelectField(); + const clearField = useClearField(); + const [searchFilter, setSearchFilter] = useState(''); const containerRef = useRef(null); const selectedOption = fieldDefinition.metadata.options.find( (option) => option.value === fieldValue, ); + const optionsToSelect = fieldDefinition.metadata.options.filter((option) => { return ( @@ -43,10 +47,17 @@ export const SelectFieldInput = ({ option.label.toLowerCase().includes(searchFilter.toLowerCase()) ); }) || []; + const optionsInDropDown = selectedOption ? [selectedOption, ...optionsToSelect] : optionsToSelect; + // handlers + const handleClearField = () => { + clearField(); + onCancel?.(); + }; + useListenClickOutside({ refs: [containerRef], callback: (event) => { @@ -85,7 +96,17 @@ export const SelectFieldInput = ({ autoFocus /> + + + {optionsInDropDown.map((option) => { return ( void; - color: ThemeColor; + color: ThemeColor | 'transparent'; text: string; + variant?: 'solid' | 'outline'; }; export const MenuItemSelectTag = ({ @@ -19,6 +20,7 @@ export const MenuItemSelectTag = ({ className, onClick, text, + variant = 'solid', }: MenuItemSelectTagProps) => { const theme = useTheme(); @@ -29,7 +31,7 @@ export const MenuItemSelectTag = ({ selected={selected} > - + {selected && } diff --git a/packages/twenty-ui/src/display/tag/components/Tag.tsx b/packages/twenty-ui/src/display/tag/components/Tag.tsx index 3b2cb67b7..51f59cfb4 100644 --- a/packages/twenty-ui/src/display/tag/components/Tag.tsx +++ b/packages/twenty-ui/src/display/tag/components/Tag.tsx @@ -16,14 +16,17 @@ const spacing1 = THEME_COMMON.spacing(1); const StyledTag = styled.h3<{ theme: ThemeType; - color: ThemeColor; + color: TagColor; weight: TagWeight; + variant: TagVariant; preventShrink?: boolean; }>` align-items: center; - background: ${({ color, theme }) => theme.tag.background[color]}; + background: ${({ color, theme }) => + color === 'transparent' ? color : theme.tag.background[color]}; border-radius: ${BORDER_COMMON.radius.sm}; - color: ${({ color, theme }) => theme.tag.text[color]}; + color: ${({ color, theme }) => + color === 'transparent' ? theme.tag.text['gray'] : theme.tag.text[color]}; display: inline-flex; font-size: ${({ theme }) => theme.font.size.md}; font-style: normal; @@ -35,6 +38,8 @@ const StyledTag = styled.h3<{ margin: 0; overflow: hidden; padding: 0 ${spacing2}; + border: ${({ variant, theme }) => + variant === 'outline' ? `2px dashed ${theme.tag.background['gray']}` : ''}; gap: ${spacing1}; @@ -58,14 +63,17 @@ const StyledIconContainer = styled.div` `; type TagWeight = 'regular' | 'medium'; +type TagVariant = 'solid' | 'outline'; +type TagColor = ThemeColor | 'transparent'; type TagProps = { className?: string; - color: ThemeColor; + color: TagColor; text: string; Icon?: IconComponent; onClick?: () => void; weight?: TagWeight; + variant?: TagVariant; preventShrink?: boolean; }; @@ -77,6 +85,7 @@ export const Tag = ({ Icon, onClick, weight = 'regular', + variant = 'solid', preventShrink, }: TagProps) => { const { theme } = useContext(ThemeContext); @@ -88,6 +97,7 @@ export const Tag = ({ color={color} onClick={onClick} weight={weight} + variant={variant} preventShrink={preventShrink} > {!!Icon && (