- Home
- Skills
- Writing & Content
- UX Writing — Buttons, Errors and Empty States
UX Writing — Buttons, Errors and Empty States
The text inside your interface, made specific and human: buttons, labels, errors, empty states, confirmations.
$7
Works with the AI tools you already use
UX Writing — Buttons, Errors and Empty States
Example session with this skill installed
Fix the copy on our team-invite flow. It's a B2B project tool, mostly used by engineering managers. Here's everything on the screen:
- Page heading: "User Management"
- Button: "Add User"
- Modal heading: "Invite New User"
- Field label: "What is the email address of the person you want to invite?"
- Placeholder: "Enter email"
- Role dropdown label: "Permission Level"
- Submit button: "Submit"
- Cancel button: "Cancel"
- Error on bad email: "Invalid input"
- Error when already a member: "Error: user exists"
- Error on seat limit: "Operation failed. Please contact support."
- Success toast: "Success!"
- Empty state when no team members: "No data"
- Remove member confirm: "Are you sure?" with OK / Cancel
- Read your context and instructions
- Compiled the ux writing
- Generated the UI component
Copy Review — Team invite flow
Audience: engineering managers, B2B project tool. They invite in bursts during onboarding, then rarely.
Voice: mid-formality · neutral-warm · terse · directing · no humour — "direct and dry". Engineering managers want the task done, not a personality.
Constraints: none stated. Assuming no character limits; flagging localisation risk on two strings.
Voice guide (short)
We sound: plain, specific, unfussy
We don't sound: chirpy, apologetic, corporate
| We say | We don't say |
|---|---|
| Invite teammates | Add Users to Your Organization |
| That email is already on your team | Error: user exists |
| Send invite | Submit |
Conventions: sentence case · second person · active voice · contractions ok · numerals · no emoji · one apology per screen, maximum
Revisions
| # | Element | Current | Revised | Why |
|---|---|---|---|---|
| 1 | Page heading | User Management | Team | "User Management" is what the database calls it. Managers think "my team". Two syllables beats four. |
| 2 | Primary button | Add User | Invite teammate | Names the real action — they aren't creating an account, they're sending an invitation. Sets the expectation that an email goes out. |
| 3 | Modal heading | Invite New User | Invite a teammate | "New" is redundant; you can't invite an existing one. Matches the button verb, so the modal confirms the click. |
| 4 | Field label | What is the email address of the person you want to invite? | Email address | Labels are nouns, not questions. 11 characters instead of 62, and it stops the form looking like a survey. |
| 5 | Helper text | (none) | They'll get an invite link that expires in 7 days | New. States the rule up front — the single most common support question in invite flows is "did it send?" |
| 6 | Placeholder | Enter email | jan@company.com | A placeholder should show the format, not repeat the label. Repeating it means the label vanishes on focus for anyone using autofill. |
| 7 | Role label | Permission Level | Role | Shorter, and it's what the dropdown actually contains (Admin, Member, Viewer). "Permission Level" implies a number. |
| 8 | Role helper | (none) | Members can create projects. Viewers can only read. | New. The decision is being made right here and nothing on screen explains it. |
| 9 | Submit | Submit | Send invite | "Submit" describes the form mechanism. "Send invite" describes what happens to another human being. |
| 10 | Cancel | Cancel | Cancel | Fine as-is. |
| 11 | Error — bad email | Invalid input | Enter a valid email address | An instruction, not a verdict. "Invalid input" also doesn't say which input on a two-field form. |
| 12 | Error — already a member | Error: user exists | jan@company.com is already on your team | Names the actual address so they can see the typo. Drops the "Error:" prefix — the red styling already says that. |
| 13 | Error — seat limit | Operation failed. Please contact support. | Your plan includes 10 seats and all 10 are in use. [Manage seats] or [Contact sales] | The old copy is a dead end. This one names the limit, gives the number, and offers the two things that actually resolve it. |
| 14 | Success toast | Success! | Invite sent to jan@company.com · Undo | Says what succeeded. Undo matters — inviting the wrong person to a B2B workspace is an awkward, visible mistake. |
| 15 | Empty state | No data | No teammates yet / Invite someone and they'll appear here. / [Invite teammate] | Three jobs: what belongs here, why it's empty, the action. "No data" does none of them. |
| 16 | Remove confirm — heading | Are you sure? | Remove Jan Kowalski from the team? | The heading should be the question, naming the person. "Are you sure?" is a question about their confidence, not about the action. |
| 17 | Remove confirm — body | (none) | They'll lose access to 4 projects immediately. Their work stays. | New. The two things the manager is actually worried about, answered before they click. |
| 18 | Remove confirm — buttons | OK / Cancel | Remove / Cancel | The button is the answer to the heading. "OK" to "Are you sure?" is fine; "OK" to "Remove Jan?" is not — the destructive button must name the act. |
New copy needed
| Element | Proposed |
|---|---|
| Loading — sending | Sending invite… |
| Pending invite row | Invited 2 days ago · [Resend] · [Cancel invite] |
| Error — network | We couldn't send the invite. Check your connection and try again. |
| Error — invalid domain (if SSO-restricted) | Your workspace only allows @company.com addresses. |
| Success — bulk | 6 invites sent. 1 skipped — jan@company.com is already on your team. |
Beyond copy
Places where wording can't fix the underlying problem:
#13 seat limit. The error fires on submit, after they've typed an email and picked a role. The seat count is known on page load — show "2 of 10 seats used" next to the invite button and disable it at the limit. Better copy on this error is a consolation prize.
#11 bad email. If this validates on every keystroke, it will flag j as invalid before they've finished typing. Validate on blur, then re-validate on change. This is the single most common form-copy complaint that turns out not to be about copy.
#14 Undo. I've written it into the toast, but it only works if the backend supports revoking a sent invite. If it doesn't, cut the Undo rather than showing a control that fails.
No bulk invite. Managers onboard teams, not individuals. One-at-a-time is the real friction here; #5's "Send invite" copy can't solve it.
Localisation notes
#13 is the longest string. German will run ~35% longer — make sure the error container wraps rather than truncates.
#14 interpolates an email address mid-sentence. Use a full templated string (Invite sent to {email}), not concatenation, so translators can move the variable.
- #15 "No teammates yet" needs a plural-safe form in languages with more than two plural categories.
ux-writing-buttons-errors-and-empty-stat.tsx
TSX · React component
Example file from a real run - the skill writes it into your workspace.
Connects securely to your tools. The creator never sees your data.
What you get
About this skill
The problem
"Something went wrong." "Invalid input." "No data." "Submit." Every product ships with this text, and it's the difference between software that feels considered and software that feels like a form. It's also the cheapest thing to fix — no migration, no redesign, just better words.
What it does
- Rewrites the text across a screen or a whole product: headings, labels, helper text, placeholders, buttons, errors, empty states, confirmations, loading, toasts and onboarding.
- Applies four rules consistently — name the outcome not the mechanism, be specific about the thing, never blame the user, cut until it breaks.
- Establishes a voice on five named axes so the next person writes consistently without asking, with four ready-made positions to pick from.
- Handles the hard cases properly: the three kinds of empty state need different copy; destructive confirmations put the question in the heading and the answer on the button; errors go what happened, then what to do, then how.
- Delivers a table — element, current, revised, reason — that pastes straight into a ticket.
Why this beats prompting it yourself
Ask for "better copy" and you get copy that's different, not copy that's consistent. This works from a fixed voice definition and pattern library, so forty strings across a product come back sounding like one person wrote them. It also flags where wording can't fix the real problem — an error that fires on first keystroke is a UX bug, not a wording bug — instead of papering over it.
Use cases
- A product that works but reads like a database
- Writing the twenty strings a new feature needs, consistently
- Establishing a voice before a team scales
- Auditing copy before a localisation pass (English expands 30–40% in German)
Known limitations
English-first. Localisation guidance covers what to avoid, not translation itself. Doesn't write marketing or landing-page copy — that's a different job.
How to install
Works the same in every agent - Claude, Cursor, Codex, Copilot and 20+ more.
- 1
Download the ZIP
Free skills download straight away. Paid skills unlock right after purchase.
- 2
Unzip into your skills folder
Every agent reads skills from one folder on your machine. Drop the unzipped folder in there.
- 3
Ask your agent to use it
Restart the agent if it was already running. It picks the skill up automatically - no config needed.
Skills folder by agent
Click the path to copy it. Create the folder if it does not exist yet.
Reviews
No reviews yet
Be one of the first to try it. Every listed skill passes our trust checks below.
Security scanned
Passed our 8-point scan before listing
Fresh listing
Recently published to Agensi
30-day refund
Not a fit? Get your money back
Trust & safety
Security scanned
Verified clean 7 days ago
- Passed all security checks, Safe to install