11"use client" ;
22
3- import { AppShell , Header , Content , MotionProvider } from "@appshell/react" ;
3+ import { useState } from "react" ;
4+ import { AppShell , Header , Content , HeaderNav , HeaderNavItem , MotionProvider } from "@appshell/react" ;
45import { framerMotionAdapter } from "@appshell/react/motion-framer" ;
5- import { Search , SlidersHorizontal , Heart , Download , MapPin , Eye } from "lucide-react" ;
6+ import type { HeaderBehavior } from "@appshell/react" ;
7+ import { Search , SlidersHorizontal , Heart , Download , MapPin , Eye , Navigation , Type , SearchCheck , Layers } from "lucide-react" ;
68
79const photos = [
810 {
@@ -123,18 +125,56 @@ function formatLikes(n: number) {
123125 return n >= 1000 ? `${ ( n / 1000 ) . toFixed ( 1 ) } k` : String ( n ) ;
124126}
125127
128+ const tabs : { label : string ; behavior : HeaderBehavior ; icon : React . ReactNode ; description : string } [ ] = [
129+ {
130+ label : "Nav" ,
131+ behavior : "reveal-nav" ,
132+ icon : < Navigation className = "size-3.5" /> ,
133+ description : "Reveals the nav bar on scroll up" ,
134+ } ,
135+ {
136+ label : "Context" ,
137+ behavior : "reveal-context" ,
138+ icon : < Type className = "size-3.5" /> ,
139+ description : "Reveals the title & subtitle on scroll up" ,
140+ } ,
141+ {
142+ label : "Search" ,
143+ behavior : "reveal-search" ,
144+ icon : < SearchCheck className = "size-3.5" /> ,
145+ description : "Reveals the search row on scroll up" ,
146+ } ,
147+ {
148+ label : "All" ,
149+ behavior : "reveal-all" ,
150+ icon : < Layers className = "size-3.5" /> ,
151+ description : "Reveals all rows on scroll up" ,
152+ } ,
153+ ] ;
154+
126155export default function RevealHeaderPage ( ) {
156+ const [ activeIndex , setActiveIndex ] = useState ( 0 ) ;
157+ const activeBehavior = tabs [ activeIndex ] . behavior ;
158+
127159 return (
128160 < MotionProvider adapter = { framerMotionAdapter } >
129161 < AppShell safeArea >
130162 < Header
131- behavior = "reveal-nav"
163+ behavior = { activeBehavior }
132164 theme = "light"
133165 logo = {
134166 < span className = "text-lg font-bold tracking-tight" > Discover</ span >
135167 }
136- title = "Explore"
137- subtitle = "Scroll down to see the header hide, scroll up to reveal it"
168+ nav = {
169+ < HeaderNav >
170+ < HeaderNavItem label = "Explore" active />
171+ < HeaderNavItem label = "Collections" />
172+ < HeaderNavItem label = "Photographers" />
173+ < HeaderNavItem label = "Trending" />
174+ </ HeaderNav >
175+ }
176+ title = "Explore Photography"
177+ subtitle = "Scroll down to hide the header, then scroll up to see which rows reveal"
138178 searchContent = {
139179 < div className = "flex items-center gap-2" >
140180 < div className = "relative flex-1" >
@@ -147,7 +187,7 @@ export default function RevealHeaderPage() {
147187 </ div >
148188 < button
149189 type = "button"
150- className = "flex items-center gap-1.5 rounded-xl border border-gray-200/80 bg-white px-3.5 py-2.5 text-sm font-medium text-gray-600 hover:bg-gray-50 hover:border-gray-300 transition-all"
190+ className = "flex items-center gap-1.5 rounded-xl border border-gray-200/80 bg-white px-3.5 py-2.5 text-sm font-medium text-gray-600 hover:bg-gray-50 hover:border-gray-300 transition-all cursor-pointer "
151191 >
152192 < SlidersHorizontal className = "size-4" />
153193 < span className = "hidden sm:inline" > Filters</ span >
@@ -157,12 +197,46 @@ export default function RevealHeaderPage() {
157197 actions = {
158198 < button
159199 type = "button"
160- className = "rounded-xl bg-gray-900 px-4 py-2 text-sm font-medium text-white hover:bg-gray-800 transition-colors"
200+ className = "rounded-xl bg-gray-900 px-4 py-2 text-sm font-medium text-white hover:bg-gray-800 transition-colors cursor-pointer "
161201 >
162202 Upload
163203 </ button >
164204 }
165205 />
206+
207+ { /* Sticky tab switcher below header */ }
208+ < div className = "sticky top-14 z-40 w-full border-b border-gray-100 bg-white/90 backdrop-blur-xl" >
209+ < div className = "mx-auto max-w-5xl px-4 sm:px-6 py-3" >
210+ < div className = "flex items-center gap-2 overflow-x-auto no-scrollbar" >
211+ < span className = "shrink-0 text-xs font-medium text-gray-400 uppercase tracking-wider mr-1" >
212+ Reveal variant
213+ </ span >
214+ { tabs . map ( ( tab , i ) => (
215+ < button
216+ key = { tab . behavior }
217+ type = "button"
218+ onClick = { ( ) => setActiveIndex ( i ) }
219+ className = { `
220+ shrink-0 flex items-center gap-1.5 rounded-full px-3.5 py-1.5 text-sm font-medium
221+ transition-all duration-200 cursor-pointer
222+ ${
223+ i === activeIndex
224+ ? "bg-gray-900 text-white shadow-sm"
225+ : "bg-gray-100 text-gray-600 hover:bg-gray-200 hover:text-gray-800"
226+ }
227+ ` }
228+ >
229+ { tab . icon }
230+ { tab . label }
231+ </ button >
232+ ) ) }
233+ </ div >
234+ < p className = "mt-1.5 text-xs text-gray-400" >
235+ { tabs [ activeIndex ] . description }
236+ </ p >
237+ </ div >
238+ </ div >
239+
166240 < Content className = "pb-8" >
167241 < div className = "mx-auto max-w-5xl px-4 sm:px-6 pt-6" >
168242 < div className = "columns-1 sm:columns-2 lg:columns-3 gap-4 space-y-4" >
@@ -202,14 +276,14 @@ export default function RevealHeaderPage() {
202276 < div className = "absolute top-3 right-3 flex items-center gap-1.5 opacity-0 group-hover:opacity-100 transition-all duration-500 ease-out translate-y-1 group-hover:translate-y-0" >
203277 < button
204278 type = "button"
205- className = "flex items-center justify-center size-8 rounded-xl bg-white/90 backdrop-blur-sm text-gray-700 hover:bg-white hover:text-red-500 transition-colors shadow-sm"
279+ className = "flex items-center justify-center size-8 rounded-xl bg-white/90 backdrop-blur-sm text-gray-700 hover:bg-white hover:text-red-500 transition-colors shadow-sm cursor-pointer "
206280 aria-label = "Like"
207281 >
208282 < Heart className = "size-4" />
209283 </ button >
210284 < button
211285 type = "button"
212- className = "flex items-center justify-center size-8 rounded-xl bg-white/90 backdrop-blur-sm text-gray-700 hover:bg-white hover:text-gray-900 transition-colors shadow-sm"
286+ className = "flex items-center justify-center size-8 rounded-xl bg-white/90 backdrop-blur-sm text-gray-700 hover:bg-white hover:text-gray-900 transition-colors shadow-sm cursor-pointer "
213287 aria-label = "Download"
214288 >
215289 < Download className = "size-4" />
@@ -236,7 +310,7 @@ export default function RevealHeaderPage() {
236310 { /* Floating variant indicator */ }
237311 < div className = "fixed bottom-4 left-4 z-50 flex items-center gap-1.5 rounded-full bg-black/70 backdrop-blur-sm px-3 py-1.5 text-[11px] font-mono text-white/80 shadow-lg" >
238312 < span className = "size-1.5 rounded-full bg-emerald-400 animate-pulse" />
239- behavior="reveal-nav " theme="light"
313+ behavior="{ activeBehavior } " theme="light"
240314 </ div >
241315 </ AppShell >
242316 </ MotionProvider >
0 commit comments