Repository navigation
Description
Summary
Expose resolved AccessibilityAttributes (label, description, live, hidden) as a dedicated first-class reactive property on ComponentNode (analogous to node.metadata added in #3469 / #3708), rather than storing and resolving @accessibility (and mirroring legacy accessibility) inside node.props.
Background & Problem
With the v1.0 @-prefixed component envelope cutover (#4037, #4044), @accessibility is a component envelope mixin alongside @metadata, @catalogId, and @checks, leaving the bare name accessibility free for custom catalog component properties.
Currently, unlike @metadata (which is extracted from ComponentModel.properties and exposed on ComponentNode.metadata), @accessibility remains inside ComponentModel.properties and is resolved by GenericBinder / NodeResolver into node.props['@accessibility'] (plus a conditional mirror onto node.props['accessibility'] when the component schema does not declare a custom accessibility property).
This creates several ergonomic and architectural warts across Core SDKs and framework adapters:
- Manual probing & unwrapping in every adapter: Framework adapters and universal helpers must probe
props['@accessibility'] ?? props['accessibility'], verify it is an attributes object rather than a custom component property, and manually unwrap or subscribe to each nestedResolvedBinding(label,description,live,hidden):- TypeScript (
typescript/core/web_core/src/universal/host_accessibility.ts):resolveAccessibilityProps(props)loops over['@accessibility', 'accessibility']and unwraps bindings. - Flutter (
dart/a2ui_flutter/lib/src/node_view.dart): readsprops.value('@accessibility') ?? props.value('accessibility')and manually manages_accessibilityUnsubscribes. - Swift (
swift/core/Sources/A2UICore/Resolution/NodeResolver.swift&swift/swiftui/Sources/A2UISwiftUI/ComponentNodeView.swift): reads@accessibility/accessibilityfromnode.properties.
- TypeScript (
- Envelope leakage into
node.props: Component implementations inspectingnode.propssee@accessibility(and the conditionalaccessibilitymirror) mixed in with their own schema-defined component properties, requiring special-case mirroring logic inGenericBinder(finalizeResolvedProps,mirrorsAccessibility) andNodeResolver.
Proposed Solution
ComponentNode.accessibilityacross Core SDKs (@a2ui/web_core,a2ui_corein Dart/Python,A2UICorein Swift):- Expose a dedicated reactive
accessibilityproperty onComponentNode(e.g.,readonly accessibility: Signal<ResolvedAccessibilityAttributes | undefined>in TypeScript,ReadonlySignal<ResolvedAccessibility?>in Dart, and corresponding properties on PythonComponentNodeand SwiftNode) withlabel,description,live, andhiddenalready resolved/unwrapped. - Resolve envelope
@accessibility(and legacy bareaccessibilityon pre-1.0 or during the Remove legacy bare-key fallback for v1.0 component envelope fields #4082 transition when undeclared as a custom property) intonode.accessibilityinstead of pollutingnode.props['@accessibility'].
- Expose a dedicated reactive
- Framework Adapter Simplification:
- Update
@a2ui/web_core/universal(A2uiLitElement),@a2ui/react,@a2ui/angular,a2ui_flutter(NodeView), andA2UISwiftUI(ComponentNodeView) to read accessibility state directly fromnode.accessibility.
- Update
- Blueprints & Conformance:
- Document
ComponentNode.accessibilityinblueprints/modules/a2ui_core.blueprint.md,blueprints/features/node_resolution.blueprint.md, andblueprints/modules/a2ui_framework_adapter.blueprint.md(alongside [Blueprints] Document AccessibilityAttributes resolution and adapter mapping in a2ui_core and a2ui_framework_adapter blueprints #3148).
- Document
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsTodo
Activity
jacobsimionato commentedon Nov 11, 2026
Coding agent prompt: Implement a dedicated reactive
accessibilityproperty onComponentNodeacross all four Core SDKs and update framework adapters to read accessibility state fromnode.accessibilityinstead of probingnode.props['@accessibility'] ?? node.props['accessibility'].Implementation Strategy
@a2ui/web_core& Web Renderers):readonly accessibility: Signal<ResolvedAccessibilityAttributes | undefined>;toComponentNode(similar toreadonly metadata: Signal<A2uiMetadata | undefined>;).@accessibility(and legacy bareaccessibilityon pre-1.0 surfaces or during the Remove legacy bare-key fallback for v1.0 component envelope fields #4082 v1.0 transition when undeclared as a custom property in the component schema) intonode.accessibilitywithlabel,description,live, andhiddenunwrapped.node.accessibilitydirectly.a2ui_core&a2ui_flutter):ReadonlySignal<ResolvedAccessibility?> get accessibility;onComponentNodeand simplifyNodeViewina2ui_flutterso it subscribes tonode.accessibilityrather than manually probingprops.value('@accessibility') ?? props.value('accessibility').a2ui_core):accessibilityonComponentNode.A2UICore&A2UISwiftUI):accessibilityonNodeand read it inComponentNodeView.conformance/core/accessibility.yaml) pass across TypeScript, Dart, Python, and Swift.