# Interface copy

> How to write button labels, form help, errors, empty states, confirmations, and toasts, each shown on its Roadie component.

Interface copy is the short text people act on, such as a button label or an
error message. Each kind follows the same pattern on every screen, so the
reader learns it once. Write it with [Voice and tone](https://ticketsolutionsptyltd.github.io/roadie/content/voice-and-tone.md)
and [Language and grammar](https://ticketsolutionsptyltd.github.io/roadie/content/language-and-grammar.md), which this page
doesn't repeat.

## Buttons

### Name the action

A label is a verb that says what happens when the reader presses it. Add the
thing it acts on when the verb alone could mean more than one thing. Keep it
to two to four words.

| Write           | Not     |
| --------------- | ------- |
| Save changes    | Submit  |
| Add ticket type | New     |
| Publish event   | OK      |
| Delete event    | Yes     |
| Buy tickets     | Proceed |

### Say what it costs

A button that takes money or can't be undone says so on the label.

**Do**

```tsx
<Button intent='accent' emphasis='strong'>Pay $96</Button>
```

Put the amount on the button that takes the payment.

**Don’t**

```tsx
<Button intent='accent' emphasis='strong'>Continue</Button>
```

Don't hide a payment behind a word that sounds like the next step.

### Links name the destination

A link, or a button with an href, says where it goes, so it makes sense read on its own.

**Do**

```tsx
<Button href='#'>View orders</Button>
```

Name the page the reader lands on.

**Don’t**

```tsx
<Button href='#'>Read more</Button>
```

Don't make the reader read around the link to learn where it goes.

### Label every icon button

An icon button has no visible words, so its aria-label carries them. Name the action, not the picture.

**Do**

```tsx
<IconButton aria-label='Remove ticket'>
```

A screen reader says what the button does.

**Don’t**

```tsx
<IconButton aria-label='Bin'>
```

Don't describe the icon. The reader hears what it looks like, not what it
does.

## Form help

### Labels

A label is a short noun phrase, with no colon and no instruction.
`showIndicator` on `Field.Label` marks required and optional fields, so a
label never carries an asterisk.

| Write            | Not                       |
| ---------------- | ------------------------- |
| Email            | Enter your email address: |
| Mobile number    | Phone #                   |
| Ticket type name | Name \*                   |
| Date of birth    | DOB                       |

### Helper text says what the reader can't guess

Use it for a format, a limit, or why we ask. Leave it out when the label says enough.

**Do**

```tsx
<Field>
  <Field.Label>Mobile number</Field.Label>
  <Field.Input type='tel' />
  <Field.HelperText>We text your tickets to this number.</Field.HelperText>
</Field>
```

Say why we ask, or the format that works.

**Don’t**

```tsx
<Field>
  <Field.Label>Mobile number</Field.Label>
  <Field.Input type='tel' />
  <Field.HelperText>Enter your mobile number.</Field.HelperText>
</Field>
```

Don't repeat the label.

### A placeholder is an example value

A placeholder disappears as the reader types, so anything they need to remember goes in the label or the helper text.

**Do**

```tsx
<Field>
  <Field.Label>Event URL</Field.Label>
  <Field.Input placeholder='ochre-kite-weekender' />
  <Field.HelperText>Use lowercase letters and hyphens.</Field.HelperText>
</Field>
```

Show a value the reader could type, and put the rule in the helper text.

**Don’t**

```tsx
<Field>
  <Field.Label>Event URL</Field.Label>
  <Field.Input placeholder='Use lowercase letters and hyphens' />
</Field>
```

Don't put the instructions where they vanish on the first keystroke.

### A choice says what happens when it's ticked

Write a checkbox or switch label as a positive statement of what the reader gets.

**Do**

```tsx
<Checkbox label='Email me when tickets go on sale' />
```

Ticking the box turns the thing on.

**Don’t**

```tsx
<Checkbox label="Don't stop sending me emails" />
```

Don't make the reader untangle a negative to know which way to tick.

## Errors

An error says what went wrong and how to fix it, next to the problem.
[Field.ErrorText](https://ticketsolutionsptyltd.github.io/roadie/components/field.md) holds an error in a value, and a
[Callout](https://ticketsolutionsptyltd.github.io/roadie/components/callout.md) holds one about a page or a step. The
[error text guideline](https://ticketsolutionsptyltd.github.io/roadie/content/language-and-grammar.md#guidelines) on Language
and grammar sets its shape: a whole sentence with a full stop.

### Lead with the fix

Start with what to do, because the reader can see which field it's on. When
the value looks right but isn't, such as an expired code, say what's wrong
first.

| Write                                    | Not                             |
| ---------------------------------------- | ------------------------------- |
| Enter an email address.                  | Email is required.              |
| Enter a mobile number like 0400 000 000. | Invalid phone number            |
| Choose at least 1 ticket.                | Quantity must be greater than 0 |
| Choose a date after today.               | Date is in the past.            |

### Don't blame the reader

Describe the problem and the fix, not the reader's mistake.

**Do**

```tsx
<Field invalid>
  <Field.Label>Access code</Field.Label>
  <Field.Input defaultValue='KITE2025' />
  <Field.ErrorText>This code has expired. Ask the promoter for a new one.</Field.ErrorText>
</Field>
```

Say what's wrong with the code and where to get one that works.

**Don’t**

```tsx
<Field invalid>
  <Field.Label>Access code</Field.Label>
  <Field.Input defaultValue='KITE2025' />
  <Field.ErrorText>You entered an expired code.</Field.ErrorText>
</Field>
```

Don't make the error about what the reader did.

### Own the errors that are ours

When Oztix fails, say "we", say what's safe, and give the next step. Leave error codes for the support team.

**Do**

```tsx
<Callout intent='danger' title="We couldn't save your changes">
  Your edits are still on this page. Try again in a minute.
</Callout>
```

Take the blame, and tell the reader their work isn't lost.

**Don’t**

```tsx
<Callout intent='danger' title='Error 500'>
  An unexpected error occurred.
</Callout>
```

Don't show a code and a sentence that says nothing.

## Empty states

An [EmptyState](https://ticketsolutionsptyltd.github.io/roadie/components/empty-state.md) says why there's nothing here and
what the reader can do about it.

### Say why it's empty

A title names what's missing. A list that has never had anything, and one a
filter or search has emptied, need different words.

| Write                        | Not                 |
| ---------------------------- | ------------------- |
| No events yet                | Nothing to see here |
| No events match your filters | 0 results           |
| No orders to refund          | Empty               |

### Give the next step

Put the action that fills the space on a button, and say in the description what it does.

**Do**

```tsx
<EmptyState size='sm'>
  <EmptyState.Title>No ticket types yet</EmptyState.Title>
  <EmptyState.Description>Add a ticket type to start selling.</EmptyState.Description>
  <EmptyState.Actions>
    <Button>Add ticket type</Button>
  </EmptyState.Actions>
</EmptyState>
```

Point the reader at the one thing that fills the page.

**Don’t**

```tsx
<EmptyState size='sm'>
  <EmptyState.Title>No data</EmptyState.Title>
  <EmptyState.Description>There's nothing here.</EmptyState.Description>
</EmptyState>
```

Don't leave the reader at a dead end.

### Say when a filter emptied the list

When a filter or search hides everything, say so, and offer the way back.

**Do**

```tsx
<EmptyState size='sm'>
  <EmptyState.Title>No events match your filters</EmptyState.Title>
  <EmptyState.Actions>
    <Button>Clear filters</Button>
  </EmptyState.Actions>
</EmptyState>
```

The reader knows the events still exist.

**Don’t**

```tsx
<EmptyState size='sm'>
  <EmptyState.Title>No events yet</EmptyState.Title>
  <EmptyState.Actions>
    <Button>Create event</Button>
  </EmptyState.Actions>
</EmptyState>
```

Don't suggest the events are gone when a filter is hiding them.

## Confirmations

A confirmation asks before something that costs money or can't be undone.
[Dialog](https://ticketsolutionsptyltd.github.io/roadie/components/dialog.md) with `role='alertdialog'` holds it.

### Ask about the thing by name

The title is a question with the action and the thing it acts on.

**Do**

```tsx
<Dialog.Title>Delete Ochre Kite Weekender?</Dialog.Title>
```

The reader knows what's at stake before reading on.

**Don’t**

```tsx
<Dialog.Title>Are you sure?</Dialog.Title>
```

Don't make the reader hunt through the body for what they're agreeing to.

### Say what happens next

The description says who it affects, and whether it can be undone, in a sentence or two.

**Do**

```tsx
<Dialog.Description>
  Fans who bought tickets get a refund. You can't undo this.
</Dialog.Description>
```

Name who it affects and say plainly that it's final.

**Don’t**

```tsx
<Dialog.Description>
  This action cannot be undone. Do you wish to proceed?
</Dialog.Description>
```

Don't warn without saying what's lost.

### Repeat the action on the button

The confirming button uses the title's verb. When that verb is cancel, the other button says what staying put means.

**Do**

```tsx
<>
  <Button>Keep event</Button>
  <Button intent='danger' emphasis='strong'>Cancel event</Button>
</>
```

Each button says what it does, even when the action is to cancel.

**Don’t**

```tsx
<>
  <Button>Cancel</Button>
  <Button intent='danger' emphasis='strong'>OK</Button>
</>
```

Don't use Cancel and OK when the action is to cancel something.

## Toasts

A [Toast](https://ticketsolutionsptyltd.github.io/roadie/components/toast.md) confirms something the reader just did, or
reports how background work finished. The Toast page says when to use one.

### Say what happened

The title names the thing and what happened to it, in the past tense. Leave
out "successfully" and the exclamation mark.

| Write               | Not                              |
| ------------------- | -------------------------------- |
| Event published     | Success!                         |
| Link copied         | Copied to clipboard successfully |
| 2 tickets sent      | Your request has been processed  |
| Ticket type deleted | Item removed                     |

### Name the action for what it does

A toast's one action is a verb, usually Undo or View.

**Do**

```tsx
toast.add({
  title: 'Ticket type deleted',
  timeout: 8000,
  actionProps: { children: 'Undo', onClick: undo }
})
```

The reader can reverse it in one press.

**Don’t**

```tsx
toast.add({
  title: 'Ticket type deleted',
  timeout: 8000,
  actionProps: { children: 'Click here', onClick: undo }
})
```

Don't make the reader guess what the button does.

### A failure says what to do

A danger toast follows Errors. The title names what failed, and the description gives the fix.

**Do**

```tsx
toast.add({
  title: "We couldn't export your orders",
  description: 'Try again in a minute.',
  intent: 'danger'
})
```

Name what failed and the next step.

**Don’t**

```tsx
toast.add({
  title: 'Error',
  description: 'Something went wrong.',
  intent: 'danger'
})
```

Don't report a failure the reader can't act on.

## In the interface

- [Button](https://ticketsolutionsptyltd.github.io/roadie/components/button.md) and [IconButton](https://ticketsolutionsptyltd.github.io/roadie/components/icon-button.md)
  labels follow Buttons.
- [Field](https://ticketsolutionsptyltd.github.io/roadie/components/field.md) labels, helper text, and error text follow Form
  help and Errors.
- [Callout](https://ticketsolutionsptyltd.github.io/roadie/components/callout.md) errors follow Errors.
- [EmptyState](https://ticketsolutionsptyltd.github.io/roadie/components/empty-state.md) titles, descriptions, and actions
  follow Empty states.
- [Dialog](https://ticketsolutionsptyltd.github.io/roadie/components/dialog.md) confirmations follow Confirmations.
- [Toast](https://ticketsolutionsptyltd.github.io/roadie/components/toast.md) titles and actions follow Toasts.

Docs updated 15 Oct 2026.
