> For the complete documentation index, see [llms.txt](https://docs.firework.com/firework-for-developers/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.firework.com/firework-for-developers/flutter-sdk/integration-guide-v2/ios-accessibility-issue-storyblock-in-column-layout.md).

# iOS Accessibility Issue: StoryBlock in Column Layout

### Problem

When `StoryBlock` is placed in a `Column` with other widgets (like `Text`), iOS VoiceOver accessibility fails:

* VoiceOver cannot interact with `StoryBlock` properly
* Tapping `StoryBlock` reads the wrong content (e.g., the `Text` label)

{% hint style="info" %}
In this problem scenario, when iOS VoiceOver is enabled, although elements within the StoryBlock—such as the Play/Pause button—are not selectable or readable through direct tap, they remain fully accessible and can be navigated and read using horizontal swipe gestures, thereby maintaining full compliance with WCAG Accessibility standards.
{% endhint %}

### Root Cause

**This is a Flutter framework limitation on iOS** when combining `Column` layouts with Platform Views, not a `StoryBlock` bug. Flutter's `Column` widget has semantic tree issues with Platform Views specifically on iOS:

1. **Semantic Node Presence**: When a widget before `StoryBlock` creates a semantic node (like `Text`), it interferes with `StoryBlock`'s accessibility on iOS
2. **Semantic Merging**: `Column` merges child semantics, causing the `Text` label to dominate and obscure `StoryBlock`'s interactive elements

**Note**: The exact mechanism is complex and may involve coordinate transformation issues in Flutter's iOS accessibility bridge. The empirical finding is clear: **any semantic node before a Platform View in a `Column` causes the problem on iOS**. This affects `UiKitView` on iOS. **Android (`PlatformViewLink`) is not affected**.

### Solution

Use `ListView` instead of `Column`:

```dart
// ❌ DON'T: Using Column
Column(
  children: [
    Text("Story Block Title"),
    StoryBlock(...),
  ],
)

// ✅ DO: Using ListView
ListView(
  shrinkWrap: true,                              // Fits content like Column
  physics: const NeverScrollableScrollPhysics(), // Disables scrolling
  children: [
    Text("Story Block Title"),
    StoryBlock(...),
  ],
)
```

#### Why ListView Works

`ListView` provides semantic isolation through Flutter's Sliver protocol:

* Each child has an independent coordinate system (no cumulative offsets)
* No automatic semantic merging
* Clear accessibility boundaries

#### Parameters Explained

* `shrinkWrap: true` - Makes ListView fit its content height (behaves like Column)
* `physics: NeverScrollableScrollPhysics()` - Disables scrolling to avoid gesture conflicts

### Alternative (Not Recommended)

If `ListView` is not feasible, use `ExcludeSemantics` to hide other widgets from accessibility:

```dart
Column(
  children: [
    ExcludeSemantics(
      child: Text("Story Block Title"),  // ⚠️ Not accessible to VoiceOver
    ),
    StoryBlock(...),
  ],
)
```

**Trade-off**: The wrapped widget becomes invisible to screen readers.
