@@ -267,6 +267,7 @@ struct DiagramCanvasView: View {
267267 Color . clear
268268 . frame ( width : cw , height : ch )
269269 . contentShape ( Rectangle ( ) )
270+ . accessibilityHidden ( true )
270271 . onTapGesture {
271272 selectedPath = nil
272273 // iPhone: Einfügemarke durch Tap auf leeren Bereich löschen.
@@ -291,13 +292,16 @@ struct DiagramCanvasView: View {
291292
292293 canvasView ( layout : layout , cw : cw , ch : ch )
293294 . allowsHitTesting ( false )
295+ // Gezeichnete Fläche; VoiceOver liest stattdessen die Blöcke darüber.
296+ . accessibilityHidden ( true )
294297
295298 if let firstRoot = layout . elements . first {
296299 rootInsertBeforeFirstStrip (
297300 firstRootFrame : firstRoot . frame ,
298301 canvasWidth : cw ,
299302 canvasHeight : ch
300303 )
304+ . accessibilityHidden ( true )
301305 }
302306
303307 ForEach ( flat , id : \. pathKey ) { node in
@@ -408,13 +412,30 @@ struct DiagramCanvasView: View {
408412 . draggable ( DiagramDragPayload ( raw : ElementPalette . moveDragIdentifier ( path : node . idPath ) ) ) {
409413 nodeDragPreview ( for : node )
410414 }
415+ // VoiceOver: ein Element pro Block (statt der unbeschrifteten Drop-Streifen darin).
416+ . accessibilityElement ( children : . ignore )
417+ . accessibilityLabel ( accessibilityLabel ( for : node ) )
418+ . accessibilityAddTraits ( selectedPath == node . idPath ? [ . isButton , . isSelected ] : . isButton )
419+ . accessibilityAction {
420+ selectedPath = node . idPath
421+ }
411422 . accessibilityHint (
412423 isPlaceholderNode
413424 ? lang . tr ( " a11y_placeholder_drop " )
414425 : lang . tr ( " a11y_node_drop " )
415426 )
416427 }
417428
429+ /// Vorgelesener Name eines Blocks: Elementart und Text, z. B. „Anweisung: int x = 5“.
430+ private func accessibilityLabel ( for node : VisuStructLayout . Node ) -> String {
431+ // Schlüssel wie in der Palette: element_anweisung, element_verzweigung, …
432+ let kind = lang . tr ( " element_ \( node . element . type ) " )
433+ let text = node . element . textLines
434+ . joined ( separator : " " )
435+ . trimmingCharacters ( in : . whitespacesAndNewlines )
436+ return text . isEmpty ? kind : " \( kind ) : \( text ) "
437+ }
438+
418439 private func copyElement ( at path : [ Int ] ) {
419440 guard let el = try? VisuStructDocumentEditing . element ( at : path , in : document ) else { return }
420441 elementClipboard = el
0 commit comments