Patterns to Avoid: Disappearing Toast Notifications

๐ **Source:** [Patterns to Avoid: Disappearing Toast Notifications](https://wpaccessibility.org/docs/topics/design/avoid/toasts/)
> [!note]+ Document Notes
> > [!info] Provenance
> > **Analysis generated:** 2026-08-27 by Claude (Opus 5) via the `readwise-deep-read` pipeline.
> > **Source:** wpaccessibility.org โ https://wpaccessibility.org/docs/topics/design/avoid/toasts/
> > **Published:** 2026-08-21 ยท **Length:** 882 words ยท article (normative guidance document, not news)
> > **Byline:** **Absent from the captured markup.** Reader's `author` field is the bare domain. `[INFERENCE]` The sample code uses the `wp-a11y` text domain and a `wpa11y_` function prefix, and the site is structured as a WordPress accessibility documentation handbook โ consistent with WordPress Accessibility Team conventions. **Inference from code conventions, not a byline.** Not asserted as fact, and no individual author is named below.
> > **Register key used throughout:** `[STATED]` author-stated claim ยท `[EVIDENCE]` demonstrated evidence ยท `[INFERENCE]` reviewer inference ยท `[RECOMMEND]` reviewer recommendation.
> > **Coverage:** Full document retrieved and read (7,186 chars of HTML): 7 headings, 7 outbound links, 2 images, 1 blockquote, 2 `<pre>` blocks, 3 lists โ all enumerated.
> > **Verification performed:** The document's PHP sample was **executed** against the attribute-building loop in `wp-includes/functions.php :: wp_get_admin_notice()` from a local **WordPress 7.0.2** checkout (`~/.wp-tests/wordpress`). Result recorded below under [Verified defect](#verified-defect-the-code-sample-does-not-do-what-its-own-docblock-says). This is the one claim here that is tested rather than reasoned.
>
> # ๐ท๏ธ Title: Patterns to avoid: Disappearing toast notifications
>
<!-- deep-read:sections start -->
## ๐งญ Table of Contents
- [๐ Summary](#-summary)
- [๐ Main Content](#-main-content)
- [๐๏ธ Notes](#๏ธ-notes)
- [๐ References](#-references)
- [๐ฃ๏ธ Paraphrase](#๏ธ-paraphrase)
- [๐ฐ Newsletter](#-newsletter)
- [โ
Action Items](#-action-items)
- [๐งช Hypotheses](#-hypotheses)
- [๐ Methodology](#-methodology)
- [โ Questions](#-questions)
- [๐ฎ Future Research](#-future-research)
- [๐ก Implications](#-implications)
- [๐ง Learning Styles Assessment](#-learning-styles-assessment)
- [๐ Accessibility Assessment](#-accessibility-assessment)
- [๐ DEIB Assessment](#-deib-assessment)
- [โ
Logical Validity](#-logical-validity)
- [๐ก๏ธ DARVO Analysis](#-darvo-analysis)
- [๐ฏ Conclusion](#-conclusion)
### ๐ References
- [Adrian Roselli โ Defining 'Toast' Messages](https://adrianroselli.com/2020/01/defining-toast-messages.html)
- [WCAG 2.2 Quick Reference โ Reflow (1.4.10)](https://www.w3.org/WAI/WCAG22/quickref/#reflow)
- [WCAG 2.2 Quick Reference โ Resize Text (1.4.4)](https://www.w3.org/WAI/WCAG22/quickref/#resize-text)
- [wpaccessibility.org โ Feedback on dynamic changes](https://wpaccessibility.org/docs/topics/code/dynamic-changes/)
- [WordPress developer reference โ `admin_notices`](https://developer.wordpress.org/reference/hooks/admin_notices/)
- [Gutenberg โ `Notice` component](https://github.com/WordPress/gutenberg/tree/trunk/packages/components/src/notice)
- [Gutenberg โ `Snackbar` component](https://github.com/WordPress/gutenberg/tree/trunk/packages/components/src/snackbar)
## ๐ Summary
**What it is.** A normative "patterns to avoid" guidance page. It distinguishes **banner** (multi-paragraph, top of screen, persists until dismissed), **snackbar** (short, bottom or near focus, "preferably stays on screen until dismissed"), and **toast** (short, auto-disappears after a few seconds); argues against the third; and supplies WordPress-specific replacements.
**The argument, and it is a good one.** `[STATED]` Six concrete failure modes for auto-dismissing toasts: the user must *notice* it, must have *time to read* it, cannot *re-read* it, may be looking somewhere else entirely, may lose it outside the viewport when zoomed, and gets nothing at all if it isn't announced to assistive tech. `[EVIDENCE]` The killer example is WordPress's own: **the Publish button is upper-right; its toast fires lower-left.** That is a real, checkable, present-tense defect in the software the audience ships on, and naming it is the page's strongest move.
**Why it matters.** `[INFERENCE]` This is a document people will **cite in audits and code review**, which raises the bar on it: guidance is load-bearing in a way commentary is not. Judged at that bar it is largely right, practically useful, and carries **one verified defect and three gaps** that matter for exactly that use.
**Risks and tradeoffs.** `[EVIDENCE]` **The PHP sample does not produce the markup its own docblock promises.** Executed against WP 7.0.2, `'attributes' => array( 'role', 'alert' )` emits `<div class="notice notice-error" role alert>` โ an empty `role` and a junk `alert` attribute โ not `role="alert"`. It fails silently: no error, no warning, correct-looking output, and the announcement simply never happens.
**Bottom line.** `[INFERENCE]` Adopt the guidance; **do not copy the code.** And before citing this page in an audit finding, supply the WCAG mapping it omits โ because the success criterion a reader will reach for first, **4.1.3 Status Messages, is *satisfied* by a properly marked-up toast that vanishes.** The real argument is 2.2.1 Timing Adjustable, and the page never makes it.
## ๐ Main Content
### Verified defect: the code sample does not do what its own docblock says
The page offers this as its `admin_notices` example, with a docblock reading `[STATED]` *"Output an admin notice with `role="alert"`, so it will be announced by assistive technology."*
```php
wp_admin_notice(
$message,
array(
'type' => 'error',
'attributes' => array( 'role', 'alert' ),
)
);
```
`[EVIDENCE]` `array( 'role', 'alert' )` is a **numerically indexed** array โ keys `0` and `1`, values `'role'` and `'alert'` โ where core expects `attr => value` pairs. The relevant loop in `wp-includes/functions.php :: wp_get_admin_notice()` (WP 7.0.2) is:
```php
foreach ( $args['attributes'] as $attr => $val ) {
if ( is_bool( $val ) ) {
$attributes .= $val ? ' ' . $attr : '';
} elseif ( is_int( $attr ) ) {
$attributes .= ' ' . esc_attr( trim( $val ) );
} elseif ( $val ) {
$attributes .= ' ' . $attr . '="' . esc_attr( trim( $val ) ) . '"';
}
}
```
`[EVIDENCE]` Both keys are integers, so both hit the **second** branch and are emitted as bare valueless attributes. Executed output:
```html
<!-- doc example: array( 'role', 'alert' ) -->
<div class="notice notice-error" role alert><p>Your message will be output.</p></div>
<!-- correct: array( 'role' => 'alert' ) -->
<div class="notice notice-error" role="alert"><p>Your message will be output.</p></div>
```
The fix is one character-pair: `array( 'role' => 'alert' )`.
`[INFERENCE]` **The instructive part is why this survives.** Core's `is_int( $attr )` branch exists deliberately, to support valueless HTML attributes like `hidden` or `disabled` written as `array( 'hidden' )`. That legitimate feature is precisely what swallows the most common malformed-array mistake. A stricter function would have thrown a `_doing_it_wrong()` โ as this same function *does* for a `type` containing spaces. **The API validates the argument that fails loudly and accepts the one that fails silently.**
`[RECOMMEND]` This is a **detectable class**, not a one-off. Any `wp_admin_notice()` / `wp_get_admin_notice()` call whose `attributes` array has integer keys is almost certainly a bug, and it is greppable. Worth adding to the `wp-a11y-reviewer` agent as an explicit check, alongside the general rule: **flag any core API that accepts a malformed argument shape without complaint.** Silent-failure surfaces are where accessibility defects accumulate, because nothing in the toolchain ever objects.
### The deeper problem: even the corrected code is unreliable
`[INFERENCE]` Fixing the array shape yields valid `role="alert"` markup โ and still probably does not announce, for two reasons the page does not raise.
**One: live regions announce *changes*, not initial content.** A region must exist in the DOM *before* its content changes for assistive tech to register and monitor it. `admin_notices` output is present in the **initial page HTML**, so there is no change to announce. Behaviour across screen readers for live-region content present at page load is inconsistent, and depending on it is the kind of assumption that passes a developer's spot-check and fails a real user. `[RECOMMEND]` This is testable, it is the single highest-value experiment in this analysis, and nobody appears to have published it for `wp_admin_notice()` specifically.
**Two: `role="alert"` contradicts the page's own recommendation.** Four paragraphs earlier the page says `[STATED]` announce with *"`aria-live="polite"` or `role="status"`."* `role="alert"` is `aria-live="assertive"` โ it **interrupts** whatever the screen reader is currently saying. For an ordinary admin notice printed on page load, that is the wrong register, and the page's own advice is the better advice. **The example contradicts the prose.**
`[INFERENCE]` The page already contains the right answer for genuinely dynamic messages and does not connect it: `[STATED]` *"For WordPress core, you can use `wp.a11y.speak()`."* That is the mechanism designed for this, and its correctness does not depend on when a region entered the DOM.
### The WCAG mapping the page omits โ and why the obvious one backfires
`[EVIDENCE]` The page cites WCAG only for **1.4.10 Reflow** and **1.4.4 Resize Text**, both attached to the zoom/viewport concern. It never maps its central complaint โ *the message disappears* โ to any success criterion. `[STATED]` It says instead: *"These are not only accessibility concerns but also usability issues."*
`[INFERENCE]` For a document meant to be cited in audits, that omission is the most consequential gap on the page, because the SC a reader reaches for first works **against** them:
| Criterion | Level | Does it cover disappearing toasts? |
|---|---|---|
| **4.1.3 Status Messages** | AA | **No โ and this is the trap.** It requires that status messages be programmatically determinable via role or properties *without receiving focus*. A toast with correct `role="status"` **passes 4.1.3 and still vanishes before it can be read.** Citing 4.1.3 hands the other side the win. |
| **2.2.1 Timing Adjustable** | A | **Yes โ this is the argument.** Auto-dismissal is a content-imposed time limit on reading. Unless the user can turn it off, adjust it, or extend it, a strong reading makes it a **Level A** failure. The page's own note that hover/focus-to-delay "can help, but the user must know this is possible" is precisely a 2.2.1 sufficiency discussion โ conducted without naming 2.2.1. |
| **2.2.3 No Timing** | AAA | Clean fit, rarely in scope. |
| **1.4.10 / 1.4.4** | AA | Yes, for the zoom-overlap concern. Correctly cited. |
`[RECOMMEND]` **Lead with 2.2.1 Timing Adjustable and never cite 4.1.3 as the failure.** Use 4.1.3 only for the separate defect of a toast that *isn't announced at all*. Conflating the two is how a toast finding gets closed as "we're conformant."
`[INFERENCE]` And the honest framing is stronger than the page's: this is a **usability failure with a Level A argument available**, not a clear-cut conformance failure. The page has it backwards โ "not only accessibility but also usability" implies accessibility is the settled part. It isn't. The usability case is airtight and the conformance case has to be argued.
### The recommended fix does not fix the stated problem
`[EVIDENCE]` The page's most vivid complaint is spatial: `[STATED]` *"the 'publish' button in WordPress is in the upper right corner, but triggers a toast notification in the lower left corner. This distance increases the likelihood that users will miss the notification."*
`[EVIDENCE]` Its Gutenberg remedy is: `[STATED]` use `Snackbar`, and *"set `explicitDismiss` to true."*
`[INFERENCE]` `explicitDismiss` stops the message auto-dismissing. **It does not move it.** A persistent snackbar in the lower-left is still lower-left while the button is upper-right โ the exact distance the page identified as the problem. The fix addresses **duration** and leaves **position** untouched, even though the page's own general advice covers position: `[STATED]` *"add messages to a region in a consistent placeโฆ close to the previous user interaction."*
`[RECOMMEND]` The two halves are both present on the page and never joined. Anyone applying this guidance should treat them as **two independent requirements** โ *persist* **and** *place near the trigger* โ and note that Gutenberg's `Snackbar` component gives you the first, not the second.
### What the page gets right
`[INFERENCE]` It would be easy to read the above as a negative assessment. It is not. The page is better than most accessibility guidance on several axes worth naming precisely:
- **The three-way taxonomy is genuinely clarifying.** Banner / snackbar / toast are used interchangeably across design systems, and separating them by *persistence* and *position* rather than by visual style is the right cut.
- **It names a defect in its own ecosystem's flagship software.** The Publish-button example is specific, current, verifiable, and mildly embarrassing to WordPress. Guidance that only criticises other people's software is worth less.
- **It cites the primary source.** Roselli's *Defining 'Toast' Messages* is the canonical treatment and is linked at the right moment.
- **It supplies a testing instruction, not just a principle:** `[STATED]` *"Test if the message stays visible when a user zooms in or enlarges the text by using reflow or text only"* โ with both WCAG techniques linked. Most guidance stops at the principle.
- **It handles the screen-reader/sighted split correctly.** `wp.a11y.speak()` is introduced to inform the screen reader user *"too"* โ the word does real work, since `speak()` is visually hidden and does nothing for the low-vision or slow-reading user the page spends most of its words on. Easy to get wrong; got right.
## ๐๏ธ Notes
Not a transcript โ dense notes, no timestamps.
- **The "Summarized" checklist contains a self-contradiction.** `[STATED]` *"The message stays on screen until the user dismisses it, or after a page reload."* Read literally, the second clause says the message persists *after* reloading. The intent is plainly "until dismissed, or until the page reloads." In a four-item normative checklist meant to be copied into review criteria, ambiguous wording is a defect rather than a typo.
- **The Eric Eggert quote is attributed but not linked.** `[EVIDENCE]` Verified against the markup: the document contains 7 `<a>` elements and **none** points to Mastodon; the attribution line *"โ Eric Eggert Mastodon"* is plain text, with "Mastodon" not hyperlinked. `[INFERENCE]` Conspicuous because the page otherwise cites well โ Roselli, WCAG quickref, developer.wordpress.org, two Gutenberg component sources are all properly linked. The one quotation is the one unlinked claim.
- **The blockquote lacks `<cite>` or `figure`/`figcaption`.** `[EVIDENCE]` `<blockquote>` followed by a bare `<p>` attribution. Minor, and worth noting only because an accessibility documentation page is held to its own standard.
- **The "done well" example is well chosen.** `[EVIDENCE]` The theme-update flow shows the actual `#a11y-speak-polite` region markup with `aria-live="polite" aria-relevant="additions text" aria-atomic="true"` and the visually-hidden clip pattern. Showing the real DOM output rather than describing it is the most useful thing a code-level doc can do โ and it is *also* the page's implicit answer to its own broken PHP example, sitting a few paragraphs below it.
- **Both screenshots have descriptive alt text** โ `"Notification: New version available"` and `"Notification: Updated"`. `[EVIDENCE]` The alt conveys the message content, which is the informative part of a notification screenshot. Correct.
- **The snackbar definition hedges where it should not.** `[STATED]` A snackbar *"preferably* stays on screen until dismissed by the user." `[INFERENCE]` "Preferably" undercuts the page's entire thesis โ if a snackbar may auto-dismiss, it is a toast, and the page has just argued against those. Either the taxonomy holds or it doesn't.
- **`wp.a11y.speak()` versus `speak()` from `@wordpress/a11y`** is stated correctly (core vs block editor) but without noting that both are the same underlying utility. A minor point of possible confusion for someone new to the split.
## ๐ References
See [๐ References](#-references). Seven outbound links, all enumerated and all live-looking.
`[EVIDENCE]` **The citation practice is good and specifically well-targeted:** one canonical external authority (Roselli), two WCAG techniques linked at the exact sentence recommending the test, one internal cross-reference (*Feedback on dynamic changes*), one core hook reference, and two links to Gutenberg component **source trees** rather than to prose documentation.
`[INFERENCE]` That last choice is worth noting approvingly โ linking `packages/components/src/snackbar` sends the reader to the props themselves, which is where `explicitDismiss` is actually defined and where it will stay accurate as the component changes. Prose docs drift; source does not.
The single uncited claim is the Eggert quotation, verified above.
## ๐ฃ๏ธ Paraphrase
There are several ways to show a user a message that appears dynamically, and they are not interchangeable. A **banner** is longer, sits at the top, and stays until dismissed. A **snackbar** is short, appears at the bottom or near where the user is working, and should stay until dismissed. A **toast** is short and disappears on its own after a few seconds.
Toasts cause problems. To get the message you have to both notice it and finish reading it before it goes. It usually appears somewhere unrelated to where you are working โ WordPress fires one in the lower left when you press Publish in the upper right โ so you may not see it at all. Not everyone reads quickly. Once it's gone you cannot get it back. Pausing on hover or focus helps only if you know that's possible, and a keyboard user may not reach it in time. Zoomed in, it can fall outside the viewport or be covered. And a screen reader user gets nothing unless it's announced with something like `aria-live="polite"` or `role="status"`.
The fix is a message that stays put: shown in a consistent, findable place, dismissed by the user or cleared when it stops being relevant, still visible when text is enlarged, and announced to assistive technology. In WordPress, use `admin_notices` for admin screens, the `Notice` or `Snackbar` components in the block editor with `explicitDismiss` set, and `wp.a11y.speak()` to make the announcement.
## ๐ฐ Newsletter
**Stop shipping toasts.** The WordPress accessibility docs have a new "patterns to avoid" page on disappearing notifications, and its sharpest example is WordPress itself: **the Publish button is upper-right, the toast fires lower-left.** Maximum distance between where you're looking and where the confirmation appears. Eric Eggert's line in the piece is the whole argument โ *"How many days of my life have I wasted in wait to get a confirmation for an action only to see in the corner of my eye on my 27-inch screen that a toast message has just disappeared?"*
The guidance is solid: put the message somewhere consistent and near what the user just did, let *them* dismiss it, check it survives zoom and text-resize, and announce it with `wp.a11y.speak()`.
**Two things to know before you use it, though.**
**Don't copy the PHP sample.** It passes `'attributes' => array( 'role', 'alert' )` โ a numerically indexed array where core wants `attr => value`. Run it and you get `<div class="notice notice-error" role alert>`: an empty `role` and a junk `alert` attribute, not `role="alert"`. No error, no warning, output that looks fine, announcement that never happens. **The fix is `array( 'role' => 'alert' )`.** Worth grepping your own plugins for โ core's support for valueless attributes like `hidden` is exactly what swallows this mistake silently.
**And if you cite this in an audit, bring the WCAG mapping the page doesn't.** The obvious criterion backfires: **4.1.3 Status Messages is *satisfied* by a properly marked-up toast that vanishes** โ cite it and you hand the other side "we're conformant." The real argument is **2.2.1 Timing Adjustable (Level A)**: auto-dismissal is a time limit on reading. Save 4.1.3 for toasts that aren't announced at all.
One more: the page's Gutenberg fix (`Snackbar` with `explicitDismiss: true`) stops the message vanishing but **doesn't move it.** Still lower-left, button still upper-right. Persistence and placement are two requirements, and the component only gives you one.
## โ
Action Items
#### DevRel
- **Developer advocacy:** `[RECOMMEND]` The verified code defect is a better talk than the toast argument. "Your accessibility fix silently didn't apply" โ a one-character bug, in published guidance, on an accessibility site, that renders without complaint โ is a memorable way into the whole class of **silent-failure APIs.**
- **Education:** Teach the 2.2.1-vs-4.1.3 distinction explicitly. `[INFERENCE]` The intuition that "status messages" is the status-message criterion is exactly wrong here, and it is the sort of error that survives training because it sounds right.
- **Developer experience:** `[RECOMMEND]` Propose a `_doing_it_wrong()` in `wp_get_admin_notice()` when `attributes` contains integer keys **whose values look like attribute names** โ or, more conservatively, document the valueless-attribute form prominently, since that ambiguity is the trap.
- **Developer marketing:** Not applicable to this source.
- **Community management:** Not applicable to this source.
- **Cross-project:** Not applicable to this source.
#### OSPO
- **Policy & Governance:** `[RECOMMEND]` A general policy worth having: **normative guidance containing runnable code should have that code executed as part of review.** Prose review does not catch an array-shape error; running it takes seconds.
- **License Compliance:** Not applicable to this source.
- **Security Management:** `[INFERENCE]` Adjacent but real โ the same silent-acceptance pattern that swallows a malformed `attributes` array is the pattern that swallows a malformed capability or nonce argument. **APIs that accept malformed shapes without complaint are a defect class that spans accessibility and security**, and the review habit is the same one.
- **Software Inventory:** Not applicable to this source.
- **Developer Support:** Not applicable to this source.
- **Community Engagement:** Not applicable to this source.
- **Strategic Alignment:** Not applicable to this source.
#### Community
- **Maintainers:** `[RECOMMEND]` Grep your codebase: `wp_admin_notice` / `wp_get_admin_notice` calls whose `attributes` array has integer keys. Mechanical, fast, and silently broken wherever it appears.
- **Contributors:** `[RECOMMEND]` **File the correction on this page.** It is a genuinely good first contribution โ small, verified, reproducible, with a one-line fix and no judgment call involved.
- **Sponsors:** Not applicable to this source.
- **Ecosystem:** Not applicable to this source.
#### WordPress
- **Core:** `[RECOMMEND]` Two candidate tickets. (1) The Publish-toast distance problem the page names โ a real, current, reproducible UX/a11y defect in the editor. (2) `_doing_it_wrong()` or improved inline docs for the `attributes` argument shape.
- **Core Performance:** Not applicable to this source.
- **Core AI:** Not applicable to this source.
- **Core Program Team:** Not applicable to this source.
- **Mobile:** `[INFERENCE]` Toasts originate in Android's `Toast` API, where the platform enforces the timing. Whether the WordPress mobile apps inherit the disappearing-message problem is out of scope for this page and a reasonable question to ask separately.
- **Playground:** `[RECOMMEND]` An ideal Playground demo: the same notice with the broken and corrected `attributes` array, side by side, with the rendered DOM visible. The bug is invisible in the UI and obvious in the markup โ exactly what Playground is good at showing.
- **Community:** Meetup material โ short, concrete, and immediately actionable.
- **Training:** `[RECOMMEND]` The SC-mapping table above is a lesson in itself. Learn WordPress has no current material on *which criterion to cite*, which is where audit findings actually succeed or fail.
- **Marketing:** Not applicable to this source.
- **Support:** Not applicable to this source.
- **Design:** `[RECOMMEND]` The persistence-vs-placement split belongs in design guidance, not just code guidance. A design system can specify "near the trigger" in a way a component prop cannot.
- **Documentation:** `[RECOMMEND]` Fix the sample, fix the "or after a page reload" clause, link the Eggert quote, and reconcile `role="alert"` in the example against `aria-live="polite"` / `role="status"` in the prose.
- **Photos / TV / Openverse / Polyglots / Meta / CLI / Hosting / Tide / Themes / Plugins:** Not applicable to this source โ a design-and-code guidance page with no surface in these teams' work.
- **Accessibility:** `[RECOMMEND]` The substantive additions this page needs: the **WCAG mapping** (2.2.1 as the argument, 4.1.3 as the trap), the **live-region-on-page-load caveat**, and the **persistence โ placement** distinction. All three are improvements to a page that is already better than most.
#### The WPOCC
- **Programs:** Not applicable to this source.
- **Projects:** `[INFERENCE]` A documentation-sprint model that includes **executing** every code sample would catch this defect class generally. Worth noting as a possible practice, not proposed as a programme.
- **Funding experiments:** Not applicable to this source.
### FAIR
- **Technical independence:** Not applicable to this source.
- **Policies and covenants:** Not applicable to this source.
- **Productized governance artifacts:** Not applicable to this source โ a technical guidance page with no governance dimension.
## ๐งช Hypotheses
1. **H1 โ Live-region roles in initial page HTML are unreliable.** An admin notice carrying `role="alert"` or `role="status"` present in the **initial DOM** is not announced by a majority of screen reader / browser pairings, because live regions announce changes rather than existing content.
2. **H2 โ The malformed-attributes pattern is widespread.** A meaningful fraction of `wp_admin_notice()` / `wp_get_admin_notice()` calls in public plugin code pass `attributes` as a numerically indexed array, producing silently invalid markup.
3. **H3 โ Distance predicts miss rate.** For an auto-dismissing message, the screen distance between the triggering control and the message predicts the probability a user fails to notice it, independent of the message's duration.
4. **H4 โ Persistence alone is insufficient.** Making a snackbar persistent (`explicitDismiss: true`) without relocating it produces a smaller improvement in noticed-message rate than relocating it near the trigger without changing duration.
5. **H5 โ Auditors reach for the wrong criterion.** Given a disappearing-toast defect, practitioners cite 4.1.3 Status Messages more often than 2.2.1 Timing Adjustable, and findings citing 4.1.3 are dismissed as non-conformant-but-passing at a higher rate.
6. **H6 โ Executing samples catches defects prose review misses.** Documentation review that runs code samples finds materially more defects per sample than review that reads them.
## ๐ Methodology
- **H1 โ the highest-value experiment here, and genuinely under-tested.** Build a WordPress admin page emitting a notice with `role="alert"` in the initial DOM, and a matched notice injected post-load via JavaScript. Test both across a screen-reader matrix (NVDA/Firefox, NVDA/Chrome, JAWS/Chrome, VoiceOver/Safari, VoiceOver/iOS, TalkBack/Chrome). Primary endpoint: announcement, yes or no. **Confound:** verbosity settings and browse-vs-focus mode both affect announcement; hold them at defaults and report them. `[RECOMMEND]` A dozen pairings, an afternoon, and it would settle a question a lot of WordPress code currently guesses at.
- **H2 โ cheapest to run.** Static analysis over the plugin directory: parse `wp_admin_notice(` / `wp_get_admin_notice(` call sites, extract the `attributes` argument, flag integer-keyed arrays whose values match known attribute names. Report as a rate over total call sites. **Limit:** static parsing misses variables built elsewhere, so the result is a **lower bound** โ state it as one.
- **H3:** Controlled task study. Participants complete a task triggering a message; manipulate trigger-to-message distance across conditions with duration fixed. Endpoint: self-reported noticing, validated against eye-tracking or a comprehension probe. **Confound:** self-report over-reports noticing; the comprehension probe is what makes it real.
- **H4:** 2ร2 factorial โ persistent/auto-dismiss ร near/far. **This is the design that separates the two variables the page conflates**, and it directly tests whether the Gutenberg `explicitDismiss` remedy is the right one.
- **H5:** Survey or corpus study of published audit reports. **Weak design** โ access to real audit reports is limited and they are rarely public. Listed because the practical stake is high, not because the study is easy.
- **H6:** Straightforward. Take a corpus of documentation pages with runnable samples; two reviewer arms, one executing and one not; compare defect counts. **Confound:** reviewer skill, so randomise assignment.
## โ Questions
- **Does `role="alert"` in initial page HTML actually announce?** If not โ which is the likely answer โ a lot of WordPress admin-notice accessibility code is decorative, and this page's example is decorative twice over.
- Why does `wp_get_admin_notice()` validate `type` with `_doing_it_wrong()` but silently accept a malformed `attributes` array? Deliberate, or an artifact of when each branch was added?
- Should Gutenberg's `Snackbar` default `explicitDismiss` to `true`? `[INFERENCE]` If the accessibility guidance says always set it, the default is wrong.
- Is there a defensible case for auto-dismissing messages *anywhere*? The page implies no. High-frequency low-stakes confirmations in a tight loop are the strongest counter-case and go unaddressed.
- What is the actual WCAG position on toast auto-dismissal? `[INFERENCE]` 2.2.1 has an "Essential" exception, and someone will argue a toast's brevity is essential to its function. The counter-argument needs to be written down.
- How many other code samples in this documentation set have never been executed?
## ๐ฎ Future Research
- **Empirical screen-reader behaviour for live regions present at page load.** Widely assumed, rarely tested, and load-bearing for a great deal of shipped code.
- **A silent-failure taxonomy for WordPress APIs.** Which core functions accept malformed argument shapes without complaint. `[INFERENCE]` Mechanically discoverable, useful to both accessibility and security review, and nobody owns it.
- **Separating persistence from placement in notification effectiveness.** The literature treats notification design largely as a timing problem; this page's own best example is a *spatial* one.
- **Whether documentation defect rates differ between executed and unexecuted samples.** Relevant well beyond accessibility.
## ๐ก Implications
- **Practice.** `[RECOMMEND]` **Adopt the guidance, do not copy the code, and supply the WCAG mapping yourself.** Concretely: persist the message, place it near the trigger, verify under zoom and text-resize, announce with `wp.a11y.speak()` rather than relying on a role attribute in static markup.
- **Policy.** Guidance carrying runnable code should be reviewed by running it. `[INFERENCE]` This defect would have survived any number of careful prose readings and could not have survived one execution.
- **Security.** `[INFERENCE]` The transferable lesson is not about toasts. **An API that accepts a malformed argument shape and produces plausible-looking output is a defect factory**, and the same shape of bug in a capability check or a nonce argument is a security problem rather than an accessibility one. The review habit โ *did this argument actually take effect?* โ is identical.
- **Education.** The 4.1.3 trap deserves to be taught explicitly. **Citing the wrong criterion is how a correct finding gets closed as compliant**, and the criterion that sounds right is the one that loses.
- **Funding models.** Not applicable to this source.
## ๐ง Learning Styles Assessment
**Reading level estimate.** By **FleschโKincaid Grade Level**, roughly **grade 10โ11** โ sentences average ~19 words, vocabulary is concrete, and paragraphs are short and single-purpose. `[INFERENCE]` Hand estimate from sentence and syllable counts on the 882-word body, not a tool score; ยฑ1.5 grades. **This is the most readable document in the batch**, and appropriately so for normative guidance. `[EVIDENCE]` A few phrasings read as non-native English โ *"Chances are that the user is busy,"* *"Then you are ensured all users will notice"* โ which affect polish rather than comprehension, and are the kind of thing a copyedit pass fixes without changing meaning.
#### ๐ Visual learners
- **Present:** Two annotated screenshots of the theme-update flow, both with descriptive alt text, plus formatted code blocks and a bulleted summary.
- **Improve:** `[EVIDENCE]` **The page's most vivid argument is spatial and has no diagram.** "Publish upper-right, toast lower-left" is a picture waiting to be drawn โ a single screen wireframe with the two positions marked would carry the point instantly and would work in any language. A three-column banner/snackbar/toast comparison graphic would do the same for the taxonomy, which is currently prose that the reader must hold in memory.
#### ๐ Aural learners
- **Present:** Nothing โ no audio version, no narration.
- **Improve:** `[INFERENCE]` Notable given the subject. A page about how screen readers announce messages has no audio demonstration. **A recording of NVDA announcing a correctly-marked message versus saying nothing for the broken one** would be the single most persuasive asset this page could add, and it is directly on-topic rather than a generic accommodation.
#### ๐ฃ๏ธ Verbal learners
- **Present:** **The page's strongest dimension.** The banner/snackbar/toast definitions are crisp and mutually exclusive, terms are defined before use, and the Eggert quote supplies a memorable verbal anchor for an abstract complaint.
- **Improve:** "Toast" itself is never explained as a metaphor (a message that pops up like bread from a toaster), which is a small missed opportunity given the page's otherwise careful term-definition habit.
#### ๐งฉ Kinesthetic learners
- **Present:** Runnable PHP, a testing instruction with linked techniques, and real DOM output to inspect.
- **Improve:** `[EVIDENCE]` **The runnable code doesn't work** โ which for a hands-on learner is the worst possible failure mode, since they are the ones who will actually paste it, see plausible output, and conclude it worked. `[RECOMMEND]` A Playground link with the broken and corrected versions side by side would turn the page's weakest asset into its best teaching moment.
#### ๐ง Logical learners
- **Present:** Clean structure โ problem, enumerated failure modes, solution, summary checklist, implementation. The six toast concerns are genuinely distinct rather than restatements.
- **Improve:** `[EVIDENCE]` **No WCAG mapping**, which is the logical spine a conformance argument needs; the reader is given six reasons and no criterion. And the example contradicts the prose (`role="alert"` vs `aria-live="polite"`/`role="status"`) with no acknowledgment โ a logical reader will notice and will not know which to follow.
#### ๐งโ๐คโ๐ง Social learners
- **Present:** One community voice (Eggert), and a cross-reference to a companion page.
- **Improve:** No discussion venue, no contribution path, no "report an issue" link. `[INFERENCE]` For documentation that invites correction โ and this page needs one โ the absence of a visible route to submit it is a real gap.
#### ๐งโโ๏ธ Solitary learners
- **Present:** Self-contained and complete; the "Summarized" checklist lets a reader self-assess without help.
- **Improve:** The checklist's ambiguous clause ("or after a page reload") undermines exactly the artifact a solitary learner depends on most.
#### ๐ฟ Naturalistic learners
- **Present:** Nothing.
- **Improve:** `[INFERENCE]` Little natural fit, and forcing one would be worse than omitting it. The nearest honest connection is *durability* โ a message that persists until acted on wastes less of the user's attention than one that must be caught โ which is a sustainability argument about human attention rather than energy. One sentence at most; not a gap.
## ๐ Accessibility Assessment
Assessed against **WCAG 2.2 AA**, from the captured markup only. `[INFERENCE]` **Scope limit stated plainly:** this evaluates content structure and text as retrieved by Reader. Focus visibility, keyboard operability, live contrast, and reflow cannot be tested from an HTML extraction โ they require the rendered page. Absence of a finding below is not a pass. `[INFERENCE]` Holding an accessibility documentation page to its own standard is fair, and it does substantially better than the news articles in this batch.
#### Screen reader semantics
- **Present:** `[EVIDENCE]` **Proper heading hierarchy** โ five `<h2>`, one `<h3>`, one `<h4>`, correctly nested with no skipped levels. **Both images carry descriptive alt text** that conveys the message content (`"Notification: New version available"`, `"Notification: Updated"`) rather than describing the picture, which is the right choice for a UI screenshot. Semantic `<blockquote>`, `<pre>`, `<code>`, and three genuine `<ul>` lists. **This is markup written by someone who knows what they are doing.**
- **Improve:** `[EVIDENCE]` The `<blockquote>` has no `<cite>` and is not wrapped in `<figure>`/`<figcaption>`; the attribution is a following `<p>`, so the quote and its source are not programmatically associated. Not a WCAG failure, and worth noting on a page held to its own standard.
#### Keyboard navigation
- **Not testable from the captured markup.** Requires the rendered page. No claim made either way.
#### Contrast and readability
- **Not testable from the captured markup** โ no CSS captured. `[INFERENCE]` Textual readability is the best in this batch: grade 10โ11, short paragraphs, terms defined before use.
#### Text resizing and reflow
- **Not testable from the captured markup.** `[EVIDENCE]` One structural note that *is* visible: the page contains two `<pre>` blocks, one of them a long single-line HTML string (the `a11y-speak-polite` region with inline styles). **Wide preformatted content is the classic 1.4.10 Reflow hazard** โ it must scroll within its own container rather than forcing horizontal page scroll at 320px. Cannot be verified from the extraction; flagged as the thing to check, and mildly ironic given the page instructs readers to test exactly this.
#### Media and captions
- **Not applicable** โ no audio or video. (See the aural-learners note above for why adding some would serve this particular subject unusually well.)
#### Forms and interactions
- **Not applicable** โ no forms or interactive controls in the captured content.
#### Standards reference
- **1.3.1 Info and Relationships (A)** โ largely satisfied; heading hierarchy and list semantics are correct. Minor gap: quote/attribution not programmatically associated.
- **1.1.1 Non-text Content (A)** โ satisfied. Both images have appropriate alt text.
- **2.4.6 Headings and Labels (AA)** โ satisfied. Descriptive headings throughout. `[INFERENCE]` Worth stating explicitly: this is the criterion both news articles in this batch failed, and this page passes it comfortably.
- **1.4.10 Reflow (AA)** โ **not assessable from the extraction.** Wide `<pre>` content is the specific risk.
## ๐ DEIB Assessment
#### Cultural breadth
- **Present:** Subject matter is universal; no region-locked examples.
- **Improve:** `[INFERENCE]` Reading speed varies with language proficiency, and the page's own argument โ *"not everyone reads fast"* โ applies with extra force to someone reading in a second language or using a machine translation. Auto-dismissal penalises non-native readers systematically, and naming that would strengthen the case at no cost.
#### Inclusive language
- **Present:** Neutral throughout, no gendered assumptions, jargon defined before use.
- **Improve:** Nothing substantive. `[EVIDENCE]` The prose has minor non-native-English constructions that a copyedit would smooth; this is a polish note, not an inclusion one, and it is worth saying plainly that the writing is clear.
#### Neurodiversity support
- **Present:** `[EVIDENCE]` **Genuinely strong.** Short paragraphs, consistent structure, descriptive headings, a summary checklist, one idea per paragraph. The "Summarized" section is exactly the kind of recap that helps readers who lose the thread in long prose.
- **Improve:** The self-contradictory checklist item ("stays on screen until the user dismisses it, or after a page reload") does the most damage to the readers who rely most on the summary. `[INFERENCE]` And the underlying subject is squarely a neurodiversity issue the page never names: **a message that vanishes penalises anyone whose attention was elsewhere**, which is a description of ADHD before it is a description of anything else. The page argues from reading speed and screen distance and never from attention โ its strongest available argument, unmade.
#### Representation
- **Present:** Two named voices โ Roselli cited as technical authority, Eggert quoted as lived experience. `[INFERENCE]` Pairing an authority with a first-person frustration is a good rhetorical structure and rare in technical documentation.
- **Improve:** `[EVIDENCE]` Both named voices are practitioners writing about the pattern; **no disabled user is quoted about their own experience of missing a message.** For guidance whose entire warrant is user harm, first-person testimony from an affected user would be more persuasive than either citation, and the page has room for it.
#### Psychological safety
- **Present:** `[EVIDENCE]` **Notably well handled.** The page criticises a widespread pattern without disparaging the developers who ship it, and it names a defect in WordPress core โ its own ecosystem's flagship โ without blame. That is the right posture for guidance meant to change behaviour.
- **Improve:** Nothing. `[INFERENCE]` The Eggert quote is mildly exasperated ("for the love of kittens") but aimed at the pattern rather than at people, and it reads as humour rather than as shaming.
## โ
Logical Validity
#### Strong reasoning
- **The six toast concerns are genuinely independent, which is what makes the argument hold.** Notice-ability, reading speed, non-repeatability, spatial separation, zoom/viewport loss, and screen-reader silence are six distinct failure modes, not one restated six ways. **Fixing any one leaves the others intact** โ which is precisely why the page's conclusion (don't use the pattern) follows rather than "use it carefully."
- **The Publish-button example is the strongest evidence on the page.** Specific, current, checkable by any reader in thirty seconds, and drawn from the audience's own software. `[EVIDENCE]` Verifiable claims about the reader's own tools are worth more than any number of general assertions.
- **The taxonomy is analytically sound.** Banner/snackbar/toast are separated by *persistence* and *position* โ the two properties that actually determine whether a message is received โ rather than by visual styling. That cut makes the argument possible; a style-based taxonomy would not.
- **The hover-to-delay concession is intellectually honest.** `[STATED]` *"Delaying the disappearance of the message on hover or focus can help, but the user must know this is possible, and a keyboard user may not have enough time to tab to the toast before it disappears."* The page raises the best counter-argument against itself and answers it specifically. That is the mark of an author arguing in good faith.
#### Fallacies
- **Internal contradiction โ the code example versus the prose.** The prose recommends `aria-live="polite"` or `role="status"`; the example uses `role="alert"`, which is assertive and interrupts. **Weakness:** a reader following the page's own sample departs from the page's own advice, with no acknowledgment that these differ. **Fix:** use `role="status"` in the example, or explain when `alert` is warranted.
- **Unsupported claim by implication โ the PHP sample.** `[EVIDENCE]` The docblock asserts the notice will have `role="alert"` "so it will be announced by assistive technology." **Verified false**: the output is `role alert`. The claim is not merely unsupported, it is contradicted by execution. **Fix:** `array( 'role' => 'alert' )`.
- **Missing warrant โ no WCAG mapping.** The page establishes harm and prescribes remedies without connecting either to a success criterion. **Weakness:** it is written to be cited in conformance contexts and supplies nothing citable, while the criterion a reader will guess (4.1.3) actively undercuts the argument. **Fix:** name 2.2.1 Timing Adjustable.
- **Non sequitur โ the Gutenberg remedy.** The stated problem includes spatial separation; the prescribed fix (`explicitDismiss: true`) addresses only duration. **Weakness:** a developer follows the guidance, ships a persistent lower-left snackbar under an upper-right button, and believes the issue is resolved. **Fix:** state persistence and placement as two requirements.
- **Equivocation in the taxonomy โ "preferably."** `[STATED]` A snackbar *"preferably* stays on screen until dismissed." If it may auto-dismiss, it is a toast by the page's own definition, and the category boundary dissolves. **Weakness:** minor, but it is the definitional foundation everything else rests on. **Fix:** drop "preferably" or explain the exception.
- **Argument from authority, lightly โ the Eggert quote.** A well-known practitioner's exasperation is offered as support. `[EVIDENCE]` Legitimate as *illustration* of the user experience; it is not evidence of frequency or severity, and the page does not overclaim it. Noted as a soft point rather than a real fallacy, and weakened slightly by being the page's one unlinked citation.
#### Tone of voice
Instructional, direct, and unusually free of hedging for accessibility guidance โ `[EVIDENCE]` *"Stop using toast messages,"* *"The best wayโฆ is to use a message component that stays on screen,"* and a checklist of four imperatives. `[INFERENCE]` That decisiveness is the right call for normative documentation: guidance that hedges gets ignored, and the page has earned its confidence with six independent reasons.
The register shifts once, for the Eggert quotation, from instruction to shared exasperation ("for the love of kittens"). `[INFERENCE]` It works โ it is the one moment that conveys what the problem *feels like* rather than what is wrong with it โ and it is clearly marked as someone else's voice.
`[INFERENCE]` The overall posture is **confident and self-critical at the same time**, which is rare: it criticises WordPress core by name, raises the strongest objection to its own thesis and answers it, and prescribes specific replacements rather than only prohibiting. The tone is not where this page falls short.
## ๐ก๏ธ DARVO Analysis
**No DARVO pattern present.** `[EVIDENCE]` DARVO โ Deny, Attack, Reverse Victim and Offender โ describes a response to *accusation*. This is technical guidance with no accused party and no accusation. There is no adversarial dimension of any kind.
Checking each element explicitly rather than omitting the section:
- **Deny:** None. The page affirms problems rather than denying them, including in its own ecosystem's software. `[EVIDENCE]` `[STATED]` "the 'publish' button in WordPressโฆ triggers a toast notification in the lower left corner" is the page naming a defect in the project it documents.
- **Attack:** None. The criticism targets a **pattern**, never a person or a team. `[EVIDENCE]` Even the sharpest line โ Eggert's "Please, for the love of kittens: Stop using toast messages" โ is aimed at the practice, and no implementer or vendor is named as culpable.
- **Reverse victim/offender:** None.
`[INFERENCE]` One adjacent observation, recorded separately because it is **not** DARVO and calling it so would inflate the finding: the page is written from the perspective of harmed users without any harmed user speaking. That is a representational gap, already logged under DEIB, and it is an absence rather than a rhetorical manoeuvre.
## ๐ฏ Conclusion
**Bottom line.** `[INFERENCE]` **Good guidance, broken sample, missing citation spine.** The argument against auto-dismissing toasts is correct, well structured, and rests on six independent failure modes โ fixing any one leaves the rest, which is what makes "don't use the pattern" the right conclusion rather than "use it carefully." Adopt it.
Three things to carry, in order of how much they change what you do:
1. **Do not copy the PHP.** `[EVIDENCE]` **Verified by execution** against WP 7.0.2: `'attributes' => array( 'role', 'alert' )` emits `<div class="notice notice-error" role alert>` โ an empty `role` and a junk `alert` โ not `role="alert"`. It fails silently, with plausible output and no warning. The fix is `array( 'role' => 'alert' )`. `[INFERENCE]` And the reason it survives is worth more than the bug: core's `is_int( $attr )` branch legitimately supports valueless attributes like `hidden`, and that feature is exactly what swallows the malformed form. **The same function raises `_doing_it_wrong()` for a `type` containing spaces โ it validates the argument that fails loudly and accepts the one that fails silently.**
2. **Bring the WCAG mapping the page omits, and avoid the obvious one.** `[INFERENCE]` **4.1.3 Status Messages is *satisfied* by a properly marked-up toast that disappears** โ citing it hands the other side "we're conformant." The argument is **2.2.1 Timing Adjustable (Level A)**: auto-dismissal is a content-imposed time limit on reading. Reserve 4.1.3 for toasts that aren't announced at all. The honest framing is a usability failure with a Level A argument available โ the page has it backwards.
3. **Persistence and placement are two requirements.** `[EVIDENCE]` The page's own headline complaint is spatial (Publish upper-right, toast lower-left); its Gutenberg remedy, `explicitDismiss: true`, stops the message vanishing and **does not move it.** Both halves are on the page and are never joined.
`[INFERENCE]` **The transferable lesson isn't about toasts.** An API that accepts a malformed argument shape and returns plausible-looking output is a defect factory, and the identical shape of bug in a capability check or a nonce argument is a security problem rather than an accessibility one. The review habit is the same either way: **ask whether the argument actually took effect, and run it to find out.** Prose review could not have caught this; one execution did.
**Practical next steps for readers.**
1. Grep for `wp_admin_notice` / `wp_get_admin_notice` calls whose `attributes` array has integer keys. Mechanical, fast, silently broken wherever it appears.
2. Apply the guidance as two requirements: **persist** the message **and** place it near the trigger.
3. Prefer `wp.a11y.speak()` over a role attribute in static markup โ live regions announce *changes*, and `admin_notices` output is in the initial DOM, so even the corrected `role="alert"` is unreliable.
4. Verify under zoom and text-resize, as the page instructs โ and check the page's own wide `<pre>` blocks while you're at it.
5. `[RECOMMEND]` **File the correction.** Verified, reproducible, one-line fix, no judgment call. It is a good first contribution and the page deserves to be right.
<!-- deep-read:sections end -->
๐ **Full text:** [[Full Document Contents/Articles/Patterns to Avoid Disappearing Toast Notifications.md|Patterns to Avoid: Disappearing Toast Notifications by wpaccessibility.org]]
## Highlights
- **Example**: the โpublishโ button in WordPress is in the upper right corner, but triggers a toast notification in the lower left corner. This distance increases the likelihood that users will miss the notification. ([View Highlight](https://read.readwise.io/read/01m11e05hb5aj4wxgmmmq30ke1))
- Note: THE STRONGEST EVIDENCE ON THE PAGE โ specific, current, checkable in thirty seconds, and drawn from the audience's own software. Guidance that only criticises other people's software is worth less. BUT THE PAGE'S OWN FIX DOESN'T FIX THIS. Its Gutenberg remedy is Snackbar with explicitDismiss: true โ which stops the message auto-dismissing and DOES NOT MOVE IT. A persistent lower-left snackbar under an upper-right button is still the exact distance just identified as the problem. The fix addresses DURATION and leaves POSITION untouched, even though the page's own general advice covers position ("close to the previous user interaction"). BOTH HALVES ARE ON THIS PAGE AND ARE NEVER JOINED. Treat them as TWO INDEPENDENT REQUIREMENTS โ persist AND place near the trigger โ and note Gutenberg's Snackbar component gives you the first, not the second. That's a design-system requirement, not a component prop: a design system can specify "near the trigger"; a prop can't. Testable as a 2x2 (persistent/auto-dismiss x near/far), which is the study that would separate the two variables this page conflates. ALSO: the page argues from reading speed and screen distance and NEVER FROM ATTENTION โ a message that vanishes penalises anyone whose attention was elsewhere, which describes ADHD before it describes anything else. Its strongest available argument, unmade. #atom/zettel/z3
- **Delaying** the disappearance of the message on hover or focus can help, but the user must know this is possible, and a keyboard user may not have enough time to tab to the toast before it disappears. ([View Highlight](https://read.readwise.io/read/01m11e0kqk8mf0b11ers0143f4))
- Note: THE MARK OF AN AUTHOR ARGUING IN GOOD FAITH โ raises the best counter-argument against its own thesis and answers it specifically. Worth keeping as a structural example, not just for the content. WHY THE OVERALL ARGUMENT ACTUALLY HOLDS: the page's six concerns are GENUINELY INDEPENDENT failure modes, not one restated six ways โ notice-ability, reading speed, non-repeatability, spatial separation, zoom/viewport loss, screen-reader silence. FIXING ANY ONE LEAVES THE OTHERS INTACT, which is precisely why the conclusion is "don't use the pattern" rather than "use it carefully." That's the test to apply to any avoid-this-pattern guidance: are the objections independent, or is it one objection wearing six hats? OTHER THINGS THIS PAGE GETS RIGHT AND MOST GUIDANCE DOESN'T: the banner/snackbar/toast taxonomy cuts by PERSISTENCE AND POSITION rather than visual style โ the two properties that actually determine whether a message is received, and the cut that makes the argument possible at all. It supplies a TESTING INSTRUCTION, not just a principle ("test if the message stays visible when a user zooms inโฆ using reflow or text only") with both WCAG techniques linked. It handles the SR/sighted split correctly โ wp.a11y.speak() informs the screen reader user "too," and that word does real work since speak() is visually hidden and does nothing for the low-vision or slow-reading user the page spends most of its words on. Easy to get wrong; got right. ONE HEDGE THAT UNDERCUTS IT: a snackbar "PREFERABLY stays on screen until dismissed." If it may auto-dismiss it IS a toast by this page's own definition, and the category boundary dissolves. Drop "preferably" or state the exception. #atom/literature/h1
- These are not only accessibility concerns but also usability issues. ([View Highlight](https://read.readwise.io/read/01m11dzsm35h36pt9v519s51h4))
- Note: THIS IS BACKWARDS, AND THE PAGE'S MISSING WCAG MAPPING IS WHY IT MATTERS. "Not only accessibility but also usability" implies the accessibility case is the settled part. IT ISN'T. The usability case is airtight; the CONFORMANCE case has to be argued โ and this page, written to be cited in audits, supplies nothing citable for its central complaint. It cites WCAG only for 1.4.10 Reflow and 1.4.4 Resize Text, both attached to the zoom concern, never to "the message disappears." THE CRITERION A READER REACHES FOR FIRST WORKS AGAINST THEM: 4.1.3 STATUS MESSAGES (AA) requires that status messages be programmatically determinable via role or properties without receiving focus โ SO A TOAST WITH CORRECT role="status" PASSES 4.1.3 AND STILL VANISHES BEFORE IT CAN BE READ. Cite 4.1.3 and you hand the other side "we're conformant." THE REAL ARGUMENT IS 2.2.1 TIMING ADJUSTABLE (LEVEL A): auto-dismissal is a content-imposed time limit on reading, and unless the user can turn it off, adjust, or extend it, that's a Level A failure. Note this page's own hover/focus-delay concession โ "can help, but the user must know this is possible" โ IS a 2.2.1 sufficiency discussion, conducted without naming 2.2.1. (2.2.3 No Timing fits cleanly but is AAA. Expect the counter-argument that a toast's brevity is "Essential" under 2.2.1's exception โ that rebuttal needs writing down.) OPERATIONAL RULE FOR AUDITS: lead with 2.2.1; reserve 4.1.3 for toasts that aren't announced AT ALL; never conflate them. Citing the wrong criterion is how a correct finding gets closed as compliant. #atom/zettel/z2 #action/h2
- To print admin screen notices use: [do\_action( โadmin\_noticesโ )](https://developer.wordpress.org/reference/hooks/admin_notices/). ([View Highlight](https://read.readwise.io/read/01m11dzbsx9td0vq22pbt11y5e))
- Note: THE CODE SAMPLE BELOW IS BROKEN โ VERIFIED BY EXECUTION, DON'T COPY IT. Its docblock says "Output an admin notice with role="alert", so it will be announced by assistive technology." It doesn't. Ran it against the attribute loop in wp-includes/functions.php :: wp_get_admin_notice() from a local WP 7.0.2 checkout. array('role','alert') is NUMERICALLY INDEXED โ keys 0 and 1, values 'role' and 'alert' โ where core wants attr => value pairs. Both keys are integers, so both hit the is_int($attr) branch and emit as bare valueless attributes. ACTUAL OUTPUT: <div class="notice notice-error" role alert> โ an EMPTY role and a JUNK alert attribute. Not role="alert". FIX: array( 'role' => 'alert' ). WHY IT SURVIVES IS WORTH MORE THAN THE BUG. Core's is_int($attr) branch exists deliberately, to support valueless HTML attributes like `hidden` written as array('hidden') โ and that legitimate feature is exactly what swallows the most common malformed-array mistake. The SAME FUNCTION raises _doing_it_wrong() for a `type` containing spaces: IT VALIDATES THE ARGUMENT THAT FAILS LOUDLY AND ACCEPTS THE ONE THAT FAILS SILENTLY. No error, no warning, output that renders fine, announcement that never happens. DETECTABLE CLASS: grep for wp_admin_notice / wp_get_admin_notice calls whose attributes array has integer keys. Add to wp-a11y-reviewer. TRANSFERABLE: an API that accepts a malformed argument shape and returns plausible output is a defect factory โ the same bug shape in a capability or nonce argument is a SECURITY problem. Same habit either way: did this argument actually take effect? Run it. Prose review could not have caught this; one execution did. EVEN ONCE FIXED IT'S QUESTIONABLE: role="alert" is assertive/interrupting and contradicts this page's own prose four paragraphs earlier (aria-live="polite" or role="status"); and admin_notices output sits in the INITIAL DOM, where live regions announce CHANGES rather than existing content. The page's own better answer โ wp.a11y.speak() โ is a few paragraphs below and never connected to this example. FILE THE CORRECTION: verified, reproducible, one line, no judgment call. #atom/zettel/z1 #action/h1