@storybook/react-native-ui-lite 10.2.2-alpha.2 → 10.2.2-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@storybook/react-native-ui-lite",
3
- "version": "10.2.2-alpha.2",
3
+ "version": "10.2.2-alpha.3",
4
4
  "description": "lightweight ui components for react native storybook",
5
5
  "keywords": [
6
6
  "react",
@@ -42,8 +42,8 @@
42
42
  "@legendapp/list": "3.0.0-beta.31",
43
43
  "@nozbe/microfuzz": "^1.0.0",
44
44
  "@storybook/react": "^10.2.2",
45
- "@storybook/react-native-theming": "^10.2.2-alpha.2",
46
- "@storybook/react-native-ui-common": "^10.2.2-alpha.2",
45
+ "@storybook/react-native-theming": "^10.2.2-alpha.3",
46
+ "@storybook/react-native-ui-common": "^10.2.2-alpha.3",
47
47
  "polished": "^4.3.1",
48
48
  "react-native-safe-area-context": "^5"
49
49
  },
@@ -58,5 +58,5 @@
58
58
  "publishConfig": {
59
59
  "access": "public"
60
60
  },
61
- "gitHead": "af294af11927af3754f6958f0f6f2a358897f7b9"
61
+ "gitHead": "b996f5156b78ae94b967434130a6af1bee2876a2"
62
62
  }
package/src/Explorer.tsx CHANGED
@@ -24,7 +24,12 @@ export const Explorer: FC<ExplorerProps> = React.memo(function Explorer({
24
24
  const containerRef = useRef<View>(null);
25
25
 
26
26
  return (
27
- <View ref={containerRef} style={containerStyle}>
27
+ <View
28
+ ref={containerRef}
29
+ style={containerStyle}
30
+ id="storybook-explorer-tree"
31
+ testID="storybook-explorer-tree"
32
+ >
28
33
  {dataset.entries.map(([refId, ref]) => (
29
34
  <Ref
30
35
  {...ref}
package/src/Layout.tsx CHANGED
@@ -209,6 +209,7 @@ export const Layout = ({
209
209
 
210
210
  const mobileMenuDrawerRef = useRef<MobileMenuDrawerRef>(null);
211
211
  const addonPanelRef = useRef<MobileAddonsPanelRef>(null);
212
+ const [isDrawerOpen, setIsDrawerOpen] = useState(false);
212
213
 
213
214
  const setSelection = useCallback(({ storyId: newStoryId }: { storyId: string }) => {
214
215
  const channel = addons.getChannel();
@@ -217,7 +218,11 @@ export const Layout = ({
217
218
  }, []);
218
219
 
219
220
  return (
220
- <View style={containerStyle}>
221
+ <View
222
+ style={containerStyle}
223
+ accessibilityElementsHidden={isDrawerOpen}
224
+ importantForAccessibility={isDrawerOpen ? 'no-hide-descendants' : 'auto'}
225
+ >
221
226
  {isDesktop ? (
222
227
  <>
223
228
  <View style={desktopSidebarStyle} pointerEvents={isResizing ? 'none' : 'auto'}>
@@ -226,7 +231,11 @@ export const Layout = ({
226
231
  <View style={desktopLogoContainer}>
227
232
  <StorybookLogo theme={theme} />
228
233
 
229
- <IconButton onPress={() => setDesktopSidebarOpen(false)} Icon={MenuIcon} />
234
+ <IconButton
235
+ onPress={() => setDesktopSidebarOpen(false)}
236
+ Icon={MenuIcon}
237
+ accessibilityLabel="Close sidebar"
238
+ />
230
239
  </View>
231
240
 
232
241
  <View style={flexStyle}>
@@ -243,7 +252,11 @@ export const Layout = ({
243
252
  </View>
244
253
  </>
245
254
  ) : (
246
- <IconButton onPress={() => setDesktopSidebarOpen(true)} Icon={MenuIcon} />
255
+ <IconButton
256
+ onPress={() => setDesktopSidebarOpen(true)}
257
+ Icon={MenuIcon}
258
+ accessibilityLabel="Open sidebar"
259
+ />
247
260
  )}
248
261
  </View>
249
262
  {desktopSidebarOpen ? (
@@ -267,6 +280,8 @@ export const Layout = ({
267
280
  style={fullScreenButtonStyle}
268
281
  hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}
269
282
  onPress={() => setUiHidden((prev) => !prev)}
283
+ accessibilityRole="button"
284
+ accessibilityLabel={uiHidden ? 'Exit fullscreen' : 'Enter fullscreen'}
270
285
  >
271
286
  {uiHidden ? (
272
287
  <CloseFullscreenIcon color={theme.color.mediumdark} />
@@ -294,6 +309,7 @@ export const Layout = ({
294
309
  style={iconFloatRightStyle}
295
310
  onPress={() => setDesktopAddonsPanelOpen(true)}
296
311
  Icon={BottomBarToggleIcon}
312
+ accessibilityLabel="Open addons panel"
297
313
  />
298
314
  )}
299
315
  </View>
@@ -309,6 +325,8 @@ export const Layout = ({
309
325
  style={navButtonStyle}
310
326
  hitSlop={navButtonHitSlop}
311
327
  onPress={() => mobileMenuDrawerRef.current?.setMobileMenuOpen(true)}
328
+ accessibilityRole="button"
329
+ accessibilityLabel="Open story list"
312
330
  >
313
331
  <MenuIcon color={theme.color.mediumdark} />
314
332
  <Text style={navButtonTextStyle} numberOfLines={1}>
@@ -321,13 +339,14 @@ export const Layout = ({
321
339
  hitSlop={addonButtonHitSlop}
322
340
  onPress={() => addonPanelRef.current.setAddonsPanelOpen(true)}
323
341
  Icon={BottomBarToggleIcon}
342
+ accessibilityLabel="Open addons panel"
324
343
  />
325
344
  </Nav>
326
345
  </Container>
327
346
  ) : null}
328
347
 
329
348
  {isDesktop ? null : (
330
- <MobileMenuDrawer ref={mobileMenuDrawerRef}>
349
+ <MobileMenuDrawer ref={mobileMenuDrawerRef} onVisibilityChange={setIsDrawerOpen}>
331
350
  <View style={mobileMenuDrawerContentStyle}>
332
351
  <StorybookLogo theme={theme} />
333
352
  </View>
@@ -148,6 +148,9 @@ export const MobileAddonsPanel = forwardRef<MobileAddonsPanelRef, { storyId?: st
148
148
  height: panelHeight,
149
149
  transform: [{ translateY: positionBottomAnimation }],
150
150
  }}
151
+ pointerEvents={isOpen ? 'auto' : 'none'}
152
+ accessibilityElementsHidden={!isOpen}
153
+ importantForAccessibility={isOpen ? 'auto' : 'no-hide-descendants'}
151
154
  >
152
155
  <View
153
156
  style={{
@@ -272,6 +275,7 @@ export const AddonsTabs = ({ onClose, storyId }: { onClose?: () => void; storyId
272
275
  hitSlop={hitSlop}
273
276
  Icon={CloseIcon}
274
277
  onPress={() => onClose?.()}
278
+ accessibilityLabel="Close addons panel"
275
279
  />
276
280
  </View>
277
281
  <ScrollView
@@ -288,7 +292,12 @@ export const AddonsTabs = ({ onClose, storyId }: { onClose?: () => void; storyId
288
292
 
289
293
  const Tab = ({ active, onPress, text }: { active: boolean; onPress: () => void; text: string }) => {
290
294
  return (
291
- <TabButton active={active} onPress={onPress}>
295
+ <TabButton
296
+ active={active}
297
+ onPress={onPress}
298
+ accessibilityRole="tab"
299
+ accessibilityState={{ selected: active }}
300
+ >
292
301
  <TabText active={active}>{text}</TabText>
293
302
  </TabButton>
294
303
  );
@@ -40,6 +40,7 @@ const portalContainerStyle: ViewStyle = {
40
40
 
41
41
  interface MobileMenuDrawerProps {
42
42
  children: ReactNode | ReactNode[];
43
+ onVisibilityChange?: (visible: boolean) => void;
43
44
  }
44
45
 
45
46
  export interface MobileMenuDrawerRef {
@@ -110,166 +111,177 @@ export const useAnimatedModalHeight = () => {
110
111
  };
111
112
 
112
113
  export const MobileMenuDrawer = memo(
113
- forwardRef<MobileMenuDrawerRef, MobileMenuDrawerProps>(({ children }, ref) => {
114
- // const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
115
- const [isVisible, setIsVisible] = useState(false);
116
- const { scrollCallback } = useSelectedNode();
117
- const theme = useTheme();
118
- const { height } = useWindowDimensions();
119
- const animatedHeight = useAnimatedModalHeight();
120
-
121
- // Slide animation for drawer entrance/exit
122
- const slideAnim = useAnimatedValue(height);
123
-
124
- // Create a reference for the drag handle animation
125
- const dragY = useAnimatedValue(0);
126
-
127
- const openDrawer = useCallback(() => {
128
- dragY.setValue(0);
129
- slideAnim.setValue(height);
130
- setIsVisible(true);
131
- // setMobileMenuOpen(true);
132
- Animated.timing(slideAnim, {
133
- toValue: 0,
134
- duration: 300,
135
- easing: Easing.out(Easing.quad),
136
- useNativeDriver: true,
137
- }).start(({ finished }) => {
138
- if (finished) {
139
- // go to the selected story and don't animate
140
- scrollCallback({ animated: false, id: undefined });
141
- }
142
- });
143
- }, [dragY, height, scrollCallback, slideAnim]);
144
-
145
- const closeDrawer = useCallback(() => {
146
- Keyboard.dismiss();
147
- // setMobileMenuOpen(false);
148
- Animated.timing(slideAnim, {
149
- toValue: height,
150
- duration: 300,
151
- easing: Easing.in(Easing.quad),
152
- useNativeDriver: true,
153
- }).start(({ finished }) => {
154
- if (finished) {
155
- setIsVisible(false);
156
- }
157
- });
158
- }, [height, slideAnim]);
159
-
160
- // Create the pan responder for handling drag gestures
161
- const panResponder = useMemo(
162
- () =>
163
- PanResponder.create({
164
- onStartShouldSetPanResponder: () => true,
165
- onMoveShouldSetPanResponder: (_, gestureState) => {
166
- // Only capture downward dragging motions
167
- return gestureState.dy > 0;
168
- },
169
- onPanResponderMove: (_, gestureState) => {
170
- // Update dragY based on the gesture
171
- if (gestureState.dy > 0) {
172
- dragY.setValue(gestureState.dy);
173
- }
174
- },
175
- onPanResponderRelease: (_, gestureState) => {
176
- if (gestureState.dy > 50) {
177
- closeDrawer();
178
- } else {
179
- // Only snap back if not closing
180
- Animated.timing(dragY, {
181
- toValue: 0,
182
- duration: 300,
183
- easing: Easing.out(Easing.quad),
184
- useNativeDriver: true,
185
- }).start();
186
- }
187
- },
114
+ forwardRef<MobileMenuDrawerRef, MobileMenuDrawerProps>(
115
+ ({ children, onVisibilityChange }, ref) => {
116
+ const [isVisible, setIsVisible] = useState(false);
117
+ const { scrollCallback } = useSelectedNode();
118
+ const theme = useTheme();
119
+ const { height } = useWindowDimensions();
120
+ const animatedHeight = useAnimatedModalHeight();
121
+
122
+ // Slide animation for drawer entrance/exit
123
+ const slideAnim = useAnimatedValue(height);
124
+
125
+ // Create a reference for the drag handle animation
126
+ const dragY = useAnimatedValue(0);
127
+
128
+ const openDrawer = useCallback(() => {
129
+ dragY.setValue(0);
130
+ slideAnim.setValue(height);
131
+ setIsVisible(true);
132
+ onVisibilityChange?.(true);
133
+
134
+ Animated.timing(slideAnim, {
135
+ toValue: 0,
136
+ duration: 300,
137
+ easing: Easing.out(Easing.quad),
138
+ useNativeDriver: true,
139
+ }).start(({ finished }) => {
140
+ if (finished) {
141
+ // go to the selected story and don't animate
142
+ scrollCallback({ animated: false, id: undefined });
143
+ }
144
+ });
145
+ }, [dragY, height, onVisibilityChange, scrollCallback, slideAnim]);
146
+
147
+ const closeDrawer = useCallback(() => {
148
+ Keyboard.dismiss();
149
+ onVisibilityChange?.(false);
150
+
151
+ Animated.timing(slideAnim, {
152
+ toValue: height,
153
+ duration: 300,
154
+ easing: Easing.in(Easing.quad),
155
+ useNativeDriver: true,
156
+ }).start(({ finished }) => {
157
+ if (finished) {
158
+ setIsVisible(false);
159
+ }
160
+ });
161
+ }, [height, onVisibilityChange, slideAnim]);
162
+
163
+ // Create the pan responder for handling drag gestures
164
+ const panResponder = useMemo(
165
+ () =>
166
+ PanResponder.create({
167
+ onStartShouldSetPanResponder: () => true,
168
+ onMoveShouldSetPanResponder: (_, gestureState) => {
169
+ // Only capture downward dragging motions
170
+ return gestureState.dy > 0;
171
+ },
172
+ onPanResponderMove: (_, gestureState) => {
173
+ // Update dragY based on the gesture
174
+ if (gestureState.dy > 0) {
175
+ dragY.setValue(gestureState.dy);
176
+ }
177
+ },
178
+ onPanResponderRelease: (_, gestureState) => {
179
+ if (gestureState.dy > 50) {
180
+ closeDrawer();
181
+ } else {
182
+ // Only snap back if not closing
183
+ Animated.timing(dragY, {
184
+ toValue: 0,
185
+ duration: 300,
186
+ easing: Easing.out(Easing.quad),
187
+ useNativeDriver: true,
188
+ }).start();
189
+ }
190
+ },
191
+ }),
192
+ [closeDrawer, dragY]
193
+ );
194
+
195
+ useImperativeHandle(ref, () => ({
196
+ setMobileMenuOpen: (open: boolean) => {
197
+ if (open) {
198
+ openDrawer();
199
+ } else {
200
+ closeDrawer();
201
+ }
202
+ },
203
+ }));
204
+
205
+ // Create the styles for the drag handle
206
+ const handleStyle = useMemo(
207
+ () => ({
208
+ width: 40,
209
+ height: 5,
210
+ backgroundColor: theme.color.mediumdark,
211
+ borderRadius: 2.5,
212
+ alignSelf: 'center' as const,
213
+ }),
214
+ [theme.color.mediumdark]
215
+ );
216
+
217
+ const drawerContainerStyle = useMemo(
218
+ () =>
219
+ ({
220
+ flex: 1,
221
+ borderTopColor: theme.appBorderColor,
222
+ borderTopWidth: 1,
223
+ borderStyle: 'solid' as const,
224
+ backgroundColor: theme.background.content,
225
+ elevation: 8,
226
+ boxShadow: `0 16px 32px 0 ${theme.color.border}`,
227
+ }) satisfies ViewStyle,
228
+ [theme.appBorderColor, theme.background.content, theme.color.border]
229
+ );
230
+
231
+ const dragHandleWrapperStyle = useMemo(
232
+ () => ({
233
+ alignItems: 'center' as const,
234
+ justifyContent: 'center' as const,
235
+ paddingBottom: 16,
236
+ paddingTop: 10,
237
+ backgroundColor: theme.background.content,
188
238
  }),
189
- [closeDrawer, dragY]
190
- );
191
-
192
- useImperativeHandle(ref, () => ({
193
- setMobileMenuOpen: (open: boolean) => {
194
- if (open) {
195
- openDrawer();
196
- } else {
197
- closeDrawer();
198
- }
199
- },
200
- }));
201
-
202
- // Create the styles for the drag handle
203
- const handleStyle = useMemo(
204
- () => ({
205
- width: 40,
206
- height: 5,
207
- backgroundColor: theme.color.mediumdark,
208
- borderRadius: 2.5,
209
- alignSelf: 'center' as const,
210
- }),
211
- [theme.color.mediumdark]
212
- );
213
-
214
- const drawerContainerStyle = useMemo(
215
- () =>
216
- ({
239
+ [theme.background.content]
240
+ );
241
+
242
+ const childrenWrapperStyle = useMemo(
243
+ () => ({
217
244
  flex: 1,
218
- borderTopColor: theme.appBorderColor,
219
- borderTopWidth: 1,
220
- borderStyle: 'solid' as const,
221
245
  backgroundColor: theme.background.content,
222
- elevation: 8,
223
- boxShadow: `0 16px 32px 0 ${theme.color.border}`,
224
- }) satisfies ViewStyle,
225
- [theme.appBorderColor, theme.background.content, theme.color.border]
226
- );
227
-
228
- const dragHandleWrapperStyle = useMemo(
229
- () => ({
230
- alignItems: 'center' as const,
231
- justifyContent: 'center' as const,
232
- paddingBottom: 16,
233
- paddingTop: 10,
234
- backgroundColor: theme.background.content,
235
- }),
236
- [theme.background.content]
237
- );
238
-
239
- const childrenWrapperStyle = useMemo(
240
- () => ({
241
- flex: 1,
242
- backgroundColor: theme.background.content,
243
- }),
244
- [theme.background.content]
245
- );
246
-
247
- return (
248
- <Portal hostName="storybook-lite-ui-root">
249
- <Animated.View
250
- style={[portalContainerStyle, { transform: [{ translateY: slideAnim }] }]}
251
- pointerEvents={isVisible ? 'auto' : 'none'}
252
- >
253
- <View style={flexStyle}>
254
- <Pressable style={flexStyle} onPress={closeDrawer} />
255
- </View>
246
+ }),
247
+ [theme.background.content]
248
+ );
256
249
 
250
+ return (
251
+ <Portal hostName="storybook-lite-ui-root">
257
252
  <Animated.View
258
- style={{
259
- height: animatedHeight,
260
- }}
253
+ style={[portalContainerStyle, { transform: [{ translateY: slideAnim }] }]}
254
+ pointerEvents={isVisible ? 'auto' : 'none'}
255
+ accessibilityElementsHidden={!isVisible}
256
+ importantForAccessibility={isVisible ? 'auto' : 'no-hide-descendants'}
257
+ accessibilityViewIsModal={isVisible}
261
258
  >
262
- <Animated.View style={[drawerContainerStyle, { transform: [{ translateY: dragY }] }]}>
263
- {/* Drag handle */}
264
- <View {...panResponder.panHandlers} style={dragHandleWrapperStyle}>
265
- <View style={handleStyle} />
266
- </View>
259
+ <View style={flexStyle}>
260
+ <Pressable
261
+ style={flexStyle}
262
+ onPress={closeDrawer}
263
+ accessibilityRole="button"
264
+ accessibilityLabel="Close story list"
265
+ />
266
+ </View>
267
+
268
+ <Animated.View
269
+ style={{
270
+ height: animatedHeight,
271
+ }}
272
+ >
273
+ <Animated.View style={[drawerContainerStyle, { transform: [{ translateY: dragY }] }]}>
274
+ {/* Drag handle */}
275
+ <View {...panResponder.panHandlers} style={dragHandleWrapperStyle}>
276
+ <View style={handleStyle} />
277
+ </View>
267
278
 
268
- <View style={childrenWrapperStyle}>{children}</View>
279
+ <View style={childrenWrapperStyle}>{children}</View>
280
+ </Animated.View>
269
281
  </Animated.View>
270
282
  </Animated.View>
271
- </Animated.View>
272
- </Portal>
273
- );
274
- })
283
+ </Portal>
284
+ );
285
+ }
286
+ )
275
287
  );
package/src/Search.tsx CHANGED
@@ -248,6 +248,8 @@ export const Search = React.memo<{
248
248
 
249
249
  {isOpen && (
250
250
  <ClearIcon
251
+ accessibilityRole="button"
252
+ accessibilityLabel="Clear search"
251
253
  onPress={() => {
252
254
  setInputValue('');
253
255
  inputRef.current.clear();
@@ -168,7 +168,12 @@ const Result: FC<SearchResultProps> = React.memo(function Result({
168
168
  const pathString = item.path?.join(' ') ?? '';
169
169
 
170
170
  return (
171
- <ResultRow {...props} onPress={press}>
171
+ <ResultRow
172
+ {...props}
173
+ onPress={press}
174
+ accessibilityRole="button"
175
+ accessibilityLabel={`${item.name}, ${item.path?.join(' / ') ?? ''}`}
176
+ >
172
177
  <IconWrapper>
173
178
  {item.type === 'component' && (
174
179
  <ComponentIcon width={14} height={14} color={theme.color.secondary} />
@@ -277,7 +282,10 @@ export const SearchResults: FC<{
277
282
  return (
278
283
  <RecentlyOpenedTitle>
279
284
  <Text>Recently opened</Text>
280
- <IconButton onPress={listItem.clearLastViewed} />
285
+ <IconButton
286
+ onPress={listItem.clearLastViewed}
287
+ accessibilityLabel="Clear recently opened"
288
+ />
281
289
  </RecentlyOpenedTitle>
282
290
  );
283
291
  case 'noResults':
package/src/Sidebar.tsx CHANGED
@@ -45,8 +45,20 @@ const Swap = React.memo(function Swap({
45
45
  // // NOTE: its important not to completely hide items so that we don't lose the state of our list items
46
46
  return (
47
47
  <>
48
- <View style={aStyle}>{a}</View>
49
- <View style={bStyle}>{b}</View>
48
+ <View
49
+ style={aStyle}
50
+ accessibilityElementsHidden={!condition}
51
+ importantForAccessibility={condition ? 'auto' : 'no-hide-descendants'}
52
+ >
53
+ {a}
54
+ </View>
55
+ <View
56
+ style={bStyle}
57
+ accessibilityElementsHidden={condition}
58
+ importantForAccessibility={condition ? 'no-hide-descendants' : 'auto'}
59
+ >
60
+ {b}
61
+ </View>
50
62
  </>
51
63
  );
52
64
  });
@@ -54,6 +54,8 @@ const BrandLogo: FC<{ theme: Theme }> = ({ theme }) => {
54
54
  onPress={() => {
55
55
  if (theme.brand.url) Linking.openURL(theme.brand.url);
56
56
  }}
57
+ accessibilityRole="link"
58
+ accessibilityLabel={theme.brand.title ?? 'Brand logo'}
57
59
  >
58
60
  {image}
59
61
  </TouchableOpacity>
@@ -85,6 +87,8 @@ const BrandTitle: FC<{ theme: Theme }> = ({ theme }) => {
85
87
  onPress={() => {
86
88
  if (theme.brand.url) Linking.openURL(theme.brand.url);
87
89
  }}
90
+ accessibilityRole="link"
91
+ accessibilityLabel={theme.brand.title}
88
92
  >
89
93
  {title}
90
94
  </TouchableOpacity>
package/src/Tree.tsx CHANGED
@@ -62,7 +62,7 @@ export const Node = React.memo<NodeProps>(function Node({
62
62
 
63
63
  if (item.type === 'story') {
64
64
  return (
65
- <LeafNodeStyleWrapper>
65
+ <LeafNodeStyleWrapper accessible={false}>
66
66
  <StoryNode
67
67
  selected={isSelected}
68
68
  key={id}
@@ -88,6 +88,7 @@ export const Node = React.memo<NodeProps>(function Node({
88
88
  event.preventDefault();
89
89
  setExpanded({ ids: [item.id], value: !isExpanded });
90
90
  }}
91
+ accessibilityRole="button"
91
92
  aria-expanded={isExpanded}
92
93
  >
93
94
  <CollapseIcon isExpanded={isExpanded} />
package/src/TreeNode.tsx CHANGED
@@ -96,7 +96,7 @@ export const GroupNode: FC<
96
96
  }, [theme.base, theme.color.primary, theme.color.ultraviolet]);
97
97
 
98
98
  return (
99
- <BranchNode isExpandable={isExpandable} {...props}>
99
+ <BranchNode isExpandable={isExpandable} accessibilityRole="button" {...props}>
100
100
  <Wrapper key={`group-${props.id}-${color}`}>
101
101
  {isExpandable && <CollapseIcon isExpanded={isExpanded} />}
102
102
  <GroupIcon width={14} height={14} color={color} />
@@ -115,7 +115,7 @@ export const ComponentNode: FC<ComponentProps<typeof BranchNode>> = React.memo(
115
115
  }, [theme.color.secondary]);
116
116
 
117
117
  return (
118
- <BranchNode isExpandable={isExpandable} {...props}>
118
+ <BranchNode isExpandable={isExpandable} accessibilityRole="button" {...props}>
119
119
  {/* workaround for macos icon color bug */}
120
120
  <Wrapper key={`component-${props.id}-${color}`}>
121
121
  {isExpandable && <CollapseIcon isExpanded={isExpanded} />}
@@ -139,7 +139,7 @@ export const StoryNode = React.memo(
139
139
  }, [props.selected, theme.color.lightest, theme.color.seafoam]);
140
140
 
141
141
  return (
142
- <LeafNode {...props} ref={ref}>
142
+ <LeafNode {...props} ref={ref} accessibilityRole="button">
143
143
  <Wrapper key={`story-${props.id}-${color}`}>
144
144
  <StoryIcon width={14} height={14} color={color} />
145
145
  </Wrapper>