1
0
mirror of synced 2025-12-21 10:57:10 -05:00
Files
docs/components/context/MainContext.tsx
Edward Thomson 0fee9aedcd Landing page: groups of features (#22313)
* homepage: reduce padding below search area

Bring as much useful content up "above the fold".

* homepage: add groups for the front page sections

Group the homepage links into sections that map to the GitHub features
page (`/features`) plus two groups that are bespoke to the docs ("Get
started" and "Developers").

* homepage: update group design

Group the feature list area using the design exploration work by
@arisacoba.  Remove the description.

* homepage: remove ungrouped items from main area

Remove ungrouped items (like the external links) from the main feature
area.  Users can still navigate to ungrouped items in the sidebar.

* fix tsc error, use Link component

* homepage: support empty icon in group

Don't assume that we have icons everywhere on the landing page groups.

* homepage: drop octocat/invertocat

Looks weird with the modern icons, looks bad in dark mode.  Drop them
for now.

* homepage: document the childGroups frontmatter property

* homepage: don't test that sidebar == main content

We're reducing the links on the homepage in the main content area, but
the sidebar should be the complete list of products.  Remove the tests
that ensure that the main content area has all the sidebar content.  But
keep the tests that ensure that the sidebar content has all the links in
the main content area.

* homepage: remove "GitHub" doc set

The "GitHub" doc set "will be removed soon as we keep moving more content
out of it, so let's not include it here to keep the page more
evergreen."

* homepage: don't test that `/github` is linked on the main page

We're removing the `/github` doc set, and it's now not in the main page
grouped links.  Remove the test that `/github` exists, now look for
`/get-started`.

* homepage: use octicons instead of images

The images from https://github.com/features will be updated 🔜 - in
the meantime, let's use octicons which are consistent and give visual
interest.

* homepage: use octicons from @primer/octicons-react

Using the react components adds `<svg>` elements instead of `<img>`
elements, which lets the element use the current fill color, supporting
both light and dark themes.

Co-authored-by: Mike Surowiec <mikesurowiec@users.noreply.github.com>
Co-authored-by: Emily Gould <4822039+emilyistoofunky@users.noreply.github.com>
2021-10-22 17:58:16 +00:00

218 lines
6.1 KiB
TypeScript

import { createContext, useContext } from 'react'
import pick from 'lodash/pick'
import type { BreadcrumbT } from 'components/Breadcrumbs'
import type { FeatureFlags } from 'components/hooks/useFeatureFlags'
import { ExcludesNull } from 'components/lib/ExcludesNull'
export type ProductT = {
external: boolean
href: string
id: string
name: string
versions?: Array<string>
}
export type ProductGroupT = {
name: string
icon: string
octicon: string
children: Array<ProductT>
}
type VersionItem = {
version: string
versionTitle: string
}
export type ProductTreeNode = {
page: {
hidden?: boolean
documentType: 'article' | 'mapTopic'
title: string
shortTitle: string
}
renderedShortTitle?: string
renderedFullTitle: string
href: string
childPages: Array<ProductTreeNode>
}
type DataT = {
ui: Record<string, any>
reusables: {
enterprise_deprecation: {
version_was_deprecated: string
version_will_be_deprecated: string
deprecation_details: string
isOldestReleaseDeprecated: boolean
}
policies: {
translation: string
}
}
variables: {
release_candidate: { version: string }
}
}
type EnterpriseServerReleases = {
isOldestReleaseDeprecated: boolean
oldestSupported: string
nextDeprecationDate: string
supported: Array<string>
}
export type MainContextT = {
breadcrumbs: {
product: BreadcrumbT
category?: BreadcrumbT
maptopic?: BreadcrumbT
article?: BreadcrumbT
}
activeProducts: Array<ProductT>
productGroups: Array<ProductGroupT>
communityRedirect: {
name: string
href: string
}
currentProduct?: ProductT
currentLayoutName: string
isHomepageVersion: boolean
isFPT: boolean
data: DataT
airGap?: boolean
error: string
currentCategory?: string
relativePath?: string
enterpriseServerReleases: EnterpriseServerReleases
currentPathWithoutLanguage: string
userLanguage: string
allVersions: Record<string, VersionItem>
currentVersion?: string
currentProductTree?: ProductTreeNode | null
featureFlags: FeatureFlags
page: {
documentType: string
type?: string
languageVariants: Array<{ name: string; code: string; hreflang: string; href: string }>
topics: Array<string>
title: string
fullTitle?: string
introPlainText?: string
hidden: boolean
permalinks?: Array<{
languageCode: string
relativePath: string
title: string
pageVersionTitle: string
pageVersion: string
href: string
}>
}
enterpriseServerVersions: Array<string>
searchVersions: Record<string, string>
nonEnterpriseDefaultVersion: string
status: number
fullUrl: string
}
export const getMainContext = (req: any, res: any): MainContextT => {
return {
breadcrumbs: req.context.breadcrumbs || {},
activeProducts: req.context.activeProducts,
productGroups: req.context.productGroups,
communityRedirect: req.context.page?.communityRedirect || {},
currentProduct: req.context.productMap[req.context.currentProduct] || null,
currentLayoutName: req.context.currentLayoutName,
isHomepageVersion: req.context.page?.documentType === 'homepage',
isFPT: req.context.currentVersion === 'free-pro-team@latest',
error: req.context.error ? req.context.error.toString() : '',
data: {
ui: req.context.site.data.ui,
reusables: {
enterprise_deprecation: req.context.site.data.reusables.enterprise_deprecation,
policies: req.context.site.data.reusables.policies,
},
variables: {
release_candidate: req.context.site.data.variables.release_candidate,
},
},
airGap: req.context.AIRGAP || false,
currentCategory: req.context.currentCategory || '',
currentPathWithoutLanguage: req.context.currentPathWithoutLanguage,
relativePath: req.context.page?.relativePath,
page: {
languageVariants: req.context.page.languageVariants,
documentType: req.context.page.documentType,
type: req.context.page.type || null,
title: req.context.page.title,
fullTitle: req.context.page.fullTitle,
topics: req.context.page.topics || [],
introPlainText: req.context.page?.introPlainText,
permalinks: req.context.page?.permalinks.map((obj: any) =>
pick(obj, [
'title',
'pageVersionTitle',
'pageVersion',
'href',
'relativePath',
'languageCode',
])
),
hidden: req.context.page.hidden || false,
},
enterpriseServerReleases: pick(req.context.enterpriseServerReleases, [
'isOldestReleaseDeprecated',
'oldestSupported',
'nextDeprecationDate',
'supported',
]),
enterpriseServerVersions: req.context.enterpriseServerVersions,
userLanguage: req.context.userLanguage || '',
allVersions: req.context.allVersions,
currentVersion: req.context.currentVersion,
currentProductTree: req.context.currentProductTree
? getCurrentProductTree(req.context.currentProductTree)
: null,
featureFlags: {},
searchVersions: req.context.searchVersions,
nonEnterpriseDefaultVersion: req.context.nonEnterpriseDefaultVersion,
status: res.statusCode,
fullUrl: req.protocol + '://' + req.get('host') + req.originalUrl,
}
}
// only pull things we need from the product tree, and make sure there are default values instead of `undefined`
const getCurrentProductTree = (input: any): ProductTreeNode | null => {
if (input.page.hidden) {
return null
}
return {
href: input.href,
renderedShortTitle: input.renderedShortTitle || '',
renderedFullTitle: input.renderedFullTitle || '',
page: {
hidden: input.page.hidden || false,
documentType: input.page.documentType,
title: input.page.title,
shortTitle: input.page.shortTitle || '',
},
childPages: (input.childPages || []).map(getCurrentProductTree).filter(ExcludesNull),
}
}
export const MainContext = createContext<MainContextT | null>(null)
export const useMainContext = (): MainContextT => {
const context = useContext(MainContext)
if (!context) {
throw new Error('"useMainContext" may only be used inside "MainContext.Provider"')
}
return context
}