Skip to content

Commit c4a1366

Browse files
authored
Merge pull request #39721 from github/repo-sync
Repo sync
2 parents cac84e1 + d13b1f0 commit c4a1366

File tree

18 files changed

+678
-43
lines changed

18 files changed

+678
-43
lines changed

content/communities/setting-up-your-project-for-healthy-contributions/setting-guidelines-for-repository-contributors.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ shortTitle: Contributor guidelines
1717

1818
To help your project contributors do good work, you can add a file with contribution guidelines to your project repository's root, `docs`, or `.github` folder. When someone opens a pull request or creates an issue, they will see a link to that file. {% ifversion fpt or ghec %}The link to the contributing guidelines also appears on your repository's `contribute` page. For an example of a `contribute` page, see [github/docs/contribute](https://github.com/github/docs/contribute).{% endif %}
1919

20+
{% ifversion fpt or ghec or ghes > 3.18 %}If your repository includes a `CONTRIBUTING.md` file, {% data variables.product.github %} also surfaces it in two other places to make it easier for contributors to discover:
21+
22+
* A "{% octicon "people" aria-hidden="true" aria-label="people" %} Contributing" tab in the repository overview (next to the "{% octicon "book" aria-hidden="true" aria-label="book" %} README" and "{% octicon "code-of-conduct" aria-hidden="true" aria-label="code-of-conduct" %} Code of conduct")
23+
* A "Contributing" link in the repository sidebar{% endif %}
24+
2025
For the repository owner, contribution guidelines are a way to communicate how people should contribute.
2126

2227
For contributors, the guidelines help them verify that they're submitting well-formed pull requests and opening useful issues.
@@ -28,7 +33,7 @@ You can create default contribution guidelines for your organization or personal
2833
> [!TIP]
2934
> Repository maintainers can set specific guidelines for issues by creating an issue or pull request template for the repository. For more information, see [AUTOTITLE](/communities/using-templates-to-encourage-useful-issues-and-pull-requests/about-issue-and-pull-request-templates).
3035
31-
## Adding a _CONTRIBUTING_ file
36+
## Adding a `CONTRIBUTING.md` file
3237

3338
{% data reusables.repositories.navigate-to-repo %}
3439
{% data reusables.files.add-file %}

data/ui.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,17 @@ footer:
260260
expert_services: Expert services
261261
blog: Blog
262262
machine: Some of this content may be machine- or AI-translated.
263+
bespoke_landing:
264+
articles: Articles
265+
all_categories: All categories
266+
search_articles: Search articles
267+
discovery_landing:
268+
recommended: Recommended
269+
articles: Articles
270+
all_categories: All categories
271+
search_articles: Search articles
272+
journey_landing:
273+
articles: '{{ number }} Articles'
263274
product_landing:
264275
quickstart: Quickstart
265276
reference: Reference

src/fixtures/fixtures/data/ui.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,17 @@ footer:
260260
expert_services: Expert services
261261
blog: Blog
262262
machine: Some of this content may be machine- or AI-translated.
263+
bespoke_landing:
264+
articles: Articles
265+
all_categories: All categories
266+
search_articles: Search articles
267+
discovery_landing:
268+
recommended: Recommended
269+
articles: Articles
270+
all_categories: All categories
271+
search_articles: Search articles
272+
journey_landing:
273+
articles: '{{ number }} Articles'
263274
product_landing:
264275
quickstart: Quickstart
265276
reference: Reference

src/frame/components/ui/ScrollButton/ScrollButton.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,14 @@ export const ScrollButton = ({ className, ariaLabel }: ScrollButtonPropsT) => {
1818
// We cannot determine document.documentElement.scrollTop height because we set the height: 100vh and set overflow to auto to keep the header sticky
1919
// That means window.scrollTop height is always 0
2020
// Using IntersectionObserver we can determine if the h1 header is in view or not. If not, we show the scroll to top button, if so, we hide it
21+
const h1Element = document.getElementsByTagName('h1')[0]
22+
if (!h1Element) {
23+
if (process.env.NODE_ENV !== 'production') {
24+
throw new Error('No h1 element found in the document.')
25+
}
26+
return
27+
}
28+
2129
const observer = new IntersectionObserver(
2230
function (entries) {
2331
if (entries[0].isIntersecting === false) {
@@ -28,7 +36,7 @@ export const ScrollButton = ({ className, ariaLabel }: ScrollButtonPropsT) => {
2836
},
2937
{ threshold: [0] },
3038
)
31-
observer.observe(document.getElementsByTagName('h1')[0])
39+
observer.observe(h1Element)
3240
return () => {
3341
observer.disconnect()
3442
}

src/frame/lib/frontmatter.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ const layoutNames = [
1414
'release-notes',
1515
'inline',
1616
'category-landing',
17+
'bespoke-landing',
18+
'discovery-landing',
19+
'journey-landing',
1720
false,
1821
]
1922

@@ -325,6 +328,11 @@ export const schema = {
325328
},
326329
description: 'Array of articles to feature in the spotlight section',
327330
},
331+
// Recommended configuration for category landing pages
332+
recommended: {
333+
type: 'array',
334+
description: 'Array of articles to feature in the carousel section',
335+
},
328336
},
329337
}
330338

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

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,34 @@ import type { Response, NextFunction } from 'express'
33
import type { ExtendedRequest, Context, Tree, ToC } from '@/types'
44
import findPageInSiteTree from '@/frame/lib/find-page-in-site-tree'
55

6+
function isNewLandingPage(currentLayoutName: string): boolean {
7+
return (
8+
currentLayoutName === 'category-landing' ||
9+
currentLayoutName === 'bespoke_landing' ||
10+
currentLayoutName === 'discovery_landing' ||
11+
currentLayoutName === 'journey_landing'
12+
)
13+
}
14+
15+
// TODO: TEMP: This is a temporary solution to turn off/on new landing pages while we develop them.
16+
function isNewLandingPageFeature(req: ExtendedRequest): boolean {
17+
return (
18+
req.query?.feature === 'bespoke-landing' ||
19+
req.query?.feature === 'journey-landing' ||
20+
req.query?.feature === 'discovery-landing'
21+
)
22+
}
23+
624
// This module adds either flatTocItems or nestedTocItems to the context object for
725
// product, category, and subcategory TOCs that don't have other layouts specified.
826
// They are rendered by includes/generic-toc-flat.html or includes/generic-toc-nested.html.
927
export default async function genericToc(req: ExtendedRequest, res: Response, next: NextFunction) {
1028
if (!req.context) throw new Error('request not contextualized')
1129
if (!req.context.page) return next()
1230
if (
31+
!isNewLandingPageFeature(req) &&
1332
req.context.currentLayoutName !== 'default' &&
14-
req.context.currentLayoutName !== 'category-landing'
33+
!isNewLandingPage(req.context.currentLayoutName || '')
1534
)
1635
return next()
1736
// This middleware can only run on product, category, and subcategories.
@@ -96,7 +115,10 @@ export default async function genericToc(req: ExtendedRequest, res: Response, ne
96115
renderIntros = false
97116
req.context.genericTocNested = await getTocItems(treePage, req.context, {
98117
recurse: isRecursive,
99-
renderIntros: req.context.currentLayoutName === 'category-landing' ? true : false,
118+
renderIntros:
119+
isNewLandingPageFeature(req) || isNewLandingPage(req.context.currentLayoutName || '')
120+
? true
121+
: false,
100122
includeHidden,
101123
})
102124
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { useMemo } from 'react'
2+
3+
import { DefaultLayout } from '@/frame/components/DefaultLayout'
4+
import { useBespokeContext } from '@/landings/context/BespokeContext'
5+
import { LandingHero } from '@/landings/components/shared/LandingHero'
6+
import { ArticleGrid } from '@/landings/components/shared/LandingArticleGridWithFilter'
7+
8+
import type { ArticleCardItems } from '@/landings/types'
9+
10+
export const BespokeLanding = () => {
11+
const { title, intro, tocItems } = useBespokeContext()
12+
13+
const flatArticles: ArticleCardItems = useMemo(
14+
() => tocItems.flatMap((item) => item.childTocItems || []),
15+
[tocItems],
16+
)
17+
18+
return (
19+
<DefaultLayout>
20+
<div data-search="article-body">
21+
<LandingHero title={title} intro={intro} />
22+
23+
<div data-search="hide">
24+
<ArticleGrid flatArticles={flatArticles} />
25+
</div>
26+
</div>
27+
</DefaultLayout>
28+
)
29+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { useMemo } from 'react'
2+
3+
import { DefaultLayout } from '@/frame/components/DefaultLayout'
4+
import { useDiscoveryContext } from '@/landings/context/DiscoveryContext'
5+
import { LandingHero } from '@/landings/components/shared/LandingHero'
6+
import { ArticleGrid } from '@/landings/components/shared/LandingArticleGridWithFilter'
7+
import { LandingCarousel } from '@/landings/components/shared/LandingCarousel'
8+
9+
import type { ArticleCardItems } from '@/landings/types'
10+
11+
export const DiscoveryLanding = () => {
12+
const { title, intro, tocItems, recommended } = useDiscoveryContext()
13+
14+
const flatArticles: ArticleCardItems = useMemo(
15+
() => tocItems.flatMap((item) => item.childTocItems || []),
16+
[tocItems],
17+
)
18+
19+
return (
20+
<DefaultLayout>
21+
<div>
22+
<LandingHero title={title} intro={intro} />
23+
<LandingCarousel flatArticles={flatArticles} recommended={recommended} />
24+
<ArticleGrid flatArticles={flatArticles} />
25+
</div>
26+
</DefaultLayout>
27+
)
28+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { DefaultLayout } from '@/frame/components/DefaultLayout'
2+
import { useJourneyContext } from '@/landings/context/JourneyContext'
3+
import { LandingHero } from '@/landings/components/shared/LandingHero'
4+
5+
export const JourneyLanding = () => {
6+
const { title, intro } = useJourneyContext()
7+
8+
return (
9+
<DefaultLayout>
10+
<div>
11+
<LandingHero title={title} intro={intro} />
12+
13+
<div>TODO</div>
14+
</div>
15+
</DefaultLayout>
16+
)
17+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
@import "@primer/css/support/variables/layout.scss";
2+
@import "@primer/css/support/mixins/layout.scss";
3+
4+
.articleGrid {
5+
display: grid;
6+
gap: 1.5rem;
7+
8+
// Mobile: 1 column
9+
grid-template-columns: 1fr;
10+
11+
// Tablet: 2 columns
12+
@include breakpoint(md) {
13+
grid-template-columns: repeat(2, 1fr);
14+
}
15+
16+
// Desktop: 3 columns
17+
@include breakpoint(lg) {
18+
grid-template-columns: repeat(3, 1fr);
19+
}
20+
}
21+
22+
.articleCard {
23+
display: flex;
24+
flex-direction: column;
25+
height: 100%;
26+
}
27+
28+
.cardContent {
29+
display: flex;
30+
flex-direction: column;
31+
height: 100%;
32+
}
33+
34+
.cardFooter {
35+
margin-top: auto;
36+
}

0 commit comments

Comments
 (0)