mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
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:
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user