Small design system simplifications
Summary: So far we distinguished `Layout.Container` from `Layout.Vertical`, but they did almost exactly the same, so figured to unify them, so smaller API ftw :) Normal containers put children vertical, and if you want to use horizontal, use Layout.Horzontal Also simplified code in Layout file a little bit. Fixed issue I split container where the main container didn't go "underneath" the fixed container Reviewed By: cekkaewnumchai Differential Revision: D24502547 fbshipit-source-id: 517db3692749e670cda8f0cd7cb1c807df818b4d
This commit is contained in:
committed by
Facebook GitHub Bot
parent
26e040ea73
commit
30f5f0b59a
@@ -67,8 +67,7 @@ const someText = <Text>Some text</Text>;
|
|||||||
const demos: PreviewProps[] = [
|
const demos: PreviewProps[] = [
|
||||||
{
|
{
|
||||||
title: 'Layout.Container',
|
title: 'Layout.Container',
|
||||||
description:
|
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.`,
|
||||||
'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: [
|
props: [
|
||||||
['rounded', 'boolean (false)', 'Make the corners rounded'],
|
['rounded', 'boolean (false)', 'Make the corners rounded'],
|
||||||
[
|
[
|
||||||
@@ -91,6 +90,16 @@ const demos: PreviewProps[] = [
|
|||||||
'boolean (false)',
|
'boolean (false)',
|
||||||
'Use a standard padding on the top side',
|
'Use a standard padding on the top side',
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
'gap',
|
||||||
|
'true / number (0)',
|
||||||
|
'Set the spacing between children. If just set, theme.space.small will be used.',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'center',
|
||||||
|
'boolean (false)',
|
||||||
|
'If set, all children will use their own naturally width, and they will be centered horizontally in the Container. If not set, all children will be stretched to the width of the Container.',
|
||||||
|
],
|
||||||
],
|
],
|
||||||
demos: {
|
demos: {
|
||||||
'Basic container with fixed dimensions': (
|
'Basic container with fixed dimensions': (
|
||||||
@@ -112,6 +121,52 @@ const demos: PreviewProps[] = [
|
|||||||
<div style={demoStyle.square}>child</div>
|
<div style={demoStyle.square}>child</div>
|
||||||
</Layout.Container>
|
</Layout.Container>
|
||||||
),
|
),
|
||||||
|
'Multiple children, gap={24}': (
|
||||||
|
<Layout.Container gap={24}>
|
||||||
|
{aButton}
|
||||||
|
{someText}
|
||||||
|
{aBox}
|
||||||
|
{aDynamicBox}
|
||||||
|
</Layout.Container>
|
||||||
|
),
|
||||||
|
'Multiple children icmw. pad center gap': (
|
||||||
|
<Layout.Container pad center gap>
|
||||||
|
{aButton}
|
||||||
|
{someText}
|
||||||
|
{aBox}
|
||||||
|
{aDynamicBox}
|
||||||
|
</Layout.Container>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Layout.Horizontal',
|
||||||
|
description:
|
||||||
|
'Use this component to arrange multiple items horizontally. All vanilla Container props can be used as well.',
|
||||||
|
props: [
|
||||||
|
[
|
||||||
|
'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="large"': (
|
||||||
|
<Layout.Horizontal gap="large">
|
||||||
|
{aButton}
|
||||||
|
{someText}
|
||||||
|
{aBox}
|
||||||
|
{aDynamicBox}
|
||||||
|
</Layout.Horizontal>
|
||||||
|
),
|
||||||
|
'Using flags: pad center gap={8} (great for toolbars and such)': (
|
||||||
|
<Layout.Horizontal pad center gap={8}>
|
||||||
|
{aButton}
|
||||||
|
{someText}
|
||||||
|
{aBox}
|
||||||
|
{aDynamicBox}
|
||||||
|
</Layout.Horizontal>
|
||||||
|
),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -139,87 +194,17 @@ const demos: PreviewProps[] = [
|
|||||||
width: 100,
|
width: 100,
|
||||||
border: `2px solid ${theme.primaryColor}`,
|
border: `2px solid ${theme.primaryColor}`,
|
||||||
}}>
|
}}>
|
||||||
<Layout.Vertical>
|
<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
|
||||||
vertical only...
|
vertical only...
|
||||||
</Text>
|
</Text>
|
||||||
{largeChild}
|
{largeChild}
|
||||||
</Layout.Vertical>
|
</Layout.Container>
|
||||||
</Layout.ScrollContainer>
|
</Layout.ScrollContainer>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
title: 'Layout.Horizontal',
|
|
||||||
description:
|
|
||||||
'Use this component to arrange multiple items horizontally. All vanilla Container props can be used as well.',
|
|
||||||
props: [
|
|
||||||
[
|
|
||||||
'gap',
|
|
||||||
Object.keys(theme.space).join(' | ') + ' | number | true',
|
|
||||||
'Set the spacing between children. For `true` theme.space.small should be used. Defaults to 0.',
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'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="large"': (
|
|
||||||
<Layout.Horizontal gap="large">
|
|
||||||
{aButton}
|
|
||||||
{someText}
|
|
||||||
{aBox}
|
|
||||||
{aDynamicBox}
|
|
||||||
</Layout.Horizontal>
|
|
||||||
),
|
|
||||||
'Using flags: pad center gap={8} (great for toolbars and such)': (
|
|
||||||
<Layout.Horizontal pad center gap={8}>
|
|
||||||
{aButton}
|
|
||||||
{someText}
|
|
||||||
{aBox}
|
|
||||||
{aDynamicBox}
|
|
||||||
</Layout.Horizontal>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
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}': (
|
|
||||||
<Layout.Vertical gap={24}>
|
|
||||||
{aButton}
|
|
||||||
{someText}
|
|
||||||
{aBox}
|
|
||||||
{aDynamicBox}
|
|
||||||
</Layout.Vertical>
|
|
||||||
),
|
|
||||||
'Using flags: pad center gap (great for toolbars and such)': (
|
|
||||||
<Layout.Vertical pad center gap>
|
|
||||||
{aButton}
|
|
||||||
{someText}
|
|
||||||
{aBox}
|
|
||||||
{aDynamicBox}
|
|
||||||
</Layout.Vertical>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
title: 'Layout.Top|Left|Right|Bottom',
|
title: 'Layout.Top|Left|Right|Bottom',
|
||||||
description:
|
description:
|
||||||
@@ -300,11 +285,11 @@ const demos: PreviewProps[] = [
|
|||||||
function ComponentPreview({title, demos, description, props}: PreviewProps) {
|
function ComponentPreview({title, demos, description, props}: PreviewProps) {
|
||||||
return (
|
return (
|
||||||
<Card title={title} size="small" type="inner">
|
<Card title={title} size="small" type="inner">
|
||||||
<Layout.Vertical gap="small">
|
<Layout.Container gap="small">
|
||||||
<Text type="secondary">{description}</Text>
|
<Text type="secondary">{description}</Text>
|
||||||
<Collapse ghost>
|
<Collapse ghost>
|
||||||
<Collapse.Panel header="Examples" key="demos">
|
<Collapse.Panel header="Examples" key="demos">
|
||||||
<Layout.Vertical gap="large">
|
<Layout.Container gap="large">
|
||||||
{Object.entries(demos).map(([name, children]) => (
|
{Object.entries(demos).map(([name, children]) => (
|
||||||
<div key={name}>
|
<div key={name}>
|
||||||
<Tabs type="line">
|
<Tabs type="line">
|
||||||
@@ -330,7 +315,7 @@ function ComponentPreview({title, demos, description, props}: PreviewProps) {
|
|||||||
</Tabs>
|
</Tabs>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</Layout.Vertical>
|
</Layout.Container>
|
||||||
</Collapse.Panel>
|
</Collapse.Panel>
|
||||||
<Collapse.Panel header="Props" key="props">
|
<Collapse.Panel header="Props" key="props">
|
||||||
<Table
|
<Table
|
||||||
@@ -358,15 +343,15 @@ function ComponentPreview({title, demos, description, props}: PreviewProps) {
|
|||||||
/>
|
/>
|
||||||
</Collapse.Panel>
|
</Collapse.Panel>
|
||||||
</Collapse>
|
</Collapse>
|
||||||
</Layout.Vertical>
|
</Layout.Container>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DesignComponentDemos = () => (
|
export const DesignComponentDemos = () => (
|
||||||
<Layout.Vertical 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.Vertical>
|
</Layout.Container>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ import {ToplevelProps} from './SandyApp';
|
|||||||
import {useValue} from 'flipper-plugin';
|
import {useValue} from 'flipper-plugin';
|
||||||
import {logout} from '../reducers/user';
|
import {logout} from '../reducers/user';
|
||||||
import config from '../fb-stubs/config';
|
import config from '../fb-stubs/config';
|
||||||
import Layout from '../ui/components/Layout';
|
import {Layout} from '../ui/components/Layout';
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
const LeftRailButtonElem = styled(Button)<{kind?: 'small'}>(({kind}) => ({
|
const LeftRailButtonElem = styled(Button)<{kind?: 'small'}>(({kind}) => ({
|
||||||
@@ -108,7 +108,7 @@ export function LeftRail({
|
|||||||
return (
|
return (
|
||||||
<Layout.Container borderRight padv={12} width={48}>
|
<Layout.Container borderRight padv={12} width={48}>
|
||||||
<Layout.Bottom>
|
<Layout.Bottom>
|
||||||
<Layout.Vertical center gap={10} padh={6}>
|
<Layout.Container center gap={10} padh={6}>
|
||||||
<LeftRailButton
|
<LeftRailButton
|
||||||
icon={<MobileFilled />}
|
icon={<MobileFilled />}
|
||||||
title="App Inspect"
|
title="App Inspect"
|
||||||
@@ -127,8 +127,8 @@ export function LeftRail({
|
|||||||
toplevelSelection={toplevelSelection}
|
toplevelSelection={toplevelSelection}
|
||||||
setToplevelSelection={setToplevelSelection}
|
setToplevelSelection={setToplevelSelection}
|
||||||
/>
|
/>
|
||||||
</Layout.Vertical>
|
</Layout.Container>
|
||||||
<Layout.Vertical center gap={10} padh={6}>
|
<Layout.Container center gap={10} padh={6}>
|
||||||
<SetupDoctorButton />
|
<SetupDoctorButton />
|
||||||
<WelcomeScreenButton />
|
<WelcomeScreenButton />
|
||||||
<ShowSettingsButton />
|
<ShowSettingsButton />
|
||||||
@@ -140,7 +140,7 @@ export function LeftRail({
|
|||||||
<RightSidebarToggleButton />
|
<RightSidebarToggleButton />
|
||||||
<LeftSidebarToggleButton />
|
<LeftSidebarToggleButton />
|
||||||
{config.showLogin && <LoginButton />}
|
{config.showLogin && <LoginButton />}
|
||||||
</Layout.Vertical>
|
</Layout.Container>
|
||||||
</Layout.Bottom>
|
</Layout.Bottom>
|
||||||
</Layout.Container>
|
</Layout.Container>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ import {Button, Tooltip, Typography} from 'antd';
|
|||||||
import {InfoCircleOutlined} from '@ant-design/icons';
|
import {InfoCircleOutlined} from '@ant-design/icons';
|
||||||
|
|
||||||
export const LeftSidebar: React.FC = ({children}) => (
|
export const LeftSidebar: React.FC = ({children}) => (
|
||||||
<Layout.Vertical borderRight padv="small" grow shrink>
|
<Layout.Container borderRight padv="small" grow shrink>
|
||||||
{children}
|
{children}
|
||||||
</Layout.Vertical>
|
</Layout.Container>
|
||||||
);
|
);
|
||||||
|
|
||||||
export function SidebarTitle({
|
export function SidebarTitle({
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ const {Title, Text, Link} = Typography;
|
|||||||
export default function SandyDesignSystem() {
|
export default function SandyDesignSystem() {
|
||||||
return (
|
return (
|
||||||
<Layout.ScrollContainer className={reset}>
|
<Layout.ScrollContainer className={reset}>
|
||||||
<Layout.Vertical gap="large">
|
<Layout.Container gap="large">
|
||||||
<Card title="Flipper Design System" bordered={false}>
|
<Card title="Flipper Design System" bordered={false}>
|
||||||
<p>
|
<p>
|
||||||
Welcome to the Flipper Design System. The Flipper design system is
|
Welcome to the Flipper Design System. The Flipper design system is
|
||||||
@@ -122,7 +122,7 @@ export default function SandyDesignSystem() {
|
|||||||
<Card title="Layout components" bordered={false}>
|
<Card title="Layout components" bordered={false}>
|
||||||
<DesignComponentDemos />
|
<DesignComponentDemos />
|
||||||
</Card>
|
</Card>
|
||||||
</Layout.Vertical>
|
</Layout.Container>
|
||||||
</Layout.ScrollContainer>
|
</Layout.ScrollContainer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -160,7 +160,7 @@ function CollapsableCategory(props: {checks: Array<HealthcheckReportItem>}) {
|
|||||||
function HealthCheckList(props: {report: HealthcheckReport}) {
|
function HealthCheckList(props: {report: HealthcheckReport}) {
|
||||||
useEffect(() => reportUsage('doctor:report:opened'), []);
|
useEffect(() => reportUsage('doctor:report:opened'), []);
|
||||||
return (
|
return (
|
||||||
<Layout.Vertical>
|
<Layout.Container>
|
||||||
<ResultTopDialog status={props.report.result.status} />
|
<ResultTopDialog status={props.report.result.status} />
|
||||||
{Object.values(props.report.categories).map((category) => (
|
{Object.values(props.report.categories).map((category) => (
|
||||||
<Layout.Container key={category.key}>
|
<Layout.Container key={category.key}>
|
||||||
@@ -187,7 +187,7 @@ function HealthCheckList(props: {report: HealthcheckReport}) {
|
|||||||
/>
|
/>
|
||||||
</Layout.Container>
|
</Layout.Container>
|
||||||
))}
|
))}
|
||||||
</Layout.Vertical>
|
</Layout.Container>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ export function AppInspect() {
|
|||||||
<SidebarTitle actions={<InfoIcon>{appTooltip}</InfoIcon>}>
|
<SidebarTitle actions={<InfoIcon>{appTooltip}</InfoIcon>}>
|
||||||
App Inspect
|
App Inspect
|
||||||
</SidebarTitle>
|
</SidebarTitle>
|
||||||
<Layout.Vertical padv="small" padh="medium" gap={theme.space.large}>
|
<Layout.Container padv="small" padh="medium" gap={theme.space.large}>
|
||||||
<AppSelector />
|
<AppSelector />
|
||||||
<Input addonAfter={<SettingOutlined />} defaultValue="mysite" />
|
<Input addonAfter={<SettingOutlined />} defaultValue="mysite" />
|
||||||
<Layout.Horizontal gap>
|
<Layout.Horizontal gap>
|
||||||
@@ -55,7 +55,7 @@ export function AppInspect() {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Layout.Horizontal>
|
</Layout.Horizontal>
|
||||||
</Layout.Vertical>
|
</Layout.Container>
|
||||||
</Layout.Container>
|
</Layout.Container>
|
||||||
<Layout.Container padv={theme.space.large}>
|
<Layout.Container padv={theme.space.large}>
|
||||||
<Layout.ScrollContainer vertical>
|
<Layout.ScrollContainer vertical>
|
||||||
|
|||||||
@@ -79,12 +79,12 @@ export function AppSelector() {
|
|||||||
<AppInspectButton title="Select the device / app to inspect">
|
<AppInspectButton title="Select the device / app to inspect">
|
||||||
<Layout.Horizontal gap center>
|
<Layout.Horizontal gap center>
|
||||||
<AppIcon appname={client?.query.app} />
|
<AppIcon appname={client?.query.app} />
|
||||||
<Layout.Vertical grow shrink>
|
<Layout.Container grow shrink>
|
||||||
<Text strong>{client?.query.app ?? ''}</Text>
|
<Text strong>{client?.query.app ?? ''}</Text>
|
||||||
<Text>
|
<Text>
|
||||||
{selectedDevice?.displayTitle() || 'Available devices'}
|
{selectedDevice?.displayTitle() || 'Available devices'}
|
||||||
</Text>
|
</Text>
|
||||||
</Layout.Vertical>
|
</Layout.Container>
|
||||||
<CaretDownOutlined />
|
<CaretDownOutlined />
|
||||||
</Layout.Horizontal>
|
</Layout.Horizontal>
|
||||||
</AppInspectButton>
|
</AppInspectButton>
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import {renderReactRoot} from '../../utils/renderReactRoot';
|
|||||||
import {Store} from '../../reducers';
|
import {Store} from '../../reducers';
|
||||||
import {useStore} from '../../utils/useStore';
|
import {useStore} from '../../utils/useStore';
|
||||||
import {launchEmulator} from '../../devices/AndroidDevice';
|
import {launchEmulator} from '../../devices/AndroidDevice';
|
||||||
import Layout from '../../ui/components/Layout';
|
import {Layout} from '../../ui/components/Layout';
|
||||||
import {
|
import {
|
||||||
launchSimulator,
|
launchSimulator,
|
||||||
getSimulators,
|
getSimulators,
|
||||||
@@ -100,9 +100,9 @@ export function LaunchEmulatorDialog({
|
|||||||
title="Launch Emulator"
|
title="Launch Emulator"
|
||||||
footer={null}
|
footer={null}
|
||||||
bodyStyle={{maxHeight: 400, overflow: 'auto'}}>
|
bodyStyle={{maxHeight: 400, overflow: 'auto'}}>
|
||||||
<Layout.Vertical gap>
|
<Layout.Container gap>
|
||||||
{items.length ? items : <Alert message="No emulators available" />}
|
{items.length ? items : <Alert message="No emulators available" />}
|
||||||
</Layout.Vertical>
|
</Layout.Container>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ function NotificationEntry({notification}: {notification: PluginNotification}) {
|
|||||||
style: {color: theme.primaryColor},
|
style: {color: theme.primaryColor},
|
||||||
});
|
});
|
||||||
return (
|
return (
|
||||||
<Layout.Vertical gap="small" pad="medium">
|
<Layout.Container gap="small" pad="medium">
|
||||||
<Layout.Horizontal gap="tiny" center>
|
<Layout.Horizontal gap="tiny" center>
|
||||||
{icon}
|
{icon}
|
||||||
<Text>{pluginId}</Text>
|
<Text>{pluginId}</Text>
|
||||||
@@ -140,7 +140,7 @@ function NotificationEntry({notification}: {notification: PluginNotification}) {
|
|||||||
Open
|
Open
|
||||||
</Button>
|
</Button>
|
||||||
<DetailCollapse detail={content.message} />
|
<DetailCollapse detail={content.message} />
|
||||||
</Layout.Vertical>
|
</Layout.Container>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,14 +151,14 @@ function NotificationList({
|
|||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<Layout.ScrollContainer vertical>
|
<Layout.ScrollContainer vertical>
|
||||||
<Layout.Vertical>
|
<Layout.Container>
|
||||||
{notifications.map((notification) => (
|
{notifications.map((notification) => (
|
||||||
<NotificationEntry
|
<NotificationEntry
|
||||||
key={notification.notification.id}
|
key={notification.notification.id}
|
||||||
notification={notification}
|
notification={notification}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</Layout.Vertical>
|
</Layout.Container>
|
||||||
</Layout.ScrollContainer>
|
</Layout.ScrollContainer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -175,12 +175,12 @@ export function Notification() {
|
|||||||
return (
|
return (
|
||||||
<LeftSidebar>
|
<LeftSidebar>
|
||||||
<Layout.Top>
|
<Layout.Top>
|
||||||
<Layout.Vertical gap="tiny" padv="tiny" borderBottom>
|
<Layout.Container gap="tiny" padv="tiny" borderBottom>
|
||||||
<SidebarTitle actions={actions}>notifications</SidebarTitle>
|
<SidebarTitle actions={actions}>notifications</SidebarTitle>
|
||||||
<Layout.Container padh="medium" padv="small">
|
<Layout.Container padh="medium" padv="small">
|
||||||
<Input placeholder="Search..." prefix={<SearchOutlined />} />
|
<Input placeholder="Search..." prefix={<SearchOutlined />} />
|
||||||
</Layout.Container>
|
</Layout.Container>
|
||||||
</Layout.Vertical>
|
</Layout.Container>
|
||||||
<NotificationList notifications={notificationExample} />
|
<NotificationList notifications={notificationExample} />
|
||||||
</Layout.Top>
|
</Layout.Top>
|
||||||
</LeftSidebar>
|
</LeftSidebar>
|
||||||
|
|||||||
@@ -35,6 +35,14 @@ type ContainerProps = {
|
|||||||
grow?: boolean;
|
grow?: boolean;
|
||||||
// allow shrinking beyond minally needed size? Makes using ellipsis on children possible
|
// allow shrinking beyond minally needed size? Makes using ellipsis on children possible
|
||||||
shrink?: boolean;
|
shrink?: boolean;
|
||||||
|
/**
|
||||||
|
* Gab between individual items
|
||||||
|
*/
|
||||||
|
gap?: Spacing;
|
||||||
|
/**
|
||||||
|
* If set, items will be aligned in the center, if false (the default) items will be stretched.
|
||||||
|
*/
|
||||||
|
center?: boolean;
|
||||||
} & PaddingProps;
|
} & PaddingProps;
|
||||||
|
|
||||||
const Container = styled.div<ContainerProps>(
|
const Container = styled.div<ContainerProps>(
|
||||||
@@ -49,6 +57,8 @@ const Container = styled.div<ContainerProps>(
|
|||||||
height,
|
height,
|
||||||
grow,
|
grow,
|
||||||
shrink,
|
shrink,
|
||||||
|
gap,
|
||||||
|
center,
|
||||||
...rest
|
...rest
|
||||||
}) => ({
|
}) => ({
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
@@ -61,6 +71,9 @@ const Container = styled.div<ContainerProps>(
|
|||||||
: shrink
|
: shrink
|
||||||
? `0 1 0` // allow shrinking smaller than natural size
|
? `0 1 0` // allow shrinking smaller than natural size
|
||||||
: `0 0 auto`, // (default) use natural size, don't grow or shrink (in parent flex direction)
|
: `0 0 auto`, // (default) use natural size, don't grow or shrink (in parent flex direction)
|
||||||
|
alignItems: center ? 'center' : 'stretch',
|
||||||
|
gap: normalizeSpace(gap, theme.space.small),
|
||||||
|
|
||||||
minWidth: shrink ? 0 : undefined,
|
minWidth: shrink ? 0 : undefined,
|
||||||
boxSizing: 'border-box',
|
boxSizing: 'border-box',
|
||||||
width,
|
width,
|
||||||
@@ -77,33 +90,9 @@ const Container = styled.div<ContainerProps>(
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
type DistributionProps = ContainerProps & {
|
const Horizontal = styled(Container)({
|
||||||
/**
|
|
||||||
* Gab between individual items
|
|
||||||
*/
|
|
||||||
gap?: Spacing;
|
|
||||||
/**
|
|
||||||
* If set, items will be aligned in the center, if false (the default) items will be stretched.
|
|
||||||
*/
|
|
||||||
center?: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
function distributionStyle({gap, center}: DistributionProps) {
|
|
||||||
return {
|
|
||||||
gap: normalizeSpace(gap, theme.space.small),
|
|
||||||
alignItems: center ? 'center' : 'stretch',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const Horizontal = styled(Container)<DistributionProps>((props) => ({
|
|
||||||
...distributionStyle(props),
|
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
}));
|
});
|
||||||
|
|
||||||
const Vertical = styled(Container)<DistributionProps>((props) => ({
|
|
||||||
...distributionStyle(props),
|
|
||||||
flexDirection: 'column',
|
|
||||||
}));
|
|
||||||
|
|
||||||
const ScrollParent = styled.div<{axis?: ScrollAxis}>(({axis}) => ({
|
const ScrollParent = styled.div<{axis?: ScrollAxis}>(({axis}) => ({
|
||||||
flex: 1,
|
flex: 1,
|
||||||
@@ -113,7 +102,7 @@ const ScrollParent = styled.div<{axis?: ScrollAxis}>(({axis}) => ({
|
|||||||
overflowY: axis === 'x' ? 'hidden' : 'auto',
|
overflowY: axis === 'x' ? 'hidden' : 'auto',
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const ScrollChild = styled(Vertical)<{axis?: ScrollAxis}>(({axis}) => ({
|
const ScrollChild = styled(Container)<{axis?: ScrollAxis}>(({axis}) => ({
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
minHeight: '100%',
|
minHeight: '100%',
|
||||||
minWidth: '100%',
|
minWidth: '100%',
|
||||||
@@ -153,6 +142,24 @@ type SplitLayoutProps = {
|
|||||||
children: [React.ReactNode, React.ReactNode];
|
children: [React.ReactNode, React.ReactNode];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function renderSplitLayout(
|
||||||
|
props: SplitLayoutProps,
|
||||||
|
direction: 'column' | 'row',
|
||||||
|
grow: 1 | 2,
|
||||||
|
) {
|
||||||
|
// eslint-disable-next-line
|
||||||
|
const isSandy = useIsSandy();
|
||||||
|
if (!isSandy) return renderLayout(props, direction === 'row', grow === 1);
|
||||||
|
let [child1, child2] = props.children;
|
||||||
|
if (props.scrollable) child2 = <ScrollContainer>{child2}</ScrollContainer>;
|
||||||
|
return (
|
||||||
|
<SandySplitContainer {...props} flexDirection={direction} grow={grow}>
|
||||||
|
{child1}
|
||||||
|
{child2}
|
||||||
|
</SandySplitContainer>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Layout component divides all available screenspace over two components:
|
* The Layout component divides all available screenspace over two components:
|
||||||
* A fixed top (or left) component, and all remaining space to a bottom component.
|
* A fixed top (or left) component, and all remaining space to a bottom component.
|
||||||
@@ -164,59 +171,22 @@ type SplitLayoutProps = {
|
|||||||
*
|
*
|
||||||
* Use Layout.Top / Right / Bottom / Left to indicate where the fixed element should live.
|
* Use Layout.Top / Right / Bottom / Left to indicate where the fixed element should live.
|
||||||
*/
|
*/
|
||||||
const Layout = {
|
export const Layout = {
|
||||||
Top(props: SplitLayoutProps) {
|
Top(props: SplitLayoutProps) {
|
||||||
const isSandy = useIsSandy();
|
return renderSplitLayout(props, 'column', 2);
|
||||||
if (!isSandy) return renderLayout(props, false, false);
|
|
||||||
let [child1, child2] = props.children;
|
|
||||||
if (props.scrollable) child2 = <ScrollContainer>{child2}</ScrollContainer>;
|
|
||||||
return (
|
|
||||||
<SandySplitContainer {...props} flexDirection="column" grow={2}>
|
|
||||||
{child1}
|
|
||||||
{child2}
|
|
||||||
</SandySplitContainer>
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
Bottom(props: SplitLayoutProps) {
|
Bottom(props: SplitLayoutProps) {
|
||||||
const isSandy = useIsSandy();
|
return renderSplitLayout(props, 'column', 1);
|
||||||
if (!isSandy) return renderLayout(props, false, true);
|
|
||||||
let [child1, child2] = props.children;
|
|
||||||
if (props.scrollable) child1 = <ScrollContainer>{child1}</ScrollContainer>;
|
|
||||||
return (
|
|
||||||
<SandySplitContainer {...props} flexDirection="column" grow={1}>
|
|
||||||
{child1}
|
|
||||||
{child2}
|
|
||||||
</SandySplitContainer>
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
Left(props: SplitLayoutProps) {
|
Left(props: SplitLayoutProps) {
|
||||||
const isSandy = useIsSandy();
|
return renderSplitLayout(props, 'row', 2);
|
||||||
if (!isSandy) return renderLayout(props, true, false);
|
|
||||||
let [child1, child2] = props.children;
|
|
||||||
if (props.scrollable) child2 = <ScrollContainer>{child2}</ScrollContainer>;
|
|
||||||
return (
|
|
||||||
<SandySplitContainer {...props} flexDirection="row" grow={2}>
|
|
||||||
{child1}
|
|
||||||
{child2}
|
|
||||||
</SandySplitContainer>
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
Right(props: SplitLayoutProps) {
|
Right(props: SplitLayoutProps) {
|
||||||
const isSandy = useIsSandy();
|
return renderSplitLayout(props, 'row', 1);
|
||||||
if (!isSandy) return renderLayout(props, true, true);
|
|
||||||
let [child1, child2] = props.children;
|
|
||||||
if (props.scrollable) child1 = <ScrollContainer>{child1}</ScrollContainer>;
|
|
||||||
return (
|
|
||||||
<SandySplitContainer {...props} flexDirection="row" grow={1}>
|
|
||||||
{child1}
|
|
||||||
{child2}
|
|
||||||
</SandySplitContainer>
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
Container,
|
Container,
|
||||||
ScrollContainer,
|
ScrollContainer,
|
||||||
Horizontal,
|
Horizontal,
|
||||||
Vertical,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Object.keys(Layout).forEach((key) => {
|
Object.keys(Layout).forEach((key) => {
|
||||||
@@ -235,14 +205,14 @@ const SandySplitContainer = styled.div<{
|
|||||||
alignItems: props.center ? 'center' : 'stretch',
|
alignItems: props.center ? 'center' : 'stretch',
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
'> :nth-child(1)': {
|
'> :nth-child(1)': {
|
||||||
flex: props.grow === 1 ? growStyle : fixedStyle,
|
flex: props.grow === 1 ? splitGrowStyle : splitFixedStyle,
|
||||||
|
minWidth: props.grow === 1 ? 0 : undefined,
|
||||||
},
|
},
|
||||||
'> :nth-child(2)': {
|
'> :nth-child(2)': {
|
||||||
flex: props.grow === 2 ? growStyle : fixedStyle,
|
flex: props.grow === 2 ? splitGrowStyle : splitFixedStyle,
|
||||||
|
minWidth: props.grow === 2 ? 0 : undefined,
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const fixedStyle = `0 0 auto`;
|
const splitFixedStyle = `0 0 auto`;
|
||||||
const growStyle = `1 0 0`;
|
const splitGrowStyle = `1 0 0`;
|
||||||
|
|
||||||
export default Layout;
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import FlexBox from './FlexBox';
|
|||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
import {useIsSandy} from '../../sandy-chrome/SandyContext';
|
import {useIsSandy} from '../../sandy-chrome/SandyContext';
|
||||||
import {theme} from '../../sandy-chrome/theme';
|
import {theme} from '../../sandy-chrome/theme';
|
||||||
import Layout from './Layout';
|
import {Layout} from './Layout';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A toolbar.
|
* A toolbar.
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import styled from '@emotion/styled';
|
|||||||
import {debounce} from 'lodash';
|
import {debounce} from 'lodash';
|
||||||
import ToggleButton from '../ToggleSwitch';
|
import ToggleButton from '../ToggleSwitch';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Layout from '../Layout';
|
import {Layout} from '../Layout';
|
||||||
import {theme} from '../../../sandy-chrome/theme';
|
import {theme} from '../../../sandy-chrome/theme';
|
||||||
|
|
||||||
const SearchBar = styled(Toolbar)({
|
const SearchBar = styled(Toolbar)({
|
||||||
|
|||||||
@@ -178,7 +178,7 @@ export {default as CenteredView} from './components/CenteredView';
|
|||||||
export {default as Info} from './components/Info';
|
export {default as Info} from './components/Info';
|
||||||
export {default as Bordered} from './components/Bordered';
|
export {default as Bordered} from './components/Bordered';
|
||||||
export {default as AlternatingRows} from './components/AlternatingRows';
|
export {default as AlternatingRows} from './components/AlternatingRows';
|
||||||
export {default as Layout} from './components/Layout';
|
export {Layout} from './components/Layout';
|
||||||
|
|
||||||
export {default as Scrollable} from './components/Scrollable';
|
export {default as Scrollable} from './components/Scrollable';
|
||||||
export * from './components/Highlight';
|
export * from './components/Highlight';
|
||||||
|
|||||||
Reference in New Issue
Block a user