Files
openclaw/ui/src/styles/layout.mobile.css
Val Alexander 0849cac106 fix(a11y): B-1+B-2+B-3 — contrast, focus states, minimum font sizes (#89822)
* fix(a11y): B-1 — raise muted text contrast to ≥4.8:1 WCAG AA

* fix(ui): C-1 — ChatSidePanel joins glass surface language

* feat(mobile): D-1 — hamburger overlay nav below 900px

- Esc key now closes nav drawer (globalKeydownHandler)
- Nav item tap targets bumped to min-height: 44px + padding: 10px 16px
  in the ≤1100px drawer breakpoint (was 40px / 0 12px)
- Hamburger toggle + overlay drawer were already wired in app-render.ts;
  this completes close-on-Esc and ensures accessible tap targets

* fix(a11y): B-2 — consistent focus-visible states distinct from hover

* fix(a11y): B-3 — lift all sub-12px text to 12px minimum

* fix(a11y): narrow focus and CSS scope

* fix(a11y): finish focus-visible selectors
2026-06-13 02:57:17 -05:00

1081 lines
22 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* ===========================================
Mobile Layout
=========================================== */
@media (max-width: 1320px) {
.content--chat .content-header {
align-items: center;
gap: 8px;
row-gap: 0;
min-height: 44px;
max-height: 44px;
overflow: visible;
}
.content--chat .content-header > div:first-child {
min-width: 0;
}
.content--chat .page-meta {
align-self: center;
height: 36px;
align-items: center;
min-width: 0;
justify-content: flex-end;
flex-wrap: nowrap;
row-gap: 0;
}
.content--chat .chat-controls {
margin-left: 0;
justify-content: flex-end;
row-gap: 0;
}
.chat-controls__session-row {
grid-template-columns: minmax(96px, 5fr) minmax(112px, 7fr) minmax(164px, 8fr);
grid-template-areas: "agent session model";
align-items: center;
gap: 8px;
width: 100%;
}
.chat-controls__session-row--single-agent {
grid-template-columns: minmax(112px, 7fr) minmax(164px, 8fr);
grid-template-areas: "session model";
}
.chat-controls__session-row--has-quota {
grid-template-columns:
minmax(96px, 5fr) minmax(112px, 7fr) minmax(164px, 8fr)
minmax(96px, auto);
grid-template-areas: "agent session model quota";
}
.chat-controls__session-row--single-agent.chat-controls__session-row--has-quota {
grid-template-columns: minmax(112px, 7fr) minmax(164px, 8fr) minmax(96px, auto);
grid-template-areas: "session model quota";
}
.chat-controls__agent {
grid-area: agent;
}
.chat-controls__session-picker {
grid-area: session;
}
.chat-controls__model {
grid-area: model;
}
.chat-controls__quota {
grid-area: quota;
min-width: 96px;
}
.chat-controls__session,
.chat-controls__agent,
.chat-controls__model {
min-width: 0;
max-width: none;
}
.chat-controls__session select,
.chat-controls__agent select,
.chat-controls__inline-select-trigger {
width: 100%;
max-width: none;
}
}
/* Tablet and smaller: switch the left nav to a slide-over drawer. */
@media (max-width: 1100px) {
.shell,
.shell--nav-collapsed {
grid-template-columns: minmax(0, 1fr);
grid-template-rows: var(--shell-topbar-height) minmax(0, 1fr);
grid-template-areas:
"topbar"
"content";
}
.shell-nav,
.shell--nav-collapsed .shell-nav {
position: fixed;
top: 0;
bottom: 0;
left: 0;
z-index: 70;
width: min(86vw, 320px);
min-width: 0;
border-right: none;
box-shadow: 0 30px 80px color-mix(in srgb, black 40%, transparent);
transform: translateX(-100%);
opacity: 0;
pointer-events: none;
transition:
transform var(--shell-focus-duration) var(--shell-focus-ease),
opacity var(--shell-focus-duration) var(--shell-focus-ease);
}
.shell--nav-collapsed:not(.shell--nav-drawer-open) .shell-nav {
width: var(--shell-nav-rail-width);
transform: translateX(0);
opacity: 1;
pointer-events: auto;
box-shadow: none;
}
.shell--nav-drawer-open .shell-nav,
.shell--nav-collapsed.shell--nav-drawer-open .shell-nav {
transform: translateX(0);
opacity: 1;
pointer-events: auto;
}
.shell-nav-backdrop {
display: block;
position: fixed;
inset: 0;
z-index: 65;
border: 0;
background: color-mix(in srgb, black 52%, transparent);
opacity: 0;
pointer-events: none;
transition: opacity var(--shell-focus-duration) var(--shell-focus-ease);
}
.shell--nav-drawer-open .shell-nav-backdrop {
opacity: 1;
pointer-events: auto;
}
/* Show the hamburger toggle at the same breakpoint where the drawer takes over. */
.topbar-nav-toggle {
display: inline-flex;
}
.sidebar,
.sidebar--collapsed {
width: 100%;
min-width: 0;
flex: 1 1 auto;
flex-direction: column;
align-items: stretch;
border-right: none;
}
.sidebar-shell,
.sidebar--collapsed .sidebar-shell {
padding: 18px 16px 14px;
border-radius: 0;
}
.shell--nav-collapsed:not(.shell--nav-drawer-open) .sidebar-shell,
.shell--nav-collapsed:not(.shell--nav-drawer-open) .sidebar--collapsed .sidebar-shell {
padding: 12px 8px 10px;
}
.sidebar-shell__header {
min-height: 0;
padding: 0 4px 16px;
}
.sidebar-shell__header .nav-collapse-toggle {
display: none;
}
.shell--nav-drawer-open .sidebar-shell__header .nav-collapse-toggle {
display: flex;
width: 44px;
min-width: 44px;
height: 44px;
}
.shell--nav-collapsed:not(.shell--nav-drawer-open) .sidebar-shell__header {
justify-content: center;
align-items: center;
gap: 0;
padding: 0 2px 16px;
}
.sidebar-nav,
.sidebar--collapsed .sidebar-nav {
flex: 1 1 auto;
display: block;
padding: 0;
overflow-x: hidden;
overflow-y: auto;
scrollbar-width: none;
}
.sidebar-nav::-webkit-scrollbar,
.sidebar--collapsed .sidebar-nav::-webkit-scrollbar {
display: none;
}
.nav-section,
.sidebar--collapsed .nav-section {
display: grid;
margin-bottom: 16px;
}
.sidebar-nav .nav-section__label,
.sidebar--collapsed .nav-section__label {
display: flex;
}
.nav-item,
.sidebar--collapsed .nav-item {
margin: 0;
min-height: 40px;
padding: 0 12px;
font-size: 13px;
border-radius: var(--radius-md);
white-space: nowrap;
flex: 0 0 auto;
width: auto;
}
.shell--nav-collapsed:not(.shell--nav-drawer-open) .sidebar--collapsed .nav-item {
justify-content: center;
width: 44px;
min-height: 44px;
padding: 0;
margin: 0 auto;
border-radius: var(--radius-lg);
}
.sidebar--collapsed .nav-item--active::before,
.sidebar--collapsed .nav-item.active::before {
content: none;
}
.sidebar--collapsed .nav-item__text,
.sidebar--collapsed .nav-item__external-icon {
display: inline-flex;
}
.shell--nav-collapsed:not(.shell--nav-drawer-open) .sidebar--collapsed .nav-item__text,
.shell--nav-collapsed:not(.shell--nav-drawer-open) .sidebar--collapsed .nav-item__external-icon {
display: none;
}
.shell--nav-collapsed:not(.shell--nav-drawer-open) .sidebar--collapsed .nav-item--active::before,
.shell--nav-collapsed:not(.shell--nav-drawer-open) .sidebar--collapsed .nav-item.active::before {
content: "";
position: absolute;
left: 8px;
top: 10px;
bottom: 10px;
width: 3px;
border-radius: var(--radius-full);
background: color-mix(in srgb, var(--accent) 86%, transparent);
box-shadow: 0 0 14px color-mix(in srgb, var(--accent) 34%, transparent);
}
.sidebar--collapsed .sidebar-shell__footer {
padding: 12px 8px 0;
}
.sidebar--collapsed .sidebar-version {
width: auto;
min-height: 40px;
padding: 0 12px;
}
.shell--nav-collapsed:not(.shell--nav-drawer-open) .sidebar--collapsed .sidebar-shell__footer {
padding: 8px 0 2px;
}
.shell--nav-collapsed:not(.shell--nav-drawer-open) .sidebar--collapsed .sidebar-version {
width: 44px;
min-height: 44px;
padding: 0;
justify-content: center;
}
.shell--nav-collapsed:not(.shell--nav-drawer-open) .sidebar-mode-switch {
display: none;
}
}
/* Mobile-specific styles */
@media (max-width: 768px), (max-width: 932px) and (max-height: 500px) and (orientation: landscape) {
.shell {
--shell-pad: 8px;
--shell-gap: 8px;
}
/* Topbar */
.topbar {
padding: 10px 12px;
min-height: auto;
}
.topnav-shell {
flex-wrap: wrap;
gap: 10px;
}
.topnav-shell__actions {
min-width: 0;
flex: 1 1 auto;
justify-content: space-between;
gap: 10px;
align-items: stretch;
}
.topnav-shell__content {
display: none;
width: 100%;
}
.topbar-nav-toggle {
display: inline-flex;
}
.topbar-status {
gap: 6px;
width: auto;
flex-wrap: nowrap;
}
.topbar-search {
min-width: 0;
flex: 1;
}
.topbar-theme-mode {
display: none;
}
.sidebar-mode-switch {
display: block;
}
.sidebar-mode-switch .topbar-theme-mode {
display: inline-flex;
width: 100%;
justify-content: center;
}
.topbar-status .pill {
padding: 4px 8px;
font-size: 12px; /* was 11px */
gap: 4px;
}
.topbar-status .pill .mono {
display: none;
}
.topbar-status .pill span:nth-child(2) {
display: none;
}
.shell-nav,
.shell--nav-collapsed .shell-nav {
width: min(92vw, 320px);
}
.shell--nav-collapsed:not(.shell--nav-drawer-open) .shell-nav {
width: min(92vw, 320px);
transform: translateX(-100%);
opacity: 0;
pointer-events: none;
}
.sidebar-shell,
.sidebar--collapsed .sidebar-shell {
padding: 16px 14px 12px;
}
.nav-item,
.sidebar--collapsed .nav-item {
font-size: 12px;
}
/* Content */
.content-header {
display: none;
}
/* Hide the entire content-header on mobile chat — controls are in mobile gear menu */
.content--chat .content-header {
display: none;
}
.content--chat {
gap: 2px;
}
/* Show the mobile gear toggle (lives in topbar now) */
.chat-mobile-controls-wrapper {
display: flex;
position: relative;
}
.chat-mobile-controls-wrapper .chat-controls-mobile-toggle {
display: flex;
width: 44px;
min-width: 44px;
height: 44px;
}
/* The dropdown panel is viewport-clamped so narrow phones never crop controls. */
.chat-mobile-controls-wrapper .chat-controls-dropdown {
display: none;
position: fixed;
top: calc(var(--shell-topbar-height) + 8px);
right: max(8px, var(--safe-area-right));
left: auto;
z-index: 100;
width: min(420px, calc(100vw - var(--safe-area-left) - var(--safe-area-right) - 16px));
background: var(--card, #161b22);
border: 1px solid var(--border, #30363d);
border-radius: var(--radius-md);
padding: 10px;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
flex-direction: column;
gap: 8px;
min-width: 0;
max-height: min(72vh, 520px);
overflow: auto;
overscroll-behavior: contain;
}
.chat-mobile-controls-wrapper .chat-controls-dropdown.open {
display: flex;
}
.chat-mobile-controls-wrapper .chat-controls-dropdown .chat-controls {
display: flex;
flex-direction: column;
align-items: stretch;
gap: 8px;
width: 100%;
}
.chat-mobile-controls-wrapper .chat-controls-dropdown .chat-controls__session-row {
display: grid;
grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
grid-template-areas:
"agent session"
"model model";
gap: 8px;
width: 100%;
}
.chat-mobile-controls-wrapper .chat-controls-dropdown .chat-controls__session-row--single-agent {
grid-template-columns: minmax(0, 1fr);
grid-template-areas:
"session"
"model";
}
.chat-mobile-controls-wrapper .chat-controls-dropdown .chat-controls__session-row--has-quota {
grid-template-areas:
"agent session"
"model model"
"quota quota";
}
.chat-mobile-controls-wrapper
.chat-controls-dropdown
.chat-controls__session-row--single-agent.chat-controls__session-row--has-quota {
grid-template-areas:
"session"
"model"
"quota";
}
.chat-mobile-controls-wrapper .chat-controls-dropdown .chat-controls__session {
min-width: unset;
max-width: unset;
width: 100%;
}
.chat-mobile-controls-wrapper .chat-controls-dropdown .chat-controls__agent {
grid-area: agent;
min-width: unset;
max-width: unset;
width: 100%;
}
.chat-mobile-controls-wrapper .chat-controls-dropdown .chat-controls__session-picker {
grid-area: session;
}
.chat-mobile-controls-wrapper .chat-controls-dropdown .chat-controls__session-trigger {
min-height: 44px;
padding: 10px 12px;
font-size: 14px;
}
.chat-mobile-controls-wrapper .chat-controls-dropdown .chat-session-picker {
position: static;
width: 100%;
max-height: min(52vh, 420px);
margin-top: 8px;
box-shadow: none;
}
.chat-mobile-controls-wrapper .chat-controls-dropdown .chat-session-picker__search input {
min-height: 44px;
font-size: 14px;
}
.chat-mobile-controls-wrapper
.chat-controls-dropdown
.chat-session-picker
.chat-session-picker__icon-button.btn--icon {
flex: 0 0 44px;
width: 44px;
min-width: 44px;
height: 44px;
padding: 0;
}
.chat-mobile-controls-wrapper .chat-controls-dropdown .chat-controls__model {
grid-area: model;
}
.chat-mobile-controls-wrapper .chat-controls-dropdown .chat-controls__quota {
width: 100%;
min-width: 0;
min-height: 40px;
}
.chat-mobile-controls-wrapper .chat-controls-dropdown .chat-controls__inline-select-trigger {
display: flex;
width: 100%;
max-width: none;
min-height: 44px;
font-size: 14px;
}
.chat-mobile-controls-wrapper .chat-controls-dropdown .chat-controls__inline-select-menu {
bottom: auto;
top: calc(100% + 6px);
width: 100%;
}
.chat-mobile-controls-wrapper .chat-controls-dropdown .chat-controls__session select,
.chat-mobile-controls-wrapper .chat-controls-dropdown .chat-controls__session-trigger {
width: 100%;
font-size: 14px;
min-height: 44px;
padding: 10px 12px;
}
.chat-mobile-controls-wrapper .chat-controls-dropdown .chat-controls__agent select {
width: 100%;
font-size: 14px;
min-height: 44px;
padding: 10px 12px;
}
.chat-mobile-controls-wrapper .chat-controls-dropdown .chat-controls__thinking {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
align-items: center;
justify-content: stretch;
gap: 8px;
width: 100%;
padding: 0;
}
.chat-mobile-controls-wrapper .chat-controls-dropdown .btn--icon {
width: 100%;
min-width: 0;
height: 44px;
}
.content {
padding: 4px 4px 16px;
gap: 12px;
}
/* Cards */
.card {
padding: 12px;
border-radius: var(--radius-md);
}
.card-title {
font-size: 13px;
}
/* Stats */
.stat-grid {
gap: 8px;
grid-template-columns: repeat(2, 1fr);
}
.stat {
padding: 10px;
border-radius: var(--radius-md);
}
.stat-label {
font-size: 12px; /* was 11px */
}
.stat-value {
font-size: 18px;
}
/* Notes */
.note-grid {
grid-template-columns: 1fr;
gap: 8px;
}
/* Forms */
.form-grid {
grid-template-columns: 1fr;
gap: 10px;
}
.field input,
.field textarea,
.field select {
padding: 8px 10px;
border-radius: var(--radius-md);
font-size: 14px;
}
/* Buttons */
.btn {
padding: 8px 12px;
font-size: 12px;
}
/* Pills */
.pill {
padding: 4px 10px;
font-size: 12px;
}
/* Chat */
.chat-header {
flex-direction: column;
align-items: stretch;
gap: 8px;
}
.chat-header__left {
flex-direction: column;
align-items: stretch;
}
.chat-header__right {
justify-content: space-between;
}
.chat-session {
min-width: unset;
width: 100%;
}
.chat-thread {
margin-top: 0;
padding: 0 8px 12px;
}
.chat-msg {
max-width: 90%;
}
.chat-bubble {
padding: 8px 12px;
border-radius: var(--radius-md);
}
.chat-compose {
gap: 8px;
}
.chat-compose__field textarea {
min-height: 60px;
padding: 8px 10px;
border-radius: var(--radius-md);
font-size: 14px;
}
.agent-chat__input {
margin: 0 8px calc(10px + var(--safe-area-bottom));
}
.agent-chat__toolbar {
align-items: stretch;
gap: 8px;
padding: 6px 8px;
}
.agent-chat__toolbar-left,
.agent-chat__toolbar-right {
flex-wrap: wrap;
gap: 6px;
}
.agent-chat__input-btn,
.agent-chat__toolbar .btn--ghost,
.chat-send-btn {
width: 44px;
min-width: 44px;
height: 44px;
}
.agent-chat__input-btn svg,
.agent-chat__toolbar .btn--ghost svg,
.chat-send-btn svg {
width: 16px;
height: 16px;
}
/* Log stream */
.log-stream {
border-radius: var(--radius-md);
max-height: 380px;
}
/* Reset the desktop fill-height chain on mobile — single page scroll is
more usable on small viewports than a tiny pinned log panel.
Selectors are intentionally double-classed so they outrank the
desktop rules in components.css / config-quick.css, which are
imported AFTER this file (see ui/src/styles.css). */
.card--fill-height.card--fill-height .log-stream {
flex: none;
min-height: 200px;
max-height: 380px;
}
.content.content--logs {
display: block;
overflow-y: auto;
}
.content.content--logs .settings-workspace {
display: block;
height: auto;
flex: initial;
}
.content.content--logs .settings-workspace__body {
display: block;
flex: initial;
}
.log-row {
grid-template-columns: 1fr;
gap: 4px;
padding: 8px;
}
.log-time {
font-size: 12px; /* was 10px */
}
.log-level {
font-size: 12px; /* was 9px */
}
.log-subsystem {
font-size: 12px; /* was 11px */
}
.log-message {
font-size: 12px;
}
/* Lists */
.list-item {
padding: 10px;
border-radius: var(--radius-md);
}
.list-title {
font-size: 13px;
}
.list-sub {
font-size: 12px; /* was 11px */
}
/* Code blocks */
.code-block {
padding: 8px;
border-radius: var(--radius-md);
font-size: 12px; /* was 11px */
}
.theme-orb__trigger {
width: 26px;
height: 26px;
font-size: 13px;
}
}
/* Small mobile */
@media (max-width: 400px) {
.shell {
--shell-pad: 4px;
}
.topbar {
padding: 8px 10px;
}
.brand-title {
font-size: 13px;
}
.nav-item {
padding: 6px 8px;
font-size: 12px; /* was 11px */
}
.content {
padding: 4px 4px 12px;
gap: 10px;
}
.card {
padding: 10px;
}
.stat {
padding: 8px;
}
.stat-value {
font-size: 16px;
}
.chat-bubble {
padding: 8px 10px;
}
.chat-compose__field textarea {
min-height: 52px;
padding: 8px 10px;
font-size: 13px;
}
.btn {
padding: 6px 10px;
font-size: 12px; /* was 11px */
}
.topbar-status .pill {
padding: 3px 6px;
font-size: 12px; /* was 10px */
}
.theme-orb__trigger {
width: 24px;
height: 24px;
font-size: 12px;
}
}
/* ===========================================
Sessions table responsive column hiding
=========================================== */
/* nth-child is 1-based and includes the checkbox column (col 1). */
/* ≤1400px: hide Verbose (col 12) and Reasoning (col 13) */
@media (max-width: 1400px) {
.data-table.sessions-table {
min-width: 1120px;
}
.sessions-table th:nth-child(12),
.sessions-table td:nth-child(12),
.sessions-table th:nth-child(13),
.sessions-table td:nth-child(13) {
display: none;
}
}
/* ≤1100px: also hide Fast (col 11) and Kind (col 4) */
@media (max-width: 1100px) {
.data-table.sessions-table {
min-width: 930px;
}
.sessions-table th:nth-child(4),
.sessions-table td:nth-child(4),
.sessions-table th:nth-child(11),
.sessions-table td:nth-child(11) {
display: none;
}
.data-table th,
.data-table td {
padding: 8px 10px;
}
}
/* ≤900px: also hide Thinking (col 10) and Label (col 3) */
@media (max-width: 900px) {
.data-table.sessions-table {
min-width: 720px;
}
.sessions-table th:nth-child(3),
.sessions-table td:nth-child(3),
.sessions-table th:nth-child(10),
.sessions-table td:nth-child(10) {
display: none;
}
}
/* ≤768px: also hide Tokens (col 8); tighten padding; stack pagination */
@media (max-width: 768px) {
.data-table.sessions-table {
min-width: 560px;
}
.sessions-table th:nth-child(8),
.sessions-table td:nth-child(8) {
display: none;
}
.data-table th,
.data-table td {
padding: 8px 6px;
font-size: 12px;
}
.data-table-pagination {
flex-direction: column;
align-items: stretch;
gap: 8px;
padding: 10px 8px;
}
.data-table-pagination__info {
text-align: center;
}
.data-table-pagination__controls {
justify-content: center;
}
.data-table-search input {
font-size: 14px;
padding: 8px 10px;
}
.data-table-wrapper {
border-radius: var(--radius-sm);
}
.session-key-cell {
max-width: 200px;
}
.session-compaction-col {
width: 96px;
min-width: 86px;
}
.session-compaction-trigger {
padding: 6px 7px;
}
.session-details-panel {
padding: 12px;
}
.session-details-panel__hero,
.session-details-section {
padding: 12px;
}
.session-details-panel__title {
max-width: 100%;
}
.session-details-grid {
grid-template-columns: minmax(0, 1fr);
}
.session-key-cell .session-link,
.session-key-cell .session-key-display-name {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
overflow-wrap: normal;
word-break: normal;
}
.filters {
flex-wrap: wrap;
gap: 8px;
}
}
/* ≤500px: hide Runtime (col 6) and Updated (col 7); keep live status visible */
@media (max-width: 500px) {
.data-table.sessions-table {
min-width: 340px;
}
.sessions-table th:nth-child(6),
.sessions-table td:nth-child(6),
.sessions-table th:nth-child(7),
.sessions-table td:nth-child(7) {
display: none;
}
.data-table.sessions-table .data-table-key-col {
width: 106px;
min-width: 106px;
max-width: 106px;
}
.sessions-table .session-status-col {
width: 76px;
min-width: 76px;
max-width: 76px;
}
.sessions-table .session-status-badge {
max-width: 72px;
gap: 5px;
padding: 2px 6px;
}
.sessions-table .session-goal-chip {
grid-template-columns: minmax(0, 1fr);
max-width: 72px;
gap: 0;
padding: 2px 6px;
}
.sessions-table .session-goal-chip__objective {
display: none;
}
.sessions-table .session-compaction-col {
width: 84px;
min-width: 84px;
}
.data-table th,
.data-table td {
padding: 6px 4px;
font-size: 12px; /* was 11px */
}
.session-key-cell {
max-width: 140px;
}
}