add more breakpoints to carousel

This commit is contained in:
jeffvli
2025-11-22 14:22:05 -08:00
parent 2b70adc1f6
commit 958ded6988
3 changed files with 87 additions and 64 deletions
@@ -16,14 +16,12 @@
min-height: 400px; min-height: 400px;
padding: var(--theme-spacing-xl); padding: var(--theme-spacing-xl);
overflow: hidden; overflow: hidden;
--items-per-row: 1;
} }
.carousel-item { .carousel-item {
position: relative; position: relative;
width: 100%; width: 100%;
min-height: 400px; min-height: 440px;
overflow: hidden; overflow: hidden;
border-radius: var(--theme-radius-md); border-radius: var(--theme-radius-md);
isolation: isolate; isolation: isolate;
@@ -51,7 +49,7 @@
justify-content: flex-start; justify-content: flex-start;
width: 100%; width: 100%;
height: 100%; height: 100%;
min-height: 400px; min-height: 440px;
padding: var(--theme-spacing-xl); padding: var(--theme-spacing-xl);
} }
@@ -73,9 +71,9 @@
align-items: center; align-items: center;
justify-content: center; justify-content: center;
width: 100%; width: 100%;
height: 200px; height: 250px;
min-height: 200px; min-height: 250px;
max-height: 200px; max-height: 250px;
} }
.metadata-section { .metadata-section {
@@ -170,25 +168,49 @@
transform: translateY(-50%) scale(0.95); transform: translateY(-50%) scale(0.95);
} }
@container (min-width: 640px) { @container (min-width: $mantine-breakpoint-xs) {
.carousel { .carousel-item {
--items-per-row: 1; min-height: 480px;
}
.content {
min-height: 480px;
}
.title-section {
height: 60px;
min-height: 60px;
max-height: 60px;
}
.image-section {
height: 300px;
min-height: 300px;
max-height: 300px;
}
.metadata-section {
height: 80px;
min-height: 80px;
max-height: 80px;
}
.album-image {
max-width: 160px;
} }
} }
@container (min-width: $mantine-breakpoint-sm) { @container (min-width: $mantine-breakpoint-sm) {
.carousel { .carousel {
--items-per-row: 3;
gap: var(--theme-spacing-lg); gap: var(--theme-spacing-lg);
} }
.carousel-item { .carousel-item {
min-height: 450px; min-height: 500px;
} }
.content { .content {
min-height: 450px; min-height: 500px;
} }
.title-section { .title-section {
@@ -198,9 +220,9 @@
} }
.image-section { .image-section {
height: 220px; height: 280px;
min-height: 220px; min-height: 280px;
max-height: 220px; max-height: 280px;
} }
.metadata-section { .metadata-section {
@@ -215,16 +237,12 @@
} }
@container (min-width: $mantine-breakpoint-md) { @container (min-width: $mantine-breakpoint-md) {
.carousel {
--items-per-row: 4;
}
.carousel-item { .carousel-item {
min-height: 500px; min-height: 550px;
} }
.content { .content {
min-height: 500px; min-height: 550px;
} }
.title-section { .title-section {
@@ -234,9 +252,9 @@
} }
.image-section { .image-section {
height: 250px; height: 320px;
min-height: 250px; min-height: 320px;
max-height: 250px; max-height: 320px;
} }
.metadata-section { .metadata-section {
@@ -251,16 +269,12 @@
} }
@container (min-width: $mantine-breakpoint-xl) { @container (min-width: $mantine-breakpoint-xl) {
.carousel {
--items-per-row: 5;
}
.carousel-item { .carousel-item {
min-height: 550px; min-height: 600px;
} }
.content { .content {
min-height: 550px; min-height: 600px;
} }
.title-section { .title-section {
@@ -270,9 +284,9 @@
} }
.image-section { .image-section {
height: 280px; height: 360px;
min-height: 280px; min-height: 360px;
max-height: 280px; max-height: 360px;
} }
.metadata-section { .metadata-section {
@@ -45,16 +45,19 @@ interface FeatureCarouselProps {
const getItemsPerRow = (breakpoints: { const getItemsPerRow = (breakpoints: {
is2xl: boolean; is2xl: boolean;
is3xl: boolean;
isLg: boolean; isLg: boolean;
isMd: boolean; isMd: boolean;
isSm: boolean; isSm: boolean;
isXl: boolean; isXl: boolean;
}) => { }) => {
if (breakpoints.is3xl) return 6;
if (breakpoints.is2xl) return 5; if (breakpoints.is2xl) return 5;
if (breakpoints.isXl) return 5; if (breakpoints.isXl) return 5;
if (breakpoints.isLg) return 4; if (breakpoints.isLg) return 4;
if (breakpoints.isMd) return 3; if (breakpoints.isMd) return 3;
return 1; if (breakpoints.isSm) return 2;
return 2;
}; };
interface CarouselItemProps { interface CarouselItemProps {
@@ -143,6 +146,7 @@ export const FeatureCarousel = ({ data }: FeatureCarouselProps) => {
const [startIndex, setStartIndex] = useState(0); const [startIndex, setStartIndex] = useState(0);
const { const {
is2xl, is2xl,
is3xl,
isLg, isLg,
isMd, isMd,
isSm, isSm,
@@ -150,6 +154,7 @@ export const FeatureCarousel = ({ data }: FeatureCarouselProps) => {
ref: containerRef, ref: containerRef,
} = useContainerQuery({ } = useContainerQuery({
'2xl': 1920, '2xl': 1920,
'3xl': 2560,
lg: 1024, lg: 1024,
md: 768, md: 768,
sm: 640, sm: 640,
@@ -157,8 +162,8 @@ export const FeatureCarousel = ({ data }: FeatureCarouselProps) => {
}); });
const itemsPerRow = useMemo( const itemsPerRow = useMemo(
() => getItemsPerRow({ is2xl, isLg, isMd, isSm, isXl }), () => getItemsPerRow({ is2xl, is3xl, isLg, isMd, isSm, isXl }),
[is2xl, isLg, isMd, isSm, isXl], [is2xl, is3xl, isLg, isMd, isSm, isXl],
); );
const visibleItems = useMemo(() => { const visibleItems = useMemo(() => {
@@ -198,6 +203,7 @@ export const FeatureCarousel = ({ data }: FeatureCarouselProps) => {
exit="exit" exit="exit"
initial="enter" initial="enter"
key={`carousel-${startIndex}`} key={`carousel-${startIndex}`}
style={{ '--items-per-row': itemsPerRow } as React.CSSProperties}
variants={fadeVariants} variants={fadeVariants}
> >
{visibleItems.map((album) => ( {visibleItems.map((album) => (
@@ -7,6 +7,7 @@ import { NativeScrollArea } from '/@/renderer/components/native-scroll-area/nati
import { albumQueries } from '/@/renderer/features/albums/api/album-api'; import { albumQueries } from '/@/renderer/features/albums/api/album-api';
import { AlbumInfiniteCarousel } from '/@/renderer/features/albums/components/album-infinite-carousel'; import { AlbumInfiniteCarousel } from '/@/renderer/features/albums/components/album-infinite-carousel';
import { AnimatedPage } from '/@/renderer/features/shared/components/animated-page'; import { AnimatedPage } from '/@/renderer/features/shared/components/animated-page';
import { LibraryContainer } from '/@/renderer/features/shared/components/library-container';
import { LibraryHeaderBar } from '/@/renderer/features/shared/components/library-header-bar'; import { LibraryHeaderBar } from '/@/renderer/features/shared/components/library-header-bar';
import { import {
HomeItem, HomeItem,
@@ -115,34 +116,36 @@ const HomeRoute = () => {
}} }}
ref={scrollAreaRef} ref={scrollAreaRef}
> >
<Stack <LibraryContainer>
gap="lg" <Stack
mb="5rem" gap="lg"
pt={windowBarStyle === Platform.WEB ? '5rem' : '3rem'} mb="5rem"
px="2rem" pt={windowBarStyle === Platform.WEB ? '5rem' : '3rem'}
> px="2rem"
{homeFeature && <FeatureCarousel data={featureItemsWithImage} />} >
{sortedCarousel.map((carousel) => { {homeFeature && <FeatureCarousel data={featureItemsWithImage} />}
if (carousel.itemType === LibraryItem.ALBUM) { {sortedCarousel.map((carousel) => {
return ( if (carousel.itemType === LibraryItem.ALBUM) {
<AlbumInfiniteCarousel return (
key={`carousel-${carousel.uniqueId}`} <AlbumInfiniteCarousel
rowCount={1} key={`carousel-${carousel.uniqueId}`}
sortBy={carousel.sortBy} rowCount={1}
sortOrder={carousel.sortOrder} sortBy={carousel.sortBy}
title={carousel.title} sortOrder={carousel.sortOrder}
/> title={carousel.title}
); />
} );
}
if ('data' in carousel && 'query' in carousel) {
// TODO: Create SongInfiniteCarousel
return null;
}
if ('data' in carousel && 'query' in carousel) {
// TODO: Create SongInfiniteCarousel
return null; return null;
} })}
</Stack>
return null; </LibraryContainer>
})}
</Stack>
</NativeScrollArea> </NativeScrollArea>
</AnimatedPage> </AnimatedPage>
); );