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,
|
||||
} from 'antd';
|
||||
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,
|
||||
NUX,
|
||||
Panel,
|
||||
@@ -29,15 +44,9 @@ import {
|
||||
TrackingScope,
|
||||
Tabs,
|
||||
Tab,
|
||||
} from 'flipper-plugin';
|
||||
import {css} from '@emotion/css';
|
||||
import reactElementToJSXString from 'react-element-to-jsx-string';
|
||||
import {IFrame} from './IFrame';
|
||||
import useBaseUrl from '@docusaurus/useBaseUrl';
|
||||
} = require('flipper-plugin');
|
||||
|
||||
const {Title, Text, Link} = Typography;
|
||||
|
||||
const demoStyle = {
|
||||
const demoStyle = {
|
||||
square: {
|
||||
background: theme.successColor,
|
||||
width: 50,
|
||||
@@ -46,40 +55,41 @@ const demoStyle = {
|
||||
textAlign: 'center',
|
||||
},
|
||||
border: {border: `1px dotted ${theme.primaryColor}`},
|
||||
};
|
||||
};
|
||||
|
||||
const largeChild = (
|
||||
const largeChild = (
|
||||
<div style={{background: theme.warningColor}}>
|
||||
<img src="https://fbflipper.com/img/mascot.png" height={500} />
|
||||
</div>
|
||||
);
|
||||
const aButton = <Button>A button</Button>;
|
||||
const aBox = <div style={{...demoStyle.square, width: 100}}>A fixed child</div>;
|
||||
const aFixedWidthBox = (
|
||||
);
|
||||
const aButton = <Button>A button</Button>;
|
||||
const aBox = (
|
||||
<div style={{...demoStyle.square, width: 100}}>A fixed child</div>
|
||||
);
|
||||
const aFixedWidthBox = (
|
||||
<div style={{background: theme.primaryColor, width: 150, color: 'white'}}>
|
||||
Fixed width box
|
||||
</div>
|
||||
);
|
||||
const aFixedHeightBox = (
|
||||
);
|
||||
const aFixedHeightBox = (
|
||||
<div
|
||||
style={{
|
||||
background: theme.primaryColor,
|
||||
height: 40,
|
||||
lineHeight: '40px',
|
||||
color: 'white',
|
||||
}}
|
||||
>
|
||||
}}>
|
||||
Fixed height box
|
||||
</div>
|
||||
);
|
||||
const aDynamicBox = (
|
||||
);
|
||||
const aDynamicBox = (
|
||||
<div style={{background: theme.warningColor, flex: 1}}>
|
||||
A dynamic child (flex: 1)
|
||||
</div>
|
||||
);
|
||||
const someText = <Text>Some text</Text>;
|
||||
);
|
||||
const someText = <Text>Some text</Text>;
|
||||
|
||||
const demos = [
|
||||
const demos = [
|
||||
{
|
||||
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.`,
|
||||
@@ -125,16 +135,14 @@ const demos = [
|
||||
style={{
|
||||
height: 50,
|
||||
background: theme.successColor,
|
||||
}}
|
||||
></Layout.Container>
|
||||
}}></Layout.Container>
|
||||
),
|
||||
'bordered pad rounded': (
|
||||
<Layout.Container
|
||||
bordered
|
||||
pad
|
||||
rounded
|
||||
style={{background: theme.backgroundDefault, width: 200}}
|
||||
>
|
||||
style={{background: theme.backgroundDefault, width: 200}}>
|
||||
<div style={demoStyle.square}>child</div>
|
||||
</Layout.Container>
|
||||
),
|
||||
@@ -215,8 +223,7 @@ const demos = [
|
||||
height: 100,
|
||||
width: 100,
|
||||
border: `2px solid ${theme.primaryColor}`,
|
||||
}}
|
||||
>
|
||||
}}>
|
||||
<Layout.Container>
|
||||
<Text ellipsis>
|
||||
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)"
|
||||
collapsible={false}
|
||||
pad
|
||||
gap
|
||||
>
|
||||
gap>
|
||||
{aFixedHeightBox}
|
||||
{aFixedHeightBox}
|
||||
</Panel>
|
||||
@@ -460,7 +466,11 @@ const demos = [
|
||||
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',
|
||||
props: [
|
||||
['scope', 'string', 'The name of the scope. For example "Login Dialog"'],
|
||||
[
|
||||
'scope',
|
||||
'string',
|
||||
'The name of the scope. For example "Login Dialog"',
|
||||
],
|
||||
],
|
||||
demos: {
|
||||
'Basic example': (
|
||||
@@ -472,9 +482,9 @@ const demos = [
|
||||
),
|
||||
},
|
||||
},
|
||||
];
|
||||
];
|
||||
|
||||
function ComponentPreview({title, demos, description, props}) {
|
||||
function ComponentPreview({title, demos, description, props}) {
|
||||
return (
|
||||
<Card title={title} size="small" type="inner">
|
||||
<TrackingScope scope={title}>
|
||||
@@ -490,8 +500,7 @@ function ComponentPreview({title, demos, description, props}) {
|
||||
style={{
|
||||
background: theme.backgroundWash,
|
||||
width: '100%',
|
||||
}}
|
||||
>
|
||||
}}>
|
||||
{children}
|
||||
</div>
|
||||
</Tab>
|
||||
@@ -501,8 +510,7 @@ function ComponentPreview({title, demos, description, props}) {
|
||||
background: theme.backgroundWash,
|
||||
width: '100%',
|
||||
padding: theme.space.medium,
|
||||
}}
|
||||
>
|
||||
}}>
|
||||
<pre>{reactElementToJSXString(children)}</pre>
|
||||
</div>
|
||||
</Tab>
|
||||
@@ -540,23 +548,30 @@ function ComponentPreview({title, demos, description, props}) {
|
||||
</TrackingScope>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const DesignComponentDemos = () => (
|
||||
const DesignComponentDemos = () => (
|
||||
<Layout.Container gap={theme.space.large}>
|
||||
{demos.map(demo => (
|
||||
<ComponentPreview key={demo.title} {...demo} />
|
||||
))}
|
||||
</Layout.Container>
|
||||
);
|
||||
);
|
||||
|
||||
function SandyDesignSystem() {
|
||||
function SandyDesignSystem() {
|
||||
const root = useRef(null);
|
||||
|
||||
// Whenever layout happens, or if the size of root changes, measure it and send a message to the parent frame.
|
||||
useLayoutEffect(() => {
|
||||
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(() => {
|
||||
sendUpdate();
|
||||
});
|
||||
@@ -574,9 +589,11 @@ function SandyDesignSystem() {
|
||||
<p>
|
||||
Welcome to the Flipper Design System. The Flipper design system is
|
||||
based on{' '}
|
||||
<Link href="https://ant.design/components/overview/">Ant Design</Link>
|
||||
. Any component found in the ANT documentation can be used. This page
|
||||
demonstrates the usage of:
|
||||
<Link href="https://ant.design/components/overview/">
|
||||
Ant Design
|
||||
</Link>
|
||||
. Any component found in the ANT documentation can be used. This
|
||||
page demonstrates the usage of:
|
||||
</p>
|
||||
<ul>
|
||||
<li>Colors</li>
|
||||
@@ -606,17 +623,17 @@ function SandyDesignSystem() {
|
||||
<li>
|
||||
In general, components that have a <code>grow</code> property will
|
||||
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>{' '}
|
||||
components will use their natural size, based on their{' '}
|
||||
<em>children</em>.
|
||||
<code>true</code>. In contrast, if grow is set to{' '}
|
||||
<code>false</code> components will use their natural size, based
|
||||
on their <em>children</em>.
|
||||
</li>
|
||||
<li>
|
||||
The other important property here is <em>scrollable</em>. If an
|
||||
element supports this property, setting it will imply{' '}
|
||||
<code>grow</code>, and the element will show a scrollbar if needed.
|
||||
Setting <code>scrollabe</code> to <code>false</code> causes the
|
||||
element to always use its natural size, growing or shrinking based
|
||||
on the contents rather than the parent.
|
||||
<code>grow</code>, and the element will show a scrollbar if
|
||||
needed. Setting <code>scrollabe</code> to <code>false</code>{' '}
|
||||
causes the element to always use its natural size, growing or
|
||||
shrinking based on the contents rather than the parent.
|
||||
</li>
|
||||
</ul>
|
||||
</Card>
|
||||
@@ -644,8 +661,8 @@ function SandyDesignSystem() {
|
||||
<>
|
||||
Common Ant components, with modifiers applied. The{' '}
|
||||
<code>Title</code>, <code>Text</code> and <code>Link</code>{' '}
|
||||
components can be found by importing the <code>Typography</code>{' '}
|
||||
namespace from Ant.
|
||||
components can be found by importing the{' '}
|
||||
<code>Typography</code> namespace from Ant.
|
||||
</>
|
||||
}
|
||||
type="info"
|
||||
@@ -688,30 +705,9 @@ function SandyDesignSystem() {
|
||||
</Card>
|
||||
</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 (
|
||||
<List.Item>
|
||||
<List.Item.Meta
|
||||
@@ -729,9 +725,9 @@ function ColorPreview({name}) {
|
||||
/>
|
||||
</List.Item>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const reset = css`
|
||||
const reset = css`
|
||||
ol,
|
||||
ul {
|
||||
list-style: revert;
|
||||
@@ -743,14 +739,38 @@ const reset = css`
|
||||
.ant-card {
|
||||
background: transparent;
|
||||
}
|
||||
`;
|
||||
`;
|
||||
|
||||
const iframe = css`
|
||||
const iframe = css`
|
||||
width: 100%;
|
||||
`;
|
||||
`;
|
||||
|
||||
const innerCss = `
|
||||
const innerCss = `
|
||||
body {
|
||||
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