feat: add sticky header with scroll shadow to admin pages

Make page headers sticky with subtle shadow on scroll. Fix min-height to 90px to prevent jumping when switching tabs. Modernize layout to use full viewport height.
This commit is contained in:
Justin Edmund 2025-11-03 23:03:40 -08:00
parent cf2842d22d
commit 9403cd047c

View file

@ -1,9 +1,22 @@
<script lang="ts"> <script lang="ts">
export let noHorizontalPadding = false const { noHorizontalPadding = false } = $props<{ noHorizontalPadding?: boolean }>()
let scrollContainer: HTMLElement
let isScrolled = $state(false)
function handleScroll(e: Event) {
const target = e.target as HTMLElement
isScrolled = target.scrollTop > 0
}
</script> </script>
<section class="admin-page" class:no-horizontal-padding={noHorizontalPadding}> <section
<div class="page-header"> class="admin-page"
class:no-horizontal-padding={noHorizontalPadding}
bind:this={scrollContainer}
onscroll={handleScroll}
>
<div class="page-header" class:scrolled={isScrolled}>
<slot name="header" /> <slot name="header" />
</div> </div>
@ -24,38 +37,34 @@
.admin-page { .admin-page {
background: white; background: white;
border-radius: $card-corner-radius; border-radius: $corner-radius-lg;
box-sizing: border-box; box-sizing: border-box;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
margin: 0 auto $unit-2x; margin: 0;
width: calc(100% - #{$unit-6x}); width: 100%;
max-width: 900px; // Much wider for admin height: 100vh;
min-height: calc(100vh - #{$unit-16x}); // Full height minus margins overflow-y: auto;
overflow: visible; overflow-x: hidden;
&:first-child {
margin-top: 0;
}
@include breakpoint('phone') {
margin-bottom: $unit-3x;
width: calc(100% - #{$unit-4x});
}
@include breakpoint('small-phone') {
width: calc(100% - #{$unit-3x});
}
} }
.page-header { .page-header {
position: sticky;
top: 0;
z-index: $z-index-sticky;
background: white;
box-sizing: border-box; box-sizing: border-box;
min-height: 110px; min-height: 90px;
padding: $unit-4x; padding: $unit-3x $unit-4x;
display: flex; display: flex;
transition: box-shadow 0.2s ease;
&.scrolled {
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}
@include breakpoint('phone') { @include breakpoint('phone') {
padding: $unit-3x; padding: $unit-2x;
} }
@include breakpoint('small-phone') { @include breakpoint('small-phone') {