Accessibility Inspector Element Detection and contrast failures with SwiftUI sheets

I am investigating Accessibility Inspector/XCTest audit results in a SwiftUI app (Target Keeper), without suppressing warnings. Environment: Xcode 27.1 (27A9275), iPadOS 27.0 Simulator, macOS 27.0.1. Debug and Release builds pass. The app uses scalable text and labeled controls.

Element Detection / native sheet

  • Main-screen Element Detection passes when the sheet is closed.
  • With a SwiftUI .sheet presented, the iPad audit reports “Potentially inaccessible text”; XCUIAccessibilityAuditIssue.element is nil. Exported Inspector HTML highlights background labels behind/outside the sheet, rather than a foreground control.
  • The separate, data-free SwiftUI application below reproduces the modal-only warning; it links no application modules or persistence.
  • Actual iPad Simulator VoiceOver testing using XCUIDevice.shared.voiceOverService passes forward/backward traversal of the real application's modal controls, without reaching the background labels. This is simulator evidence, not physical-device acceptance.
  • A trial explicit modal container/.isModal trait did not clear the audit and was reverted; no warnings are filtered.

Minimal independent app:

import SwiftUI
@main struct ModalRepro: App {
 @State private var showing=false
 private let names=["Vegetables","Protein","Fruit","Dairy","Grains","Healthy Fats"]
 var body:some Scene {WindowGroup {
  NavigationStack {
   VStack(spacing:24) {
    Button("Nutrition") {}.accessibilityLabel("Choose Page").accessibilityValue("Nutrition")
    LazyVGrid(columns:[GridItem(.flexible()),GridItem(.flexible()),GridItem(.flexible())],spacing:40) {
     ForEach(names,id:\.self) { name in
      Button {} label: {
       VStack(spacing:10) {
        Circle().fill(.blue.opacity(0.3)).frame(width:250,height:250)
        Text(name).font(.system(size:17)).accessibilityHidden(true)
       }
      }.buttonStyle(.plain).accessibilityLabel(name)
     }
    }
    Button("Show modal") {showing=true}
   }.padding(24).frame(maxWidth:.infinity,maxHeight:.infinity).background(Color.black)
  }.preferredColorScheme(.dark)
   .sheet(isPresented:$showing) {
    NavigationStack {
     VStack {Text("Foreground content");Button("Close") {showing=false}}
      .frame(maxWidth:.infinity,maxHeight:.infinity).background(Color.black)
      .navigationTitle("Modal flow")
    }.preferredColorScheme(.dark)
   }
 }}
}

In an Xcode UI-test target, launch this app, run try app.performAccessibilityAudit(for: [.elementDetection]), tap “Show modal”, then run the same audit again. The first passes and the second fails. No issue handler ignores failures.

Contrast / scrolling — separate unresolved finding
All four iPhone combined-audit configurations (portrait/landscape, normal/maximum Dynamic Type) pass in the tested picker state. However, iPad maximum-text combined audits and a separate scrolled iPhone maximum-text landscape contrast audit still fail; we are not calling these resolved.

In the scrolled iPhone case, XCTest identifies a count label whose frame is entirely above the visible results viewport. Inspector's exported HTML reports 1.37:1 using #252526 versus #000000; its marked screenshot rectangle overlaps the dark search/header area, not visible count text. Visible sampled labels instead have white or light foregrounds on opaque dark fills (e.g. #FFFFFF/#1C1C1E = 17.01:1; #98989F/#1C1C1E = 5.94:1). These are screenshot core-pixel measurements, not proof every warning is false. We compare ordinary text against 4.5:1 and interactive non-text against 3:1. iPad maximum-text warnings have not yet been matched to an exact visible color pair. Original failures and HTML exports are preserved privately.

Questions

  1. Is Element Detection expected to inspect background elements behind a presented native SwiftUI sheet? Is this a known tool limitation/framework issue, or does the sample need different semantics?
  2. What is the supported way to establish modal accessibility boundaries with SwiftUI sheets, and when should .isModal be added explicitly?
  3. How should we distinguish a real contrast defect from clipping, occlusion, translucency, or sampling of an offscreen element? Which Inspector export fields/diagnostics should establish the actual sampled text/background pair?
  4. What additional evidence/manual and physical-device tests does Apple recommend before qualifying accessibility when the minimal audit reproduction fails but actual VoiceOver modal focus behaves correctly? We are not asking to waive audits or declare full accessibility from a VoiceOver pass alone.

I read Apple's audit guidance and modal trait documentation:
https://developer.apple.com/documentation/accessibility/performing-accessibility-audits-for-your-app
https://developer.apple.com/documentation/swiftui/accessibilitytraits/ismodal
https://developer.apple.com/help/app-store-connect/manage-app-accessibility/sufficient-contrast-evaluation-criteria/

Related discussion https://developer.apple.com/forums/thread/823968 recommends Feedback for a different apparent Dynamic Type false positive; it does not answer these modal/contrast questions. A Feedback draft is prepared but not submitted, so I have no Feedback ID yet. No private data, identifiers, credentials, app containers or confidential application source are included.

October 29 diagnostic update: we now have matched iPad failure-state hierarchies and screenshots.
The earlier XCTest exports contained a main-screen hierarchy captured BEFORE opening the picker. To close that gap, a diagnostic harness now records the hierarchy and screenshot inside the audit issue handler. The three targeted iPad cases reproduce in that matched modal state: landscape normal fails Element Detection; portrait/landscape maximum Dynamic Type fail Contrast. All original assertions and seven audit categories remain intact; the handler returns false. XCUIAccessibilityAuditIssue.element is still nil. Test details, activity exports and matched snapshots expose neither the failed node/bounds nor its sampled colors. We have not identified the exact landscape detection target or the maximum-text contrast targets.
Retained evidence for context:

  • The data-free SwiftUI reproduction in the original post passes main-screen Element Detection with the sheet closed and fails with it presented; it uses no app modules or persistence. The portrait Inspector report highlights background Nutrition, Vegetables, Dairy and Grains text behind/outside the sheet.
  • Actual iPad Simulator VoiceOver forward/backward modal traversal passes without reaching those background labels. This is not physical-device or full accessibility acceptance.
  • The iPhone scrolled-state report gives #252526 against #000000, 1.37:1, while XCTest places the count label wholly above the visible results viewport. That is the tool-reported sample, not a verified visible glyph/background pair.
  • Unchanged .95 passes Banana visibility and all picker-control steps before reproducing that contrast failure. Zero visible height occurred in a rejected lazy-stack trial, which was reverted.
  • Debug and Release builds pass. All five original gates remain unresolved: two iPad normal Element Detection cases, two iPad maximum-text Contrast cases, and the separate scrolled iPhone Contrast case. No warning is filtered or waived.
    Given these matched captures, could Apple clarify:
  1. Is Element Detection expected to evaluate background text behind a presented SwiftUI sheet?
  2. What supported semantics establish the modal accessibility boundary?
  3. When issue.element is nil, which supported diagnostic/export identifies the actual sampled node, bounds and foreground/background colors?
  4. How should offscreen or clipped text contrast findings be distinguished from visible contrast defects?
  5. What independent VoiceOver/manual evidence should accompany a minimal reproduction when modal focus passes but the audit fails?
    Original reports, matched screenshots and hierarchies are retained locally. No attachments or private data are included here. We are seeking a diagnosis, not a waiver or a claim that the warnings are harmless.