demo · v149

Comment Composer

A social-style comment box. Instead of swallowing media into the body, this UI surfaces every inserted image or sticker as a removable attachment chip — the pattern Twitter/Bluesky-style apps actually want. Each insertion is logged so you can see the beforeinputinput flow.

compose IME media: probing…
desktop fallback · drop an image file here to see the same code path
simulate IME commitContent
No rejected IME media yet.

events

how it works

const acceptedTypes = new Set(['image/png', 'image/jpeg', 'image/gif', 'image/webp']);

editor.addEventListener('beforeinput', (e) => {
  if (!e.dataTransfer) return;
  const fallbackText = e.dataTransfer.getData('text/plain');

  for (const item of e.dataTransfer.items) {
    if (item.kind !== 'file') continue;
    const file = item.getAsFile();
    if (!file) continue;
    if (!acceptedTypes.has(file.type)) {
      rejectAttachment(file, 'unsupported MIME type');
      e.preventDefault();
      continue;
    }
    if (file.size > maxBytes) {
      rejectAttachment(file, 'over 5 MB limit');
      e.preventDefault();
      continue;
    }
    addAttachment(file, fallbackText);
    e.preventDefault();
  }
});

Same handler covers IME inserts, paste, and drop. The IME path arrives as a synthetic InputEvent with a populated dataTransfer — exactly the shape Android's InputConnection.commitContent() turns into web-land.

capability probe

// Heuristic: editable elements expose a dataTransfer on InputEvent
// when the IME supports commitContent. Trip a fake event to read the prototype.
const supportsIMEMedia = 'dataTransfer' in InputEvent.prototype;

see also

implementation reference

Need the exact API surface, compatibility boundaries, errors, lifecycle, and source links? Read the matching gendn reference ↗