From ec4c5ee4b1ada4df300227d114954f5a96b8fb2c Mon Sep 17 00:00:00 2001 From: eti Date: Tue, 4 Aug 2026 18:54:29 +0200 Subject: [PATCH] web/components: keep the selected ButtonGroup segment's border on sibling hover Signed-off-by: eti --- web/src/lib/components/ui/Button.svelte | 10 +++++++++- .../components/ui/ButtonGroup.stories.svelte | 17 +++++++++++++---- web/src/lib/components/ui/ButtonGroup.svelte | 12 ++++++++++-- 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/web/src/lib/components/ui/Button.svelte b/web/src/lib/components/ui/Button.svelte index 0e4cd059..2ecf0efc 100644 --- a/web/src/lib/components/ui/Button.svelte +++ b/web/src/lib/components/ui/Button.svelte @@ -178,6 +178,7 @@ {:else} - {/if} diff --git a/web/src/lib/components/ui/ButtonGroup.stories.svelte b/web/src/lib/components/ui/ButtonGroup.stories.svelte index f2142e3a..ca6695b3 100644 --- a/web/src/lib/components/ui/ButtonGroup.stories.svelte +++ b/web/src/lib/components/ui/ButtonGroup.stories.svelte @@ -54,8 +54,17 @@ `ghost`. Never plain `default` for unselected — that reads as the hovered state. --> - - - - +
+ + + + + + + + + + +
diff --git a/web/src/lib/components/ui/ButtonGroup.svelte b/web/src/lib/components/ui/ButtonGroup.svelte index 50bd88ea..6b7a1979 100644 --- a/web/src/lib/components/ui/ButtonGroup.svelte +++ b/web/src/lib/components/ui/ButtonGroup.svelte @@ -8,12 +8,20 @@ spaced: { true: "gap-2", false: [ - "items-stretch gap-0 rounded-sm overflow-hidden border border-border-default bg-background-subtle dark:bg-background-canvas", + "items-stretch gap-0 overflow-hidden rounded-sm border border-border-default bg-background-subtle dark:bg-background-canvas", "*:relative *:border-y-0", "[&>*:first-child]:-ml-px [&>*:last-child]:-mr-px", "[&>*:not(:first-child)]:-ml-px [&>*:not(:first-child)]:[--btn-radius-l:0px]", "[&>*:not(:last-child)]:[--btn-radius-r:0px]", - "[&>*:focus-visible]:z-10 [&>*:hover]:z-10" + // children overlap by 1px so adjacent borders collapse into a single seam, which + // also means a child's fill paints into its neighbour's border column. ghost + // segments have a transparent border and nothing to repaint there, so every + // bordered child has to sit above them — otherwise hovering a ghost rubs out the + // selected segment's border on whichever edge they share. + "[&>*:not([data-variant=ghost])]:z-10", + // the group clips overflow, so an outward focus ring gets cut off at its edges and + // by bordered neighbours. draw it inside the child instead. + "[&>*:focus-visible]:-outline-offset-2" ] } }, -- 2.51.2