diff --git a/packages/twenty-front/src/modules/page-layout/hooks/useTemporaryFieldsConfiguration.ts b/packages/twenty-front/src/modules/page-layout/hooks/useTemporaryFieldsConfiguration.ts index 26d794ed09..01a3a488c1 100644 --- a/packages/twenty-front/src/modules/page-layout/hooks/useTemporaryFieldsConfiguration.ts +++ b/packages/twenty-front/src/modules/page-layout/hooks/useTemporaryFieldsConfiguration.ts @@ -25,26 +25,60 @@ export const useTemporaryFieldsConfiguration = ( field.type !== FieldMetadataType.RICH_TEXT_V2, ); - const fields = fieldsToDisplay.map((field, index) => ({ - fieldMetadataId: field.id, - position: index, - })); + if (fieldsToDisplay.length === 0) { + return null; + } - if (fields.length === 0) { + const generalFields: Array<{ fieldMetadataId: string; position: number }> = + []; + const otherFields: Array<{ fieldMetadataId: string; position: number }> = + []; + + let generalPosition = 0; + let otherPosition = 0; + + fieldsToDisplay.forEach((field) => { + if (field.type === FieldMetadataType.LINKS) { + otherFields.push({ + fieldMetadataId: field.id, + position: otherPosition++, + }); + } else { + generalFields.push({ + fieldMetadataId: field.id, + position: generalPosition++, + }); + } + }); + + const sections = []; + + if (generalFields.length > 0) { + sections.push({ + id: `${objectNameSingular}-section-general`, + title: t`General`, + position: 0, + fields: generalFields, + }); + } + + if (otherFields.length > 0) { + sections.push({ + id: `${objectNameSingular}-section-other`, + title: t`Other`, + position: 1, + fields: otherFields, + }); + } + + if (sections.length === 0) { return null; } return { __typename: 'FieldsConfiguration', configurationType: 'FIELDS', - sections: [ - { - id: `${objectNameSingular}-section-general`, - title: t`General`, - position: 0, - fields, - }, - ], + sections, }; }, [objectMetadataItem, objectNameSingular, t]); diff --git a/packages/twenty-front/src/modules/page-layout/widgets/fields/components/FieldsWidgetSectionContainer.tsx b/packages/twenty-front/src/modules/page-layout/widgets/fields/components/FieldsWidgetSectionContainer.tsx index eacd19d88f..eed1cf46a8 100644 --- a/packages/twenty-front/src/modules/page-layout/widgets/fields/components/FieldsWidgetSectionContainer.tsx +++ b/packages/twenty-front/src/modules/page-layout/widgets/fields/components/FieldsWidgetSectionContainer.tsx @@ -1,14 +1,22 @@ +import { useTheme } from '@emotion/react'; import styled from '@emotion/styled'; -import { Section } from 'twenty-ui/layout'; +import { useState } from 'react'; +import { IconChevronDown } from 'twenty-ui/display'; +import { AnimatedExpandableContainer, Section } from 'twenty-ui/layout'; const StyledFieldsWidgetSectionContainer = styled(Section)` padding-top: ${({ theme }) => theme.spacing(3)}; - padding-bottom: ${({ theme }) => theme.spacing(3)}; + padding-bottom: 0; width: auto; + + &:not(:first-of-type) { + padding-top: 0; + } `; const StyledHeader = styled.header` align-items: center; + cursor: pointer; display: flex; height: 24px; justify-content: space-between; @@ -17,9 +25,18 @@ const StyledHeader = styled.header` `; const StyledTitleLabel = styled.div` + color: ${({ theme }) => theme.font.color.tertiary}; font-weight: ${({ theme }) => theme.font.weight.medium}; `; +const StyledChevronIcon = styled(IconChevronDown)<{ isExpanded: boolean }>` + color: ${({ theme }) => theme.font.color.tertiary}; + transform: ${({ isExpanded }) => + isExpanded ? 'rotate(180deg)' : 'rotate(0deg)'}; + transition: ${({ theme }) => + `transform ${theme.animation.duration.normal}s ease`}; +`; + type FieldsWidgetSectionContainerProps = { children: React.ReactNode; title: string; @@ -29,12 +46,29 @@ export const FieldsWidgetSectionContainer = ({ children, title, }: FieldsWidgetSectionContainerProps) => { + const [isExpanded, setIsExpanded] = useState(true); + const theme = useTheme(); + + const handleToggleSection = () => + setIsExpanded((previousIsExpanded) => !previousIsExpanded); + return ( - + {title} + - {children} + + {children} + ); }; diff --git a/packages/twenty-ui/src/layout/animated-expandable-container/components/AnimatedExpandableContainer.tsx b/packages/twenty-ui/src/layout/animated-expandable-container/components/AnimatedExpandableContainer.tsx index b8eb1e6f60..4f9bc75e39 100644 --- a/packages/twenty-ui/src/layout/animated-expandable-container/components/AnimatedExpandableContainer.tsx +++ b/packages/twenty-ui/src/layout/animated-expandable-container/components/AnimatedExpandableContainer.tsx @@ -30,6 +30,7 @@ type AnimatedExpandableContainerProps = { animationDurations?: AnimationDurations; mode?: AnimationMode; containAnimation?: boolean; + initial?: boolean; }; export const AnimatedExpandableContainer = ({ @@ -39,6 +40,7 @@ export const AnimatedExpandableContainer = ({ animationDurations = 'default', mode = 'scroll-height', containAnimation = true, + initial = true, }: AnimatedExpandableContainerProps) => { const theme = useTheme(); const contentRef = useRef(null); @@ -71,7 +73,7 @@ export const AnimatedExpandableContainer = ({ ); return ( - + {isExpanded && (