Compare commits

...
Author SHA1 Message Date
Sonarly Claude Code d5fe781ce9 fix(twenty-front): cap settings page marginLeft to prevent large blank area on wide viewports
https://sonarly.com/issue/30109?type=bug

The `DefaultLayout` component centers the Settings page by computing a `marginLeft` that scales linearly with viewport width. At ultrawide viewports (≥1400px), this formula produces hundreds of pixels of dead space on the left.

Fix: Removed the `marginLeft` centering animation from `DefaultLayout.tsx` that was pushing the entire settings page container to the right on desktop viewports.

**What changed:** The `StyledPageContainer` previously used `motion.create()` to animate a `marginLeft` computed as `(viewportWidth - 808) / 2` when on settings pages. This centered the 808px settings content (512px content + 220px nav drawer + 76px padding) horizontally, creating increasingly large dead space on the left at wider viewports (e.g., ~800px of blank space at 2400px).

**The fix:** Converted `StyledPageContainer` from a `motion.div` back to a plain `styled.div`, removing the centering formula entirely. The settings page now left-aligns identically to all other pages — the settings navigation drawer sits at the left edge where the main navigation used to be, and the settings content extends from there.

**Cleanup:** Removed 6 imports and 3 variables that were only used for the centering calculation:
- `useIsSettingsPage` hook
- `OBJECT_SETTINGS_WIDTH` constant
- `NAVIGATION_DRAWER_CONSTRAINTS` constant
- `useScreenSize` hook
- `motion` from framer-motion
- `useContext` from React
- `ThemeContext` from twenty-ui
- `isSettingsPage`, `windowsWidth`, and `theme` local variables
2026-04-23 02:06:27 +00:00
@@ -9,10 +9,8 @@ import { LayoutCustomizationBar } from '@/layout-customization/components/Layout
import { AppNavigationDrawer } from '@/navigation/components/AppNavigationDrawer';
import { MobileNavigationBar } from '@/navigation/components/MobileNavigationBar';
import { PageDragDropProvider } from '@/navigation-menu-item/display/dnd/providers/PageDragDropProvider';
import { useIsSettingsPage } from '@/navigation/hooks/useIsSettingsPage';
import { OBJECT_SETTINGS_WIDTH } from '@/settings/data-model/constants/ObjectSettings';
import { SignInAppNavigationDrawerMock } from '@/sign-in-background-mock/components/SignInAppNavigationDrawerMock';
import { Suspense, lazy, useContext } from 'react';
import { Suspense, lazy } from 'react';
const SignInBackgroundMockPage = lazy(() =>
import('@/sign-in-background-mock/components/SignInBackgroundMockPage').then(
@@ -21,13 +19,11 @@ const SignInBackgroundMockPage = lazy(() =>
);
import { useShowFullscreen } from '@/ui/layout/fullscreen/hooks/useShowFullscreen';
import { useShowAuthModal } from '@/ui/layout/hooks/useShowAuthModal';
import { NAVIGATION_DRAWER_CONSTRAINTS } from '@/ui/layout/resizable-panel/constants/NavigationDrawerConstraints';
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
import { styled } from '@linaria/react';
import { AnimatePresence, LayoutGroup, motion } from 'framer-motion';
import { AnimatePresence, LayoutGroup } from 'framer-motion';
import { Outlet } from 'react-router-dom';
import { useScreenSize } from 'twenty-ui/utilities';
import { ThemeContext, themeCssVariables } from 'twenty-ui/theme-constants';
import { themeCssVariables } from 'twenty-ui/theme-constants';
const StyledLayout = styled.div`
background: ${themeCssVariables.background.noisy};
display: flex;
@@ -43,13 +39,12 @@ const StyledLayout = styled.div`
}
`;
const StyledPageContainerBase = styled.div`
const StyledPageContainer = styled.div`
display: flex;
flex: 1 1 auto;
flex-direction: row;
min-height: 0;
`;
const StyledPageContainer = motion.create(StyledPageContainerBase);
const StyledNavigationDrawerWrapper = styled.div`
flex-shrink: 0;
@@ -63,11 +58,8 @@ const StyledMainContainer = styled.div`
export const DefaultLayout = () => {
const isMobile = useIsMobile();
const isSettingsPage = useIsSettingsPage();
const windowsWidth = useScreenSize().width;
const showAuthModal = useShowAuthModal();
const useShowFullScreen = useShowFullscreen();
const { theme } = useContext(ThemeContext);
return (
<>
@@ -76,21 +68,7 @@ export const DefaultLayout = () => {
<AppErrorBoundary FallbackComponent={AppFullScreenErrorFallback}>
<InformationBannerIsImpersonating />
<LayoutCustomizationBar />
<StyledPageContainer
animate={{
marginLeft:
isSettingsPage && !isMobile && !useShowFullScreen
? (windowsWidth -
(OBJECT_SETTINGS_WIDTH +
NAVIGATION_DRAWER_CONSTRAINTS.default +
76)) /
2
: 0,
}}
transition={{
duration: theme.animation.duration.normal,
}}
>
<StyledPageContainer>
<PageDragDropProvider>
{!showAuthModal && <KeyboardShortcutMenu />}
{showAuthModal ? (