Fix style guide generation

Summary:
The website generation fails on newer versions of `flipper-plugin` as it contains an import-time side effect. This leads to this error during build time:

```
[ERROR] Docusaurus server-side rendering could not render static page with path /docs/extending/style-guide/.
[INFO] It looks like you are using code that should run on the client-side only.
To get around it, try using `<BrowserOnly>` (https://docusaurus.io/docs/docusaurus-core/#browseronly) or `ExecutionEnvironment` (https://docusaurus.io/doc
s/docusaurus-core/#executionenvironment).
It might also require to wrap your client code in `useEffect` hook and/or import a third-party library dynamically (if any).
```

This ain't pretty but by wrapping the entire file in a single function that conditionally imports the `flipper-plugin` if we are indeed in a browser environment fixes the problem.

Reviewed By: antonk52

Differential Revision: D43773298

fbshipit-source-id: 8e1099249626ca9fe745ce51014491fe9674a5a4
This commit is contained in:
Pascal Hartig
2023-03-03 11:04:13 -08:00
committed by Facebook GitHub Bot
parent a46b7c2e78
commit 13f9fa64ff

View File

@@ -20,7 +20,22 @@ import {
Table, Table,
} from 'antd'; } from 'antd';
import {CodeOutlined} from '@ant-design/icons'; import {CodeOutlined} from '@ant-design/icons';
import { import {css} from '@emotion/css';
import reactElementToJSXString from 'react-element-to-jsx-string';
import {IFrame} from './IFrame';
import useBaseUrl from '@docusaurus/useBaseUrl';
import useIsBrowser from '@docusaurus/useIsBrowser';
const {Title, Text, Link} = Typography;
export default function StyleGuide() {
// We need a browser environment to access the window object and import flipper-plugin.
const isBrowser = useIsBrowser();
if (!isBrowser) {
return <>The Style Guide is only available in a browser environment.</>;
}
const {
Layout, Layout,
NUX, NUX,
Panel, Panel,
@@ -29,13 +44,7 @@ import {
TrackingScope, TrackingScope,
Tabs, Tabs,
Tab, Tab,
} from 'flipper-plugin'; } = require('flipper-plugin');
import {css} from '@emotion/css';
import reactElementToJSXString from 'react-element-to-jsx-string';
import {IFrame} from './IFrame';
import useBaseUrl from '@docusaurus/useBaseUrl';
const {Title, Text, Link} = Typography;
const demoStyle = { const demoStyle = {
square: { square: {
@@ -54,7 +63,9 @@ const largeChild = (
</div> </div>
); );
const aButton = <Button>A button</Button>; const aButton = <Button>A button</Button>;
const aBox = <div style={{...demoStyle.square, width: 100}}>A fixed child</div>; const aBox = (
<div style={{...demoStyle.square, width: 100}}>A fixed child</div>
);
const aFixedWidthBox = ( const aFixedWidthBox = (
<div style={{background: theme.primaryColor, width: 150, color: 'white'}}> <div style={{background: theme.primaryColor, width: 150, color: 'white'}}>
Fixed width box Fixed width box
@@ -67,8 +78,7 @@ const aFixedHeightBox = (
height: 40, height: 40,
lineHeight: '40px', lineHeight: '40px',
color: 'white', color: 'white',
}} }}>
>
Fixed height box Fixed height box
</div> </div>
); );
@@ -125,16 +135,14 @@ const demos = [
style={{ style={{
height: 50, height: 50,
background: theme.successColor, background: theme.successColor,
}} }}></Layout.Container>
></Layout.Container>
), ),
'bordered pad rounded': ( 'bordered pad rounded': (
<Layout.Container <Layout.Container
bordered bordered
pad pad
rounded rounded
style={{background: theme.backgroundDefault, width: 200}} style={{background: theme.backgroundDefault, width: 200}}>
>
<div style={demoStyle.square}>child</div> <div style={demoStyle.square}>child</div>
</Layout.Container> </Layout.Container>
), ),
@@ -215,8 +223,7 @@ const demos = [
height: 100, height: 100,
width: 100, width: 100,
border: `2px solid ${theme.primaryColor}`, border: `2px solid ${theme.primaryColor}`,
}} }}>
>
<Layout.Container> <Layout.Container>
<Text ellipsis> <Text ellipsis>
This text is truncated because it is too long and scroll is This text is truncated because it is too long and scroll is
@@ -351,8 +358,7 @@ const demos = [
title="Panel 3 (not collapsible, pad, gap)" title="Panel 3 (not collapsible, pad, gap)"
collapsible={false} collapsible={false}
pad pad
gap gap>
>
{aFixedHeightBox} {aFixedHeightBox}
{aFixedHeightBox} {aFixedHeightBox}
</Panel> </Panel>
@@ -460,7 +466,11 @@ const demos = [
description: description:
'Describes more precisely the place in the UI for all underlying Tracked elements. Multiple Tracking scopes are automatically nested. Use the `withTrackingScope` HoC to automatically wrap a component definition in a tracking scope', 'Describes more precisely the place in the UI for all underlying Tracked elements. Multiple Tracking scopes are automatically nested. Use the `withTrackingScope` HoC to automatically wrap a component definition in a tracking scope',
props: [ props: [
['scope', 'string', 'The name of the scope. For example "Login Dialog"'], [
'scope',
'string',
'The name of the scope. For example "Login Dialog"',
],
], ],
demos: { demos: {
'Basic example': ( 'Basic example': (
@@ -490,8 +500,7 @@ function ComponentPreview({title, demos, description, props}) {
style={{ style={{
background: theme.backgroundWash, background: theme.backgroundWash,
width: '100%', width: '100%',
}} }}>
>
{children} {children}
</div> </div>
</Tab> </Tab>
@@ -501,8 +510,7 @@ function ComponentPreview({title, demos, description, props}) {
background: theme.backgroundWash, background: theme.backgroundWash,
width: '100%', width: '100%',
padding: theme.space.medium, padding: theme.space.medium,
}} }}>
>
<pre>{reactElementToJSXString(children)}</pre> <pre>{reactElementToJSXString(children)}</pre>
</div> </div>
</Tab> </Tab>
@@ -556,7 +564,14 @@ function SandyDesignSystem() {
// Whenever layout happens, or if the size of root changes, measure it and send a message to the parent frame. // Whenever layout happens, or if the size of root changes, measure it and send a message to the parent frame.
useLayoutEffect(() => { useLayoutEffect(() => {
if (root.current) { if (root.current) {
const sendUpdate = () => window.postMessage({name: 'setStyleGuideHeight', value: `${root.current.scrollHeight}px`}, '*'); const sendUpdate = () =>
window.postMessage(
{
name: 'setStyleGuideHeight',
value: `${root.current.scrollHeight}px`,
},
'*',
);
const observer = new ResizeObserver(() => { const observer = new ResizeObserver(() => {
sendUpdate(); sendUpdate();
}); });
@@ -574,9 +589,11 @@ function SandyDesignSystem() {
<p> <p>
Welcome to the Flipper Design System. The Flipper design system is Welcome to the Flipper Design System. The Flipper design system is
based on{' '} based on{' '}
<Link href="https://ant.design/components/overview/">Ant Design</Link> <Link href="https://ant.design/components/overview/">
. Any component found in the ANT documentation can be used. This page Ant Design
demonstrates the usage of: </Link>
. Any component found in the ANT documentation can be used. This
page demonstrates the usage of:
</p> </p>
<ul> <ul>
<li>Colors</li> <li>Colors</li>
@@ -606,17 +623,17 @@ function SandyDesignSystem() {
<li> <li>
In general, components that have a <code>grow</code> property will In general, components that have a <code>grow</code> property will
grow to use the full height of their <em>parents</em> if{' '} grow to use the full height of their <em>parents</em> if{' '}
<code>true</code>. In contrast, if grow is set to <code>false</code>{' '} <code>true</code>. In contrast, if grow is set to{' '}
components will use their natural size, based on their{' '} <code>false</code> components will use their natural size, based
<em>children</em>. on their <em>children</em>.
</li> </li>
<li> <li>
The other important property here is <em>scrollable</em>. If an The other important property here is <em>scrollable</em>. If an
element supports this property, setting it will imply{' '} element supports this property, setting it will imply{' '}
<code>grow</code>, and the element will show a scrollbar if needed. <code>grow</code>, and the element will show a scrollbar if
Setting <code>scrollabe</code> to <code>false</code> causes the needed. Setting <code>scrollabe</code> to <code>false</code>{' '}
element to always use its natural size, growing or shrinking based causes the element to always use its natural size, growing or
on the contents rather than the parent. shrinking based on the contents rather than the parent.
</li> </li>
</ul> </ul>
</Card> </Card>
@@ -644,8 +661,8 @@ function SandyDesignSystem() {
<> <>
Common Ant components, with modifiers applied. The{' '} Common Ant components, with modifiers applied. The{' '}
<code>Title</code>, <code>Text</code> and <code>Link</code>{' '} <code>Title</code>, <code>Text</code> and <code>Link</code>{' '}
components can be found by importing the <code>Typography</code>{' '} components can be found by importing the{' '}
namespace from Ant. <code>Typography</code> namespace from Ant.
</> </>
} }
type="info" type="info"
@@ -690,27 +707,6 @@ function SandyDesignSystem() {
); );
} }
export default function DesignSystemFramed() {
// We're displaying the style guide in an iframe to isolate it's styles.
// But we don't know how big it is, so don't know how high to make the iframe to avoid a double scroll bar.
// So lets get the js inside the frame measure itself and post a message to this frame, where we'll then
// adjust the size of the iframe to match.
useEffect(() => {
window.addEventListener("message", (event) => {
if (event.data.name === 'setStyleGuideHeight') {
document.getElementById('styleguide').style.height = event.data.value;
}
})
}, [])
return (
<IFrame className={iframe} id="styleguide">
<link id="styleguidestylesheet" rel="stylesheet" href={useBaseUrl("/css/style-guide.css")} />
<style>{innerCss}</style>
<SandyDesignSystem />
</IFrame>
);
}
function ColorPreview({name}) { function ColorPreview({name}) {
return ( return (
<List.Item> <List.Item>
@@ -754,3 +750,27 @@ const innerCss = `
overflow: hidden; overflow: hidden;
} }
`; `;
// We're displaying the style guide in an iframe to isolate it's styles.
// But we don't know how big it is, so don't know how high to make the iframe to avoid a double scroll bar.
// So lets get the js inside the frame measure itself and post a message to this frame, where we'll then
// adjust the size of the iframe to match.
useEffect(() => {
window.addEventListener('message', event => {
if (event.data.name === 'setStyleGuideHeight') {
document.getElementById('styleguide').style.height = event.data.value;
}
});
}, []);
return (
<IFrame className={iframe} id="styleguide">
<link
id="styleguidestylesheet"
rel="stylesheet"
href={useBaseUrl('/css/style-guide.css')}
/>
<style>{innerCss}</style>
<SandyDesignSystem />
</IFrame>
);
}