ReviewOS

craft-native/craft

fix(ios): labelled Modal hides interactive children from accessibility

#402
Closed glennmichael123 opened this 8 days ago ·
8 days ago

Reproduced on current main

Craft 45a33630e45b6ba84a43008ea3a36596f7287278, clean checkout; generated native iOS app, Xcode 26.6, iPhone 17 Pro simulator / iOS 26.5. No Craft source modifications.

Opening an STX shared Dialog with title="Outer dialog" draws its sheet and button correctly, but XCTest cannot discover the visible button. The exported accessibility hierarchy contains a leaf Other labelled Outer dialog and no descendants beneath it:

Other, {{0.0, 62.0}, {402.0, 778.0}}, identifier: 'n39', label: 'Outer dialog'

The screenshot shows the sheet's Open nested dialog button. app.buttons["open-inner"].waitForExistence(timeout: 10) fails. This prevents native accessibility validation of the nested-dialog flow in stacksjs/stx#2089.

The same screen's unlabelled non-modal Popover passes actual touch, clipping escape, outside dismissal and retained child-state checks. Shared tabs also pass. This report concerns the labelled modal container, not a general failure to render the screen.

Source cause

In packages/ios/templates/CraftNativeScreen.swift, applyAccessibility (around lines 9839–9843) treats ScrollView, FlatList, SectionList, Picker and certain group roles as containers. Modal is absent. A Modal with accessibilityLabel consequently receives isAccessibilityElement = true, hiding its descendants from accessibility queries. The shared Dialog correctly projects its accessible name onto that Modal.

Minimal shared-source shape:

<Dialog title="Outer dialog" :open="open">
  <DialogPanel>
    <Button testID="open-inner">Open nested dialog</Button>
  </DialogPanel>
</Dialog>

Requested fix / acceptance

Preserve a labelled modal's accessible group/name while exposing its children as actionable native elements. Verify an actual generated screen can find and tap the nested button; retain appropriate modal accessibility containment. Include the analogous labelled Drawer case. Do not solve this by deleting the component's accessible name.

Local evidence: /var/folders/sq/p6y46h2x6ddgq6w1yyxhd_9h0000gn/T/stx-portability-ios-pyG3uL/TestResults.xcresult; exported app hierarchy 50A6DA3B-8053-4393-805A-C97FB4F3C05E.txt. The maintained STX fixture and XCTest will be committed to stacksjs/stx with a read-only Craft SDK runner.

8 days ago

Fixed in commit 17e09f4. Labelled Modal and Drawer nodes now remain accessibility containers so their interactive children stay discoverable. Added native renderer coverage for labelled modal/drawer children; bun test packages/ios/src/index.test.ts passes 129/129.

Sign in to comment on this issue.