Skip to content

Commit a685e7a

Browse files
committed
tui: show monochrome file icons by default in tree view, revealing colors on hover to reduce visual clutter and help users focus on code content
1 parent ce7484b commit a685e7a

3 files changed

Lines changed: 73 additions & 5 deletions

File tree

packages/app/src/components/file-tree.tsx

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -447,12 +447,13 @@ export default function FileTree(props: {
447447
})
448448

449449
return (
450-
<div class={`flex flex-col gap-0.5 ${props.class ?? ""}`}>
450+
<div data-component="filetree" class={`flex flex-col gap-0.5 ${props.class ?? ""}`}>
451451
<For each={nodes()}>
452452
{(node) => {
453453
const expanded = () => file.tree.state(node.path)?.expanded ?? false
454454
const deep = () => deeps().get(node.path) ?? -1
455455
const kind = () => visibleKind(node, kinds(), marks())
456+
const active = () => !!kind() && !node.ignored
456457

457458
return (
458459
<Switch>
@@ -530,7 +531,30 @@ export default function FileTree(props: {
530531
onClick={() => props.onFileClick?.(node)}
531532
>
532533
<div class="w-4 shrink-0" />
533-
<FileIcon node={node} class="text-icon-weak size-4" />
534+
<Switch>
535+
<Match when={node.ignored}>
536+
<FileIcon
537+
node={node}
538+
class="size-4 filetree-icon filetree-icon--mono"
539+
style="color: var(--icon-weak-base)"
540+
mono
541+
/>
542+
</Match>
543+
<Match when={active()}>
544+
<FileIcon
545+
node={node}
546+
class="size-4 filetree-icon filetree-icon--mono"
547+
style={kindTextColor(kind()!)}
548+
mono
549+
/>
550+
</Match>
551+
<Match when={!node.ignored}>
552+
<span class="filetree-iconpair size-4">
553+
<FileIcon node={node} class="size-4 filetree-icon filetree-icon--color" />
554+
<FileIcon node={node} class="size-4 filetree-icon filetree-icon--mono" mono />
555+
</span>
556+
</Match>
557+
</Switch>
534558
</FileTreeNode>
535559
</FileTreeNodeTooltip>
536560
</Match>

packages/ui/src/components/file-icon.css

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,35 @@
33
width: 16px;
44
height: 16px;
55
}
6+
7+
/*
8+
File tree: show monochrome weak icons by default.
9+
On hover, show the original file-type colors.
10+
*/
11+
[data-component="filetree"] .filetree-icon--mono {
12+
color: var(--icon-base);
13+
}
14+
15+
[data-component="filetree"] .filetree-iconpair {
16+
position: relative;
17+
display: inline-flex;
18+
width: 16px;
19+
height: 16px;
20+
}
21+
22+
[data-component="filetree"] .filetree-iconpair [data-component="file-icon"] {
23+
position: absolute;
24+
inset: 0;
25+
}
26+
27+
[data-component="filetree"] .filetree-iconpair .filetree-icon--color {
28+
opacity: 0;
29+
}
30+
31+
[data-component="filetree"]:hover .filetree-iconpair .filetree-icon--color {
32+
opacity: 1;
33+
}
34+
35+
[data-component="filetree"]:hover .filetree-iconpair .filetree-icon--mono {
36+
opacity: 0;
37+
}

packages/ui/src/components/file-icon.tsx

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
11
import type { Component, JSX } from "solid-js"
2-
import { createMemo, splitProps } from "solid-js"
2+
import { createMemo, splitProps, Show } from "solid-js"
33
import sprite from "./file-icons/sprite.svg"
44
import type { IconName } from "./file-icons/types"
55

6+
let filter = 0
7+
68
export type FileIconProps = JSX.GSVGAttributes<SVGSVGElement> & {
79
node: { path: string; type: "file" | "directory" }
810
expanded?: boolean
11+
mono?: boolean
912
}
1013

1114
export const FileIcon: Component<FileIconProps> = (props) => {
12-
const [local, rest] = splitProps(props, ["node", "class", "classList", "expanded"])
15+
const [local, rest] = splitProps(props, ["node", "class", "classList", "expanded", "mono"])
1316
const name = createMemo(() => chooseIconName(local.node.path, local.node.type, local.expanded || false))
17+
const id = `file-icon-mono-${filter++}`
1418
return (
1519
<svg
1620
data-component="file-icon"
@@ -20,7 +24,15 @@ export const FileIcon: Component<FileIconProps> = (props) => {
2024
[local.class ?? ""]: !!local.class,
2125
}}
2226
>
23-
<use href={`${sprite}#${name()}`} />
27+
<Show when={local.mono}>
28+
<defs>
29+
<filter id={id} color-interpolation-filters="sRGB">
30+
<feFlood flood-color="currentColor" result="flood" />
31+
<feComposite in="flood" in2="SourceAlpha" operator="in" />
32+
</filter>
33+
</defs>
34+
</Show>
35+
<use href={`${sprite}#${name()}`} filter={local.mono ? `url(#${id})` : undefined} />
2436
</svg>
2537
)
2638
}

0 commit comments

Comments
 (0)