chore: improve scroll behavior of DashboardLayout wrapped pages (#19396)

Updates the the `DashboardLayout` to create a singular scroll area
between the top nav bar and the deployment banner on the bottom. Also
improves the scroll behavior of the org settings pages.

<img width="2122" height="1413" alt="CleanShot 2025-08-18 at 13 53 01"
src="https://github.com/user-attachments/assets/a9920509-69e7-471d-ac0d-853cb212fcae"
/>




https://github.com/user-attachments/assets/128be43d-433f-4a0f-af5b-bbfb7d646345
This commit is contained in:
Brett Kolodny
2025-08-26 14:14:44 -04:00
committed by GitHub
parent 59525f879b
commit d274f832b3
20 changed files with 33 additions and 40 deletions
+3 -2
View File
@@ -5,10 +5,11 @@ import { cn } from "utils/cn";
interface SidebarProps {
children?: ReactNode;
className?: string;
}
export const Sidebar: FC<SidebarProps> = ({ children }) => {
return <nav className="w-60 flex-shrink-0">{children}</nav>;
export const Sidebar: FC<SidebarProps> = ({ className, children }) => {
return <nav className={cn("w-60 flex-shrink-0", className)}>{children}</nav>;
};
interface SidebarHeaderProps {
@@ -23,10 +23,10 @@ export const DashboardLayout: FC = () => {
{canViewDeployment && <LicenseBanner />}
<AnnouncementBanners />
<div className="flex flex-col min-h-screen">
<div className="flex flex-col h-screen justify-between">
<Navbar />
<div className="flex flex-col flex-1 min-h-0 pb-12">
<div className="flex flex-col flex-1 min-h-0 overflow-y-auto">
<Suspense fallback={<Loader />}>
<Outlet />
</Suspense>
@@ -91,7 +91,7 @@ const OrganizationSettingsLayout: FC = () => {
organizationPermissions,
}}
>
<div>
<div className="flex flex-col flex-1 min-h-0">
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
@@ -121,8 +121,8 @@ const OrganizationSettingsLayout: FC = () => {
)}
</BreadcrumbList>
</Breadcrumb>
<hr className="h-px border-none bg-border" />
<div className="px-10 max-w-screen-2xl">
<div className="h-px border-none bg-border" />
<div className="flex flex-col flex-1 min-h-0 pl-10">
<Suspense fallback={<Loader />}>
<Outlet />
</Suspense>
@@ -13,7 +13,7 @@ export const OrganizationSidebar: FC = () => {
useOrganizationSettings();
return (
<BaseSidebar>
<BaseSidebar className="pt-10">
<OrganizationSidebarView
activeOrganization={organization}
orgPermissions={organizationPermissions}
@@ -5,9 +5,9 @@ import { OrganizationSidebar } from "./OrganizationSidebar";
const OrganizationSidebarLayout: FC = () => {
return (
<div className="flex flex-row gap-28 py-10">
<div className="flex flex-row flex-1 min-h-0 w-full">
<OrganizationSidebar />
<main css={{ flexGrow: 1 }}>
<main className="flex flex-col items-center flex-1 min-h-0 h-full overflow-y-auto w-full px-10 pt-10">
<Suspense fallback={<Loader />}>
<Outlet />
</Suspense>
+1 -1
View File
@@ -57,7 +57,7 @@ export const AuditPageView: FC<AuditPageViewProps> = ({
const isEmpty = !isLoading && auditLogs?.length === 0;
return (
<Margins>
<Margins className="pb-12">
<PageHeader>
<PageHeaderTitle>
<Stack direction="row" spacing={1} alignItems="center">
@@ -56,7 +56,7 @@ export const ConnectionLogPageView: FC<ConnectionLogPageViewProps> = ({
const isEmpty = !isLoading && connectionLogs?.length === 0;
return (
<Margins>
<Margins className="pb-12">
<PageHeader>
<PageHeaderTitle>
<Stack direction="row" spacing={1} alignItems="center">
@@ -24,7 +24,7 @@ export const CreateTemplateGalleryPageView: FC<
CreateTemplateGalleryPageViewProps
> = ({ starterTemplatesByTag, error }) => {
return (
<Margins>
<Margins className="pb-12">
<PageHeader
actions={
<Button asChild size="sm" variant="outline">
+2 -2
View File
@@ -76,7 +76,7 @@ const GroupsPage: FC = () => {
}
return (
<>
<div className="w-full max-w-screen-2xl pb-10">
{helmet}
<Stack
@@ -107,7 +107,7 @@ const GroupsPage: FC = () => {
canCreateGroup={permissions.createGroup}
groupsEnabled={groupsEnabled}
/>
</>
</div>
);
};
@@ -58,7 +58,7 @@ const CustomRolesPage: FC = () => {
}
return (
<>
<div className="w-full max-w-screen-2xl pb-10">
<Helmet>
<title>
{pageTitle(
@@ -116,7 +116,7 @@ const CustomRolesPage: FC = () => {
}}
/>
</RequirePermission>
</>
</div>
);
};
@@ -117,7 +117,7 @@ const IdpSyncPage: FC = () => {
}
return (
<>
<div className="w-full max-w-screen-2xl pb-10">
{helmet}
<div className="flex flex-col gap-12">
@@ -182,7 +182,7 @@ const IdpSyncPage: FC = () => {
</Cond>
</ChooseOne>
</div>
</>
</div>
);
};
@@ -1,4 +1,3 @@
import type { Interpolation, Theme } from "@emotion/react";
import { getErrorMessage } from "api/errors";
import { groupsByUserIdInOrganization } from "api/queries/groups";
import {
@@ -156,9 +155,7 @@ const OrganizationMembersPage: FC = () => {
</ul>
</p>
<p css={styles.test}>
Are you sure you want to remove this member?
</p>
<p className="pb-5">Are you sure you want to remove this member?</p>
</Stack>
}
/>
@@ -166,10 +163,4 @@ const OrganizationMembersPage: FC = () => {
);
};
const styles = {
test: {
paddingBottom: 20,
},
} satisfies Record<string, Interpolation<Theme>>;
export default OrganizationMembersPage;
@@ -81,7 +81,7 @@ export const OrganizationMembersPageView: FC<
updateMemberRoles,
}) => {
return (
<div>
<div className="w-full max-w-screen-2xl pb-10">
<SettingsHeader>
<SettingsHeaderTitle>Members</SettingsHeaderTitle>
</SettingsHeader>
@@ -99,7 +99,7 @@ const OrganizationProvisionerJobsPageView: FC<
}
return (
<>
<div className="w-full max-w-screen-2xl pb-10">
<Helmet>
<title>
{pageTitle(
@@ -227,7 +227,7 @@ const OrganizationProvisionerJobsPageView: FC<
</TableBody>
</Table>
</section>
</>
</div>
);
};
@@ -45,7 +45,7 @@ export const OrganizationProvisionerKeysPageView: FC<
OrganizationProvisionerKeysPageViewProps
> = ({ showPaywall, provisionerKeyDaemons, error, onRetry }) => {
return (
<section>
<section className="w-full max-w-screen-2xl pb-10">
<SettingsHeader>
<SettingsHeaderTitle>Provisioner Keys</SettingsHeaderTitle>
<SettingsHeaderDescription>
@@ -58,7 +58,7 @@ export const OrganizationProvisionersPageView: FC<
onRetry,
}) => {
return (
<section>
<section className="w-full max-w-screen-2xl pb-10">
<SettingsHeader>
<SettingsHeaderTitle>Provisioners</SettingsHeaderTitle>
<SettingsHeaderDescription>
@@ -68,7 +68,7 @@ export const OrganizationSettingsPageView: FC<
const [isDeleting, setIsDeleting] = useState(false);
return (
<div>
<div className="w-full max-w-screen-2xl pb-10">
<SettingsHeader>
<SettingsHeaderTitle>Settings</SettingsHeaderTitle>
</SettingsHeader>
@@ -108,7 +108,7 @@ export const TemplateLayout: FC<PropsWithChildren> = ({
if (error || workspacePermissionsQuery.error) {
return (
<div css={{ margin: 16 }}>
<div className="p-4">
<ErrorAlert error={error} />
</div>
);
@@ -119,7 +119,7 @@ export const TemplateLayout: FC<PropsWithChildren> = ({
}
return (
<>
<div className="pb-12">
<TemplatePageHeader
template={data.template}
activeVersion={data.activeVersion}
@@ -166,6 +166,6 @@ export const TemplateLayout: FC<PropsWithChildren> = ({
<Suspense fallback={<Loader />}>{children}</Suspense>
</TemplateLayoutContext.Provider>
</Margins>
</>
</div>
);
};
@@ -205,7 +205,7 @@ export const TemplatesPageView: FC<TemplatesPageViewProps> = ({
const isEmpty = templates && templates.length === 0;
return (
<Margins>
<Margins className="pb-12">
<PageHeader
actions={
canCreateTemplates && (
@@ -21,6 +21,7 @@ import {
terminalFontLabels,
terminalFonts,
} from "theme/constants";
import { cn } from "utils/cn";
import { Section } from "../Section";
interface AppearanceFormProps {
@@ -164,7 +165,7 @@ const AutoThemePreviewButton: FC<AutoThemePreviewButtonProps> = ({
onChange={onSelect}
css={{ ...visuallyHidden }}
/>
<label htmlFor={displayName} className={className}>
<label htmlFor={displayName} className={cn("relative", className)}>
<ThemePreview
css={{
// This half is absolute to not advance the layout (which would offset the second half)