Skip to content

Commit

Permalink
feat: add first page structure for tutorial
Browse files Browse the repository at this point in the history
  • Loading branch information
noobinthisgame committed Apr 21, 2022
1 parent aaf488d commit 06192f1
Show file tree
Hide file tree
Showing 8 changed files with 878 additions and 427 deletions.
23 changes: 22 additions & 1 deletion contentlayer.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,27 @@ const Doc = defineDocumentType(() => ({
},
}))

const Tutorial = defineDocumentType(() => ({
name: 'Tutorial',
filePathPattern: 'tutorial/**/*.mdx',
bodyType: 'mdx',
fields: {
title: { type: 'string', required: true },
description: { type: 'string', required: true },
},
computedFields: {
...computedFields,
frontMatter: {
type: 'json',
resolve: (doc) => ({
title: doc.title,
description: doc.description,
slug: `/tutorial`,
}),
},
},
}))

const FAQ = defineDocumentType(() => ({
name: 'FAQ',
filePathPattern: 'faq/*.mdx',
Expand Down Expand Up @@ -150,7 +171,7 @@ const Changelog = defineDocumentType(() => ({

const contentLayerConfig = makeSource({
contentDirPath: 'pages',
documentTypes: [Doc, Guides, FAQ, Changelog, Blogs],
documentTypes: [Doc, Guides, FAQ, Changelog, Blogs, Tutorial],
mdx: {
rehypePlugins: [rehypeMdxCodeMeta],
remarkPlugins: [remarkSlug, remarkGfm, remarkEmoji],
Expand Down
4 changes: 4 additions & 0 deletions layouts/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import PageContainer from 'components/page-container'

const BlogLayout = dynamic(() => import('layouts/blog'))
const MDXLayout = dynamic(() => import('layouts/mdx'))
const TutorialLayout = dynamic(() => import('layouts/tutorial'))

export default function DefaultLayout({ children, frontMatter }) {
const slug = frontMatter?.slug
Expand All @@ -15,6 +16,9 @@ export default function DefaultLayout({ children, frontMatter }) {
docs: <MDXLayout frontmatter={frontMatter}>{children}</MDXLayout>,
changelog: <MDXLayout frontmatter={frontMatter}>{children}</MDXLayout>,
faq: <MDXLayout frontmatter={frontMatter}>{children}</MDXLayout>,
tutorial: (
<TutorialLayout frontmatter={frontMatter}>{children}</TutorialLayout>
),
default: (
<PageContainer frontmatter={frontMatter}>{children}</PageContainer>
),
Expand Down
50 changes: 50 additions & 0 deletions layouts/tutorial.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { ReactNode } from 'react'
import Pagination from 'components/pagination'
import TutorialContainer from 'components/tutorial/tutorial-container'
import componentsSidebar from 'configs/components-sidebar.json'
import guidesSidebar from 'configs/guides-sidebar.json'
import styledSystemSidebar from 'configs/styled-system-sidebar.json'
import { findRouteByPath, removeFromLast } from 'utils/find-route-by-path'
import { getRouteContext } from 'utils/get-route-context'

export function getRoutes(slug: string) {
// for home page, use docs sidebar
if (slug === '/') return guidesSidebar.routes

const configMap = {
'/guides': guidesSidebar,
'/docs/styled-system': styledSystemSidebar,
'/docs/components': componentsSidebar,
}

const [, sidebar] =
Object.entries(configMap).find(([path]) => slug.startsWith(path)) ?? []

return sidebar?.routes ?? []
}

interface MDXLayoutProps {
frontmatter: any
children: ReactNode
}

export default function MDXLayout({ frontmatter, children }: MDXLayoutProps) {
const routes = getRoutes(frontmatter.slug)

const route = findRouteByPath(removeFromLast(frontmatter.slug, '#'), routes)
const routeContext = getRouteContext(route, routes)

return (
<TutorialContainer
frontmatter={frontmatter}
pagination={
<Pagination
next={routeContext.nextRoute}
previous={routeContext.prevRoute}
/>
}
>
{children}
</TutorialContainer>
)
}
33 changes: 33 additions & 0 deletions pages/tutorial/[[...slug]].tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { allTutorials } from '.contentlayer/data'
import type { Tutorial } from '.contentlayer/types'
import { GetStaticPaths, GetStaticProps } from 'next'
import { useMDXComponent } from 'next-contentlayer/hooks'
import { MDXComponents } from 'components/mdx-components'
import Layout from 'layouts'

export default function Page({ tutorial }: { tutorial: Tutorial }) {
const Component = useMDXComponent(tutorial.body.code)
return (
<Layout frontMatter={tutorial.frontMatter}>
<Component components={MDXComponents} />
</Layout>
)
}

export const getStaticPaths: GetStaticPaths = async () => {
const tutorials = allTutorials
.map((t) => t._id.replace('tutorial/', '').replace('.mdx', ''))
.map((id) => ({ params: { slug: id.split('/') } }))
return { paths: tutorials, fallback: false }
}

export const getStaticProps: GetStaticProps = async (ctx) => {
const params = Array.isArray(ctx.params.slug)
? ctx.params.slug
: [ctx.params.slug]

const tutorial = allTutorials.find((tutorial) =>
tutorial._id.includes(params.join('/')),
)
return { props: { tutorial } }
}
8 changes: 8 additions & 0 deletions pages/tutorial/basics.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
title: 'Basics'
description:
'Some of the most asked questions with their answers to help you get started
with Chakra UI.'
---

This is the section about chakra ui basics
133 changes: 133 additions & 0 deletions src/components/tutorial/tutorial-container.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import { Box, Flex, chakra, Stack, HStack } from '@chakra-ui/react'
import { SkipNavContent, SkipNavLink } from '@chakra-ui/skip-nav'
import {
SandpackCodeEditor,
SandpackLayout,
SandpackPreview,
SandpackProvider,
Navigator,
} from '@codesandbox/sandpack-react'
import { useRouter } from 'next/router'
import * as React from 'react'
import PageTransition from '../page-transition'
import { TutorialSidebar } from './tutorial-sidebar'
import EditPageLink from 'components/edit-page-button'
import Footer from 'components/footer'
import Header from 'components/header'
import SEO from 'components/seo'
import { t } from 'utils/i18n'

function useHeadingFocusOnRouteChange() {
const router = useRouter()

React.useEffect(() => {
const onRouteChange = () => {
const [heading] = Array.from(document.getElementsByTagName('h1'))
heading?.focus()
}
router.events.on('routeChangeComplete', onRouteChange)
return () => {
router.events.off('routeChangeComplete', onRouteChange)
}
}, [router.events])
}

export interface Heading {
level: 'h2' | 'h3'
text: string
id: string
}

interface PageContainerProps {
frontmatter: {
slug?: string
title: string
description?: string
editUrl?: string
version?: string
headings?: Heading[]
}
children: React.ReactNode
sidebar?: React.ReactElement
pagination?: React.ReactElement
}

function TutorialContainer({
frontmatter,
children,
pagination,
}: PageContainerProps) {
useHeadingFocusOnRouteChange()

if (!frontmatter) return <></>

const { title, description, editUrl, headings = [] } = frontmatter

const files = {}

return (
<>
<SEO title={title} description={description} />
<SkipNavLink zIndex={20}>
{t('component.page-container.skip-to-content')}
</SkipNavLink>
<Header />
<Box as='main' className='main-content' w='full' maxW='8xl' mx='auto'>
<Box display={{ md: 'flex' }}>
<TutorialSidebar />
<Box flex='1' minW='0'>
<SkipNavContent />
<Box id='content' px={5} mx='auto' minH='76vh'>
<SandpackProvider customSetup={{ files }} template='react'>
{/* <ScrollContainer h='100vh' w='53vw'> */}
<Box
minW='0'
flex='auto'
px={{ base: '4', sm: '6', xl: '8' }}
pt='10'
>
<PageTransition style={{ maxWidth: '48rem' }}>
<HStack>
<chakra.h1 tabIndex={-1} outline={0} apply='mdx.h1'>
{title}
</chakra.h1>
{children}
<Box mt='40px'>
<Box>{editUrl && <EditPageLink href={editUrl} />}</Box>
{pagination || null}
</Box>

{/* </ScrollContainer> */}
<Box>
<SandpackLayout theme={'night-owl'}>
<Stack spacing={0} h='100vh' w='100%'>
<Navigator />
<SandpackCodeEditor
showLineNumbers
customStyle={{
height: '50%',
fontFamily: 'poppins',
}}
/>
<SandpackPreview
customStyle={{ height: 'calc(50% - 40px)' }}
/>
</Stack>
</SandpackLayout>
</Box>
</HStack>
<Box pb='20'>
<Footer />
</Box>
</PageTransition>
</Box>
</SandpackProvider>
</Box>
</Box>
</Box>
</Box>
</>
)
}

export default TutorialContainer
3 changes: 3 additions & 0 deletions src/components/tutorial/tutorial-sidebar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const TutorialSidebar = () => {
return <div>This is the sidebar</div>
}
Loading

0 comments on commit 06192f1

Please sign in to comment.