One of the main features of Docz is that it allows you to create your own theme from scratch and just use the data parsed from Docz. We provide a bunch of components that can help you create your own theme with little effort.
Let's assume we have the following project structure :
pages/ hello-world.mdx src/ gatsby-theme-docz/ index.js ui/ Page.js doczrc.js package.json
The previous way of customizing docz in v0 and v1 was to use the theme
property inside the doczrc.js
file.
With v2, we leverage GatsbyJS theme shadowing to override any and all files of the theme.
For example, to create a new theme wrapper and override some styles, we create a file located at src/gatsby-theme-docz/index.js
that shadows gatsby-theme-docz/src/index.js
and provide a new theme container implementation as shown below.
Create your theme component that takes in children
as props and export it as default while using the theme()
high order component as an enhancer.
// src/gatsby-theme-docz/index.js import React from 'react' import { theme } from 'docz' const Theme = ({ children }) => <div>{children}</div> export default theme()(Theme)
It's required to "pass down" the
children
property inside your theme component in order to render Docz routes properly.
If you create something like the above example you won't have anything too useful to show. To customize your documentation make sure to check the gatsby-docz-theme source code to decide which modules you want to override.
Each theme has its own default themeConfig
object that allows you to override any part of the default theme found here.
The themeConfig
allows you to customize fonts, colors, spaces, styles properties and other project global variables.
// src/gatsby-theme-docz/index.js import React from 'react' import { theme } from 'docz' const Theme = ({ children }) => <div>{children}</div> const themeConfig = { colors: { primary: 'tomato', secondary: 'khaki', gray: 'lightslategray', }, } export default theme(themeConfig)(Theme)
By default, Docz will use this object as the default configuration and merge it with the themeConfig
setting in the project configuration.
You can then use the useConfig
hook to do a lot of things, like use css-in-js theming or retrieve props from your themeConfig
in a deep rendered component.
// src/gatsby-theme-docz/index.js import React from 'react' import { theme, useConfig } from 'docz' import { ThemeProvider } from 'theme-ui' const Theme = () => { const config = useConfig() return ( <ThemeProvider theme={config}> <div>My theme</div> </ThemeProvider> ) } const themeConfig = { colors: { primary: 'tomato', secondary: 'khaki', gray: 'lightslategray', }, } export default theme(themeConfig)(Theme)
As explained in the components API section, the <ComponentsProvider>
is the component responsible for providing components to MDX and Docz to render your markdown files with.
With these components passed to the provider, you can change how your mdx file will be rendered and alter default behaviors and styles.
// src/gatsby-theme-docz/index.js import React from 'react' import { theme, useConfig, ComponentsProvider } from 'docz' import { ThemeProvider } from 'theme-ui' import * as components from './ui' const map = { page: components.Page, notFound: components.NotFound, render: components.Render, h1: components.H1, h2: components.H2, h3: components.H3, h4: components.H4, h5: components.H5, h6: components.H6, ul: components.List, loading: components.Loading, table: components.Table, pre: components.Pre, inlineCode: components.Code, } const Theme = ({ children }) => { const config = useConfig() return ( <ThemeProvider theme={config}> <ComponentsProvider components={map}> {children} </ComponentsProvider> </ThemeProvider> ) } const themeConfig = { colors: { primary: 'tomato', secondary: 'khaki', gray: 'lightslategray', }, } export default theme(themeConfig)(Theme)
This is powerful because it pushes you to think about your site as a set of base components and to create a default style for each one that will be used in all your documents while keeping your code DRY.
By now you should have a working site. But with the code above you will only see a single page without any link or information about the rest of your documents.
Having a way to navigate your documentation is essential in your documentation site.
Let's create a Menu
component by using the useMenus
hook and the <Link>
component.
The hook will give you information about all the menus' information parsed by Docz and the component will provide a way to navigate between them.
An example Menu
component is shown below :
// src/Menu.js import React from 'react' import { useMenus, Link } from 'docz' export const Menu = () => { const menus = useMenus() return ( <ul> {menus.map(menu => ( <li key={menu.id}> <Link to={menu.route}>{menu.name}</Link> </li> ))} </ul> ) }
This will create a fully functional navigation menu to your documentation and you can then use the <Menu />
component inside your theme:
// src/gatsby-theme-docz/index.js import React from 'react' import { theme, useConfig, ComponentsProvider } from 'docz' import { ThemeProvider } from 'theme-ui' import { Menu } from './Menu' import * as components from './my-components' const map = { page: components.Page, notFound: components.NotFound, render: components.Render, h1: components.H1, h2: components.H2, h3: components.H3, h4: components.H4, h5: components.H5, h6: components.H6, ul: components.List, loading: components.Loading, table: components.Table, pre: components.Pre, inlineCode: components.Code, } const Theme = ({ children }) => { const config = useConfig() return ( <ThemeProvider theme={config}> <Menu /> <ComponentsProvider components={map}> {children} </ComponentsProvider> </ThemeProvider> ) } const themeConfig = { colors: { primary: 'tomato', secondary: 'khaki', gray: 'lightslategray', }, } export default theme(themeConfig)(Theme)
You can also use this component to create other things like a search component, link to custom pages or whatever else you would like.
Another interesting thing that you can do when you're creating your own theme is to use the componentMap
's <Page>
component to customize the document preview depending on each document's settings.
Each document can have its own settings defined in the header of the .mdx
file.
The Page
component receives a prop called doc
that contains the settings data. You can use this data to build your own variations of the rendered pages.
For example, suppose that you'd like to add a hero image to some documents and leave others unchanged.
You could do that by providing a hero
property to your document, and then if that property is defined you would render a hero, else you would show the document as is.
Your markdown would look something like this :
<!-- hello-world.mdx --> --- name: Hello world hero: /my/hero/img.png --- # Hello world This is a page!
And your Page
component would look like the following :
// src/ui/Page.js import React from 'react' import MyCoolHero from './MyCoolHero' export const Page = ({ doc, children }) => ( <div> {doc.hero && <MyCoolHero img={doc.hero} />} {children} </div> )
Armed with this knowledge, you can create many variations of your documents based on the data provided in your MDX.
To see an example of a theme, you can check the source code of gatsby-theme-docz
.