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:
committed by
Facebook GitHub Bot
parent
a46b7c2e78
commit
13f9fa64ff
@@ -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,15 +44,9 @@ 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: {
|
||||||
background: theme.successColor,
|
background: theme.successColor,
|
||||||
width: 50,
|
width: 50,
|
||||||
@@ -46,40 +55,41 @@ const demoStyle = {
|
|||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
},
|
},
|
||||||
border: {border: `1px dotted ${theme.primaryColor}`},
|
border: {border: `1px dotted ${theme.primaryColor}`},
|
||||||
};
|
};
|
||||||
|
|
||||||
const largeChild = (
|
const largeChild = (
|
||||||
<div style={{background: theme.warningColor}}>
|
<div style={{background: theme.warningColor}}>
|
||||||
<img src="https://fbflipper.com/img/mascot.png" height={500} />
|
<img src="https://fbflipper.com/img/mascot.png" height={500} />
|
||||||
</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 = (
|
||||||
const aFixedWidthBox = (
|
<div style={{...demoStyle.square, width: 100}}>A fixed child</div>
|
||||||
|
);
|
||||||
|
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
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
const aFixedHeightBox = (
|
const aFixedHeightBox = (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
background: theme.primaryColor,
|
background: theme.primaryColor,
|
||||||
height: 40,
|
height: 40,
|
||||||
lineHeight: '40px',
|
lineHeight: '40px',
|
||||||
color: 'white',
|
color: 'white',
|
||||||
}}
|
}}>
|
||||||
>
|
|
||||||
Fixed height box
|
Fixed height box
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
const aDynamicBox = (
|
const aDynamicBox = (
|
||||||
<div style={{background: theme.warningColor, flex: 1}}>
|
<div style={{background: theme.warningColor, flex: 1}}>
|
||||||
A dynamic child (flex: 1)
|
A dynamic child (flex: 1)
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
const someText = <Text>Some text</Text>;
|
const someText = <Text>Some text</Text>;
|
||||||
|
|
||||||
const demos = [
|
const demos = [
|
||||||
{
|
{
|
||||||
title: 'Layout.Container',
|
title: 'Layout.Container',
|
||||||
description: `Layout.Container can be used to organize the UI in regions. It takes care of paddings and borders. Children will be arranged vertically. Use Layout.Horizontal instead for arranging children horizontally. If you need a margin on this component, try to wrap it in other Layout component instead.`,
|
description: `Layout.Container can be used to organize the UI in regions. It takes care of paddings and borders. Children will be arranged vertically. Use Layout.Horizontal instead for arranging children horizontally. If you need a margin on this component, try to wrap it in other Layout component instead.`,
|
||||||
@@ -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': (
|
||||||
@@ -472,9 +482,9 @@ const demos = [
|
|||||||
),
|
),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
function ComponentPreview({title, demos, description, props}) {
|
function ComponentPreview({title, demos, description, props}) {
|
||||||
return (
|
return (
|
||||||
<Card title={title} size="small" type="inner">
|
<Card title={title} size="small" type="inner">
|
||||||
<TrackingScope scope={title}>
|
<TrackingScope scope={title}>
|
||||||
@@ -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>
|
||||||
@@ -540,23 +548,30 @@ function ComponentPreview({title, demos, description, props}) {
|
|||||||
</TrackingScope>
|
</TrackingScope>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const DesignComponentDemos = () => (
|
const DesignComponentDemos = () => (
|
||||||
<Layout.Container gap={theme.space.large}>
|
<Layout.Container gap={theme.space.large}>
|
||||||
{demos.map(demo => (
|
{demos.map(demo => (
|
||||||
<ComponentPreview key={demo.title} {...demo} />
|
<ComponentPreview key={demo.title} {...demo} />
|
||||||
))}
|
))}
|
||||||
</Layout.Container>
|
</Layout.Container>
|
||||||
);
|
);
|
||||||
|
|
||||||
function SandyDesignSystem() {
|
function SandyDesignSystem() {
|
||||||
const root = useRef(null);
|
const root = useRef(null);
|
||||||
|
|
||||||
// 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"
|
||||||
@@ -688,30 +705,9 @@ function SandyDesignSystem() {
|
|||||||
</Card>
|
</Card>
|
||||||
</Layout.Container>
|
</Layout.Container>
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
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>
|
||||||
<List.Item.Meta
|
<List.Item.Meta
|
||||||
@@ -729,9 +725,9 @@ function ColorPreview({name}) {
|
|||||||
/>
|
/>
|
||||||
</List.Item>
|
</List.Item>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const reset = css`
|
const reset = css`
|
||||||
ol,
|
ol,
|
||||||
ul {
|
ul {
|
||||||
list-style: revert;
|
list-style: revert;
|
||||||
@@ -743,14 +739,38 @@ const reset = css`
|
|||||||
.ant-card {
|
.ant-card {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const iframe = css`
|
const iframe = css`
|
||||||
width: 100%;
|
width: 100%;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const innerCss = `
|
const innerCss = `
|
||||||
body {
|
body {
|
||||||
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>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user