style(web): size + space the toolbar icon buttons to match the header

Make the server-list toolbar's expand/collapse toggle and open/close-monitoring
icons the same width and spacing as the header's theme / client-settings icons:

- ListToggle (default variant), PinColumnButton, and the MonitoringControls
  close button now render as `ActionIcon variant="subtle" size={36}` (glyph 20),
  matching the header's 36px ActionIcons, instead of wider `Button`s.
- ServerListControls uses `gap="sm"` so its buttons sit the same 12px apart as
  the header's RightSection controls.

Update a TaskListPanel test that found the toggle by a brittle
`mantine-Button-root` class to select it by its accessible name instead.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BrihGWcrM9JGRyu41nzZYw
This commit is contained in:
cliffhall 2026-07-10 20:49:18 -04:00
commit ea8715c9c4
5 changed files with 28 additions and 19 deletions

View file

@ -1,4 +1,4 @@
import { ActionIcon, Button } from "@mantine/core"; import { ActionIcon } from "@mantine/core";
import { RiExpandVerticalLine, RiCollapseVerticalLine } from "react-icons/ri"; import { RiExpandVerticalLine, RiCollapseVerticalLine } from "react-icons/ri";
export interface ListToggleProps { export interface ListToggleProps {
@ -29,9 +29,16 @@ export function ListToggle({
); );
} }
// `size={36}` matches the header's theme / client-settings ActionIcons so the
// toolbar's toggle reads as the same size icon button.
return ( return (
<Button size="sm" variant="subtle" aria-label={label} onClick={onToggle}> <ActionIcon
variant="subtle"
size={36}
aria-label={label}
onClick={onToggle}
>
<Icon size={20} /> <Icon size={20} />
</Button> </ActionIcon>
); );
} }

View file

@ -1,4 +1,4 @@
import { Button } from "@mantine/core"; import { ActionIcon } from "@mantine/core";
import { TbLayoutSidebarRightExpand } from "react-icons/tb"; import { TbLayoutSidebarRightExpand } from "react-icons/tb";
export interface PinColumnButtonProps { export interface PinColumnButtonProps {
@ -14,15 +14,16 @@ export interface PinColumnButtonProps {
* that screen in as a column; on the server list it just opens the column (a * that screen in as a column; on the server list it just opens the column (a
* different `label`). Distinct from `PinToggle` (which pins individual history * different `label`). Distinct from `PinToggle` (which pins individual history
* entries) — this one opens a side column, so it uses a right-sidebar glyph. * entries) — this one opens a side column, so it uses a right-sidebar glyph.
* Styled to match the panel's expand/collapse `ListToggle` (subtle icon button). * `size={36}` matches the header's theme / client-settings ActionIcons and the
* toolbar's `ListToggle`, so all these icon buttons share one width.
*/ */
export function PinColumnButton({ export function PinColumnButton({
onPin, onPin,
label = "Pin as column", label = "Pin as column",
}: PinColumnButtonProps) { }: PinColumnButtonProps) {
return ( return (
<Button size="sm" variant="subtle" aria-label={label} onClick={onPin}> <ActionIcon variant="subtle" size={36} aria-label={label} onClick={onPin}>
<TbLayoutSidebarRightExpand size={20} /> <TbLayoutSidebarRightExpand size={20} />
</Button> </ActionIcon>
); );
} }

View file

@ -1,4 +1,4 @@
import { Button, Group, SegmentedControl, TextInput } from "@mantine/core"; import { ActionIcon, Group, SegmentedControl, TextInput } from "@mantine/core";
import { TbLayoutSidebarRightCollapse } from "react-icons/tb"; import { TbLayoutSidebarRightCollapse } from "react-icons/tb";
import { ClearButton } from "../../elements/ClearButton/ClearButton"; import { ClearButton } from "../../elements/ClearButton/ClearButton";
@ -69,14 +69,14 @@ export function MonitoringControls({
) : null ) : null
} }
/> />
<Button <ActionIcon
size="sm"
variant="subtle" variant="subtle"
size={36}
aria-label="Close monitoring column" aria-label="Close monitoring column"
onClick={onClose} onClick={onClose}
> >
<TbLayoutSidebarRightCollapse size={20} /> <TbLayoutSidebarRightCollapse size={20} />
</Button> </ActionIcon>
</ControlsBar> </ControlsBar>
); );
} }

View file

@ -34,7 +34,9 @@ export function ServerListControls({
onOpenMonitor, onOpenMonitor,
}: ServerListControlsProps) { }: ServerListControlsProps) {
return ( return (
<Group justify="flex-end"> // `gap="sm"` matches the header's control spacing (its RightSection group),
// so these buttons sit the same distance apart as the header icons.
<Group justify="flex-end" gap="sm">
<Button variant="default" onClick={onExport} disabled={serverCount === 0}> <Button variant="default" onClick={onExport} disabled={serverCount === 0}>
Export Export
</Button> </Button>

View file

@ -169,13 +169,12 @@ describe("TaskListPanel", () => {
screen.getAllByRole("button", { name: "Collapse" }).length, screen.getAllByRole("button", { name: "Collapse" }).length,
).toBeGreaterThan(0); ).toBeGreaterThan(0);
const buttons = screen.getAllByRole("button"); // The ListToggle is labelled "Collapse all" / "Expand all" — distinct from
const toggle = buttons.find( // the per-entry "Collapse" / "Expand" buttons.
(b) => const toggle = screen.getByRole("button", {
b.textContent === "" && b.classList.contains("mantine-Button-root"), name: /Collapse all|Expand all/,
); });
expect(toggle).toBeDefined(); await user.click(toggle);
await user.click(toggle!);
// After toggle, entries collapsed — they show Expand // After toggle, entries collapsed — they show Expand
expect( expect(