Skip to content

Conversation

@BinaryMuse
Copy link
Contributor

I've been experimenting a little with the idea of automatically generating docs from our components' propTypes. This PR is currently pretty hacky and dirty, but it demonstrates a proof of concept.

Result

I'll start from the endpoint: here is the props documentation for SideNav, which has been automatically generated and displayed with a ComponentProps component dropped into the associated .mdx file.

image

As you can see, the props documentation contains the props for the component as well as the props made available due to the component "inheriting" from other components. Also, the system props section has been generated by walking the inheritance tree and collecting all the system props made available to each component in the tree.

The markdown used to display this is currently:

## SideNav props

import {SideNav} from "@primer/components"
import ComponentProps from "../components/ComponentProps"

<ComponentProps Component={SideNav} name="SideNav" />

## SideNav.Link props

<ComponentProps Component={SideNav.Link} name="SideNav.Link" />

Generating the props data

In order to generate this content, the components' propTypes declaration needs to be a little smarter about the props themselves. As an example, here's the JavaScript used to generate the propTypes for SideNav:

addDocumentedProps(SideNav, {
  system: [COMMON],
  inherited: [BorderBox],
  own: {
    as: elementType.desc('Sets the HTML tag for the element'),
    bordered: PropTypes.bool.desc('Renders the component with a border'),
    children: PropTypes.node.hidden,
    theme: PropTypes.object.hidden,
    variant: PropTypes.oneOf(['normal', 'lightweight']).desc(
      'Set to `lightweight` to render [in a lightweight style](#lightweight-variant)'
    )
  }
})

SideNav.defaultProps = {
  theme,
  bordered: false,
  variant: 'normal'
}

(I'm not a huge fan of this syntax, but it works for now.)

The system works with all the validators provided by the prop-types package, and can also work with custom validators (such as our own elementType). It also works with isRequired, as well as providing its own desc() for setting the prop description and hidden to hide the prop from the documentation entirely.

What's next

This was an experiment to scratch my own itch; it's pretty hacky and could use a lot of work. However, I wanted to share it to get my thoughts down somewhere and see if the idea caught anyone else's fancy.

@vercel
Copy link

vercel bot commented Apr 15, 2020

This pull request is being automatically deployed with ZEIT Now (learn more).
To see the status of your deployment, click below or on the icon next to each commit.

@colebemis
Copy link
Contributor

Excited about this 😸

@BinaryMuse
Copy link
Contributor Author

Changed up the syntax slightly to make it more similar to creating regular propTypes:

SideNav.propTypes = PropTypes.doc({
  system: [COMMON],
  inherited: [BorderBox],
  own: {
    as: elementType.desc('Sets the HTML tag for the element'),
    bordered: PropTypes.bool.desc('Renders the component with a border'),
    children: PropTypes.node.hidden,
    theme: PropTypes.object.hidden,
    variant: PropTypes.oneOf(['normal', 'lightweight']).desc(
      'Set to `lightweight` to render [in a lightweight style](#lightweight-variant)'style](#lightweight-variant)'
    )
  }
})

@BinaryMuse
Copy link
Contributor Author

Here's a different take on the "inherited" props based on today's conversation:

image

Personally I like this a lot better; all the props are shown at once, and since the displayed system props are also automatically consolidated based on walking the tree, I think it makes more sense.

@emplums emplums changed the base branch from master to main September 16, 2020 21:24
@emplums
Copy link

emplums commented Feb 22, 2021

Going to close this for now since it's getting pretty stale! We might want to take another look at this approach when the TS migration is done

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants