From 3ffb266af6061410352d31b36c31ea64d01cd363 Mon Sep 17 00:00:00 2001 From: TJ Date: Thu, 20 Aug 2026 16:08:51 -0700 Subject: [PATCH] fix(site): align settings header style and paywall spacing (#28418) Settings pages rendered the premium upsell banner at different vertical offsets and the IdP sync pages used a lighter heading style than the rest of the settings UI. Three causes: 1. The IdP Sync (`/organizations/:org/idp-sync`) and Organization IdP Sync (`/deployment/idp-org-sync`) pages hand-rolled their headers with a bare `

` (missing `font-semibold`) and a `flex flex-col gap-12` wrapper (48px above the banner). 2. Workspace Proxies and Appearance wrapped `SettingsHeader` in flex columns with their own `gap` (`gap-4`, `gap-8`), which stacked on top of the header's built-in `pb-6`, pushing the banner to 40px and 56px offsets respectively while Groups sits at 24px. 3. `SettingsHeaderDescription` used `leading-normal` (21px lines) while the inline `Link` component ("View docs") renders a 24px-tall `inline-flex leading-6` box, inflating the line box on pages whose description contains a docs link and shifting content below by ~3px. Changes: - Replace the custom header markup on both IdP sync pages with the shared `SettingsHeader`, `SettingsHeaderTitle`, and `SettingsHeaderDescription` components; the Export Policy button moves into the `actions` slot. - Hoist `SettingsHeader` out of the gap wrappers on Workspace Proxies and Appearance so the header's `pb-6` is the single source of header-to-content spacing; the gap now applies only within the entitled content. - Set `SettingsHeaderDescription` to `leading-6` so description line height matches the inline `Link`, whether or not a docs link is present. All affected pages now start content, including the premium paywall, 24px below the header description. _Created by Coder Agents on behalf of @tracyjohnsonux._ --- .../SettingsHeader/SettingsHeader.tsx | 2 +- .../AppearanceSettingsPageView.tsx | 6 +- .../IdpOrgSyncPage/IdpOrgSyncPage.tsx | 40 ++--- .../IdpSyncPage/IdpSyncPage.tsx | 140 +++++++++--------- .../WorkspaceProxyPage/WorkspaceProxyView.tsx | 6 +- 5 files changed, 102 insertions(+), 92 deletions(-) diff --git a/site/src/components/SettingsHeader/SettingsHeader.tsx b/site/src/components/SettingsHeader/SettingsHeader.tsx index 2d056832bff..fcac611aa85 100644 --- a/site/src/components/SettingsHeader/SettingsHeader.tsx +++ b/site/src/components/SettingsHeader/SettingsHeader.tsx @@ -97,7 +97,7 @@ export const SettingsHeaderDescription: FC = ({ return (

diff --git a/site/src/pages/DeploymentSettingsPage/AppearanceSettingsPage/AppearanceSettingsPageView.tsx b/site/src/pages/DeploymentSettingsPage/AppearanceSettingsPage/AppearanceSettingsPageView.tsx index dce55b3def7..1308d694d0c 100644 --- a/site/src/pages/DeploymentSettingsPage/AppearanceSettingsPage/AppearanceSettingsPageView.tsx +++ b/site/src/pages/DeploymentSettingsPage/AppearanceSettingsPage/AppearanceSettingsPageView.tsx @@ -48,7 +48,7 @@ export const AppearanceSettingsPageView: FC< const getFieldHelpers = getFormHelpers(form); return ( -

+
@@ -73,7 +73,7 @@ export const AppearanceSettingsPageView: FC< canViewPremium={canViewPremium} /> ) : ( - <> +
- +
)}
); diff --git a/site/src/pages/DeploymentSettingsPage/IdpOrgSyncPage/IdpOrgSyncPage.tsx b/site/src/pages/DeploymentSettingsPage/IdpOrgSyncPage/IdpOrgSyncPage.tsx index 9b8c35fa2d6..4a9bdd449d1 100644 --- a/site/src/pages/DeploymentSettingsPage/IdpOrgSyncPage/IdpOrgSyncPage.tsx +++ b/site/src/pages/DeploymentSettingsPage/IdpOrgSyncPage/IdpOrgSyncPage.tsx @@ -9,7 +9,12 @@ import { } from "#/api/queries/idpsync"; import { Loader } from "#/components/Loader/Loader"; import { PaywallPremium } from "#/components/Paywall/PaywallPremium"; -import { SettingsHeaderDocsLink } from "#/components/SettingsHeader/SettingsHeader"; +import { + SettingsHeader, + SettingsHeaderDescription, + SettingsHeaderDocsLink, + SettingsHeaderTitle, +} from "#/components/SettingsHeader/SettingsHeader"; import { useAuthenticated } from "#/hooks/useAuthenticated"; import { useDashboard } from "#/modules/dashboard/useDashboard"; import { useFeatureVisibility } from "#/modules/dashboard/useFeatureVisibility"; @@ -63,22 +68,23 @@ const IdpOrgSyncPage: FC = () => { <> {pageTitle("Organization IdP Sync")} -
-
-
-

Organization IdP Sync

-

- Automatically assign users to an organization based on their IdP - claims. -

-
-
- - -
-
+
+ + + +
+ } + > + Organization IdP Sync + + Automatically assign users to an organization based on their IdP + claims. + + {!isIdpSyncEnabled ? ( {
{title} -
-
-
-

IdP Sync

-

- Automatically assign groups or roles to a user based on their IdP - claims. -

-
+ -
- {!isIdpSyncEnabled ? ( - - ) : ( - { - const mutation = patchGroupSyncSettingsMutation.mutateAsync(data); - toast.promise(mutation, { - loading: "Updating IdP group sync settings...", - success: "IdP group sync settings updated.", - error: (error) => ({ - message: getErrorMessage( - error, - "Failed to update IdP group sync settings.", - ), + } + > + IdP Sync + + Automatically assign groups or roles to a user based on their IdP + claims. + + + {!isIdpSyncEnabled ? ( + + ) : ( + { + const mutation = patchGroupSyncSettingsMutation.mutateAsync(data); + toast.promise(mutation, { + loading: "Updating IdP group sync settings...", + success: "IdP group sync settings updated.", + error: (error) => ({ + message: getErrorMessage( + error, + "Failed to update IdP group sync settings.", + ), + description: getErrorDetail(error), + }), + }); + }} + onSubmitRoleSyncSettings={async (data) => { + try { + await patchRoleSyncSettingsMutation.mutateAsync(data); + toast.success("IdP Role sync settings updated."); + } catch (error) { + toast.error( + getErrorMessage( + error, + "Failed to update IdP role sync settings.", + ), + { description: getErrorDetail(error), - }), - }); - }} - onSubmitRoleSyncSettings={async (data) => { - try { - await patchRoleSyncSettingsMutation.mutateAsync(data); - toast.success("IdP Role sync settings updated."); - } catch (error) { - toast.error( - getErrorMessage( - error, - "Failed to update IdP role sync settings.", - ), - { - description: getErrorDetail(error), - }, - ); - } - }} - /> - )} -
+ }, + ); + } + }} + /> + )}
); }; diff --git a/site/src/pages/UserSettingsPage/WorkspaceProxyPage/WorkspaceProxyView.tsx b/site/src/pages/UserSettingsPage/WorkspaceProxyPage/WorkspaceProxyView.tsx index 235d5b4da60..661c347a65d 100644 --- a/site/src/pages/UserSettingsPage/WorkspaceProxyPage/WorkspaceProxyView.tsx +++ b/site/src/pages/UserSettingsPage/WorkspaceProxyPage/WorkspaceProxyView.tsx @@ -45,7 +45,7 @@ export const WorkspaceProxyView: FC = ({ permissions, }) => { return ( -
+
= ({ canViewPremium={permissions.viewAllLicenses} /> ) : ( - <> +
{Boolean(getWorkspaceProxiesError) && ( )} @@ -96,7 +96,7 @@ export const WorkspaceProxyView: FC = ({ /> - +
)}
);