A short time ago, in a galaxy very,
very near....

Episode IV

A New Hope

It is a period of designer unrest. Our patternfly.org designers demand more features with less bugs. Little do they know, patternfly.org is currently three sites merged into one behemoth.


With technical debt mounting, Rebel spies managed to steal secret plans to Gatsby's ultimate weapon, the GATSBY THEME, a modular system with enough power to refactor all three sites at once.


Pursued by the looming deadlines, PatternFly.org contributors race to finish implementing the GATSBY THEME that can save the designers and restore freedom to the galaxy . . . .

Currently, we have three documentation sites:

patternfly.org

  • Hosts HTML/CSS, React, and Design docs for Patternfly
  • Uses git submodules to source patternfly-next and patternfly-react repos
  • Includes features like global search, fullscreen preview thumbnails, a version banner, and side nav context switcher
  • Does not share many styles with HTML/CSS or React docs
Org screenshot Current org docs

Problems

Org design snippet Org design snippet

            export default (props) => {
              const alertTypes = AlertTypes();
              const alertVariations = AlertVariations();
              const headingText = 'Alert';
              const variablesRoot = 'pf-c-alert';
            
              return <Documentation
                data={props}
                docs={Docs}
                heading={headingText}
                variablesRoot={variablesRoot}>
                  <Example heading="Alert types"
                    handlebars={AlertTypesRaw}>
                    {alertTypes}
                  </Example>
                  <Example heading="Alert Variations"
                    handlebars={AlertVariationsRaw}>
                  <Example heading="Alert variations"
                    handlebars={AlertVariationsRaw}>
                    {alertVariations}
                  </Example>
                </Documentation>
          

Upstream prop injection for patternfly.org in patternfly-next's repo. PR here.

Problem

New docs without the injected prop won't be able to show snippets. We have to go back upstream, which costs a lot of time...

Biggest Problems

  • Upstream doc changes frequently have unintended downstream consequences
  • Can't touch documentation configuration upstream

Patternfly.org adds many custom styles to markdown, even sometimes changing the DOM


            const changeHeadingLevel = (html, level) => {
              const modifiedHtml = html
                .replace(/<h2/g, `<${level} class="pf-u-mt-xl pf-u-mb-sm"`)
                .replace(/h2>/g, `${level}>`);
              return modifiedHtml;
            };
            const changeTableResponsiveness = html =>
              html.replace(/<table>/g, '<table class="pf-m-grid">')
            const HTML_DOCS = { __html:
              changeTableResponsiveness(changeHeadingLevel(docs, 'h3')) };

Custom rendering markdown for Core examples

React h2 looks fine Org h2 bug

Solution

Unify the configuration using a Gatsby theme. Luckily, all our sites use Gatsby.

Start with patternfly-next (pf4.patternfly.org) and patternfly-react (patternfly-react.surge.sh).

Work up to making a new patternfly-org (https://patternfly.org).

pf4.patternfly.org

  • Hosts HTML/CSS docs for patternfly-next
  • Uses Handlebars to compile HTML examples
  • Used index.js barrel files with custom Gatsby config

            import React from 'react';
            import Documentation from '@siteComponents/Documentation';
            import Example from '@siteComponents/Example';
            import brandSimpleExampleRaw from '!raw!./brand-simple-example.hbs';
            import BrandSimpleExample from './brand-simple-example.hbs';
            import docs from '../docs/code.md';

            export const Docs = docs;
            export default props => {
              const brandSimpleExample = BrandSimpleExample();
              const headingText = 'Brand';
              const variablesRoot = 'pf-c-brand';

              return <Documentation data={props} docs={Docs} heading={headingText} variablesRoot={variablesRoot}>
                  <Example heading="Brand simple" handlebars={brandSimpleExampleRaw}>
                    {brandSimpleExample}
                  </Example>
                </Documentation>;
            };

Old Core docs code

Old HTML/CSS docs Old Core docs

Problems

  • Inconsistent index.js files -- why should HTML devs know React?
  • Markdown content is outside of file
  • Not designed to be imported into Patternfly.org
    • Webpack import aliasing
    • Inconsistent urls with React/Org
      • /components/Badge
      • /documentation/core/components/badge

Solution: Gatsby theme

  • Copy over look and feel from current Patternfly.org
  • Add plugin options for top/side navigation
  • Stop using SASS for workspace
  • PREFIX ALL CSS CLASSES
  • Find design issues upstream

            ---
            title: Brand
            section: components
            ---
            
            ## Examples
            ```hbs title=Basic
            {{#> brand brand--attribute='src="/assets/images/pf_logo.svg" alt="PatternFly logo"'}} 
            {{/brand}}
            ```
            
            ## Documentation
            ### Overiew
            Simple brand component.
            
            ### Accessibility
            | Attribute | Applied to | Outcome |
            | -- | -- | -- |
            | `alt` | `.pf-c-brand` | The alt attribute specifies an alternate text for an image,
            if the image cannot be displayed. **Required** |
            
            ### Usage
            | Class | Applied to | Outcome |
            | -- | -- | -- |
            | `.pf-c-brand` | `<img>` |  Initiates a brand image. **Required** |
          

New docs code

Here's the PR (+19,108/-22,516)

New HTML/CSS docs New Core docs

React Problems

  • Using SASS and non-prefixed selectors for examples
  • Example titles and export names

            ## Simple area chart with right aligned legend
            ```js
            (jsx)
            ```

to


            ```js title=Basic-with-right-aligned-legend
            ExampleName = (jsx) OR
            class ExampleName extends React.Component {
            ```

Here's the PR (+5,402/-6,381)

Old React docs Old React docs
New React docs New React docs

Result

  • Consistent look and feel
  • Consistent examples
    • Prefixed CSS classes for site (.ws-*)
    • Prefixed CSS classes for examples
      (#ws-core-l-flex-basic, .ws-core-l-bullseye)
    • No inconsistently imported SASS
  • Easier to develop patternfly.org
    • DRY code
    • Run all 3 sites at once
    • Build in 8m (down from 25 minutes)

New features

  • Per-page fullscreen links (a11y!)
  • Codesandbox links (quick testing!)
  • Maintainable Javascript
  • Maintainable styling

Pitfalls

I didn't realize Gatsby was also building all the project SASS. I stopped Core development for 2 days.

  • Hot reload docs: #2349
  • Don't ship duplicated CSS: #2360
  • Properly copy SASS files to dist: #2367
  • Fix HTML formatting regression: #2363
  • Properly copy SASS to dist: #2367
  • Use CSSNano for minification again: #2360

TODO

  • Reimplement unique patternfly.org features
    • Design section
    • Global search
    • Fullscreen preview thumbnails
  • Make it easier develop patternfly.org

Repos