Commit 1431fe4
feat(adaptive-cards): add richCardTitleAsHeading styleOption to opt out of role=heading on rich card titles (#5839)
* feat(adaptive-cards): add richCardTitleAsHeading styleOption to opt out of role=heading on rich card titles
Today the title of hero/thumbnail/audio/video/animation/receipt cards is
rendered with Adaptive Cards style: 'heading', which the Adaptive Cards SDK
exposes as role='heading' + aria-level. This was originally requested in
issue #4327 and shipped in 4.15.3.
Subsequent a11y audits (e.g. for hosts where these cards appear inside a
chat transcript) flag the same heading as 'Unnecessary heading level is
programmatically defined for Title' under MAS 1.3.1 / WCAG 1.3.1, because
card titles inside a chat are not page-level headings and break document
outline tools.
Reconcile the two by making the behavior configurable via
styleOptions.richCardTitleAsHeading. Default is true so existing
consumers (including the original #4327 reporter) keep today's behavior;
consumers can pass false to drop the heading style.
Adds a sibling test heroCard.noHeading.html to the existing
heroCard.heading.html that asserts no .ac-textBlock[role='heading'] is
rendered when richCardTitleAsHeading is false.
* address review comments from automated reviewer
1. heroCard.noHeading.html: scope queries to the hero card activity
container instead of querying the whole document. Match the title
text block by its expected text so future text blocks elsewhere on
the page do not make the test flaky.
2. AdaptiveCardsStyleOptions.ts: drop the incomplete 'reverse request'
bullet that had no link; keep the @see link to #4327 only.
3. AdaptiveCardBuilder.ts: add https:// prefix to the #4327 URL so
tooling auto-links it.
* code-review: drop 'as const', narrow doc comment to actual code paths
1. AdaptiveCardBuilder.ts: drop 'as const' on the conditional 'style: heading'.
AGENTS.md says 'Avoid as'; the original code wrote 'style: heading'
without any cast because addTextBlock takes Partial<TextBlock>, and
TextBlock.style accepts string. Same here.
2. AdaptiveCardsStyleOptions.ts: tighten the doc-comment to match the
actual call graph instead of listing card types.
Cards that flow through addCommonHeaders today:
- hero (via addCommon)
- OAuth (direct)
- thumbnail no-image branch (via addCommon)
- animation/audio/video (via CommonCard -> addCommon)
Cards that DON'T (their titles use direct addTextBlock w/o style:heading):
- receipt
- thumbnail with images
- signin
* trim verbose comments and changelog entry to match repo style
* address review: snapshot both heroCard heading tests + fix changelog format
- heroCard.noHeading.html: add host.snapshot('local') and wait for allImagesLoaded so the captured snapshot is stable.
- heroCard.heading.html: bring the default-styling test to parity with the noHeading test - scope queries to the hero card activity, assert role='heading' on the title text block, and add host.snapshot('local') so both behaviors can be visually compared (per OEvgeny).
- CHANGELOG.md: rewrite the entry in the repo's standard '<verb> <desc>, in PR [#NNNN](url), by [@author](url)' single-line form (per compulim).
* test: commit image snapshot baselines for heroCard heading/noHeading
Generated by running the docker compose / selenium / jest stack from a clean WSL Ubuntu build:
npm install && npm run build
docker compose -f docker-compose-wsl2.yml up --detach --scale chrome=2
./node_modules/.bin/jest --ci=false --forceExit --runInBand --testPathPattern=heroCard -u
Both snapshots are visually identical (as expected - the only difference is the role='heading' attribute on the title text block, which has no visual styling). The behavioural difference is asserted via the role assertions in each test's JS.
* test: visually highlight [role=heading] in heroCard snapshots
Per OEvgeny: add custom CSS so the role='heading' attribute is visually visible in image snapshots. Adds a small heading-indicator.css (yellow background + dashed red outline on any [role='heading'] element, following the focus-indicator.css pattern), linked from both heroCard.heading.html and heroCard.noHeading.html.
Result: heroCard.heading.html.snap-1.png now shows the highlighted title; heroCard.noHeading.html.snap-1.png stays unhighlighted, so reviewers can visually confirm the role=heading semantics from the snapshots alone.
* Reverse styleOptions so default is falsy
---------
Co-authored-by: Christopher Jennison <cjennison@microsoft.com>
Co-authored-by: Eugene <EOlonov@gmail.com>
Co-authored-by: William Wong <compulim@users.noreply.github.com>1 parent 1ffc7bc commit 1431fe4
9 files changed
Lines changed: 79 additions & 5 deletions
File tree
- __tests__/html2/accessibility/attachment
- packages/bundle/src/adaptiveCards
- Attachment
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
19 | 19 | | |
20 | 20 | | |
21 | 21 | | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
22 | 27 | | |
23 | 28 | | |
24 | 29 | | |
| |||
Lines changed: 4 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
Lines changed: 13 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
| 5 | + | |
5 | 6 | | |
6 | 7 | | |
7 | 8 | | |
| |||
21 | 22 | | |
22 | 23 | | |
23 | 24 | | |
| 25 | + | |
24 | 26 | | |
25 | 27 | | |
26 | | - | |
27 | | - | |
28 | | - | |
| 28 | + | |
| 29 | + | |
29 | 30 | | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
30 | 40 | | |
31 | 41 | | |
32 | 42 | | |
| |||
Lines changed: 46 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
Lines changed: 8 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
25 | 25 | | |
26 | 26 | | |
27 | 27 | | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
28 | 36 | | |
29 | 37 | | |
30 | 38 | | |
| |||
Lines changed: 2 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
119 | 119 | | |
120 | 120 | | |
121 | 121 | | |
122 | | - | |
| 122 | + | |
123 | 123 | | |
| 124 | + | |
124 | 125 | | |
125 | 126 | | |
126 | | - | |
127 | 127 | | |
128 | 128 | | |
129 | 129 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
| 8 | + | |
8 | 9 | | |
9 | 10 | | |
10 | 11 | | |
| |||
0 commit comments