Skip to content

Commit 45f189b

Browse files
committed
[devtool] optimize segement explorer tree view
1 parent 4e71be3 commit 45f189b

File tree

2 files changed

+44
-108
lines changed

2 files changed

+44
-108
lines changed

packages/next/src/client/components/react-dev-overlay/ui/components/overview/segment-explorer.tsx

Lines changed: 32 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -9,46 +9,6 @@ import {
99
} from '../../../../../../shared/lib/devtool/app-segment-tree'
1010
import type { Trie, TrieNode } from '../../../../../../shared/lib/devtool/trie'
1111

12-
const IconLayout = (props: React.SVGProps<SVGSVGElement>) => {
13-
return (
14-
<svg
15-
{...props}
16-
viewBox="0 0 16 16"
17-
fill="none"
18-
xmlns="http://www.w3.org/2000/svg"
19-
>
20-
<path
21-
d="M16 12.5L15.9873 12.7559C15.8677 13.9323 14.9323 14.8677 13.7559 14.9873L13.5 15H2.5L2.24414 14.9873C1.06772 14.8677 0.132274 13.9323 0.0126953 12.7559L0 12.5V1H16V12.5ZM1.5 6.25488V12.5C1.5 13.0523 1.94772 13.5 2.5 13.5H4.99512V6.25488H1.5ZM6.24512 6.25488V13.5H13.5C14.0523 13.5 14.5 13.0523 14.5 12.5V6.25488H6.24512ZM1.5 5.00488H14.5V2.5H1.5V5.00488Z"
22-
fill="currentColor"
23-
/>
24-
</svg>
25-
)
26-
}
27-
28-
const IconPage = (props: React.SVGProps<SVGSVGElement>) => {
29-
return (
30-
<svg
31-
{...props}
32-
viewBox="0 0 16 16"
33-
fill="none"
34-
strokeLinejoin="round"
35-
xmlns="http://www.w3.org/2000/svg"
36-
>
37-
<path
38-
fillRule="evenodd"
39-
clipRule="evenodd"
40-
d="M14.5 6.5V13.5C14.5 14.8807 13.3807 16 12 16H4C2.61929 16 1.5 14.8807 1.5 13.5V1.5V0H3H8H9.08579C9.351 0 9.60536 0.105357 9.79289 0.292893L14.2071 4.70711C14.3946 4.89464 14.5 5.149 14.5 5.41421V6.5ZM13 6.5V13.5C13 14.0523 12.5523 14.5 12 14.5H4C3.44772 14.5 3 14.0523 3 13.5V1.5H8V5V6.5H9.5H13ZM9.5 2.12132V5H12.3787L9.5 2.12132Z"
41-
fill="currentColor"
42-
/>
43-
</svg>
44-
)
45-
}
46-
47-
const ICONS = {
48-
layout: <IconLayout width={16} />,
49-
page: <IconPage width={16} />,
50-
}
51-
5212
function PageSegmentTree({ tree }: { tree: Trie<SegmentNode> | undefined }) {
5313
if (!tree) {
5414
return null
@@ -63,6 +23,7 @@ function PageSegmentTree({ tree }: { tree: Trie<SegmentNode> | undefined }) {
6323
node={tree.getRoot()}
6424
level={0}
6525
segment=""
26+
parentSegment=""
6627
/>
6728
</div>
6829
)
@@ -71,11 +32,13 @@ function PageSegmentTree({ tree }: { tree: Trie<SegmentNode> | undefined }) {
7132
function PageSegmentTreeLayerPresentation({
7233
tree,
7334
segment,
35+
parentSegment,
7436
node,
7537
level,
7638
}: {
7739
tree: Trie<SegmentNode>
7840
segment: string
41+
parentSegment: string
7942
node: TrieNode<SegmentNode>
8043
level: number
8144
}) {
@@ -97,6 +60,12 @@ function PageSegmentTreeLayerPresentation({
9760
return a.localeCompare(b)
9861
})
9962

63+
// check if it has file children
64+
const hasFileChildren = sortedChildrenKeys.some((key) => {
65+
const childNode = node.children[key]
66+
return !!childNode?.value?.type
67+
})
68+
10069
return (
10170
<div
10271
className="segment-explorer-item"
@@ -106,38 +75,28 @@ function PageSegmentTreeLayerPresentation({
10675
<div className={cx('segment-explorer-item-row')}>
10776
<div className="segment-explorer-line">
10877
<div className={`segment-explorer-line-text-${nodeName}`}>
109-
<span
110-
className={cx(
111-
'segment-explorer-line-icon',
112-
`segment-explorer-line-icon-${nodeName}`
113-
)}
114-
>
115-
{nodeName === 'layout' ? ICONS.layout : ICONS.page}
116-
</span>
117-
<span className="segment-explorer-filename-path">{fileName}</span>
118-
</div>
119-
</div>
120-
</div>
121-
) : segment ? (
122-
<div className={'segment-explorer-item-row'}>
123-
<div className="segment-explorer-line">
124-
<div className={`segment-explorer-line-text-${nodeName}`}>
125-
<span
126-
className={cx(
127-
'segment-explorer-line-icon',
128-
`segment-explorer-line-icon-${nodeName}`
78+
<div className="segment-explorer-filename">
79+
{parentSegment && (
80+
<span className="segment-explorer-filename--path">
81+
{parentSegment}
82+
</span>
12983
)}
130-
></span>
131-
<span className="segment-explorer-filename-path">
132-
{`${segment}/`}
133-
</span>
84+
<span className="segment-explorer-filename--name">
85+
{fileName}
86+
</span>
87+
</div>
13488
</div>
13589
</div>
13690
</div>
13791
) : null}
13892

13993
<div
140-
className="segment-explorer-segment-children"
94+
className={cx(
95+
'segment-explorer-children',
96+
// If it's children levels, show indents if there's any file at that level.
97+
// Otherwise it's empty folder, no need to show indents.
98+
level > 0 && hasFileChildren && 'segment-explorer-children--intended'
99+
)}
141100
data-nextjs-devtool-segment-explorer-level={level}
142101
>
143102
{sortedChildrenKeys.map((childSegment) => {
@@ -147,6 +106,7 @@ function PageSegmentTreeLayerPresentation({
147106
<PageSegmentTreeLayerPresentation
148107
key={childSegment}
149108
segment={childSegment}
109+
parentSegment={segment}
150110
tree={tree}
151111
node={child}
152112
level={level + 1}
@@ -188,36 +148,23 @@ export const DEV_TOOLS_INFO_RENDER_FILES_STYLES = css`
188148
padding: 2px 0;
189149
}
190150
191-
[data-nextjs-devtool-segment-explorer-level].segment-explorer-segment-children {
192-
padding-left: 20px;
193-
}
194-
[data-nextjs-devtool-segment-explorer-level='0'].segment-explorer-segment-children {
195-
padding-left: 0px;
151+
.segment-explorer-children--intended {
152+
padding-left: 16px;
196153
}
197154
198-
.segment-explorer-filename-path {
199-
display: inline-block;
155+
.segment-explorer-filename--path {
156+
margin-right: 8px;
200157
}
201-
202-
.segment-explorer-filename-path a {
203-
color: inherit;
204-
text-decoration: inherit;
158+
.segment-explorer-filename--name {
159+
color: var(--color-gray-800);
205160
}
206161
207162
.segment-explorer-line {
208163
white-space: pre;
209164
cursor: default;
210165
}
211166
212-
.segment-explorer-line-icon {
213-
margin-right: 4px;
214-
}
215-
.segment-explorer-line-icon-page {
216-
color: inherit;
217-
}
218-
219-
.segment-explorer-line-text-page {
167+
.segment-explorer-line {
220168
color: var(--color-gray-1000);
221-
font-weight: 500;
222169
}
223170
`

test/development/app-dir/segment-explorer/segment-explorer.test.ts

Lines changed: 12 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -26,35 +26,24 @@ describe('segment-explorer', () => {
2626
it('should render the segment explorer for parallel routes', async () => {
2727
const browser = await next.browser('/parallel-routes')
2828
expect(await getSegmentExplorerContent(browser)).toMatchInlineSnapshot(`
29-
"app/
30-
layout.tsx
31-
parallel-routes/
32-
layout.tsx
33-
page.tsx
34-
@bar/
35-
layout.tsx
36-
page.tsx
37-
@foo/
38-
layout.tsx
39-
page.tsx"
29+
"applayout.tsx
30+
parallel-routeslayout.tsx
31+
parallel-routespage.tsx
32+
@barlayout.tsx
33+
@barpage.tsx
34+
@foolayout.tsx
35+
@foopage.tsx"
4036
`)
4137
})
4238

4339
it('should render the segment explorer for nested routes', async () => {
4440
const browser = await next.browser('/blog/~/grid')
4541
expect(await getSegmentExplorerContent(browser)).toMatchInlineSnapshot(`
46-
"app/
47-
layout.tsx
48-
(v2)/
49-
layout.tsx
50-
blog/
51-
(team)/
52-
layout.tsx
53-
~/
54-
(overview)/
55-
layout.tsx
56-
grid/
57-
page.tsx"
42+
"applayout.tsx
43+
(v2)layout.tsx
44+
(team)layout.tsx
45+
(overview)layout.tsx
46+
gridpage.tsx"
5847
`)
5948
})
6049
})

0 commit comments

Comments
 (0)