From f2f3ba2eaff30439215b57c4d3f7facf77e1788d Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Thu, 13 Aug 2026 12:34:50 -0700 Subject: [PATCH] refactor(ui): consolidate responsive breakpoints onto a canonical ladder (#123160) Use the 400, 560, 640, 768, 900, 1100, and 1320px max-width ladder. Round noncanonical thresholds up to the next rung so compact layouts engage before desktop layouts become cramped. Move the 1180px agent-tool summary breakpoint to 1320px because the persistent desktop rail leaves about a 1020px content column at that viewport; 1100px would coincide with the rail disappearing and the content expanding. Stylelint now enforces the ladder and the existing compound-query exceptions. --- config/stylelint.config.mjs | 8 ++++++++ ui/src/pages/activity/run-inspector.css | 2 +- ui/src/pages/portals/portals.css | 2 +- ui/src/styles/activity.css | 2 +- ui/src/styles/approval.css | 2 +- ui/src/styles/chat/layout.css | 2 +- ui/src/styles/chat/sidebar.css | 2 +- ui/src/styles/chat/tool-cards.css | 2 +- ui/src/styles/components.css | 12 ++++++------ ui/src/styles/config.css | 2 +- ui/src/styles/cron.css | 2 +- ui/src/styles/custodian-panel.css | 2 +- ui/src/styles/custodian.css | 2 +- ui/src/styles/dreams.css | 2 +- ui/src/styles/hub-tabs.css | 2 +- ui/src/styles/layout.mobile.css | 4 ++-- ui/src/styles/lobster-pet.css | 2 +- ui/src/styles/logbook.css | 4 ++-- ui/src/styles/memory-import.css | 2 +- ui/src/styles/memory-overview.css | 2 +- ui/src/styles/model-providers.css | 2 +- ui/src/styles/option-card.css | 2 +- ui/src/styles/secrets-store.css | 2 +- ui/src/styles/sessions.css | 2 +- ui/src/styles/skill-workshop.css | 8 ++++---- ui/src/styles/usage.css | 2 +- ui/src/styles/workboard.css | 2 +- 27 files changed, 44 insertions(+), 36 deletions(-) diff --git a/config/stylelint.config.mjs b/config/stylelint.config.mjs index 089c0b36cd77..c36af26b5aa3 100644 --- a/config/stylelint.config.mjs +++ b/config/stylelint.config.mjs @@ -29,6 +29,14 @@ export default { files: ["**/*.css"], rules: { "color-no-hex": true, + // Control UI max-width breakpoints use one ladder: 400, 560, 640, + // 768, 900, 1100, and 1320px. Round thresholds up to the next rung + // so compact layouts engage before desktop layouts become cramped. + "media-feature-name-value-allowed-list": { + "max-width": ["400px", "560px", "640px", "768px", "900px", "1100px", "1320px", "932px"], + "max-height": ["500px"], + "min-width": ["769px", "933px", "1121px", "1400px", "1600px"], + }, }, }, { diff --git a/ui/src/pages/activity/run-inspector.css b/ui/src/pages/activity/run-inspector.css index 39baa4566e48..f0c9e8e527a4 100644 --- a/ui/src/pages/activity/run-inspector.css +++ b/ui/src/pages/activity/run-inspector.css @@ -173,7 +173,7 @@ gap: var(--space-1); } -@media (max-width: 720px) { +@media (max-width: 768px) { .run-inspector__fact, .run-inspector__values > div { grid-template-columns: 1fr; diff --git a/ui/src/pages/portals/portals.css b/ui/src/pages/portals/portals.css index c2835ff6722f..c1249383302e 100644 --- a/ui/src/pages/portals/portals.css +++ b/ui/src/pages/portals/portals.css @@ -199,7 +199,7 @@ font-size: var(--control-ui-text-sm); } -@media (max-width: 760px) { +@media (max-width: 768px) { .portals-layout { grid-template-columns: minmax(0, 1fr); min-height: auto; diff --git a/ui/src/styles/activity.css b/ui/src/styles/activity.css index ff82f9fd15dc..ca3bb0fe27c1 100644 --- a/ui/src/styles/activity.css +++ b/ui/src/styles/activity.css @@ -215,7 +215,7 @@ openclaw-activity-page { font-size: var(--control-ui-text-sm); } -@media (max-width: 720px) { +@media (max-width: 768px) { .activity-entry__meta { white-space: normal; } diff --git a/ui/src/styles/approval.css b/ui/src/styles/approval.css index 4f1f4d25741d..d47e588834d8 100644 --- a/ui/src/styles/approval.css +++ b/ui/src/styles/approval.css @@ -389,7 +389,7 @@ } } -@media (max-width: 600px) { +@media (max-width: 640px) { .approval-page { align-content: start; place-items: start center; diff --git a/ui/src/styles/chat/layout.css b/ui/src/styles/chat/layout.css index cdca7a8c28e6..afaf12839939 100644 --- a/ui/src/styles/chat/layout.css +++ b/ui/src/styles/chat/layout.css @@ -3211,7 +3211,7 @@ button.chat-reply-preview--message:disabled { padding: 0; } -@media (max-width: 860px) { +@media (max-width: 900px) { .agent-chat__input-btn { width: 36px; min-width: 36px; diff --git a/ui/src/styles/chat/sidebar.css b/ui/src/styles/chat/sidebar.css index 6b073863b1d1..e64056d8c76f 100644 --- a/ui/src/styles/chat/sidebar.css +++ b/ui/src/styles/chat/sidebar.css @@ -1744,7 +1744,7 @@ openclaw-session-discussion { margin-bottom: 0.95em; } -@media (max-width: 720px) { +@media (max-width: 768px) { .sidebar-markdown-shell__toolbar { flex-direction: column; align-items: stretch; diff --git a/ui/src/styles/chat/tool-cards.css b/ui/src/styles/chat/tool-cards.css index 9998d2a29fb8..56f94803a214 100644 --- a/ui/src/styles/chat/tool-cards.css +++ b/ui/src/styles/chat/tool-cards.css @@ -2134,7 +2134,7 @@ openclaw-tooltip.chat-tasks-status__preview { } } -@media (max-width: 480px) { +@media (max-width: 560px) { .chat-tool-card__block-content { max-height: min(360px, 55vh); } diff --git a/ui/src/styles/components.css b/ui/src/styles/components.css index d2e51c4c5e8f..a006ef19ce13 100644 --- a/ui/src/styles/components.css +++ b/ui/src/styles/components.css @@ -904,7 +904,7 @@ openclaw-github-link-hovercard-provider { } } -@media (max-width: 520px) { +@media (max-width: 560px) { .github-link-hovercard { padding: 14px; } @@ -4265,7 +4265,7 @@ td.data-table-key-col { padding: clamp(24px, 3vw, 52px); } -@media (max-width: 720px) { +@media (max-width: 768px) { .md-preview-dialog__panel { width: 100%; min-height: calc(100vh - 12px); @@ -4676,7 +4676,7 @@ td.data-table-key-col { } } -@media (max-width: 1180px) { +@media (max-width: 1320px) { .agent-tool-summary { grid-template-columns: minmax(0, 1fr) auto; } @@ -4690,7 +4690,7 @@ td.data-table-key-col { } } -@media (max-width: 760px) { +@media (max-width: 768px) { .agent-tools-group__summary { flex-wrap: wrap; align-items: flex-start; @@ -4791,13 +4791,13 @@ td.data-table-key-col { } } -@media (max-width: 980px) { +@media (max-width: 1100px) { .agent-tools-list { grid-template-columns: 1fr; } } -@media (max-width: 600px) { +@media (max-width: 640px) { .agents-toolbar-row { flex-direction: column; align-items: stretch; diff --git a/ui/src/styles/config.css b/ui/src/styles/config.css index 8ef14b83e6c6..12aecdae41e5 100644 --- a/ui/src/styles/config.css +++ b/ui/src/styles/config.css @@ -938,7 +938,7 @@ height: 14px; } -@media (max-width: 820px) { +@media (max-width: 900px) { .mcp-command-card__grid { grid-template-columns: 1fr; } diff --git a/ui/src/styles/cron.css b/ui/src/styles/cron.css index 0196d670d144..3cc4fc19bab4 100644 --- a/ui/src/styles/cron.css +++ b/ui/src/styles/cron.css @@ -980,7 +980,7 @@ margin-bottom: 0; } -@media (max-width: 600px) { +@media (max-width: 640px) { .cron-run-entry__body table { display: block; overflow-x: auto; diff --git a/ui/src/styles/custodian-panel.css b/ui/src/styles/custodian-panel.css index b129a1d96347..eb892306120b 100644 --- a/ui/src/styles/custodian-panel.css +++ b/ui/src/styles/custodian-panel.css @@ -128,7 +128,7 @@ openclaw-custodian-panel { margin-left: 42px; } -@media (max-width: 600px) { +@media (max-width: 640px) { .cp--right { top: var(--shell-topbar-height, 0); right: 0; diff --git a/ui/src/styles/custodian.css b/ui/src/styles/custodian.css index 6fa198ea5d09..b35ce1ec220a 100644 --- a/ui/src/styles/custodian.css +++ b/ui/src/styles/custodian.css @@ -491,7 +491,7 @@ openclaw-custodian-page { } } -@media (max-width: 600px) { +@media (max-width: 640px) { .custodian { padding-inline: 12px; } diff --git a/ui/src/styles/dreams.css b/ui/src/styles/dreams.css index 080295256fd1..2e5bc95d11ba 100644 --- a/ui/src/styles/dreams.css +++ b/ui/src/styles/dreams.css @@ -1112,7 +1112,7 @@ /* ---- Responsive ---- */ -@media (max-width: 880px) { +@media (max-width: 900px) { .dreams { min-height: calc(100vh - 96px); } diff --git a/ui/src/styles/hub-tabs.css b/ui/src/styles/hub-tabs.css index 9a5501c8042d..a46f12029ffb 100644 --- a/ui/src/styles/hub-tabs.css +++ b/ui/src/styles/hub-tabs.css @@ -95,7 +95,7 @@ wa-tab.hub-tab:focus-visible::part(base) { justify-self: end; } -@media (min-width: 769px) and (max-width: 1024px) { +@media (min-width: 769px) and (max-width: 1100px) { .content-header.hub-page-header { grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: diff --git a/ui/src/styles/layout.mobile.css b/ui/src/styles/layout.mobile.css index f210e0b49c64..84735fad50a6 100644 --- a/ui/src/styles/layout.mobile.css +++ b/ui/src/styles/layout.mobile.css @@ -769,8 +769,8 @@ html.openclaw-native-macos body .shell--mobile-nav .topnav-shell__actions { } } -/* ≤500px: also hide Kind (col 3) and Updated (col 5); keep live status visible */ -@media (max-width: 500px) { +/* ≤560px: also hide Kind (col 3) and Updated (col 5); keep live status visible */ +@media (max-width: 560px) { .data-table.sessions-table { min-width: 320px; } diff --git a/ui/src/styles/lobster-pet.css b/ui/src/styles/lobster-pet.css index 78b9dbf6a202..0624298152ac 100644 --- a/ui/src/styles/lobster-pet.css +++ b/ui/src/styles/lobster-pet.css @@ -1767,7 +1767,7 @@ openclaw-lobster-pet[data-dex-complete]::after { filter: drop-shadow(0 0 4px rgba(244, 184, 64, 0.4)); } -@media (max-width: 540px) { +@media (max-width: 560px) { .lobsterdex-page__header { align-items: flex-start; flex-direction: column; diff --git a/ui/src/styles/logbook.css b/ui/src/styles/logbook.css index 559394bf61e1..9980d438005e 100644 --- a/ui/src/styles/logbook.css +++ b/ui/src/styles/logbook.css @@ -91,7 +91,7 @@ align-items: start; } -@media (max-width: 980px) { +@media (max-width: 1100px) { .logbook__layout { grid-template-columns: minmax(0, 1fr); } @@ -275,7 +275,7 @@ background: color-mix(in oklab, var(--warn) 12%, transparent); } -@media (max-width: 700px) { +@media (max-width: 768px) { .logbook-card__header { grid-template-columns: 4px minmax(0, 1fr); } diff --git a/ui/src/styles/memory-import.css b/ui/src/styles/memory-import.css index 961f39a805a8..86097042b35f 100644 --- a/ui/src/styles/memory-import.css +++ b/ui/src/styles/memory-import.css @@ -284,7 +284,7 @@ font-size: 10px; } -@media (max-width: 720px) { +@media (max-width: 768px) { .memory-import__backfill-dates, .memory-import__backfill-actions { justify-content: flex-start; diff --git a/ui/src/styles/memory-overview.css b/ui/src/styles/memory-overview.css index c15cc18e7890..f5986428c907 100644 --- a/ui/src/styles/memory-overview.css +++ b/ui/src/styles/memory-overview.css @@ -50,7 +50,7 @@ margin-top: var(--space-4); } -@media (max-width: 620px) { +@media (max-width: 640px) { .memory-overview__hero { grid-template-columns: 112px minmax(0, 1fr); min-height: 176px; diff --git a/ui/src/styles/model-providers.css b/ui/src/styles/model-providers.css index 977686953f72..844d32d4a93a 100644 --- a/ui/src/styles/model-providers.css +++ b/ui/src/styles/model-providers.css @@ -191,7 +191,7 @@ grid-template-columns: minmax(160px, 0.8fr) minmax(220px, 1.4fr) auto; } -@media (max-width: 700px) { +@media (max-width: 768px) { .model-providers__head { align-items: flex-start; flex-wrap: wrap; diff --git a/ui/src/styles/option-card.css b/ui/src/styles/option-card.css index def560e7e562..1a813f96911b 100644 --- a/ui/src/styles/option-card.css +++ b/ui/src/styles/option-card.css @@ -118,7 +118,7 @@ color: var(--text); } -@media (max-width: 700px) { +@media (max-width: 768px) { .option-card__choices { grid-template-columns: 1fr; } diff --git a/ui/src/styles/secrets-store.css b/ui/src/styles/secrets-store.css index a7262cf81da5..b451f64bf1de 100644 --- a/ui/src/styles/secrets-store.css +++ b/ui/src/styles/secrets-store.css @@ -202,7 +202,7 @@ padding-top: var(--space-2); } -@media (max-width: 760px) { +@media (max-width: 768px) { .secrets-store__table { min-width: 720px; } diff --git a/ui/src/styles/sessions.css b/ui/src/styles/sessions.css index 93b13da56612..f938a7566119 100644 --- a/ui/src/styles/sessions.css +++ b/ui/src/styles/sessions.css @@ -1049,7 +1049,7 @@ } /* --- Narrow layouts --- */ -@media (max-width: 760px) { +@media (max-width: 768px) { .sessions-overview { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-2); diff --git a/ui/src/styles/skill-workshop.css b/ui/src/styles/skill-workshop.css index 5d5c77403e43..9250ce284cf0 100644 --- a/ui/src/styles/skill-workshop.css +++ b/ui/src/styles/skill-workshop.css @@ -1090,7 +1090,7 @@ text-decoration-color: var(--accent); } -@media (max-width: 760px) { +@media (max-width: 768px) { .sw-triage { grid-template-columns: minmax(0, 1fr); } @@ -1369,7 +1369,7 @@ padding-block: 20px; } -@media (max-width: 820px) { +@media (max-width: 900px) { .sw-history { grid-template-columns: 58px minmax(0, 1fr); } @@ -1383,7 +1383,7 @@ } } -@media (max-width: 520px) { +@media (max-width: 560px) { .sw-history { grid-template-columns: 1fr; padding: 20px; @@ -1860,7 +1860,7 @@ flex-shrink: 0; } -@media (max-width: 720px) { +@media (max-width: 768px) { .sw-today__actions, .sw-today__upnext { grid-template-columns: 1fr; diff --git a/ui/src/styles/usage.css b/ui/src/styles/usage.css index 84b423b2033f..88a9115d04db 100644 --- a/ui/src/styles/usage.css +++ b/ui/src/styles/usage.css @@ -1937,7 +1937,7 @@ } } -@media (max-width: 600px) { +@media (max-width: 640px) { .usage-page { gap: 14px; } diff --git a/ui/src/styles/workboard.css b/ui/src/styles/workboard.css index af0f2b649d5b..3477b95124db 100644 --- a/ui/src/styles/workboard.css +++ b/ui/src/styles/workboard.css @@ -1493,7 +1493,7 @@ openclaw-workboard-card-dashboard { grid-column: 1 / -1; } -@media (max-width: 860px) { +@media (max-width: 900px) { .workboard-draft { width: 100%; height: 100dvh;