Use HorizontalGutter component, simplify Flex

This commit is contained in:
Chi Vinh Le
2018-08-24 19:11:56 +02:00
parent 10df1de98e
commit 3dc3e1435a
28 changed files with 286 additions and 148 deletions
@@ -13,7 +13,7 @@ import Flex from '../Flex'
## Regular Button
<Playground>
<Flex itemGutter>
<Flex itemGutter wrap>
<Button>Push Me</Button>
<Button size="small">Push Me</Button>
<Button size="large">Push Me</Button>
@@ -29,7 +29,7 @@ import Flex from '../Flex'
## Filled Button
<Playground>
<Flex itemGutter>
<Flex itemGutter wrap>
<Button variant="filled">Push Me</Button>
<Button variant="filled" size="small">Push Me</Button>
<Button variant="filled" size="large">Push Me</Button>
@@ -45,7 +45,7 @@ import Flex from '../Flex'
## Outlined Button
<Playground>
<Flex itemGutter>
<Flex itemGutter wrap>
<Button variant="outlined">Push Me</Button>
<Button variant="outlined" size="small">Push Me</Button>
<Button variant="outlined" size="large">Push Me</Button>
@@ -61,7 +61,7 @@ import Flex from '../Flex'
## Ghost Button
<Playground>
<Flex itemGutter>
<Flex itemGutter wrap>
<Button variant="ghost">Push Me</Button>
<Button variant="ghost" size="small">Push Me</Button>
<Button variant="ghost" size="large">Push Me</Button>
@@ -5,19 +5,19 @@ menu: UI Kit
import { Playground, PropsTable } from 'docz'
import CallOut from './CallOut'
import Flex from '../Flex'
import HorizontalGutter from '../HorizontalGutter'
# CallOut
## Basic Use
<Playground>
<Flex itemGutter direction="column">
<HorizontalGutter>
<CallOut>This is a component for a callout. Any text that you are wanting to draw attention to such as community guidelines, announcements, etc. can be placed in something like a callout box. The color of the callout box can be customized according your own needs.</CallOut>
<CallOut color="primary">This is a component for a callout. Any text that you are wanting to draw attention to such as community guidelines, announcements, etc. can be placed in something like a callout box. The color of the callout box can be customized according your own needs.</CallOut>
<CallOut color="error">This is a component for a callout. Any text that you are wanting to draw attention to such as community guidelines, announcements, etc. can be placed in something like a callout box. The color of the callout box can be customized according your own needs.</CallOut>
<CallOut color="error">The email address or password you entered is incorrect. Try again</CallOut>
<CallOut color="error" fullWidth>The email address or password you entered is incorrect. Try again</CallOut>
</Flex>
</HorizontalGutter>
</Playground>
+4 -2
View File
@@ -1,10 +1,12 @@
.root {
width: 100%;
}
.flex {
display: flex;
width: 100%;
}
.inline {
width: auto;
}
.halfItemGutter {
+29 -8
View File
@@ -28,6 +28,7 @@ interface InnerProps {
itemGutter?: boolean | "half" | "double";
className?: string;
wrap?: boolean | "reverse";
inline?: boolean;
/** Internal: Forwarded Ref */
forwardRef?: Ref<HTMLDivElement>;
@@ -44,6 +45,7 @@ const Flex: StatelessComponent<InnerProps> = props => {
wrap,
forwardRef,
children,
inline,
...rest
} = props;
@@ -77,21 +79,40 @@ const Flex: StatelessComponent<InnerProps> = props => {
classObject[(classes as any)[`direction${pascalCase(direction)}`]] = true;
}
const rootClassNames: string = cn(classes.root, className);
const rootClassNames: string = cn(classes.root, className, {
[classes.inline]: inline === true,
});
const flexClassNames: string = cn(classes.flex, classObject);
// The first div is required to support nested `Flex` components with itemGutters.
// text nodes can't be modified with css, so replace them with spans.
// Readd spaces at the beginning or end of text nodes because
// flex removes it.
const content = React.Children.map(children, child => {
if (typeof child === "string") {
return <span>{child.replace(/^ +| +$/g, "\xa0")}</span>;
}
return child;
});
if (wrap && itemGutter) {
// The first div is required to support nested `Flex` components with itemGutters.
return (
<div ref={forwardRef} className={rootClassNames} {...rest}>
<div className={flexClassNames}>{content}</div>
</div>
);
}
return (
<div ref={forwardRef} className={rootClassNames} {...rest}>
<div className={flexClassNames}>{children}</div>
<div
ref={forwardRef}
className={cn(rootClassNames, flexClassNames)}
{...rest}
>
{content}
</div>
);
};
Flex.defaultProps = {
wrap: true,
};
const enhanced = withForwardRef(withStyles(styles)(Flex));
export default enhanced;
export type FlexProps = PropTypesOf<typeof enhanced>;
@@ -1,10 +1,10 @@
import cn from "classnames";
import React, { HTMLAttributes, ReactNode } from "react";
import React, { ReactNode } from "react";
import { StatelessComponent } from "react";
import { withStyles } from "talk-ui/hocs";
import Flex from "../Flex";
import HorizontalGutter from "../HorizontalGutter";
import * as styles from "./FormField.css";
interface InnerProps {
@@ -18,14 +18,13 @@ const FormField: StatelessComponent<InnerProps> = props => {
const { classes, className, children, ...rest } = props;
return (
<Flex
direction="column"
<HorizontalGutter
className={cn(classes.root, className)}
itemGutter="half"
size="half"
{...rest}
>
{children}
</Flex>
</HorizontalGutter>
);
};
@@ -0,0 +1,27 @@
.root {
}
.half {
& > * {
margin: 0 0 calc(0.5 * var(--spacing-unit)) 0 !important;
}
& > *:last-child {
margin: 0 !important;
}
}
.full {
& > * {
margin: 0 0 var(--spacing-unit) 0 !important;
}
& > *:last-child {
margin: 0 !important;
}
}
.double {
& > * {
margin: 0 0 calc(2 * var(--spacing-unit)) 0 !important;
}
& > *:last-child {
margin: 0 !important;
}
}
@@ -0,0 +1,42 @@
---
name: HorizontalGutter
menu: UI Kit
---
import { Playground } from "docz"
import HorizontalGutter from "./HorizontalGutter"
import Button from "../Button"
# Spinner
## Usage
### Full gutter
<Playground>
<HorizontalGutter>
<div style={{backgroundColor: "grey", height: "30px"}} />
<div style={{backgroundColor: "grey", height: "30px"}} />
<div style={{backgroundColor: "grey", height: "30px"}} />
</HorizontalGutter>
</Playground>
### Half gutter
<Playground>
<HorizontalGutter size="half">
<div style={{backgroundColor: "grey", height: "30px"}} />
<div style={{backgroundColor: "grey", height: "30px"}} />
<div style={{backgroundColor: "grey", height: "30px"}} />
</HorizontalGutter>
</Playground>
### Double gutter
<Playground>
<HorizontalGutter size="double">
<div style={{backgroundColor: "grey", height: "30px"}} />
<div style={{backgroundColor: "grey", height: "30px"}} />
<div style={{backgroundColor: "grey", height: "30px"}} />
</HorizontalGutter>
</Playground>
@@ -0,0 +1,37 @@
import cn from "classnames";
import React, { HTMLAttributes, Ref, StatelessComponent } from "react";
import { withForwardRef, withStyles } from "talk-ui/hocs";
import { PropTypesOf } from "talk-ui/types";
import * as styles from "./HorizontalGutter.css";
interface InnerProps extends HTMLAttributes<HTMLSpanElement> {
/**
* This prop can be used to add custom classnames.
* It is handled by the `withStyles `HOC.
*/
classes: typeof styles;
size?: "half" | "full" | "double";
/** The name of the HorizontalGutter to render */
children?: React.ReactNode;
/** Internal: Forwarded Ref */
forwardRef?: Ref<HTMLDivElement>;
}
const HorizontalGutter: StatelessComponent<InnerProps> = props => {
const { classes, className, size, forwardRef, ...rest } = props;
const rootClassName = cn(classes.root, className, classes[size!]);
return <div className={rootClassName} {...rest} ref={forwardRef} />;
};
HorizontalGutter.defaultProps = {
size: "full",
};
const enhanced = withForwardRef(withStyles(styles)(HorizontalGutter));
export type HorizontalGutterProps = PropTypesOf<typeof enhanced>;
export default enhanced;
@@ -0,0 +1 @@
export { default, HorizontalGutterProps } from "./HorizontalGutter";
@@ -5,15 +5,15 @@ menu: UI Kit
import { Playground, PropsTable } from 'docz'
import InputLabel from './InputLabel.tsx'
import Flex from '../Flex'
import HorizontalGutter from '../HorizontalGutter'
# InputLabel
## Basic Use
<Playground>
<Flex itemGutter direction="column">
<HorizontalGutter>
<InputLabel>Well... Hello there.</InputLabel>
</Flex>
</HorizontalGutter>
</Playground>
@@ -5,16 +5,16 @@ menu: UI Kit
import { Playground, PropsTable } from 'docz'
import TextField from './TextField.tsx'
import Flex from '../Flex'
import HorizontalGutter from '../HorizontalGutter'
# TextField
## Basic Use
<Playground>
<Flex itemGutter direction="column">
<HorizontalGutter>
<TextField placeholder="This is a placeholder" />
<TextField defaultValue="This is an input field" />
<TextField color="error" defaultValue="A TextField with an error" />
<TextField color="error" defaultValue="A TextField with an error" fullWidth/>
</Flex>
</HorizontalGutter>
</Playground>
@@ -6,7 +6,7 @@ menu: UI Kit
import { Playground } from 'docz'
import ToggleShow from './ToggleShow'
import Button from '../Button'
import Flex from '../Flex'
import HorizontalGutter from '../HorizontalGutter'
# ToggleShow
A render props component to manage visible state.
@@ -15,12 +15,12 @@ A render props component to manage visible state.
<Playground>
<ToggleShow>
{({ toggleShow, show }) => (
<Flex itemGutter direction="column">
<HorizontalGutter>
{show && <div>Hello World!</div>}
<Button onClick={toggleShow} variant="filled" color="primary">
Toggle Show
</Button>
</Flex>
</HorizontalGutter>
)}
</ToggleShow>
</Playground>
@@ -5,13 +5,13 @@ menu: UI Kit
import { Playground } from 'docz'
import Typography from './Typography'
import Flex from '../Flex'
import HorizontalGutter from '../HorizontalGutter'
# Typography
## Basic Use
<Playground>
<Flex itemGutter direction="column">
<HorizontalGutter>
<Typography variant="heading1">Heading1</Typography>
<Typography variant="heading2">Heading2</Typography>
<Typography variant="heading3">Heading3</Typography>
@@ -19,28 +19,28 @@ import Flex from '../Flex'
<Typography variant="bodyCopy">BodyCopy</Typography>
<Typography variant="bodyCopyBold">bodyCopyBold</Typography>
<Typography variant="timestamp">timestamp</Typography>
</Flex>
</HorizontalGutter>
</Playground>
## Using different colors
<Playground>
<Flex itemGutter direction="column">
<HorizontalGutter>
<Typography color="textPrimary">textPrimary</Typography>
<Typography color="textSecondary">textSecondary</Typography>
<Typography color="success">success</Typography>
<Typography color="error">error</Typography>
</Flex>
</HorizontalGutter>
</Playground>
## Set align
<Playground>
<Flex itemGutter direction="column" alignItems="stretch" style={{width: "200px"}}>
<HorizontalGutter style={{width: "200px"}}>
<Typography align="left">left</Typography>
<Typography align="center">center</Typography>
<Typography align="right">right</Typography>
<Typography align="justify"> No hay nadie que ame el dolor mismo, que lo busque, lo encuentre y lo
quiera, simplemente porque es el dolor.</Typography>
</Flex>
</HorizontalGutter>
</Playground>
## Cut off long text
@@ -29,7 +29,7 @@ interface InnerProps extends HTMLAttributes<any> {
/**
* The content of the component.
*/
children: ReactNode;
children?: ReactNode;
/**
* Override or extend the styles applied to the component.
*/
@@ -49,11 +49,11 @@ interface InnerProps extends HTMLAttributes<any> {
| "error"
| "success";
/**
* The component used for the root node.
* Either a string to use a DOM element or a component.
* The container used for the root node.
* Either a string to use a DOM element, a component, or an element.
* By default, it maps the variant to a good default headline component.
*/
component?: React.ComponentType<any> | string;
container?: React.ReactElement<any> | React.ComponentType<any> | string;
/**
* If `true`, the text will have a bottom margin.
*/
@@ -87,7 +87,7 @@ const Typography: StatelessComponent<InnerProps> = props => {
classes,
className,
color,
component,
container,
gutterBottom,
headlineMapping,
noWrap,
@@ -117,10 +117,20 @@ const Typography: StatelessComponent<InnerProps> = props => {
className
);
const Component =
component || (paragraph ? "p" : headlineMapping![variant!]) || "span";
const Container =
container || (paragraph ? "p" : headlineMapping![variant!]) || "span";
return <Component ref={forwardRef} className={rootClassName} {...rest} />;
const innerProps = {
ref: forwardRef,
className: rootClassName,
...rest,
};
if (React.isValidElement<any>(Container)) {
return React.cloneElement(Container, innerProps);
} else {
return <Container {...innerProps} />;
}
};
Typography.defaultProps = {
@@ -5,16 +5,16 @@ menu: UI Kit
import { Playground } from 'docz'
import ValidationMessage from './ValidationMessage.tsx'
import Flex from '../Flex'
import HorizontalGutter from '../HorizontalGutter'
# ValidationMessage
## Basic Use
<Playground>
<Flex itemGutter direction="column">
<HorizontalGutter>
<ValidationMessage>Invalid characters. Try again</ValidationMessage>
<ValidationMessage fullWidth>Account with this email address already exists. Try another email. </ValidationMessage>
</Flex>
</HorizontalGutter>
</Playground>
@@ -1,7 +1,8 @@
import cn from "classnames";
import React from "react";
import { ReactNode, StatelessComponent } from "react";
import React, { ReactNode, StatelessComponent } from "react";
import { withStyles } from "talk-ui/hocs";
import Icon from "../Icon";
import * as styles from "./ValidationMessage.css";
+1
View File
@@ -17,3 +17,4 @@ export { default as Popup } from "./Popup";
export { default as FormField } from "./FormField";
export { default as InputDescription } from "./InputDescription";
export { default as Spinner } from "./Spinner";
export { default as HorizontalGutter } from "./HorizontalGutter";