Sticky Sections
Section headers with pushing effect
Demonstrates iOS-style sticky headers using the stickyIndices prop for 20 sections with 10 items each. When a new header scrolls up, it 'pushes' the previous sticky header out of the view.
Section A
Item 0-0
Item 0-1
Item 0-2
Item 0-3
<script setup lang="ts">
import type { Ref } from 'vue';
import { VirtualScroll } from '@pdanpdan/virtual-scroll';
import { computed, inject, ref } from 'vue';
import ExampleContainer from '#/components/ExampleContainer.vue';
import ScrollStatus from '#/components/ScrollStatus.vue';
import { useExampleScroll } from '#/lib/useExampleScroll';
import { html as highlightedCode } from './+Page.vue?highlight';
const sectionCount = 20;
const itemsPerSection = 10;
const items = computed(() => {
const result = [];
for (let s = 0; s < sectionCount; s++) {
// Header item
result.push({ type: 'header', label: `Section ${ String.fromCharCode(65 + s) }` });
// Data items
for (let i = 0; i < itemsPerSection; i++) {
result.push({ type: 'item', label: `Item ${ s }-${ i }` });
}
}
return result;
});
const stickyIndices = computed(() => {
const indices = [];
for (let i = 0; i < items.value.length; i += (itemsPerSection + 1)) {
indices.push(i);
}
return indices;
});
const {
scrollDetails,
onScroll,
} = useExampleScroll();
const debugMode = inject<Ref<boolean>>('debugMode', ref(false));
</script>
<template>
<ExampleContainer :code="highlightedCode">
<template #title>
<span class="example-title example-title--group-3">Sticky Sections</span>
</template>
<template #description>
Demonstrates iOS-style sticky headers using the <strong>stickyIndices</strong> prop for {{ sectionCount }} sections with {{ itemsPerSection }} items each. When a new header scrolls up, it 'pushes' the previous sticky header out of the view.
</template>
<template #icon>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="example-icon example-icon--group-3"
>
<path stroke-linecap="round" stroke-linejoin="round" d="M17.593 3.322c1.1.128 1.907 1.077 1.907 2.185V21L12 17.25 4.5 21V5.507c0-1.108.806-2.057 1.907-2.185a48.507 48.507 0 0 1 11.186 0Z" />
</svg>
</template>
<template #subtitle>
Section headers with pushing effect
</template>
<template #controls>
<ScrollStatus :scroll-details="scrollDetails" direction="vertical" />
</template>
<VirtualScroll
:debug="debugMode"
class="example-container"
:items="items"
:item-size="50"
:sticky-indices="stickyIndices"
aria-label="Sticky sections list"
@scroll="onScroll"
>
<template #item="{ item, isStickyActive }">
<div
v-if="item.type === 'header'"
class="example-sticky-header example-sticky-header--start h-full transition-shadow"
:class="{ 'shadow-md z-1': isStickyActive }"
>
{{ item.label }}
</div>
<div v-else class="example-vertical-item example-vertical-item--fixed">
{{ item.label }}
</div>
</template>
</VirtualScroll>
</ExampleContainer>
</template>
- Scroll Status
- Directionvertical
- Current Item #-
- Rendered Range #0:0
- Total Size (px)0h
- Viewport Size (px)0h
- Scroll Offset (px)0y