Task #436: tint the whole incoming-note popup with the note color

The popup was a colored body sitting inside a white frame; users
wanted the WHOLE popup to look like the sticky note itself, with
only the outer ring + chrome remaining as frame.

- Outer rounded-2xl card now uses `colorBg(current.color)` directly
  (replacing `bg-background`). Default-color notes still render on
  `bg-white dark:bg-card` so the look is unchanged for uncolored
  notes.
- Removed the inner card-in-card colored body wrapper; title +
  content/checklist now render directly on the tinted surface.
- Header divider switched from `bg-muted/40` (opaque chrome) to a
  translucent `border-black/10 dark:border-white/10` so the tint
  flows under the avatar/title/X without an opaque strip.
- Action row moved into its own bordered footer strip (same
  translucent divider) so the 3 buttons stay legible on every
  palette tint while letting the colored surface bleed through.
- Added `data-popup-color` on the card for diagnostics.
- Reply popups inherit the same tint via the existing `color` field
  on the reply payload (no plumbing change).

No payload, locale, or test-id changes. All popup e2e suites pass:
notes-popup-on-receive (3/3), notes-popup-touch-tap (2/2).
This commit is contained in:
Riyadh
2026-05-07 10:14:11 +00:00
parent 20583740e5
commit 3df27665b9
@@ -372,17 +372,21 @@ export function IncomingNotePopup() {
}}
>
<div
className={`rounded-2xl bg-background ring-4 ring-amber-400/70 shadow-2xl shadow-amber-500/30 overflow-hidden transition-transform duration-200 ${
enterAnim ? "scale-100" : "scale-95"
}`}
className={`rounded-2xl ring-4 ring-amber-400/70 shadow-2xl shadow-amber-500/30 overflow-hidden transition-transform duration-200 ${colorBg(
current.color,
)} ${enterAnim ? "scale-100" : "scale-95"}`}
data-popup-color={current.color}
>
{/* Drag handle / header */}
{/* Drag handle / header — sits ON the tinted surface (no
opaque chrome behind it) so the whole card reads as one
continuous sticky note. Use a translucent dark divider
that works across every palette tint. */}
<div
onPointerDown={onHandlePointerDown}
onPointerMove={onHandlePointerMove}
onPointerUp={onHandlePointerEnd}
onPointerCancel={onHandlePointerEnd}
className="flex items-center gap-3 px-4 py-3 cursor-grab active:cursor-grabbing select-none border-b bg-muted/40 touch-none"
className="flex items-center gap-3 px-4 py-3 cursor-grab active:cursor-grabbing select-none border-b border-black/10 dark:border-white/10 touch-none"
data-testid="incoming-note-popup-drag-handle"
title={t("notes.popup.dragHint")}
>
@@ -423,32 +427,27 @@ export function IncomingNotePopup() {
</button>
</div>
{/* Body — render the inner note as a real sticky note. The
outer floating frame (header + actions) keeps its chrome;
this inner block matches the NoteCard surface so users see
the same artefact they'd see on the Notes page. */}
<div className="p-4 space-y-3">
<div
className={`rounded-xl border border-black/5 shadow-sm p-3 max-h-[40vh] overflow-y-auto ${colorBg(
current.color,
)}`}
data-testid="incoming-note-popup-body"
>
{bodyTitle && (
<div className="font-semibold text-sm text-foreground break-words">
{bodyTitle}
{/* Body sits directly on the tinted card surface — no
card-in-card. The whole popup IS the sticky note; only
the outer ring + header chrome remain as frame. */}
<div
className="p-4 space-y-3 max-h-[50vh] overflow-y-auto"
data-testid="incoming-note-popup-body"
>
{bodyTitle && (
<div className="font-semibold text-sm text-foreground break-words">
{bodyTitle}
</div>
)}
{isChecklistNote ? (
<PopupChecklistPreview items={checklistItems} />
) : (
bodyContent && (
<div className="text-sm text-foreground/80 whitespace-pre-wrap break-words">
{bodyContent}
</div>
)}
{isChecklistNote ? (
<PopupChecklistPreview items={checklistItems} />
) : (
bodyContent && (
<div className="text-sm text-foreground/80 mt-2 whitespace-pre-wrap break-words">
{bodyContent}
</div>
)
)}
</div>
)
)}
{queueLength > 1 && (
<div
@@ -458,10 +457,13 @@ export function IncomingNotePopup() {
{t("notes.popup.queueMore", { count: queueLength - 1 })}
</div>
)}
</div>
{/* Action row — exactly three buttons: Done, Open note,
Reply. The standalone Dismiss button was removed; the
X in the header still closes. */}
{/* Action row sits on its own faint divider strip so the
buttons stay legible against any tint, while still
letting the colored surface bleed through (no opaque
white footer). */}
<div className="px-4 py-3 border-t border-black/10 dark:border-white/10">
<div className="flex flex-wrap gap-2 sm:flex-nowrap justify-end">
<Button
type="button"