SayUI
Input & controls

Post Composer / Content Composer

A focused publishing surface that combines an editor, audience or context controls, attachments, draft handling, and one publish action.

Also known as tweet composer · social post editor · content composer · new post editor

Demo · not production-ready code

Prompt for AI

Pick a stack, copy a ready prompt, paste into Cursor / Claude / ChatGPT.

Your stack

Shapes the prompt you copy

React + Tailwind + shadcn/ui · EN

Stack: React + Tailwind + shadcn/ui. Use React with Tailwind CSS and shadcn/ui patterns (Radix-based primitives, cn(), class-first styling).

Task: implement "Post Composer / Content Composer".

Build a post composer with author identity, an optional audience selector, an accessible multi-line editor, a labeled attachment toolbar, draft-preserving close behavior, and one Publish/Post action. Disable publish when there is no valid content, keep the draft while media uploads or publishing fails, expose progress and errors, and return focus correctly when the composer is modal.

Anatomy:
- author identity: Avatar or account context anchors who will publish the post.
- audience / context selector: Optional control for visibility, destination, or reply permissions.
- post editor: The primary text area or rich-text surface; its accessible name must persist while typing.
- attachment toolbar: Named actions for media, emoji, polls, location, or other supported content.
- publish action: One primary action, disabled when content is invalid and busy while publishing.

Preferred API / pattern: `controlled composer form + textarea/editor + attachment state`

Keep scope minimal: only this UI pattern, match existing project style.

Acceptance checks

  • Avoid: Treating the whole composer as one form field
  • Avoid: Icon-only media actions without accessible names.
  • Avoid: Closing or failing publish clears the user's draft.
  • Avoid: Publish remains active for empty content or double-submits while busy.
  • Avoid: A desktop modal composer without focus trap, Escape policy, or focus r

In plain wordsHow people search for it

the box where I write a new social postthe tweet window with an avatar, media tools, and a Post buttonthe editor for writing a caption and attaching photos before publishinga What's happening input with audience controls and a publish action

AnatomyOpen for part names

author identity
Avatar or account context anchors who will publish the post.
audience / context selector
Optional control for visibility, destination, or reply permissions.
post editor
The primary text area or rich-text surface; its accessible name must persist while typing.
attachment toolbar
Named actions for media, emoji, polls, location, or other supported content.
publish action
One primary action, disabled when content is invalid and busy while publishing.

How to write itOpen for stack patterns

Web (HTML/CSS)<form> + <textarea|contenteditable> + named toolbar buttons
React + Tailwind + shadcn/uicontrolled composer form + textarea/editor + attachment state
SwiftUITextEditor + PhotosPicker + toolbar + async publish action
Ant DesignForm + Input.TextArea + Upload + Button

Notes

A composer is a task surface, not a single form field. It coordinates identity, audience, text, attachments, draft state, validation, upload progress, and publishing. It may live in a modal on desktop or a dedicated page on mobile. Keep draft/close behavior explicit so dismissing does not silently destroy work, label every icon-only toolbar action, and announce publish or upload failures without clearing the draft.

Common mistakesHumans and models trip here

  • Treating the whole composer as one form field: attachments, audience, draft, and publish state disappear.
  • Icon-only media actions without accessible names.
  • Closing or failing publish clears the user's draft.
  • Publish remains active for empty content or double-submits while busy.
  • A desktop modal composer without focus trap, Escape policy, or focus return.

More failure symptoms on AI broke it.

Related patterns

Spotted a wrong name or missing pattern?

Message on X