Screen Documentation Style Guide - cressie176/Load64 GitHub Wiki

Screen Documentation Style Guide

This guide defines the standard structure and conventions for documenting LoadC64 screens. Every screen document should follow these patterns consistently, in the same way that a Storybook story describes a component: purpose, visual design, region-by-region breakdown, states, behaviour, and validation.


Document Structure

Each screen document must contain the following top-level sections in this order:

  1. ## Primary Purpose
  2. ## Secondary Purpose (optional)
  3. ## Main Screen Design
  4. One ### section per named region (e.g. ### TOP BAR, ### LIST, ### BOTTOM BAR)
  5. ### Behaviour (where needed)
  6. ### Validation Rules (where needed)

Sections for overlays and contextual states (e.g. capture mode, confirmation dialogs) are documented inline within the screen they belong to, not in separate files.


Primary Purpose

A single sentence describing what this screen enables the user to do.

## Primary Purpose

Manage controller family templates used as a seed configuration for physical devices.
## Primary Purpose

Map or unmap a physical control name and event to a canonical control name within a controller family.
## Primary Purpose

Create a new controller family template.

Main Screen Design

An ASCII wireframe of the screen in its default state, inside a fenced code block. The outer frame is always 80 characters wide. Named regions are labelled in ALL CAPS inside the frame.

Full screen (default state)

┌──────────────────────────────────────────────────────────────────────────────┐
│ TOP BAR                                                                      │
│  Screen Title                                                                │
├──────────────────────────────────────────────────────────────────────────────┤
│                                                                              │
│  CONTENT REGION                                                              │
│                                                                              │
├──────────────────────────────────────────────────────────────────────────────┤
│ BOTTOM BAR                                                                   │
└──────────────────────────────────────────────────────────────────────────────┘

With a CTA in the top bar

CTAs sit right-aligned in the top bar, separated from the title by spaces.

┌──────────────────────────────────────────────────────────────────────────────┐
│ TOP BAR                                                                      │
│  Controller Families                                                [ Add ]  │
├──────────────────────────────────────────────────────────────────────────────┤

With multiple CTAs in the top bar

Multiple CTAs are space-separated, right-aligned.

┌──────────────────────────────────────────────────────────────────────────────┐
│ TOP BAR                                                                      │
│  <Family Name>                                           [Rename]  [Delete]  │
├──────────────────────────────────────────────────────────────────────────────┤

Bottom bar with content

When the bottom bar carries a contextual cmessage, show it in the wireframe.

├──────────────────────────────────────────────────────────────────────────────┤
│ BOTTOM BAR                                                                   │
│  <Family Name> created                                                       │
└──────────────────────────────────────────────────────────────────────────────┘

When the bottom bar is empty by default, leave it blank.

├──────────────────────────────────────────────────────────────────────────────┤
│ BOTTOM BAR                                                                   │
│                                                                              │
└──────────────────────────────────────────────────────────────────────────────┘

Partial wireframe (state variant)

When documenting a state variant (e.g. bottom bar after an action), show only the relevant portion of the frame using at the top.

├──────────────────────────────────────────────────────────────────────────────┤
│ BOTTOM BAR                                                                   │
│  Logitech created                                                            │
└──────────────────────────────────────────────────────────────────────────────┘

Named Regions

Each region in the wireframe gets a ### section. The section heading matches the label used in the wireframe exactly.

Region properties

Every region section opens with a set of bold property tags using inline <br/> line breaks:

**Type:** Single-selection vertical list<br/>
**Focusable:** Yes (primary focus region)<br/>
**Interactive:** Yes<br/>
**Order:** Alphabetically by name<br/>
**Purpose:** Browse and select items<br/>

Use only the properties that apply. Common properties:

Property Used for
Type Lists, forms, and other structured regions
Focusable All regions — describes whether the user can focus it
Interactive All regions — describes whether the user can act on it
Order Lists — describes the sort order
Purpose All regions — one-line description of the region's role

TOP BAR

The top bar always exists. It displays the screen title and optionally hosts CTAs.

### TOP BAR

**Focusable:** [Rename] and [Delete] CTAs only<br/>
**Interactive:** [Rename] and [Delete] CTAs only<br/>
**Purpose:** Display the family name and provide rename and delete actions<br/>

When the top bar has no interactive elements:

### TOP BAR

**Focusable:** No<br/>
**Interactive:** No<br/>
**Purpose:** Display the screen title<br/>

BOTTOM BAR

The bottom bar always exists. Document its focusability, interactivity, purpose, and every message state it can display.

### BOTTOM BAR

**Focusable:** No<br/>
**Interactive:** No<br/>
**Purpose:** Display confirmation messages after adding, renaming or deleting a controller family<br/>

Follow with wireframe snippets for each message state:

After creating a family:

​```
├──────────────────────────────────────────────────────────────────────────────┤
│ BOTTOM BAR                                                                   │
│  <Family Name> created                                                       │
└──────────────────────────────────────────────────────────────────────────────┘
​```

After renaming a family:

​```
├──────────────────────────────────────────────────────────────────────────────┤
│ BOTTOM BAR                                                                   │
│  <Old Family Name> renamed to <New Family Name>                              │
└──────────────────────────────────────────────────────────────────────────────┘
​```

After deleting a family:

​```
├──────────────────────────────────────────────────────────────────────────────┤
│ BOTTOM BAR                                                                   │
│  <Family Name> deleted                                                       │
└──────────────────────────────────────────────────────────────────────────────┘
​```

When the bottom bar is purely structural (no messages):

### BOTTOM BAR

**Focusable:** No<br/>
**Interactive:** No<br/>
**Purpose:** Structural consistency with other primary screens only. No controls are present on this screen.<br/>

LIST regions

### LIST

**Type:** Single-selection vertical list<br/>
**Focusable:** Yes (primary focus region)<br/>
**Interactive:** Yes<br/>
**Order:** Alphabetically by family name<br/>
**Purpose:** Browse and select controller families for editing<br/>

Selecting a controller family navigates to the Controller Family Detail screen for that family.

Always state:

  • What the list is ordered by
  • What happens when an item is selected

Multi-column lists

When list rows contain multiple columns, describe each column:

All canonical controls are always shown, whether mapped or unmapped. Each row shows:
- Canonical name (LoadC64 canonical control, e.g. `button_south`)
- Control name (label printed on the physical button, e.g. "A") — shown as `` if unmapped
- Event identifier (OS event, e.g. `button_0`) — shown as `` if unmapped

Use to represent an empty or unmapped value in both the wireframe and prose.

FORM regions

Form regions are named descriptively (e.g. CONTROL EDITOR). Document each field inline, or add a ### Validation Rules table.

┌────────────────────────────────────────────────────────────────────────────┐
│                  ┌──────────────────────────────────────────────────────┐  │
│  Control Name *  │ _                                                    │  │
│                  └──────────────────────────────────────────────────────┘  │
│                                                                            │
│                  ┌──────────────────────────────────────────────────────┐  │
│  Canonical Name  │ button_south                                      \/ │  │
│                  └──────────────────────────────────────────────────────┘  │
│                                                                            │
│  [Save]   [Cancel]                                                         │
└────────────────────────────────────────────────────────────────────────────┘

Field conventions in wireframes:

Convention Meaning
_ Empty text input, cursor visible
Value_ Pre-populated text input, cursor at end
Value \/ Dropdown (closed)
Waiting... Placeholder shown during an active capture/listening state
Value_ [Browse] File picker — text editable directly or via OS file picker opened by [Browse]

Required fields

Append * to the field label in the wireframe for any field that is required. Labels in the same form are left-padded to the same width, so the input boxes remain column-aligned.

┌────────────────────────────────────────────────────────────────────────────┐
│                  ┌──────────────────────────────────────────────────────┐  │
│  Games Dir *     │ _                                                    │  │
│                  └──────────────────────────────────────────────────────┘  │
│                                                                            │
│                  ┌──────────────────────────────────────────────────────┐  │
│  Server          │ _                                                    │  │
│                  └──────────────────────────────────────────────────────┘  │
└────────────────────────────────────────────────────────────────────────────┘

The * suffix is a wireframe-level documentation convention only. It is not part of the rendered UI label.


CTAs

CTAs are written in square brackets: [Save], [Cancel], [Delete], [Add], [Rename], [Capture].

Control types

The control type used to implement a CTA depends on what it does:

CTA type Control Rationale
Top bar CTA that navigates to a screen Nav bar link Represents a navigation destination
Top bar CTA that opens an overlay, triggers an action, or switches mode Button Does not navigate; produces an in-place effect
Form-area CTA ([Save], [Cancel], etc.) Button Acts within a form context

Each CTA that appears on screen gets its own ### section documenting what it does.

Primary action CTAs (top bar)

### [Add] CTA

Navigates to the Add Controller Family screen.

Destructive CTAs

Destructive CTAs always open a confirmation overlay before acting.

### [Delete] CTA

Opens a confirmation overlay before deleting.

Follow with the overlay wireframe and an option table:

┌──────────────────────────────────────────────────────────────────────────────┐
│                    ┌──────────────────────────────┐                          │
│                    │ Delete <Family Name>?        │                          │
│                    │                              │                          │
│                    │   > Yes                      │                          │
│                    │     No                       │                          │
│                    └──────────────────────────────┘                          │
└──────────────────────────────────────────────────────────────────────────────┘
| Option | Behaviour                                                              |
|--------|------------------------------------------------------------------------|
| Yes    | Delete the family and return to Controller Families list               |
| No     | Close the overlay and return to Controller Family Detail               |

Where the destructive action has a dependency warning, document it between the overlay wireframe and the option table:

If the family is referenced by one or more controller configurations, a warning is shown:

​```
<Family Name> is used by <n> controller(s). Deleting it will remove their family reference.
​```

Form action CTAs (in-form)

### [Save] / [Cancel]

- [Save] saves the mapping and returns to the Controller Family Detail screen.
- [Cancel] discards changes and returns to the Controller Family Detail screen.

Mode-switching CTAs

Some CTAs put the UI into a special mode. Document the inactive state, the active state wireframe, and how to exit.

### [Capture] CTA

Enters capture mode. The button label changes to [Cancel] while capture mode is active.

When capture mode is active:

​```
│   Event           ┌───────────────────────────────────────┐            │
│                   │ Waiting...                            │ [Cancel]   │
│                   └───────────────────────────────────────┘            │
​```

- Normal joystick navigation is suspended.
- The first accepted controller event populates the field and exits capture mode automatically.
- [Cancel] or Escape exits capture mode without changing the field.

Overlays

Confirmation overlay

┌──────────────────────────────────────────────────────────────────────────────┐
│                    ┌──────────────────────────────┐                          │
│                    │ Delete <Family Name>?        │                          │
│                    │                              │                          │
│                    │   > Yes                      │                          │
│                    │     No                       │                          │
│                    └──────────────────────────────┘                          │
└──────────────────────────────────────────────────────────────────────────────┘

The > prefix on the focused item is used consistently across lists and overlays to indicate the current selection.


Behaviour Section

The ### Behaviour section is a bullet list. Each bullet describes one discrete rule, interaction, or navigation outcome. Write in present tense, starting with the subject (the CTA, the field, or the user action).

### Behaviour

- Fields are pre-populated with the current values when editing an existing mapping, or empty if unmapped.
- [Capture] enters capture mode. While in capture mode, normal joystick navigation is suspended and LoadC64 listens for the next controller event.
- Both digital events (buttons, d-pad directions) and analog events (thumbstick axes, triggers) are accepted. However, analog events below a minimum threshold are ignored to filter out resting-position noise.
- The first accepted event populates the Event field and capture mode exits automatically, restoring normal navigation.
- [Cancel] (shown in place of [Capture] during capture mode) or Escape exits capture mode without changing the Event field.
- [Save] saves the mapping and returns to the Controller Family Detail screen.
- [Cancel] (in the form footer) discards changes and returns to the Controller Family Detail screen.
- [Delete] removes the mapping for this canonical name, leaving it unmapped, and returns to the Controller Family Detail screen. Only shown when the canonical name is currently mapped.
- If validation fails, the error is shown in the bottom bar and the form remains open.

When a CTA has its own ### section, document its behaviour there rather than in the top-level ### Behaviour list. Use ### Behaviour only for screen-level rules and form-level interactions.


Validation Rules

The ### Validation Rules section is a table with four columns: Name, Type, Required, Notes.

### Validation Rules

| Name         | Type   | Required | Notes                                                               |
|--------------|--------|----------|---------------------------------------------------------------------|
| Control Name | String | Yes      | Must be unique within the controller family                         |
| Event        | String | Yes      | Must map to at most one canonical name within the controller family |
### Validation Rules

| Name | Type   | Required | Notes          |
|------|--------|----------|----------------|
| Name | String | Yes      | Must be unique |

Always document validation rules in this table. Do not scatter validation constraints only in prose.


Navigation and State Transitions

Describe navigation outcomes in prose within ### Behaviour or in a CTA section. Use consistent phrasing:

Pattern Example
Navigate forward navigates to the Controller Family Detail screen
Return to parent returns to the Controller Families list
Return to same screen returns to the Controller Family Detail screen
No navigation closes the overlay and returns focus to the list

Never document generic navigation controls such as Tab, Shift+Tab, Back, or Escape in screen documents, either in prose or in wireframe bottom bar content. These are universal conventions and do not belong in screen-level documentation. The only exception is when Escape has a specific non-obvious effect within a particular mode (e.g. exiting capture mode), in which case it should be documented as part of that mode's behaviour.


Names and Slugs

Users always interact with human-readable names, never slugs. The slug is derived automatically from the name and is never shown as an editable field. Screen documents must use "Name" (or a domain-specific equivalent such as "Family Name" or "Compilation Name") for user-facing labels and template variables.

For entities where the slug alone is the filename (profiles, controller families), the derived slug must be unique within their directory. Validation should detect collisions and report them in terms of the name the user entered, not the derived slug. For games and controllers, the slug is combined with a unique ID (e.g. atic-atac--54321), so the name does not need to be unique.


Template Variables

Use <angle brackets> for values that are substituted at runtime. Use them consistently in wireframes, prose, and bottom bar message examples.

Convention Example
Dynamic title <Family Name>
Dynamic message <Family Name> deleted
Rename message <Old Family Name> renamed to <New Family Name>
Count <n> controller(s)

Wireframe Value Convention

Each screen area uses either placeholders or examples consistently throughout. Do not mix conventions within the same area.

Area Convention Rationale
Top bar Placeholder The title is always runtime-derived (game name, owner, etc.)
Main area Placeholder or Example Use whichever makes the layout clearest; apply it consistently
Bottom bar Placeholder Bottom bar content is always a runtime message or validation error

Placeholder means <angle bracket> template variables only — no real values.

Example means real representative values only — no <angle bracket> placeholders. Use _ for an empty text input (cursor position), Waiting... for an active capture state, and for an unmapped or unconfigured value. These are documentation conventions, not placeholders.


Page Template

Use this skeleton as the starting point for every new screen document.

## Primary Purpose

<One sentence describing what this screen enables the user to do.>

## Secondary Purpose

-   <One sentence describing each secondary purpose.>
-   <One sentence describing each secondary purpose.>

## Main Screen Design

​```
┌──────────────────────────────────────────────────────────────────────────────┐
│ TOP BAR                                                                      │
│  <Screen Title>                                                              │
├──────────────────────────────────────────────────────────────────────────────┤
│                                                                              │
│  <REGION NAME>                                                               │
│                                                                              │
├──────────────────────────────────────────────────────────────────────────────┤
│ BOTTOM BAR                                                                   │
│                                                                              │
└──────────────────────────────────────────────────────────────────────────────┘
​```

### TOP BAR

**Focusable:** <Yes / No / CTA names only><br/>
**Interactive:** <Yes / No / CTA names only><br/>
**Purpose:** <One line><br/>

### <REGION NAME>

**Type:** <e.g. Single-selection vertical list><br/>
**Focusable:** <Yes / No><br/>
**Interactive:** <Yes / No><br/>
**Order:** <e.g. Alphabetically by name><br/>
**Purpose:** <One line><br/>

### BOTTOM BAR

**Focusable:** No<br/>
**Interactive:** No<br/>
**Purpose:** <One line><br/>

### Behaviour

-

### Validation Rules

| Name | Type | Required | Notes |
|------|------|----------|-------|
|      |      |          |       |
⚠️ **GitHub.com Fallback** ⚠️