[DevTools] Show list of named Activities in Suspense tab (#35092)
Sebastian "Sebbie" Silbermann committed
Nov 18, 2025 at 09:52 UTC
7f1a085b282d30dbb151f40c41bd53fc9045deb1
7 files changed
+221
-99
packages/react-devtools-shared/src/devtools/store.js
+27
@@ -1058,6 +1058,33 @@ export default class Store extends EventEmitter<{
1058
return timeline;
1059
}
1060
1061
+ getActivities(): Array<{id: Element['id'], depth: number}> {
1062
+ const target: Array<{id: Element['id'], depth: number}> = [];
1063
+ // TODO: Keep a live tree in the backend so we don't need to recalculate
1064
+ // this each time while also including filtered Activities.
1065
+ this._pushActivitiesInDocumentOrder(this.roots, target, 0);
1066
+ return target;
1067
+ }
1068
+
1069
+ _pushActivitiesInDocumentOrder(
1070
+ children: $ReadOnlyArray<Element['id']>,
1071
+ target: Array<{id: Element['id'], depth: number}>,
1072
+ depth: number,
1073
+ ): void {
1074
+ for (let i = 0; i < children.length; i++) {
1075
+ const child = this._idToElement.get(children[i]);
1076
+ if (child === undefined) {
1077
+ continue;
1078
+ }
1079
+ if (child.type === ElementTypeActivity && child.nameProp !== null) {
1080
+ target.push({id: child.id, depth});
1081
+ this._pushActivitiesInDocumentOrder(child.children, target, depth + 1);
1082
+ } else {
1083
+ this._pushActivitiesInDocumentOrder(child.children, target, depth);
1084
+ }
1085
+ }
1086
+ }
1087
+
1088
getRendererIDForElement(id: number): number | null {
1089
let current = this._idToElement.get(id);
1090
while (current !== undefined) {
packages/react-devtools-shared/src/devtools/views/Components/TreeContext.js
+6
-1
@@ -59,6 +59,7 @@ export type StateContext = {
59
60
// Activity slice
61
activityID: Element['id'] | null,
62
+ activities: $ReadOnlyArray<{id: Element['id'], depth: number}>,
63
64
// Inspection element panel
65
inspectedElementID: number | null,
@@ -172,6 +173,7 @@ type State = {
173
174
// Activity slice
175
activityID: Element['id'] | null,
176
+ activities: $ReadOnlyArray<{id: Element['id'], depth: number}>,
177
178
// Inspection element panel
179
inspectedElementID: number | null,
@@ -809,6 +811,7 @@ function reduceActivityState(
811
case 'HANDLE_STORE_MUTATION':
812
let {activityID} = state;
813
const [, , activitySliceIDChange] = action.payload;
814
+ const activities = store.getActivities();
815
if (activitySliceIDChange === 0 && activityID !== null) {
816
activityID = null;
817
} else if (
@@ -817,10 +820,11 @@ function reduceActivityState(
820
) {
821
activityID = activitySliceIDChange;
822
}
820
- if (activityID !== state.activityID) {
823
+ if (activityID !== state.activityID || activities !== state.activities) {
824
return {
825
...state,
826
activityID,
827
+ activities,
828
};
829
}
830
}
@@ -863,6 +867,7 @@ function getInitialState({
867
868
// Activity slice
869
activityID: null,
870
+ activities: store.getActivities(),
871
872
// Inspection element panel
873
inspectedElementID:
packages/react-devtools-shared/src/devtools/views/SuspenseTab/ActivityList.css
+17
-4
@@ -1,20 +1,33 @@
1
-.ActivityList {
1
+.ActivityListContaier {
2
+ display: flex;
3
+ flex-direction: column;
4
+}
5
+
6
+.ActivityListHeader {
7
+ /* even if empty, provides layout alignment with the main view */
8
+ display: flex;
9
+ flex: 0 0 42px;
10
+ border-bottom: 1px solid var(--color-border);
11
+}
12
+
13
+.ActivityListList {
14
cursor: default;
15
list-style-type: none;
16
margin: 0;
17
padding: 0;
18
}
19
8
-.ActivityList[data-pending-activity-slice-selection="true"] {
20
+.ActivityListList[data-pending-activity-slice-selection="true"] {
21
cursor: wait;
22
}
23
12
-.ActivityList:focus {
24
+.ActivityListList:focus {
25
outline: none;
26
}
27
28
.ActivityListItem {
29
color: var(--color-component-name);
30
+ line-height: var(--line-height-data);
31
padding: 0 0.25rem;
32
user-select: none;
33
}
@@ -27,7 +40,7 @@
40
background-color: var(--color-background-inactive);
41
}
42
30
-.ActivityList:focus .ActivityListItem[aria-selected="true"] {
43
+.ActivityListList:focus .ActivityListItem[aria-selected="true"] {
44
background-color: var(--color-background-selected);
45
color: var(--color-text-selected);
46
packages/react-devtools-shared/src/devtools/views/SuspenseTab/ActivityList.js
+108
-27
@@ -15,10 +15,14 @@ import typeof {
15
SyntheticMouseEvent,
16
SyntheticKeyboardEvent,
17
} from 'react-dom-bindings/src/events/SyntheticEvent';
18
+import type Store from 'react-devtools-shared/src/devtools/store';
19
20
import * as React from 'react';
20
-import {useContext, useTransition} from 'react';
21
-import {ComponentFilterActivitySlice} from 'react-devtools-shared/src/frontend/types';
21
+import {useContext, useMemo, useTransition} from 'react';
22
+import {
23
+ ComponentFilterActivitySlice,
24
+ ElementTypeActivity,
25
+} from 'react-devtools-shared/src/frontend/types';
26
import styles from './ActivityList.css';
27
import {
28
TreeStateContext,
@@ -26,6 +30,8 @@ import {
30
} from '../Components/TreeContext';
31
import {useHighlightHostInstance} from '../hooks';
32
import {StoreContext} from '../context';
33
+import ButtonIcon from '../ButtonIcon';
34
+import Button from '../Button';
35
36
export function useChangeActivitySliceAction(): (
37
id: Element['id'] | null,
@@ -62,15 +68,49 @@ export function useChangeActivitySliceAction(): (
68
return changeActivitySliceAction;
69
}
70
71
+function findNearestActivityParentID(
72
+ elementID: Element['id'],
73
+ store: Store,
74
+): Element['id'] | null {
75
+ let currentID: null | Element['id'] = elementID;
76
+ while (currentID !== null) {
77
+ const element = store.getElementByID(currentID);
78
+ if (element === null) {
79
+ return null;
80
+ }
81
+ if (element.type === ElementTypeActivity) {
82
+ return element.id;
83
+ }
84
+ currentID = element.parentID;
85
+ }
86
+
87
+ return currentID;
88
+}
89
+
90
+function useSelectedActivityID(): Element['id'] | null {
91
+ const {inspectedElementID} = useContext(TreeStateContext);
92
+ const store = useContext(StoreContext);
93
+ return useMemo(() => {
94
+ if (inspectedElementID === null) {
95
+ return null;
96
+ }
97
+ const nearestActivityID = findNearestActivityParentID(
98
+ inspectedElementID,
99
+ store,
100
+ );
101
+ return nearestActivityID;
102
+ }, [inspectedElementID, store]);
103
+}
104
+
105
export default function ActivityList({
106
activities,
107
}: {
68
- activities: $ReadOnlyArray<Element>,
108
+ activities: $ReadOnlyArray<{id: Element['id'], depth: number}>,
109
}): React$Node {
70
- const {inspectedElementID} = useContext(TreeStateContext);
110
+ const {activityID, inspectedElementID} = useContext(TreeStateContext);
111
const treeDispatch = useContext(TreeDispatcherContext);
72
- // TODO: Derive from inspected element
73
- const selectedActivityID = inspectedElementID;
112
+ const store = useContext(StoreContext);
113
+ const selectedActivityID = useSelectedActivityID();
114
const {highlightHostInstance, clearHighlightHostInstance} =
115
useHighlightHostInstance();
116
@@ -79,8 +119,13 @@ export default function ActivityList({
119
const changeActivitySliceAction = useChangeActivitySliceAction();
120
121
function handleKeyDown(event: SyntheticKeyboardEvent) {
82
- // TODO: Implement keyboard navigation
122
switch (event.key) {
123
+ case 'Escape':
124
+ startActivitySliceSelection(() => {
125
+ changeActivitySliceAction(null);
126
+ });
127
+ event.preventDefault();
128
+ break;
129
case 'Enter':
130
case ' ':
131
if (inspectedElementID !== null) {
@@ -149,25 +194,61 @@ export default function ActivityList({
194
}
195
196
return (
152
- <ol
153
- role="listbox"
154
- className={styles.ActivityList}
155
- data-pending-activity-slice-selection={isPendingActivitySliceSelection}
156
- tabIndex={0}
157
- onKeyDown={handleKeyDown}>
158
- {activities.map(activity => (
159
- <li
160
- key={activity.id}
161
- role="option"
162
- aria-selected={activity.id === selectedActivityID ? 'true' : 'false'}
163
- className={styles.ActivityListItem}
164
- onClick={handleClick.bind(null, activity.id)}
165
- onDoubleClick={handleDoubleClick}
166
- onPointerOver={highlightHostInstance.bind(null, activity.id, false)}
167
- onPointerLeave={clearHighlightHostInstance}>
168
- {activity.nameProp}
169
- </li>
170
- ))}
171
- </ol>
197
+ <div className={styles.ActivityListContaier}>
198
+ <div className={styles.ActivityListHeader}>
199
+ {activityID !== null && (
200
+ // TODO: Obsolete once filtered Activities are included in this list.
201
+ <Button
202
+ onClick={startActivitySliceSelection.bind(
203
+ null,
204
+ changeActivitySliceAction.bind(null, null),
205
+ )}
206
+ title="Back to full tree view">
207
+ <ButtonIcon type="previous" />
208
+ </Button>
209
+ )}
210
+ </div>
211
+ <ol
212
+ role="listbox"
213
+ className={styles.ActivityListList}
214
+ data-pending-activity-slice-selection={isPendingActivitySliceSelection}
215
+ tabIndex={0}
216
+ onKeyDown={handleKeyDown}>
217
+ {activities.map(({id, depth}) => {
218
+ const activity = store.getElementByID(id);
219
+ if (activity === null) {
220
+ return null;
221
+ }
222
+ const name = activity.nameProp;
223
+ if (name === null) {
224
+ // This shouldn't actually happen. We only want to show activities with a name.
225
+ // And hide the whole list if no named Activities are present.
226
+ return null;
227
+ }
228
+
229
+ // TODO: Filtered Activities should have dedicated styles once we include
230
+ // filtered Activities in this list.
231
+ return (
232
+ <li
233
+ key={activity.id}
234
+ role="option"
235
+ aria-selected={
236
+ activity.id === selectedActivityID ? 'true' : 'false'
237
+ }
238
+ className={styles.ActivityListItem}
239
+ onClick={handleClick.bind(null, activity.id)}
240
+ onDoubleClick={handleDoubleClick}
241
+ onPointerOver={highlightHostInstance.bind(
242
+ null,
243
+ activity.id,
244
+ false,
245
+ )}
246
+ onPointerLeave={clearHighlightHostInstance}>
247
+ {'\u00A0'.repeat(depth) + name}
248
+ </li>
249
+ );
250
+ })}
251
+ </ol>
252
+ </div>
253
);
254
}
packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseTab.css
+1
-1
@@ -92,7 +92,7 @@
92
}
93
94
.ActivityList {
95
- flex: 0 0 var(--horizontal-resize-tree-list-percentage);
95
+ flex: 0 0 var(--horizontal-resize-activity-list-percentage);;
96
border-right: 1px solid var(--color-border);
97
overflow: auto;
98
}
packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseTab.js
+58
-62
@@ -6,14 +6,11 @@
6
*
7
* @flow
8
*/
9
-import type {Element} from 'react-devtools-shared/src/frontend/types';
10
-
9
import * as React from 'react';
10
import {
11
useContext,
12
useEffect,
13
useLayoutEffect,
16
- useMemo,
14
useReducer,
15
useRef,
16
Fragment,
@@ -44,12 +41,13 @@ import typeof {SyntheticPointerEvent} from 'react-dom-bindings/src/events/Synthe
41
import SettingsModal from 'react-devtools-shared/src/devtools/views/Settings/SettingsModal';
42
import SettingsModalContextToggle from 'react-devtools-shared/src/devtools/views/Settings/SettingsModalContextToggle';
43
import {SettingsModalContextController} from 'react-devtools-shared/src/devtools/views/Settings/SettingsModalContext';
44
+import {TreeStateContext} from '../Components/TreeContext';
45
46
type Orientation = 'horizontal' | 'vertical';
47
48
type LayoutActionType =
51
- | 'ACTION_SET_TREE_LIST_TOGGLE'
52
- | 'ACTION_SET_TREE_LIST_HORIZONTAL_FRACTION'
49
+ | 'ACTION_SET_ACTIVITY_LIST_TOGGLE'
50
+ | 'ACTION_SET_ACTIVITY_LIST_HORIZONTAL_FRACTION'
51
| 'ACTION_SET_INSPECTED_ELEMENT_TOGGLE'
52
| 'ACTION_SET_INSPECTED_ELEMENT_HORIZONTAL_FRACTION'
53
| 'ACTION_SET_INSPECTED_ELEMENT_VERTICAL_FRACTION';
@@ -59,8 +57,8 @@ type LayoutAction = {
57
};
58
59
type LayoutState = {
62
- treeListHidden: boolean,
63
- treeListHorizontalFraction: number,
60
+ activityListHidden: boolean,
61
+ activityListHorizontalFraction: number,
62
inspectedElementHidden: boolean,
63
inspectedElementHorizontalFraction: number,
64
inspectedElementVerticalFraction: number,
@@ -97,7 +95,7 @@ function ToggleUniqueSuspenders() {
95
);
96
}
97
100
-function ToggleTreeList({
98
+function ToggleActivityList({
99
dispatch,
100
state,
101
}: {
@@ -108,13 +106,15 @@ function ToggleTreeList({
106
<Button
107
onClick={() =>
108
dispatch({
111
- type: 'ACTION_SET_TREE_LIST_TOGGLE',
109
+ type: 'ACTION_SET_ACTIVITY_LIST_TOGGLE',
110
payload: null,
111
})
112
}
115
- title={state.treeListHidden ? 'Show Tree List' : 'Hide Tree List'}>
113
+ title={
114
+ state.activityListHidden ? 'Show Activity List' : 'Hide Activity List'
115
+ }>
116
<ButtonIcon
117
- type={state.treeListHidden ? 'panel-left-open' : 'panel-left-close'}
117
+ type={state.activityListHidden ? 'panel-left-open' : 'panel-left-close'}
118
/>
119
</Button>
120
);
@@ -272,17 +272,6 @@ function SynchronizedScrollContainer({
272
);
273
}
274
275
-// TODO: Get this from the store directly.
276
-// The backend needs to keep a separate tree so that resuspending keeps Activity around.
277
-function useActivities(): $ReadOnlyArray<Element> {
278
- const activities = useMemo(() => {
279
- const items: Array<Element> = [];
280
- return items;
281
- }, []);
282
-
283
- return activities;
284
-}
285
-
275
function SuspenseTab(_: {}) {
276
const store = useContext(StoreContext);
277
const {hideSettings} = useContext(OptionsContext);
@@ -292,14 +281,14 @@ function SuspenseTab(_: {}) {
281
initLayoutState,
282
);
283
295
- const activities = useActivities();
284
+ const {activities} = useContext(TreeStateContext);
285
// If there are no named Activity boundaries, we don't have any tree list and we should hide
286
// both the panel and the button to toggle it.
298
- const treeListDisabled = activities.length === 0;
287
+ const activityListDisabled = activities.length === 0;
288
289
const wrapperTreeRef = useRef<null | HTMLElement>(null);
290
const resizeTreeRef = useRef<null | HTMLElement>(null);
302
- const resizeTreeListRef = useRef<null | HTMLElement>(null);
291
+ const resizeActivityListRef = useRef<null | HTMLElement>(null);
292
293
// TODO: We'll show the recently inspected element in this tab when it should probably
294
// switch to the nearest Suspense boundary when we switch into this tab.
@@ -308,8 +297,8 @@ function SuspenseTab(_: {}) {
297
inspectedElementHidden,
298
inspectedElementHorizontalFraction,
299
inspectedElementVerticalFraction,
311
- treeListHidden,
312
- treeListHorizontalFraction,
300
+ activityListHidden,
301
+ activityListHorizontalFraction,
302
} = state;
303
304
useLayoutEffect(() => {
@@ -328,12 +317,12 @@ function SuspenseTab(_: {}) {
317
inspectedElementVerticalFraction * 100,
318
);
319
331
- const resizeTreeListElement = resizeTreeListRef.current;
320
+ const resizeActivityListElement = resizeActivityListRef.current;
321
setResizeCSSVariable(
333
- resizeTreeListElement,
334
- 'tree-list',
322
+ resizeActivityListElement,
323
+ 'activity-list',
324
'horizontal',
336
- treeListHorizontalFraction * 100,
325
+ activityListHorizontalFraction * 100,
326
);
327
}, []);
328
useEffect(() => {
@@ -344,8 +333,8 @@ function SuspenseTab(_: {}) {
333
inspectedElementHidden,
334
inspectedElementHorizontalFraction,
335
inspectedElementVerticalFraction,
347
- treeListHidden,
348
- treeListHorizontalFraction,
336
+ activityListHidden,
337
+ activityListHorizontalFraction,
338
}),
339
);
340
}, 500);
@@ -355,8 +344,8 @@ function SuspenseTab(_: {}) {
344
inspectedElementHidden,
345
inspectedElementHorizontalFraction,
346
inspectedElementVerticalFraction,
358
- treeListHidden,
359
- treeListHorizontalFraction,
347
+ activityListHidden,
348
+ activityListHorizontalFraction,
349
]);
350
351
const onResizeStart = (event: SyntheticPointerEvent) => {
@@ -420,14 +409,14 @@ function SuspenseTab(_: {}) {
409
}
410
};
411
423
- const onResizeTreeList = (event: SyntheticPointerEvent) => {
412
+ const onResizeActivityList = (event: SyntheticPointerEvent) => {
413
const element = event.currentTarget;
414
const isResizing = element.hasPointerCapture(event.pointerId);
415
if (!isResizing) {
416
return;
417
}
418
430
- const resizeElement = resizeTreeListRef.current;
419
+ const resizeElement = resizeActivityListRef.current;
420
const wrapperElement = resizeTreeRef.current;
421
422
if (wrapperElement === null || resizeElement === null) {
@@ -443,11 +432,11 @@ function SuspenseTab(_: {}) {
432
const currentMousePosition =
433
orientation === 'horizontal' ? event.clientX - left : event.clientY - top;
434
446
- const boundaryMin = MINIMUM_TREE_LIST_SIZE;
435
+ const boundaryMin = MINIMUM_ACTIVITY_LIST_SIZE;
436
const boundaryMax =
437
orientation === 'horizontal'
449
- ? width - MINIMUM_TREE_LIST_SIZE
450
- : height - MINIMUM_TREE_LIST_SIZE;
438
+ ? width - MINIMUM_ACTIVITY_LIST_SIZE
439
+ : height - MINIMUM_ACTIVITY_LIST_SIZE;
440
441
const isMousePositionInBounds =
442
currentMousePosition > boundaryMin && currentMousePosition < boundaryMax;
@@ -455,10 +444,15 @@ function SuspenseTab(_: {}) {
444
if (isMousePositionInBounds) {
445
const resizedElementDimension =
446
orientation === 'horizontal' ? width : height;
458
- const actionType = 'ACTION_SET_TREE_LIST_HORIZONTAL_FRACTION';
447
+ const actionType = 'ACTION_SET_ACTIVITY_LIST_HORIZONTAL_FRACTION';
448
const percentage = (currentMousePosition / resizedElementDimension) * 100;
449
461
- setResizeCSSVariable(resizeElement, 'tree-list', orientation, percentage);
450
+ setResizeCSSVariable(
451
+ resizeElement,
452
+ 'activity-list',
453
+ orientation,
454
+ percentage,
455
+ );
456
457
dispatch({
458
type: actionType,
@@ -473,19 +467,21 @@ function SuspenseTab(_: {}) {
467
<SettingsModalContextController>
468
<div className={styles.SuspenseTab} ref={wrapperTreeRef}>
469
<div className={styles.TreeWrapper} ref={resizeTreeRef}>
476
- {treeListDisabled ? null : (
470
+ {activityListDisabled ? null : (
471
<div
472
className={styles.ActivityList}
479
- hidden={treeListHidden}
480
- ref={resizeTreeListRef}>
473
+ hidden={activityListHidden}
474
+ ref={resizeActivityListRef}>
475
<ActivityList activities={activities} />
476
</div>
477
)}
484
- {treeListDisabled ? null : (
485
- <div className={styles.ResizeBarWrapper} hidden={treeListHidden}>
478
+ {activityListDisabled ? null : (
479
+ <div
480
+ className={styles.ResizeBarWrapper}
481
+ hidden={activityListHidden}>
482
<div
483
onPointerDown={onResizeStart}
488
- onPointerMove={onResizeTreeList}
484
+ onPointerMove={onResizeActivityList}
485
onPointerUp={onResizeEnd}
486
className={styles.ResizeBar}
487
/>
@@ -493,10 +489,10 @@ function SuspenseTab(_: {}) {
489
)}
490
<div className={styles.TreeView}>
491
<header className={styles.SuspenseTreeViewHeader}>
496
- {treeListDisabled ? (
492
+ {activityListDisabled ? (
493
<div />
494
) : (
499
- <ToggleTreeList dispatch={dispatch} state={state} />
495
+ <ToggleActivityList dispatch={dispatch} state={state} />
496
)}
497
{store.supportsClickToInspect && (
498
<Fragment>
@@ -559,19 +555,19 @@ function SuspenseTab(_: {}) {
555
const LOCAL_STORAGE_KEY = 'React::DevTools::SuspenseTab::layout';
556
const VERTICAL_TREE_MODE_MAX_WIDTH = 600;
557
const MINIMUM_TREE_SIZE = 100;
562
-const MINIMUM_TREE_LIST_SIZE = 100;
558
+const MINIMUM_ACTIVITY_LIST_SIZE = 100;
559
560
function layoutReducer(state: LayoutState, action: LayoutAction): LayoutState {
561
switch (action.type) {
566
- case 'ACTION_SET_TREE_LIST_TOGGLE':
562
+ case 'ACTION_SET_ACTIVITY_LIST_TOGGLE':
563
return {
564
...state,
569
- treeListHidden: !state.treeListHidden,
565
+ activityListHidden: !state.activityListHidden,
566
};
571
- case 'ACTION_SET_TREE_LIST_HORIZONTAL_FRACTION':
567
+ case 'ACTION_SET_ACTIVITY_LIST_HORIZONTAL_FRACTION':
568
return {
569
...state,
574
- treeListHorizontalFraction: action.payload,
570
+ activityListHorizontalFraction: action.payload,
571
};
572
case 'ACTION_SET_INSPECTED_ELEMENT_TOGGLE':
573
return {
@@ -597,8 +593,8 @@ function initLayoutState(): LayoutState {
593
let inspectedElementHidden = false;
594
let inspectedElementHorizontalFraction = 0.65;
595
let inspectedElementVerticalFraction = 0.5;
600
- let treeListHidden = false;
601
- let treeListHorizontalFraction = 0.35;
596
+ let activityListHidden = false;
597
+ let activityListHorizontalFraction = 0.35;
598
599
try {
600
let data = localStorageGetItem(LOCAL_STORAGE_KEY);
@@ -608,8 +604,8 @@ function initLayoutState(): LayoutState {
604
inspectedElementHorizontalFraction =
605
data.inspectedElementHorizontalFraction;
606
inspectedElementVerticalFraction = data.inspectedElementVerticalFraction;
611
- treeListHidden = data.treeListHidden;
612
- treeListHorizontalFraction = data.treeListHorizontalFraction;
607
+ activityListHidden = data.activityListHidden;
608
+ activityListHorizontalFraction = data.activityListHorizontalFraction;
609
}
610
} catch (error) {}
611
@@ -617,8 +613,8 @@ function initLayoutState(): LayoutState {
613
inspectedElementHidden,
614
inspectedElementHorizontalFraction,
615
inspectedElementVerticalFraction,
620
- treeListHidden,
621
- treeListHorizontalFraction,
616
+ activityListHidden,
617
+ activityListHorizontalFraction,
618
};
619
}
620
@@ -634,7 +630,7 @@ function getTreeOrientation(
630
631
function setResizeCSSVariable(
632
resizeElement: null | HTMLElement,
637
- name: 'tree' | 'tree-list',
633
+ name: 'tree' | 'activity-list',
634
orientation: null | Orientation,
635
percentage: number,
636
): void {
packages/react-devtools-shell/src/app/Segments/index.js
+4
-4
@@ -77,13 +77,13 @@ function Root({children}: {children: React.Node}): React.Node {
77
78
export default function Segments(): React.Node {
79
return (
80
- <React.Activity name="/" mode="visible">
80
+ <React.Activity name="root" mode="visible">
81
<Root>
82
- <React.Activity name="/outer/" mode="visible">
82
+ <React.Activity name="outer" mode="visible">
83
<OuterSegment>
84
- <React.Activity name="/outer/inner" mode="visible">
84
+ <React.Activity name="inner" mode="visible">
85
<InnerSegment>
86
- <React.Activity name="/outer/inner/page" mode="visible">
86
+ <React.Activity name="slot" mode="visible">
87
<Page />
88
</React.Activity>
89
</InnerSegment>