fix some carousel stuff

This commit is contained in:
Pas 2025-05-03 18:18:35 -06:00
parent 3efd78025b
commit e1cf13cf3d
2 changed files with 48 additions and 50 deletions

View file

@ -295,42 +295,42 @@ input[type=range].styled-slider.slider-progress::-ms-fill-lower {
position: relative; position: relative;
-webkit-mask-image: linear-gradient( -webkit-mask-image: linear-gradient(
to bottom, to bottom,
rgba(0, 0, 0, 0), transparent,
rgba(0, 0, 0, 1) var(--mask-fade-distance), black var(--mask-fade-distance),
rgba(0, 0, 0, 1) calc(100% - var(--mask-fade-distance)), black calc(100% - var(--mask-fade-distance)),
rgba(0, 0, 0, 0) 100% transparent
); );
mask-image: var(-webkit-mask-image); mask-image: var(-webkit-mask-image);
z-index: 1; z-index: 1;
} }
.vertical-carousel-container.mask-none { .vertical-carousel-container.hide-top-gradient {
-webkit-mask-image: linear-gradient(
to bottom,
black,
black calc(100% - var(--mask-fade-distance)),
transparent
);
mask-image: var(-webkit-mask-image);
}
.vertical-carousel-container.hide-bottom-gradient {
-webkit-mask-image: linear-gradient(
to bottom,
transparent,
black var(--mask-fade-distance),
black
);
mask-image: var(-webkit-mask-image);
}
.vertical-carousel-container.hide-top-gradient.hide-bottom-gradient {
-webkit-mask-image: none; -webkit-mask-image: none;
mask-image: none; mask-image: none;
} }
.vertical-carousel-container.mask-image-bottom-only {
-webkit-mask-image: linear-gradient(
to bottom,
rgba(0, 0, 0, 1),
rgba(0, 0, 0, 1) calc(100% - var(--mask-fade-distance)),
rgba(0, 0, 0, 0) 100%
);
mask-image: var(-webkit-mask-image);
}
.vertical-carousel-container.mask-image-top-only {
-webkit-mask-image: linear-gradient(
to bottom,
rgba(0, 0, 0, 0),
rgba(0, 0, 0, 1) var(--mask-fade-distance),
rgba(0, 0, 0, 1)
);
mask-image: var(-webkit-mask-image);
}
@media (max-width: 768px) { @media (max-width: 768px) {
.vertical-carousel-container { .vertical-carousel-container {
--mask-fade-distance: 20px; --mask-fade-distance: 20px;
} }
} }

View file

@ -169,28 +169,27 @@ export function AppearancePart(props: {
const activeThemeRef = useRef<HTMLDivElement>(null); const activeThemeRef = useRef<HTMLDivElement>(null);
const [isAtTop, setIsAtTop] = useState(true); const [isAtTop, setIsAtTop] = useState(true);
const [isAtBottom, setIsAtBottom] = useState(false); const [isAtBottom, setIsAtBottom] = useState(false);
const topSentinelRef = useRef<HTMLDivElement>(null);
const bottomSentinelRef = useRef<HTMLDivElement>(null); const checkScrollPosition = () => {
const container = carouselRef.current;
if (!container) return;
setIsAtTop(container.scrollTop <= 0);
setIsAtBottom(
Math.abs(
container.scrollHeight - container.scrollTop - container.clientHeight,
) < 2,
);
};
useEffect(() => { useEffect(() => {
const observer = new IntersectionObserver( const container = carouselRef.current;
(entries) => { if (!container) return;
entries.forEach((entry) => {
if (entry.target === topSentinelRef.current) {
setIsAtTop(entry.isIntersecting);
}
if (entry.target === bottomSentinelRef.current) {
setIsAtBottom(entry.isIntersecting);
}
});
},
{ root: carouselRef.current, threshold: 1 },
);
if (topSentinelRef.current) observer.observe(topSentinelRef.current); container.addEventListener("scroll", checkScrollPosition);
if (bottomSentinelRef.current) observer.observe(bottomSentinelRef.current); checkScrollPosition(); // Check initial position
return () => observer.disconnect(); return () => container.removeEventListener("scroll", checkScrollPosition);
}, []); }, []);
useEffect(() => { useEffect(() => {
@ -207,6 +206,8 @@ export function AppearancePart(props: {
container.scrollTop - container.scrollTop -
containerRect.top - containerRect.top -
(containerRect.height - elementRect.height) / 2; (containerRect.height - elementRect.height) / 2;
checkScrollPosition(); // Update masks after scrolling
} }
}, [props.active]); }, [props.active]);
@ -263,16 +264,14 @@ export function AppearancePart(props: {
<div <div
ref={carouselRef} ref={carouselRef}
className={classNames( className={classNames(
"grid grid-cols-2 gap-4 max-w-[600px] max-h-[28rem] overflow-y-auto", "grid grid-cols-2 gap-4 max-w-[600px] max-h-[36rem] overflow-y-auto",
"vertical-carousel-container", "vertical-carousel-container",
{ {
"mask-none": isAtTop && isAtBottom, "hide-top-gradient": isAtTop,
"mask-image-bottom-only": isAtTop && !isAtBottom, "hide-bottom-gradient": isAtBottom,
"mask-image-top-only": !isAtTop && isAtBottom,
}, },
)} )}
> >
<div ref={topSentinelRef} className="absolute top-0 h-px" />
{availableThemes.map((v) => ( {availableThemes.map((v) => (
<div <div
key={v.id} key={v.id}
@ -287,7 +286,6 @@ export function AppearancePart(props: {
/> />
</div> </div>
))} ))}
<div ref={bottomSentinelRef} className="absolute bottom-0 h-px" />
</div> </div>
</div> </div>
</div> </div>