Skip to content

Commit 85cc4f7

Browse files
committed
components
1 parent 96cbd88 commit 85cc4f7

15 files changed

Lines changed: 664 additions & 202 deletions

components/filetree.html

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
<div class="filetree">
2+
<style>
3+
.filetree .host {
4+
/* Height comes from the model — see `fit` below. */
5+
border-radius: 0.5rem;
6+
/* The tree defaults to `system-ui` at 13px; take the page font instead. */
7+
--trees-font-family-override: var(--sans-serif);
8+
--trees-font-size-override: 0.85rem;
9+
/* The tree paints its own background on the host, so clip it to the
10+
radius or the corners stay square. */
11+
overflow: hidden;
12+
}
13+
</style>
14+
15+
<div class="host"></div>
16+
17+
<script type="module">
18+
// A vanilla `@pierre/trees` file tree — https://trees.software/docs#get-started-with-vanilla.
19+
const PATHS = [
20+
".gitignore",
21+
"README.md",
22+
"package.json",
23+
"vite.config.ts",
24+
".github/workflows/ci.yml",
25+
".github/workflows/release.yml",
26+
"src/index.ts",
27+
"src/components/Button.tsx",
28+
"src/components/Card.tsx",
29+
"src/hooks/useDebounce.ts",
30+
"src/styles/globals.css",
31+
"src/utils/cn.ts",
32+
];
33+
34+
// Every directory in the set, so the tree opens fully expanded. A collapsed
35+
// folder chain (`.github/workflows`) renders as one row, but naming both
36+
// halves is harmless and keeps this a plain prefix walk.
37+
const DIRECTORIES = [
38+
...new Set(
39+
PATHS.flatMap((path) => {
40+
const parts = path.split("/").slice(0, -1);
41+
return parts.map((_, i) => parts.slice(0, i + 1).join("/"));
42+
}),
43+
),
44+
];
45+
46+
// A VS Code-shaped theme object, which `themeToTreeStyles` maps onto the
47+
// `--trees-theme-*` variables the tree reads. Warm dark neutrals so the
48+
// panel doesn't fight the page, with the site green on selection and focus.
49+
const THEME = {
50+
type: "dark",
51+
bg: "#1b1a18",
52+
fg: "#d8d4cc",
53+
colors: {
54+
"sideBar.background": "#1b1a18",
55+
"sideBar.foreground": "#d8d4cc",
56+
"sideBar.border": "#2d2b28",
57+
"sideBarSectionHeader.foreground": "#d8d4cc",
58+
"list.activeSelectionBackground": "#33470a",
59+
"list.activeSelectionForeground": "#f2efe8",
60+
"list.hoverBackground": "rgba(255, 255, 255, 0.06)",
61+
"list.focusOutline": "#8ab82e",
62+
"scrollbarSlider.background": "rgba(255, 255, 255, 0.14)",
63+
},
64+
};
65+
66+
// The block is inlined by the compiler, so the same script may run for more
67+
// than one copy on a page. Claim every unmounted host, and let the later
68+
// copies of this script find nothing left to do.
69+
const hosts = document.querySelectorAll(".filetree:not([data-mounted])");
70+
for (const host of hosts) host.dataset.mounted = "true";
71+
72+
if (hosts.length > 0) {
73+
// Dynamic import so a blocked or offline CDN degrades to a note instead
74+
// of a silently empty box.
75+
let FileTree, themeToTreeStyles;
76+
try {
77+
({ FileTree, themeToTreeStyles } =
78+
await import("https://esm.sh/@pierre/trees@1.0.0-beta.6"));
79+
} catch {
80+
for (const host of hosts) {
81+
host.querySelector(".host").textContent =
82+
"couldn't load @pierre/trees";
83+
}
84+
}
85+
86+
for (const host of hosts) {
87+
if (!FileTree) break;
88+
89+
const tree = new FileTree({
90+
paths: PATHS,
91+
icons: "standard",
92+
initialExpandedPaths: DIRECTORIES,
93+
initialSelectedPaths: ["src/components/Button.tsx"],
94+
density: "compact",
95+
});
96+
97+
const container = host.querySelector(".host");
98+
tree.render({ fileTreeContainer: container });
99+
100+
// Custom properties need `setProperty`; the rest are plain style keys.
101+
for (const [key, value] of Object.entries(themeToTreeStyles(THEME))) {
102+
if (key.startsWith("--")) container.style.setProperty(key, value);
103+
else container.style[key] = value;
104+
}
105+
106+
// The tree is virtualized, so it needs a height to render into rather
107+
// than growing on its own. Take that height from the model, once, while
108+
// everything is still expanded — that's the tallest the tree can get, so
109+
// nothing ever scrolls. Deliberately not re-fit on collapse: the panel
110+
// holds its size instead of yanking the rest of the page up and down.
111+
container.style.height = `${tree.getVisibleCount() * tree.getItemHeight()}px`;
112+
}
113+
}
114+
</script>
115+
</div>

include/styles/main.scss

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,15 @@ header {
237237
}
238238

239239
.demo,
240-
pre {
240+
pre,
241+
table {
242+
padding-top: 1.5rem;
243+
padding-bottom: 1.5rem;
244+
}
245+
246+
.demo:not(.sm),
247+
pre,
248+
table {
241249
// border-top: 1px solid var(--darker-border);
242250
// border-bottom: 1px solid var(--darker-border);
243251
background-color: var(--background);
@@ -250,8 +258,6 @@ header {
250258
overflow-x: auto;
251259
position: relative;
252260
z-index: 99;
253-
padding-top: 1.5rem;
254-
padding-bottom: 1.5rem;
255261
}
256262

257263
pre {
@@ -271,15 +277,41 @@ header {
271277
}
272278
}
273279

274-
.demo {
280+
table {
281+
border-spacing: 0;
282+
border-collapse: collapse;
283+
284+
th {
285+
font-style: italic;
286+
font-weight: normal;
287+
}
288+
289+
th,
290+
td {
291+
border: 1px solid var(--darker-border);
292+
margin: 0;
293+
text-align: left;
294+
padding: 7px 14px;
295+
}
296+
297+
tr {
298+
margin: 0;
299+
}
300+
}
301+
302+
.demo:not(.sm),
303+
table {
304+
font-family: var(--monospace);
305+
font-size: 0.995rem;
306+
}
307+
308+
.demo:not(.sm) {
275309
--unit-fill: color-mix(in srgb, var(--theme) 9%, var(--foreground));
276310
--unit-border: color-mix(in srgb, var(--theme) 42%, var(--foreground));
277311
--band-fill: #e9f0f8;
278312
--band-border: #9db8d4;
279313

280314
// font-family: var(--sans-serif);
281-
font-family: var(--monospace);
282-
font-size: 0.995rem;
283315
padding: var(--article-block-padding);
284316
// padding-left: calc(50vw - 50% - var(--article-inline-padding));
285317

out/index.html

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)