Feat: Frontend app shell
This commit is contained in:
82
Frontend/src/components/shell/LeftRail/LeftRail.module.scss
Normal file
82
Frontend/src/components/shell/LeftRail/LeftRail.module.scss
Normal file
@@ -0,0 +1,82 @@
|
||||
.rail {
|
||||
--rail-workspace-size: var(--control-size-lg);
|
||||
--rail-action-size: var(--control-size-md);
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: var(--space-3);
|
||||
padding: var(--space-3) var(--space-2);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.topCluster,
|
||||
.bottomCluster {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: var(--space-2);
|
||||
}
|
||||
|
||||
.items {
|
||||
width: 100%;
|
||||
min-height: 0;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: var(--space-2);
|
||||
overflow-y: auto;
|
||||
overscroll-behavior: contain;
|
||||
padding-block: var(--space-1);
|
||||
}
|
||||
|
||||
.logo {
|
||||
width: var(--rail-workspace-size);
|
||||
height: var(--rail-workspace-size);
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: var(--radius-lg);
|
||||
background: var(--color-accent);
|
||||
color: var(--color-accent-contrast);
|
||||
font-weight: 700;
|
||||
letter-spacing: -0.02em;
|
||||
}
|
||||
|
||||
.workspaceButton {
|
||||
width: var(--rail-workspace-size);
|
||||
height: var(--rail-workspace-size);
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
@include interactive-frame(var(--color-surface-muted), var(--color-border), var(--color-text-muted), var(--radius-lg));
|
||||
@include text-label;
|
||||
@include interactive-frame-hover();
|
||||
}
|
||||
|
||||
.workspaceButtonActive {
|
||||
background: var(--color-accent);
|
||||
border-color: transparent;
|
||||
color: var(--color-accent-contrast);
|
||||
box-shadow: var(--shadow-soft);
|
||||
}
|
||||
|
||||
.addButton {
|
||||
width: var(--rail-action-size);
|
||||
height: var(--rail-action-size);
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 1px dashed var(--color-border-strong);
|
||||
border-radius: var(--radius-pill);
|
||||
background: transparent;
|
||||
color: var(--color-text-muted);
|
||||
|
||||
&:hover {
|
||||
background: var(--color-surface-hover);
|
||||
color: var(--color-text);
|
||||
}
|
||||
}
|
||||
42
Frontend/src/components/shell/LeftRail/LeftRail.tsx
Normal file
42
Frontend/src/components/shell/LeftRail/LeftRail.tsx
Normal file
@@ -0,0 +1,42 @@
|
||||
// Path: Frontend/src/components/shell/LeftRail/LeftRail.tsx
|
||||
|
||||
import { For, type JSX } from "solid-js";
|
||||
import { Plus } from "../../../lib/icons";
|
||||
import { railItems } from "../data/shell.data";
|
||||
import styles from "./LeftRail.module.scss";
|
||||
|
||||
export const LeftRail = (): JSX.Element => {
|
||||
return (
|
||||
<aside class={styles.rail} aria-label="Workspace rail">
|
||||
<div class={styles.topCluster}>
|
||||
<div class={styles.logo} aria-hidden="true">
|
||||
M
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class={styles.items}>
|
||||
<For each={railItems}>
|
||||
{(item): JSX.Element => (
|
||||
<button
|
||||
type="button"
|
||||
classList={{
|
||||
[styles.workspaceButton]: true,
|
||||
[styles.workspaceButtonActive]: !!item.active,
|
||||
}}
|
||||
title={item.label}
|
||||
aria-label={item.label}
|
||||
>
|
||||
{item.abbreviation}
|
||||
</button>
|
||||
)}
|
||||
</For>
|
||||
</div>
|
||||
|
||||
<div class={styles.bottomCluster}>
|
||||
<button type="button" class={styles.addButton} aria-label="Create workspace" title="Create workspace">
|
||||
<Plus size={16} strokeWidth={2} />
|
||||
</button>
|
||||
</div>
|
||||
</aside>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user