From 088cd3025ace01a57d1016b77d4008111b54fad6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rapha=C3=ABl=20Bosi?=
<71827178+bosiraphael@users.noreply.github.com>
Date: Fri, 19 Dec 2025 14:31:57 +0100
Subject: [PATCH] Implement new version of the side panel sub header (#16683)
## Before
## After
---
.../components/CommandMenuBackButton.tsx | 8 +-
.../components/SidePanelHeader.tsx | 148 ------------------
.../components/SidePanelHeaderSyncEffect.tsx | 17 --
.../__stories__/SidePanelHeader.stories.tsx | 101 ------------
.../CommandMenuSubPageNavigationHeader.tsx | 39 -----
.../SidePanelSubPageNavigationHeader.tsx | 40 +++++
.../components/ChartFiltersSettings.tsx | 46 +++---
7 files changed, 69 insertions(+), 330 deletions(-)
delete mode 100644 packages/twenty-front/src/modules/command-menu/components/SidePanelHeader.tsx
delete mode 100644 packages/twenty-front/src/modules/command-menu/components/SidePanelHeaderSyncEffect.tsx
delete mode 100644 packages/twenty-front/src/modules/command-menu/components/__stories__/SidePanelHeader.stories.tsx
delete mode 100644 packages/twenty-front/src/modules/command-menu/pages/common/components/CommandMenuSubPageNavigationHeader.tsx
create mode 100644 packages/twenty-front/src/modules/command-menu/pages/common/components/SidePanelSubPageNavigationHeader.tsx
diff --git a/packages/twenty-front/src/modules/command-menu/components/CommandMenuBackButton.tsx b/packages/twenty-front/src/modules/command-menu/components/CommandMenuBackButton.tsx
index 70bd56c4dd..c5cc326503 100644
--- a/packages/twenty-front/src/modules/command-menu/components/CommandMenuBackButton.tsx
+++ b/packages/twenty-front/src/modules/command-menu/components/CommandMenuBackButton.tsx
@@ -13,11 +13,13 @@ import { MenuItem } from 'twenty-ui/navigation';
const StyledNavigationIcon = styled.div`
align-items: center;
- color: ${({ theme }) => theme.font.color.secondary};
cursor: pointer;
display: flex;
justify-content: center;
- margin-right: ${({ theme }) => theme.spacing(1)};
+`;
+
+const StyledIconChevronLeft = styled(IconChevronLeft)`
+ color: ${({ theme }) => theme.font.color.secondary};
`;
export const CommandMenuBackButton = () => {
@@ -50,7 +52,7 @@ export const CommandMenuBackButton = () => {
clickableComponent={
theme.background.secondary};
- border-bottom: 1px solid ${({ theme }) => theme.border.color.medium};
- display: flex;
- flex-direction: row;
- padding: ${({ theme }) => theme.spacing(4)};
- gap: ${({ theme }) => theme.spacing(2)};
-`;
-
-const StyledHeaderInfo = styled.div`
- display: flex;
- flex-direction: column;
- width: 100%;
- gap: ${({ theme }) => theme.spacing(2)};
-`;
-
-const StyledHeaderTitle = styled.div`
- color: ${({ theme }) => theme.font.color.primary};
- font-weight: ${({ theme }) => theme.font.weight.semiBold};
- font-size: ${({ theme }) => theme.font.size.xl};
- width: fit-content;
- max-width: 420px;
- & > input:disabled {
- color: ${({ theme }) => theme.font.color.primary};
- }
-`;
-
-const StyledHeaderType = styled.div`
- color: ${({ theme }) => theme.font.color.tertiary};
- padding-left: ${({ theme }) => theme.spacing(1)};
-`;
-
-const StyledHeaderIconContainer = styled.div`
- align-self: flex-start;
- display: flex;
- justify-content: center;
- align-items: center;
- background-color: ${({ theme }) => theme.background.transparent.light};
- border-radius: ${({ theme }) => theme.border.radius.sm};
- padding: ${({ theme }) => theme.spacing(2)};
-`;
-
-type SidePanelHeaderProps = {
- Icon: IconComponent;
- iconColor: string;
- initialTitle: string;
- headerType: string;
- iconTooltip?: string;
-} & (
- | {
- disabled: true;
- onTitleChange?: never;
- }
- | {
- disabled?: boolean;
- onTitleChange: (newTitle: string) => void;
- }
-);
-
-export const SidePanelHeader = ({
- Icon,
- iconColor,
- initialTitle,
- headerType,
- disabled,
- onTitleChange,
- iconTooltip,
-}: SidePanelHeaderProps) => {
- const [shouldFocusTitleInput, setShouldFocusTitleInput] =
- useRecoilComponentState(commandMenuShouldFocusTitleInputComponentState);
-
- const theme = useTheme();
-
- const [title, setTitle] = useState(initialTitle);
-
- const { updateCommandMenuPageInfo } = useUpdateCommandMenuPageInfo();
-
- const handleChange = (newTitle: string) => {
- setTitle(newTitle);
- };
-
- const saveTitle = () => {
- onTitleChange?.(title);
- updateCommandMenuPageInfo({
- pageTitle: title,
- pageIcon: Icon,
- });
- };
-
- const tooltipId = `side-panel-icon-tooltip-${headerType.replace(/\s+/g, '-')}`;
-
- return (
- <>
-
-
-
-
-
- {iconTooltip && (
-
- )}
-
-
- {
- setTitle(initialTitle);
- }}
- onClickOutside={saveTitle}
- onTab={saveTitle}
- onShiftTab={saveTitle}
- shouldOpen={shouldFocusTitleInput}
- onOpen={() => setShouldFocusTitleInput(false)}
- />
-
- {headerType}
-
-
- >
- );
-};
diff --git a/packages/twenty-front/src/modules/command-menu/components/SidePanelHeaderSyncEffect.tsx b/packages/twenty-front/src/modules/command-menu/components/SidePanelHeaderSyncEffect.tsx
deleted file mode 100644
index 0eb5df13ae..0000000000
--- a/packages/twenty-front/src/modules/command-menu/components/SidePanelHeaderSyncEffect.tsx
+++ /dev/null
@@ -1,17 +0,0 @@
-import { useEffect } from 'react';
-
-type SidePanelHeaderTitleSyncEffectProps = {
- initialTitle: string;
- setTitle: (title: string) => void;
-};
-
-export const SidePanelHeaderTitleSyncEffect = ({
- initialTitle,
- setTitle,
-}: SidePanelHeaderTitleSyncEffectProps) => {
- useEffect(() => {
- setTitle(initialTitle);
- }, [initialTitle, setTitle]);
-
- return null;
-};
diff --git a/packages/twenty-front/src/modules/command-menu/components/__stories__/SidePanelHeader.stories.tsx b/packages/twenty-front/src/modules/command-menu/components/__stories__/SidePanelHeader.stories.tsx
deleted file mode 100644
index e1963a8c67..0000000000
--- a/packages/twenty-front/src/modules/command-menu/components/__stories__/SidePanelHeader.stories.tsx
+++ /dev/null
@@ -1,101 +0,0 @@
-import { type Meta, type StoryObj } from '@storybook/react';
-import { expect, fn, userEvent, waitFor, within } from '@storybook/test';
-import { IconPlus } from 'twenty-ui/display';
-import { ComponentDecorator } from 'twenty-ui/testing';
-import { THEME_LIGHT } from 'twenty-ui/theme';
-import { CommandMenuPageComponentInstanceContext } from '@/command-menu/states/contexts/CommandMenuPageComponentInstanceContext';
-import { SidePanelHeader } from '../SidePanelHeader';
-
-const meta: Meta = {
- title: 'Modules/CommandMenu/SidePanelHeader',
- component: SidePanelHeader,
- args: {
- onTitleChange: fn(),
- },
- argTypes: {},
- decorators: [
- ComponentDecorator,
- (Story) => (
-
-
-
- ),
- ],
- parameters: {
- disableHotkeyInitialization: true,
- },
-};
-
-export default meta;
-
-type Story = StoryObj;
-
-export const Default: Story = {
- args: {
- headerType: 'Action',
- iconColor: THEME_LIGHT.font.color.tertiary,
- initialTitle: 'Create Record',
- Icon: IconPlus,
- },
- play: async ({ canvasElement }) => {
- const canvas = within(canvasElement);
-
- expect(await canvas.findByText('Create Record')).toBeVisible();
- expect(await canvas.findByText('Action')).toBeVisible();
- },
-};
-
-export const EditableTitle: Story = {
- args: {
- headerType: 'Action',
- iconColor: THEME_LIGHT.font.color.tertiary,
- initialTitle: 'Create Record',
- Icon: IconPlus,
- onTitleChange: fn(),
- },
- play: async ({ canvasElement, args }) => {
- const canvas = within(canvasElement);
- const titleText = await canvas.findByText('Create Record');
- await userEvent.click(titleText);
-
- const titleInput = await canvas.findByDisplayValue('Create Record');
-
- const NEW_TITLE = 'New Title';
-
- await userEvent.clear(titleInput);
- await userEvent.type(titleInput, NEW_TITLE);
-
- await userEvent.keyboard('{Enter}');
-
- await waitFor(() => {
- expect(args.onTitleChange).toHaveBeenCalledWith(NEW_TITLE);
- });
- },
-};
-
-export const Disabled: Story = {
- args: {
- headerType: 'Action',
- iconColor: THEME_LIGHT.font.color.tertiary,
- initialTitle: 'Create Record',
- Icon: IconPlus,
- disabled: true,
- onTitleChange: fn(),
- },
- play: async ({ canvasElement, args }) => {
- const canvas = within(canvasElement);
-
- const titleText = await canvas.findByText('Create Record');
-
- expect(window.getComputedStyle(titleText).cursor).toBe('default');
-
- await userEvent.click(titleText);
-
- const titleInput = canvas.queryByDisplayValue('Create Record');
- expect(titleInput).not.toBeInTheDocument();
-
- expect(args.onTitleChange).not.toHaveBeenCalled();
- },
-};
diff --git a/packages/twenty-front/src/modules/command-menu/pages/common/components/CommandMenuSubPageNavigationHeader.tsx b/packages/twenty-front/src/modules/command-menu/pages/common/components/CommandMenuSubPageNavigationHeader.tsx
deleted file mode 100644
index 00f9cdef08..0000000000
--- a/packages/twenty-front/src/modules/command-menu/pages/common/components/CommandMenuSubPageNavigationHeader.tsx
+++ /dev/null
@@ -1,39 +0,0 @@
-import styled from '@emotion/styled';
-import { IconChevronLeft } from 'twenty-ui/display';
-import { IconButton } from 'twenty-ui/input';
-
-const StyledContainer = styled.div`
- align-items: center;
- display: flex;
-
- flex-direction: row;
-`;
-
-const StyledTextContainer = styled.div`
- color: ${({ theme }) => theme.font.color.primary};
- font-size: ${({ theme }) => theme.font.size.md};
-
- padding-left: ${({ theme }) => theme.spacing(1)};
- padding-bottom: ${({ theme }) => theme.spacing(0.2)};
-`;
-
-type CommandMenuSubPageNavigationHeaderProps = {
- title: string;
- onBackClick: () => void;
-};
-
-export const CommandMenuSubPageNavigationHeader = ({
- onBackClick,
- title,
-}: CommandMenuSubPageNavigationHeaderProps) => {
- return (
-
-
- {title}
-
- );
-};
diff --git a/packages/twenty-front/src/modules/command-menu/pages/common/components/SidePanelSubPageNavigationHeader.tsx b/packages/twenty-front/src/modules/command-menu/pages/common/components/SidePanelSubPageNavigationHeader.tsx
new file mode 100644
index 0000000000..181f59fb6b
--- /dev/null
+++ b/packages/twenty-front/src/modules/command-menu/pages/common/components/SidePanelSubPageNavigationHeader.tsx
@@ -0,0 +1,40 @@
+import styled from '@emotion/styled';
+import { IconChevronLeft } from 'twenty-ui/display';
+import { IconButton } from 'twenty-ui/input';
+
+const StyledContainer = styled.div`
+ align-items: center;
+ border-bottom: 1px solid ${({ theme }) => theme.border.color.light};
+ display: flex;
+ gap: ${({ theme }) => theme.spacing(1)};
+ padding: 0 ${({ theme }) => theme.spacing(2)};
+ height: 40px;
+`;
+
+const StyledText = styled.span`
+ color: ${({ theme }) => theme.font.color.tertiary};
+ font-size: ${({ theme }) => theme.font.size.md};
+ font-weight: ${({ theme }) => theme.font.weight.medium};
+`;
+
+type SidePanelSubPageNavigationHeaderProps = {
+ title: string;
+ onBackClick: () => void;
+};
+
+export const SidePanelSubPageNavigationHeader = ({
+ onBackClick,
+ title,
+}: SidePanelSubPageNavigationHeaderProps) => {
+ return (
+
+
+ {title}
+
+ );
+};
diff --git a/packages/twenty-front/src/modules/command-menu/pages/page-layout/components/ChartFiltersSettings.tsx b/packages/twenty-front/src/modules/command-menu/pages/page-layout/components/ChartFiltersSettings.tsx
index 544cd2a064..9a83ee7132 100644
--- a/packages/twenty-front/src/modules/command-menu/pages/page-layout/components/ChartFiltersSettings.tsx
+++ b/packages/twenty-front/src/modules/command-menu/pages/page-layout/components/ChartFiltersSettings.tsx
@@ -1,6 +1,6 @@
-import { CommandMenuSubPageNavigationHeader } from '@/command-menu/pages/common/components/CommandMenuSubPageNavigationHeader';
-import { ChartFiltersSettingsInitializeStateEffect } from '@/command-menu/pages/page-layout/components/ChartFiltersSettingsInitializeStateEffect';
import { useCommandMenuHistory } from '@/command-menu/hooks/useCommandMenuHistory';
+import { SidePanelSubPageNavigationHeader } from '@/command-menu/pages/common/components/SidePanelSubPageNavigationHeader';
+import { ChartFiltersSettingsInitializeStateEffect } from '@/command-menu/pages/page-layout/components/ChartFiltersSettingsInitializeStateEffect';
import { usePageLayoutIdFromContextStoreTargetedRecord } from '@/command-menu/pages/page-layout/hooks/usePageLayoutFromContextStoreTargetedRecord';
import { useUpdateCurrentWidgetConfig } from '@/command-menu/pages/page-layout/hooks/useUpdateCurrentWidgetConfig';
import { type ChartWidget } from '@/command-menu/pages/page-layout/types/ChartWidget';
@@ -95,30 +95,32 @@ export const ChartFiltersSettings = ({
);
return (
-
-
+
-
-
{t`Conditions`}
-
-
+
+
{t`Conditions`}
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+ >
);
};