From 18aaf1f3e8094e3507933c61e5e3e11947828eff Mon Sep 17 00:00:00 2001 From: Marcel Date: Fri, 8 May 2026 11:32:31 +0200 Subject: [PATCH] style(documents): gate timeline bar hover under (hover: hover) (#385) Co-Authored-By: Claude Sonnet 4.6 --- frontend/src/lib/document/TimelineBars.svelte | 10 +++++++--- .../document/TimelineDensityFilter.svelte.spec.ts | 15 +++++++++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/frontend/src/lib/document/TimelineBars.svelte b/frontend/src/lib/document/TimelineBars.svelte index 6466edde..fb0db1ca 100644 --- a/frontend/src/lib/document/TimelineBars.svelte +++ b/frontend/src/lib/document/TimelineBars.svelte @@ -104,9 +104,13 @@ function barHeight(count: number): number { opacity: 0.7; } -.bar:hover .bar-fill { - background-color: var(--palette-mint, #a1dcd8); - opacity: 0.85; +/* Gate hover under (hover: hover) so emulated mouse events on touch devices + don't leave a tapped bar stuck in :hover until the next tap elsewhere. */ +@media (hover: hover) { + .bar:hover .bar-fill { + background-color: var(--palette-mint, #a1dcd8); + opacity: 0.85; + } } /* Graylog-style range selector window: left/right borders mark the dragged diff --git a/frontend/src/lib/document/TimelineDensityFilter.svelte.spec.ts b/frontend/src/lib/document/TimelineDensityFilter.svelte.spec.ts index fb362065..404d913b 100644 --- a/frontend/src/lib/document/TimelineDensityFilter.svelte.spec.ts +++ b/frontend/src/lib/document/TimelineDensityFilter.svelte.spec.ts @@ -348,6 +348,21 @@ describe('TimelineDensityFilter — touch targets', () => { expect(clearBtn.className).toMatch(/focus-visible:ring-brand-navy/); expect(clearBtn.className).toMatch(/focus-visible:ring-offset-2/); }); + + it('bar hover style is gated by @media (hover: hover) to avoid touch-device hover-stick', async () => { + render(TimelineDensityFilter, makeProps()); + const cssText = Array.from(document.styleSheets) + .flatMap((sheet) => { + try { + return Array.from(sheet.cssRules); + } catch { + return []; + } + }) + .map((rule) => rule.cssText) + .join('\n'); + expect(cssText).toMatch(/@media \(hover: hover\)/); + }); }); describe('TimelineDensityFilter — accessibility', () => {