Skip to content

Screen readers still cannot read Experience content after #673 (form, subscription, and form-state cases) #675

Closed

Description

@sean-cstk

Summary

#673 added dialog semantics to the message slideout and bar templates, closing #670.
Three accessibility defects in the same area remain in the build now in production, and
the customer who raised #670 is still reporting unreadable Experiences.

Verified against the build currently served at
https://c.lytics.io/static/pathfora.min.js (v1.2.21, byte-identical to master
dfce6f6, checked 2026-08-26). Behavior confirmed by rendering each widget type and
layout in Chrome and inspecting the resulting DOM, not by reading templates.

Defect 1: form, subscription slideout and subscription bar have no dialog semantics

#673 changed only src/templates/message/. These templates were not covered and still
render with no pf-widget-container, no role, and no accessible name or description:

  • src/templates/form/slideout.html
  • src/templates/subscription/slideout.html
  • src/templates/subscription/bar.html

Measured, before any customer-side workaround:

form/slideout          wrap=ROOT | role=NONE | labelledby=notset | describedby=notset
subscription/slideout  wrap=ROOT | role=NONE | labelledby=notset | describedby=notset
subscription/bar       wrap=ROOT | role=NONE | labelledby=notset | describedby=notset

Customer-visible effect: a lead-capture Experience is not announced as a dialog and its
headline and message are never read.

Defect 2: the aria references in the #673 templates do not resolve

message/slideout.html and message/bar.html carry:

<div class="pf-widget-container" role="dialog"
     aria-labelledby="pf-widget-headline"
     aria-describedby="pf-widget-message">

No element in either template has id="pf-widget-headline" or
id="pf-widget-message" — those strings are present as class names only. Both
references point at ids that do not exist. modal and gate are unaffected because
their templates do set those ids.

Measured on the production build:

message/slideout  role=dialog | aria-labelledby="pf-widget-headline" -> DANGLING (no such id)
                              | aria-describedby="pf-widget-message" -> DANGLING (no such id)
message/bar       role=dialog | aria-labelledby="pf-widget-headline" -> DANGLING (no such id)
                              | aria-describedby="pf-widget-message" -> DANGLING (no such id)
modal             role=dialog | aria-labelledby="pf-widget-headline" -> RESOLVES text="<headline>"

Customer-visible effect: the Experience announces as a dialog but has no accessible
name or description, so its text is not read. bar additionally references a headline
element that does not exist in that layout at all.

Defect 3: form success and error states are not exposed after submit

constructFormState (src/rollup/form/construct-form-state.js) creates additional
elements carrying the same pf-widget-headline and pf-widget-message class names, one
set per state. A form Experience with formStates therefore renders three of each.
handleFormStates (src/rollup/form/handle-form-states.js) reveals a state by adding a
success or error class; it does not update any accessible name or description, and
the state containers are not marked as live regions.

Measured on a form slideout with formStates.success configured:

headline elements = 3, message elements = 3
  0: "Join our list"  parent=pf-widget-content
  1: "Thanks!"        parent=success-state
  2: "Oops"           parent=error-state

after the success class is applied:
  visible text  = "Thanks!"
  dialog name   = "Join our list"   (unchanged)

Customer-visible effect: a screen-reader user submits a lead-capture form and receives
no announcement of the confirmation or of a submission error. This is the point in the
interaction where feedback matters most.

Customer impact (ZD 22915 — Clorox)

  • Clorox retested after v1.2.21 shipped. Their "present message" Experiences improved;
    their "capture lead" Experiences are still not read out. That maps to Defect 1.
  • Defect 2 means the Add aria labels to slideout and bar widgets #673 change does not deliver a working accessible name on any
    layout it touched, so the improvement Clorox observed came from a customer-side
    workaround rather than from the shipped templates.
  • Clorox is a public-facing consumer brand treating this as a compliance requirement,
    and lead-capture forms are the Experience type where a missed submission has the most
    direct business consequence.
  • The library is a single shared script loaded by every customer running Experiences, so
    all three defects are present on every customer site using the affected types.

Legal / compliance exposure

  • US web accessibility is enforced under the ADA (Title III), with WCAG 2.1/2.2 Level AA
    as the de facto conformance standard, and Section 508 in federal contexts.
  • The EU European Accessibility Act (in force June 2025) creates comparable obligations
    for global brands.
  • Unnamed dialogs, unresolvable aria-labelledby references, and unannounced form
    status changes are all commonly cited WCAG failures (name/role/value; status
    messages). Because this markup is injected into the customer's own page, it becomes
    part of the customer's compliance surface.

References

Verification notes

Defects 1 and 2 were measured by rendering each type and layout against the production
build. Defect 3 was measured by rendering a form slideout with formStates and applying
the state class that handleFormStates applies. DOM and attribute state was inspected
directly; announcement behavior in a specific screen reader was not tested.

Activity

  1. sean-cstk commented on Sep 4, 2026

    @sean-cstk
    ContributorAuthor

    Tracked in Jira: LYT-1120 — https://contentstack.atlassian.net/browse/LYT-1120

    Filed on the LYT board per the escalation path for work that needs a core engineer. The Jira ticket carries the same detail and is the system of record for this work.

  2. self-assigned this
    on Sep 10, 2026
  3. ashyablok-cs commented on Sep 21, 2026

    @ashyablok-cs
    Contributor

    closed by #675

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions