feat: quick emoji reactions on hover, in-app notification toasts, mention pulse audit

P5-17: MessageQuickReactions moved from 3-dots menu to hover toolbar;
shows 5 recent emoji directly on hover. Clicking a quick-reaction also
closes any open emoji picker (setEmojiBoardAnchor). Line separator
removed from component.

P5-7: LotusToastContainer slides in from bottom-right when window is
focused — replaces OS notification for in-focus events. Correct room
path (DM vs home) derived from mDirectAtom. Invite toast routes to
inbox. 4s auto-dismiss. Full TDS styling via CSS custom properties.

P5-8: Confirmed already implemented upstream (MentionHighlightPulse,
0.6s scale+glow, one-shot, prefers-reduced-motion). Marked complete.

Code-review fixes: toast navigation used nonexistent /room/ route;
emoji picker stayed open after toolbar quick-reaction.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-04 21:32:37 -04:00
parent 24e6882e72
commit 4876c2e4ca
7 changed files with 300 additions and 17 deletions
+27
View File
@@ -0,0 +1,27 @@
import { atom } from 'jotai';
export type ToastNotif = {
id: string;
avatarUrl?: string;
displayName: string;
body: string;
roomName: string;
roomId: string;
hashPath?: string; // overrides window.location.hash navigation when set
};
const baseAtom = atom<ToastNotif[]>([]);
// Write-only setter used in ClientNonUIFeatures
export const toastQueueAtom = atom<ToastNotif[], [ToastNotif | null], void>(
(get) => get(baseAtom),
(get, set, notif) => {
if (notif === null) return; // no-op guard
set(baseAtom, [...get(baseAtom), notif]);
}
);
export const dismissToastAtom = atom<null, [string], void>(
null,
(get, set, id) => set(baseAtom, get(baseAtom).filter((t) => t.id !== id))
);