Skip to content

Commit 3ef8879

Browse files
authored
Add new landing page article grid (#57757)
1 parent 75f067f commit 3ef8879

File tree

9 files changed

+343
-147
lines changed

9 files changed

+343
-147
lines changed

data/ui.yml

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -261,18 +261,17 @@ footer:
261261
expert_services: Expert services
262262
blog: Blog
263263
machine: Some of this content may be machine- or AI-translated.
264-
bespoke_landing:
265-
articles: Articles
266-
all_categories: All categories
267-
search_articles: Search articles
268-
discovery_landing:
269-
recommended: Recommended
270-
articles: Articles
271-
all_categories: All categories
272-
search_articles: Search articles
273264
journey_landing:
274265
articles: '{{ number }} Articles'
275266
product_landing:
267+
article_grid:
268+
heading: Articles
269+
all_categories: All categories
270+
search_articles: Search articles
271+
no_articles_found: No articles found matching your criteria.
272+
showing_results: Showing {start}-{end} of {total}
273+
carousel:
274+
recommended: Recommended
276275
quickstart: Quickstart
277276
reference: Reference
278277
overview: Overview

src/fixtures/fixtures/data/ui.yml

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -261,18 +261,17 @@ footer:
261261
expert_services: Expert services
262262
blog: Blog
263263
machine: Some of this content may be machine- or AI-translated.
264-
bespoke_landing:
265-
articles: Articles
266-
all_categories: All categories
267-
search_articles: Search articles
268-
discovery_landing:
269-
recommended: Recommended
270-
articles: Articles
271-
all_categories: All categories
272-
search_articles: Search articles
273264
journey_landing:
274265
articles: '{{ number }} Articles'
275266
product_landing:
267+
article_grid:
268+
heading: Articles
269+
all_categories: All categories
270+
search_articles: Search articles
271+
no_articles_found: No articles found matching your criteria.
272+
showing_results: Showing {start}-{end} of {total}
273+
carousel:
274+
recommended: Recommended
276275
quickstart: Quickstart
277276
reference: Reference
278277
overview: Overview

src/frame/middleware/context/generic-toc.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ export default async function genericToc(req: ExtendedRequest, res: Response, ne
106106
recurse: isRecursive,
107107
renderIntros,
108108
includeHidden,
109+
textOnly:
110+
isNewLandingPageFeature(req) || isNewLandingPage(req.context.currentLayoutName || ''),
109111
})
110112
}
111113

@@ -120,6 +122,8 @@ export default async function genericToc(req: ExtendedRequest, res: Response, ne
120122
? true
121123
: false,
122124
includeHidden,
125+
textOnly:
126+
isNewLandingPageFeature(req) || isNewLandingPage(req.context.currentLayoutName || ''),
123127
})
124128
}
125129

@@ -132,6 +136,7 @@ type Options = {
132136
recurse: boolean
133137
renderIntros: boolean
134138
includeHidden: boolean
139+
textOnly: boolean
135140
}
136141

137142
async function getTocItems(node: Tree, context: Context, opts: Options): Promise<ToC[]> {
@@ -154,13 +159,13 @@ async function getTocItems(node: Tree, context: Context, opts: Options): Promise
154159
if (page.rawIntro) {
155160
// The intro can contain Markdown even though it might not
156161
// contain any Liquid.
157-
// Deliberately don't use `textOnly:true` here because we intend
158-
// to display the intro, in a table of contents component,
159-
// with the HTML (dangerouslySetInnerHTML).
162+
// Use textOnly for new landing pages to strip HTML tags.
163+
// For other pages, we intend to display the intro in a table of contents
164+
// component with the HTML (dangerouslySetInnerHTML).
160165
intro = await page.renderProp(
161166
'rawIntro',
162167
context,
163-
context.currentLayoutName === 'category-landing' ? { textOnly: true } : {},
168+
opts.textOnly ? { textOnly: true } : {},
164169
)
165170
}
166171
}

src/landings/components/bespoke/BespokeLanding.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export const BespokeLanding = () => {
2020
<div data-search="article-body">
2121
<LandingHero title={title} intro={intro} heroImage={heroImage} introLinks={introLinks} />
2222

23-
<div data-search="hide">
23+
<div className="container-xl px-3 px-md-6 mt-6 mb-4">
2424
<ArticleGrid flatArticles={flatArticles} />
2525
</div>
2626
</div>

src/landings/components/shared/LandingArticleGridWithFilter.module.scss

Lines changed: 175 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,165 @@
11
@import "@primer/css/support/variables/layout.scss";
22
@import "@primer/css/support/mixins/layout.scss";
33

4+
.headerTitleText {
5+
font-size: var(--h3-size, 1.25rem);
6+
font-weight: var(--base-text-weight-semibold, 600);
7+
line-height: var(--heading-lineHeight);
8+
}
9+
10+
.noArticlesContainer {
11+
width: 100%;
12+
text-align: left;
13+
}
14+
15+
.noArticlesText {
16+
color: var(--fgColor-muted, var(--color-fg-muted, #656d76));
17+
}
18+
19+
.articleCardBox {
20+
display: flex;
21+
flex-direction: column;
22+
padding: 1.5rem;
23+
min-height: 7.5rem;
24+
box-shadow:
25+
0 0.0625rem 0.1875rem 0 rgba(31, 35, 40, 0.08),
26+
0 0.0625rem 0 0 rgba(31, 35, 40, 0.06);
27+
}
28+
29+
.cardHeader {
30+
display: flex;
31+
flex-direction: column;
32+
}
33+
34+
.cardTitle {
35+
margin: 0 0 0.5rem 0;
36+
font-size: 1.1rem;
37+
font-weight: var(--base-text-weight-semibold, 600);
38+
}
39+
40+
.cardTitleLink {
41+
color: var(--fgColor-accent);
42+
text-decoration: none;
43+
44+
&:hover {
45+
text-decoration: underline;
46+
}
47+
}
48+
49+
.cardIntro {
50+
margin: 0;
51+
color: var(--fgColor-muted);
52+
font-size: 0.9rem;
53+
line-height: 1.4;
54+
}
55+
56+
.tagsContainer {
57+
margin-bottom: 0.5rem;
58+
}
59+
60+
.filterHeader {
61+
display: flex;
62+
flex-direction: column;
63+
align-items: stretch;
64+
border-bottom: 1px solid var(--borderColor-default);
65+
padding-bottom: 1rem;
66+
margin-top: 3rem;
67+
margin-bottom: 1rem;
68+
gap: 0.75rem;
69+
70+
// Medium screens: horizontal layout with tighter spacing
71+
@include breakpoint(md) {
72+
flex-direction: row;
73+
align-items: center;
74+
gap: 0.75rem;
75+
}
76+
77+
// Large screens: horizontal layout with normal spacing
78+
@include breakpoint(lg) {
79+
gap: 1rem;
80+
}
81+
}
82+
83+
.titleAndDropdownRow {
84+
display: flex;
85+
flex-direction: row;
86+
align-items: center;
87+
gap: 0.75rem;
88+
flex-shrink: 0;
89+
90+
// Medium screens and up: maintain tight spacing, don't grow
91+
@include breakpoint(md) {
92+
gap: 1rem;
93+
flex-shrink: 0;
94+
flex-grow: 0;
95+
}
96+
}
97+
98+
.headerTitle {
99+
flex-shrink: 0;
100+
margin: 0;
101+
font-size: 1.5rem;
102+
font-weight: 600;
103+
text-align: left;
104+
width: auto;
105+
106+
// All screen sizes: keep title compact
107+
@include breakpoint(md) {
108+
flex-shrink: 0;
109+
width: auto;
110+
}
111+
}
112+
113+
.categoryDropdown {
114+
min-width: 12rem;
115+
flex: 1;
116+
117+
button {
118+
width: fit-content;
119+
text-align: left !important;
120+
121+
span {
122+
justify-content: start !important;
123+
}
124+
125+
// Medium screens: full width but constrained by container
126+
@include breakpoint(md) {
127+
width: 100%;
128+
}
129+
}
130+
131+
// Medium screens: smaller min-width and constrained max-width
132+
@include breakpoint(md) {
133+
min-width: 20rem;
134+
max-width: 30%;
135+
}
136+
137+
// Large screens: larger sizing
138+
@include breakpoint(lg) {
139+
min-width: 20rem;
140+
max-width: 40%;
141+
}
142+
}
143+
144+
.searchContainer {
145+
margin-left: 0;
146+
width: auto;
147+
148+
// Medium screens: flexible width with spacing
149+
@include breakpoint(md) {
150+
flex: 0 1 25%;
151+
min-width: 12.5rem;
152+
margin-left: auto;
153+
}
154+
155+
// Large screens: larger width with auto margin
156+
@include breakpoint(lg) {
157+
width: 30%;
158+
flex: 0 0 30%;
159+
margin-left: auto;
160+
}
161+
}
162+
4163
.articleGrid {
5164
display: grid;
6165
gap: 1.5rem;
@@ -25,12 +184,24 @@
25184
height: 100%;
26185
}
27186

28-
.cardContent {
187+
.paginationContainer {
29188
display: flex;
30189
flex-direction: column;
31-
height: 100%;
190+
justify-content: center;
191+
align-items: center;
192+
margin-top: 1rem;
193+
padding-top: 1rem;
194+
gap: 0.75rem;
195+
196+
// Medium screens and up: horizontal layout with space between
197+
@include breakpoint(md) {
198+
flex-direction: row;
199+
justify-content: space-between;
200+
gap: 0;
201+
}
32202
}
33203

34-
.cardFooter {
35-
margin-top: auto;
204+
.showingResults {
205+
color: var(--fgColor-muted, var(--color-fg-muted, #656d76));
206+
font-size: 0.875rem;
36207
}

0 commit comments

Comments
 (0)