diff --git a/packages/twenty-front/src/modules/layout-customization/components/LayoutCustomizationBar.tsx b/packages/twenty-front/src/modules/layout-customization/components/LayoutCustomizationBar.tsx
index 3a3f5750f6..c42e7a9f09 100644
--- a/packages/twenty-front/src/modules/layout-customization/components/LayoutCustomizationBar.tsx
+++ b/packages/twenty-front/src/modules/layout-customization/components/LayoutCustomizationBar.tsx
@@ -1,15 +1,24 @@
+import { styled } from '@linaria/react';
+import { useLingui } from '@lingui/react/macro';
+import { AnimatePresence, motion } from 'framer-motion';
+import { useAtomValue } from 'jotai';
+import { useContext } from 'react';
+import { isDefined } from 'twenty-shared/utils';
+import { IconCheck, IconPaint } from 'twenty-ui/display';
+import { ThemeContext, themeCssVariables } from 'twenty-ui/theme-constants';
+
+import { LayoutCustomizationBarMenuDropdown } from '@/layout-customization/components/LayoutCustomizationBarMenuDropdown';
+import { LayoutCustomizationBarResetConfirmationModal } from '@/layout-customization/components/LayoutCustomizationBarResetConfirmationModal';
import { useCancelLayoutCustomization } from '@/layout-customization/hooks/useCancelLayoutCustomization';
import { useIsLayoutCustomizationDirty } from '@/layout-customization/hooks/useIsLayoutCustomizationDirty';
import { useSaveLayoutCustomization } from '@/layout-customization/hooks/useSaveLayoutCustomization';
import { isLayoutCustomizationModeEnabledState } from '@/layout-customization/states/isLayoutCustomizationModeEnabledState';
+import { objectMetadataItemsSelector } from '@/object-metadata/states/objectMetadataItemsSelector';
+import { currentPageLayoutIdState } from '@/page-layout/states/currentPageLayoutIdState';
+import { pageLayoutPersistedComponentState } from '@/page-layout/states/pageLayoutPersistedComponentState';
import { SaveAndCancelButtons } from '@/settings/components/SaveAndCancelButtons/SaveAndCancelButtons';
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
-import { styled } from '@linaria/react';
-import { useLingui } from '@lingui/react/macro';
-import { AnimatePresence, motion } from 'framer-motion';
-import { useContext } from 'react';
-import { IconCheck, IconPaint } from 'twenty-ui/display';
-import { ThemeContext, themeCssVariables } from 'twenty-ui/theme-constants';
+import { PageLayoutType } from '~/generated-metadata/graphql';
const StyledContainer = styled.div`
align-items: center;
@@ -22,10 +31,27 @@ const StyledContainer = styled.div`
width: 100%;
`;
+const StyledLeftSection = styled.div`
+ align-items: center;
+ display: flex;
+ flex: 1;
+ gap: ${themeCssVariables.spacing[2]};
+`;
+
const StyledTitle = styled.span`
align-items: center;
display: flex;
+ flex: 1;
gap: ${themeCssVariables.spacing[2]};
+ justify-content: center;
+ text-align: center;
+`;
+
+const StyledRightSection = styled.div`
+ align-items: center;
+ display: flex;
+ flex: 1;
+ justify-content: flex-end;
`;
const LayoutCustomizationBarContent = () => {
@@ -36,6 +62,26 @@ const LayoutCustomizationBarContent = () => {
const { cancel } = useCancelLayoutCustomization();
const { isDirty } = useIsLayoutCustomizationDirty();
+ const currentPageLayoutId = useAtomStateValue(currentPageLayoutIdState);
+ const persistedPageLayout = useAtomValue(
+ pageLayoutPersistedComponentState.atomFamily({
+ instanceId: currentPageLayoutId ?? '',
+ }),
+ );
+ const objectMetadataItems = useAtomStateValue(objectMetadataItemsSelector);
+
+ const recordPageLayoutObject =
+ isDefined(currentPageLayoutId) &&
+ persistedPageLayout?.type === PageLayoutType.RECORD_PAGE
+ ? objectMetadataItems.find(
+ (item) => item.id === persistedPageLayout.objectMetadataId,
+ )
+ : undefined;
+
+ const title = isDefined(recordPageLayoutObject)
+ ? t`${recordPageLayoutObject.labelPlural} layout edition`
+ : t`Layout customization`;
+
return (
{
}}
>
+
+ {isDefined(recordPageLayoutObject) && (
+
+ )}
+
- {t`Layout customization`}
+ {title}
-
+
+
+
+ {isDefined(recordPageLayoutObject) && isDefined(currentPageLayoutId) && (
+
+ )}
);
};
diff --git a/packages/twenty-front/src/modules/layout-customization/components/LayoutCustomizationBarMenuDropdown.tsx b/packages/twenty-front/src/modules/layout-customization/components/LayoutCustomizationBarMenuDropdown.tsx
new file mode 100644
index 0000000000..f6876c648a
--- /dev/null
+++ b/packages/twenty-front/src/modules/layout-customization/components/LayoutCustomizationBarMenuDropdown.tsx
@@ -0,0 +1,66 @@
+import { styled } from '@linaria/react';
+import { useLingui } from '@lingui/react/macro';
+import { IconDotsVertical, IconReload } from 'twenty-ui/display';
+import { LightIconButton } from 'twenty-ui/input';
+import { MenuItem } from 'twenty-ui/navigation';
+import { themeCssVariables } from 'twenty-ui/theme-constants';
+
+import { LAYOUT_CUSTOMIZATION_BAR_DROPDOWN_ID } from '@/layout-customization/constants/LayoutCustomizationBarDropdownId';
+import { RESET_RECORD_PAGE_LAYOUT_MODAL_ID } from '@/layout-customization/constants/ResetRecordPageLayoutModalId';
+import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
+import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
+import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
+import { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/GenericDropdownContentWidth';
+import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
+import { useModal } from '@/ui/layout/modal/hooks/useModal';
+
+const StyledInvertedIconButtonWrapper = styled.span`
+ align-items: center;
+ display: flex;
+
+ button {
+ color: ${themeCssVariables.font.color.inverted};
+ }
+
+ button:hover {
+ background: ${themeCssVariables.background.transparent.light};
+ }
+`;
+
+export const LayoutCustomizationBarMenuDropdown = () => {
+ const { t } = useLingui();
+ const { closeDropdown } = useCloseDropdown();
+ const { openModal } = useModal();
+
+ const handleResetClick = () => {
+ closeDropdown(LAYOUT_CUSTOMIZATION_BAR_DROPDOWN_ID);
+ openModal(RESET_RECORD_PAGE_LAYOUT_MODAL_ID);
+ };
+
+ return (
+
+
+
+ }
+ dropdownComponents={
+
+
+
+
+
+ }
+ />
+ );
+};
diff --git a/packages/twenty-front/src/modules/layout-customization/components/LayoutCustomizationBarResetConfirmationModal.tsx b/packages/twenty-front/src/modules/layout-customization/components/LayoutCustomizationBarResetConfirmationModal.tsx
new file mode 100644
index 0000000000..3469053de9
--- /dev/null
+++ b/packages/twenty-front/src/modules/layout-customization/components/LayoutCustomizationBarResetConfirmationModal.tsx
@@ -0,0 +1,36 @@
+import { useLingui } from '@lingui/react/macro';
+
+import { RESET_RECORD_PAGE_LAYOUT_MODAL_ID } from '@/layout-customization/constants/ResetRecordPageLayoutModalId';
+import { useRefreshPageLayoutAfterReset } from '@/page-layout/hooks/useRefreshPageLayoutAfterReset';
+import { useResetPageLayoutToDefault } from '@/page-layout/hooks/useResetPageLayoutToDefault';
+import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal';
+
+type LayoutCustomizationBarResetConfirmationModalProps = {
+ pageLayoutId: string;
+};
+
+export const LayoutCustomizationBarResetConfirmationModal = ({
+ pageLayoutId,
+}: LayoutCustomizationBarResetConfirmationModalProps) => {
+ const { t } = useLingui();
+
+ const { resetPageLayoutToDefault } = useResetPageLayoutToDefault();
+ const { refreshPageLayoutAfterReset } =
+ useRefreshPageLayoutAfterReset(pageLayoutId);
+
+ const handleConfirmReset = async () => {
+ await resetPageLayoutToDefault({ pageLayoutId });
+ await refreshPageLayoutAfterReset();
+ };
+
+ return (
+
+ );
+};
diff --git a/packages/twenty-front/src/modules/layout-customization/constants/LayoutCustomizationBarDropdownId.ts b/packages/twenty-front/src/modules/layout-customization/constants/LayoutCustomizationBarDropdownId.ts
new file mode 100644
index 0000000000..263d131a8c
--- /dev/null
+++ b/packages/twenty-front/src/modules/layout-customization/constants/LayoutCustomizationBarDropdownId.ts
@@ -0,0 +1,2 @@
+export const LAYOUT_CUSTOMIZATION_BAR_DROPDOWN_ID =
+ 'layout-customization-bar-dropdown';
diff --git a/packages/twenty-front/src/modules/layout-customization/constants/ResetRecordPageLayoutModalId.ts b/packages/twenty-front/src/modules/layout-customization/constants/ResetRecordPageLayoutModalId.ts
new file mode 100644
index 0000000000..35d8f87002
--- /dev/null
+++ b/packages/twenty-front/src/modules/layout-customization/constants/ResetRecordPageLayoutModalId.ts
@@ -0,0 +1,2 @@
+export const RESET_RECORD_PAGE_LAYOUT_MODAL_ID =
+ 'reset-record-page-layout-modal';