Getting Started

Writing

Clear, consistent copy is as much a part of the design as color and spacing. These conventions govern all text that appears in the interface: labels, buttons, error messages, status indicators, and empty states.

Voice

The interface speaks directly and informatively. It does not apologize unnecessarily, use filler phrases, or adopt a chatty tone. Every word should earn its place.

AvoidPrefer
Oops! Something went wrong.Could not save changes. Check your connection and try again.
Hey there! Ready to get started?No tasks yet. Create your first task to get started.
Please be advised that this action cannot be undone.This cannot be undone.
You have successfully saved your changes!Changes saved.
Click here to learn more.Learn more about task statuses.

Sentence case

Use sentence case everywhere in the UI: navigation labels, page headings, button labels, table column headers, and form field labels. Title case is reserved for product names and proper nouns only.

IncorrectCorrect
Create New TaskCreate new task
Project OverviewProject overview
Due DateDue date
Assigned ToAssigned to
Activity LogActivity log

Action verbs for CTAs

Button labels are verbs that describe what the action does, not vague calls to action. Lead with the verb. Keep labels short — one or two words is ideal.

AvoidPrefer
Click hereSave changes
SubmitCreate task
OKConfirm
Yes, delete itDelete task
CloseCancel (when dismissing a form) or Close (when closing info)
// Confirmation dialog — clear, specific actions
<Dialog>
  <DialogHeader>
    <DialogTitle>Delete task</DialogTitle>
    <DialogDescription>
      This task and all associated comments will be permanently deleted.
      This cannot be undone.
    </DialogDescription>
  </DialogHeader>
  <DialogFooter>
    <Button variant="outline">Cancel</Button>
    <Button variant="destructive">Delete task</Button>
  </DialogFooter>
</Dialog>

Error messages

State the problem clearly, then suggest what the user can do about it. Avoid technical jargon. Never blame the user.

AvoidPrefer
Error 422: Unprocessable EntityTitle is required.
Something went wrongCould not load tasks. Refresh to try again.
Invalid inputDue date must be today or later.
Network error occurredCould not connect. Check your internet connection.

Inline field errors appear below the input. They should be short — one sentence — and avoid restating the field name if it is already visible.

// Field error — direct and specific
<div className="space-y-1.5">
  <label htmlFor="title" className="text-sm text-foreground">
    Title
  </label>
  <input
    id="title"
    className="border-destructive ring-destructive/20"
    aria-describedby="title-error"
    aria-invalid="true"
  />
  <p id="title-error" className="text-xs text-destructive">
    Title is required.
  </p>
</div>

Status labels

Status values are always capitalized as proper nouns. Use consistent terminology across the admin app and any client-facing surfaces.

StatusDisplay labelUsage
todoTo doTask not yet started
in_progressIn progressActively being worked on
in_reviewIn reviewAwaiting approval or feedback
doneDoneCompleted successfully
blockedBlockedCannot proceed — dependency or impediment
cancelledCancelledDeliberately stopped, not failed

Empty states

Empty states should tell the user why the area is empty and what they can do about it. A good empty state has four elements: an icon, a short heading, a one-sentence description, and a primary action.

// Empty state pattern
<div className="flex flex-col items-center gap-3 py-16 text-center">
  <div className="flex h-10 w-10 items-center justify-center rounded-lg bg-surface-200">
    <ClipboardList size={18} className="text-foreground-muted" aria-hidden="true" />
  </div>
  <div className="space-y-1">
    <p className="text-sm font-medium text-foreground">No tasks yet</p>
    <p className="text-sm text-foreground-lighter">
      Create your first task to start tracking work.
    </p>
  </div>
  <Button size="md" onClick={onCreateTask}>
    <Plus size={14} aria-hidden="true" />
    New task
  </Button>
</div>

Numeric formatting

Use consistent number formatting across the interface. Never abbreviate numbers in a context where precision matters (a task count, a record ID). Abbreviate only in dashboards and summary tiles where space is constrained.

ContextFormatExample
Record count in a tableFull number1,284 tasks
Dashboard summary tileAbbreviated1.3k
Dates (absolute)Day Mon Year12 Jan 2025
Dates (relative, recent)Relative phrase2 hours ago, yesterday
PercentagesNo decimal unless significant72%, not 72.3%