Feat: Add collapsible shell

This commit is contained in:
MangoPig
2026-06-17 05:37:29 +01:00
parent 630b3778db
commit 7fdc5f2d22
15 changed files with 478 additions and 52 deletions

View File

@@ -1,7 +1,6 @@
.rail {
--rail-workspace-size: var(--control-size-lg);
--rail-action-size: var(--control-size-md);
--rail-dock-clearance: 8rem;
position: relative;
z-index: 3;
flex: 1;
@@ -10,10 +9,19 @@
flex-direction: column;
align-items: center;
gap: var(--space-3);
padding: var(--space-3) var(--space-2) calc(var(--space-3) + var(--rail-dock-clearance));
padding: var(--space-3) var(--space-2) calc(var(--space-3) + var(--rail-dock-clearance, 8rem));
overflow: visible;
}
.railCollapsed {
--rail-workspace-size: calc(var(--control-size-md) + 0.1rem);
--rail-action-size: calc(var(--control-size-md) + 0.1rem);
justify-content: flex-start;
gap: 0;
padding-top: var(--space-4);
padding-inline: var(--space-1);
}
.topCluster,
.bottomCluster {
width: 100%;
@@ -25,12 +33,22 @@
.bottomCluster {
margin-top: auto;
margin-bottom: var(--rail-bottom-offset, 0rem);
}
.topCluster {
gap: var(--space-3);
}
.railCollapsed .topCluster {
gap: var(--space-3);
}
.railCollapsed .topCluster,
.railCollapsed .bottomCluster {
align-items: center;
}
.items {
width: 100%;
min-height: 0;

View File

@@ -1,6 +1,6 @@
// Path: Frontend/src/components/shell/LeftRail/LeftRail.tsx
import { For, type JSX } from "solid-js";
import { For, Show, type JSX } from "solid-js";
import { Plus } from "../../../lib/icons";
import { railItems, type RailItem } from "../data/shell.data";
import styles from "./LeftRail.module.scss";
@@ -42,29 +42,49 @@ const RailEntry = (props: RailEntryProps): JSX.Element => {
);
};
export const LeftRail = (): JSX.Element => {
type LeftRailProps = {
collapsed: boolean;
};
export const LeftRail = (props: LeftRailProps): JSX.Element => {
const personalItem = railItems.find((item) => item.kind === "personal");
const organizationItems = railItems.filter((item) => item.kind === "organization");
return (
<aside class={styles.rail} aria-label="Server rail">
<aside
classList={{
[styles.rail]: true,
[styles.railCollapsed]: props.collapsed,
}}
aria-label="Server rail"
>
<div class={styles.topCluster}>
{personalItem ? <RailEntry item={personalItem} label={personalItem.label} abbreviation="M" personal /> : null}
<Show when={!props.collapsed && personalItem}>
{(item): JSX.Element => (
<RailEntry item={item()} label={item().label} abbreviation={item().abbreviation} personal />
)}
</Show>
<div class={styles.sectionDivider} aria-hidden="true" />
<Show when={!props.collapsed}>
<div class={styles.sectionDivider} aria-hidden="true" />
</Show>
</div>
<div class={styles.items}>
<For each={organizationItems}>
{(item): JSX.Element => <RailEntry item={item} label={item.label} abbreviation={item.abbreviation} />}
</For>
</div>
<Show when={!props.collapsed}>
<div class={styles.items}>
<For each={organizationItems}>
{(item): JSX.Element => <RailEntry item={item} label={item.label} abbreviation={item.abbreviation} />}
</For>
</div>
</Show>
<div class={styles.bottomCluster}>
<button type="button" class={styles.addButton} aria-label="Create server" title="Create server">
<Plus size={16} strokeWidth={2} />
</button>
</div>
<Show when={!props.collapsed}>
<div class={styles.bottomCluster}>
<button type="button" class={styles.addButton} aria-label="Create server" title="Create server">
<Plus size={16} strokeWidth={2} />
</button>
</div>
</Show>
</aside>
);
};