---
title: Accessibility
---

# Accessibility

## Overview

To better support visually impaired users, mini apps support configuring accessibility attributes. Accessibility features are available in screen reader mode. You can enable screen readers as follows:

- **iOS**: Settings → General → Accessibility → VoiceOver
- **Android**: Settings → Accessibility → TalkBack

Take the `View` component as an example. You can add `role` and `aria-label` attributes to it. The `role` attribute defines the semantic role of the component — for instance, setting it to `'img'` causes the screen reader to announce "image" when focused, and setting it to `'button'` causes it to announce "button". The `aria-label` attribute provides additional descriptive text that the screen reader will announce when the element is focused.

## Accessibility Styles

The base library automatically manages the accessibility style switch. When accessibility styles are enabled, it adds `data-a11y="true"` to the HTML root node; when disabled, it removes the attribute. You do not need to set this attribute manually. Instead, use it in selectors to provide higher contrast, clearer focus states, or larger touch targets in accessibility mode.

```css
[data-a11y='true'] .action-btn {
  min-height: 96rpx;
  outline: 4rpx solid #1677ff;
}
```

The following ARIA attributes can be passed as props to any component to define custom accessibility semantics.

## Accessibility Properties

| Property | Description |
| --- | --- |
| role | Semantic role, e.g. `button`, `checkbox`, `slider`, `link` |
| aria-label | Text read aloud by assistive technology to describe the element |
| aria-labelledby | References the id of another element whose text serves as the label for this element (useful for elements with a separate heading) |
| aria-describedby | References the id of another element whose text provides a description for this element |
| aria-disabled | Whether the element is disabled |
| aria-hidden | When `'true'`, assistive technology ignores this element and its subtree; useful for purely decorative content |
| aria-checked | Whether the element is checked (applies to `checkbox`, `radio`, `switch`) |
| aria-selected | Whether the element is selected (applies to list items, tabs, and other selectable scenarios) |
| aria-expanded | Whether the element is expanded (applies to collapsible panels, etc.) |
| aria-haspopup | Whether the element has an associated popup (e.g. a dropdown menu) |
| aria-live | Live region update policy. Values: `off` (default, no announcement), `polite` (announces after update completes), `assertive` (interrupts current announcement immediately) |
| aria-atomic | Used with `aria-live`. When `'true'`, assistive technology announces the entire live region; when `'false'`, only the changed portion is announced |
| aria-relevant | Used with `aria-live`. Specifies what types of changes trigger an announcement. Values: `additions`, `removals`, `text`, `all` |
| aria-required | Whether the form element is required (applies to `input`, `textarea`, etc.) |
| aria-flowto | Specifies the id of the next element in reading order, overriding the default document order |
| aria-valuetext | Human-readable text for the current value of a range element (takes precedence over `aria-valuenow` when announced) |
| aria-valuemin | Minimum value of a range element (applies to `slider`) |
| aria-valuemax | Maximum value of a range element (applies to `slider`) |
| aria-valuenow | Current value of a range element (applies to `slider`) |
| tabindex | Position of the element in Tab key navigation order; `0` makes it focusable, `-1` removes it from Tab order |

## Built-in ARIA Properties

The following components have built-in ARIA attributes that are set automatically — no manual configuration required:

| Component | Accessibility Properties |
| --- | --- |
| Button | `role="button"` `aria-disabled` |
| Input / Textarea | `aria-disabled` |
| Checkbox | `role="checkbox"` `aria-checked` `aria-disabled` |
| Radio | `role="radio"` `aria-checked` `aria-disabled` |
| Switch | `role="switch"` `aria-checked` `aria-disabled` |
| Slider | `role="slider"` `aria-valuemin` `aria-valuemax` `aria-valuenow` `aria-disabled` |
| Picker | `aria-haspopup="true"` `aria-disabled` |
| Navigator | `role="link"` `tabindex="0"` |

## Examples

### Add role and aria-label to a View

```jsx | sandbox previewTitle="Custom Accessibility"
import React from 'react';
import { View, Text } from '@ray-js/ray';

export default function AccessibilityDemo() {
  return (
    <View
      role="button"
      aria-label="Close dialog"
      tabindex="0"
      style={{ padding: '20rpx', background: '#f0f0f0', display: 'inline-block' }}
    >
      <Text>x</Text>
    </View>
  );
}
```

### Frequently Asked Questions

**I passed a `role` to `Button`, but it doesn't seem to work. Why?**

`Button` has a built-in `role="button"`. Any custom `role` passed to it will be overridden by the built-in value. To use a custom semantic role, use `View` or another element without a built-in role.

**Which takes precedence when both `aria-label` and inner text are present?**

Assistive technology generally prioritizes `aria-label` over inner text. If the component's inner text already conveys the meaning clearly, there is no need to set `aria-label`. For elements like icon-only buttons that lack descriptive text, always set `aria-label`.

**How should I choose a value for `tabindex`?**

Use only `0` or `-1`. A value of `0` adds the element to the natural Tab order; `-1` makes it programmatically focusable but excludes it from Tab navigation. Avoid positive integers, as they disrupt the natural Tab order.
