fix(web): review-round attachment refinements

Body-portal the lightbox and toast so transformed ancestors cannot trap
their fixed positioning (a lightbox opened from a chat message covered only
the chat column); make the toast pointer-transparent; observe the rail
element's own size instead of window resizes; consume vertical wheel ticks
exclusively via a non-passive listener with LINE/PAGE delta normalization;
keep the start position when the rail mounts over an existing draft; honor
prefers-reduced-motion for the toast, remove-control, and paging; retry
loads through the guarded load effect; note the deliberate promptError
re-announce; pin the intake toast in the assembled snapshot; sync the
superseded multimodal note and package docs.
This commit is contained in:
creatixchu
2026-08-11 17:45:11 +08:00
parent e611e825b1
commit 87e3c95027
22 changed files with 218 additions and 73 deletions

View File

@@ -133,4 +133,18 @@ it('accepts pasted images into the composer rail in order and removes them', asy
await waitFor(() => {
expect(document.querySelector('[role="group"][aria-label="Pending images"]')).toBeNull()
})
// An unsupported file announces a transient toast (the inline strip is
// gone) and the banner dismisses itself after its hold-and-fade lifetime.
fireEvent.paste(textarea, {
clipboardData: {
items: [{ kind: 'file', type: 'text/plain', getAsFile: () => new File(['x'], 'notes.txt', { type: 'text/plain' }) }],
getData: () => '',
},
})
const toast = await screen.findByRole('alert')
expect(toast.textContent).toContain('Unsupported image format: text/plain')
await waitFor(() => {
expect(screen.queryByRole('alert')).toBeNull()
}, { timeout: 6_000 })
})