move ShowMoreOptionsBanner inline where it's used

This commit is contained in:
FTCHD
2026-07-11 23:34:18 +03:00
parent 4a8669db17
commit a07fb0b093
2 changed files with 58 additions and 58 deletions
-56
View File
@@ -1,56 +0,0 @@
import { ChevronDownIcon } from 'lucide-react'
import { startTransition, useEffect } from 'react'
import { usePersistedStore } from '../../store/persisted'
export default function ShowMoreOptionsBanner() {
const acknowledgements = usePersistedStore((state) => state.acknowledgements)
const showMoreOptions = !acknowledgements.includes('showMoreOptions')
useEffect(() => {
if (acknowledgements.includes('showMoreOptions')) return
const handleScroll = () => {
usePersistedStore.setState((prev) => {
if (prev.acknowledgements.includes('showMoreOptions')) return prev
return {
acknowledgements: [...prev.acknowledgements, 'showMoreOptions'],
}
})
}
window.addEventListener('scroll', handleScroll, { once: true })
return () => {
window.removeEventListener('scroll', handleScroll)
}
}, [acknowledgements])
if (!showMoreOptions) return null
return (
<div
className="absolute flex flex-col items-center justify-center w-full gap-1 bg-white dark:bg-[#121212] bottom-0 group py-2"
onClick={() => {
startTransition(() => {
usePersistedStore.setState((prev) => ({
acknowledgements: [...prev.acknowledgements, 'showMoreOptions'],
}))
})
requestAnimationFrame(() => {
setTimeout(() => {
scrollTo({
top: document.body.scrollHeight,
behavior: 'smooth',
})
}, 400)
})
}}
>
<p className="text-small animate-show-more-title group-hover:text-foreground-500 text-foreground-400">
Show more options
</p>
<ChevronDownIcon className="size-5 stroke-foreground-400 animate-show-more group-hover:stroke-foreground-500" />
</div>
)
}
+58 -2
View File
@@ -1,5 +1,6 @@
import { Accordion, AccordionItem, Avatar } from '@heroui/react'
import {
ChevronDownIcon,
CopyIcon,
DiamondPercentIcon,
FilterIcon,
@@ -8,8 +9,8 @@ import {
ServerIcon,
WrenchIcon,
} from 'lucide-react'
import { type ComponentType, type ReactNode, useMemo } from 'react'
import ShowMoreOptionsBanner from '../ShowMoreOptionsBanner'
import { type ComponentType, type ReactNode, startTransition, useEffect, useMemo } from 'react'
import { usePersistedStore } from '../../../store/persisted'
// Avatar/indicator/title per option category — exactly what each page's accordion rendered.
export const CATEGORY_META: Record<
@@ -110,3 +111,58 @@ export default function OptionsAccordion({
</div>
)
}
// A one-time nudge pinned to the bottom of the banner-wrapped accordion, inviting the user to
// scroll for more options. Dismisses itself the first time the user scrolls, and is remembered.
function ShowMoreOptionsBanner() {
const acknowledgements = usePersistedStore((state) => state.acknowledgements)
const showMoreOptions = !acknowledgements.includes('showMoreOptions')
useEffect(() => {
if (acknowledgements.includes('showMoreOptions')) return
const handleScroll = () => {
usePersistedStore.setState((prev) => {
if (prev.acknowledgements.includes('showMoreOptions')) return prev
return {
acknowledgements: [...prev.acknowledgements, 'showMoreOptions'],
}
})
}
window.addEventListener('scroll', handleScroll, { once: true })
return () => {
window.removeEventListener('scroll', handleScroll)
}
}, [acknowledgements])
if (!showMoreOptions) return null
return (
<div
className="absolute flex flex-col items-center justify-center w-full gap-1 bg-white dark:bg-[#121212] bottom-0 group py-2"
onClick={() => {
startTransition(() => {
usePersistedStore.setState((prev) => ({
acknowledgements: [...prev.acknowledgements, 'showMoreOptions'],
}))
})
requestAnimationFrame(() => {
setTimeout(() => {
scrollTo({
top: document.body.scrollHeight,
behavior: 'smooth',
})
}, 400)
})
}}
>
<p className="text-small animate-show-more-title group-hover:text-foreground-500 text-foreground-400">
Show more options
</p>
<ChevronDownIcon className="size-5 stroke-foreground-400 animate-show-more group-hover:stroke-foreground-500" />
</div>
)
}