More shaving on design system

Summary: Added standardized dimensions for padding and gap, to encourage people to build layouts that look consistent, using for example `padv="small"`

Reviewed By: cekkaewnumchai

Differential Revision: D23961386

fbshipit-source-id: 33cd3b8974858e021a8b7d1b32f018fe3f007c63
This commit is contained in:
Michel Weststrate
2020-10-01 05:32:07 -07:00
committed by Facebook GitHub Bot
parent e8370e9fc1
commit b105574d00
10 changed files with 148 additions and 107 deletions

View File

@@ -27,6 +27,7 @@ import {notNull} from './utils/typeUtils';
import constants from './fb-stubs/constants';
import {Logger} from './fb-interfaces/Logger';
import {NormalizedMenuEntry, buildInMenuEntries} from 'flipper-plugin';
import {StyleGuide} from './sandy-chrome/StyleGuide';
export type DefaultKeyboardAction = keyof typeof buildInMenuEntries;
export type TopLevelMenu = 'Edit' | 'View' | 'Window' | 'Help';
@@ -339,6 +340,12 @@ function getTemplate(
store.dispatch(setActiveSheet(ACTIVE_SHEET_PLUGINS));
},
},
{
label: 'Flipper style guide',
click() {
store.dispatch(setStaticView(StyleGuide));
},
},
{
label: 'Toggle Developer Tools',
accelerator: (function () {

View File

@@ -37,12 +37,10 @@ export function AppInspect() {
<SidebarTitle actions={<InfoIcon>{appTooltip}</InfoIcon>}>
App Inspect
</SidebarTitle>
<Layout.Vertical
padding={`${theme.space.small}px ${theme.space.medium}px`}
gap={theme.space.large}>
<Layout.Vertical padv="small" padh="medium" gap={theme.space.large}>
<DeviceDropdown />
<Input addonAfter={<SettingOutlined />} defaultValue="mysite" />
<Layout.Horizontal gap={theme.space.small}>
<Layout.Horizontal gap>
<Button icon={<SettingOutlined />} type="link" />
<Button icon={<SettingOutlined />} type="link" />
<Button icon={<SettingOutlined />} type="link" />

View File

@@ -72,14 +72,14 @@ const demos: PreviewProps[] = [
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)',
'padv / padh / pad',
Object.keys(theme.space).join(' | ') + ' | number | true',
'Short-hand to set the horizontal, vertical or both paddings. The keys correspond to the theme space settings. Using `true` picks the default horizontal / vertical padding for inline elements.',
],
[
'padding',
'CSS Padding',
'Short-hand to set the style.padding property',
'width / height',
'number',
'Set the width / height of this container in pixels. Use sparingly.',
],
[
'bordered',
@@ -87,25 +87,10 @@ const demos: PreviewProps[] = [
'This container will use a default border on all sides',
],
[
'borderTop',
'borderTop / borderRight / borderBottom / borderLeft',
'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': (
@@ -149,8 +134,8 @@ const demos: PreviewProps[] = [
props: [
[
'gap',
'number (0)',
'Set the spacing between children. Typically theme.space.small should be used.',
Object.keys(theme.space).join(' | ') + ' | number | true',
'Set the spacing between children. For `true` theme.space.small should be used. Defaults to 0.',
],
[
'center',
@@ -159,8 +144,8 @@ const demos: PreviewProps[] = [
],
],
demos: {
'Basic usage, gap={24}': (
<Layout.Horizontal gap={24}>
'Basic usage, gap="large"': (
<Layout.Horizontal gap="large">
{aButton}
{someText}
{aBox}
@@ -287,11 +272,11 @@ const demos: PreviewProps[] = [
function ComponentPreview({title, demos, description, props}: PreviewProps) {
return (
<Card title={title} size="small" type="inner">
<Layout.Vertical gap={theme.space.small}>
<Layout.Vertical gap="small">
<Text type="secondary">{description}</Text>
<Collapse ghost>
<Collapse.Panel header="Examples" key="demos">
<Layout.Vertical gap={theme.space.large}>
<Layout.Vertical gap="large">
{Object.entries(demos).map(([name, children]) => (
<div key={name}>
<Tabs type="line">

View File

@@ -31,13 +31,6 @@ import {errorCounterAtom} from '../chrome/ConsoleLogs';
import {ToplevelProps} from './SandyApp';
import {useValue} from 'flipper-plugin';
const LeftRailContainer = styled(Layout.Bottom)({
width: 48,
borderRight: `1px solid ${theme.dividerColor}`,
padding: `${theme.paddingLarge}px ${theme.paddingSmall}px`,
});
LeftRailContainer.displayName = 'LeftRailContainer';
const LeftRailButtonElem = styled(Button)<{kind?: 'small'}>(({kind}) => ({
width: kind === 'small' ? 32 : 36,
height: kind === 'small' ? 32 : 36,
@@ -97,7 +90,8 @@ export function LeftRail({
setToplevelSelection,
}: ToplevelProps) {
return (
<LeftRailContainer>
<Layout.Container borderRight padv={12} padh={6} width={48}>
<Layout.Bottom>
<Layout.Vertical center gap={10}>
<LeftRailButton
icon={<MobileFilled />}
@@ -136,7 +130,8 @@ export function LeftRail({
<LeftSidebarToggleButton />
<LeftRailButton icon={<LoginOutlined />} title="Log In" />
</Layout.Vertical>
</LeftRailContainer>
</Layout.Bottom>
</Layout.Container>
);
}

View File

@@ -15,9 +15,9 @@ import {Button, Tooltip, Typography} from 'antd';
import {InfoCircleOutlined} from '@ant-design/icons';
export const LeftSidebar: React.FC = ({children}) => (
<Layout.Vertical borderRight padding={`${theme.space.small}px 0`}>
{children}
</Layout.Vertical>
<Layout.Container borderRight padv="small">
<Layout.Vertical>{children}</Layout.Vertical>
</Layout.Container>
);
export function SidebarTitle({
@@ -36,7 +36,7 @@ export function SidebarTitle({
}
const LeftMenuTitle = styled(Layout.Horizontal)({
padding: `0px ${theme.paddingLarge}px`,
padding: `0px ${theme.inlinePaddingH}px`,
lineHeight: `${theme.space.large}px`,
fontSize: theme.fontSize.smallBody,
textTransform: 'uppercase',

View File

@@ -91,11 +91,7 @@ export function SandyApp({logger}: {logger: Logger}) {
setToplevelSelection={setToplevelSelection}
/>
<Sidebar width={250} minWidth={220} maxWidth={800} gutter>
{leftMenuContent && (
<Layout.Container borderRight>
{leftMenuContent}
</Layout.Container>
)}
{leftMenuContent && leftMenuContent}
</Sidebar>
</Layout.Horizontal>
<MainContainer>

View File

@@ -18,9 +18,9 @@ const {Title, Text, Link} = Typography;
export default function SandyDesignSystem() {
return (
<Layout.ScrollContainer className={resetLists}>
<Layout.Vertical gap={theme.space.large}>
<Card title="Flipper Design System">
<Layout.ScrollContainer className={reset}>
<Layout.Vertical gap="large">
<Card title="Flipper Design System" bordered={false}>
<p>
Welcome to the Flipper Design System. The Flipper design system is
based on{' '}
@@ -57,7 +57,7 @@ export default function SandyDesignSystem() {
</li>
</ul>
</Card>
<Card title="Colors">
<Card title="Colors" bordered={false}>
<Alert message="The following colors are available on the <code>theme</code> object. Please stick to this color palette, as these colors will be translated to dark mode correctly." />
<ColorPreview name="primaryColor" />
<ColorPreview name="successColor" />
@@ -72,7 +72,7 @@ export default function SandyDesignSystem() {
<ColorPreview name="backgroundTransparentHover" />
<ColorPreview name="dividerColor" />
</Card>
<Card title="Typography">
<Card title="Typography" bordered={false}>
<Space direction="vertical">
<Alert
message={
@@ -106,7 +106,7 @@ export default function SandyDesignSystem() {
<Input placeholder="Input" />
</Space>
</Card>
<Card title="Theme variables">
<Card title="Theme variables" bordered={false}>
<Alert
message={
<>
@@ -118,7 +118,7 @@ export default function SandyDesignSystem() {
/>
<pre>{JSON.stringify(theme, null, 2)}</pre>
</Card>
<Card title="Layout components">
<Card title="Layout components" bordered={false}>
<DesignComponentDemos />
</Card>
</Layout.Vertical>
@@ -146,7 +146,7 @@ function ColorPreview({name}: {name: keyof typeof theme}) {
);
}
const resetLists = css`
const reset = css`
ol,
ul {
list-style: revert;
@@ -155,4 +155,7 @@ const resetLists = css`
.ant-alert {
margin-bottom: ${theme.space.huge}px;
}
.ant-card {
background: transparent;
}
`;

View File

@@ -0,0 +1,15 @@
/**
* 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 SandyDesignSystem from './SandyDesignSystem';
export function StyleGuide() {
return <SandyDesignSystem />;
}

View File

@@ -26,8 +26,8 @@ export const theme = {
dividerColor: 'var(--flipper-divider-color)',
borderRadius: 'var(--flipper-border-radius)',
containerBorderRadius: 8,
paddingSmall: 6, // vertical padding on inline elements like buttons
paddingLarge: 12, // horizontal ,,,
inlinePaddingV: 6, // vertical padding on inline elements like buttons
inlinePaddingH: 12, // horizontal ,,,
space: {
// from Space component in Ant
tiny: 4,
@@ -51,3 +51,35 @@ export function useIsDarkMode(): boolean {
(state) => state.settingsState.enableSandy && state.settingsState.darkMode,
);
}
export type Spacing = keyof typeof theme['space'] | number | undefined | true;
export type PaddingProps = {
padv?: Spacing;
padh?: Spacing;
pad?: Spacing;
};
export function normalizePadding({
padv,
padh,
pad,
}: PaddingProps): string | undefined {
if (padv === undefined && padh === undefined && pad === undefined) {
return undefined;
}
return `${normalizeSpace(
padv ?? pad ?? 0,
theme.inlinePaddingV,
)}px ${normalizeSpace(padh ?? pad ?? 0, theme.inlinePaddingH)}px`;
}
export function normalizeSpace(spacing: Spacing, defaultSpace: number): number {
return spacing === true
? defaultSpace
: spacing === undefined
? 0
: typeof spacing === 'string'
? theme.space[spacing]
: spacing;
}

View File

@@ -9,7 +9,13 @@
import React, {CSSProperties} from 'react';
import styled from '@emotion/styled';
import {theme} from '../../sandy-chrome/theme';
import {
normalizePadding,
normalizeSpace,
PaddingProps,
Spacing,
theme,
} from '../../sandy-chrome/theme';
import {useIsSandy} from '../../sandy-chrome/SandyContext';
import {renderLayout} from './LegacyLayout';
@@ -17,7 +23,6 @@ type ContainerProps = {
children?: React.ReactNode;
className?: string;
style?: React.CSSProperties;
padding?: CSSProperties['padding'];
borderBottom?: boolean;
borderTop?: boolean;
borderRight?: boolean;
@@ -25,7 +30,9 @@ type ContainerProps = {
bordered?: boolean;
rounded?: boolean;
padded?: boolean;
};
width?: number;
height?: number;
} & PaddingProps;
const Container = styled.div<ContainerProps>(
({
@@ -34,13 +41,16 @@ const Container = styled.div<ContainerProps>(
borderLeft,
borderRight,
borderTop,
padding,
rounded,
padded,
width,
height,
...rest
}) => ({
width,
height,
display: 'flex',
flexDirection: 'column',
padding: padded ? theme.space.small : padding,
padding: normalizePadding(rest),
borderRadius: rounded ? theme.containerBorderRadius : undefined,
flex: 1,
borderStyle: 'solid',
@@ -79,7 +89,7 @@ type DistributionProps = ContainerProps & {
/**
* Gab between individual items
*/
gap?: CSSProperties['gap'];
gap?: Spacing;
/**
* If set, items will be aligned in the center, if false (the default) items will be stretched.
*/
@@ -89,14 +99,14 @@ type DistributionProps = ContainerProps & {
const Horizontal = styled(Container)<DistributionProps>(({gap, center}) => ({
display: 'flex',
flexDirection: 'row',
gap,
gap: normalizeSpace(gap, theme.space.small),
alignItems: center ? 'center' : 'stretch',
}));
const Vertical = styled(Container)<DistributionProps>(({gap, center}) => ({
display: 'flex',
flexDirection: 'column',
gap,
gap: normalizeSpace(gap, theme.space.small),
alignItems: center ? 'center' : 'stretch',
}));