diff --git a/packages/twenty-front/src/modules/object-record/record-field/ui/form-types/components/FormDateTimeFieldInput.tsx b/packages/twenty-front/src/modules/object-record/record-field/ui/form-types/components/FormDateTimeFieldInput.tsx
index 4be6858601..dae7b3d5da 100644
--- a/packages/twenty-front/src/modules/object-record/record-field/ui/form-types/components/FormDateTimeFieldInput.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-field/ui/form-types/components/FormDateTimeFieldInput.tsx
@@ -5,6 +5,7 @@ import { VariableChipStandalone } from '@/object-record/record-field/ui/form-typ
import { type VariablePickerComponent } from '@/object-record/record-field/ui/form-types/types/VariablePickerComponent';
import { InputLabel } from '@/ui/input/components/InputLabel';
import {
+ DATE_TIME_PICKER_MONTH_YEAR_PANEL_DROPDOWN_ID,
DateTimePicker,
MONTH_AND_YEAR_DROPDOWN_MONTH_SELECT_ID,
MONTH_AND_YEAR_DROPDOWN_YEAR_SELECT_ID,
@@ -15,6 +16,7 @@ import { useUserTimezone } from '@/ui/input/components/internal/date/hooks/useUs
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { OverlayContainer } from '@/ui/layout/overlay/components/OverlayContainer';
import { useHotkeysOnFocusedElement } from '@/ui/utilities/hotkey/hooks/useHotkeysOnFocusedElement';
+import { ParentClickOutsideIdContext } from '@/ui/utilities/pointer-event/contexts/ParentClickOutsideIdContext';
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
import { isStandaloneVariableString } from '@/workflow/utils/isStandaloneVariableString';
@@ -133,6 +135,7 @@ export const FormDateTimeFieldInput = ({
enabled: displayDatePicker,
excludedClickOutsideIds: [
FORM_DATE_TIME_FIELD_PICKER_CLICK_OUTSIDE_ID,
+ DATE_TIME_PICKER_MONTH_YEAR_PANEL_DROPDOWN_ID,
MONTH_AND_YEAR_DROPDOWN_MONTH_SELECT_ID,
MONTH_AND_YEAR_DROPDOWN_YEAR_SELECT_ID,
],
@@ -296,17 +299,21 @@ export const FormDateTimeFieldInput = ({
}
>
-
+
+
+
diff --git a/packages/twenty-front/src/modules/settings/components/SettingsDatePickerInput.tsx b/packages/twenty-front/src/modules/settings/components/SettingsDatePickerInput.tsx
index 3e75420adb..f6bb20b761 100644
--- a/packages/twenty-front/src/modules/settings/components/SettingsDatePickerInput.tsx
+++ b/packages/twenty-front/src/modules/settings/components/SettingsDatePickerInput.tsx
@@ -11,12 +11,14 @@ import {
} from '@floating-ui/react';
import {
+ DATE_TIME_PICKER_MONTH_YEAR_PANEL_DROPDOWN_ID,
DateTimePicker,
MONTH_AND_YEAR_DROPDOWN_MONTH_SELECT_ID,
MONTH_AND_YEAR_DROPDOWN_YEAR_SELECT_ID,
} from '@/ui/input/components/internal/date/components/DateTimePicker';
import { useUserTimezone } from '@/ui/input/components/internal/date/hooks/useUserTimezone';
import { OverlayContainer } from '@/ui/layout/overlay/components/OverlayContainer';
+import { ParentClickOutsideIdContext } from '@/ui/utilities/pointer-event/contexts/ParentClickOutsideIdContext';
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
import { isDefined } from 'twenty-shared/utils';
import { IconCalendar } from 'twenty-ui/icon';
@@ -62,10 +64,6 @@ const StyledIconContainer = styled.div`
display: flex;
`;
-const StyledFloatingContainer = styled.div`
- z-index: 1000;
-`;
-
export type SettingsDatePickerInputProps = {
label?: string;
instanceId?: string;
@@ -107,6 +105,7 @@ export const SettingsDatePickerInput = ({
enabled: isOpen,
excludedClickOutsideIds: [
SETTINGS_DATE_PICKER_CLICK_OUTSIDE_ID,
+ DATE_TIME_PICKER_MONTH_YEAR_PANEL_DROPDOWN_ID,
MONTH_AND_YEAR_DROPDOWN_MONTH_SELECT_ID,
MONTH_AND_YEAR_DROPDOWN_YEAR_SELECT_ID,
],
@@ -163,22 +162,26 @@ export const SettingsDatePickerInput = ({
{isOpen && (
-
-
+
+
+
-
+
)}
diff --git a/packages/twenty-front/src/modules/settings/components/__stories__/SettingsDatePickerInput.stories.tsx b/packages/twenty-front/src/modules/settings/components/__stories__/SettingsDatePickerInput.stories.tsx
new file mode 100644
index 0000000000..f50769a486
--- /dev/null
+++ b/packages/twenty-front/src/modules/settings/components/__stories__/SettingsDatePickerInput.stories.tsx
@@ -0,0 +1,82 @@
+import { SettingsDatePickerInput } from '@/settings/components/SettingsDatePickerInput';
+import { type Meta, type StoryObj } from '@storybook/react-vite';
+import { useState } from 'react';
+import { expect, userEvent, within } from 'storybook/test';
+import { ComponentDecorator } from 'twenty-ui/testing';
+
+// Midday UTC so the rendered date stays on 15 Jan 2023 across timezones
+const INITIAL_DATE = new Date('2023-01-15T12:00:00Z');
+
+const SettingsDatePickerInputStory = () => {
+ const [value, setValue] = useState(INITIAL_DATE);
+
+ return (
+
+ );
+};
+
+const meta: Meta = {
+ title: 'Modules/Settings/SettingsDatePickerInput',
+ component: SettingsDatePickerInput,
+ decorators: [ComponentDecorator],
+ render: () => ,
+};
+
+export default meta;
+type Story = StoryObj;
+
+export const Default: Story = {
+ play: async ({ canvasElement }) => {
+ const canvas = within(canvasElement);
+ const body = within(canvasElement.ownerDocument.body);
+
+ await userEvent.click(
+ await canvas.findByText(/2023/, {}, { timeout: 10000 }),
+ );
+
+ await body.findByRole(
+ 'button',
+ { name: 'Select month and year' },
+ { timeout: 10000 },
+ );
+ },
+};
+
+// Regression test for the month/year panel closing the whole picker on click.
+// Opening the month select used to trigger the parent click-outside listener and
+// close the date picker, so the month/year controls could never be used.
+export const ChangingMonthKeepsPickerOpen: Story = {
+ play: async ({ canvasElement }) => {
+ const canvas = within(canvasElement);
+ const body = within(canvasElement.ownerDocument.body);
+
+ await userEvent.click(
+ await canvas.findByText(/2023/, {}, { timeout: 10000 }),
+ );
+
+ const monthYearButton = await body.findByRole(
+ 'button',
+ { name: 'Select month and year' },
+ { timeout: 10000 },
+ );
+ await userEvent.click(monthYearButton);
+
+ await userEvent.click(
+ await body.findByText('January', {}, { timeout: 10000 }),
+ );
+
+ // The picker must stay open after interacting with the month select
+ expect(
+ body.getByRole('button', { name: 'Select month and year' }),
+ ).toBeInTheDocument();
+
+ await userEvent.click(
+ await body.findByText('February', {}, { timeout: 10000 }),
+ );
+
+ expect(await body.findByText('February')).toBeInTheDocument();
+ expect(
+ body.getByRole('button', { name: 'Select month and year' }),
+ ).toBeInTheDocument();
+ },
+};
diff --git a/packages/twenty-front/src/modules/ui/input/components/internal/date/components/DateTimePicker.tsx b/packages/twenty-front/src/modules/ui/input/components/internal/date/components/DateTimePicker.tsx
index 00f7aeebe9..cf18fe9db5 100644
--- a/packages/twenty-front/src/modules/ui/input/components/internal/date/components/DateTimePicker.tsx
+++ b/packages/twenty-front/src/modules/ui/input/components/internal/date/components/DateTimePicker.tsx
@@ -205,6 +205,8 @@ const StyledContainer = styled.div<{
& .react-datepicker__month {
margin-top: 0;
+ margin-left: 0;
+ margin-right: 0;
pointer-events: ${({ calendarDisabled }) =>
calendarDisabled ? 'none' : 'auto'};