SiteAlignedSample report · fictional product

Example Civic Software Accessibility Findings Report

Example Permit Portal 4.2 (build 4.2.118). Companion to the WCAG Edition Accessibility Conformance Report (ACR), the completed Voluntary Product Accessibility Template (VPAT®).

Version 1.0, issued . Testing: to .

This is a sample. The product, company, findings and code are fictional, and tool versions are placeholders. It shows how SiteAligned reports problems so a team can fix them: what's wrong, where, who it affects, how to reproduce it and how to fix it. Code examples are illustrative; test any change in your own product before release.

Summary for leadership

We tested six flows of Example Permit Portal 4.2 against the Web Content Accessibility Guidelines (WCAG) 2.2, Level A and AA. Most criteria are supported, but one critical problem blocks a required task. Of the 56 criteria in the ACR, 41 are rated Supports and 15 Partially Supports. We found 9 problems and 2 advisories:

Fix first, in this order:

  1. F1: the inspection date picker. People who use a keyboard can't schedule an inspection at all, and every permit needs one.
  2. F3 and F4: people using screen readers aren't told when an upload fails or when their session is about to end, so they can lose work without knowing.
  3. F2: application status is never spoken, so people using screen readers can't tell where their permit stands.

Each of these fixes is contained to one component. After they ship, a retest will re-evaluate the affected ratings and the ACR will be reissued with a new date.

Findings at a glance

Findings at a glance
IDFindingSeverityWCAG criteria
F1: go to findingInspection date picker can't be used without a mouseCritical2.1.1 Keyboard (A); 4.1.2 Name, Role, Value (A); 2.5.3 Label in Name (A)
F2: go to findingApplication status is not announcedHigh1.1.1 Non-text Content (A)
F3: go to findingRejected uploads are shown only by a red borderHigh3.3.1 Error Identification (A); 1.4.1 Use of Color (A); 3.3.3 Error Suggestion (AA)
F4: go to findingPeople using screen readers aren't warned before the session times outHigh2.2.1 Timing Adjustable (A)
F5: go to findingFee summary loses its pairing and forces sideways scrollingMedium1.3.1 Info and Relationships (A); 1.3.2 Meaningful Sequence (A); 1.4.10 Reflow (AA)
F6: go to findingFocus is lost when the Add document dialog closesMedium2.4.3 Focus Order (A)
F7: go to findingUploaded documents can be reordered only by draggingMedium2.5.7 Dragging Movements (AA)
F8: go to findingCheckbox borders are too faint to seeLow1.4.11 Non-text Contrast (AA)
F9: go to findingUpload confirmation is not announcedLow4.1.3 Status Messages (AA)
A1: go to findingThe timeout warning gives only two minutesAdvisoryMeets 2.2.1 Timing Adjustable (A) on length
A2: go to findingThe error summary heading doesn't say what to doAdvisoryMeets 3.3.1 Error Identification (A) and 2.4.6 Headings and Labels (AA)

Severity levels

Finding details

The full test environment and scope are in the ACR. Each finding names the screen, the element and what it was tested with, so someone who wasn't there can reproduce it. Evidence IDs refer to recordings and screenshots available on request.

F1 Inspection date picker can't be used without a mouse

Severity: Critical
WCAG
2.1.1 Keyboard (A); 4.1.2 Name, Role, Value (A); 2.5.3 Label in Name (A)
Where
Schedule inspection screen; element #inspection-date .calendar-grid
Tested with
Keyboard only in Chrome 144 on Windows 11; NVDA 2025.3.2 with Firefox 147
Who it affects
People who use a keyboard, switch devices or voice control, and people using screen readers
Evidence
Screen recording E-01 (keyboard), E-02 (NVDA)

Steps to reproduce

  1. Sign in and open an issued permit (status: Approved).
  2. Choose "Schedule inspection."
  3. With no screen reader running, press Tab from the field before the date picker.
  4. Then turn on NVDA and move through the calendar with the down arrow key in browse mode, and press Enter on a day.

What happens

Tab moves from the previous field straight to "Back"; the calendar is never reached and arrow keys do nothing. With NVDA, the day cells are read as plain numbers with no role, full date or selected state, and pressing Enter does nothing because the click handler is on the calendar container, not on each day. The inspection date can only be set with the picker and is required, so the step can't be completed.

What should happen

Every available day can be reached and chosen with the keyboard, and screen readers announce each day as a selectable date with its full date and selected state.

Recommended fix

The simplest fix is a text field that accepts a typed date, with the format shown in the hint and checked on the server. If only some dates are available, a select menu or radio buttons listing those dates is simpler still. If the calendar must stay, rebuild it following the W3C ARIA Authoring Practices "Date Picker Dialog" example.

<label for="insp-date">Inspection date (required)</label>
<p id="insp-hint">For example, 11/14/2026</p>
<input id="insp-date" name="inspection_date" type="text"
  inputmode="numeric" autocomplete="off"
  aria-describedby="insp-hint" required>

W3C references: G202, F54, F59, F96; ARIA Authoring Practices: Date Picker Dialog example

F2 Application status is not announced

Severity: High
WCAG
1.1.1 Non-text Content (A)
Where
Applications list; element img.status-icon
Tested with
JAWS 2026.2512.50 with Chrome 144; NVDA 2025.3.2 with Firefox 147; VoiceOver with Safari 26.2 on macOS 26.2
Who it affects
People using screen readers
Evidence
Screen recordings E-03 (JAWS), E-04 (VoiceOver)

Steps to reproduce

  1. Open "My applications."
  2. With each screen reader, move through a row with the down arrow key.

What happens

JAWS and NVDA read "Permit 2041, Deck addition" and skip the status icon. VoiceOver reads "Permit 2041, Deck addition, status-approved.png, image." In no case is the status spoken as a word.

What should happen

The status is spoken as text: "Approved," "Pending" or "Rejected."

Recommended fix

Show the status as visible text next to the icon and hide the icon from assistive technology, or give the icon alt text that names the status. Visible text also helps people who don't recognize the icons.

<span class="status">
  <img src="status-approved.png" alt=""> Approved
</span>

W3C references: F65, H37, H67

F3 Rejected uploads are shown only by a red border

Severity: High
WCAG
3.3.1 Error Identification (A); 1.4.1 Use of Color (A); 3.3.3 Error Suggestion (AA)
Where
Upload documents step; element li.file-item.is-invalid
Tested with
NVDA 2025.3.2 with Firefox 147; visual check in Chrome 144
Who it affects
People using screen readers, people with low vision or color blindness, and anyone who misses the color change
Evidence
Screenshot E-05; screen recording E-06 (NVDA)

Steps to reproduce

  1. On the Upload documents step, upload a file in an unsupported format, such as a .heic photo.

What happens

The file's border changes from gray to red. No text explains the problem and nothing is announced, so the person can continue without knowing the file was rejected.

What should happen

A text message on the file, such as "Not uploaded: use PDF, JPG or PNG," that is announced when it appears and is tied to the file's Remove button.

Recommended fix

Add a text error to the file row, connect it to the row's Remove button with aria-describedby, and announce it through the step's single status message area (the same one F9 uses).

<!-- status area: on the page from the start, empty -->
<div id="upload-status" role="status"></div>

<li class="file-item is-invalid">
  site-plan.heic
  <p id="err-3" class="file-error">Not uploaded: use PDF, JPG or PNG.</p>
  <button type="button" aria-describedby="err-3">Remove
    <span class="visually-hidden">site-plan.heic</span></button>
</li>

// when a file is rejected:
status.textContent = "site-plan.heic was not uploaded. Use PDF, JPG or PNG.";

W3C references: F81, G83, G85, ARIA21, ARIA22

F4 People using screen readers aren't warned before the session times out

Severity: High
WCAG
2.2.1 Timing Adjustable (A)
Where
All signed-in screens; element div.timeout-warning
Tested with
NVDA 2025.3.2 with Firefox 147; JAWS 2026.2512.50 with Chrome 144
Who it affects
People using screen readers
Evidence
Screen recording E-07 (NVDA)

Steps to reproduce

  1. Sign in, start an application, and wait 18 minutes without activity.

What happens

The timeout warning and its Stay signed in button appear on screen, but nothing is announced and focus stays where it was. Someone using a screen reader can be signed out and lose changes made since their last save.

What should happen

The warning is announced as soon as it appears, and the Stay signed in button is easy to reach.

Recommended fix

Show the warning as an alert dialog and move focus to the Stay signed in button. A lighter alternative is to put the warning text in a role="alert" area that is on the page from the start, though people then still have to find the button.

<div role="alertdialog" aria-modal="true"
     aria-labelledby="to-title" aria-describedby="to-text">
  <h2 id="to-title">You'll be signed out in 2 minutes</h2>
  <p id="to-text">Your changes since your last save will be lost.</p>
  <button type="button" id="stay">Stay signed in</button>
</div>
// when shown: document.getElementById("stay").focus();

W3C references: SCR16, ARIA19; ARIA Authoring Practices: Alert and Message Dialogs pattern

F5 Fee summary loses its pairing and forces sideways scrolling

Severity: Medium
WCAG
1.3.1 Info and Relationships (A); 1.3.2 Meaningful Sequence (A); 1.4.10 Reflow (AA)
Where
Payment step; element div.fee-summary
Tested with
NVDA 2025.3.2 with Firefox 147; Chrome 144 at 400% zoom (320 CSS pixels wide)
Who it affects
People using screen readers; people who zoom in or use narrow screens
Evidence
Screen recording E-08 (NVDA); screenshot E-09 (400% zoom)

Steps to reproduce

  1. On the Payment step, read the fee summary with NVDA.
  2. Zoom the browser to 400%.

What happens

The fee names sit in one container and the amounts in another, so NVDA reads every fee name first and then every amount. At 400% the summary has a fixed width and the whole page scrolls sideways. The total is read correctly.

What should happen

Each amount is read with its fee name, and the summary fits the screen width.

Recommended fix

Rebuild the summary as a two-column table with a caption and row headers, and remove the fixed width on .fee-summary.

<table>
  <caption>Permit fees</caption>
  <thead><tr><th scope="col">Fee</th><th scope="col">Amount</th></tr></thead>
  <tbody>
    <tr><th scope="row">Plan review</th><td>$180.00</td></tr>
    <tr><th scope="row">Building permit</th><td>$240.00</td></tr>
  </tbody>
  <tfoot><tr><th scope="row">Total</th><td>$420.00</td></tr></tfoot>
</table>

W3C references: H51, H63, H39; C32 (reflow)

F6 Focus is lost when the Add document dialog closes

Severity: Medium
WCAG
2.4.3 Focus Order (A)
Where
Upload documents step; element div[role="dialog"]#add-document
Tested with
Keyboard only in Chrome 144 and Firefox 147
Who it affects
People who use a keyboard or a screen reader
Evidence
Screen recording E-10 (keyboard)

Steps to reproduce

  1. Press "Add document," choose a file, then press "Done."

What happens

Focus moves to the page itself; the next Tab goes to the "Skip to main content" link, so people have to tab back through the whole page.

What should happen

Focus returns to the Add document button.

Recommended fix

Remember which button opened the dialog and move focus back to it when the dialog closes. If the dialog is rebuilt as a native dialog element opened with showModal(), browsers return focus automatically.

let opener;
function openDialog(e) {
  opener = e.currentTarget;   // the Add document button
  dialog.hidden = false;
  dialog.querySelector("h2").focus();
}
function closeDialog() {
  dialog.hidden = true;
  opener.focus();
}

W3C references: SCR37, G59; ARIA Authoring Practices: Dialog (Modal) pattern

F7 Uploaded documents can be reordered only by dragging

Severity: Medium
WCAG
2.5.7 Dragging Movements (AA)
Where
Upload documents step; element ul.file-list
Tested with
Mouse and touch in Chrome 144 on Windows 11 and Android 16
Who it affects
People who can't drag precisely, including many people using a mouse with a tremor, a head pointer or a touch screen
Evidence
Screen recording E-11 (touch)

Steps to reproduce

  1. Upload two files and try to change their order without dragging.

What happens

People using a mouse or touch screen can reorder documents only by dragging. People using a keyboard can use Alt+Up and Alt+Down, but that doesn't help someone using a pointer who can't drag.

What should happen

Each document has Move up and Move down buttons, or an order field.

Recommended fix

Add Move up and Move down buttons to each file. After a move, keep focus on the moved file's button, disable Move up on the first file and Move down on the last, and announce the new position in the step's status area.

<button type="button">Move up
  <span class="visually-hidden">site-plan.pdf</span></button>

// after moving:
status.textContent = "site-plan.pdf moved to position 1 of 3.";

W3C references: G219, F108

F8 Checkbox borders are too faint to see

Severity: Low
WCAG
1.4.11 Non-text Contrast (AA)
Where
Contacts step; element input[type="checkbox"].form-check (custom-styled)
Tested with
Colour Contrast Analyser 3.5; Chrome 144
Who it affects
People with low vision
Evidence
Contrast measurement E-12

Steps to reproduce

  1. Measure the checkbox border against the white background.

What happens

The custom-styled border is #bec1c8 on white, 1.8:1. The labels can be selected to toggle each checkbox and the checked state shows a dark check mark, which is why this is rated Low.

What should happen

At least 3:1, for example #868a94 (3.46:1).

Recommended fix

Darken the border of the custom checkbox, or use the browser's own checkbox styled with accent-color.

/* custom checkbox drawn with appearance: none */
.form-check { border-color: #868a94; }

W3C references: Understanding 1.4.11: user interface components

F9 Upload confirmation is not announced

Severity: Low
WCAG
4.1.3 Status Messages (AA)
Where
Upload documents step; element span.upload-done
Tested with
NVDA 2025.3.2 with Firefox 147
Who it affects
People using screen readers
Evidence
Screen recording E-13 (NVDA)

Steps to reproduce

  1. Upload a valid PDF file.

What happens

"File uploaded" appears next to the file but is not announced. The file does appear in the list, so people can check it, which is why this is rated Low.

What should happen

"File uploaded" is announced without moving focus.

Recommended fix

Put the message in the step's status area, which must be on the page from the start and empty; don't hide or remove the area itself.

// when an upload finishes:
status.textContent = "site-plan.pdf uploaded.";

W3C references: ARIA22

Advisories

These meet WCAG but still make tasks harder for some people. They are worth fixing and don't affect the conformance levels in the ACR.

A1 The timeout warning gives only two minutes

Severity: Advisory
WCAG
Meets 2.2.1 Timing Adjustable (A) on length; the missing announcement is F4. Related: 2.2.6 Timeouts (AAA, not in scope)
Where
All signed-in screens; element div.timeout-warning
Tested with
Observation during testing
Who it affects
People who use screen readers, switch devices or voice control, and anyone who reads slowly

Steps to reproduce

  1. Wait 18 minutes without activity.

What happens

Two minutes meets WCAG's 20-second minimum, but it is short for people who need longer to notice the warning and reach the Stay signed in button.

What should happen

A longer warning, or drafts saved automatically so nothing is lost.

Recommended fix

Show the warning at least five minutes before timeout and save drafts automatically.

W3C references: SCR16

A2 The error summary heading doesn't say what to do

Severity: Advisory
WCAG
Meets 3.3.1 Error Identification (A) and 2.4.6 Headings and Labels (AA)
Where
Permit application form; element div.error-summary h2
Tested with
Observation during testing
Who it affects
Everyone, especially people with cognitive disabilities

Steps to reproduce

  1. Submit the form with two required fields empty.

What happens

The summary heading reads "Oops! Something went wrong." The linked list of errors below it is correct.

What should happen

A heading that says what to do, such as "Fix 2 problems to continue."

Recommended fix

Change the heading text.

W3C references: G130

About the visually-hidden class

Several examples use a visually-hidden class for text that screen readers read but that isn't shown on screen. If your product doesn't have one, this is a widely used version:

.visually-hidden {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%);
  white-space: nowrap; border: 0;
}