Feat: Add responsive workspace shell
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
import { For, Show, createSignal, type JSX } from "solid-js";
|
||||
import { ChevronLeft, ChevronRight } from "../../../lib/icons";
|
||||
import { ProjectSelector } from "../ProjectSelector/ProjectSelector";
|
||||
import { serverSidebarItems, workspaceSidebarHeaderActions } from "../data/shell.data";
|
||||
import { workspaceSidebarHeaderActions, workspaceStaticItems, workspaceTree, type SidebarItem, type WorkspaceTreeNode } from "../data/shell.data";
|
||||
import styles from "./WorkspaceSidebar.module.scss";
|
||||
|
||||
type WorkspaceSidebarProps = {
|
||||
@@ -12,6 +12,72 @@ type WorkspaceSidebarProps = {
|
||||
onToggleRailCollapse: () => void;
|
||||
};
|
||||
|
||||
const WorkspaceHomeEntry = (props: { item: SidebarItem }): JSX.Element => {
|
||||
const Icon = props.item.icon;
|
||||
|
||||
return (
|
||||
<li>
|
||||
<button
|
||||
type="button"
|
||||
classList={{
|
||||
[styles.navItem]: true,
|
||||
[styles.navItemActive]: !!props.item.active,
|
||||
}}
|
||||
aria-current={props.item.active ? "page" : undefined}
|
||||
aria-label={props.item.label}
|
||||
title={props.item.label}
|
||||
>
|
||||
<Icon class={styles.icon} size={18} strokeWidth={2} />
|
||||
<span class={styles.label}>{props.item.label}</span>
|
||||
<Show when={props.item.meta}>
|
||||
<span class={styles.itemMeta}>{props.item.meta}</span>
|
||||
</Show>
|
||||
</button>
|
||||
</li>
|
||||
);
|
||||
};
|
||||
|
||||
const WorkspaceTreeBranch = (props: { nodes: readonly WorkspaceTreeNode[]; depth?: number }): JSX.Element => {
|
||||
const depth = () => props.depth ?? 0;
|
||||
|
||||
return (
|
||||
<ul class={styles.treeList} role="list">
|
||||
<For each={props.nodes}>
|
||||
{(node): JSX.Element => {
|
||||
const Icon = node.icon;
|
||||
|
||||
return (
|
||||
<li>
|
||||
<button
|
||||
type="button"
|
||||
classList={{
|
||||
[styles.treeItem]: true,
|
||||
[styles.treeItemActive]: !!node.active,
|
||||
[styles.treeItemFolder]: node.kind === "folder",
|
||||
}}
|
||||
style={{ "--tree-depth": String(depth()) }}
|
||||
aria-current={node.active ? "page" : undefined}
|
||||
aria-label={node.label}
|
||||
title={node.label}
|
||||
>
|
||||
<Icon class={styles.icon} size={18} strokeWidth={2} />
|
||||
<span class={styles.label}>{node.label}</span>
|
||||
<Show when={node.meta}>
|
||||
<span class={styles.itemMeta}>{node.meta}</span>
|
||||
</Show>
|
||||
</button>
|
||||
|
||||
<Show when={node.children?.length}>
|
||||
<WorkspaceTreeBranch nodes={node.children ?? []} depth={depth() + 1} />
|
||||
</Show>
|
||||
</li>
|
||||
);
|
||||
}}
|
||||
</For>
|
||||
</ul>
|
||||
);
|
||||
};
|
||||
|
||||
export const WorkspaceSidebar = (props: WorkspaceSidebarProps): JSX.Element => {
|
||||
const [isProjectDrawerOpen, setIsProjectDrawerOpen] = createSignal(false);
|
||||
const railToggleLabel = (): string => (props.railCollapsed ? "Expand server rail" : "Collapse server rail");
|
||||
@@ -78,36 +144,18 @@ export const WorkspaceSidebar = (props: WorkspaceSidebarProps): JSX.Element => {
|
||||
}}
|
||||
>
|
||||
<Show when={!props.collapsed}>
|
||||
<span class={styles.sectionLabel}>Navigation</span>
|
||||
<span class={styles.sectionLabel}>Workspace</span>
|
||||
</Show>
|
||||
<div class={styles.navScroller}>
|
||||
<ul class={styles.navList} role="list">
|
||||
<For each={serverSidebarItems}>
|
||||
{(item): JSX.Element => {
|
||||
const Icon = item.icon;
|
||||
|
||||
return (
|
||||
<li>
|
||||
<button
|
||||
type="button"
|
||||
classList={{
|
||||
[styles.navItem]: true,
|
||||
[styles.navItemActive]: !!item.active,
|
||||
}}
|
||||
aria-label={item.label}
|
||||
title={item.label}
|
||||
>
|
||||
<Icon class={styles.icon} size={18} strokeWidth={2} />
|
||||
<span class={styles.label}>{item.label}</span>
|
||||
<Show when={item.meta}>
|
||||
<span class={styles.itemMeta}>{item.meta}</span>
|
||||
</Show>
|
||||
</button>
|
||||
</li>
|
||||
);
|
||||
}}
|
||||
</For>
|
||||
<For each={workspaceStaticItems}>{(item): JSX.Element => <WorkspaceHomeEntry item={item} />}</For>
|
||||
</ul>
|
||||
|
||||
<Show when={!props.collapsed}>
|
||||
<div class={styles.treeSectionLabel}>Items</div>
|
||||
</Show>
|
||||
|
||||
<WorkspaceTreeBranch nodes={workspaceTree} />
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
Reference in New Issue
Block a user