From d02ff9ac24d6d720c478e8424e73eebae9ec98fe Mon Sep 17 00:00:00 2001 From: Guilhem Date: Thu, 24 Sep 2026 15:12:09 +0200 Subject: [PATCH] fix: centre the toggle knob inside its track (#11314) * fix: centre the toggle knob inside its track The knob was positioned against the toggle's wrapper rather than the track, so its 2px inset resolved to a 1px gap inside the track's 1px border. On a 1x screen a toggle that lands on a fractional x blurs its edges across a whole pixel, which swallows that 1px gap and makes the knob look like it overflows the track. Position the knob inside the track's border with a 2px gap on every side, size the toggle in whole px so the 18px root font of large screens cannot make the track fractional, and give each size an explicit checked translate now that the knob is no longer exactly one translate-x-full wide. Co-Authored-By: Claude Opus 5 (1M context) * refactor: hoist the toggle knob's shared inset out of the size branches Co-Authored-By: Claude Opus 5 (1M context) * chore(frontend): add a Toggles tab to the kitchen sink Covers the four sizes, the three colors, the label and EE-badge variants, and a grid of quarter-pixel offsets: the knob's gap against the track border only misreads once the track lands between device pixels. Co-Authored-By: Claude Opus 5 (1M context) --------- Co-authored-by: Claude Opus 5 (1M context) --- frontend/src/lib/components/Toggle.svelte | 16 ++-- frontend/src/routes/kitchen_sink/+page.svelte | 83 +++++++++++++++++++ 2 files changed, 94 insertions(+), 5 deletions(-) diff --git a/frontend/src/lib/components/Toggle.svelte b/frontend/src/lib/components/Toggle.svelte index 16e1086a94..200b449ee7 100644 --- a/frontend/src/lib/components/Toggle.svelte +++ b/frontend/src/lib/components/Toggle.svelte @@ -93,6 +93,8 @@ +
+
diff --git a/frontend/src/routes/kitchen_sink/+page.svelte b/frontend/src/routes/kitchen_sink/+page.svelte index b3ae4ef196..e21f9da550 100644 --- a/frontend/src/routes/kitchen_sink/+page.svelte +++ b/frontend/src/routes/kitchen_sink/+page.svelte @@ -4,6 +4,7 @@ import TabContent from '$lib/components/common/tabs/TabContent.svelte' import Tabs from '$lib/components/common/tabs/Tabs.svelte' import DarkModeToggle from '$lib/components/sidebar/DarkModeToggle.svelte' + import Toggle from '$lib/components/Toggle.svelte' import GfmMarkdown from '$lib/components/GfmMarkdown.svelte' import AssistantMessage from '$lib/components/copilot/chat/AssistantMessage.svelte' import type { DisplayMessage } from '$lib/components/copilot/chat/shared' @@ -133,12 +134,23 @@ That's the full round-trip.` role: 'assistant', content: chatSampleContent } + + const toggleSizes = ['2xs', 'xs', 'sm', 'md'] as const + const toggleColors = ['blue', 'red', 'nord'] as const + // The knob's gap against the track border is thin enough that it only misreads once the + // track lands between device pixels, which needs a 1x screen. These offsets put one row of + // each size on every quarter-pixel so the worst case is on the page rather than left to + // whichever label widths a real view happens to have. + const subpixelOffsets = [0, 0.25, 0.5, 0.75] + let toggleChecked = $state(true) + let toggleDisabled = $state(false) + @@ -195,6 +207,77 @@ That's the full round-trip.`
+ +
+ + +
+ +
+
Sizes
+
+ {#each toggleSizes as size} + + {/each} +
+
+ +
+
Colors
+
+ {#each toggleColors as color} + + {/each} +
+
+ +
+
Labels
+
+ + + + +
+
+ +
+
Quarter-pixel offsets
+
+ Zoom a 1x screen in on these: the knob must keep a visible ring of track on every side in + both states. It reads as overflowing the track once that ring drops below a device pixel. +
+
+ {#each toggleSizes as size} +
+ {#each subpixelOffsets as offset} +
+ +
+ {/each} +
+ {/each} +
+
+
The three markdownProse presets, same source. Each is sized for its own