Use when writing or auditing interface copy, button labels, error messages, empty states, onboarding, microcopy, tooltips, or any text inside an interface. Covers tone, voice, button-label patterns, error-message construction, empty state copy, and the most common UX writing anti-patterns. Trigger when the user mentions copy, microcopy, button text, error message, empty state, onboarding, tone, or voice.
Interface copy is design. A 4-word button label is a design decision. A confusing empty state breaks an otherwise polished product. The rules below produce copy that disappears into use.
| Bad | Good |
|---|---|
| Submit | Send message / Create account / Save changes |
| OK | Got it / Continue / Done |
| Cancel | Cancel (this one is fine) / Discard / Keep editing |
| Click here | (link should describe destination) |
| Learn more | Read the security guide |
| Yes / No | Save changes / Discard |
| Continue | Continue to payment |
Rule: button label = verb + object when possible. "Save", "Save profile", "Save and continue".
| Context | Primary | Secondary |
|---|---|---|
| Saving | Save changes | Cancel |
| Discarding | Discard changes | Keep editing |
| Destructive | Delete project | Cancel |
| Confirming | Yes, sign me out | No, stay signed in |
Destructive actions always require explicit confirmation language. "Delete" alone, with the user already on a delete confirmation modal, is acceptable. "Delete project" is better.
| Context | Tone |
|---|---|
| Marketing CTA | Bold, benefit-focused: "Start free trial" |
| App primary action | Direct, action-focused: "Save changes" |
| Destructive | Clear and confirming: "Delete forever" |
| Loading state | Present continuous: "Saving…", "Sending…" |
| Success state | Past tense: "Saved", "Sent" |
Three parts: what happened, why, how to fix.
What: "We couldn't send your message."
Why: "Your internet connection dropped."
Fix: "Check your connection and try again."
Concatenated for short use: "We couldn't send your message. Check your connection and try again."
| Bad | Good |
|---|---|
| Error | We couldn't load your projects. Try refreshing. |
| Invalid input | Enter a valid email. Example: [email protected]. |
| Failed | Couldn't save changes. Check your connection and retry. |
| Required | Email is required. |
| Wrong | Password must be at least 8 characters. |
| Network error | We're having trouble reaching our servers. Try again in a moment. |
| 500 | Something went wrong on our end. We're looking into it. |
| 404 | We couldn't find that page. It may have been moved or deleted. |
Error tone rules:
Every list, table, search, and dashboard has an empty state. Plan for it.
| Empty type | Pattern |
|---|---|
| First-time empty (no data ever) | Brief explanation + CTA to create first item |
| User-cleared empty (deleted everything) | Confirmation that the area is empty + restore option if applicable |
| Search empty (no results) | "No results for '[query]'" + suggestions to refine |
| Filter empty (filters too narrow) | "No results match your filters" + "Clear filters" button |
| Loading empty (data still fetching) | Skeleton, not "No data" |
Empty state structure:
1. Visual (illustration, icon, or just typography)
2. Headline (4-8 words, what's empty)
3. Description (1 sentence, why and what next)
4. Primary action (button to fix or create)
5. Optional secondary (learn more, alternative)
No projects yet (first-time):
[icon]
You don't have any projects yet
Projects help you organize work into separate spaces.
[+ Create your first project]
[Read the guide]
No search results:
No results for "octopus"
Try a different search, or check your spelling.
[Clear search]
No notifications:
You're all caught up.
(Sometimes one line is enough.)
| Wait | Copy |
|---|---|
| < 400ms | (none — instant feels best) |
| 400ms–2s | "Loading…" or skeleton |
| 2s–10s | "Loading [thing]…" with what specifically |
| > 10s | "This is taking longer than usual…" + estimated remaining if known |
Use "…" (ellipsis character) or "...". Be consistent. Don't mix.
| Action | Confirmation |
|---|---|
| Save | "Saved" (toast, dismisses in 3s) |
| Send | "Message sent" |
| Delete | "Project deleted" + "Undo" (5s window) |
| Copy | "Copied to clipboard" |
Always offer Undo for destructive actions. A 5-second toast with Undo is more humane than a confirmation dialog before the action.
Pick a position and stay there:
| Context | Tone |
|---|---|
| Onboarding | Welcoming, encouraging |
| Routine actions | Neutral, efficient |
| Errors | Calm, reassuring, concrete |
| Destructive confirmations | Serious, clear |
| Success | Brief, satisfying |
| Marketing | Persuasive, benefit-focused |
Rule: tone bends to context, voice stays constant. Your error messages and your marketing copy should sound like the same product.
| Bad | Good |
|---|---|
| (none) | We'll never share your email. |
| Password | At least 8 characters with one number. |
| Phone | Include country code, e.g., +1 555 555 1234. |
| Name | (often no hint needed) |
| Bad | Good |
|---|---|
| Allow notifications? | Get notified when someone replies to your post |
| Use camera? | Take a photo to add to your profile |
| Access location? | Show events near you |
Explain the benefit before the prompt. Most users deny generic permission requests; specific benefit increases acceptance.
| Bad | Good |
|---|---|
| Welcome to our platform | (use product name) |
| Let's get started! | (skip, just start) |
| Tell us about yourself | Help us personalize your experience (with explanation of what's used) |
Onboarding rule: every step justifies itself. "We need this because…" or skip the step entirely.
| Pattern | Example |
|---|---|
| Currency | $1,299.00 (en-US), 1.299,00 € (de-DE) |
| Large numbers | "1.2M users" preferred to "1,234,567 users" in dashboards |
| Dates (relative, recent) | "2 hours ago", "yesterday" |
| Dates (absolute, distant) | "Mar 14, 2026" not "03/14/26" (ambiguous) |
| Time | "2:30 PM" (US) or "14:30" (24-hour) — match user locale |
| Percentages | Round to 1 decimal in dashboards: "12.4%" |
Use Intl APIs for formatting: Intl.NumberFormat, Intl.DateTimeFormat. Never hardcode locale formats.
| Anti-pattern | Why it fails | Fix |
|---|---|---|
| "Submit" button | Generic | Use the verb |
| "Click here" link | Useless out of context | Describe destination |
| "Error" with no detail | User stuck | What/why/how |
| "Invalid input" | Doesn't say what's invalid | Specific |
| All caps for emphasis | Reads as shouting | Use weight or color |
| Multiple exclamation marks | Childish | Maximum one, sparingly |
| Emojis in error messages | Wrong tone | Save for celebrations |
| "Please" before everything | Verbose | "Save" not "Please save" |
| "Sorry for the inconvenience" | Empty apology | Fix the issue, brief acknowledgement |
| Title Case Buttons | Slow to read | Sentence case |
| ALLCAPS HEADINGS | Slow to read | Use weight |
| "We" voice from a single-user product | Confusing | Match voice to product |
| Marketing tone in error messages | Off-key | Calm, helpful |
| Truncated text without context | User can't tell what's hidden | Tooltip on hover/focus or "more" link |
| "Coming soon" with no date | Frustrating | Date or remove the mention |
Writing a button label?
├─ Verb + object: "Save changes", "Send message", "Delete project"
├─ Sentence case
├─ Loading state: present continuous ("Saving…")
└─ Success state: past tense ("Saved")
Writing an error?
├─ What happened (in the user's terms)
├─ Why (if helpful)
├─ How to fix (most important)
├─ Tone: calm, not alarming
└─ Don't blame the user
Writing an empty state?
├─ Headline: 4-8 words, what's empty
├─ Description: 1 sentence why
├─ Primary action: how to fix or create
└─ Skip if "You're all caught up" suffices