~repos /website

#astro#js#html#css

git clone https://pyrossh.dev/repos/website.git

木 Personal website of pyrossh. Built with astrojs, shiki, vite.



src/components/RecursiveList.astro



---
import { Icon } from "astro-icon/components";
import allIcons from "@iconify-json/vscode-icons/icons.json" assert { type: "json" };
import prettyBytes from "pretty-bytes";
import { resolveFileIcon } from "@/utils/files";
interface FileNode {
name: string;
path: string;
isDirectory: boolean;
size: number;
ext: string;
absolutePath: string;
children?: FileNode[];
}
interface Props {
items: FileNode[];
repoId: string;
depth?: number;
}
const { items, repoId, depth = 0 } = Astro.props;
---
{
items.map((item) => {
if (item.isDirectory && item.children) {
return (
<li class="folder" style={`padding-left: ${depth * 1}rem;`}>
<details>
<summary>
<Icon
name="mdi:folder"
size="24px"
color="hsl(45deg 75.37% 60%)"
/>
<span>{item.name}</span>
</summary>
<ul>
<Astro.self
items={item.children}
repoId={repoId}
depth={depth + 1}
/>
</ul>
</details>
</li>
);
} else {
const iconName = resolveFileIcon(item.name, item.ext);
const fileType = allIcons.icons[`file-type-${iconName}`]
? `file-type-${iconName}`
: "default-file";
return (
<li class="file" style={`padding-left: ${depth * 1}rem;`}>
<div class="file-content">
<div class="file-name">
<Icon name={`vscode-icons:${fileType}`} size="18px" />
<a href={`/repos/${repoId}/files/${item.path}`} rel="nofollow">
{item.name}
</a>
</div>
{item.size && (
<div class="file-size">
<span>{prettyBytes(item.size).replace(" ", "")}</span>
</div>
)}
</div>
</li>
);
}
})
}
<style>
svg[data-icon] {
margin-right: 0.3rem;
}
.folder {
margin: 0;
details {
margin: 0.25rem 0;
}
summary {
display: flex;
align-items: center;
cursor: pointer;
padding: 0.4rem;
background-color: var(--color-box-bg);
}
ul {
padding: 0;
margin: 0.25rem 0 0.5rem 1rem;
}
}
.file {
margin: 0.25rem 0;
.file-content {
display: flex;
padding: 0.4rem;
background-color: var(--color-box-bg);
}
.file-name {
flex: 1;
display: flex;
align-items: center;
a {
text-decoration: none;
&:hover {
/* color: var(--color-link); */
text-decoration: underline;
text-underline-offset: 3px;
}
}
}
.file-size {
margin-left: auto;
padding-left: 1rem;
opacity: 0.7;
}
}
</style>