Skip to content

Commit 6cbd0e2

Browse files
authored
support new frontmatter for filtering the category dropdown (#58197)
1 parent e14c49a commit 6cbd0e2

File tree

5 files changed

+71
-10
lines changed

5 files changed

+71
-10
lines changed

src/frame/lib/frontmatter.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,14 @@ export const schema: Schema = {
405405
maxItems: 9,
406406
description: 'Array of articles to feature in the carousel section',
407407
},
408+
// Included categories for article grid filtering
409+
includedCategories: {
410+
type: 'array',
411+
items: {
412+
type: 'string',
413+
},
414+
description: 'Array of category names to include in the article grid dropdown filter',
415+
},
408416
},
409417
}
410418

src/landings/components/bespoke/BespokeLanding.tsx

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,16 @@ import { UtmPreserver } from '@/frame/components/UtmPreserver'
66
import { LandingCarousel } from '@/landings/components/shared/LandingCarousel'
77

88
export const BespokeLanding = () => {
9-
const { title, intro, heroImage, introLinks, tocItems, recommended } = useLandingContext()
9+
const {
10+
title,
11+
intro,
12+
heroImage,
13+
introLinks,
14+
tocItems,
15+
recommended,
16+
includedCategories,
17+
landingType,
18+
} = useLandingContext()
1019

1120
return (
1221
<DefaultLayout>
@@ -16,7 +25,11 @@ export const BespokeLanding = () => {
1625

1726
<div className="container-xl px-3 px-md-6 mt-6 mb-4">
1827
<LandingCarousel recommended={recommended} />
19-
<ArticleGrid tocItems={tocItems} />
28+
<ArticleGrid
29+
tocItems={tocItems}
30+
includedCategories={includedCategories}
31+
landingType={landingType}
32+
/>
2033
</div>
2134
</div>
2235
</DefaultLayout>

src/landings/components/discovery/DiscoveryLanding.tsx

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,16 @@ import { LandingCarousel } from '@/landings/components/shared/LandingCarousel'
66
import { UtmPreserver } from '@/frame/components/UtmPreserver'
77

88
export const DiscoveryLanding = () => {
9-
const { title, intro, heroImage, introLinks, tocItems, recommended } = useLandingContext()
9+
const {
10+
title,
11+
intro,
12+
heroImage,
13+
introLinks,
14+
tocItems,
15+
recommended,
16+
includedCategories,
17+
landingType,
18+
} = useLandingContext()
1019

1120
return (
1221
<DefaultLayout>
@@ -15,7 +24,11 @@ export const DiscoveryLanding = () => {
1524
<LandingHero title={title} intro={intro} heroImage={heroImage} introLinks={introLinks} />
1625
<div className="container-xl px-3 px-md-6 mt-6 mb-4">
1726
<LandingCarousel recommended={recommended} />
18-
<ArticleGrid tocItems={tocItems} />
27+
<ArticleGrid
28+
tocItems={tocItems}
29+
includedCategories={includedCategories}
30+
landingType={landingType}
31+
/>
1932
</div>
2033
</div>
2134
</DefaultLayout>

src/landings/components/shared/LandingArticleGridWithFilter.tsx

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,14 @@ import cx from 'classnames'
66
import { Link } from '@/frame/components/Link'
77
import { useTranslation } from '@/languages/components/useTranslation'
88
import { ArticleCardItems, ChildTocItem, TocItem } from '@/landings/types'
9+
import { LandingType } from '@/landings/context/LandingContext'
910

1011
import styles from './LandingArticleGridWithFilter.module.scss'
1112

1213
type ArticleGridProps = {
1314
tocItems: TocItem[]
15+
includedCategories?: string[]
16+
landingType: LandingType
1417
}
1518

1619
const ALL_CATEGORIES = 'all_categories'
@@ -66,7 +69,7 @@ const useResponsiveArticlesPerPage = () => {
6669
return articlesPerPage
6770
}
6871

69-
export const ArticleGrid = ({ tocItems }: ArticleGridProps) => {
72+
export const ArticleGrid = ({ tocItems, includedCategories, landingType }: ArticleGridProps) => {
7073
const { t } = useTranslation('product_landing')
7174
const [searchQuery, setSearchQuery] = useState('')
7275
const [selectedCategory, setSelectedCategory] = useState(ALL_CATEGORIES)
@@ -83,21 +86,42 @@ export const ArticleGrid = ({ tocItems }: ArticleGridProps) => {
8386
[tocItems],
8487
)
8588

89+
// Filter articles based on includedCategories for discovery landing pages
90+
// For bespoke landing pages, show all articles regardless of includedCategories
91+
const filteredArticlesByLandingType = useMemo(() => {
92+
if (landingType === 'discovery' && includedCategories && includedCategories.length > 0) {
93+
// For discovery pages, only include articles that have at least one matching category
94+
return allArticles.filter((article) => {
95+
if (!article.category || article.category.length === 0) return false
96+
return article.category.some((cat) =>
97+
includedCategories.some((included) => included.toLowerCase() === cat.toLowerCase()),
98+
)
99+
})
100+
}
101+
// For bespoke pages or when includedCategories is empty/undefined, return all articles
102+
return allArticles
103+
}, [allArticles, includedCategories, landingType])
104+
86105
// Reset to first page when articlesPerPage changes (screen size changes)
87106
useEffect(() => {
88107
setCurrentPage(1)
89108
}, [articlesPerPage])
90109

91-
// Extract unique categories from the articles
110+
// Extract unique categories from the filtered articles, filtering dropdown by includedCategories if provided
92111
const categories: string[] = [
93112
ALL_CATEGORIES,
94-
...Array.from(new Set(allArticles.flatMap((item) => item.category || []))).sort((a, b) =>
95-
a.localeCompare(b),
96-
),
113+
...Array.from(new Set(filteredArticlesByLandingType.flatMap((item) => item.category || [])))
114+
.filter((category) => {
115+
if (!includedCategories || includedCategories.length === 0) return true
116+
// Case-insensitive comparison for dropdown filtering
117+
const lowerCategory = category.toLowerCase()
118+
return includedCategories.some((included) => included.toLowerCase() === lowerCategory)
119+
})
120+
.sort((a, b) => a.localeCompare(b)),
97121
]
98122

99123
const applyFilters = () => {
100-
let results = allArticles
124+
let results = filteredArticlesByLandingType
101125

102126
if (searchQuery) {
103127
results = results.filter((token) => {

src/landings/context/LandingContext.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ export type LandingContextT = {
2626
introLinks?: Record<string, string>
2727
// For journey landing pages
2828
journeyTracks?: JourneyTrack[]
29+
// For article grid category filtering
30+
includedCategories?: string[]
2931
}
3032

3133
export const LandingContext = createContext<LandingContextT | null>(null)
@@ -83,5 +85,6 @@ export const getLandingContextFromRequest = async (
8385
introLinks: page.introLinks || null,
8486
recommended,
8587
journeyTracks,
88+
includedCategories: page.includedCategories || [],
8689
}
8790
}

0 commit comments

Comments
 (0)