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:
parent
cf2842d22d
commit
9403cd047c
1 changed files with 34 additions and 25 deletions
|
|
@ -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') {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue