fix(callout-banner): tone-preserving hover on clickable banners - #12
Conversation
Replace hover:bg-accent with tone-aware color-mix rules so destructive and warning banners stay in their soft fill family on hover.
@Component-layer :hover lost to Tailwind bg utilities. Register *-soft-hover tokens and apply hover:bg-*-soft-hover on clickable banners.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e95223273e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (props.tone === 'destructive') { | ||
| const rest = 'border-destructive-border bg-destructive-soft' | ||
| return props.clickable | ||
| ? `${rest} transition-colors hover:bg-destructive-soft-hover hover:border-destructive-border-hover` |
There was a problem hiding this comment.
Move hover chrome back into style.css
For every clickable banner, these hover:* and transition-colors utilities put interaction chrome in the Vue utility layer, leaving the new data-slot/data-tone attributes unused and preventing this state from being maintained through the library's central chrome contract. Move the tone-specific hover and transition rules into style.css, keyed by the added data attributes, rather than resolving the cascade conflict by bypassing the required ownership boundary.
AGENTS.md reference: AGENTS.md:L112-L114
Useful? React with 👍 / 👎.
| if (props.tone === 'destructive') { | ||
| const rest = 'border-destructive-border bg-destructive-soft' | ||
| return props.clickable | ||
| ? `${rest} transition-colors hover:bg-destructive-soft-hover hover:border-destructive-border-hover` |
There was a problem hiding this comment.
Keep the border unchanged when deepening the hover fill
On every clickable-banner hover, this now deepens both the background and the border, stacking two simultaneous chrome changes where the design contract permits one layer to change in place. Preserve the tone by deepening only the soft fill and remove the hover:border-* treatment and its dedicated border-hover tokens.
AGENTS.md reference: AGENTS.md:L142-L151
Useful? React with 👍 / 👎.
Points packages/ui at felinics/ui#12 (squash-merged), the hover fix the bot issue banner relies on.
#898) * fix(web): rebuild bot memories tab on the owner vocabulary (#826) The memories tab was assembled from hand-rolled shapes referencing tokens that don't exist (--radius-card/--radius-control → square corners against the rounded MetricReadout tiles) and nesting bordered MemoryCards inside SettingsSection cards. Rebase every shape on its owner: - MemoryCard -> SettingsRow(align=start): hairline-separated rows inside the section card, no more card-in-card or undefined radius - degraded banner -> CalloutBanner(warning); ingest action in its slot - search field -> InputGroup + addon icons (was a raw <input>) - graph section -> SectionGroup(muted) with the chart card as its bare body; pane loading/empty -> PanePlaceholder; node chips -> Badge - compact popover fields -> FormStack/FieldStack; dialog field -> FieldStack - cold-load skeleton mirrors the section-card frame (one block) Behavior carried over intact (search debounce/enter/clear, layer chips with counts, dated groups + 30-row sentinel batches, compact ratio/decay, ingest/refresh wiring). Two deliberate changes: the compact button's tooltip repeated its own label (dropped), and a list-load failure used to toast then render the fake "no memories yet" empty state — it now shows an honest inline error state (loadFailed + resolved message), so the dead memoryStatusError and the compactStatusUnavailable locale key go with it. * fix(web): pin the memory-graph tooltip to the popover language ECharts' default item tooltip derives its border from the node's own accent color over a translucent white fill, so hovering a yellow node framed the popup in orange. Give it explicit surface tokens instead (popover fill, hairline border, foreground/muted type, menu radius, dropdown shadow) and render the name as a medium title line above the muted memory preview. Also enable labelLayout.hideOverlap — dense graphs were painting every node label into an unreadable overlapping soup. * fix(web): rebuild the memory settings page on the owner vocabulary The settings > Memory page was the same AI-drift family as the bot memories tab: a hand-rolled Advanced disclosure on an undefined --radius-control token, a 'middle card' mixing giant unframed stat tiles with a form row, and copy that didn't earn its place. - Built-in section -> SectionGroup + SettingsSection with just the Embedding Model row. The two unframed MetricReadout tiles are cut: 'Memory mode' always reads Graph (the only mode the built-in runtime saves — dead info) and 'Semantic Index' readiness is fully derived from whether the row's model is set (duplicated info). The status query and skeleton that fed the tiles go with them. - Advanced -> a plain SectionGroup (title + hint) over the BackendCard grid, replacing the hand-written Collapsible trigger. Two quiet cards don't need a disclosure; the one-shot auto-open logic is gone too. - BackendCard subtitle no longer repeats the card name when the draft's display name IS the type name ('Mem0 / Mem0' stutter). - Header Save uses Button :loading instead of a hand-placed Spinner. - provider-setting header card: defined token as a class (rounded-menu-shell) and type-scale classes (text-control/text-body). - Delete add-memory-provider.vue: unreachable dead code — external backends are created by the detail pane's materialize-on-save flow. - Copy: cut the marketing-style graph description paragraph and remove 14 dead memory.* i18n keys (en/zh/ja), most already orphaned by earlier churn. * fix(web): take over the remaining echarts defaults on the memory graph - Tooltip text never wrapped: echarts sizes the tooltip to the content's intrinsic width, so max-width in extraCssText never engaged and a one-line preview stretched the box past any sane width. The formatter now owns a 16rem capped, break-word wrapper instead. - Node labels used --muted-foreground (a warm-tinted gray) and the default blur state crushed everything non-adjacent to ~0.1 opacity, which read as a washed-out green-gray soup. Labels now render in --foreground and the blur fade is explicit (0.2/0.15/0.25). - Nodes get a --background halo stroke so edges stop at the ring instead of cutting into the fill. No node drop shadows: elevation stays an overlay-only language (the tooltip keeps the dropdown shadow). - Drop the section description under 'Memory Graph' — the title and the node/link counts already say everything; graphViewHint removed from all three locales. * fix(web): render memory-graph nodes in the badge language The solid node fills used the icon/text-grade saturated accents (#2383e2 & friends) — canonical tokens, but tuned for 16px glyphs, so at 30-46px solid discs they read murky against the white canvas (and the only brighter accent set in the system is the dark-mode block, not a light-theme alternative). Nothing colored in the house renders as a large solid fill; colored surfaces are soft tint + saturated ink. Nodes now follow the same badge language: --accent-{hue}-soft-active fill ringed by --accent-{hue}. * fix(web): solid-dot nodes, SettingsSection frame, sharp tooltip Three corrections from review: - Nodes are plain solid accent dots again — no ring/fill split. The badge-language treatment was the wrong answer to what is purely a color-ramp question. - The section frame goes from SectionGroup back to SettingsSection, the same owner every other tab section uses (Hooks' Status/Events): the SectionGroup header lacks the min-h-7 row and insets only the title, so the graph header never matched the spacing semantics of its siblings. The chart now fills the section card's body. - Tooltip transitionDuration: 0. The default 0.4s makes the tooltip chase the cursor, so every mousemove renders it mid-animation and Chromium shifts the composited layer at fractional offsets — the 'motion blur' that smeared CJK text until the animation settled. confine keeps it inside the chart's rounded card. * refactor(web): split memory graph into composable modules Extract the ECharts playground into pure helpers and focused composables so interaction, layout, and chart option building can be tested and maintained separately from the Vue shell. * fix(web): move memory status from General to Overview Drop the expandable memory graph status card from settings and show a lightweight metric row on Overview instead, matching the Runtime block. * fix(web): keep Overview metric tiles when runtime data is missing Always render the Runtime and Memory metric grids with em-dash placeholders instead of collapsing to a lone footnote line, and drop the Memory health badge. * fix(web): center memory row edit action on the full row Vertically center the pencil against the whole SettingsRow (text plus badges) instead of top-aligning with the first line. * fix(web): drop redundant dates from grouped memory stream rows Section headers already carry the day label; hide per-row timestamps in the dated stream. Search results still show relative/absolute time. * fix(web): drop Overview config block and lead with usage Remove the redundant model Configuration section (General owns setup). Move the token usage chart above memory telemetry so the dashboard numbers sit higher on the page. * fix(web): tone-safe CalloutBanner hover and Runtime status row CalloutBanner clickable hover used hover:bg-accent, which replaced the destructive/warning soft fill with neutral gray. Hover now intensifies the same tone via UI package data-slot rules (submodule bump). Overview Runtime: show the unavailable-metrics note inline beside the title (in place of the status badge), keep the three metric tiles as em dashes, and use a neutral secondary badge when metrics are present. * fix(web): CalloutBanner hover tokens and Runtime status badge copy Use registered *-soft-hover Tailwind tokens so issue banner hover is visible without turning gray. Show unavailable-metrics text inside the Runtime secondary badge, not as plain text beside the title. * fix(web): drop sentence periods from Runtime status badge copy Badge chips should read as labels, not full sentences — remove trailing punctuation from runtime unavailable/stopped strings (en/zh/ja). * fix(web): restore memory sync via Index & sync dialog on Memories tab Move manual sync out of General settings into an Advanced ActionCard on the Memories tab. The dialog is a single owner-rhythm row (provider name + health left, sync action right) — no hand-rolled cards, no metric tiles; index counts already live on Overview. Provider display name resolves through the shared cached providers/settings queries. Also: Runtime badge on Overview carries only Running/Stopped (the unavailable note moves to a footnote below the tiles), dead memory locale keys are removed, and the memory-graph loading overlay uses the z-ladder token. * chore(web): bump ui submodule for CalloutBanner tone-preserving hover Points packages/ui at felinics/ui#12 (squash-merged), the hover fix the bot issue banner relies on.
Summary
Two stacked fixes for CalloutBanner hover on clickable banners (used by the bot issue banner in felinics/Memoh#898):
168bb87— replacehover:bg-accentwith tone-aware color-mix rules so destructive/warning banners stay in their soft fill family on hovere952232— register*-soft-hovertokens and applyhover:bg-*-soft-hover; the @Component-layer:hoverrule was losing to Tailwind bg utilitiesLanding order
This must land before felinics/Memoh#898 — that PR's
packages/uigitlink points ate952232. Please merge without squash (merge commit or rebase) so the gitlink SHA stays fetchable; otherwise the shell repo's submodule checkouts (CI) keep failing.