Skip to content

Commit c482968

Browse files
committed
style: refactor roundness settings UI and improve accessibility with aria-labels
1 parent 93aaf8c commit c482968

File tree

6 files changed

+88
-124
lines changed

6 files changed

+88
-124
lines changed

ui/src/styles/chat/layout.css

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,11 @@
451451
.agent-chat__toolbar .btn--ghost svg {
452452
width: 16px;
453453
height: 16px;
454+
fill: none;
455+
stroke: currentColor;
456+
stroke-width: 1.5px;
457+
stroke-linecap: round;
458+
stroke-linejoin: round;
454459
}
455460

456461
.agent-chat__input-btn:hover:not(:disabled),

ui/src/styles/config.css

Lines changed: 33 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -553,110 +553,57 @@
553553
color: var(--text-strong);
554554
}
555555

556-
/* Roundness slider */
557-
.settings-slider {
558-
display: grid;
559-
gap: 10px;
560-
}
561-
562-
.settings-slider__header {
556+
/* Roundness options */
557+
.settings-roundness__options {
563558
display: flex;
564-
align-items: center;
565-
justify-content: space-between;
559+
gap: 6px;
566560
}
567561

568-
.settings-slider__label {
562+
.settings-roundness__btn {
563+
flex: 1;
569564
display: flex;
565+
flex-direction: column;
570566
align-items: center;
571-
gap: 6px;
572-
font-size: 12px;
573-
font-weight: 600;
574-
color: var(--muted);
575-
}
576-
577-
.settings-slider__key-swatch {
578-
display: inline-block;
579-
width: 14px;
580-
height: 14px;
581-
border: 1.5px solid var(--muted);
582-
flex-shrink: 0;
583-
}
584-
585-
.settings-slider__key-swatch--sharp {
586-
border-radius: 0;
587-
}
588-
589-
.settings-slider__key-swatch--round {
590-
border-radius: var(--radius-sm);
591-
}
592-
593-
.settings-slider__value {
594-
font-size: 12px;
595-
font-weight: 600;
596-
color: var(--muted);
597-
font-variant-numeric: tabular-nums;
598-
}
599-
600-
.settings-slider__input {
601-
-webkit-appearance: none;
602-
appearance: none;
603-
width: 100%;
604-
height: 6px;
605-
border-radius: var(--radius-full);
606-
background: var(--bg-muted);
607-
outline: none;
567+
gap: 8px;
568+
padding: 12px 6px 10px;
569+
border: 1px solid var(--border);
570+
border-radius: var(--radius-md);
571+
background: var(--bg);
608572
cursor: pointer;
609-
transition: background var(--duration-fast) ease;
573+
transition:
574+
background var(--duration-fast) ease,
575+
border-color var(--duration-fast) ease;
610576
}
611577

612-
.settings-slider__input:hover {
613-
background: var(--border-strong);
578+
.settings-roundness__btn:hover {
579+
background: var(--bg-hover);
614580
}
615581

616-
.settings-slider__input::-webkit-slider-thumb {
617-
-webkit-appearance: none;
618-
appearance: none;
619-
width: 18px;
620-
height: 18px;
621-
border-radius: 50%;
622-
background: var(--accent);
623-
border: 2px solid var(--bg-elevated);
624-
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.25);
625-
cursor: pointer;
626-
transition:
627-
transform var(--duration-fast) ease,
628-
box-shadow var(--duration-fast) ease;
582+
.settings-roundness__btn.active {
583+
border-color: var(--accent);
584+
background: var(--accent-subtle);
629585
}
630586

631-
.settings-slider__input::-webkit-slider-thumb:hover {
632-
transform: scale(1.15);
633-
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
587+
.settings-roundness__swatch {
588+
width: 28px;
589+
height: 20px;
590+
background: var(--bg-muted);
591+
border: 1.5px solid var(--border-strong);
592+
transition: border-radius var(--duration-fast) ease;
634593
}
635594

636-
.settings-slider__input::-moz-range-thumb {
637-
width: 18px;
638-
height: 18px;
639-
border-radius: 50%;
640-
background: var(--accent);
641-
border: 2px solid var(--bg-elevated);
642-
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.25);
643-
cursor: pointer;
595+
.settings-roundness__btn.active .settings-roundness__swatch {
596+
border-color: var(--accent);
644597
}
645598

646-
.settings-slider__preview {
647-
display: flex;
648-
gap: 8px;
649-
align-items: center;
650-
justify-content: center;
651-
padding: 8px 0 0;
599+
.settings-roundness__label {
600+
font-size: 11px;
601+
font-weight: 600;
602+
color: var(--muted);
652603
}
653604

654-
.settings-slider__preview-swatch {
655-
width: 32px;
656-
height: 22px;
657-
background: var(--bg-muted);
658-
border: 1px solid var(--border);
659-
transition: border-radius var(--duration-fast) ease;
605+
.settings-roundness__btn.active .settings-roundness__label {
606+
color: var(--accent);
660607
}
661608

662609
.settings-info-grid {

ui/src/ui/storage.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,22 @@ import { getSafeLocalStorage } from "../local-storage.ts";
2525
import { inferBasePathFromPathname, normalizeBasePath } from "./navigation.ts";
2626
import { parseThemeSelection, type ThemeMode, type ThemeName } from "./theme.ts";
2727

28+
export const BORDER_RADIUS_STOPS = [0, 25, 50, 75, 100] as const;
29+
export type BorderRadiusStop = (typeof BORDER_RADIUS_STOPS)[number];
30+
31+
function snapBorderRadius(value: number): BorderRadiusStop {
32+
let best: BorderRadiusStop = BORDER_RADIUS_STOPS[0];
33+
let bestDist = Math.abs(value - best);
34+
for (const stop of BORDER_RADIUS_STOPS) {
35+
const dist = Math.abs(value - stop);
36+
if (dist < bestDist) {
37+
best = stop;
38+
bestDist = dist;
39+
}
40+
}
41+
return best;
42+
}
43+
2844
export type UiSettings = {
2945
gatewayUrl: string;
3046
token: string;
@@ -253,7 +269,7 @@ export function loadSettings(): UiSettings {
253269
typeof parsed.borderRadius === "number" &&
254270
parsed.borderRadius >= 0 &&
255271
parsed.borderRadius <= 100
256-
? parsed.borderRadius
272+
? snapBorderRadius(parsed.borderRadius)
257273
: defaults.borderRadius,
258274
locale: isSupportedLocale(parsed.locale) ? parsed.locale : undefined,
259275
};

ui/src/ui/views/config.ts

Lines changed: 26 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { html, nothing, type TemplateResult } from "lit";
22
import { icons } from "../icons.ts";
3+
import { BORDER_RADIUS_STOPS, type BorderRadiusStop } from "../storage.ts";
34
import type { ThemeTransitionContext } from "../theme-transition.ts";
45
import type { ThemeMode, ThemeName } from "../theme.ts";
56
import type { ConfigUiHints } from "../types.ts";
@@ -13,6 +14,14 @@ import {
1314
} from "./config-form.shared.ts";
1415
import { analyzeConfigSchema, renderConfigForm, SECTION_META } from "./config-form.ts";
1516

17+
const BORDER_RADIUS_LABELS: Record<BorderRadiusStop, string> = {
18+
0: "None",
19+
25: "Slight",
20+
50: "Default",
21+
75: "Round",
22+
100: "Full",
23+
};
24+
1625
export type ConfigProps = {
1726
raw: string;
1827
originalRaw: string;
@@ -592,43 +601,23 @@ function renderAppearanceSection(props: ConfigProps) {
592601
<div class="settings-appearance__section">
593602
<h3 class="settings-appearance__heading">Roundness</h3>
594603
<p class="settings-appearance__hint">Adjust corner radius across the UI.</p>
595-
<div class="settings-slider">
596-
<div class="settings-slider__header">
597-
<span class="settings-slider__label">
598-
<span class="settings-slider__key-swatch settings-slider__key-swatch--sharp"></span>
599-
Square
600-
</span>
601-
<span class="settings-slider__value">${props.borderRadius}%</span>
602-
<span class="settings-slider__label">
603-
Round
604-
<span class="settings-slider__key-swatch settings-slider__key-swatch--round"></span>
605-
</span>
606-
</div>
607-
<input
608-
type="range"
609-
class="settings-slider__input"
610-
min="0"
611-
max="100"
612-
step="1"
613-
.value=${String(props.borderRadius)}
614-
@input=${(e: Event) => {
615-
const v = Number((e.target as HTMLInputElement).value);
616-
props.setBorderRadius(v);
617-
}}
618-
/>
619-
<div class="settings-slider__preview">
620-
<div
621-
class="settings-slider__preview-swatch"
622-
style="border-radius: ${Math.round(10 * (props.borderRadius / 50))}px"
623-
></div>
624-
<div
625-
class="settings-slider__preview-swatch"
626-
style="border-radius: ${Math.round(14 * (props.borderRadius / 50))}px"
627-
></div>
628-
<div
629-
class="settings-slider__preview-swatch"
630-
style="border-radius: ${Math.round(20 * (props.borderRadius / 50))}px"
631-
></div>
604+
<div class="settings-roundness">
605+
<div class="settings-roundness__options">
606+
${BORDER_RADIUS_STOPS.map(
607+
(stop) => html`
608+
<button
609+
type="button"
610+
class="settings-roundness__btn ${stop === props.borderRadius ? "active" : ""}"
611+
@click=${() => props.setBorderRadius(stop)}
612+
>
613+
<span
614+
class="settings-roundness__swatch"
615+
style="border-radius: ${Math.round(10 * (stop / 50))}px"
616+
></span>
617+
<span class="settings-roundness__label">${BORDER_RADIUS_LABELS[stop]}</span>
618+
</button>
619+
`,
620+
)}
632621
</div>
633622
</div>
634623
</div>

ui/src/ui/views/usage-render-details.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,7 @@ function renderSessionDetailPanel(
287287
class="btn btn--sm btn--ghost"
288288
@click=${onClose}
289289
title=${t("usage.details.close")}
290+
aria-label=${t("usage.details.close")}
290291
>
291292
×
292293
</button>
@@ -1026,6 +1027,7 @@ function renderSessionLogsCompact(
10261027
<select
10271028
multiple
10281029
size="4"
1030+
aria-label="Filter by role"
10291031
@change=${(event: Event) =>
10301032
onFilterRolesChange(
10311033
Array.from((event.target as HTMLSelectElement).selectedOptions).map(
@@ -1041,6 +1043,7 @@ function renderSessionLogsCompact(
10411043
<select
10421044
multiple
10431045
size="4"
1046+
aria-label="Filter by tool"
10441047
@change=${(event: Event) =>
10451048
onFilterToolsChange(
10461049
Array.from((event.target as HTMLSelectElement).selectedOptions).map(
@@ -1065,6 +1068,7 @@ function renderSessionLogsCompact(
10651068
<input
10661069
type="text"
10671070
placeholder=${t("usage.details.searchConversation")}
1071+
aria-label=${t("usage.details.searchConversation")}
10681072
.value=${filters.query}
10691073
@input=${(event: Event) => onFilterQueryChange((event.target as HTMLInputElement).value)}
10701074
/>

ui/src/ui/views/usage-render-overview.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ function renderFilterChips(
102102
class="filter-chip-remove"
103103
@click=${onClearDays}
104104
title=${t("usage.filters.remove")}
105+
aria-label="Remove days filter"
105106
>
106107
×
107108
</button>
@@ -118,6 +119,7 @@ function renderFilterChips(
118119
class="filter-chip-remove"
119120
@click=${onClearHours}
120121
title=${t("usage.filters.remove")}
122+
aria-label="Remove hours filter"
121123
>
122124
×
123125
</button>
@@ -134,6 +136,7 @@ function renderFilterChips(
134136
class="filter-chip-remove"
135137
@click=${onClearSessions}
136138
title=${t("usage.filters.remove")}
139+
aria-label="Remove session filter"
137140
>
138141
×
139142
</button>

0 commit comments

Comments
 (0)