mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 17:40:44 +00:00
fix(ui): align sidebar trigger affordances
Align the Control UI and exported transcript sidebar triggers around a shared accessible hamburger affordance.
This commit is contained in:
@@ -106,6 +106,42 @@
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.sidebar-menu-trigger {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
width: 38px;
|
||||
height: 38px;
|
||||
padding: 0;
|
||||
border: 1px solid color-mix(in srgb, var(--border) 84%, transparent);
|
||||
border-radius: var(--radius-full);
|
||||
background: color-mix(in srgb, var(--bg-elevated) 80%, transparent);
|
||||
color: var(--muted);
|
||||
cursor: pointer;
|
||||
transition:
|
||||
border-color var(--duration-fast) ease,
|
||||
background var(--duration-fast) ease,
|
||||
color var(--duration-fast) ease,
|
||||
transform var(--duration-fast) ease;
|
||||
box-shadow: inset 0 1px 0 color-mix(in srgb, white 8%, transparent);
|
||||
}
|
||||
|
||||
.sidebar-menu-trigger:hover {
|
||||
border-color: color-mix(in srgb, var(--border-strong) 88%, transparent);
|
||||
background: color-mix(in srgb, var(--bg-hover) 84%, transparent);
|
||||
color: var(--text);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.sidebar-menu-trigger:active {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.sidebar-menu-trigger:focus-visible {
|
||||
outline: none;
|
||||
box-shadow: var(--focus-ring);
|
||||
}
|
||||
|
||||
.topbar-nav-toggle {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@@ -126,16 +126,6 @@
|
||||
/* Show the hamburger toggle at the same breakpoint where the drawer takes over. */
|
||||
.topbar-nav-toggle {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 38px;
|
||||
height: 38px;
|
||||
padding: 0;
|
||||
border: 1px solid color-mix(in srgb, var(--border) 84%, transparent);
|
||||
border-radius: var(--radius-full);
|
||||
background: color-mix(in srgb, var(--bg-elevated) 80%, transparent);
|
||||
color: var(--muted);
|
||||
box-shadow: inset 0 1px 0 color-mix(in srgb, white 8%, transparent);
|
||||
}
|
||||
|
||||
.sidebar,
|
||||
@@ -309,17 +299,6 @@
|
||||
|
||||
.topbar-nav-toggle {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
width: 38px;
|
||||
height: 38px;
|
||||
padding: 0;
|
||||
border: 1px solid color-mix(in srgb, var(--border) 84%, transparent);
|
||||
border-radius: var(--radius-full);
|
||||
background: color-mix(in srgb, var(--bg-elevated) 80%, transparent);
|
||||
color: var(--muted);
|
||||
box-shadow: inset 0 1px 0 color-mix(in srgb, white 8%, transparent);
|
||||
}
|
||||
|
||||
.topbar-status {
|
||||
|
||||
@@ -11,6 +11,15 @@ function readMobileCss(): string {
|
||||
return readFileSync(cssPath!, "utf8");
|
||||
}
|
||||
|
||||
function readLayoutCss(): string {
|
||||
const cssPath = [
|
||||
resolve(process.cwd(), "ui/src/styles/layout.css"),
|
||||
resolve(process.cwd(), "..", "ui/src/styles/layout.css"),
|
||||
].find((candidate) => existsSync(candidate));
|
||||
expect(cssPath).toBeTruthy();
|
||||
return readFileSync(cssPath!, "utf8");
|
||||
}
|
||||
|
||||
describe("chat header responsive mobile styles", () => {
|
||||
it("keeps the chat header and session controls from clipping on narrow widths", () => {
|
||||
const css = readMobileCss();
|
||||
@@ -21,3 +30,19 @@ describe("chat header responsive mobile styles", () => {
|
||||
expect(css).toContain(".chat-controls__thinking-select");
|
||||
});
|
||||
});
|
||||
|
||||
describe("sidebar menu trigger styles", () => {
|
||||
it("keeps the mobile sidebar trigger visibly interactive on hover and keyboard focus", () => {
|
||||
const css = readLayoutCss();
|
||||
|
||||
expect(css).toContain(".sidebar-menu-trigger {");
|
||||
expect(css).toContain("cursor: pointer;");
|
||||
expect(css).toContain(".sidebar-menu-trigger:hover {");
|
||||
expect(css).toContain("background: color-mix(in srgb, var(--bg-hover) 84%, transparent);");
|
||||
expect(css).toContain("color: var(--text);");
|
||||
expect(css).toContain(".sidebar-menu-trigger:focus-visible {");
|
||||
expect(css).toContain("box-shadow: var(--focus-ring);");
|
||||
expect(css).toContain(".topbar-nav-toggle {");
|
||||
expect(css).toContain("display: none;");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1341,7 +1341,7 @@ export function renderApp(state: AppViewState) {
|
||||
<div class="topnav-shell">
|
||||
<button
|
||||
type="button"
|
||||
class="topbar-nav-toggle"
|
||||
class="sidebar-menu-trigger topbar-nav-toggle"
|
||||
@click=${() => {
|
||||
state.navDrawerOpen = !navDrawerOpen;
|
||||
}}
|
||||
|
||||
@@ -393,6 +393,7 @@ describe("control UI routing", () => {
|
||||
}
|
||||
|
||||
expect(toggle.classList.contains("topbar-nav-toggle")).toBe(true);
|
||||
expect(toggle.classList.contains("sidebar-menu-trigger")).toBe(true);
|
||||
expect(actions.classList.contains("topnav-shell__actions")).toBe(true);
|
||||
expect(topShell.firstElementChild).toBe(toggle);
|
||||
expect(topShell.querySelector(".topbar-nav-toggle")).toBe(toggle);
|
||||
|
||||
Reference in New Issue
Block a user