fix(messaging-ui): mail cards no longer clip + emoji picker portals above overflow (0.1.3)

- Mail reader: .miu-mail-msg gets flex:0 0 auto so cards keep their natural height
  in the scrolling column instead of being compressed + clipped by overflow:hidden.
- Reaction/emoji picker renders through a PopoverPortal to <body> (positioned +
  themed) so it floats above the message list instead of being cut by the scroll
  container's overflow. 72 tests green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-23 02:52:18 +05:30
parent 2753a8a367
commit 3c5c6964e2
5 changed files with 97 additions and 30 deletions
@@ -1,5 +1,6 @@
import { useState } from 'react';
import { useRef, useState } from 'react';
import { highlightMentions } from '../mentions';
import { PopoverPortal } from './popover-portal';
import type { Attachment } from '../types';
import type { UiMessage } from '../hooks/use-messages';
@@ -43,6 +44,7 @@ export function MessageItem({
onOpenThread?: (messageId: string) => void;
}) {
const [pickerOpen, setPickerOpen] = useState(false);
const reactBtnRef = useRef<HTMLButtonElement>(null);
const m = message;
return (
@@ -55,25 +57,27 @@ export function MessageItem({
<div className="miu-msg-actions">
{canReact ? (
<div className="miu-react-wrap">
<button type="button" className="miu-react-btn" title="React" onClick={() => setPickerOpen((p) => !p)}>
<button ref={reactBtnRef} type="button" className="miu-react-btn" title="React" onClick={() => setPickerOpen((p) => !p)}>
🙂
</button>
{pickerOpen ? (
<div className="miu-react-picker">
{REACTION_EMOJIS.map((e) => (
<button
key={e}
type="button"
className="miu-react-emoji"
onClick={() => {
onReact(m.id, e);
setPickerOpen(false);
}}
>
{e}
</button>
))}
</div>
<PopoverPortal anchorRef={reactBtnRef} onClose={() => setPickerOpen(false)}>
<div className="miu-react-picker">
{REACTION_EMOJIS.map((e) => (
<button
key={e}
type="button"
className="miu-react-emoji"
onClick={() => {
onReact(m.id, e);
setPickerOpen(false);
}}
>
{e}
</button>
))}
</div>
</PopoverPortal>
) : null}
</div>
) : null}