{children}
diff --git a/layouts/NewComponentLayout.tsx b/layouts/NewComponentLayout.tsx
new file mode 100644
index 00000000..f0ef1f6f
--- /dev/null
+++ b/layouts/NewComponentLayout.tsx
@@ -0,0 +1,173 @@
+import React from 'react';
+import styled from '@emotion/styled';
+import { GuidelinesContextProvider } from 'contexts/GuidelinesContext';
+import startCase from 'lodash/startCase';
+import Head from 'next/head';
+import { useSession } from 'next-auth/react';
+import { ComponentFields } from 'utils/ContentStack/types';
+import getFullPageTitle from 'utils/getFullPageTitle';
+import { mq } from 'utils/mediaQuery';
+import { CustomComponentDoc } from 'utils/tsdoc.utils';
+
+import GuidelineBreadcrumbs from 'components/GuidelineBreadcrumbs';
+import FigmaIcon from 'components/icons/FigmaIcon';
+import GithubIcon from 'components/icons/GithubIcon';
+import { LiveExample } from 'components/pages/example/LiveExample';
+
+import Button from '@leafygreen-ui/button';
+import LinkIcon from '@leafygreen-ui/icon/dist/Link';
+import LeafyGreenProvider from '@leafygreen-ui/leafygreen-provider';
+import { palette } from '@leafygreen-ui/palette';
+import { spacing } from '@leafygreen-ui/tokens';
+import { Body, H1, Overline } from '@leafygreen-ui/typography';
+
+const Container = styled('div')`
+ ${mq({
+ // 51px is a magic number for baseline alignment with the first SideNavGroup header
+ marginTop: [`${spacing[4]}px`, `${spacing[4]}px`, '51px'],
+ // width: ['100%', '100%', '90%', '75%'],
+ paddingLeft: [`${spacing[2]}`, `${spacing[4]}px`, '120px'],
+ paddingRight: [`${spacing[2]}`, `${spacing[4]}px`, '120px'],
+ })}
+`;
+
+const FlexContainer = styled('div')`
+ display: flex;
+ gap: ${spacing[7]}px;
+ position: relative;
+ ${mq({
+ flexDirection: ['column-reverse', 'row'],
+ })}
+`;
+
+const ContentContainer = styled('div')`
+ flex: 2;
+`;
+
+const BreadcrumbsContainer = styled('div')`
+ position: sticky;
+ height: fit-content;
+ top: ${spacing[6]}px;
+ flex: 1;
+`;
+
+const HeaderContainer = styled('div')`
+ background-color: ${palette.green.dark3};
+ ${mq({
+ padding: [`${spacing[2]}`, `${spacing[4]}px`, `${spacing[7]}px`],
+ paddingLeft: [`${spacing[2]}`, `${spacing[4]}px`, '120px'],
+ paddingRight: [`${spacing[2]}`, `${spacing[4]}px`, '120px'],
+ })}
+ background-image: url('/Blob.svg');
+ background-repeat: no-repeat;
+ background-position: 100% 0%;
+`;
+
+const Header = styled(H1)`
+ margin-bottom: ${spacing[3]}px;
+ text-transform: capitalize;
+`;
+
+const getLinkIcon = linkType => {
+ switch (linkType) {
+ case 'Figma':
+ return
;
+ case 'Github':
+ return
;
+ default:
+ return
;
+ }
+};
+
+const LinksContainer = styled('div')`
+ display: flex;
+ gap: ${spacing[2]}px;
+`;
+
+const NewComponentLayout = ({
+ component,
+ componentName,
+ children,
+ tsDoc,
+}: {
+ component?: ComponentFields;
+ children: React.ReactNode;
+ componentName: string;
+ tsDoc: Array
| null;
+}) => {
+ const pageTitle = getFullPageTitle(startCase(componentName));
+ const { data: session } = useSession();
+
+ return (
+
+
+
+
+ {pageTitle}
+
+ {/* If the description field doesn't exist, it will default to a description of the site, defined in _document. */}
+ {component?.description && (
+
+ )}
+
+
+
+ {component &&
+ (!component.private || (component.private && session)) ? (
+ <>
+
+
+ {/* Add id for hard-coded breadcrumb */}
+ {startCase(componentName)}
+
+ {component.description}
+
+
+ {component.links_data &&
+ component.links_data.map(linkObject => (
+
+ ))}
+
+
+
+
+
+
+
+
+ Playground
+
+
+
+ {children}
+
+
+
+
+
+
+ >
+ ) : (
+ children
+ )}
+
+
+
+ );
+};
+
+NewComponentLayout.displayName = 'NewComponentLayout';
+
+export default NewComponentLayout;
diff --git a/next.config.js b/next.config.js
index 1940b296..0a38eebc 100644
--- a/next.config.js
+++ b/next.config.js
@@ -42,7 +42,7 @@ const nextConfig = {
config.module.rules.push({
test: /\.svg$/,
use: ['@svgr/webpack'],
- include: isPathInLeafygreen,
+ // include: [isPathInLeafygreen, '/public'],
});
return config;
diff --git a/pages/[contentPageGroup]/private/[contentPageTitle].tsx b/pages/[contentPageGroup]/private/[contentPageTitle].tsx
new file mode 100644
index 00000000..d46ee66f
--- /dev/null
+++ b/pages/[contentPageGroup]/private/[contentPageTitle].tsx
@@ -0,0 +1,41 @@
+import { ReactElement } from 'react';
+import ContentPageLayout from 'layouts/ContentPageLayout';
+import startCase from 'lodash/startCase';
+import { unstable_getServerSession } from 'next-auth';
+import { authOptions } from 'pages/api/auth/[...nextauth]';
+import { getContentPage } from 'utils/ContentStack/getContentstackResources';
+
+import ContentstackRichText from 'components/ContentstackRichText';
+import Unauthorized from 'components/Unauthorized';
+
+const ContentPage = ({ contentPage }) => {
+ if (contentPage !== null)
+ return ;
+
+ return ;
+};
+
+ContentPage.getLayout = function getLayout(page: ReactElement) {
+ return (
+
+ {page}
+
+ );
+};
+
+export async function getServerSideProps({ params, req, res }) {
+ const session = await unstable_getServerSession(req, res, authOptions);
+ const contentPage = session
+ ? await getContentPage(startCase(params.contentPageTitle))
+ : null;
+ return {
+ props: {
+ contentPage,
+ contentPageTitle: contentPage ? contentPage.title : null,
+ },
+ };
+}
+
+export default ContentPage;
diff --git a/pages/component/[componentName]/guidelines.tsx b/pages/component/[componentName]/guidelines.tsx
deleted file mode 100644
index 5ef4f693..00000000
--- a/pages/component/[componentName]/guidelines.tsx
+++ /dev/null
@@ -1,38 +0,0 @@
-import { ReactElement } from 'react';
-import ComponentLayout from 'layouts/ComponentLayout';
-import { containerPadding } from 'styles/globals';
-import {
- getStaticComponentPaths,
- getStaticComponentProps,
-} from 'utils/ContentStack/getStaticComponent';
-import isEmptyRichText from 'utils/isEmptyRichText';
-
-import ComingSoon from 'components/ComingSoon';
-import ContentstackRichText from 'components/ContentstackRichText';
-
-const ComponentGuidelines = ({ component }) => {
- const guidelines = component.designguidelines;
- return !guidelines || isEmptyRichText(guidelines) ? (
-
- ) : (
-
- {}
-
- );
-};
-
-ComponentGuidelines.getLayout = function getLayout(page: ReactElement) {
- return (
-
- {page}
-
- );
-};
-
-export const getStaticPaths = getStaticComponentPaths;
-export const getStaticProps = getStaticComponentProps;
-
-export default ComponentGuidelines;
diff --git a/pages/component/[componentName]/index.tsx b/pages/component/[componentName]/index.tsx
new file mode 100644
index 00000000..2512d426
--- /dev/null
+++ b/pages/component/[componentName]/index.tsx
@@ -0,0 +1,59 @@
+import { ReactElement } from 'react';
+import NewComponentLayout from 'layouts/NewComponentLayout';
+import { containerPadding } from 'styles/globals';
+import { getTSDoc } from 'utils/_getComponentResources';
+import { getComponent } from 'utils/ContentStack/getContentstackResources';
+import { getStaticComponentPaths } from 'utils/ContentStack/getStaticComponent';
+import { ComponentPageMeta } from 'utils/ContentStack/types';
+import isEmptyRichText from 'utils/isEmptyRichText';
+
+import ComingSoon from 'components/ComingSoon';
+import ContentstackRichText from 'components/ContentstackRichText';
+
+import { ExamplePageProps } from './example';
+
+const ComponentGuidelines = ({ component }) => {
+ const guidelines = component.designguidelines;
+ return !guidelines || isEmptyRichText(guidelines) ? (
+
+ ) : (
+
+ {}
+
+ );
+};
+
+ComponentGuidelines.getLayout = function getLayout(page: ReactElement) {
+ return (
+
+ {page}
+
+ );
+};
+
+export const getStaticPaths = getStaticComponentPaths;
+export const getStaticProps = async ({
+ params,
+}): Promise<{ props: ExamplePageProps }> => {
+ const { componentName } = params;
+ const component: ComponentPageMeta | null =
+ (await getComponent(componentName, {
+ includeContent: true,
+ })) ?? null;
+
+ const tsDoc = await getTSDoc(componentName);
+
+ return {
+ props: {
+ componentName,
+ component,
+ tsDoc,
+ },
+ };
+};
+
+export default ComponentGuidelines;
diff --git a/public/Blob.svg b/public/Blob.svg
new file mode 100644
index 00000000..3a6ed2f0
--- /dev/null
+++ b/public/Blob.svg
@@ -0,0 +1,3 @@
+
diff --git a/utils/ContentStack/getContentstackResources.ts b/utils/ContentStack/getContentstackResources.ts
index 72ec6948..67c869ec 100644
--- a/utils/ContentStack/getContentstackResources.ts
+++ b/utils/ContentStack/getContentstackResources.ts
@@ -14,6 +14,7 @@ const ENV_MAP = {
production: 'main',
staging: 'staging',
dev: 'staging',
+ experimental: 'experimental',
} as const;
const environment = ((): string => {
@@ -32,6 +33,10 @@ const Stack = Contentstack.Stack({
api_key: process.env.NEXT_PUBLIC_CONTENTSTACK_API_KEY as string,
delivery_token: process.env.NEXT_PUBLIC_CONTENTSTACK_DELIVERY_TOKEN as string,
environment,
+ branch:
+ process.env.NEXT_PUBLIC_ENVIRONMENT === 'experimental'
+ ? 'experimental'
+ : 'main',
});
interface QueryOptions {
@@ -45,6 +50,7 @@ const componentProperties = [
'url',
'figmaurl',
'private',
+ 'links_data',
'codesandbox_url',
];
const optionalComponentProperties = ['designguidelines'];
@@ -108,7 +114,16 @@ export async function getContentPageGroups(): Promise> {
const pageGroups: Array = (
await query
.includeReference('content_pages')
- .only(['content_pages', 'uid', 'title', 'url', 'iconname'])
+ .only([
+ 'content_pages',
+ 'uid',
+ 'title',
+ 'url',
+ 'iconname',
+ 'private',
+ 'rendering_order',
+ ])
+ .ascending('rendering_order')
.toJSON()
.find()
)[0].map(({ content_pages, ...meta }: ContentPageGroup) => {
@@ -117,11 +132,15 @@ export async function getContentPageGroups(): Promise> {
content_pages: content_pages
// TODO: strip fields in initial query
// Strip any additional fields
- .map(({ uid, title, url }) => ({ uid, title, url }))
+ .map(({ uid, title, url, is_private }: ContentPage) => ({
+ uid,
+ title,
+ url,
+ is_private,
+ }))
.sort((a, b) => a.title.localeCompare(b.title)),
};
});
-
return pageGroups;
} catch (error) {
console.error('No Content Page Groups found', error);
diff --git a/utils/ContentStack/types.ts b/utils/ContentStack/types.ts
index f9b0ee1c..4068b12c 100644
--- a/utils/ContentStack/types.ts
+++ b/utils/ContentStack/types.ts
@@ -1,9 +1,16 @@
+export interface ContentstackMetadata {
+ uid: string;
+}
+export interface ContentstackObject {
+ _metadata: ContentstackMetadata;
+}
+
export interface ContentPageGroup extends Object {
uid: string;
title: string;
url: string;
iconname: string;
- content_pages: Array;
+ content_pages: Array;
}
/**
@@ -20,6 +27,7 @@ export interface ContentPageMeta {
*/
export interface ContentPage extends ContentPageMeta {
content: unknown;
+ is_private?: boolean;
}
/**
@@ -35,12 +43,18 @@ export interface ComponentPageMeta {
private?: boolean;
}
+export interface LinkData extends ContentstackObject {
+ link: { title: string; href: string };
+ type?: string;
+}
+
/**
* A {@link ComponentPageMeta} with additional data fields
* including `figmaUrl` & `designguidelines` content
*/
export interface ComponentFields extends ComponentPageMeta {
designguidelines?: unknown;
+ links_data?: Array<{ link_data: LinkData }>;
}
export interface BaseLayoutProps {