diff --git a/components/Blocks/CarouselCards/Filters/filters.module.css b/components/Blocks/CarouselCards/Filters/filters.module.css new file mode 100644 index 000000000..1a6c3fac4 --- /dev/null +++ b/components/Blocks/CarouselCards/Filters/filters.module.css @@ -0,0 +1,32 @@ +.container { + display: flex; + gap: var(--Spacing-x1); + overflow-x: auto; + scroll-snap-type: x mandatory; + scrollbar-width: none; +} + +.filter, +.filterSelected { + border-radius: var(--Corner-radius-Rounded); + padding: var(--Spacing-x1) var(--Spacing-x2); + transition: all 0.2s ease-in-out; + scroll-snap-align: start; + flex-shrink: 0; + font-size: var(--typography-Caption-Bold-Mobile-fontSize); + font-family: var(--typography-Body-Regular-fontFamily); + font-weight: 400; + cursor: pointer; +} + +.filter { + color: var(--UI-Text-High-contrast); + background: transparent; + border: 1px solid var(--UI-Input-Controls-Border-Hover); +} + +.filterSelected { + color: var(--Base-Text-Inverted); + background: var(--Base-Button-Tertiary-Fill-Normal); + border: 1px solid transparent; +} diff --git a/components/Blocks/CarouselCards/Filters/index.tsx b/components/Blocks/CarouselCards/Filters/index.tsx new file mode 100644 index 000000000..42b8e0cc1 --- /dev/null +++ b/components/Blocks/CarouselCards/Filters/index.tsx @@ -0,0 +1,36 @@ +"use client" + +import styles from "./filters.module.css" + +import type { CarouselCardFilter } from "@/types/enums/carouselCards" + +interface FiltersProps { + categories: Array<{ identifier: CarouselCardFilter; label: string }> + selectedFilter: CarouselCardFilter + onFilterSelect: (filter: CarouselCardFilter) => void +} + +export default function Filters({ + categories, + selectedFilter, + onFilterSelect, +}: FiltersProps) { + return ( +
+ {categories.map((category) => ( + + ))} +
+ ) +} diff --git a/components/Blocks/carouselCards.module.css b/components/Blocks/CarouselCards/carouselCards.module.css similarity index 87% rename from components/Blocks/carouselCards.module.css rename to components/Blocks/CarouselCards/carouselCards.module.css index 38fcc7653..4ea1a4c2a 100644 --- a/components/Blocks/carouselCards.module.css +++ b/components/Blocks/CarouselCards/carouselCards.module.css @@ -1,8 +1,3 @@ -.code { - padding: var(--Spacing-x2); - background: var(--Base-Surface-Secondary-light-Normal); -} - /* Mock styles for the carousel cards. Will be removed/replaced when the carousel functionality is implemented (SW-1542). diff --git a/components/Blocks/CarouselCards.tsx b/components/Blocks/CarouselCards/index.tsx similarity index 63% rename from components/Blocks/CarouselCards.tsx rename to components/Blocks/CarouselCards/index.tsx index a02a9c555..36323107e 100644 --- a/components/Blocks/CarouselCards.tsx +++ b/components/Blocks/CarouselCards/index.tsx @@ -1,7 +1,13 @@ +"use client" + +import { useState } from "react" + import ContentCard from "@/components/ContentCard" import SectionContainer from "@/components/Section/Container" import SectionHeader from "@/components/Section/Header" +import Filters from "./Filters" + import styles from "./carouselCards.module.css" import type { CarouselCardsProps } from "@/types/components/blocks/carouselCards" @@ -16,30 +22,36 @@ export default function CarouselCards({ carousel_cards }: CarouselCardsProps) { link, } = carousel_cards + const [activeFilter, setActiveFilter] = useState( + enableFilters ? defaultFilter : null + ) + + const filteredCards = !activeFilter + ? cards + : cards.filter( + (card) => "filterId" in card && card.filterId === activeFilter + ) + return ( - {enableFilters && ( -
- Filter data -
- {/* Filter component will go here */} -
-              {JSON.stringify({ filterCategories, defaultFilter }, null, 2)}
-            
-
-
+ {filterCategories.length > 0 && activeFilter && ( + )} {/* Carousel functionality will go here */}
- {cards.map((card) => ( + {filteredCards.map((card) => ( ))}
diff --git a/components/ContentCard/index.tsx b/components/ContentCard/index.tsx index 727b1afc4..b67842a58 100644 --- a/components/ContentCard/index.tsx +++ b/components/ContentCard/index.tsx @@ -6,7 +6,7 @@ import Subtitle from "@/components/TempDesignSystem/Text/Subtitle" import styles from "./contentCard.module.css" -import type { ContentCardLinkProps,ContentCardProps } from "./contentCard" +import type { ContentCardLinkProps, ContentCardProps } from "./contentCard" export default function ContentCard({ heading, diff --git a/lib/graphql/Fragments/Blocks/CarouselCards.graphql b/lib/graphql/Fragments/Blocks/CarouselCards.graphql index 1b2cbaa99..24fd31a6e 100644 --- a/lib/graphql/Fragments/Blocks/CarouselCards.graphql +++ b/lib/graphql/Fragments/Blocks/CarouselCards.graphql @@ -23,7 +23,6 @@ fragment CarouselCards_StartPage on StartPageBlocksCarouselCards { carousel_cards { heading enable_filters - default_filter card_groups { filter_category { filter_identifier diff --git a/server/routers/contentstack/schemas/blocks/carouselCards.ts b/server/routers/contentstack/schemas/blocks/carouselCards.ts index 4f4205441..56c7f6a40 100644 --- a/server/routers/contentstack/schemas/blocks/carouselCards.ts +++ b/server/routers/contentstack/schemas/blocks/carouselCards.ts @@ -33,7 +33,6 @@ const carouselCardsWithFilters = z.object({ }), }) ), - default_filter: z.nativeEnum(CarouselCardFilterEnum), }) const carouselCardsWithoutFilters = z.object({ @@ -50,7 +49,6 @@ const carouselCardsWithoutFilters = z.object({ }), }) ), - default_filter: z.null(), }) export const carouselCardsSchema = z.object({ @@ -112,7 +110,9 @@ export const carouselCardsSchema = z.object({ filterId: group.filter_category.filter_identifier, })) ), - defaultFilter: data.default_filter, + defaultFilter: + data.card_groups[0]?.filter_category.filter_identifier ?? + filterCategories[0]?.identifier, link: data.link ? { href: data.link.href, text: data.link.title } : undefined, diff --git a/types/enums/carouselCards.ts b/types/enums/carouselCards.ts index 23b123c87..cc36eae86 100644 --- a/types/enums/carouselCards.ts +++ b/types/enums/carouselCards.ts @@ -1,5 +1,6 @@ export const CarouselCardFilterEnum = { offers: "offers", + popular_destinations: "popular_destinations", popular_hotels: "popular_hotels", popular_cities: "popular_cities", spa_wellness: "spa_wellness",