fix(site): stack settings layouts on mobile (#27334)

## Problem

On mobile viewports every settings shell renders a fixed 240px sidebar
next to the content in a non-responsive flex row, leaving the content
almost no width. The MCP Servers page is worst: its fixed-layout table
cannot shrink, so the whole page collapses into a single cramped column.

## Changes

- `Sidebar` component: full width below the `lg` breakpoint, `w-60` at
`lg`+.
- Six settings layouts (AI, Deployment, Organization, User, Workspace,
Template) stack the nav above the content below `lg` and keep the
previous side-by-side spacing at `lg`+. Content wrappers get `min-w-0`
so flex children cannot force overflow, and horizontal padding tightens
on small screens.
- MCP servers table gets `min-w-[640px]` so the existing `overflow-auto`
wrapper provides horizontal scrolling instead of colliding column
headers.

Tailwind class changes only; no component or behavior changes.

## Testing

- `pnpm check` and `pnpm run lint:types` pass.
- Dogfood UAT on a dev deployment: at 390x844 the MCP Servers,
Deployment, Account, and Template settings pages stack nav-above-content
with no horizontal body overflow and a scrollable MCP table; boundary
verified stacked at 1023px and side-by-side at 1024px; at 1440x900 the
layouts are pixel-identical to before (240px sidebar, 112px gap, 40px
padding).

Closes CODAGT-828.

> Created by Mux, an AI agent, on Mike's behalf.
This commit is contained in:
Michael Suchacz
2026-07-20 19:35:23 +02:00
committed by GitHub
parent 66e6f40b8b
commit f18c664be2
8 changed files with 24 additions and 20 deletions
+5 -1
View File
@@ -8,7 +8,11 @@ interface SidebarProps {
}
export const Sidebar: FC<SidebarProps> = ({ className, children }) => {
return <nav className={cn("w-60 flex-shrink-0", className)}>{children}</nav>;
return (
<nav className={cn("w-full lg:w-60 flex-shrink-0", className)}>
{children}
</nav>
);
};
interface SidebarHeaderProps {
@@ -51,10 +51,10 @@ const DeploymentSettingsLayout: FC = () => {
</BreadcrumbList>
</Breadcrumb>
<div className="h-px border-none bg-border" />
<section className="px-10 max-w-screen-2xl mx-auto">
<div className="flex flex-row gap-28 py-10">
<section className="px-4 sm:px-6 lg:px-10 max-w-screen-2xl mx-auto">
<div className="flex flex-col gap-8 py-6 lg:flex-row lg:gap-28 lg:py-10">
<DeploymentSidebar />
<div className="grow">
<div className="grow min-w-0">
<Suspense fallback={<Loader />}>
<Outlet />
</Suspense>
@@ -5,10 +5,10 @@ import { OrganizationSidebar } from "./OrganizationSidebar";
const OrganizationSidebarLayout: FC = () => {
return (
<section className="px-10 max-w-screen-2xl mx-auto">
<div className="flex flex-row gap-28 py-10">
<section className="px-4 sm:px-6 lg:px-10 max-w-screen-2xl mx-auto">
<div className="flex flex-col gap-8 py-6 lg:flex-row lg:gap-28 lg:py-10">
<OrganizationSidebar />
<div className="grow">
<div className="grow min-w-0">
<Suspense fallback={<Loader />}>
<Outlet />
</Suspense>
@@ -5,10 +5,10 @@ import { AISettingsSidebar } from "#/modules/management/AISettingsSidebar";
const AISettingsLayout = () => {
return (
<section className="px-10 w-full max-w-screen-2xl mx-auto">
<div className="flex flex-row gap-28 py-10">
<section className="px-4 sm:px-6 lg:px-10 w-full max-w-screen-2xl mx-auto">
<div className="flex flex-col gap-8 py-6 lg:flex-row lg:gap-28 lg:py-10">
<AISettingsSidebar />
<div className="grow">
<div className="grow min-w-0">
<Suspense fallback={<Loader />}>
<Outlet />
</Suspense>
@@ -55,7 +55,7 @@ const MCPServersPageView: FC<MCPServersPageViewProps> = ({
<ErrorAlert error={error} />
</div>
)}
<Table className="table-fixed" aria-label="MCP servers">
<Table className="table-fixed min-w-[640px]" aria-label="MCP servers">
<TableHeader>
<TableRow>
<TableHead className="w-1/2">Name</TableHead>
@@ -52,8 +52,8 @@ export const TemplateSettingsLayout: FC = () => {
<>
<title>{pageTitle(templateName, "Settings")}</title>
<Margins>
<div className="flex flex-row gap-20 py-12">
<Margins className="max-sm:!px-4">
<div className="flex flex-col gap-8 py-6 lg:flex-row lg:gap-20 lg:py-12">
{templateQuery.isError || permissionsQuery.isError ? (
<ErrorAlert error={templateQuery.error} />
) : (
@@ -65,7 +65,7 @@ export const TemplateSettingsLayout: FC = () => {
>
<Sidebar template={templateQuery.data} />
<Suspense fallback={<Loader />}>
<div className="w-full">
<div className="w-full min-w-0">
<Outlet />
</div>
</Suspense>
+3 -3
View File
@@ -29,10 +29,10 @@ const Layout: FC = () => {
</BreadcrumbList>
</Breadcrumb>
<div className="h-px border-none bg-border" />
<section className="px-10 max-w-screen-2xl mx-auto">
<div className="flex flex-row gap-28 py-10">
<section className="px-4 sm:px-6 lg:px-10 max-w-screen-2xl mx-auto">
<div className="flex flex-col gap-8 py-6 lg:flex-row lg:gap-28 lg:py-10">
<Sidebar user={me} />
<div className="grow">
<div className="grow min-w-0">
<Suspense fallback={<Loader />}>
<Outlet />
</Suspense>
@@ -35,8 +35,8 @@ export const WorkspaceSettingsLayout: FC = () => {
<>
<title>{pageTitle(workspaceName, "Settings")}</title>
<Margins>
<div className="flex flex-row gap-20 py-12">
<Margins className="max-sm:!px-4">
<div className="flex flex-col gap-8 py-6 lg:flex-row lg:gap-20 lg:py-12">
{error ? (
<ErrorAlert error={error} />
) : (
@@ -50,7 +50,7 @@ export const WorkspaceSettingsLayout: FC = () => {
>
<Sidebar />
<Suspense fallback={<Loader />}>
<div className="w-full">
<div className="w-full min-w-0">
<Outlet />
</div>
</Suspense>