Skip to content

Commit cf5e59e

Browse files
(feat) sidebar (#77)
* added sidebar Signed-off-by: Benjamin Strasser <bp.strasser@gmail.com> * Sidebar is collapsable Signed-off-by: Benjamin Strasser <bp.strasser@gmail.com> * Sidebar state is now synced with localstorage Signed-off-by: Benjamin Strasser <bp.strasser@gmail.com> * Changed sidebar communciation to use load functions Signed-off-by: Benjamin Strasser <bp.strasser@gmail.com> * Moved Sidebar into component Signed-off-by: Benjamin Strasser <bp.strasser@gmail.com> * Added profile page Signed-off-by: Benjamin Strasser <bp.strasser@gmail.com> * redirect signed in users to /projects + after sign in Signed-off-by: Benjamin Strasser <bp.strasser@gmail.com> * added lang postcss to style stags using @apply Signed-off-by: Benjamin Strasser <bp.strasser@gmail.com> * added localStorageWritable to sidebar Signed-off-by: Benjamin Strasser <bp.strasser@gmail.com> * fixed bug where themeselector navigated to profile page Signed-off-by: Benjamin Strasser <bp.strasser@gmail.com> --------- Signed-off-by: Benjamin Strasser <bp.strasser@gmail.com>
1 parent 6677f1e commit cf5e59e

File tree

18 files changed

+168
-8
lines changed

18 files changed

+168
-8
lines changed

src/components/sidebar/index.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import Sidebar from './sidebar.svelte'
2+
3+
export type NavigationElement = {
4+
name: string
5+
icon: ConstructorOfATypedSvelteComponent
6+
route: string
7+
}
8+
9+
export { Sidebar }
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
<script lang="ts">
2+
import type { NavigationElement } from '.'
3+
import { page } from '$app/stores'
4+
import { ThemeSelector } from '$components/ui/theme-selector'
5+
6+
import ChevronLeft from 'lucide-svelte/icons/chevron-left'
7+
import ChevronRight from 'lucide-svelte/icons/chevron-right'
8+
import { localStorageWritable } from '$lib/utils/localstorage-writable'
9+
10+
export let sidebarElements: NavigationElement[] = []
11+
12+
const collapsedSidebar = localStorageWritable('collapsedSidebar', false)
13+
</script>
14+
15+
<div
16+
class:collapsedSidebar={$collapsedSidebar}
17+
class="duration-400 flex h-full w-80 flex-none flex-col bg-secondary text-secondary-foreground transition-all ease-in-out"
18+
>
19+
<!-- Top Section -->
20+
<div class="m-8 mb-6 mr-0 flex items-center text-2xl">
21+
<div>⌘</div>
22+
<div class="ml-2 overflow-hidden whitespace-nowrap" class:collapsedElement={$collapsedSidebar}>
23+
Tiny-TMS
24+
</div>
25+
<button
26+
on:click={() => ($collapsedSidebar = !$collapsedSidebar)}
27+
class="ml-auto mr-2 cursor-pointer rounded-full hover:bg-primary-foreground"
28+
>
29+
{#if $collapsedSidebar}
30+
<ChevronRight />
31+
{:else}
32+
<ChevronLeft />
33+
{/if}
34+
</button>
35+
</div>
36+
37+
<div class="mx-4 flex-grow">
38+
{#each sidebarElements as element}
39+
<a
40+
href={element.route}
41+
class="flex cursor-pointer rounded-lg border border-transparent p-4 hover:border-primary"
42+
class:selected={$page.url.pathname.endsWith(element.route)}
43+
>
44+
<svelte:component this={element.icon} class="min-h-6 min-w-6"></svelte:component>
45+
<div
46+
class="ml-2 overflow-hidden whitespace-nowrap"
47+
class:collapsedElement={$collapsedSidebar}
48+
>
49+
{element.name}
50+
</div>
51+
</a>
52+
{/each}
53+
</div>
54+
55+
<div class="m-4 mt-auto flex items-center justify-between">
56+
<a class="flex items-center" href="/profile">
57+
<div class="ml-4 mr-2.5 min-h-8 min-w-8 rounded-full bg-yellow-300"></div>
58+
<div class:collapsedElement={$collapsedSidebar} class="overflow-hidden whitespace-nowrap">
59+
My Account
60+
</div>
61+
</a>
62+
<div class:collapsedElement={$collapsedSidebar} class="overflow-hidden">
63+
<ThemeSelector />
64+
</div>
65+
</div>
66+
</div>
67+
68+
<style lang="postcss">
69+
.collapsedElement {
70+
display: none;
71+
}
72+
73+
.collapsedSidebar {
74+
@apply w-[90px];
75+
}
76+
.selected {
77+
@apply bg-primary-foreground;
78+
}
79+
</style>

src/components/ui/theme-selector/theme-selector.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
</label>
5252
</div>
5353

54-
<style lang="css">
54+
<style lang="postcss">
5555
input[type='radio']:checked + label {
5656
@apply border border-primary;
5757
}

src/routes/(auth)/+layout.svelte

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,5 +48,7 @@
4848
</div>
4949
</div>
5050

51-
<div class="my-auto w-1/2"><slot></slot></div>
51+
<div class="my-auto w-1/2">
52+
<slot />
53+
</div>
5254
</div>

src/routes/(auth)/login/+page.server.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { dev } from '$app/environment'
99

1010
export const load: PageServerLoad = async ({ locals: { user } }) => {
1111
if (user) {
12-
throw redirect(302, '/')
12+
throw redirect(302, '/projects')
1313
}
1414

1515
return {

src/routes/(auth)/login/login-form.svelte

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@
1414
1515
const form = superForm(data, {
1616
validators: zodClient(loginSchema),
17-
async onUpdated({ form }) {
17+
async onUpdate({ form }) {
1818
if (form.message) {
1919
if ($page.status >= 400) {
2020
toast.error(form.message)
2121
} else {
2222
toast.success(form.message)
23-
await goto('/guarded')
23+
await goto('/projects')
2424
}
2525
}
2626
}

src/routes/(auth)/signup/+page.server.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { redirect } from '@sveltejs/kit'
77

88
export const load: PageServerLoad = async (event) => {
99
if (event.locals.user) {
10-
throw redirect(302, '/')
10+
throw redirect(302, '/projects')
1111
}
1212

1313
return {
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<script lang="ts">
2+
import { Sidebar } from '$components/sidebar'
3+
import { page } from '$app/stores'
4+
</script>
5+
6+
<div class="flex h-full">
7+
<Sidebar sidebarElements={$page.data.sidebarElements} />
8+
<slot />
9+
</div>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import List from 'lucide-svelte/icons/list'
2+
import type { LayoutLoad } from './$types'
3+
4+
export const load: LayoutLoad = () => {
5+
const sidebarElements = [
6+
{
7+
name: 'My Projects',
8+
route: '/projects',
9+
icon: List
10+
}
11+
]
12+
13+
return {
14+
sidebarElements
15+
}
16+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Profile

0 commit comments

Comments
 (0)