Update layout

Sidebar now animates properly. Navigation has progressive blur behind it on scroll
This commit is contained in:
Justin Edmund 2025-09-24 00:45:28 -07:00
parent 06a91bd532
commit b564a5e5e0
4 changed files with 134 additions and 90 deletions

View file

@ -21,7 +21,7 @@
const { open = false, title, onclose, children, headerActions }: Props = $props()
</script>
<aside class="sidebar" class:open style:--sidebar-width={open ? SIDEBAR_WIDTH : '0'}>
<aside class="sidebar" class:open style:--sidebar-width={SIDEBAR_WIDTH}>
{#if title}
<SidebarHeader {title} {onclose} actions={headerActions} />
{/if}
@ -50,42 +50,56 @@
display: flex;
flex-direction: column;
flex-shrink: 0;
width: 0;
width: var(--sidebar-width);
overflow: hidden;
transition: width $duration-slide ease-in-out;
transform: translateX(100%);
opacity: 0;
transition:
transform $duration-slide ease-in-out,
opacity $duration-slide ease-in-out;
z-index: 50;
&.open {
width: var(--sidebar-width);
transform: translateX(0);
opacity: 1;
}
.sidebar-content {
flex: 1;
overflow-y: auto;
overflow-x: hidden;
padding: $unit-2x;
// Smooth scrolling
scroll-behavior: smooth;
// Better scrollbar styling to match main content
// Use overlay scrollbars that auto-hide
overflow-y: overlay;
// Thin, minimal scrollbar styling
&::-webkit-scrollbar {
width: 8px;
width: 10px;
}
&::-webkit-scrollbar-track {
background: var(--bg-secondary, #f1f1f1);
background: transparent;
}
&::-webkit-scrollbar-thumb {
background: var(--border-primary, #888);
border-radius: 4px;
background: rgba(0, 0, 0, 0.2);
border-radius: 10px;
border: 2px solid transparent;
background-clip: padding-box;
&:hover {
background: var(--text-secondary, #555);
background: rgba(0, 0, 0, 0.4);
background-clip: padding-box;
}
}
// Firefox scrollbar styling
scrollbar-width: thin;
scrollbar-color: rgba(0, 0, 0, 0.2) transparent;
// Improve mobile scrolling performance
@media (max-width: 768px) {
-webkit-overflow-scrolling: touch;
@ -95,17 +109,10 @@
// Mobile styles - overlay approach
@media (max-width: 768px) {
z-index: 100;
transform: translateX(100%);
transition:
transform $duration-slide ease-in-out,
width 0s;
width: 90vw !important;
max-width: 400px;
box-shadow: -2px 0 8px rgba(0, 0, 0, 0.15);
&.open {
transform: translateX(0);
}
// Mobile already uses transform, no additional changes needed
}
}
</style>

View file

@ -18,55 +18,71 @@
</script>
<div class="sidebar-header">
<div class="header-left">
{#if actions}
{@render actions()}
{/if}
</div>
<h2 class="sidebar-title">{title}</h2>
{#if actions}
<div class="header-actions">
{@render actions()}
</div>
{/if}
{#if onclose}
<button
onclick={onclose}
class="close-button"
aria-label="Close sidebar"
>
{@html closeIcon}
</button>
{/if}
<div class="header-right">
{#if onclose}
<button onclick={onclose} class="close-button" aria-label="Close sidebar">
{@html closeIcon}
</button>
{/if}
</div>
</div>
<style lang="scss">
@use '$src/themes/spacing' as *;
@use '$src/themes/colors' as *;
@use '$src/themes/typography' as *;
@use '$src/themes/layout' as *;
.sidebar-header {
display: flex;
align-items: center;
gap: $unit;
justify-content: space-between;
min-height: $nav-height;
padding: $unit-2x;
border-bottom: 1px solid var(--border-primary);
flex-shrink: 0;
background: var(--bg-primary);
.sidebar-title {
flex: 1;
margin: 0;
font-size: $font-large;
font-weight: $bold;
color: var(--text-primary);
// Match mobile navigation height
@media (max-width: 768px) {
min-height: $nav-height-mobile;
}
.header-actions {
.header-left,
.header-right {
width: 32px; // Same width as close button for balance
flex-shrink: 0;
display: flex;
gap: $unit;
align-items: center;
justify-content: center;
}
.header-left {
justify-content: flex-start;
}
.header-right {
justify-content: flex-end;
}
.sidebar-title {
margin: 0;
font-size: $font-regular;
font-weight: $medium;
color: var(--text-primary);
text-align: center;
flex: 1;
}
.close-button {
margin-left: $unit;
padding: $unit;
background: transparent;
border: none;
@ -76,10 +92,11 @@
justify-content: center;
border-radius: 4px;
color: var(--text-secondary);
transition: background-color 0.2s, color 0.2s;
transition:
background-color 0.2s,
color 0.2s;
width: 32px;
height: 32px;
flex-shrink: 0;
:global(svg) {
width: 14px;
@ -97,4 +114,4 @@
}
}
}
</style>
</style>

View file

@ -46,11 +46,11 @@
<Tooltip.Provider>
<div class="app-container" class:sidebar-open={sidebar.isOpen}>
<div class="nav-wrapper">
<Navigation isAuthenticated={data?.isAuthenticated} username={data?.account?.username} role={data?.account?.role} />
</div>
<div class="main-pane">
<div class="nav-blur-background"></div>
<div class="main-navigation">
<Navigation isAuthenticated={data?.isAuthenticated} username={data?.account?.username} role={data?.account?.role} />
</div>
<main class="main-content">
{@render children?.()}
</main>
@ -87,23 +87,26 @@
position: relative;
overflow: hidden;
// Fixed navigation wrapper with blur effect
.nav-wrapper {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 100;
width: 100vw;
// Main pane with content
.main-pane {
flex: 1;
display: flex;
flex-direction: column;
min-width: 0;
transition: margin-right $duration-slide ease-in-out;
position: relative;
height: 100%;
// Single blur layer with gradient mask for progressive effect
&::before {
content: '';
position: absolute;
// Blur background that shifts with main pane
.nav-blur-background {
position: fixed;
top: 0;
left: 0;
right: 0;
height: 80px; // Taller to test the progressive effect
z-index: 1; // Lower z-index so scrollbar appears above
pointer-events: none;
transition: right $duration-slide ease-in-out;
// Color gradient for the background
background: linear-gradient(
@ -131,67 +134,80 @@
black 40%,
transparent 100%
);
pointer-events: none;
z-index: 1;
}
// Navigation content above the blur layer
:global(nav) {
position: relative;
z-index: 2;
// Navigation wrapper - fixed but shifts with main-pane
.main-navigation {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 10; // Above blur but below scrollbar
transition: right $duration-slide ease-in-out;
pointer-events: auto;
}
}
// Main pane with content
.main-pane {
flex: 1;
display: flex;
flex-direction: column;
min-width: 0;
transition: margin-right $duration-slide ease-in-out;
position: relative;
height: 100%;
// Main content area with independent scroll - content starts at top
// Main content area with independent scroll
.main-content {
flex: 1;
overflow-y: auto;
overflow-x: hidden;
position: relative;
padding-top: 56px; // Space for fixed navigation to match blur height
padding-top: 80px; // Space for fixed navigation (matching test height)
z-index: 2; // Ensure scrollbar is above blur background
// Smooth scrolling
scroll-behavior: smooth;
// Better scrollbar styling
// Use overlay scrollbars that auto-hide on macOS
overflow-y: overlay;
// Thin, minimal scrollbar styling
&::-webkit-scrollbar {
width: 8px;
width: 10px;
}
&::-webkit-scrollbar-track {
background: var(--bg-secondary, #f1f1f1);
background: transparent;
}
&::-webkit-scrollbar-thumb {
background: var(--border-primary, #888);
border-radius: 4px;
background: rgba(0, 0, 0, 0.2);
border-radius: 10px;
border: 2px solid transparent;
background-clip: padding-box;
&:hover {
background: var(--text-secondary, #555);
background: rgba(0, 0, 0, 0.4);
background-clip: padding-box;
}
}
// Firefox scrollbar styling
scrollbar-width: thin;
scrollbar-color: rgba(0, 0, 0, 0.2) transparent;
}
}
// When sidebar is open, adjust main pane width
// When sidebar is open, adjust main pane and navigation
&.sidebar-open {
.main-pane {
margin-right: var(--sidebar-width, 420px);
// Blur background and navigation shift with the main pane
.nav-blur-background,
.main-navigation {
right: var(--sidebar-width, 420px);
}
// Mobile: don't adjust margin, use overlay
@media (max-width: 768px) {
margin-right: 0;
.nav-blur-background,
.main-navigation {
right: 0; // Don't shift on mobile
}
}
}
}

View file

@ -1,5 +1,9 @@
@use 'spacing';
// Navigation and header heights
$nav-height: 76px;
$nav-height-mobile: 60px;
// Scale factors
$scale-wide: scale(1.05, 1.05);
$scale-tall: scale(1.012, 1.012);