diff --git a/desktop/app/package.json b/desktop/app/package.json
index 73404b36a..f65c0faa1 100644
--- a/desktop/app/package.json
+++ b/desktop/app/package.json
@@ -49,6 +49,7 @@
"react-color": "^2.18.1",
"react-debounce-render": "^6.0.0",
"react-dom": "^16.13.0",
+ "react-element-to-jsx-string": "^14.3.1",
"react-markdown": "^4.2.2",
"react-player": "^1.15.2",
"react-redux": "^7.1.1",
diff --git a/desktop/app/src/sandy-chrome/AppInspect.tsx b/desktop/app/src/sandy-chrome/AppInspect.tsx
index 20a47d723..50e4d7a95 100644
--- a/desktop/app/src/sandy-chrome/AppInspect.tsx
+++ b/desktop/app/src/sandy-chrome/AppInspect.tsx
@@ -9,33 +9,23 @@
import React from 'react';
import {Button, Dropdown, Menu, Radio, Input} from 'antd';
-import {shell} from 'electron';
import {LeftSidebar, SidebarTitle, InfoIcon} from './LeftSidebar';
import {
AppleOutlined,
AndroidOutlined,
SettingOutlined,
} from '@ant-design/icons';
-import {Layout, styled} from '../ui';
+import {Layout, Link} from '../ui';
import {theme} from './theme';
const appTooltip = (
<>
Inspect apps by selecting connected devices and emulators. Navigate and
bookmark frequent destinations in the app. Refresh, screenshot and
- screenrecord is also available.
- {
-
- }
+ screenrecord is also available.{' '}
+
+ Learn More
+
>
);
@@ -43,11 +33,13 @@ export function AppInspect() {
return (
- <>
+ {appTooltip}}>
App Inspect
-
+
} defaultValue="mysite" />
@@ -55,20 +47,14 @@ export function AppInspect() {
} type="link" />
} type="link" />
-
- >
-
Dynamic section
+
+
+ Dynamic section
);
}
-const TopSection = styled(Layout.Vertical)({
- boxShadow: `inset 0px -1px 0px ${theme.dividerColor}`,
- padding: `8px 12px`,
- gap: theme.space.middle,
-});
-
function DeviceDropdown() {
return (
diff --git a/desktop/app/src/sandy-chrome/DesignComponentDemos.tsx b/desktop/app/src/sandy-chrome/DesignComponentDemos.tsx
new file mode 100644
index 000000000..63fffee74
--- /dev/null
+++ b/desktop/app/src/sandy-chrome/DesignComponentDemos.tsx
@@ -0,0 +1,359 @@
+/**
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ * @format
+ */
+
+import React from 'react';
+import {Typography, Card, Table, Collapse, Button, Tabs} from 'antd';
+import {Layout} from '../ui';
+import {theme} from './theme';
+import reactElementToJSXString from 'react-element-to-jsx-string';
+import {CodeOutlined} from '@ant-design/icons';
+
+const {Text} = Typography;
+
+const demoStyle: Record = {
+ square: {
+ background: theme.successColor,
+ width: 50,
+ height: 50,
+ lineHeight: '50px',
+ textAlign: 'center',
+ },
+ border: {border: `1px dotted ${theme.primaryColor}`},
+} as const;
+
+type PreviewProps = {
+ title: string;
+ description?: string;
+ props: [string, string, string][];
+ demos: Record;
+};
+
+const largeChild = (
+
+
+
+);
+const aButton = ;
+const aBox =
A fixed child
;
+const aFixedWidthBox = (
+
+ Fixed width box
+
+);
+const aFixedHeightBox = (
+
+ Fixed height box
+
+);
+const aDynamicBox = (
+
+ A dynamic child (flex: 1)
+
+);
+const someText = Some text;
+
+const demos: PreviewProps[] = [
+ {
+ title: 'Layout.Container',
+ description:
+ 'Layout.Container can be used to organize the UI in regions. It takes care of paddings and borders. To arrange multiple children use one of the other Layout components. If you need a margin on this component, try to wrap it in other Layout component instead.',
+ props: [
+ ['rounded', 'boolean (false)', 'Make the corners rounded'],
+ [
+ 'padded',
+ 'boolean (false)',
+ 'Use a standard small padding for this container (use `padding` for non-default padding)',
+ ],
+ [
+ 'padding',
+ 'CSS Padding',
+ 'Short-hand to set the style.padding property',
+ ],
+ [
+ 'bordered',
+ 'boolean (false)',
+ 'This container will use a default border on all sides',
+ ],
+ [
+ 'borderTop',
+ 'boolean (false)',
+ 'Use a standard padding on the top side',
+ ],
+ [
+ 'borderRight',
+ 'boolean (false)',
+ 'Use a standard padding on the right side',
+ ],
+ [
+ 'borderBottom',
+ 'boolean (false)',
+ 'Use a standard padding on the bottom side',
+ ],
+ [
+ 'borderLeft',
+ 'boolean (false)',
+ 'Use a standard padding on the left side',
+ ],
+ ],
+ demos: {
+ 'Basic container with fixed dimensions': (
+
+ ),
+ 'Basic container with fixed height': (
+
+ ),
+ 'bordered padded rounded': (
+
+
child
+
+ ),
+ },
+ },
+ {
+ title: 'Layout.ScrollContainer',
+ description:
+ 'Use this component to create an area that can be scrolled. The scrollable area will automatically consume all available space. ScrollContainer accepts all properties that Container accepts as well. Padding will be applied to the child rather than the parent.',
+ props: [],
+ demos: {
+ 'Basic usage': (
+
+ {largeChild}
+
+ ),
+ },
+ },
+ {
+ title: 'Layout.Horizontal',
+ description:
+ 'Use this component to arrange multiple items horizontally. All vanilla Container props can be used as well.',
+ props: [
+ [
+ 'gap',
+ 'number (0)',
+ 'Set the spacing between children. Typically theme.space.small should be used.',
+ ],
+ [
+ 'center',
+ 'boolean (false)',
+ 'If set, all children will use their own height, and they will be centered vertically in the layout. If not set, all children will be stretched to the height of the layout.',
+ ],
+ ],
+ demos: {
+ 'Basic usage, gap={24}': (
+
+ {aButton}
+ {someText}
+ {aBox}
+ {aDynamicBox}
+
+ ),
+ 'Using flags: padded center gap={8} (great for toolbars and such)': (
+
+ {aButton}
+ {someText}
+ {aBox}
+ {aDynamicBox}
+
+ ),
+ },
+ },
+ {
+ title: 'Layout.Vertical',
+ description:
+ 'Use this component to arrange multiple items vertically. All vanilla Container props can be used as well.',
+ props: [
+ [
+ 'gap',
+ 'number (0)',
+ 'Set the spacing between children. Typically theme.space.small should be used.',
+ ],
+ [
+ 'center',
+ 'boolean (false)',
+ 'If set, all children will use their own height, and they will be centered vertically in the layout. If not set, all children will be stretched to the height of the layout.',
+ ],
+ ],
+ demos: {
+ 'Basic usage, gap={24}': (
+
+ {aButton}
+ {someText}
+ {aBox}
+ {aDynamicBox}
+
+ ),
+ 'Using flags: padded center gap={8} (great for toolbars and such)': (
+
+ {aButton}
+ {someText}
+ {aBox}
+ {aDynamicBox}
+
+ ),
+ },
+ },
+ {
+ title: 'Layout.Top|Left|Right|Bottom',
+ description:
+ "Divides all available space over two children. The (top|left|right|bottom)-most first child will keep it's own dimensions, and positioned (top|left|right|bottom) of the other child. All remaining space will be assigned to the remaining child.",
+ props: [
+ [
+ 'scrollable',
+ 'boolean (false)',
+ 'If set, the area of the second child will automatically be made scrollable.',
+ ],
+ ],
+ demos: {
+ 'Layout.Top': (
+
+ {aFixedHeightBox}
+ {aDynamicBox}
+
+ ),
+ 'Layout.Left': (
+
+ {aFixedWidthBox}
+ {aDynamicBox}
+
+ ),
+ 'Layout.Right': (
+
+ {aDynamicBox}
+ {aFixedWidthBox}
+
+ ),
+ 'Layout.Bottom': (
+
+ {aDynamicBox}
+ {aFixedHeightBox}
+
+ ),
+ 'Layout.Top + scrollable': (
+
+
+ {aFixedHeightBox}
+ {largeChild}
+
+
+ ),
+ 'Layout.Left + scrollable': (
+
+
+ {aFixedWidthBox}
+ {largeChild}
+
+
+ ),
+ 'Layout.Right + scrollable': (
+
+
+ {largeChild}
+ {aFixedWidthBox}
+
+
+ ),
+ 'Layout.Bottom + scrollable': (
+
+
+ {largeChild}
+ {aFixedHeightBox}
+
+
+ ),
+ },
+ },
+];
+
+function ComponentPreview({title, demos, description, props}: PreviewProps) {
+ return (
+
+
+ {description}
+
+
+
+ {Object.entries(demos).map(([name, children]) => (
+
;
}
-
-function TemporarilyContent() {
- return (
-
- New UI for Flipper, Sandy Project! Nothing to see now. Go back to current
- Flipper
-
-
-
- );
-}
diff --git a/desktop/app/src/sandy-chrome/SandyDesignSystem.tsx b/desktop/app/src/sandy-chrome/SandyDesignSystem.tsx
new file mode 100644
index 000000000..875f72cce
--- /dev/null
+++ b/desktop/app/src/sandy-chrome/SandyDesignSystem.tsx
@@ -0,0 +1,158 @@
+/**
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ * @format
+ */
+
+import React from 'react';
+import {Typography, Button, Space, Input, Card, Alert, List} from 'antd';
+import {Layout} from '../ui';
+import {theme} from './theme';
+import {css} from 'emotion';
+import {DesignComponentDemos} from './DesignComponentDemos';
+
+const {Title, Text, Link} = Typography;
+
+export default function SandyDesignSystem() {
+ return (
+
+
+
+
+ Welcome to the Flipper Design System. The Flipper design system is
+ based on{' '}
+
+ Ant Design
+
+ . Any component found in the ANT documentation can be used. This
+ page demonstrates the usage of:
+
+
+
Colors
+
Typography
+
Theme Variables
+
Layout components
+
+
+ The following components from Ant should not be used:
+
+
+
+ Layout: use Flipper's Layout.* instead.
+
+
+
Sandy guidelines
+
+
+ Avoid using `margin` properties, use padding on the container
+ indeed, or gap in combination with{' '}
+ Layout.Horizontal|Vertical
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Common Ant components, with modifiers applied. The{' '}
+ Title, Text and Link{' '}
+ components can be found by importing the{' '}
+ Typography namespace from Ant.
+ >
+ }
+ type="info"
+ />
+ Title
+ Title level=2
+ Title level=3
+ Title level=4
+ Text
+ Text - type=secondary
+ Text - type=success
+ Text - type=warning
+ Text - danger
+ Text - disbled
+ Text - strong
+ Text - code
+ Link
+
+ Link - type=secondary
+
+
+
+
+
+
+
+
+ The following theme veriables are exposed from the Flipper{' '}
+ theme object. See the colors section above for a
+ preview of the colors.
+ >
+ }
+ />
+