Docz: Playground-local stylesheets

Created on 5 Sep 2018  路  13Comments  路  Source: doczjs/docz

Hey 馃憢

I'm migrating the docs from Vanilla Form, my form state/validation management library. Currently I'm using Styleguidist, so migrating to Docz is pretty easy as all documentation and examples are already in Markdown.

Background

As the documentation examples are using plain HTML elements, I've used Styleguidist's require configuration option to apply Milligram styles for better-looking components in playground. This basically requires applies Milligram globally in the docs page.

For the Docz migration I followed the same idea, but using the CSS plugin to achieve it. I could make it work and all playground examples now have Milligram styles, but as a side-effect, Docz theme is completely screwed up, as Milligram uses global CSS.

Playground Isolation

I like a lot that both Styleguidist and Docz render playgrounds inline (no funky iframes), even understanding that conflicts ranging from HTML IDs to CSS could happen. On the other hand, I've come to believe that having at least styles isolation inside playgrounds is an important thing, because not all libraries are using fancy CSS systems (emotion, styled, css-modules, ...), so their styles could interfere with Docz's own theme.

Possible solution

Trying to avoid using iframe, it seems that Shadow DOM could be a thing here. By Shadow DOM-ing playground's preview and injecting style tags inside the playground we could get the desired styles isolation.

EDIT:: After some tinkering, I came with this component to Shadow DOM the example. The only downside is that it breaks HTML preview (for obvious reasons):

import React from 'react'
import ShadowDOM from 'react-shadow'
import marx from 'marx-css/css/marx.css'

const Themed = ({children}) =>
  <ShadowDOM include={[marx]}><div>{children}</div></ShadowDOM>

export default Themed

I had to match \.css$ and use file-loader in the pipeline to achieve the desired effect.

Even if this is already sufficient for me, having to repeat the theme wrapper every demo makes the demos clunky.

Most helpful comment

You can do the following in case you don't want to commit .docz (since has tmp folders)

import fs from "fs";

export default {
  typescript: true,
  htmlContext: {
    head: {
      raw: `<style>${fs.readFileSync(
        process.cwd() + "/src/assets/demo.css"
      )}</style>`
    }
  }
};

All 13 comments

Hey @derekstavis you can use the new htmlContext that's doesn't document yet on our docz 馃檮But is very simple and should fix your problem:

export default {
  htmlContext: {
    head: {
      links: [{ rel: 'stylesheet', href: '/path/of/your/css' }]
    }
  }
}

You can see more info about HtmlContext here: https://github.com/pedronauck/docz/blob/master/packages/docz-core/src/commands/args.ts#L27-L40

@pedronauck Could you please expand on how this htmlContext is used?

I've updated my doczrc.js config as follows, but I'm getting a 404 response for the CSS when I load the page GET http://localhost:3000/build/main.css 404 (Not Found)

doczrc.js
```doczrc.js
export default {
indexHtml: './src/documentation/index.html',
htmlContext: {
head: {
links: [
{ rel: 'stylesheet', href: '/build/main.css' }
]
}
}
};

**./src/documentation/index.html**
```index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="description" content="{{ description }}">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>{{ title }}</title>
    {{ head }}
  </head>
  <body>
    <div id="root" />
    {{ footer }}
  </body>
</html>

@pedronauck I believe the issue he is mentioning is applying the css only to the previewer.

I could make it work and all playground examples now have Milligram styles, but as a side-effect, Docz theme is completely screwed up, as Milligram uses global CSS.

So he is able to load the styles globally but it messes up the Docz theme itself. Is there a workaround for that?

@donifer Hi, i'm also getting the same error (404) when trying to append a custom .css file. htmlContext: { head: { links: [{ rel: "stylesheet", href: "./style.css" }] } }

Maybe i'm putting the css file in the wrong place? I put it along with the doczrc.js file

@pedronauck I believe the issue he is mentioning is applying the css only to the previewer.

I could make it work and all playground examples now have Milligram styles, but as a side-effect, Docz theme is completely screwed up, as Milligram uses global CSS.

So he is able to load the styles globally but it messes up the Docz theme itself. Is there a workaround for that?

@donifer, what you can do is pass some class just to playground, but some css that just act in the playground isn't possible :confused:

@pedronauck So even a global style.css isn't possible? Or at least, style the html? Maybe add some custom styles like fonts, colors, etc

You can put styles using htmlContext, but the public url need to be .docz/public. But I'm seeing that this is with a bug now, I'm fixing it and making a new release!

Ok, thank you very much! :)

i also get 404.

  htmlContext: {
    head: {
      links: [
        {
          rel: 'stylesheet',
          href: './index.css'
        }
      ],
      raw: [
        '<style>html{font-size:50px;}</style>'
      ]
    }
  }

index.css is in the root directory

@pedronauck Do you have any objection to using iframes to load each Playground? I see this issue coming up quite often and iframes seem to be the way to go for similar component docs generator tools.

Without style isolation, there's no way to safely use Docz.

@Dobby89 I don't have any objections, to be honest, I really think is the best solution since with an iframe we can simulate viewport and be able to work more effectively with responsive queries. But, I tried to transform playground render using iframes, but I didn't get success. I'll try again on v1.

You can do the following in case you don't want to commit .docz (since has tmp folders)

import fs from "fs";

export default {
  typescript: true,
  htmlContext: {
    head: {
      raw: `<style>${fs.readFileSync(
        process.cwd() + "/src/assets/demo.css"
      )}</style>`
    }
  }
};

@giulianok That's useful, thanks. Now I'm stuck by docz overriding the styles I inlined, since the styles added to 'htmlContext' become the first style tag in the document...any ideas?

Specifically, I'm attempting to define the font-family for the document, and docz is overriding it as Source Sans Pro in a later style tag

Was this page helpful?
0 / 5 - 0 ratings

Related issues

bugzpodder picture bugzpodder  路  26Comments

ronghang picture ronghang  路  33Comments

tadeuszwojcik picture tadeuszwojcik  路  30Comments

godmar picture godmar  路  24Comments

robjac picture robjac  路  41Comments