Skip to content

Accessibility in Power Apps Component Framework (PCF) controls

The Power Apps Component Framework (PCF) lets you build custom code components that render inside model-driven apps, canvas apps, and Power Pages. Unlike canvas apps' Studio-native controls, a PCF component is raw HTML/CSS/JS (or React) that you own end-to-end—there's no Accessibility Checker for custom components, and Microsoft doesn't publish a dedicated PCF accessibility article.

Key takeaway: A standard PCF control gives you almost nothing for accessibility automatically—no accessibility-focused API on the Context object, no automatic ARIA injection, and no reduced-motion signal. Building a React control with the Fluent platform library (see below) is the one documented exception, since it inherits the host app's theme—including high-contrast—automatically. Either way, you're responsible for keyboard navigation, ARIA roles and labels, and screen-reader testing for every component you ship.

For Solution Architects: There's no platform conformance statement for PCF at all (see comparison across surfaces)—every control is a bespoke accessibility deliverable. If you can choose, scope custom controls as React controls using the Fluent platform library rather than standard controls: you inherit Fluent's accessible-by-default components and automatic host theming, which meaningfully lowers effort from High to Medium. A standard control gets none of that for free.

In this article:What Microsoft documents · React and Fluent UI · Framework vs. author responsibility · Undocumented APIs · Checklist

What Microsoft documents

The only official PCF accessibility guidance is a short "Check accessibility" section inside the code components best-practices article. It states that component authors should:

  • Provide keyboard-based alternatives to mouse/touch interactions (for example, tab to focus a dropdown, use arrow keys to navigate its options).
  • Set alt text and ARIA attributes so screen readers announce an accurate representation of the component's interface.
  • Use browser developer tools to inspect the rendered component for accessibility issues.

Microsoft specifically recommends building on Fluent UI React components where possible, since they're largely accessible and screen-reader-compatible out of the box—reducing how much of this you have to implement from scratch.

Building with React and Fluent UI

PCF officially supports a React-based control type, distinct from the default "standard" control:

  • Scaffold one with pac pcf init --framework react (or -fw react). This sets control-type="virtual" in ControlManifest.Input.xml instead of standard, and ReactControl.updateView returns a ReactElement rather than rendering directly into a div.

  • The manifest declares platform libraries it needs, for example:

    xml
    <platform-library name="React" version="16.14.0" />
    <platform-library name="Fluent" version="9.46.2" />

    Both Fluent 8 (@fluentui/react) and Fluent 9 (@fluentui/react-components) are supported as platform libraries—but not both in the same manifest.

  • Because these libraries are the platform's own shared instance (not a copy your component bundles), your control's bundle size shrinks, and—significantly for accessibility—its theming stays aligned with the host app's Fluent design system automatically, rather than needing to be re-implemented per component.

  • Limitation: React controls & platform libraries are supported for canvas apps and model-driven apps, but not for Power Pages. A PCF control embedded in Power Pages must still be a standard (non-virtual) control.

Fluent UI itself has a detailed accessibility architecture worth knowing before you build on it—component labelling anti-patterns, focus-indicator APIs, live-region/notification best practices, and truncation guidance. See Accessibility in Fluent UI React (v9) for the full breakdown.

What the framework provides vs. what you must implement

Framework providesComponent author must implement
A container DOM element scoped to your componentAll ARIA roles, states, and labels
Lifecycle hooks (init, updateView, destroy)Keyboard navigation and focus management
context.mode (visible/disabled state flags)Reflecting disabled/visible state through ARIA (e.g. aria-disabled)
context.userSettings.isRTL (bidirectional layout flag)Reduced-motion handling—no platform signal exists for it
Automatic host theme (including high-contrast) consistency, but only if you use the React framework's Fluent platform library, not a bundled copyScreen-reader testing and verifying announcements

Important: No context.accessibility property exists. The documented Context object exposes client, copilot, device, events, factory, formatting, mode, navigation, parameters, resources, updatedProperties, userSettings, utils, and webAPI—none of which are accessibility-specific.

A note on undocumented APIs

An unofficial context.fluentDesignLanguage property is referenced in community blog posts (not on Microsoft Learn) as a way to read theme tokens when a model-driven app's modern Fluent v9 theming is enabled. It isn't part of the documented Context reference. Don't rely on it, or represent it, as an official accessibility or theming API.

The officially documented equivalent is the Fluent platform library described above: declare <platform-library name="Fluent" version="..." /> in your React control's manifest, build your UI from @fluentui/react (v8) or @fluentui/react-components (v9) components, and the host app's theme—including high-contrast mode—carries through automatically because you're using the same shared library instance as the host, not a bundled copy. A standard (non-React) control, or a React control that bundles its own copy of Fluent instead of declaring it as a platform library, gets none of this for free—build and test its high-contrast/theme handling explicitly instead.

Quick tips / suggested review checklist

  • [ ] Use Fluent UI React controls where possible, per Microsoft's own recommendation.
  • [ ] Every custom-rendered interactive element has an explicit ARIA role, state, and label—the framework injects none of this automatically.
  • [ ] Full keyboard navigation and visible focus management are implemented and manually tested.
  • [ ] The component has been inspected with a browser's built-in accessibility dev tools.
  • [ ] If building a React control, Fluent is declared as a platform library in the manifest (not bundled) so host theming—including high-contrast—carries through automatically; if building a standard control, high-contrast and reduced-motion behavior have been tested directly instead.
  • [ ] If the control targets Power Pages, it's built as a standard control—React controls & platform libraries aren't supported there.
  • [ ] The component has been tested inside every host it targets (model-driven app, canvas app, Power Pages), since none of them run an automatic accessibility check on custom components.
  • [ ] No accessibility or theming claim depends on an undocumented API such as context.fluentDesignLanguage.