-
Notifications
You must be signed in to change notification settings - Fork 547
Accessibility guidelines #14379
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Accessibility guidelines #14379
Changes from 31 commits
d9c4d9c
e2ae369
169e964
91c7bc1
85a9ecc
b7311d6
1092f24
0dccf8b
40e1fee
56b1564
49cf096
58dcfc8
1408867
d8ea896
a92580c
c875bf9
e3ff5e1
1284062
ce98e54
b7470d2
2557f3f
1ba0cc6
bbc7d00
d2bbefe
15cf5c6
e5575b6
f8f14e1
b4509f7
fd78601
2f0e6d8
c1e5644
db4dd9f
1f4f0c7
48e7be4
bc219ce
8cc8320
dda0333
1436134
d4386a2
d6ef1cb
839db52
936c88e
7dfdd6a
0c1bd47
e9c72e3
4ba402b
d8dfd43
f2af979
d7424ee
0a032bc
f5782f8
1a21e54
4f4413f
5ea2360
717683c
33fa975
739b9ad
eec901c
2b3f0d6
5c4e3fa
443178c
1e5af00
4c2a0ca
e076249
a6c69fb
43deb21
fd34a52
c7f14bb
cd3c455
3091946
87a50c1
7c9d99c
3c26189
b5f6da7
79aa03e
65df2a6
a5a0a8c
656440e
79a84f8
41e9d5d
f2fbe0c
7434196
a5f6869
76970c1
ff0ebd9
b14ae17
cd67094
a944e36
85adc2d
f078fc3
b6fcd62
0204bdc
eb4a7fa
50e8410
be903ad
f67aa57
3f7f8a6
af2e160
0c868f4
a5370e1
ca5792f
d8dcf3d
bdc20f4
18a9811
e9f6a18
4a1d0b3
6ef8be3
b579a73
ef5c796
f7113a9
b79d477
7d630bf
530dd02
5597d9e
9264f83
b7fe5b0
e77f785
26a243c
916ce50
e56b9ac
56d9959
72cc597
226cb2f
8c4bbb1
36d9783
ef9f856
780bc4a
5241054
1f5c03e
ef6b1af
63490ed
0bf0058
6611aab
436cade
e695270
b38ddc4
fe6359b
108bc6a
a366a60
bdec559
b89e48f
49dfb59
4274f1a
72508d3
b6bf189
0cb6fab
bb83f08
d314526
104b8c0
037aa42
ec03638
21b9e83
ea598a7
0b474ca
df468c0
2050041
f1d701e
25941a2
74629e7
b2374d2
0a9ee2f
2849042
80d2bca
7fd9ffd
1a6ac17
fa6048c
010a032
51c763c
86aa2e1
784011d
7553a6f
79d1337
ee8459c
3fee6ac
eb11083
c9a6e28
601f1bc
b1c5fa1
3d5494e
71812c1
bff4948
d4e6207
d0d0265
347d196
75929af
829771b
50e8d13
7d1fd46
d31466e
2590f9f
55a8db0
5742786
af6957e
2831c4b
41c149b
3d7cebe
4a4cb0c
83fa6b4
75438c6
1c3bbba
dbec32c
43c1811
0a3df0d
fec14a0
50a785a
44c90fa
752d30f
979bd7c
c9e34be
d514d23
456018c
c0bb40a
8b89c7c
122f677
5b36599
c62fc99
d8a22f2
8005451
574a47c
ab765e5
f50e4c5
7db53e2
ca404c7
d67a764
445e627
7a2c1de
3301f23
1fc753a
c480eb9
23fffca
0f7d18e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,337 @@ | ||||||
| --- | ||||||
| title: Accessibility Guidelines for HTML Widgets in Teams | ||||||
| author: Suzanne Tocco | ||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Validated by the build; must be a GitHub alias |
||||||
| description: TODO | ||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Guidance on the description field:
|
||||||
| ms.topic: article | ||||||
| ms.date: 05/27/2026 | ||||||
| --- | ||||||
|
|
||||||
|
|
||||||
| # Accessibility guidelines for HTML widgets in Microsoft Teams 365 | ||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just "Teams" or "Microsoft Teams" I think? The former's probably fine, given the overall context of these docs. |
||||||
|
|
||||||
| HTML widgets (MCP apps) allow partners to render custom HTML and JavaScript experiences inside a sandboxed `<iframe>` within Teams chat. Because these widgets appear inline with conversational content, they must meet a consistent accessibility bar so that all users, including those who use assistive technologies, can perceive, understand, and operate them. | ||||||
|
|
||||||
| This article describes the minimum accessibility requirements for HTML widgets and provides recommended best practices and testing guidance. | ||||||
|
|
||||||
| ## Scope | ||||||
|
|
||||||
| These guidelines apply to all partner-built HTML widgets (MCP apps) that are rendered inside an `<iframe>` in Teams chat. The requirements are in addition to general web accessibility standards such as [WCAG 2.2](https://www.w3.org/TR/WCAG22/) and the [WAI-ARIA Authoring Practices](https://www.w3.org/WAI/ARIA/apg/). | ||||||
|
|
||||||
| > [!TIP] | ||||||
| > If you are building your widget with React, we recommend using [Fluent UI React v9](https://storybooks.fluentui.dev/react/?path=/docs/concepts-introduction--docs) components and tokens. They implement accessible, Teams-compatible patterns out of the box and reduce the amount of custom accessibility work required. Fluent UI React v9 is not required — partners may use any framework or library as long as the accessibility requirements in this article are met. | ||||||
|
|
||||||
|
|
||||||
|
|
||||||
| ## Responsibility model | ||||||
|
|
||||||
| Teams and partners share responsibility for accessibility. The following table clarifies what each party owns. | ||||||
|
|
||||||
| | Requirement | Teams | Partner | | ||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I just learned relatively recently that there's an accessibility-friendly way to do these with SVG images. This is fine for now, most docs do exactly this, but your article being about accessibility inspired me, so when I get a moment this week I'll tee it up. Same for the do/don't icons in the tables below. |
||||||
| |-------------------------------------------|:-----:|:-------:| | ||||||
| | Widget container label (e.g. "Scout widget") | ✅ | | | ||||||
| | Tab stop for widget container | ✅ | | | ||||||
| | Tab order of message elements | ✅ | | | ||||||
| | Focus into and out of the widget container | ✅ | | | ||||||
| | Widget-level loading and error states | ✅ | | | ||||||
| | Keyboard navigation inside widget | | ✅ | | ||||||
| | ARIA labels for interactive elements | | ✅ | | ||||||
| | Screen reader support for widget content | | ✅ | | ||||||
| | Color contrast inside widget | | ✅ | | ||||||
| | High contrast support inside widget | | ✅ | | ||||||
| | Error handling for content inside widget | | ✅ | | ||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
| ### Keyboard accessibility | ||||||
|
|
||||||
| > [!NOTE] | ||||||
| > Teams manages focus into and out of the widget container. The requirements below apply to keyboard navigation within the widget content only. | ||||||
|
|
||||||
| **Keyboard operability**: All interactive elements must be reachable and operable using standard keyboard input such as Tab, Shift+Tab, arrow keys, Enter, and Space, as appropriate for the control type. | ||||||
|
|
||||||
| **No focus traps**: Widgets must not trap focus. Users must be able to navigate through all interactive elements in a logical order and exit the widget without getting stuck. | ||||||
|
|
||||||
| **Visible focus**: All interactive elements must have a clear, visible focus indicator that meets contrast requirements and is not removed via CSS without an accessible replacement. | ||||||
|
|
||||||
| **Custom controls**: Custom widgets and controls must follow the keyboard interaction patterns defined in the [ARIA Authoring Practices](https://www.w3.org/WAI/ARIA/apg/) for their respective roles (for example,`button`, `menu`, `dialog`, `listbox`). | ||||||
|
|
||||||
| **Dialogs and modals**: Modal dialogs and overlays are possible within a widget but are not recommended. Because widgets render inside a small iframe, a modal will be constrained to that space and may feel disorienting to users. If your use case requires a modal, consider whether the expanded surface would be a better fit for that interaction. | ||||||
| If you do implement a modal inside your widget, if you are using Fluent UI React v9 use the [Dialog](https://storybooks.fluentui.dev/react/?path=/docs/components-dialog--docs) or [Popover](https://storybooks.fluentui.dev/react/?path=/docs/components-popover--docs) components rather than a custom implementation, as they handle focus trapping, focus restoration, and ARIA attributes correctly out of the box. For custom modal behavior, [useModalAttributes](https://storybooks.fluentui.dev/react/?path=/docs/utilities-focus-management-usemodalattributes--docs) is available. | ||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
| **Focus restoration**: When an element is removed from the DOM after a user action (for example, after submitting a form or closing a panel), focus must be restored to a logical element rather than dropping to the document body. Use Fluent V9's [useRestoreFocusSource and useRestoreFocusTarget](https://storybooks.fluentui.dev/react/?path=/docs/utilities-focus-management-userestorefocussource--docs) hooks to handle this automatically. | ||||||
|
|
||||||
|
|
||||||
|
|
||||||
| <table> | ||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Replace HTML with markdown table syntax |
||||||
| <tr> | ||||||
| <th align="left">✅ Do</th> | ||||||
| <th align="left">❌ Don't</th> | ||||||
| </tr> | ||||||
| <tr> | ||||||
| <td> | ||||||
|
|
||||||
| - Use Fluent UI React v9 Dialog or Popover for modal experiences | ||||||
| - Restore focus to the triggering element after a dialog or panel closes | ||||||
|
|
||||||
| </td> | ||||||
| <td> | ||||||
|
|
||||||
| - Don't remove focus outlines without providing an accessible alternative | ||||||
| - Don't auto-advance focus between controls without a clear user action | ||||||
|
|
||||||
| </td> | ||||||
| </tr> | ||||||
| </table> | ||||||
|
|
||||||
| ## Screen reader semantics | ||||||
|
|
||||||
| Widgets must expose meaningful structure and semantics so that screen readers and other assistive technologies can correctly interpret and announce content. | ||||||
|
|
||||||
| **Semantic HTML** | ||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using bold text as mini-headings is considered an anti-pattern; see if H3s look OK. Same in a few other spots further down. The bullet lists where each bullet starts with bold text are good to go, though. |
||||||
|
|
||||||
| Use native HTML elements whenever possible, such as `<button>`, `<input>`, `<label>`, `<ul>`, `<li>`, `<nav>`, and `<form>`. | ||||||
|
|
||||||
| **Role, name, state** | ||||||
|
|
||||||
| All interactive elements must have: | ||||||
|
|
||||||
| - A meaningful role (native or ARIA) | ||||||
| - An accessible name (visible text, `aria-label`, or `aria-labelledby`) | ||||||
| - Accurate state and property information (for example, `aria-expanded`, `aria-checked`, `aria-selected`, `aria-disabled`) | ||||||
|
|
||||||
| **Dynamic updates** | ||||||
|
|
||||||
| Use live regions to announce important changes to screen readers: | ||||||
|
|
||||||
| - `aria-live="polite"` for non-critical updates such as loading results | ||||||
| - `aria-live="assertive"` for critical updates such as errors | ||||||
|
|
||||||
| If you are using Fluent V9 and React, use [AriaLiveAnnouncer](https://storybooks.fluentui.dev/react/?path=/docs/utilities-aria-live-arialiveannouncer--docs) with the [useAnnounce](https://storybooks.fluentui.dev/react/?path=/docs/utilities-aria-live-useannounce--docs) hook rather than implementing raw aria-live regions. If your widget includes text inputs and needs to announce updates while the user is typing, use [useTypingAnnounce](https://storybooks.fluentui.dev/react/?path=/docs/utilities-aria-live-usetypingannounce--docs) instead. | ||||||
|
|
||||||
| **Images** | ||||||
|
|
||||||
| Images that convey meaning must include descriptive `alt` text. Decorative images should be marked with empty `alt=""` or hidden from assistive technologies. | ||||||
|
|
||||||
|
|
||||||
| <table> | ||||||
| <tr> | ||||||
| <th align="left">✅ Do</th> | ||||||
| <th align="left">❌ Don't</th> | ||||||
| </tr> | ||||||
| <tr> | ||||||
| <td> | ||||||
|
|
||||||
| - Use headings (`<h1>`–`<h3>`) to structure content and help screen reader users navigate | ||||||
| - Treat the widget as a self-contained web application — don't rely on Teams to provide roles or labels for content inside the iframe | ||||||
|
|
||||||
| </td> | ||||||
| <td> | ||||||
|
|
||||||
| - Don't use generic `<div>` or `<span>` elements as controls without roles and labels | ||||||
| - Don't override correct native semantics with ARIA when native elements already provide the needed behavior | ||||||
|
|
||||||
| </td> | ||||||
| </tr> | ||||||
| </table> | ||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
| ## Focus management | ||||||
|
|
||||||
| Because widgets are embedded in a conversational experience, focus behavior within the widget must be predictable and must not disrupt the user's workflow in chat. | ||||||
|
|
||||||
| **No focus stealing** | ||||||
|
|
||||||
| Widgets must not automatically move focus within the iframe when they load. Focus should remain where Teams has placed it until the user explicitly interacts with the widget. | ||||||
|
|
||||||
| **Initial focus** | ||||||
|
|
||||||
| When the user moves focus into the widget, focus should land on the first meaningful interactive element, not on a hidden or non-interactive element. | ||||||
|
|
||||||
| **Dialogs and overlays** | ||||||
|
|
||||||
| If the widget opens a modal dialog: | ||||||
|
|
||||||
| - Move focus into the dialog when it opens | ||||||
| - Trap focus within the dialog while it's open | ||||||
| - Return focus to the triggering element when the dialog closes | ||||||
|
|
||||||
|
|
||||||
|
|
||||||
| ## Color, contrast, and high contrast mode | ||||||
|
|
||||||
| Widgets must remain perceivable in different contrast settings, including Windows High Contrast Mode. | ||||||
|
|
||||||
| **Text contrast** | ||||||
|
|
||||||
| Text and essential icons must meet [WCAG 2.2 AA contrast ratios](https://www.w3.org/WAI/WCAG22/Understanding/contrast-minimum.html): | ||||||
|
|
||||||
| - At least 4.5:1 for normal text | ||||||
| - At least 3:1 for large text (18pt or 14pt bold and above) | ||||||
|
|
||||||
| **High contrast mode** | ||||||
|
|
||||||
| Ensure that interactive elements, focus indicators, and key icons remain visible and understandable when the user enables Windows High Contrast Mode. | ||||||
|
|
||||||
| **Color independence** | ||||||
|
|
||||||
| Don't rely on color alone to convey meaning. Use text, icons, patterns, or other indicators in addition to color. | ||||||
|
|
||||||
| <table> | ||||||
| <tr> | ||||||
| <th align="left">✅ Do</th> | ||||||
| <th align="left">❌ Don't</th> | ||||||
| </tr> | ||||||
| <tr> | ||||||
| <td> | ||||||
|
|
||||||
| - Test in Windows High Contrast Mode before submission | ||||||
| - Pair color with a label or icon to communicate state | ||||||
| - Use [Fluent UI React v9 color tokens](https://storybooks.fluentui.dev/react/?path=/docs/theme-colors--docs) for backgrounds, borders, and text | ||||||
|
|
||||||
| </td> | ||||||
| <td> | ||||||
|
|
||||||
| - Don't use low-contrast text or icons for critical information | ||||||
| - Don't use placeholder text as the only label for an input | ||||||
| - Don't hardcode color values — use [Fluent UI React v9 color tokens](https://storybooks.fluentui.dev/react/?path=/docs/theme-colors--docs) or CSS variables so your widget adapts to Teams themes | ||||||
|
|
||||||
| </td> | ||||||
| </tr> | ||||||
| </table> | ||||||
|
|
||||||
|
|
||||||
| ## Responsive layout and zoom | ||||||
|
|
||||||
| Widgets must adapt to the chat container and remain usable at different zoom levels and viewport sizes. | ||||||
|
|
||||||
| - **Zoom support:** Support at least 200% browser zoom without loss of content or functionality | ||||||
| - **Flexible layout:** Avoid fixed pixel heights — allow the widget to grow vertically as needed so content isn't clipped | ||||||
| - **No horizontal scrolling:** Layout should adapt to the narrow widths typical of chat containers | ||||||
|
|
||||||
|
|
||||||
|
|
||||||
| ## Motion, animation, and timing | ||||||
|
|
||||||
| Motion and animation must not cause discomfort or interfere with usability. | ||||||
|
|
||||||
| - **Reduced motion:** Respect the user's `prefers-reduced-motion` setting by reducing or disabling non-essential animations | ||||||
| - **Safe motion:** Avoid flashing content or rapid animations that could trigger photosensitive reactions | ||||||
| - **Auto-advancing content:** Don't auto-advance carousels or content without user input. If auto-advance is necessary, provide controls to pause, stop, and manually navigate | ||||||
|
|
||||||
|
|
||||||
|
|
||||||
| ## Error handling inside the widget | ||||||
|
|
||||||
| > [!NOTE] | ||||||
| > Teams handles widget-level loading and error states. Partners are responsible for accessible error handling within their own widget content. | ||||||
|
SuzanneTocco marked this conversation as resolved.
Outdated
|
||||||
|
|
||||||
|
|
||||||
| **Announcements** | ||||||
|
|
||||||
| Use `aria-live="assertive"` or an appropriate live region to announce critical errors to screen readers. If using Fluent UI React v9, use [useAnnounce](https://storybooks.fluentui.dev/react/?path=/docs/utilities-aria-live-useannounce--docs) with `polite: false` for error announcements. | ||||||
|
|
||||||
|
|
||||||
| **Clear messaging** | ||||||
|
|
||||||
| Error messages must: | ||||||
|
|
||||||
| - Describe what went wrong in clear, concise language | ||||||
| - Explain how the user can fix the issue or try again | ||||||
|
|
||||||
|
|
||||||
| **Input errors** | ||||||
|
|
||||||
| For invalid fields: | ||||||
|
|
||||||
| - Set `aria-invalid="true"` on the input | ||||||
| - Associate the error message with the input using `aria-describedby` or a similar mechanism | ||||||
|
|
||||||
|
|
||||||
| ## Loading states inside the widget | ||||||
|
|
||||||
| > [!NOTE] | ||||||
| > Teams handles the widget-level loading state. The requirements below apply to any loading states that occur within your widget content after initial render. | ||||||
|
|
||||||
| - **Visible indicator:** Show a clear loading indicator when your widget fetches or processes data after initial render | ||||||
| - **Announcements:** Use `aria-live="polite"` to announce loading and completion states to screen readers. If using Fluent UI React v9, use [useAnnounce](https://storybooks.fluentui.dev/react/?path=/docs/utilities-aria-live-useannounce--docs) with `polite: true` | ||||||
| - **Focus behavior:** Don't trap focus during loading — users must still be able to move focus within the widget | ||||||
| - **Skeleton UI:** If you use skeleton screens, either hide them from assistive technologies using `aria-hidden="true"`, or provide meaningful labels that describe the loading state | ||||||
|
|
||||||
|
|
||||||
|
|
||||||
| ## Minimum accessibility bar for submission | ||||||
|
SuzanneTocco marked this conversation as resolved.
Outdated
|
||||||
|
|
||||||
| Widgets must meet all of the following requirements to be accepted. Widgets that don't meet this bar may be rejected or require remediation before publishing. | ||||||
|
SuzanneTocco marked this conversation as resolved.
Outdated
|
||||||
|
|
||||||
| | Requirements | | ||||||
| |:---| | ||||||
| | ✅ Fully operable with a keyboard, with no focus traps inside the widget | | ||||||
| | ✅ Usable with screen readers, with meaningful roles, names, and states on all interactive elements | | ||||||
| | ✅ Meets WCAG 2.2 AA contrast ratios for text and essential UI elements | | ||||||
| | ✅ Remains usable in Windows High Contrast Mode | | ||||||
| | ✅ Provides accessible error handling and loading states for content inside the widget | | ||||||
| | ✅ Supports at least 200% zoom without loss of content or functionality | | ||||||
| | ✅ Respects `prefers-reduced-motion` and avoids harmful flashing | | ||||||
| | ✅ Adapts to the chat container without requiring horizontal scrolling | | ||||||
|
|
||||||
| > [!WARNING] | ||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd drop this, I think the text above is sufficient. When I worked with the Learn content folks it was "common knowledge" (apparently based on studies that none of us ever actually saw) that these alerts are often counterproductive, users tend to skip past them. Also - rejected or accepted by what process? |
||||||
| > Widgets that don't meet these requirements may be rejected or require remediation before they can be published. | ||||||
|
|
||||||
|
|
||||||
| ## Recommended best practices | ||||||
|
SuzanneTocco marked this conversation as resolved.
Outdated
|
||||||
|
|
||||||
| The following practices aren't required but are strongly recommended to improve the overall experience. | ||||||
|
|
||||||
| - **Skip links:** Provide a "Skip to main content" link at the top of the widget to let keyboard and screen reader users bypass repeated navigation | ||||||
| - **Headings:** Use headings (`<h1>`–`<h3>`) to structure content and make navigation easier for screen reader users | ||||||
| - **Simple interaction models:** Prefer simple, predictable interaction patterns over highly custom or novel controls | ||||||
| - **Scrolling:** Avoid complex nested scroll regions. If a scrollable region is necessary, ensure it has a clear label and is keyboard accessible | ||||||
| - **Tooltips:** Implement accessible tooltips using `aria-describedby` and ensure they're available on focus as well as hover | ||||||
| - **Tooltips:** Use [Fluent UI React v9 ](https://storybooks.fluentui.dev/react/?path=/docs/concepts-introduction--docs) components wherever possible — they implement accessible patterns out of the box and reduce the amount of custom accessibility work required | ||||||
|
|
||||||
|
|
||||||
| ## Testing guidance | ||||||
|
|
||||||
| Partners should validate accessibility using a combination of automated and manual testing before submission. Because widgets run inside a sandboxed iframe, some automated tools may not scan iframe content by default — open your widget content directly in a browser tab to get accurate results from automated tools. | ||||||
|
|
||||||
|
|
||||||
| ### Automated testing tools | ||||||
|
SuzanneTocco marked this conversation as resolved.
Outdated
|
||||||
|
|
||||||
| | Tool | Type | Notes | | ||||||
| |---|---|---| | ||||||
| | [Lighthouse](https://developer.chrome.com/docs/lighthouse) | Browser (Chrome DevTools) | Built into Chrome — good starting point for catching common issues. No install required. | | ||||||
| | [axe DevTools](https://www.deque.com/axe/devtools/) | Browser extension | More detailed accessibility analysis than Lighthouse. Free version available. | | ||||||
| | [WAVE](https://wave.webaim.org/extension/) | Browser extension | Visual overlay that highlights issues directly on the page. Good for quick visual checks. | | ||||||
| | [Colour Contrast Analyser](https://www.tpgi.com/color-contrast-checker/) | Desktop tool | Checks contrast ratios for text and UI elements against WCAG standards. | | ||||||
| | [WebAIM Contrast Checker](https://webaim.org/resources/contrastchecker/) | Web-based | Quick browser-based contrast ratio checker. No install required. | | ||||||
|
|
||||||
|
|
||||||
| ### Manual testing tools | ||||||
|
|
||||||
| | Test type | What to verify | | ||||||
| |---|---| | ||||||
| | Keyboard-only | Navigate the entire widget using only the keyboard. Verify no focus traps and a logical tab order throughout. | | ||||||
| | Screen reader | Test with at least one screen reader — Narrator or NVDA on Windows, VoiceOver on Mac. Verify all elements are announced meaningfully. | | ||||||
| | High contrast | Enable Windows High Contrast Mode and verify that content, controls, and focus indicators remain visible. | | ||||||
| | Zoom | Increase browser zoom to 200% and confirm content and functionality are fully preserved. | | ||||||
| | Reduced motion | Enable reduced motion in OS settings and verify animations are minimized or disabled. | | ||||||
| | Responsive | Test in narrow viewports representative of Teams chat container widths. | | ||||||
|
|
||||||
|
|
||||||
| ## Related content | ||||||
|
|
||||||
| - [HTML widgets overview for Microsoft Teams](#) | ||||||
| - [UX guidelines for HTML widgets in Microsoft Teams](#) | ||||||
| - [Teams store validation guidelines](#) | ||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. TODO on these links |
||||||
| - [Fluent UI React v9](https://storybooks.fluentui.dev/react/?path=/docs/concepts-introduction--docs) | ||||||
| - [Fluent UI React v9 components](https://react.fluentui.dev/) | ||||||
| - [WCAG 2.2 contrast requirements](https://www.w3.org/WAI/WCAG22/Understanding/contrast-minimum.html) | ||||||
| - [WAI-ARIA Authoring Practices](https://www.w3.org/WAI/ARIA/apg/) | ||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| --- | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let me know if you actually want to ship without this and the UX guidelines doc and we can get rid of them in this pull request and rejigger the table of contents configuration as needed. |
||
| title: TODO | ||
| author: SuzanneTocco | ||
| description: TODO | ||
| ms.topic: article | ||
| ms.date: 05/27/2026 | ||
| --- | ||
|
|
||
| TODO | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was a mistake in the starter content I gave you.