feat(ui): styled app-wide tooltip component (LC-370) #376

Merged
longjacksonle merged 1 commit from feat/lc-370-tooltip-component into main 2026-06-19 15:13:10 +02:00

Closes LC-370.

What

Replaces the native title= tooltips on the enclave rail and room header with one styled, theme-aware tooltip component.

  • New helper server/assets/tooltip.js: a single position:fixed #lc-tooltip element appended to <body>, driven declaratively by data-lc-tip="text" (+ optional data-lc-tip-pos="top|right|bottom|left"). Fixed positioning is the point: the enclave rail is overflow-y-auto, which forces horizontal clipping, so a CSS-only ::after tooltip cannot escape it.
  • Behavior: shows after a 400ms hover delay, immediately on keyboard focus; hides on leave / blur / scroll / resize / Escape.
  • Styling (#lc-tooltip in main.css, served raw so it is never purged): token-driven chip (var(--content) on var(--surface-elevated)) that inverts correctly across light, dark, and high-contrast themes.
  • Converted surfaces: enclave rail (enclave_switcher.html, pos="right") - enclave link, settings gear, discover +, sidebar-collapse; room header (room_header.html, pos="bottom") - room-info heading, jump-to-date, info-docs, moderators.

Accessibility

The tooltip element is aria-hidden decoration. Every converted trigger keeps or gains its own accessible name: icon-only controls carry an explicit aria-label; controls with visible text keep the visible text (no redundant aria-label that would override it). No title= is left alongside data-lc-tip, so nothing double-renders.

Docs

docs/ui-conventions.md gains a "Tooltips (LC-370)" section: the attribute contract, the accessible-name rule, and the rail-right / topbar-bottom placement convention.

Testing

  • ./dev/cargo check -p lets-chat-server - clean (Askama validates the templates at compile time).
  • just test and just test-saas - both green.
  • No new Tailwind utilities introduced, so no CSS rebuild required.

🤖 Generated with Claude Code

Closes LC-370. ## What Replaces the native `title=` tooltips on the enclave rail and room header with one styled, theme-aware tooltip component. - **New helper** `server/assets/tooltip.js`: a single `position:fixed` `#lc-tooltip` element appended to `<body>`, driven declaratively by `data-lc-tip="text"` (+ optional `data-lc-tip-pos="top|right|bottom|left"`). Fixed positioning is the point: the enclave rail is `overflow-y-auto`, which forces horizontal clipping, so a CSS-only `::after` tooltip cannot escape it. - **Behavior**: shows after a 400ms hover delay, immediately on keyboard focus; hides on leave / blur / scroll / resize / Escape. - **Styling** (`#lc-tooltip` in `main.css`, served raw so it is never purged): token-driven chip (`var(--content)` on `var(--surface-elevated)`) that inverts correctly across light, dark, and high-contrast themes. - **Converted surfaces**: enclave rail (`enclave_switcher.html`, `pos="right"`) - enclave link, settings gear, discover `+`, sidebar-collapse; room header (`room_header.html`, `pos="bottom"`) - room-info heading, jump-to-date, info-docs, moderators. ## Accessibility The tooltip element is `aria-hidden` decoration. Every converted trigger keeps or gains its own accessible name: icon-only controls carry an explicit `aria-label`; controls with visible text keep the visible text (no redundant `aria-label` that would override it). No `title=` is left alongside `data-lc-tip`, so nothing double-renders. ## Docs `docs/ui-conventions.md` gains a "Tooltips (LC-370)" section: the attribute contract, the accessible-name rule, and the rail-right / topbar-bottom placement convention. ## Testing - `./dev/cargo check -p lets-chat-server` - clean (Askama validates the templates at compile time). - `just test` and `just test-saas` - both green. - No new Tailwind utilities introduced, so no CSS rebuild required. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
feat(ui): styled app-wide tooltip component (LC-370)
All checks were successful
check-secrets / Kingfisher (push) Successful in 5s
check-secrets / TruffleHog (push) Successful in 5s
check-secrets / TruffleHog (pull_request) Successful in 5s
check-secrets / Nosey parker (push) Successful in 3s
check-secrets / Kingfisher (pull_request) Successful in 4s
check-secrets / Nosey parker (pull_request) Successful in 6s
Create release / Create release from merged PR (pull_request) Has been skipped
Check / clippy + fmt + tests (pull_request) Successful in 2m56s
090e7b95fb
Replace native title= attributes on the enclave rail and room header with a styled, theme-aware tooltip driven by data-lc-tip / data-lc-tip-pos. The component is a single position:fixed element (server/assets/tooltip.js) so it escapes the overflow:auto clipping on the vertical enclave rail that a CSS-only ::after tooltip cannot survive. Shows after a 400ms hover delay, immediately on keyboard focus, hides on leave/blur/scroll/resize/Escape.

The tooltip element is aria-hidden decoration: every converted trigger keeps (or gains) its own accessible name, so there is no a11y regression. Icon-only controls carry an explicit aria-label; controls with visible text keep the visible text as their name. The #lc-tooltip chip is token-driven (dark-on-light / light-on-dark) so it reads correctly in light, dark, and high-contrast themes.

Rail tooltips open right; room-header tooltips open bottom, away from the chrome edge. Convention documented in docs/ui-conventions.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
longjacksonle deleted branch feat/lc-370-tooltip-component 2026-06-19 15:13:10 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/lets-chat!376
No description provided.