From 37a70143dbee70fbe762c50617c65b72359e5192 Mon Sep 17 00:00:00 2001 From: Priscila Oliveira Date: Mon, 13 Apr 2026 08:45:28 +0200 Subject: [PATCH 1/5] fix(settings): Prevent action button clipping in page frame layout The SettingsPageHeader uses a negative margin trick (-32px) designed for the non-page-frame layout where the container has 32px top padding. In the page frame layout, the container only has 8px top padding, causing the action button to extend above the scroll container origin and become inaccessible. Co-Authored-By: Claude Opus 4.6 --- .../components/settingsPageHeader.tsx | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/static/app/views/settings/components/settingsPageHeader.tsx b/static/app/views/settings/components/settingsPageHeader.tsx index 536686e524d1c5..6ff21ff97cb464 100644 --- a/static/app/views/settings/components/settingsPageHeader.tsx +++ b/static/app/views/settings/components/settingsPageHeader.tsx @@ -1,6 +1,7 @@ import styled from '@emotion/styled'; import * as Layout from 'sentry/components/layouts/thirds'; +import {useHasPageFrameFeature} from 'sentry/views/navigation/useHasPageFrameFeature'; type Props = { /** @@ -38,15 +39,20 @@ function UnstyledSettingsPageHeader({ body, tabs, noTitleStyles = false, + className, ...props }: Props) { + const hasPageFrame = useHasPageFrameFeature(); // If Header is narrow, use align-items to center . // Otherwise, use a fixed margin to prevent an odd alignment. // This is needed as Actions could be a button or a dropdown. const isNarrow = !subtitle; return ( -
+
{icon && {icon}} @@ -106,6 +112,18 @@ export const SettingsPageHeader = styled(UnstyledSettingsPageHeader)< >` font-size: 14px; margin-top: -${p => p.theme.space['3xl']}; + + &.has-page-frame { + margin-top: 0; + + ${Title} { + margin-top: 0; + } + + ${Action} { + margin-top: 0; + } + } `; const BodyWrapper = styled('div')` From dc8bfb11dbd2fd7304554f8205b7833aade9d07f Mon Sep 17 00:00:00 2001 From: Priscila Oliveira Date: Mon, 13 Apr 2026 08:52:07 +0200 Subject: [PATCH 2/5] fix(settings): Keep inner margins to preserve spacing Only reset the wrapper's negative margin in the page-frame case. The Title and Action inner margins provide correct internal layout and spacing below the header. Co-Authored-By: Claude Opus 4.6 --- .../app/views/settings/components/settingsPageHeader.tsx | 8 -------- 1 file changed, 8 deletions(-) diff --git a/static/app/views/settings/components/settingsPageHeader.tsx b/static/app/views/settings/components/settingsPageHeader.tsx index 6ff21ff97cb464..8b5dce8f67813e 100644 --- a/static/app/views/settings/components/settingsPageHeader.tsx +++ b/static/app/views/settings/components/settingsPageHeader.tsx @@ -115,14 +115,6 @@ export const SettingsPageHeader = styled(UnstyledSettingsPageHeader)< &.has-page-frame { margin-top: 0; - - ${Title} { - margin-top: 0; - } - - ${Action} { - margin-top: 0; - } } `; From 799574b1edc27de3af21efcbe273839eb85d87c4 Mon Sep 17 00:00:00 2001 From: Priscila Oliveira Date: Mon, 13 Apr 2026 09:01:59 +0200 Subject: [PATCH 3/5] fix(settings): Portal action button to TopBar in page frame Move the action button (e.g. "Create Project") into the TopBar actions slot when the page-frame feature is active, matching the pattern used by dashboards and other pages. Co-Authored-By: Claude Opus 4.6 --- .../components/settingsPageHeader.tsx | 45 +++++++++++-------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/static/app/views/settings/components/settingsPageHeader.tsx b/static/app/views/settings/components/settingsPageHeader.tsx index 8b5dce8f67813e..2d60935edb67b1 100644 --- a/static/app/views/settings/components/settingsPageHeader.tsx +++ b/static/app/views/settings/components/settingsPageHeader.tsx @@ -1,6 +1,8 @@ +import {Fragment} from 'react'; import styled from '@emotion/styled'; import * as Layout from 'sentry/components/layouts/thirds'; +import {TopBar} from 'sentry/views/navigation/topBar'; import {useHasPageFrameFeature} from 'sentry/views/navigation/useHasPageFrameFeature'; type Props = { @@ -49,26 +51,31 @@ function UnstyledSettingsPageHeader({ const isNarrow = !subtitle; return ( -
- - - {icon && {icon}} - {title && ( - - <Layout.Title>{title}</Layout.Title> - {subtitle && <Subtitle colorSubtitle={colorSubtitle}>{subtitle}</Subtitle>} - - )} - - {action && {action}} - + + {hasPageFrame && action && {action}} +
+ + + {icon && {icon}} + {title && ( + + <Layout.Title>{title}</Layout.Title> + {subtitle && ( + <Subtitle colorSubtitle={colorSubtitle}>{subtitle}</Subtitle> + )} + + )} + + {!hasPageFrame && action && {action}} + - {body && {body}} - {tabs && {tabs}} -
+ {body && {body}} + {tabs && {tabs}} +
+ ); } From 091fe3ec158394d036c7c853b96a932a66b3fc3c Mon Sep 17 00:00:00 2001 From: Priscila Oliveira Date: Mon, 13 Apr 2026 09:02:40 +0200 Subject: [PATCH 4/5] ref(settings): Remove unnecessary margin override The action button is now portaled to the TopBar, so the negative margin clipping workaround is no longer needed. Co-Authored-By: Claude Opus 4.6 --- .../views/settings/components/settingsPageHeader.tsx | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/static/app/views/settings/components/settingsPageHeader.tsx b/static/app/views/settings/components/settingsPageHeader.tsx index 2d60935edb67b1..ad17a31b91f304 100644 --- a/static/app/views/settings/components/settingsPageHeader.tsx +++ b/static/app/views/settings/components/settingsPageHeader.tsx @@ -41,7 +41,6 @@ function UnstyledSettingsPageHeader({ body, tabs, noTitleStyles = false, - className, ...props }: Props) { const hasPageFrame = useHasPageFrameFeature(); @@ -53,10 +52,7 @@ function UnstyledSettingsPageHeader({ return ( {hasPageFrame && action && {action}} -
+
{icon && {icon}} @@ -119,10 +115,6 @@ export const SettingsPageHeader = styled(UnstyledSettingsPageHeader)< >` font-size: 14px; margin-top: -${p => p.theme.space['3xl']}; - - &.has-page-frame { - margin-top: 0; - } `; const BodyWrapper = styled('div')` From 08ac002df02d9a241f447195739504b3bf8ac57e Mon Sep 17 00:00:00 2001 From: Priscila Oliveira Date: Mon, 13 Apr 2026 11:37:27 +0200 Subject: [PATCH 5/5] ref(settings): Simplify settings page header action rendering Use a single conditional to choose between the page-frame slot and the inline action wrapper. Keep the mutually exclusive action rendering in one branch so future updates only need to change one representation. Co-Authored-By: OpenAI Codex --- .../components/settingsPageHeader.tsx | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/static/app/views/settings/components/settingsPageHeader.tsx b/static/app/views/settings/components/settingsPageHeader.tsx index ad17a31b91f304..d5a5e6b221d284 100644 --- a/static/app/views/settings/components/settingsPageHeader.tsx +++ b/static/app/views/settings/components/settingsPageHeader.tsx @@ -1,4 +1,3 @@ -import {Fragment} from 'react'; import styled from '@emotion/styled'; import * as Layout from 'sentry/components/layouts/thirds'; @@ -50,28 +49,29 @@ function UnstyledSettingsPageHeader({ const isNarrow = !subtitle; return ( - - {hasPageFrame && action && {action}} -
- - - {icon && {icon}} - {title && ( - - <Layout.Title>{title}</Layout.Title> - {subtitle && ( - <Subtitle colorSubtitle={colorSubtitle}>{subtitle}</Subtitle> - )} - - )} - - {!hasPageFrame && action && {action}} - +
+ + + {icon && {icon}} + {title && ( + + <Layout.Title>{title}</Layout.Title> + {subtitle && <Subtitle colorSubtitle={colorSubtitle}>{subtitle}</Subtitle>} + + )} + + {action ? ( + hasPageFrame ? ( + {action} + ) : ( + {action} + ) + ) : null} + - {body && {body}} - {tabs && {tabs}} -
- + {body && {body}} + {tabs && {tabs}} +
); }