Skip to content

custom aria labels for inputs #9752

@maribethb

Description

@maribethb

Check for duplicates

  • I have searched for similar issues before opening a new one.

Problem

typically when we need to label inputs, we derive a label from the surrounding fields. however, sometimes developers want to set a custom label for an input that doesn't come from the field row.

Request

Changes to Input API:

/**
 * Represents a string or a function that returns a string which can be used as a custom ARIA string to
 * represent an Input, or null if the default fallback should be used. See
 * setAriaLabelProvider for more context.
 */
export type AriaLabelProvider = ((input: Input) => string | null) | string;

/**
 * Sets a custom ARIA label provider for this input, or null if it should be reset
 * to use the default method.
 *
 * Inputs do not compute ARIA contexts directly, so the set provider will be used
 * in select cases when the Input needs to be represented (such as for parts of a
 * block label or for connections). Note that overriding this provider will not
 * recompute any already constructed ARIA labels, and it cannot be assumed that the
 * provider will be called any particular number of times during label
 * recomputation. As such, implementations should make sure to provide a
 * deterministic and idempotent ARIA representation each time the provider is
 * called for a given input. It's also fine to reuse providers across multiple
 * Input implementations.
 */
setAriaLabelProvider(provider: AriaLabelProvider | null)

/**
 * Returns the string from the custom ARIA label provider set, or null if the default label (from the field row) should
 * be used. See setAriaLabelProvider for more context.
 */
getAriaLabelText(): string | null

The implementation for getAriaLabelText should:

  1. check if the AriaLabelProvider exists. if not, return null
  2. if it is a string, call parsing.replaceMessageReferences on it so that developers can supply translatable strings in the json block definitions
  3. if is a function, call the function and return the resulting string

Block changes

private inputFromJson() method (in block.ts) changed to check the element (json representation of field) for a ariaLabelText property, and, if present, calls setAriaLabelProvider on the created input. The element parameter to this method is currently untyped so no changes are needed there.

The (currently optional) types for json block definitions are in i_json_block_definition and should be updated to include this optional property.

Here is an example block definition for a block with one value input with a custom label, defined in both JavaScript and JSON.

const my_block = {
  init: function() {
    this.appendValueInput('NAME')
.setAriaLabelProvider((input) => ‘my custom label’);
    this.setTooltip('');
    this.setHelpUrl('');
    this.setColour(225);
  }
};
{
  "type": "my_block",
  "tooltip": "",
  "helpUrl": "",
  "message0": "%1",
  "args0": [
    {
      "type": "input_value",
      "name": "NAME",
	“ariaLabelText”: “my custom string”,
    }
  ],
  "colour": 225
}

Blocks defined in JavaScript can use either a plain string or a function that returns a string. Since JSON block definitions cannot contain functions, developers can either supply a plain string, define their blocks in JavaScript instead, or use an extension to supply the aria label provider method. If a plain string is supplied, developers can use the message reference format to supply translatable strings.

Aria label updates

Finally, any place that tries to get an aria label for an input should first check if getAriaLabelText() returns non-null, and prefer that value if it exists, before falling back to the existing behavior. This occurs in the block label composer and possibly in some move mode code.

Alternatives considered

No response

Additional context

No response

Metadata

Metadata

Assignees

Labels

issue: feature requestDescribes a new feature and why it should be added

Projects

Status

In Progress

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions