Update layout
Sidebar now animates properly. Navigation has progressive blur behind it on scroll
This commit is contained in:
parent
06a91bd532
commit
b564a5e5e0
4 changed files with 134 additions and 90 deletions
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in a new issue