feat: sidebar toggling animation

This commit is contained in:
ae 2025-05-04 15:57:30 +03:00
parent 2197df05ef
commit 75fd86046b
Signed by: ae
GPG Key ID: 995EFD5C1B532B3E
3 changed files with 48 additions and 20 deletions

View File

@ -30,6 +30,9 @@
--dark-error-background: #4b0000e0; --dark-error-background: #4b0000e0;
--dark-success-text: #adfcaa; --dark-success-text: #adfcaa;
--dark-success-background: #004b0ae0; --dark-success-background: #004b0ae0;
--sidebar-expanded-width: 19.5rem; /* w-64 + w-14 */
--sidebar-collapsed-width: 3.5rem; /* w-14 */
} }
/* Scrollbar width */ /* Scrollbar width */
@ -265,14 +268,31 @@
/* Sidebar */ /* Sidebar */
/* * * * * * * * * */ /* * * * * * * * * */
.outer-sidebar-container {
@apply relative z-10 flex h-full transition-all duration-200 ease-in-out;
}
.sidebar-expanded {
@apply w-[var(--sidebar-expanded-width)];
}
.sidebar-collapsed {
@apply w-[var(--sidebar-collapsed-width)];
}
.mini-sidebar { .mini-sidebar {
@apply flex w-14 flex-col items-center border-r border-[var(--light-accent)]/20 bg-[var(--light-foreground)] py-4; /* Higher Z-value than the actual sidebar so that this stays always on top of it */
@apply z-10 flex w-14 min-w-14 flex-col items-center border-r border-[var(--light-accent)]/20 bg-[var(--light-foreground)] py-4;
} }
.dark .mini-sidebar { .dark .mini-sidebar {
@apply border-[var(--dark-accent)]/20 bg-[var(--dark-foreground)]; @apply border-[var(--dark-accent)]/20 bg-[var(--dark-foreground)];
} }
.mini-sidebar-button-container {
@apply mt-6 flex flex-col gap-4 transition-all duration-200 ease-in-out;
}
.sidebar-button { .sidebar-button {
@apply flex h-8 w-8 items-center justify-center rounded-lg border border-[var(--light-accent)] bg-transparent p-0 text-[var(--light-text)] hover:bg-[var(--light-background)]/80; @apply flex h-8 w-8 items-center justify-center rounded-lg border border-[var(--light-accent)] bg-transparent p-0 text-[var(--light-text)] hover:bg-[var(--light-background)]/80;
} }
@ -282,7 +302,7 @@
} }
.sidebar { .sidebar {
@apply z-10 flex h-full flex-col overflow-hidden border-r border-[var(--light-accent)]/20 bg-[var(--light-foreground)] transition-all duration-300 ease-in-out; @apply z-10 flex h-full flex-col overflow-hidden border-r border-[var(--light-accent)]/20 bg-[var(--light-foreground)] transition-all duration-200 ease-in-out;
} }
.dark .sidebar { .dark .sidebar {
@ -291,18 +311,21 @@
/* Take up full screen width on mobile */ /* Take up full screen width on mobile */
@media (max-width: 768px) { @media (max-width: 768px) {
.sidebar { .outer-sidebar-container {
/* Max width must take into account width of "mini sidebar" */ @apply w-auto;
@apply w-[calc(100vw-3.5rem)];
} }
body.sidebar-open { .sidebar {
@apply absolute left-[var(--sidebar-collapsed-width)] max-w-[calc(100vw-var(--sidebar-collapsed-width))] min-w-[calc(100vw-var(--sidebar-collapsed-width))];
}
body.sidebar-expanded {
@apply overflow-hidden; @apply overflow-hidden;
} }
} }
/* 16rem width on desktop or equivalent screens */ /* 16rem width on desktop or equivalent screens */
@media (min-width: 768px) { @media (min-width: 769px) {
.sidebar { .sidebar {
@apply w-64; @apply w-64;
} }
@ -440,24 +463,22 @@
@apply bg-[var(--dark-background)]; @apply bg-[var(--dark-background)];
} }
/* Minimize wasted screen height on short displays */
@media (max-width: 768px) {
.main-content {
@apply pb-2;
}
}
.content-wrapper { .content-wrapper {
@apply flex h-screen flex-1 flex-col overflow-hidden py-12; @apply ml-0 flex h-screen flex-1 flex-col overflow-hidden py-12 transition-all duration-200 ease-in-out;
} }
.note-content-fixed-width { .note-content-fixed-width {
@apply mx-auto flex h-full w-full max-w-[800px] flex-col px-8 py-0; @apply mx-auto flex h-full w-full max-w-[800px] flex-col px-8 py-0;
} }
/* Minimize wasted screen space on generally small displays */
@media (max-width: 768px) { @media (max-width: 768px) {
.main-content {
@apply pb-2;
}
.content-wrapper { .content-wrapper {
@apply py-0; @apply ml-[var(--mini-sidebar-width)] py-0;
} }
.note-content-fixed-width { .note-content-fixed-width {

View File

@ -284,7 +284,7 @@
/> />
<!-- Main content area --> <!-- Main content area -->
<div class="content-wrapper ml-0 transition-all duration-300"> <div class="content-wrapper">
<!-- Note content area with fixed width --> <!-- Note content area with fixed width -->
<div class="note-content-fixed-width"> <div class="note-content-fixed-width">
<main class="main-content"> <main class="main-content">

View File

@ -70,7 +70,11 @@
<!-- TODO: handle pagination support later if it becomes an issue (`util/itemPagination.ts`) --> <!-- TODO: handle pagination support later if it becomes an issue (`util/itemPagination.ts`) -->
<!-- Outmost sidebar container with collapsible functionality --> <!-- Outmost sidebar container with collapsible functionality -->
<div class="relative z-10 flex h-full"> <div
class="outer-sidebar-container"
class:sidebar-expanded={isSidebarOpen}
class:sidebar-collapsed={!isSidebarOpen}
>
<!-- Collapsed mini sidebar (always visible) --> <!-- Collapsed mini sidebar (always visible) -->
<div class="mini-sidebar"> <div class="mini-sidebar">
<button <button
@ -87,7 +91,7 @@
<!-- Mini sidebar icons --> <!-- Mini sidebar icons -->
{#if !isSidebarOpen} {#if !isSidebarOpen}
<div class="mt-6 flex flex-col gap-4"> <div class="mini-sidebar-button-container">
<button on:click={createNewNote} class="sidebar-button" aria-label="Create new note"> <button on:click={createNewNote} class="sidebar-button" aria-label="Create new note">
<Create classString="h-5 w-5" /> <Create classString="h-5 w-5" />
</button> </button>
@ -117,7 +121,10 @@
class="sidebar" class="sidebar"
class:translate-x-0={isSidebarOpen} class:translate-x-0={isSidebarOpen}
class:translate-x-[-100%]={!isSidebarOpen} class:translate-x-[-100%]={!isSidebarOpen}
class:hidden={!isSidebarOpen} class:opacity-100={isSidebarOpen}
class:opacity-0={!isSidebarOpen}
class:pointer-events-none={!isSidebarOpen}
class:pointer-events-auto={isSidebarOpen}
class:md:relative={true} class:md:relative={true}
> >
<!-- Header with app logo and display name --> <!-- Header with app logo and display name -->