Skip to main content

Accessibility Styles

Why Accessibility is important​

The fundamental purpose of an interface is to provide people with access to information: accessibility is the foundation of an interface. All people experience limitations in their abilities, whether it's temporary, situational or permanent. The aim of accessibility is to remove any obstacles that reduce the experience of using, understanding, and navigating your interface.

This page provides details of the Litho components, methods, nodes, events, and headings available to ensure your interface provides the 'full experience' promoted by Meta.

info

For information on how Meta is committed to creating a full UI experience for all people, see the Meta Accessibility site.

Implementing Accessibility features​

Accessibility properties and events for components can be implemented by adding them to the Style object.

Following is an example of how to combine a Style, that was passed to a Primitive Component, with a newly created Style object that implements accessibility properties and events and will be returned on the LithoPrimitive object from the render() method:

class SimpleImageViewWithAccessibilityPrimitiveComponent(private val style: Style = Style) :
PrimitiveComponent() {
override fun PrimitiveComponentScope.render(): LithoPrimitive {
val a11y =
Style.accessibilityRole(AccessibilityRole.IMAGE)
.accessibilityRoleDescription("Image View")
.importantForAccessibility(ImportantForAccessibility.YES)
.onInitializeAccessibilityNodeInfo { nodeInfo ->
nodeInfo.superDelegate.onInitializeAccessibilityNodeInfo(nodeInfo.host, nodeInfo.info)
nodeInfo.info.addAction(
AccessibilityNodeInfoCompat.AccessibilityActionCompat(
AccessibilityNodeInfoCompat.ACTION_CLICK,
"actionDescriptionText",
),
)
}

return LithoPrimitive(primitive = SimpleImageViewPrimitive, style = a11y + style)
}
}

Accessibility Properties​

Accessibility Heading​

Whether the view is a heading for a section of content for accessibility purposes.

import com.facebook.litho.accessibility.accessibilityHeading

MyComponent(style = Style.accessibilityHeading(true))

Accessibility Role​

The Android Talkback "role" this component has. This will be read out when the view is visited in Talkback mode.

import com.facebook.litho.accessibility.accessibilityRole
import com.facebook.litho.AccessibilityRole

MyComponent(style = Style.accessibilityRole(AccessibilityRole.BUTTON))

Accessibility Role Description​

The description for this Component's accessibility role. This will be read out when the view is visited in Talkback mode.

import com.facebook.litho.accessibility.accessibilityRoleDescription

MyComponent(style = Style.accessibilityRoleDescription("Custom action button"))

Content Description​

A description of the contents of this Component for accessibility.

import com.facebook.litho.accessibility.contentDescription

MyComponent(style = Style.contentDescription("Profile picture"))

State Description​

Sets the state description of the component.

import com.facebook.litho.accessibility.stateDescription

MyComponent(style = Style.stateDescription("Selected"))

Important For Accessibility​

Sets whether this Component is "important for accessibility". If it is, it fires accessibility events and is reported to accessibility services that query the screen.

import com.facebook.litho.accessibility.importantForAccessibility
import com.facebook.litho.accessibility.ImportantForAccessibility

MyComponent(style = Style.importantForAccessibility(ImportantForAccessibility.YES))

ImportantForAccessibility values​

import com.facebook.litho.accessibility.ImportantForAccessibility

// Automatically determine whether a view is important for accessibility
ImportantForAccessibility.AUTO

// The view is important for accessibility
ImportantForAccessibility.YES

// The view is not important for accessibility
ImportantForAccessibility.NO

// The view is not important for accessibility, nor are any of its descendant views
ImportantForAccessibility.NO_HIDE_DESCENDANTS

Screen Reader Focusable​

Sets whether this View should be a focusable element for screen readers.

import com.facebook.litho.accessibility.screenReaderFocusable

MyComponent(style = Style.screenReaderFocusable(true))

Request Initial Accessibility Focus​

Sets whether the node has requested initial accessibility focus.

import com.facebook.litho.accessibility.requestInitialAccessibilityFocus

MyComponent(style = Style.requestInitialAccessibilityFocus(true))

Min Duration Between Content Changes​

Sets the minimum time duration between two content change events, which is used in throttling content change events in accessibility services.

import com.facebook.litho.accessibility.minDurationBetweenContentChangesMillis

MyComponent(style = Style.minDurationBetweenContentChangesMillis(1000L))

Labeled By​

Sets the view which serves as the label of the view represented by this info for accessibility purposes.

import com.facebook.litho.accessibility.labeledBy

MyComponent(style = Style.labeledBy("label_view_tag"))

Pane Title​

Visually distinct portion of a window with window-like semantics are considered panes for accessibility purposes. Panes should have descriptive titles.

import com.facebook.litho.accessibility.paneTitle

MyComponent(style = Style.paneTitle("Settings Panel"))

Live Region​

Sets the live region mode for this view. This indicates to accessibility services whether they should automatically notify the user about changes to the view's content description or text.

import com.facebook.litho.accessibility.liveRegion
import android.view.View

MyComponent(style = Style.liveRegion(View.ACCESSIBILITY_LIVE_REGION_POLITE))

Live Region modes​

import android.view.View

// No live region notification
View.ACCESSIBILITY_LIVE_REGION_NONE

// Polite interruption (wait for a pause)
View.ACCESSIBILITY_LIVE_REGION_POLITE

// Assertive interruption (interrupt immediately)
View.ACCESSIBILITY_LIVE_REGION_ASSERTIVE

Container Title​

Sets the container title for app-developer-defined container which can be any type of ViewGroup or layout. Container title will be used to group together related controls.

import com.facebook.litho.accessibility.containerTitle

MyComponent(style = Style.containerTitle("Form Section"))

Accessibility Events​

onInitializeAccessibilityEvent​

Initializes an AccessibilityEvent with information about the the host View which dispatched the event.

import com.facebook.litho.accessibility.onInitializeAccessibilityEvent

MyComponent(
style = Style.onInitializeAccessibilityEvent { event ->
// Initialize accessibility event
}
)

onInitializeAccessibilityNodeInfo​

Initializes an AccessibilityNodeInfoCompat with information about the host view.

import com.facebook.litho.accessibility.onInitializeAccessibilityNodeInfo

MyComponent(
style = Style.onInitializeAccessibilityNodeInfo { event ->
// Initialize accessibility node info
}
)

onPopulateAccessibilityNode​

Gives a chance to the component to implement its own accessibility support.

import com.facebook.litho.accessibility.onPopulateAccessibilityNode

MyComponent(
style = Style.onPopulateAccessibilityNode { event ->
// Populate accessibility node
}
)

onPopulateAccessibilityEvent​

Gives a chance to the host View to populate the accessibility event with its text content.

import com.facebook.litho.accessibility.onPopulateAccessibilityEvent

MyComponent(
style = Style.onPopulateAccessibilityEvent { event ->
// Populate accessibility event
}
)

onRequestSendAccessibilityEventWithResult​

Called when a child of the host View requests sending an AccessibilityEvent. Return true to allow the event to propagate, or false to block it. Delegate to superDelegate to preserve the View's default behavior.

import com.facebook.litho.accessibility.onRequestSendAccessibilityEventWithResult

MyComponent(
style = Style.onRequestSendAccessibilityEventWithResult { event ->
event.superDelegate.onRequestSendAccessibilityEvent(
event.host,
event.child,
event.event,
)
}
)

onPerformAccessibilityActionWithResult​

Called when performing the specified accessibility action on the view. Return true when the action was handled. Return false, or delegate to superDelegate, when it was not.

import android.view.accessibility.AccessibilityNodeInfo
import com.facebook.litho.accessibility.onPerformAccessibilityActionWithResult

MyComponent(
style = Style.onPerformAccessibilityActionWithResult { event ->
if (event.action == AccessibilityNodeInfo.ACTION_CLICK) {
activate()
true
} else {
event.superDelegate.performAccessibilityAction(
event.host,
event.action,
event.args,
)
}
}
)

onSendAccessibilityEvent​

Called when Sends an accessibility event of the given type. If accessibility is not enabled this method has no effect.

import com.facebook.litho.accessibility.onSendAccessibilityEvent

MyComponent(
style = Style.onSendAccessibilityEvent { event ->
// Send accessibility event
}
)

onSendAccessibilityEventUnchecked​

Sends an accessibility event. This method behaves exactly as sendAccessibilityEvent() but takes as an argument an empty AccessibilityEvent and does not perform a check whether accessibility is enabled.

import com.facebook.litho.accessibility.onSendAccessibilityEventUnchecked

MyComponent(
style = Style.onSendAccessibilityEventUnchecked { event ->
// Send accessibility event unchecked
}
)

onVirtualViewKeyboardFocusChanged​

Called when a virtual view child of the host View has changed keyboard focus and gives an opportunity to the parent (the host) to react (changing visual display, etc.)

import com.facebook.litho.accessibility.onVirtualViewKeyboardFocusChanged

MyComponent(
style = Style.onVirtualViewKeyboardFocusChanged { event ->
// Handle virtual view keyboard focus change
}
)

onPerformActionForVirtualViewWithResult​

Performs the specified accessibility action on a virtual view child of the host View. Return true when the action was handled, or false otherwise.

caution

Litho does not currently dispatch this handler. Virtual views come only from Spec components that declare extra accessibility nodes, and Litho calls their @OnPerformActionForVirtualView method instead.

import com.facebook.litho.accessibility.onPerformActionForVirtualViewWithResult

MyComponent(
style = Style.onPerformActionForVirtualViewWithResult { event ->
// Perform the action, then return whether it was handled
true
}
)

Focus Order​

You can customize the default focus order behavior by creating focus order properties using useFocusOrder() hook and adding them to the Style object. This allows you to tailor the focus order to your specific needs, ensuring that interactive elements are navigable in a logical and predictable manner.

val hideElements = useState { false }
val (first, second, third, fourth, fifth) = useFocusOrder()

return Column(
style = Style.padding(16.dp).contentDescription("Fourth hello!").focusOrder(fourth),
) {
child(
Text(
text = "First hello!",
style =
Style.focusOrder(first).onClick { hideElements.update { !hideElements.value } },
),
)

if (hideElements.value) {
child(Text(text = "Fifth hello!", style = Style.focusOrder(fifth)))
child(TextInput(initialText = "Second hello!", style = Style.focusOrder(second)))
}
child(Text(text = "Third hello!", style = Style.focusOrder(third)))
}