Skip to content

feat: Bubble ARIA methods#9783

Merged
mikeharv merged 6 commits into
RaspberryPiFoundation:v13from
mikeharv:bubble-aria-apis
Apr 30, 2026
Merged

feat: Bubble ARIA methods#9783
mikeharv merged 6 commits into
RaspberryPiFoundation:v13from
mikeharv:bubble-aria-apis

Conversation

@mikeharv
Copy link
Copy Markdown
Contributor

This updates Bubble with new API changes:

  • type AriaLabelProvider
  • recomputeAriaContext()
  • setAriaLabelProvider()
  • getAriaLabel()

These new methods ensure that Bubbles have a valid ARIA label and the default role group. To use, Bubble owners (such as Icons) are responsible computing the context at the correct times and providing an AriaLabelProvider to override the default "Bubble" label.

The basics

The details

Resolves

Fixes #9661

Proposed Changes

Bubble will be updated with new API changes:

/**
 * Represents a function that, when called, can provide a custom ARIA string to
 * represent a bubble, or null if the default fallback should be used. See
 * setAriaLabelProvider for more context.
 */
export type AriaLabelProvider = (bubble: Bubble) => string | null;

/**
 * Recomputes the ARIA label and role for this bubble. This is automatically called
 * during initialization, but implementations may find it useful to call this if
 * the bubble's label should be changed.
 *
 * Bubbles use a default non-specific label unless they're customized otherwise
 * which is the responsibility of the bubble's owner rather than bubble
 * implementations. Customization can be done via setAriaLabelProvider.
 */
protected recomputeAriaContext()

/**
 * Sets a custom ARIA label provider for this bubble, or null if it should be reset
 * to use the default method.
 *
 * Bubbles do not compute ARIA labels specifically to their implementation since
 * they can be rather general-purpose. Instead, owners of the specific bubble
 * instance (such as an icon) are responsible for defining custom label providers
 * for their bubbles.
 *
 * Note that calling this isn't sufficient for it to actually be used.
 * recomputeAriaContext will likely also need to be called to actually apply the
 * custom label to the bubble's focusable element.
 */
setAriaLabelProvider(provider: AriaLabelProvider | null)

/**
 * Returns the ARIA label to use for this bubble based on the provider set via
 * setAriaLabelProvider. This will return null if the provider is absent or
 * returns null.
 *
 * @returns The ARIA label to use for this bubble, or null to use a default.
 */
getAriaLabel(): string | null

The documentation strings explain the contracts of these methods, but it's expected that implementations will never need to override any of these values. Bubble owners (such as Icons) are responsible for actually setting up the Bubble instance's ARIA context to be correct (e.g. by calling recomputeAriaContext as the correct time). All bubbles are treated as role group unless recomputeAriaContext is overridden. The focusable element's label is set to the value returned by getAriaLabel (or a default 'Bubble' if no AriaLabelProvider is configured or it returns null, to ensure that at least some human-readable label is used).

Reason for Changes

This provides the groundwork that is necessary to give built-in bubble owners (such as mutators, warnings, and comments) reasonable ARIA labels. This will also make it possible for developers to do the same for their own Bubble implementations.

Test Coverage

To start, this just tests that the three main types of bubbles we support have the correct role and a label. It also tests, via comments, that a label provider works as expected. A follow-up task will define those providers and test that they are working as expected.

Documentation

Additional Information

@mikeharv mikeharv requested a review from a team as a code owner April 30, 2026 17:11
@mikeharv mikeharv requested a review from gonfunko April 30, 2026 17:11
@github-actions github-actions Bot added the PR: feature Adds a feature label Apr 30, 2026
Comment thread packages/blockly/core/bubbles/bubble.ts Outdated
* represent a bubble, or null if the default fallback should be used. See
* setAriaLabelProvider for more context.
*/
export type AriaLabelProvider = (bubble: Bubble) => string | null;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would probably update this to allow either a string or a function that returns a string. Then it will match patterns used elsewhere (in block for the role description, and in input for the aria label). Those two places didn't exist when the design was originally written for this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like a good idea. Added.


const label = this.getAriaLabel()?.trim();

aria.setState(element, aria.State.LABEL, label ? label : 'Bubble');
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Bubble string would need to be localized. I do wonder if there's a better default we could use, because "bubble" is so meaningless to end users. But I can't think of another one that's better. At least the built-in use cases of bubble will be able to have better defaults so this would only occur if someone is implementing a custom icon that launches a custom bubble and doesn't bother to set a correct label.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, thanks! I agree that it's meaningless, but weighed the trade offs in the same way as you.

Comment thread packages/blockly/tests/mocha/mutator_test.js Outdated
Comment thread packages/blockly/tests/mocha/mutator_test.js
@mikeharv mikeharv merged commit 9a01417 into RaspberryPiFoundation:v13 Apr 30, 2026
4 checks passed
lizschwab pushed a commit to lizschwab/blockly that referenced this pull request Apr 30, 2026
* feat: Bubble ARIA methods

* fix: lint

* fix: code review

* fix: whitespace

* fix: use standard block

* fix: remove unneeded teardown steps
@mikeharv mikeharv mentioned this pull request May 1, 2026
1 task
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

PR: feature Adds a feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants