import React from 'react' import { Title, Flex, FlexItem } from 'playbook-ui' const FlexDefault = (props) => { return ( <> <Title size={4} text="Row" /> <br /> <div className="flex-doc-example"> <Flex orientation="row" > <FlexItem> {'1'} </FlexItem> <FlexItem> {'2'} </FlexItem> <FlexItem> {'3'} </FlexItem> <FlexItem> {'4'} </FlexItem> </Flex> </div> <br /> <Title size={4} text="Column" /> <br /> <div className="flex-doc-example"> <Flex align="start" orientation="column" > <FlexItem> {'1'} </FlexItem> <FlexItem> {'2'} </FlexItem> <FlexItem> {'3'} </FlexItem> <FlexItem> {'4'} </FlexItem> </Flex> </div> </> ) } export default FlexDefault
inline
| Type: Boolean
By default this prop is false
which sets the flex container to take up the full width of its parent container. When the prop is set to true
the flex container sets its width to be the same size as the containing items.
import React from 'react' import { Flex, FlexItem, Title } from 'playbook-ui' const FlexInline = (props) => { return ( <> <div className="flex-doc-example"> <Title size={4} text="Row" /> <br /> <Flex className="bg_light" inline > <FlexItem> {'1'} </FlexItem> <FlexItem> {'2'} </FlexItem> <FlexItem> {'3'} </FlexItem> <FlexItem> {'4'} </FlexItem> </Flex> <br /> <Title size={4} text="Column" /> <br /> <Flex className="bg_light" inline orientation="column" > <FlexItem> {'1'} </FlexItem> <FlexItem> {'2'} </FlexItem> <FlexItem> {'3'} </FlexItem> <FlexItem> {'4'} </FlexItem> </Flex> </div> </> ) } export default FlexInline
reverse
| Type: Boolean
When set to true
this prop will reverse the order of items in the flex container.
import React from 'react' import { Flex, FlexItem, Title } from 'playbook-ui' const FlexReverse = (props) => { return ( <> <div className="flex-doc-example"> <Title size={4} text="Row" /> <br /> <Flex className="bg_light" justify="start" orientation="row" reverse > <FlexItem> {'1'} </FlexItem> <FlexItem> {'2'} </FlexItem> <FlexItem> {'3'} </FlexItem> <FlexItem> {'4'} </FlexItem> </Flex> <br /> <Title size={4} text="Column" /> <br /> <Flex align="start" className="bg_light" orientation="column" reverse > <FlexItem> {'1'} </FlexItem> <FlexItem> {'2'} </FlexItem> <FlexItem> {'3'} </FlexItem> <FlexItem> {'4'} </FlexItem> </Flex> </div> </> ) } export default FlexReverse
wrap
| Type: Boolean
When set to true
this prop will move the next item in flex container to a new line if there is no more room.
import React from 'react' import { Body, Flex, FlexItem, Title } from 'playbook-ui' const FlexWrap = (props) => { return ( <> <div className="flex-doc-example"> <Body text="Resize your browser" /> <Title size={4} text="Wrap" /> <br /> <Flex className="bg_light" wrap > <FlexItem fixedSize="300px"> {'1'} </FlexItem> <FlexItem fixedSize="300px"> {'2'} </FlexItem> <FlexItem fixedSize="300px"> {'3'} </FlexItem> <FlexItem fixedSize="300px"> {'4'} </FlexItem> <FlexItem fixedSize="300px"> {'5'} </FlexItem> <FlexItem fixedSize="300px"> {'6'} </FlexItem> <FlexItem fixedSize="300px"> {'7'} </FlexItem> <FlexItem fixedSize="300px"> {'8'} </FlexItem> <FlexItem fixedSize="300px"> {'9'} </FlexItem> <FlexItem fixedSize="300px"> {'10'} </FlexItem> </Flex> <br /> <Title size={4} text="No Wrap" /> <br /> <Flex className="bg_light"> <FlexItem fixedSize="300px"> {'1'} </FlexItem> <FlexItem fixedSize="300px"> {'2'} </FlexItem> <FlexItem fixedSize="300px"> {'3'} </FlexItem> <FlexItem fixedSize="300px"> {'4'} </FlexItem> <FlexItem fixedSize="300px"> {'5'} </FlexItem> <FlexItem fixedSize="300px"> {'6'} </FlexItem> <FlexItem fixedSize="300px"> {'7'} </FlexItem> <FlexItem fixedSize="300px"> {'8'} </FlexItem> <FlexItem fixedSize="300px"> {'9'} </FlexItem> <FlexItem fixedSize="300px"> {'10'} </FlexItem> </Flex> </div> </> ) } export default FlexWrap
import React from 'react' import { Flex, FlexItem, Title } from 'playbook-ui' const FlexSpacing = (props) => { return ( <> <div className="flex-doc-example"> <Title size={4} text="None" /> <br /> <Flex className="bg_light" justify="none" > <FlexItem> {'1'} </FlexItem> <FlexItem> {'2'} </FlexItem> <FlexItem> {'3'} </FlexItem> <FlexItem> {'4'} </FlexItem> </Flex> <br /> <Title size={4} text="Around" /> <br /> <Flex className="bg_light" justify="around" > <FlexItem> {'1'} </FlexItem> <FlexItem> {'2'} </FlexItem> <FlexItem> {'3'} </FlexItem> <FlexItem> {'4'} </FlexItem> </Flex> <br /> <Title size={4} text="Between" /> <br /> <Flex className="bg_light" justify="between" > <FlexItem> {'1'} </FlexItem> <FlexItem> {'2'} </FlexItem> <FlexItem> {'3'} </FlexItem> <FlexItem> {'4'} </FlexItem> </Flex> <br /> <Title size={4} text="Evenly" /> <br /> <Flex className="bg_light" justify="evenly" > <FlexItem> {'1'} </FlexItem> <FlexItem> {'2'} </FlexItem> <FlexItem> {'3'} </FlexItem> <FlexItem> {'4'} </FlexItem> </Flex> </div> </> ) } export default FlexSpacing
import React from 'react' import { Flex, FlexItem, Title } from 'playbook-ui' const FlexJustify = (props) => { return ( <> <Title size={4} text="Row" /> <br /> <div className="flex-doc-example"> <Flex justify="start" orientation="row" > <FlexItem> {'1'} </FlexItem> <FlexItem> {'2'} </FlexItem> <FlexItem> {'3'} </FlexItem> <FlexItem> {'4'} </FlexItem> </Flex> </div> <br /> <div className="flex-doc-example"> <Flex justify="center" orientation="row" > <FlexItem> {'1'} </FlexItem> <FlexItem> {'2'} </FlexItem> <FlexItem> {'3'} </FlexItem> <FlexItem> {'4'} </FlexItem> </Flex> </div> <br /> <div className="flex-doc-example"> <Flex justify="end" orientation="row" > <FlexItem> {'1'} </FlexItem> <FlexItem> {'2'} </FlexItem> <FlexItem> {'3'} </FlexItem> <FlexItem> {'4'} </FlexItem> </Flex> </div> <br /> <Title size={4} text="Column" /> <br /> <div className="flex-doc-example tall"> <Flex align="start" className="bg_light tall" justify="start" orientation="column" > <FlexItem> {'1'} </FlexItem> <FlexItem> {'2'} </FlexItem> <FlexItem> {'3'} </FlexItem> <FlexItem> {'4'} </FlexItem> </Flex> </div> <br /> <div className="flex-doc-example tall"> <Flex align="start" className="bg_light tall" justify="center" orientation="column" > <FlexItem> {'1'} </FlexItem> <FlexItem> {'2'} </FlexItem> <FlexItem> {'3'} </FlexItem> <FlexItem> {'4'} </FlexItem> </Flex> </div> <br /> <div className="flex-doc-example tall"> <Flex align="start" className="bg_light tall" justify="end" orientation="column" > <FlexItem> {'1'} </FlexItem> <FlexItem> {'2'} </FlexItem> <FlexItem> {'3'} </FlexItem> <FlexItem> {'4'} </FlexItem> </Flex> </div> </> ) } export default FlexJustify
import React from 'react' import { Flex, FlexItem, Title } from 'playbook-ui' const FlexAlign = (props) => { return ( <> <Title size={4} text="row" /> <br /> <div className="flex-doc-example "> <Flex align="start" > <FlexItem> {'1'} </FlexItem> <FlexItem> {'2'} </FlexItem> <FlexItem padding="xl"> {'3'} </FlexItem> <FlexItem padding="md"> {'4'} </FlexItem> </Flex> </div> <br /> <div className="flex-doc-example "> <Flex align="center" > <FlexItem> {'1'} </FlexItem> <FlexItem> {'2'} </FlexItem> <FlexItem padding="xl"> {'3'} </FlexItem> <FlexItem padding="md"> {'4'} </FlexItem> </Flex> </div> <br /> <div className="flex-doc-example "> <Flex align="end" > <FlexItem> {'1'} </FlexItem> <FlexItem> {'2'} </FlexItem> <FlexItem padding="xl"> {'3'} </FlexItem> <FlexItem padding="md"> {'4'} </FlexItem> </Flex> </div> <br /> <div className="flex-doc-example "> <Flex align="stretch" orientation="row" > <FlexItem> {'1'} </FlexItem> <FlexItem> {'2'} </FlexItem> <FlexItem padding="xl"> {'3'} </FlexItem> <FlexItem padding="md"> {'4'} </FlexItem> </Flex> </div> <br /> <Title size={4} text="Column" /> <br /> <div className="flex-doc-example "> <Flex align="start" orientation="column" > <FlexItem> {'1'} </FlexItem> <FlexItem> {'2'} </FlexItem> <FlexItem> {'3'} </FlexItem> <FlexItem> {'4'} </FlexItem> </Flex> </div> <br /> <div className="flex-doc-example "> <Flex align="center" orientation="column" > <FlexItem> {'1'} </FlexItem> <FlexItem> {'2'} </FlexItem> <FlexItem> {'3'} </FlexItem> <FlexItem> {'4'} </FlexItem> </Flex> </div> <br /> <div className="flex-doc-example "> <Flex align="end" orientation="column" > <FlexItem> {'1'} </FlexItem> <FlexItem> {'2'} </FlexItem> <FlexItem> {'3'} </FlexItem> <FlexItem> {'4'} </FlexItem> </Flex> </div> <br /> <div className="flex-doc-example "> <Flex align="stretch" orientation="column" > <FlexItem> {'1'} </FlexItem> <FlexItem> {'2'} </FlexItem> <FlexItem> {'3'} </FlexItem> <FlexItem> {'4'} </FlexItem> </Flex> </div> </> ) } export default FlexAlign
gap
| row_gap
| rowGap
| column_gap
| columnGap
| Type: String | Values: xxs | xs | sm | md | lg | xl | none
Setting the gap prop sets the row_gap || rowGap and the column_gap || columnGap props to the same size and creates equal space within a flex container.
Setting the row_gap || rowGap prop creates space between rows in a flex container.
Setting the column_gap || columnGap prop creates space between columns in a flex container.
import React from 'react' import { Flex, FlexItem } from 'playbook-ui' const FlexGap = (props) => { const count = () => { const array = [] for (let i = 0; i < 40; i++) { array.push(i) } return array } return ( <> <div className="flex-doc-example"> <Flex gap="xxs" wrap > {count().map((v, key) => ( <FlexItem key={key}> {v} </FlexItem> ))} </Flex> </div> <br /> <div className="flex-doc-example"> <Flex columnGap="lg" > <FlexItem> {'1'} </FlexItem> <FlexItem> {'2'} </FlexItem> <FlexItem> {'3'} </FlexItem> <FlexItem> {'4'} </FlexItem> </Flex> </div> <br /> <div className="flex-doc-example"> <Flex orientation="column" rowGap="xl" > <FlexItem> {'1'} </FlexItem> <FlexItem> {'2'} </FlexItem> <FlexItem> {'3'} </FlexItem> <FlexItem> {'4'} </FlexItem> </Flex> </div> </> ) } export default FlexGap
display_flex
| Type: Booleanflex
| Type: String | Values: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12fixed_size
| Type: String | Values: Any CSS px or % valuegrow
| Type: Booleanshrink
| Type: Booleanorder
| Type: String | Values: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | first
Flex is a short hand to set the flex item to take up (x) amount of available space
Setting Flex to 1 is equal to setting the grow & shrink prop to true
Setting Flex to 0 is equal to setting the grow & shrink prop to false
If grow & shrink are true, grow will take precedence an the flex item will take up as much space as possible, then if other elements are added shrink would allow other items to squish inside the flex container
display_flex will either be true or false. If true, then the class will be applied to the kit
import React from 'react' import { Flex, FlexItem, Title } from 'playbook-ui' const FlexItemExample = (props) => { return ( <> <Title size={4} text="Display Flex" /> <br /> <div className="flex-doc-example"> <FlexItem displayFlex gap="xs" > <FlexItem> {'We'} </FlexItem> <FlexItem> {'Are'} </FlexItem> <FlexItem> {'Being'} </FlexItem> <FlexItem> {'Flexed'} </FlexItem> </FlexItem> </div> <br /> <Title size={4} text="Grow" /> <br /> <div className="flex-doc-example"> <Flex gap="xs" > <FlexItem grow> {'I\'m growing'} </FlexItem> <FlexItem> {'2'} </FlexItem> <FlexItem> {'3'} </FlexItem> <FlexItem> {'4'} </FlexItem> </Flex> </div> <br /> <Title size={4} text="Shrink" /> <br /> <div className="flex-doc-example"> <Flex gap="xs" > <FlexItem> {'I\'m shrinking'} </FlexItem> <FlexItem flex={1}> {'2'} </FlexItem> <FlexItem flex={1}> {'3'} </FlexItem> <FlexItem flex={1}> {'4'} </FlexItem> </Flex> </div> <br /> <Title size={4} text="Fixed Size" /> <br /> <div className="flex-doc-example"> <Flex gap="xs" > <FlexItem fixedSize="250px"> {'I\'m 250px'} </FlexItem> <FlexItem flex={1}> {'2'} </FlexItem> <FlexItem flex={1}> {'3'} </FlexItem> <FlexItem flex={1}> {'4'} </FlexItem> </Flex> </div> <br /> <Title size={4} text="Flex" /> <br /> <div className="flex-doc-example"> <Flex gap="xs" > <FlexItem flex={1}> {'1'} </FlexItem> <FlexItem flex={3}> {'2'} </FlexItem> <FlexItem flex={1}> {'3'} </FlexItem> <FlexItem flex={2}> {'4'} </FlexItem> </Flex> </div> <br /> <Title size={4} text="Order" /> <br /> <div className="flex-doc-example"> <Flex gap="xs" > <FlexItem order={4}> {'1'} </FlexItem> <FlexItem order={2}> {'2'} </FlexItem> <FlexItem order={1}> {'3'} </FlexItem> <FlexItem order={3}> {'4'} </FlexItem> </Flex> </div> </> ) } export default FlexItemExample
align_self
| Type: String | Values: start | end | center | stretch
Align-self aligns the Flex Item on the cross axis. This prop may also be applied to the Flex kit and will act the same way.
import React from 'react' import { Flex, FlexItem, Title } from 'playbook-ui' const FlexItemAlignSelf = (props) => { return ( <> <Title size={4} text="Row" /> <br /> <div className="flex-doc-example "> <Flex > <FlexItem alignSelf="start"> {'1'} </FlexItem> <FlexItem padding="md"> {'2'} </FlexItem> <FlexItem padding="md"> {'3'} </FlexItem> <FlexItem padding="md"> {'4'} </FlexItem> </Flex> </div> <br /> <div className="flex-doc-example "> <Flex > <FlexItem alignSelf="end"> {'1'} </FlexItem> <FlexItem padding="md"> {'2'} </FlexItem> <FlexItem padding="md"> {'3'} </FlexItem> <FlexItem padding="md"> {'4'} </FlexItem> </Flex> </div> <br /> <div className="flex-doc-example "> <Flex > <FlexItem alignSelf="center"> {'1'} </FlexItem> <FlexItem padding="md"> {'2'} </FlexItem> <FlexItem padding="md"> {'3'} </FlexItem> <FlexItem padding="md"> {'4'} </FlexItem> </Flex> </div> <br /> <div className="flex-doc-example "> <Flex > <FlexItem alignSelf="stretch"> {'1'} </FlexItem> <FlexItem padding="md"> {'2'} </FlexItem> <FlexItem padding="md"> {'3'} </FlexItem> <FlexItem padding="md"> {'4'} </FlexItem> </Flex> </div> <br /> <br /> <Title size={4} text="Column" /> <br /> <div className="flex-doc-example "> <Flex orientation="column" > <FlexItem alignSelf="start" padding="sm" > {'1'} </FlexItem> <FlexItem padding="sm"> {'2'} </FlexItem> <FlexItem padding="sm"> {'3'} </FlexItem> <FlexItem padding="sm"> {'4'} </FlexItem> </Flex> </div> <br /> <div className="flex-doc-example "> <Flex orientation="column" > <FlexItem alignSelf="end" padding="sm" > {'1'} </FlexItem> <FlexItem padding="sm"> {'2'} </FlexItem> <FlexItem padding="sm"> {'3'} </FlexItem> <FlexItem padding="sm"> {'4'} </FlexItem> </Flex> </div> <br /> <div className="flex-doc-example "> <Flex orientation="column" > <FlexItem alignSelf="center" padding="sm" > {'1'} </FlexItem> <FlexItem padding="sm"> {'2'} </FlexItem> <FlexItem padding="sm"> {'3'} </FlexItem> <FlexItem padding="sm"> {'4'} </FlexItem> </Flex> </div> <br /> <div className="flex-doc-example "> <Flex orientation="column" > <FlexItem alignSelf="stretch" padding="sm" > {'1'} </FlexItem> <FlexItem padding="sm"> {'2'} </FlexItem> <FlexItem padding="sm"> {'3'} </FlexItem> <FlexItem padding="sm"> {'4'} </FlexItem> </Flex> </div> </> ) } export default FlexItemAlignSelf
import React from 'react' import { Layout, Body } from 'playbook-ui' const LayoutColor = (props) => { return ( <div> <Layout collapse="md" position="left" size="sm" > <Layout.Side> {'Light'} </Layout.Side> <Layout.Body> {'Body'} </Layout.Body> </Layout> <br /> <br /> <Layout collapse="md" position="left" size="sm" variant="dark" > <Layout.Side> <Body dark text="Dark" /> </Layout.Side> <Layout.Body> {'Body'} </Layout.Body> </Layout> <br /> <br /> <Layout collapse="md" position="left" size="sm" variant="gradient" > <Layout.Side> <Body dark text="Gradient" /> </Layout.Side> <Layout.Body> {'Body'} </Layout.Body> </Layout> </div> ) } export default LayoutColor
import React from 'react' import { Layout } from 'playbook-ui' const LayoutTransparent = (props) => { return ( <div> <Layout collapse="sm" position="left" size="xs" transparent > <Layout.Side> {'Side'} </Layout.Side> <Layout.Body> {'Body'} </Layout.Body> </Layout> </div> ) } export default LayoutTransparent
import React from 'react' import { Layout } from 'playbook-ui' const LayoutSizes = (props) => { return ( <div> <Layout collapse="xs" position="left" size="xs" > <Layout.Side> {'Side'} </Layout.Side> <Layout.Body> {'Body'} </Layout.Body> </Layout> <br /> <br /> <Layout collapse="xs" position="left" size="sm" > <Layout.Side> {'Side'} </Layout.Side> <Layout.Body> {'Body'} </Layout.Body> </Layout> <br /> <br /> <Layout collapse="xs" position="left" size="md" > <Layout.Side> {'Side'} </Layout.Side> <Layout.Body> {'Body'} </Layout.Body> </Layout> <br /> <br /> <Layout collapse="xs" position="left" size="lg" > <Layout.Side> {'Side'} </Layout.Side> <Layout.Body> {'Body'} </Layout.Body> </Layout> <br /> <br /> <Layout collapse="xs" position="left" size="xl" > <Layout.Side> {'Side'} </Layout.Side> <Layout.Body> {'Body'} </Layout.Body> </Layout> </div> ) } export default LayoutSizes
Layout can leverage the max-width property. Learn more in our visual guidelines.
import React from 'react' import { Layout, Card } from 'playbook-ui' const LayoutCollection = (props) => { return ( <div> <Layout layout="collection" > <Layout.Body> <Card>{'Card content'}</Card> <Card>{'Card content'}</Card> <Card>{'Card content'}</Card> <Card>{'Card content'}</Card> <Card>{'Card content'}</Card> <Card>{'Card content'}</Card> <Card>{'Card content'}</Card> <Card>{'Card content'}</Card> <Card>{'Card content'}</Card> <Card>{'Card content'}</Card> </Layout.Body> </Layout> </div> ) } export default LayoutCollection
The left element on Collection Detail can be used for things such as navigation or secondary content to the element on the right. The right content can be used the same way that you would use Collection. The element on the right should be the primary focus and can be used for repeating elements such as cards.
import React from 'react' import { Layout, Card, Nav, NavItem } from 'playbook-ui' const Cards = ({ n }) => { const cards = [] for (let i = 0; i < n; ++i) { cards.push(<Card key={i}>{'Card content'}</Card>) } return (cards) } const LayoutCollectionDetail = (props) => { return ( <div> <Layout layout="collection_detail" > <Card padding="none"> { <Nav link="#" marginTop="sm" orientation="vertical" title="Menu" > <NavItem link="#" text="Photos" /> <NavItem link="#" text="Music" /> <NavItem active link="#" text="Video" /> <NavItem link="#" text="Files" /> </Nav> } </Card> <Layout.Body> <Cards n={16} /> </Layout.Body> </Layout> </div> ) } export default LayoutCollectionDetail
import React from 'react' import { Avatar, Caption, Card, Flex, FlexItem, Icon, Layout, MultipleUsers, Timestamp, Title } from 'playbook-ui' const LayoutKanban = (props) => { return ( <div> <Layout layout="kanban"> <Layout.Body> <Caption>{'Queue'}</Caption> <Card padding="sm" shadow="deep" > <Flex orientation="row" spacing="between" > <FlexItem> <Title size="4">{'Design Homepage'}</Title> </FlexItem> <FlexItem> <Icon icon="ellipsis-h" /> </FlexItem> </Flex> <Flex orientation="row" spacing="between" vertical="bottom" > <FlexItem marginTop="xs"> <Avatar imageUrl="https://images.unsplash.com/photo-1494790108377-be9c29b29330?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=200&fit=max&s=707b9c33066bf8808c934c8ab394dff6" name="Michelle Smith" size="sm" /> </FlexItem> <FlexItem> <Flex orientation="row" vertical="center" > <Icon icon="clock" /> <Timestamp text="00:00:00 h" /> </Flex> </FlexItem> </Flex> </Card> <Card padding="sm" shadow="deep" > <Flex orientation="row" spacing="between" > <FlexItem> <Title size="4">{'Change Old App Icon'}</Title> </FlexItem> <FlexItem> <Icon icon="ellipsis-h" /> </FlexItem> </Flex> <Flex orientation="row" spacing="between" vertical="bottom" > <FlexItem marginTop="xs"> <Avatar imageUrl="https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=634&q=80" name="Roger Donahue" size="sm" /> </FlexItem> <FlexItem> <Flex orientation="row" vertical="center" > <Icon icon="clock" /> <Timestamp text="00:00:00 h" /> </Flex> </FlexItem> </Flex> </Card> </Layout.Body> <Layout.Body> <Caption>{'In Progress'}</Caption> <Card padding="sm" shadow="deep" > <Flex orientation="row" spacing="between" > <FlexItem> <Title size="4">{'Dashboard Updates'}</Title> </FlexItem> <FlexItem> <Icon icon="ellipsis-h" /> </FlexItem> </Flex> <Flex orientation="row" spacing="between" vertical="bottom" > <FlexItem marginTop="xs"> <Avatar imageUrl="https://images.unsplash.com/photo-1509868918748-a554ad25f858?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=200&fit=max&s=3159ec467959b2aada4b75d565c270aa" name="Michelle Smith" size="sm" /> </FlexItem> <FlexItem> <Flex orientation="row" vertical="center" > <Icon icon="clock" /> <Timestamp text="00:00:00 h" /> </Flex> </FlexItem> </Flex> </Card> <Card padding="sm" shadow="deep" > <Flex orientation="row" spacing="between" > <FlexItem> <Title size="4">{'Usability Testing'}</Title> </FlexItem> <FlexItem> <Icon icon="ellipsis-h" /> </FlexItem> </Flex> <Flex orientation="row" spacing="between" vertical="bottom" > <FlexItem marginTop="xs"> <MultipleUsers paddingLeft="xs" users={[ { name: 'Shawn Palmer', imageUrl: 'https://images.unsplash.com/photo-1506794778202-cad84cf45f1d?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=200&fit=max&s=74daec1914d1d105202bca8a310a6a71', }, { name: 'Andrew Murray Cooper Craig', imageUrl: 'https://images.unsplash.com/photo-1513732822839-24f03a92f633?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=200&fit=max&ixid=eyJhcHBfaWQiOjE3Nzg0fQ', }, ]} /> </FlexItem> <FlexItem> <Flex orientation="row" vertical="center" > <Icon icon="clock" /> <Timestamp text="00:00:00 h" /> </Flex> </FlexItem> </Flex> </Card> <Card padding="sm" shadow="deep" > <Flex orientation="row" spacing="between" > <FlexItem> <Title size="4">{'New Icons'}</Title> </FlexItem> <FlexItem> <Icon icon="ellipsis-h" /> </FlexItem> </Flex> <Flex orientation="row" spacing="between" vertical="bottom" > <FlexItem marginTop="xs"> <Avatar imageUrl="https://images.unsplash.com/photo-1502378735452-bc7d86632805?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=200&fit=max&s=aa3a807e1bbdfd4364d1f449eaa96d82" name="Roger Donahue" size="sm" /> </FlexItem> <FlexItem> <Flex orientation="row" vertical="center" > <Icon icon="clock" /> <Timestamp text="00:00:00 h" /> </Flex> </FlexItem> </Flex> </Card> </Layout.Body> <Layout.Body> <Caption>{'Validation'}</Caption> <Card padding="sm" shadow="deep" > <Flex orientation="row" spacing="between" > <FlexItem> <Title size="4">{'Build Full Page Example'}</Title> </FlexItem> <FlexItem> <Icon icon="ellipsis-h" /> </FlexItem> </Flex> <Flex orientation="row" spacing="between" vertical="bottom" > <FlexItem marginTop="xs"> <Avatar imageUrl="https://images.unsplash.com/photo-1494790108377-be9c29b29330?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=200&fit=max&s=707b9c33066bf8808c934c8ab394dff6" name="Michelle Smith" size="sm" /> </FlexItem> <FlexItem> <Flex orientation="row" vertical="center" > <Icon icon="clock" /> <Timestamp text="00:00:00 h" /> </Flex> </FlexItem> </Flex> </Card> <Card padding="sm" shadow="deep" > <Flex orientation="row" spacing="between" > <FlexItem> <Title size="4">{'Design System Documentation'}</Title> </FlexItem> <FlexItem> <Icon icon="ellipsis-h" /> </FlexItem> </Flex> <Flex orientation="row" spacing="between" vertical="bottom" > <FlexItem marginTop="xs"> <Avatar imageUrl="https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=634&q=80" name="Roger Donahue" size="sm" /> </FlexItem> <FlexItem> <Flex orientation="row" vertical="center" > <Icon icon="clock" /> <Timestamp text="00:00:00 h" /> </Flex> </FlexItem> </Flex> </Card> <Card padding="sm" shadow="deep" > <Flex orientation="row" spacing="between" > <FlexItem> <Title size="4">{'Prop Bug'}</Title> </FlexItem> <FlexItem> <Icon icon="ellipsis-h" /> </FlexItem> </Flex> <Flex orientation="row" spacing="between" vertical="bottom" > <FlexItem marginTop="xs"> <Avatar imageUrl="https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=634&q=80" name="Roger Donahue" size="sm" /> </FlexItem> <FlexItem> <Flex orientation="row" vertical="center" > <Icon icon="clock" /> <Timestamp text="00:00:00 h" /> </Flex> </FlexItem> </Flex> </Card> <Card padding="sm" shadow="deep" > <Flex orientation="row" spacing="between" > <FlexItem> <Title size="4">{'Discovery Session'}</Title> </FlexItem> <FlexItem> <Icon icon="ellipsis-h" /> </FlexItem> </Flex> <Flex orientation="row" spacing="between" vertical="bottom" > <FlexItem marginTop="xs"> <Avatar imageUrl="https://images.unsplash.com/photo-1494790108377-be9c29b29330?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=200&fit=max&s=707b9c33066bf8808c934c8ab394dff6" name="Michelle Smith" size="sm" /> </FlexItem> <FlexItem> <Flex orientation="row" vertical="center" > <Icon icon="clock" /> <Timestamp text="00:00:00 h" /> </Flex> </FlexItem> </Flex> </Card> <Card padding="sm" shadow="deep" > <Flex orientation="row" spacing="between" > <FlexItem> <Title size="4">{'Design Exploration'}</Title> </FlexItem> <FlexItem> <Icon icon="ellipsis-h" /> </FlexItem> </Flex> <Flex orientation="row" spacing="between" vertical="bottom" > <FlexItem marginTop="xs"> <Avatar imageUrl="https://images.unsplash.com/photo-1513732822839-24f03a92f633?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=200&fit=max&ixid=eyJhcHBfaWQiOjE3Nzg0fQ" name="Roger Donahue" size="sm" /> </FlexItem> <FlexItem> <Flex orientation="row" vertical="center" > <Icon icon="clock" /> <Timestamp text="00:00:00 h" /> </Flex> </FlexItem> </Flex> </Card> <Card padding="sm" shadow="deep" > <Flex orientation="row" spacing="between" > <FlexItem> <Title size="4">{'Fix Sketch Bugs'}</Title> </FlexItem> <FlexItem> <Icon icon="ellipsis-h" /> </FlexItem> </Flex> <Flex orientation="row" spacing="between" vertical="bottom" > <FlexItem marginTop="xs"> <Avatar imageUrl="https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=634&q=80" name="Roger Donahue" size="sm" /> </FlexItem> <FlexItem> <Flex orientation="row" vertical="center" > <Icon icon="clock" /> <Timestamp text="00:00:00 h" /> </Flex> </FlexItem> </Flex> </Card> <Card padding="sm" shadow="deep" > <Flex orientation="row" spacing="between" > <FlexItem> <Title size="4">{'Test Out Figma'}</Title> </FlexItem> <FlexItem> <Icon icon="ellipsis-h" /> </FlexItem> </Flex> <Flex orientation="row" spacing="between" vertical="bottom" > <FlexItem marginTop="xs"> <Avatar imageUrl="https://images.unsplash.com/photo-1494790108377-be9c29b29330?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=200&fit=max&s=707b9c33066bf8808c934c8ab394dff6" name="Michelle Smith" size="sm" /> </FlexItem> <FlexItem> <Flex orientation="row" vertical="center" > <Icon icon="clock" /> <Timestamp text="00:00:00 h" /> </Flex> </FlexItem> </Flex> </Card> <Card padding="sm" shadow="deep" > <Flex orientation="row" spacing="between" > <FlexItem> <Title size="4">{'Ship New Feature'}</Title> </FlexItem> <FlexItem> <Icon icon="ellipsis-h" /> </FlexItem> </Flex> <Flex orientation="row" spacing="between" vertical="bottom" > <FlexItem marginTop="xs"> <Avatar imageUrl="https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=634&q=80" name="Roger Donahue" size="sm" /> </FlexItem> <FlexItem> <Flex orientation="row" vertical="center" > <Icon icon="clock" /> <Timestamp text="00:00:00 h" /> </Flex> </FlexItem> </Flex> </Card> <Card padding="sm" shadow="deep" > <Flex orientation="row" spacing="between" > <FlexItem> <Title size="4">{'Meet with Client'}</Title> </FlexItem> <FlexItem> <Icon icon="ellipsis-h" /> </FlexItem> </Flex> <Flex orientation="row" spacing="between" vertical="bottom" > <FlexItem marginTop="xs"> <Avatar imageUrl="https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=634&q=80" name="Roger Donahue" size="sm" /> </FlexItem> <FlexItem> <Flex orientation="row" vertical="center" > <Icon icon="clock" /> <Timestamp text="00:00:00 h" /> </Flex> </FlexItem> </Flex> </Card> <Card padding="sm" shadow="deep" > <Flex orientation="row" spacing="between" > <FlexItem> <Title size="4">{'Re-engineer Old Modal'}</Title> </FlexItem> <FlexItem> <Icon icon="ellipsis-h" /> </FlexItem> </Flex> <Flex orientation="row" spacing="between" vertical="bottom" > <FlexItem marginTop="xs"> <Avatar imageUrl="https://images.unsplash.com/photo-1494790108377-be9c29b29330?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=200&fit=max&s=707b9c33066bf8808c934c8ab394dff6" name="Michelle Smith" size="sm" /> </FlexItem> <FlexItem> <Flex orientation="row" vertical="center" > <Icon icon="clock" /> <Timestamp text="00:00:00 h" /> </Flex> </FlexItem> </Flex> </Card> <Card padding="sm" shadow="deep" > <Flex orientation="row" spacing="between" > <FlexItem> <Title size="4">{'Setup Permissions'}</Title> </FlexItem> <FlexItem> <Icon icon="ellipsis-h" /> </FlexItem> </Flex> <Flex orientation="row" spacing="between" vertical="bottom" > <FlexItem marginTop="xs"> <Avatar imageUrl="https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=634&q=80" name="Roger Donahue" size="sm" /> </FlexItem> <FlexItem> <Flex orientation="row" vertical="center" > <Icon icon="clock" /> <Timestamp text="00:00:00 h" /> </Flex> </FlexItem> </Flex> </Card> <Card padding="sm" shadow="deep" > <Flex orientation="row" spacing="between" > <FlexItem> <Title size="4">{'Build Prototype'}</Title> </FlexItem> <FlexItem> <Icon icon="ellipsis-h" /> </FlexItem> </Flex> <Flex orientation="row" spacing="between" vertical="bottom" > <FlexItem marginTop="xs"> <Avatar imageUrl="https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=634&q=80" name="Roger Donahue" size="sm" /> </FlexItem> <FlexItem> <Flex orientation="row" vertical="center" > <Icon icon="clock" /> <Timestamp text="00:00:00 h" /> </Flex> </FlexItem> </Flex> </Card> <Card padding="sm" shadow="deep" > <Flex orientation="row" spacing="between" > <FlexItem> <Title size="4">{'Collaborate with Team'}</Title> </FlexItem> <FlexItem> <Icon icon="ellipsis-h" /> </FlexItem> </Flex> <Flex orientation="row" spacing="between" vertical="bottom" > <FlexItem marginTop="xs"> <Avatar imageUrl="https://images.unsplash.com/photo-1494790108377-be9c29b29330?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=200&fit=max&s=707b9c33066bf8808c934c8ab394dff6" name="Michelle Smith" size="sm" /> </FlexItem> <FlexItem> <Flex orientation="row" vertical="center" > <Icon icon="clock" /> <Timestamp text="00:00:00 h" /> </Flex> </FlexItem> </Flex> </Card> <Card padding="sm" shadow="deep" > <Flex orientation="row" spacing="between" > <FlexItem> <Title size="4">{'Interview Candidates'}</Title> </FlexItem> <FlexItem> <Icon icon="ellipsis-h" /> </FlexItem> </Flex> <Flex orientation="row" spacing="between" vertical="bottom" > <FlexItem marginTop="xs"> <Avatar imageUrl="https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=634&q=80" name="Roger Donahue" size="sm" /> </FlexItem> <FlexItem> <Flex orientation="row" vertical="center" > <Icon icon="clock" /> <Timestamp text="00:00:00 h" /> </Flex> </FlexItem> </Flex> </Card> <Card padding="sm" shadow="deep" > <Flex orientation="row" spacing="between" > <FlexItem> <Title size="4">{'Run Testing Suite'}</Title> </FlexItem> <FlexItem> <Icon icon="ellipsis-h" /> </FlexItem> </Flex> <Flex orientation="row" spacing="between" vertical="bottom" > <FlexItem marginTop="xs"> <Avatar imageUrl="https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=634&q=80" name="Roger Donahue" size="sm" /> </FlexItem> <FlexItem> <Flex orientation="row" vertical="center" > <Icon icon="clock" /> <Timestamp text="00:00:00 h" /> </Flex> </FlexItem> </Flex> </Card> <Card padding="sm" shadow="deep" > <Flex orientation="row" spacing="between" > <FlexItem> <Title size="4">{'Live Coding Session'}</Title> </FlexItem> <FlexItem> <Icon icon="ellipsis-h" /> </FlexItem> </Flex> <Flex orientation="row" spacing="between" vertical="bottom" > <FlexItem marginTop="xs"> <Avatar imageUrl="https://images.unsplash.com/photo-1494790108377-be9c29b29330?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=200&fit=max&s=707b9c33066bf8808c934c8ab394dff6" name="Michelle Smith" size="sm" /> </FlexItem> <FlexItem> <Flex orientation="row" vertical="center" > <Icon icon="clock" /> <Timestamp text="00:00:00 h" /> </Flex> </FlexItem> </Flex> </Card> <Card padding="sm" shadow="deep" > <Flex orientation="row" spacing="between" > <FlexItem> <Title size="4">{'All Hands Meeting'}</Title> </FlexItem> <FlexItem> <Icon icon="ellipsis-h" /> </FlexItem> </Flex> <Flex orientation="row" spacing="between" vertical="bottom" > <FlexItem marginTop="xs"> <Avatar imageUrl="https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=634&q=80" name="Roger Donahue" size="sm" /> </FlexItem> <FlexItem> <Flex orientation="row" vertical="center" > <Icon icon="clock" /> <Timestamp text="00:00:00 h" /> </Flex> </FlexItem> </Flex> </Card> <Card padding="sm" shadow="deep" > <Flex orientation="row" spacing="between" > <FlexItem> <Title size="4">{'Growth Engineering Meeting'}</Title> </FlexItem> <FlexItem> <Icon icon="ellipsis-h" /> </FlexItem> </Flex> <Flex orientation="row" spacing="between" vertical="bottom" > <FlexItem marginTop="xs"> <Avatar imageUrl="https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=634&q=80" name="Roger Donahue" size="sm" /> </FlexItem> <FlexItem> <Flex orientation="row" vertical="center" > <Icon icon="clock" /> <Timestamp text="00:00:00 h" /> </Flex> </FlexItem> </Flex> </Card> </Layout.Body> <Layout.Body> <Caption>{'Done'}</Caption> <Card padding="sm" shadow="deep" > <Flex orientation="row" spacing="between" > <FlexItem> <Title size="4">{'Re-rendering Bug'}</Title> </FlexItem> <FlexItem> <Icon icon="ellipsis-h" /> </FlexItem> </Flex> <Flex orientation="row" spacing="between" vertical="bottom" > <FlexItem marginTop="xs"> <Avatar imageUrl="https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=634&q=80" name="Roger Donahue" size="sm" /> </FlexItem> <FlexItem> <Flex orientation="row" vertical="center" > <Icon icon="clock" /> <Timestamp text="00:00:00 h" /> </Flex> </FlexItem> </Flex> </Card> <Card padding="sm" shadow="deep" > <Flex orientation="row" spacing="between" > <FlexItem> <Title size="4">{'Gather Resources'}</Title> </FlexItem> <FlexItem> <Icon icon="ellipsis-h" /> </FlexItem> </Flex> <Flex orientation="row" spacing="between" vertical="bottom" > <FlexItem marginTop="xs"> <Avatar imageUrl="https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=634&q=80" name="Roger Donahue" size="sm" /> </FlexItem> <FlexItem> <Flex orientation="row" vertical="center" > <Icon icon="clock" /> <Timestamp text="00:00:00 h" /> </Flex> </FlexItem> </Flex> </Card> </Layout.Body> <Layout.Body> <Caption>{'Another Column'}</Caption> <Card padding="sm" shadow="deep" > <Flex orientation="row" spacing="between" > <FlexItem> <Title size="4">{'All Hands Meeting'}</Title> </FlexItem> <FlexItem> <Icon icon="ellipsis-h" /> </FlexItem> </Flex> <Flex orientation="row" spacing="between" vertical="bottom" > <FlexItem marginTop="xs"> <Avatar imageUrl="https://images.unsplash.com/photo-1544817747-b11e3e3b6ac2?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=200&fit=max&ixid=eyJhcHBfaWQiOjE3Nzg0fQ" name="Roger Donahue" size="sm" /> </FlexItem> <FlexItem> <Flex orientation="row" vertical="center" > <Icon icon="clock" /> <Timestamp text="00:00:00 h" /> </Flex> </FlexItem> </Flex> </Card> <Card padding="sm" shadow="deep" > <Flex orientation="row" spacing="between" > <FlexItem> <Title size="4">{'Growth Engineering Meeting'}</Title> </FlexItem> <FlexItem> <Icon icon="ellipsis-h" /> </FlexItem> </Flex> <Flex orientation="row" spacing="between" vertical="bottom" > <FlexItem marginTop="xs"> <Avatar imageUrl="https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=634&q=80" name="Roger Donahue" size="sm" /> </FlexItem> <FlexItem> <Flex orientation="row" vertical="center" > <Icon icon="clock" /> <Timestamp text="00:00:00 h" /> </Flex> </FlexItem> </Flex> </Card> </Layout.Body> <Layout.Body> <Caption>{'Another Column'}</Caption> <Card padding="sm" shadow="deep" > <Flex orientation="row" spacing="between" > <FlexItem> <Title size="4">{'All Hands Meeting'}</Title> </FlexItem> <FlexItem> <Icon icon="ellipsis-h" /> </FlexItem> </Flex> <Flex orientation="row" spacing="between" vertical="bottom" > <FlexItem marginTop="xs"> <Avatar imageUrl="https://images.unsplash.com/photo-1463453091185-61582044d556?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=200&fit=max&s=73a9df4b7bd1b330db1e903e08575ec1" name="Roger Donahue" size="sm" /> </FlexItem> <FlexItem> <Flex orientation="row" vertical="center" > <Icon icon="clock" /> <Timestamp text="00:00:00 h" /> </Flex> </FlexItem> </Flex> </Card> <Card padding="sm" shadow="deep" > <Flex orientation="row" spacing="between" > <FlexItem> <Title size="4">{'Pairing'}</Title> </FlexItem> <FlexItem> <Icon icon="ellipsis-h" /> </FlexItem> </Flex> <Flex orientation="row" spacing="between" vertical="bottom" > <FlexItem marginTop="xs"> <Avatar imageUrl="https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=634&q=80" name="Roger Donahue" size="sm" /> </FlexItem> <FlexItem> <Flex orientation="row" vertical="center" > <Icon icon="clock" /> <Timestamp text="00:00:00 h" /> </Flex> </FlexItem> </Flex> </Card> </Layout.Body> <Layout.Body> <Caption>{'Another Column'}</Caption> <Card padding="sm" shadow="deep" > <Flex orientation="row" spacing="between" > <FlexItem> <Title size="4">{'Design Session'}</Title> </FlexItem> <FlexItem> <Icon icon="ellipsis-h" /> </FlexItem> </Flex> <Flex orientation="row" spacing="between" vertical="bottom" > <FlexItem marginTop="xs"> <Avatar imageUrl="https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=634&q=80" name="Roger Donahue" size="sm" /> </FlexItem> <FlexItem> <Flex orientation="row" vertical="center" > <Icon icon="clock" /> <Timestamp text="00:00:00 h" /> </Flex> </FlexItem> </Flex> </Card> <Card padding="sm" shadow="deep" > <Flex orientation="row" spacing="between" > <FlexItem> <Title size="4">{'UX Engineering Meeting'}</Title> </FlexItem> <FlexItem> <Icon icon="ellipsis-h" /> </FlexItem> </Flex> <Flex orientation="row" spacing="between" vertical="bottom" > <FlexItem marginTop="xs"> <Avatar imageUrl="https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=634&q=80" name="Roger Donahue" size="sm" /> </FlexItem> <FlexItem> <Flex orientation="row" vertical="center" > <Icon icon="clock" /> <Timestamp text="00:00:00 h" /> </Flex> </FlexItem> </Flex> </Card> </Layout.Body> </Layout> </div> ) } export default LayoutKanban
import React from 'react' import { Layout, Card } from 'playbook-ui' const LayoutContent = () => { return ( <div> <Layout layout="content"> <Layout.Header> <Card> {'Header'} </Card> </Layout.Header> <Layout.Side> <Card> {'Sidebar'} <br /> <br /> {'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec iaculis, risus a fringilla luctus, sapien eros sodales ex, quis molestie est nulla non turpis. Vestibulum aliquet at ipsum eget posuere. Morbi sed laoreet erat. Sed commodo posuere lectus, at porta nulla ornare a. Suspendisse quam est, sollicitudin ut enim sit amet, commodo placerat enim. Donec laoreet metus ac mauris pellentesque mattis.'} </Card> </Layout.Side> <Layout.Body> <Card> {'Body'} <br /> <br /> {'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec iaculis, risus a fringilla luctus, sapien eros sodales ex, quis molestie est nulla non turpis. Vestibulum aliquet at ipsum eget posuere. Morbi sed laoreet erat. Sed commodo posuere lectus, at porta nulla ornare a. Suspendisse quam est, sollicitudin ut enim sit amet, commodo placerat enim. Donec laoreet metus ac mauris pellentesque mattis. Pellentesque luctus vel mauris non aliquam. Mauris hendrerit mattis porttitor. Curabitur vehicula justo non ex consectetur commodo. Quisque posuere aliquet quam. Maecenas malesuada magna mauris, ac tempor metus euismod at.'} <br /> <br /> {'Cras ornare fermentum magna mollis efficitur. Sed vitae nulla vel purus ultrices mollis. Maecenas id nulla id libero faucibus feugiat quis sit amet turpis. In commodo pellentesque risus at fringilla. Integer non interdum leo, non commodo ante. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut mi augue, dignissim at orci vel, egestas aliquam mi. Proin finibus aliquet tempor. Integer cursus, ex quis gravida rhoncus, nisi elit viverra ipsum, non efficitur est ex ac tortor. Praesent vitae odio massa.'} </Card> </Layout.Body> <Layout.Footer> <Card> {'Footer'} </Card> </Layout.Footer> </Layout> </div> ) } export default LayoutContent
import React from 'react' import { Layout, Image } from 'playbook-ui' const LayoutMasonry = (props) => { return ( <Layout layout="masonry" > <Layout.Body> <Layout.Item> <Image url="https://images.unsplash.com/photo-1611932084285-4fc50bfb7102?ixid=MXwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHwxMnx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=60" /> </Layout.Item> <Layout.Item size="md"> <Image url="https://images.unsplash.com/photo-1611934529218-748707e1d066?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=2307&q=80" /> </Layout.Item> <Layout.Item> <Image url="https://images.unsplash.com/photo-1611927263897-c2f1156bc760?ixid=MXwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHwyMHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=60" /> </Layout.Item> <Layout.Item size="lg"> <Image url="https://images.unsplash.com/photo-1611927263897-c2f1156bc760?ixid=MXwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHwyMHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=60" /> </Layout.Item> <Layout.Item> <Image url="https://images.unsplash.com/photo-1606851685679-2a35cfdd62d6?ixid=MXwxMjA3fDF8MHxlZGl0b3JpYWwtZmVlZHwxMXx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=60" /> </Layout.Item> <Layout.Item size="md"> <Image url="https://images.unsplash.com/photo-1612092172331-d788286028d5?ixid=MXwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHw3Mnx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=60" /> </Layout.Item> <Layout.Item> <Image url="https://images.unsplash.com/photo-1612123912968-5f6e964e8ea5?ixid=MXwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHw0N3x8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=60" /> </Layout.Item> <Layout.Item size="md"> <Image url="https://images.unsplash.com/photo-1606851685679-2a35cfdd62d6?ixid=MXwxMjA3fDF8MHxlZGl0b3JpYWwtZmVlZHwxMXx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=60" /> </Layout.Item> <Layout.Item> <Image url="https://unsplash.it/500/400/?image=634" /> </Layout.Item> </Layout.Body> </Layout> ) } export default LayoutMasonry
Use <Layout.RoundLabel>
, <Layout.Round>
, <Layout.Game>
, and/or <Layout.Participant>
to make a bracket layout. Feel free to use custom components in place of the template components based on your needs.
On mobile devices, <Layout.RoundLabel>
will display (on desktop these components are hidden) and the bracket will be in one column.
Ensure that each <Layout.Game>
maintains a consistent height for the bracket lines to lay out properly.
import React from 'react' import { Layout, Caption, SectionSeparator } from 'playbook-ui' const teamData = { eagles: { avatar:"https://images.unsplash.com/photo-1628703117067-fb7c9c20946e?w=500&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8Mnx8ZWFnbGVzfGVufDB8fDB8fHww", name:"Eagles", rank:"#1 NFC East", territory:"PHI", }, packers: { avatar:"https://images.unsplash.com/photo-1486297678162-eb2a19b0a32d?q=80&w=500&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", name:"Packers", rank:"#3 NFC North", territory:"GB", }, vikings: { avatar:"https://images.unsplash.com/photo-1525540796810-55f9fbc5592f?w=500&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8MTV8fHZpa2luZ3xlbnwwfHwwfHx8MA%3D%3D", name:"Vikings", rank:"#2 NFC North", territory:"MIN", }, rams: { avatar:"https://images.unsplash.com/photo-1490739043913-239b6cdf4084?q=80&w=500&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", name:"Rams", rank:"#1 NFC West", territory:"LAR", }, lions: { avatar:"https://images.unsplash.com/photo-1614027164847-1b28cfe1df60?q=80&w=500&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", name:"Lions", rank:"#1 NFC North", territory:"DET", }, commanders: { avatar:"https://images.unsplash.com/photo-1501466044931-62695aada8e9?q=80&w=500&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", name:"Commanders", rank:"#2 NFC East", territory:"WAS", }, buccaneers: { avatar:"https://images.unsplash.com/photo-1584116843008-46d529f04145?q=80&w=500&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", name:"Buccaneers", rank:"#1 NFC South", territory:"TB", }, chiefs: { avatar:"https://plus.unsplash.com/premium_photo-1697729864667-57f5f29e946b?w=500&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8MXx8a2Fuc2FzJTIwY2l0eXxlbnwwfHwwfHx8MA%3D%3D", name:"Chiefs", rank:"#1 AFC West", territory:"KC", }, chargers: { avatar:"https://images.unsplash.com/photo-1529310399831-ed472b81d589?q=80&w=500&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", name:"Chargers", rank:"#2 AFC West", territory:"LAC", }, texans: { avatar:"https://images.unsplash.com/photo-1545345540-ea5d968030af?q=80&w=500&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", name:"Texans", rank:"#1 AFC South", territory:"HOU", }, broncos: { avatar:"https://images.unsplash.com/photo-1553284965-83fd3e82fa5a?q=80&w=500&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", name:"Broncos", rank:"#3 AFC West", territory:"DEN", }, bills: { avatar:"https://images.unsplash.com/photo-1575414914265-ebc9aa2637f4?q=80&w=500&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", name:"Bills", rank:"#1 AFC East", territory:"BUF", }, steelers: { avatar:"https://plus.unsplash.com/premium_photo-1697730155764-cc8ca8f78cbe?w=500&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8MXx8cGl0dHNidXJnaHxlbnwwfHwwfHx8MA%3D%3D", name:"Steelers", rank:"#2 AFC North", territory:"PIT", }, ravens: { avatar:"https://images.unsplash.com/photo-1433888376991-1297486ba3f5?w=500&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8Mnx8cmF2ZW58ZW58MHx8MHx8fDA%3D", name:"Ravens", rank:"#1 AFC North", territory:"BAL", }, bye: { avatar:"", name:"BYE", rank:"", territory:"", }, } const LayoutBracket = () => { return ( <div> <Layout layout="bracket" > <Layout.RoundLabel> <Caption>Wild Card</Caption> <SectionSeparator marginY="sm"/> </Layout.RoundLabel> <Layout.Round marginBottom={{ xs: "md", sm: "md" }}> <Layout.Game> <Layout.Participant avatar={teamData.packers.avatar} name={teamData.packers.name} points="10" rank={teamData.packers.rank} territory={teamData.packers.territory} /> <Layout.Participant avatar={teamData.eagles.avatar} name={teamData.eagles.name} points="22" rank={teamData.eagles.rank} self territory={teamData.eagles.territory} winner /> </Layout.Game> <Layout.Game> <Layout.Participant avatar={teamData.vikings.avatar} name={teamData.vikings.name} points="9" rank={teamData.vikings.rank} territory={teamData.vikings.territory} /> <Layout.Participant avatar={teamData.rams.avatar} name={teamData.rams.name} points="27" rank={teamData.rams.rank} territory={teamData.rams.territory} winner /> </Layout.Game> <Layout.Game> <Layout.Participant avatar={teamData.lions.avatar} name={teamData.lions.name} points="" rank={teamData.lions.rank} territory={teamData.lions.territory} winner /> <Layout.Participant avatar={teamData.bye.avatar} name={teamData.bye.name} points="" rank={teamData.bye.rank} territory={teamData.bye.territory} /> </Layout.Game> <Layout.Game> <Layout.Participant avatar={teamData.commanders.avatar} name={teamData.commanders.name} points="23" rank={teamData.commanders.rank} territory={teamData.commanders.territory} winner /> <Layout.Participant avatar={teamData.buccaneers.avatar} name={teamData.buccaneers.name} points="20" rank={teamData.buccaneers.rank} territory={teamData.buccaneers.territory} /> </Layout.Game> <Layout.Game> <Layout.Participant avatar={teamData.chiefs.avatar} name={teamData.chiefs.name} points="" rank={teamData.chiefs.rank} territory={teamData.chiefs.territory} winner /> <Layout.Participant avatar={teamData.bye.avatar} name={teamData.bye.name} points="" rank={teamData.bye.rank} territory={teamData.bye.territory} /> </Layout.Game> <Layout.Game> <Layout.Participant avatar={teamData.chargers.avatar} name={teamData.chargers.name} points="12" rank={teamData.chargers.rank} territory={teamData.chargers.territory} /> <Layout.Participant avatar={teamData.texans.avatar} name={teamData.texans.name} points="32" rank={teamData.texans.rank} territory={teamData.texans.territory} winner /> </Layout.Game> <Layout.Game> <Layout.Participant avatar={teamData.broncos.avatar} name={teamData.broncos.name} points="7" rank={teamData.broncos.rank} territory={teamData.broncos.territory} /> <Layout.Participant avatar={teamData.bills.avatar} name={teamData.bills.name} points="31" rank={teamData.bills.rank} territory={teamData.bills.territory} winner /> </Layout.Game> <Layout.Game> <Layout.Participant avatar={teamData.steelers.avatar} name={teamData.steelers.name} points="14" rank={teamData.steelers.rank} territory={teamData.steelers.territory} /> <Layout.Participant avatar={teamData.ravens.avatar} name={teamData.ravens.name} points="28" rank={teamData.ravens.rank} territory={teamData.ravens.territory} winner /> </Layout.Game> </Layout.Round> <Layout.RoundLabel> <Caption>Divisional</Caption> <SectionSeparator marginY="sm"/> </Layout.RoundLabel> <Layout.Round marginBottom={{ xs: "md", sm: "md" }}> <Layout.Game> <Layout.Participant avatar={teamData.rams.avatar} name={teamData.rams.name} points="22" rank={teamData.rams.rank} territory={teamData.rams.territory} /> <Layout.Participant avatar={teamData.eagles.avatar} name={teamData.eagles.name} points="28" rank={teamData.eagles.rank} self territory={teamData.eagles.territory} winner /> </Layout.Game> <Layout.Game> <Layout.Participant avatar={teamData.commanders.avatar} name={teamData.commanders.name} points="45" rank={teamData.commanders.rank} territory={teamData.commanders.territory} winner /> <Layout.Participant avatar={teamData.lions.avatar} name={teamData.lions.name} points="31" rank={teamData.lions.rank} territory={teamData.lions.territory} /> </Layout.Game> <Layout.Game> <Layout.Participant avatar={teamData.texans.avatar} name={teamData.texans.name} points="14" rank={teamData.texans.rank} territory={teamData.texans.territory} /> <Layout.Participant avatar={teamData.chiefs.avatar} name={teamData.chiefs.name} points="23" rank={teamData.chiefs.rank} territory={teamData.chiefs.territory} winner /> </Layout.Game> <Layout.Game> <Layout.Participant avatar={teamData.ravens.avatar} name={teamData.ravens.name} points="25" rank={teamData.ravens.rank} territory={teamData.ravens.territory} /> <Layout.Participant avatar={teamData.bills.avatar} name={teamData.bills.name} points="27" rank={teamData.bills.rank} territory={teamData.bills.territory} winner /> </Layout.Game> </Layout.Round> <Layout.RoundLabel> <Caption>Conference</Caption> <SectionSeparator marginY="sm"/> </Layout.RoundLabel> <Layout.Round marginBottom={{ xs: "md", sm: "md" }}> <Layout.Game> <Layout.Participant avatar={teamData.commanders.avatar} name={teamData.commanders.name} points="23" rank={teamData.commanders.rank} territory={teamData.commanders.territory} /> <Layout.Participant avatar={teamData.eagles.avatar} name={teamData.eagles.name} points="55" rank={teamData.eagles.rank} self territory={teamData.eagles.territory} winner /> </Layout.Game> <Layout.Game> <Layout.Participant avatar={teamData.bills.avatar} name={teamData.bills.name} points="29" rank={teamData.bills.rank} territory={teamData.bills.territory} /> <Layout.Participant avatar={teamData.chiefs.avatar} name={teamData.chiefs.name} points="32" rank={teamData.chiefs.rank} territory={teamData.chiefs.territory} winner /> </Layout.Game> </Layout.Round> <Layout.RoundLabel> <Caption>Super Bowl</Caption> <SectionSeparator marginY="sm"/> </Layout.RoundLabel> <Layout.Round> <Layout.Game> <Layout.Participant avatar={teamData.chiefs.avatar} name={teamData.chiefs.name} points="22" rank={teamData.chiefs.rank} territory={teamData.chiefs.territory} /> <Layout.Participant avatar={teamData.eagles.avatar} name={teamData.eagles.name} points="40" rank={teamData.eagles.rank} self territory={teamData.eagles.territory} winner /> </Layout.Game> </Layout.Round> </Layout> </div> ) } export default LayoutBracket
Card can leverage the max-width property. Learn more in our visual guidelines.
Add a background color by passing the color name to background. List of all colors can be viewed here under Product Colors and Status: Subtle Variations.
import React from 'react' import { Title, Body, Card } from 'playbook-ui' const CardBackground = (props) => { return ( <div> <Title marginBottom="sm" size={4} tag="h4" text="Card Colors" /> <Card background="dark" dark marginBottom="sm" > <Body dark text="Dark" /> </Card> <Card marginBottom="sm" > <Body text="White / Default" /> </Card> <Card background="light" marginBottom="sm" > <Body text="Light"/> </Card> <Title marginBottom="sm" size={4} tag="h4" text="Product Colors" /> <Card background="product_1_background" marginBottom="sm" > <Body dark text="Product 1 Background" /> </Card> <Card background="product_7_highlight" marginBottom="sm" > <Body dark text="Product 7 Highlight" /> </Card> <Card background="product_2_highlight" marginBottom="sm" > <Body dark text="Product 2 Highlight" /> </Card> <Title marginBottom="sm" size={4} tag="h4" text="Subtle Status Colors" /> <Card background="success_subtle" marginBottom="sm" > <Body text="Success Subtle" /> </Card> <Card background="warning_subtle" marginBottom="sm" > <Body text="Warning Subtle" /> </Card> <Card background="info_subtle" marginBottom="sm" > <Body text="Info Subtle" /> </Card> </div> ) } export default CardBackground
Card highlight can pass status, product, and category colors. List of all colors can be viewed here.
import React from 'react' import { Card } from 'playbook-ui' const CardHighlight = (props) => { return ( <div> <Card highlight={{ position: 'side', color: 'product_6_highlight' }} marginBottom="sm" > {'Side Position & Product 6 Highlight Color'} </Card> <Card highlight={{ position: 'top', color: 'warning' }} marginBottom="sm" > {'Top Position & Warning Color'} </Card> <Card highlight={{ position: 'side', color: 'category_2' }} > {'Side Position & Category 2 Color'} </Card> </div> ) } export default CardHighlight
Card headers pass category, product, status and background colors only. List of all category, product, status and background colors can be viewed here.
import React from 'react' import { Card, Title, Body } from 'playbook-ui' const CardHeader = (props) => { return ( <> <Title marginBottom='sm' size={4} tag="h4" text="Category Colors" /> <Card marginBottom='sm' padding="none" > <Card.Header headerColor="category_1" > <Body dark text="Category 1" /> </Card.Header> <Card.Body> <Body text="Body" /> </Card.Body> </Card> <Card marginBottom='sm' padding="none" > <Card.Header headerColor="category_3" > <Body text="Category 3" /> </Card.Header> <Card.Body padding="md" > <Body text="Body" /> </Card.Body> </Card> <Title marginBottom='sm' size={4} tag="h4" text="Product Colors" /> <Card marginBottom='sm' padding="none" > <Card.Header headerColor="product_2_background" > <Body dark text="Product 2 Background" /> </Card.Header> <Card.Body> <Body text="Body" /> </Card.Body> </Card> <Card marginBottom='sm' padding="none" > <Card.Header headerColor="product_6_background" > <Body dark text="Product 6 Background" /> </Card.Header> <Card.Body> <Body text="Body" /> </Card.Body> </Card> <Title marginBottom='sm' size={4} tag="h4" text="Background Colors" /> <Card marginBottom='sm' padding="none" > <Card.Header headerColor="white" > <Body text="White" /> </Card.Header> <Card.Body> <Body text="Body" /> </Card.Body> </Card> <Card marginBottom='sm' padding="none" > <Card.Header headerColor="dark" > <Body dark text="Dark" /> </Card.Header> <Card.Body> <Body text="Body" /> </Card.Body> </Card> <Title marginBottom='sm' size={4} tag="h4" text="Striped Colors" /> <Card marginBottom='sm' padding="none" > <Card.Header headerColor="category_1" headerColorStriped > <Body dark text="Striped Category 1" /> </Card.Header> <Card.Body> <Body text="Body" /> </Card.Body> </Card> <Title marginBottom='sm' size={4} tag="h4" text="Status Colors" /> <Card marginBottom='sm' padding="none" > <Card.Header headerColor="success" > <Body dark text="Success" /> </Card.Header> <Card.Body> <Body text="Body" /> </Card.Body> </Card> <Card marginBottom='sm' padding="none" > <Card.Header headerColor="error" > <Body dark text="Error" /> </Card.Header> <Card.Body> <Body text="Body" /> </Card.Body> </Card> <Card marginBottom='sm' padding="none" > <Card.Header headerColor="success_subtle" > <Body text="Success Subtle" /> </Card.Header> <Card.Body> <Body text="Body" /> </Card.Body> </Card> <Card marginBottom='sm' padding="none" > <Card.Header headerColor="error_subtle" > <Body text="Error Subtle" /> </Card.Header> <Card.Body> <Body text="Body" /> </Card.Body> </Card> </> ) } export default CardHeader
import React from 'react' import { Card } from 'playbook-ui' const CardTag = (props) => { return ( <div> <Card tag="section" > {'section'} </Card> <br /> <Card tag="footer" > {'footer'} </Card> <br /> <Card tag="header" > {'header'} </Card> <br /> <Card tag="article" > {'article'} </Card> <br /> <Card tag="aside" > {'aside'} </Card> <br /> <Card tag="main" > {'main'} </Card> <br /> <Card tag="nav" > {'nav'} </Card> </div> ) } export default CardTag
import React from 'react' import { Card } from 'playbook-ui' const CardPadding = (props) => { return ( <div> <Card padding="none" > {'Card content'} </Card> <br /> <Card padding="xs" > {'Card content'} </Card> <br /> <Card padding="sm" > {'Card content'} </Card> <br /> <Card padding="md" > {'Card content'} </Card> <br /> <Card padding="lg" > {'Card content'} </Card> <br /> <Card padding="xl" > {'Card content'} </Card> <br /> </div> ) } export default CardPadding
import React from 'react' import { Card } from 'playbook-ui' const CardShadow = (props) => { return ( <div> <Card shadow="none" > {'Card content'} </Card> <br /> <Card shadow="deep" > {'Card content'} </Card> <br /> <Card shadow="deeper" > {'Card content'} </Card> <br /> <Card shadow="deepest" > {'Card content'} </Card> <br /> </div> ) } export default CardShadow
import React from 'react' import { Card } from 'playbook-ui' const CardContent = (props) => { return ( <div> <Card cursor="pointer" > {'Card content'} </Card> <br /> <Card > {`Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec iaculis, risus a fringilla luctus, sapien eros sodales ex, quis molestie est nulla non turpis. Vestibulum aliquet at ipsum eget posuere. Morbi sed laoreet erat. Sed commodo posuere lectus, at porta nulla ornare a. Suspendisse quam est, sollicitudin ut enim sit amet, commodo placerat enim. Donec laoreet metus ac mauris pellentesque mattis. Pellentesque luctus vel mauris non aliquam. Mauris hendrerit mattis porttitor. Curabitur vehicula justo non ex consectetur commodo. Quisque posuere aliquet quam. Maecenas malesuada magna mauris, ac tempor metus euismod at. Cras ornare fermentum magna mollis efficitur. Sed vitae nulla vel purus ultrices mollis. Maecenas id nulla id libero faucibus feugiat quis sit amet turpis. In commodo pellentesque risus at fringilla. Integer non interdum leo, non commodo ante. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut mi augue, dignissim at orci vel, egestas aliquam mi. Proin finibus aliquet tempor. Integer cursus, ex quis gravida rhoncus, nisi elit viverra ipsum, non efficitur est ex ac tortor. Praesent vitae odio massa.`} </Card> <br /> </div> ) } export default CardContent
import React from 'react' import { Card, SectionSeparator } from 'playbook-ui' const CardSeparator = (props) => { return ( <Card padding="none" > <Card.Body> {'Header'} </Card.Body> <SectionSeparator variant="card" /> <Card.Body> { 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec iaculis, risus a fringilla luctus, sapien eros sodales ex, quis molestie est nulla non turpis. Vestibulum aliquet at ipsum eget posuere. Morbi sed laoreet erat. Sed commodo posuere lectus, at porta nulla ornare a. Suspendisse quam est, sollicitudin ut enim sit amet, commodo placerat enim. Donec laoreet metus ac mauris pellentesque mattis. Pellentesque luctus vel mauris non aliquam. Mauris hendrerit mattis porttitor. Curabitur vehicula justo non ex consectetur commodo. Quisque posuere aliquet quam. Maecenas malesuada magna mauris, ac tempor metus euismod at. Cras ornare fermentum magna mollis efficitur. Sed vitae nulla vel purus ultrices mollis. Maecenas id nulla id libero faucibus feugiat quis sit amet turpis. In commodo pellentesque risus at fringilla. Integer non interdum leo, non commodo ante. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut mi augue, dignissim at orci vel, egestas aliquam mi. Proin finibus aliquet tempor. Integer cursus, ex quis gravida rhoncus, nisi elit viverra ipsum, non efficitur est ex ac tortor. Praesent vitae odio massa.' } </Card.Body> <SectionSeparator variant="card" /> <Card.Body> {'Footer'} </Card.Body> </Card> ) } export default CardSeparator
Remove card border only for dashboard cards.
border_radius_md
is the card kit default
import React from 'react' import { Card } from 'playbook-ui' const CardLight = (props) => { return ( <div> <Card borderRadius="rounded" > {'Rounded (1000px)'} </Card> <br /> <Card borderRadius="xl" > {'Extra large (16px)'} </Card> <br /> <Card borderRadius="lg" > {'Large (8px)'} </Card> <br /> <Card borderRadius="md" > {'Medium (6px)'} </Card> <br /> <Card borderRadius="sm" > {'Small (4px)'} </Card> <br /> <Card borderRadius="xs" > {'Extra small (4px)'} </Card> <br /> <Card borderRadius="none" > {'None'} </Card> </div> ) } export default CardLight
To guarantee the vertical section separator displays properly, please add the vertical: "stretch"
/vertical="stretch"
property to the parent container (which is commonly a Flex container). This will stretch the container’s child elements vertically and ensure the section separator appears as expected.
import React from 'react' import { SectionSeparator, Flex, FlexItem } from 'playbook-ui' const SectionSeparatorVertical = (props) => { return ( <Flex inline="flex-container" vertical="stretch" > <FlexItem> {'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua'} </FlexItem> <SectionSeparator orientation="vertical" /> <FlexItem> {'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua'} </FlexItem> <SectionSeparator orientation="vertical" /> <FlexItem> {'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua'} </FlexItem> </Flex> ) } export default SectionSeparatorVertical
Pass anything (including any of our kits) to the children
prop to customize a separator's content.
NOTE: passing children
overrides any content passed to text
import React from 'react' import { Card, Caption, SectionSeparator } from 'playbook-ui' const children = ( <Card borderRadius="rounded" justifyContent="center" padding="none" > <Caption paddingLeft="xs" paddingRight="xs" size="xs" text="TODAY" /> </Card> ) const SectionSeparatorChildren = (props) => { return ( <SectionSeparator lineStyle='dashed' > {children} </SectionSeparator> ) } export default SectionSeparatorChildren
Pass "primary" to the color
prop to change any section separator color.
NOTE: Passing children
overrides any content provided via the text
prop. The color
prop does not affect the text
prop's color, and the color of children
is determined by the children's individual props. For greater control over text color customization, consider using a separator with children
.
import React from "react" import { SectionSeparator, Flex, Detail, Icon } from 'playbook-ui' const children = ( <Flex padding="xs"> <Icon color="primary" icon="arrow-down" /> <Detail color="link" size="sm" text="Children" /> </Flex> ) const SectionSeparatorColor = (props) => { return ( <div> <SectionSeparator text="Default Separator" /> <SectionSeparator color="primary" text="Primary Separator" /> <SectionSeparator color="primary" lineStyle="dashed" text="Primary Dashed Separator" /> <SectionSeparator color="primary" > {children} </SectionSeparator> </div> ) } export default SectionSeparatorColor
To add a lazyload on the background image simply use the transition
prop and one of the three string options "fade"
, "blur"
, or "scale"
.
import React, { useState } from 'react' import { Background, Card, Flex, FlexItem, Select, Title } from 'playbook-ui' const BackgroundImage = (props) => { const [transition, setTransition] = useState('') const handleTransition = ({ target }) => { setTransition(target.value) } const options = [ { value: 'fade', }, { value: 'blur', }, { value: 'scale', }, ] return ( <> <Background alt="colorful background" className="background lazyload" imageUrl="https://images.unsplash.com/photo-1528459801416-a9e53bbf4e17?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1000&q=80" transition={transition} > <Flex orientation="column" vertical="center" > <FlexItem> <Title dark padding="lg" size={1} text="Background Kit Image" /> </FlexItem> <FlexItem padding="lg" > <Card shadow="deepest" > { 'We cannot seek achievement for ourselves and forget about progress and prosperity for our community... Our ambitions must be broad enough to include the aspirations and needs of others, for their sakes and for our own. - Cesar Chavez' } </Card> </FlexItem> </Flex> </Background> <Flex marginTop="xl"> <FlexItem fixedSize="250px"> <Select blankSelection="Select a Transition..." label="" name="dropdown" onChange={handleTransition} options={options} transition={transition} /> </FlexItem> </Flex> </> ) } export default BackgroundImage
Status colors can be passed into the background kit. success
, success_secondary
, warning
, warning_secondary
, error
, error_secondary
, info
, info_secondary
, neutral
, neutral_secondary
, primary
, and primary_secondary
import React from 'react' import { Background, Flex } from 'playbook-ui' const BackgroundStatus = (props) => ( <Flex gap="md" justify="center" wrap > <Background backgroundColor="success" padding="xl" /> <br /> <Background backgroundColor="success_secondary" padding="xl" /> <br /> <Background backgroundColor="warning" padding="xl" /> <br /> <Background backgroundColor="warning_secondary" padding="xl" /> <br /> <Background backgroundColor="error" padding="xl" /> <br /> <Background backgroundColor="error_secondary" padding="xl" /> <br /> <Background backgroundColor="info" padding="xl" /> <br /> <Background backgroundColor="info_secondary" padding="xl" /> <br /> <Background backgroundColor="neutral" padding="xl" /> <br /> <Background backgroundColor="neutral_secondary" padding="xl" /> <br /> <Background backgroundColor="primary" padding="xl" /> <br /> <Background backgroundColor="primary_secondary" padding="xl" /> </Flex> ) export default BackgroundStatus
Status Subtle colors can be passed into the background kit. success_subtle
, warning_subtle
,error_subtle
, info_subtle
and neutral_subtle
import React from 'react' import { Background, Flex } from 'playbook-ui' const BackgroundStatusSubtle = (props) => ( <Flex gap="md" justify="center" wrap > <Background backgroundColor="success_subtle" padding="xl" /> <br /> <Background backgroundColor="warning_subtle" padding="xl" /> <br /> <Background backgroundColor="error_subtle" padding="xl" /> <br /> <Background backgroundColor="info_subtle" padding="xl" /> <br /> <Background backgroundColor="neutral_subtle" padding="xl" /> <br /> </Flex> ) export default BackgroundStatusSubtle
Category colors can be passed into the background kit. Values category_1
to category_21
are accepted. List of all category and status colors can be viewed here.
import React from 'react' import { Background, Flex } from 'playbook-ui' const BackgroundCategory = (props) => ( <Flex gap="md" justify="center" wrap > <Background backgroundColor="category_1" padding="xl" /> <Background backgroundColor="category_2" padding="xl" /> <Background backgroundColor="category_3" padding="xl" /> <Background backgroundColor="category_4" padding="xl" /> <Background backgroundColor="category_5" padding="xl" /> <Background backgroundColor="category_6" padding="xl" /> <Background backgroundColor="category_7" padding="xl" /> <Background backgroundColor="category_8" padding="xl" /> <Background backgroundColor="category_9" padding="xl" /> <Background backgroundColor="category_10" padding="xl" /> <Background backgroundColor="category_11" padding="xl" /> <Background backgroundColor="category_12" padding="xl" /> <Background backgroundColor="category_13" padding="xl" /> <Background backgroundColor="category_14" padding="xl" /> <Background backgroundColor="category_15" padding="xl" /> <Background backgroundColor="category_16" padding="xl" /> <Background backgroundColor="category_17" padding="xl" /> <Background backgroundColor="category_18" padding="xl" /> <Background backgroundColor="category_19" padding="xl" /> <Background backgroundColor="category_20" padding="xl" /> <Background backgroundColor="category_21" padding="xl" /> </Flex> ) export default BackgroundCategory
Background size can be passed into the background kit. Values auto
, cover
, and contain
are accepted.
💡 Note: When using contain
you might not want to have a repeating background as this will not always look pleasant. To prevent this, you may pass no-repeat
to the backgroundRepeat
prop.
import React, { Fragment as F } from 'react' import { Background } from 'playbook-ui' const BackgroundSize = (props) => ( <F> <Background alt="colorful background" backgroundSize="auto" className="background lazyload" imageUrl="https://images.unsplash.com/photo-1528459801416-a9e53bbf4e17?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1000&q=80" padding="xl" /> <br/> <Background alt="colorful background" backgroundSize="cover" className="background lazyload" imageUrl="https://images.unsplash.com/photo-1528459801416-a9e53bbf4e17?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1000&q=80" padding="xl" /> <br/> <Background alt="colorful background" backgroundRepeat="no-repeat" backgroundSize="contain" className="background lazyload" imageUrl="https://images.unsplash.com/photo-1528459801416-a9e53bbf4e17?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1000&q=80" padding="xl" /> </F> ) export default BackgroundSize
An overlay can be added to the background image by setting the imageOverlay
prop and adding a backgroundColor
. The imageOverlay
prop can be set to any opacity ranging from opacity_1
to opacity_10
.
import React from 'react' import { Background, Flex, FlexItem, Title } from 'playbook-ui' const BackgroundOverlay = (props) => { return ( <Background alt="colorful background" backgroundColor="category_21" className="background lazyload" imageOverlay="opacity_2" imageUrl="https://unsplash.it/500/400/?image=633" > <Flex orientation="column" vertical="center" > <FlexItem> <Title dark padding="lg" size={1} text="Background Kit Image" /> </FlexItem> </Flex> </Background> ) } export default BackgroundOverlay
import React from 'react' import { Collapsible } from 'playbook-ui' const CollapsibleDefault = (props) => ( <Collapsible > <Collapsible.Main> <div>{'Main Section'}</div> </Collapsible.Main> <Collapsible.Content> <div> { 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. In vel erat sed purus hendrerit viverra. Duis et vestibulum metus. Sed consequat ut ante non vehicula. Etiam nunc massa, pharetra vel quam id, posuere rhoncus quam. Quisque imperdiet arcu enim, nec aliquet justo auctor eget. Curabitur in metus nec nunc rhoncus faucibus vitae ac elit. Nulla facilisi. Vestibulum quis pretium nulla. Nulla ut accumsan velit. Duis varius urna sed sem tempor, sit amet fermentum nibh auctor. Praesent lorem arcu, egestas non ante quis, placerat pellentesque lectus.Vestibulum lacinia ipsum quis venenatis tristique. Vivamus suscipit, libero eu fringilla egestas, orci urna commodo arcu, vel gravida turpis ipsum molestie nibh. Donec cursus eu ante sagittis ultrices. Phasellus id sagittis risus. Mauris dapibus neque faucibus, tempor ligula vel, cursus ante. Donec faucibus gravida porta. Nullam egestas est quis aliquam feugiat. Sed eget metus diam. Cras eget placerat libero.' } </div> </Collapsible.Content> </Collapsible> ) export default CollapsibleDefault
This kit uses icon
sizes. If you don't give it a size, it will default to medium. This can be replaced with the sizes below:
lg
xs
sm
1x
2x
3x
4x
5x
6x
7x
8x
9x
10x
import React from 'react' import { Collapsible } from 'playbook-ui' const CollapsibleSize = (props) => ( <div> <Collapsible iconSize="xs" marginBottom="xs" > <Collapsible.Main> <div>{'Extra Small Section'}</div> </Collapsible.Main> <Collapsible.Content> <div> { 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. In vel erat sed purus hendrerit viverra. Duis et vestibulum metus. Sed consequat ut ante non vehicula. Etiam nunc massa, pharetra vel quam id, posuere rhoncus quam. Quisque imperdiet arcu enim, nec aliquet justo auctor eget. Curabitur in metus nec nunc rhoncus faucibus vitae ac elit. Nulla facilisi. Vestibulum quis pretium nulla. Nulla ut accumsan velit. Duis varius urna sed sem tempor, sit amet fermentum nibh auctor. Praesent lorem arcu, egestas non ante quis, placerat pellentesque lectus.Vestibulum lacinia ipsum quis venenatis tristique. Vivamus suscipit, libero eu fringilla egestas, orci urna commodo arcu, vel gravida turpis ipsum molestie nibh. Donec cursus eu ante sagittis ultrices. Phasellus id sagittis risus. Mauris dapibus neque faucibus, tempor ligula vel, cursus ante. Donec faucibus gravida porta. Nullam egestas est quis aliquam feugiat. Sed eget metus diam. Cras eget placerat libero.' } </div> </Collapsible.Content> </Collapsible> <Collapsible iconSize="sm" marginBottom="xs" > <Collapsible.Main> <div>{'Small Section'}</div> </Collapsible.Main> <Collapsible.Content> <div> { 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. In vel erat sed purus hendrerit viverra. Duis et vestibulum metus. Sed consequat ut ante non vehicula. Etiam nunc massa, pharetra vel quam id, posuere rhoncus quam. Quisque imperdiet arcu enim, nec aliquet justo auctor eget. Curabitur in metus nec nunc rhoncus faucibus vitae ac elit. Nulla facilisi. Vestibulum quis pretium nulla. Nulla ut accumsan velit. Duis varius urna sed sem tempor, sit amet fermentum nibh auctor. Praesent lorem arcu, egestas non ante quis, placerat pellentesque lectus.Vestibulum lacinia ipsum quis venenatis tristique. Vivamus suscipit, libero eu fringilla egestas, orci urna commodo arcu, vel gravida turpis ipsum molestie nibh. Donec cursus eu ante sagittis ultrices. Phasellus id sagittis risus. Mauris dapibus neque faucibus, tempor ligula vel, cursus ante. Donec faucibus gravida porta. Nullam egestas est quis aliquam feugiat. Sed eget metus diam. Cras eget placerat libero.' } </div> </Collapsible.Content> </Collapsible> <Collapsible marginBottom="xs" > <Collapsible.Main> <div>{'Default Section'}</div> </Collapsible.Main> <Collapsible.Content> <div> { 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. In vel erat sed purus hendrerit viverra. Duis et vestibulum metus. Sed consequat ut ante non vehicula. Etiam nunc massa, pharetra vel quam id, posuere rhoncus quam. Quisque imperdiet arcu enim, nec aliquet justo auctor eget. Curabitur in metus nec nunc rhoncus faucibus vitae ac elit. Nulla facilisi. Vestibulum quis pretium nulla. Nulla ut accumsan velit. Duis varius urna sed sem tempor, sit amet fermentum nibh auctor. Praesent lorem arcu, egestas non ante quis, placerat pellentesque lectus.Vestibulum lacinia ipsum quis venenatis tristique. Vivamus suscipit, libero eu fringilla egestas, orci urna commodo arcu, vel gravida turpis ipsum molestie nibh. Donec cursus eu ante sagittis ultrices. Phasellus id sagittis risus. Mauris dapibus neque faucibus, tempor ligula vel, cursus ante. Donec faucibus gravida porta. Nullam egestas est quis aliquam feugiat. Sed eget metus diam. Cras eget placerat libero.' } </div> </Collapsible.Content> </Collapsible> <Collapsible iconSize="lg" marginBottom="xs" > <Collapsible.Main> <div>{'Large Section'}</div> </Collapsible.Main> <Collapsible.Content> <div> { 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. In vel erat sed purus hendrerit viverra. Duis et vestibulum metus. Sed consequat ut ante non vehicula. Etiam nunc massa, pharetra vel quam id, posuere rhoncus quam. Quisque imperdiet arcu enim, nec aliquet justo auctor eget. Curabitur in metus nec nunc rhoncus faucibus vitae ac elit. Nulla facilisi. Vestibulum quis pretium nulla. Nulla ut accumsan velit. Duis varius urna sed sem tempor, sit amet fermentum nibh auctor. Praesent lorem arcu, egestas non ante quis, placerat pellentesque lectus.Vestibulum lacinia ipsum quis venenatis tristique. Vivamus suscipit, libero eu fringilla egestas, orci urna commodo arcu, vel gravida turpis ipsum molestie nibh. Donec cursus eu ante sagittis ultrices. Phasellus id sagittis risus. Mauris dapibus neque faucibus, tempor ligula vel, cursus ante. Donec faucibus gravida porta. Nullam egestas est quis aliquam feugiat. Sed eget metus diam. Cras eget placerat libero.' } </div> </Collapsible.Content> </Collapsible> </div> ) export default CollapsibleSize
This kit uses default
color by default, and can be replaced with colors below:
light
lighter
success
error
link
import React from 'react' import { Collapsible } from 'playbook-ui' const CollapsibleColor = (props) => ( <div> <Collapsible iconColor='default' marginBottom="xs" > <Collapsible.Main> <div>{'Default Section'}</div> </Collapsible.Main> <Collapsible.Content> <div> { 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. In vel erat sed purus hendrerit viverra. Duis et vestibulum metus. Sed consequat ut ante non vehicula. Etiam nunc massa, pharetra vel quam id, posuere rhoncus quam. Quisque imperdiet arcu enim, nec aliquet justo auctor eget. Curabitur in metus nec nunc rhoncus faucibus vitae ac elit. Nulla facilisi. Vestibulum quis pretium nulla. Nulla ut accumsan velit. Duis varius urna sed sem tempor, sit amet fermentum nibh auctor. Praesent lorem arcu, egestas non ante quis, placerat pellentesque lectus.Vestibulum lacinia ipsum quis venenatis tristique. Vivamus suscipit, libero eu fringilla egestas, orci urna commodo arcu, vel gravida turpis ipsum molestie nibh. Donec cursus eu ante sagittis ultrices. Phasellus id sagittis risus. Mauris dapibus neque faucibus, tempor ligula vel, cursus ante. Donec faucibus gravida porta. Nullam egestas est quis aliquam feugiat. Sed eget metus diam. Cras eget placerat libero.' } </div> </Collapsible.Content> </Collapsible> <Collapsible iconColor='lighter' marginBottom="xs" > <Collapsible.Main> <div>{'Light Section'}</div> </Collapsible.Main> <Collapsible.Content> <div> { 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. In vel erat sed purus hendrerit viverra. Duis et vestibulum metus. Sed consequat ut ante non vehicula. Etiam nunc massa, pharetra vel quam id, posuere rhoncus quam. Quisque imperdiet arcu enim, nec aliquet justo auctor eget. Curabitur in metus nec nunc rhoncus faucibus vitae ac elit. Nulla facilisi. Vestibulum quis pretium nulla. Nulla ut accumsan velit. Duis varius urna sed sem tempor, sit amet fermentum nibh auctor. Praesent lorem arcu, egestas non ante quis, placerat pellentesque lectus.Vestibulum lacinia ipsum quis venenatis tristique. Vivamus suscipit, libero eu fringilla egestas, orci urna commodo arcu, vel gravida turpis ipsum molestie nibh. Donec cursus eu ante sagittis ultrices. Phasellus id sagittis risus. Mauris dapibus neque faucibus, tempor ligula vel, cursus ante. Donec faucibus gravida porta. Nullam egestas est quis aliquam feugiat. Sed eget metus diam. Cras eget placerat libero.' } </div> </Collapsible.Content> </Collapsible> <Collapsible iconColor='light' marginBottom="xs" > <Collapsible.Main> <div>{'Lighter Section'}</div> </Collapsible.Main> <Collapsible.Content> <div> { 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. In vel erat sed purus hendrerit viverra. Duis et vestibulum metus. Sed consequat ut ante non vehicula. Etiam nunc massa, pharetra vel quam id, posuere rhoncus quam. Quisque imperdiet arcu enim, nec aliquet justo auctor eget. Curabitur in metus nec nunc rhoncus faucibus vitae ac elit. Nulla facilisi. Vestibulum quis pretium nulla. Nulla ut accumsan velit. Duis varius urna sed sem tempor, sit amet fermentum nibh auctor. Praesent lorem arcu, egestas non ante quis, placerat pellentesque lectus.Vestibulum lacinia ipsum quis venenatis tristique. Vivamus suscipit, libero eu fringilla egestas, orci urna commodo arcu, vel gravida turpis ipsum molestie nibh. Donec cursus eu ante sagittis ultrices. Phasellus id sagittis risus. Mauris dapibus neque faucibus, tempor ligula vel, cursus ante. Donec faucibus gravida porta. Nullam egestas est quis aliquam feugiat. Sed eget metus diam. Cras eget placerat libero.' } </div> </Collapsible.Content> </Collapsible> <Collapsible iconColor='link' marginBottom="xs" > <Collapsible.Main> <div>{'Link Section'}</div> </Collapsible.Main> <Collapsible.Content> <div> { 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. In vel erat sed purus hendrerit viverra. Duis et vestibulum metus. Sed consequat ut ante non vehicula. Etiam nunc massa, pharetra vel quam id, posuere rhoncus quam. Quisque imperdiet arcu enim, nec aliquet justo auctor eget. Curabitur in metus nec nunc rhoncus faucibus vitae ac elit. Nulla facilisi. Vestibulum quis pretium nulla. Nulla ut accumsan velit. Duis varius urna sed sem tempor, sit amet fermentum nibh auctor. Praesent lorem arcu, egestas non ante quis, placerat pellentesque lectus.Vestibulum lacinia ipsum quis venenatis tristique. Vivamus suscipit, libero eu fringilla egestas, orci urna commodo arcu, vel gravida turpis ipsum molestie nibh. Donec cursus eu ante sagittis ultrices. Phasellus id sagittis risus. Mauris dapibus neque faucibus, tempor ligula vel, cursus ante. Donec faucibus gravida porta. Nullam egestas est quis aliquam feugiat. Sed eget metus diam. Cras eget placerat libero.' } </div> </Collapsible.Content> </Collapsible> <Collapsible iconColor='error' marginBottom="xs" > <Collapsible.Main> <div>{'Error Section'}</div> </Collapsible.Main> <Collapsible.Content> <div> { 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. In vel erat sed purus hendrerit viverra. Duis et vestibulum metus. Sed consequat ut ante non vehicula. Etiam nunc massa, pharetra vel quam id, posuere rhoncus quam. Quisque imperdiet arcu enim, nec aliquet justo auctor eget. Curabitur in metus nec nunc rhoncus faucibus vitae ac elit. Nulla facilisi. Vestibulum quis pretium nulla. Nulla ut accumsan velit. Duis varius urna sed sem tempor, sit amet fermentum nibh auctor. Praesent lorem arcu, egestas non ante quis, placerat pellentesque lectus.Vestibulum lacinia ipsum quis venenatis tristique. Vivamus suscipit, libero eu fringilla egestas, orci urna commodo arcu, vel gravida turpis ipsum molestie nibh. Donec cursus eu ante sagittis ultrices. Phasellus id sagittis risus. Mauris dapibus neque faucibus, tempor ligula vel, cursus ante. Donec faucibus gravida porta. Nullam egestas est quis aliquam feugiat. Sed eget metus diam. Cras eget placerat libero.' } </div> </Collapsible.Content> </Collapsible> <Collapsible iconColor='success' > <Collapsible.Main> <div>{'Success Section'}</div> </Collapsible.Main> <Collapsible.Content> <div> { 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. In vel erat sed purus hendrerit viverra. Duis et vestibulum metus. Sed consequat ut ante non vehicula. Etiam nunc massa, pharetra vel quam id, posuere rhoncus quam. Quisque imperdiet arcu enim, nec aliquet justo auctor eget. Curabitur in metus nec nunc rhoncus faucibus vitae ac elit. Nulla facilisi. Vestibulum quis pretium nulla. Nulla ut accumsan velit. Duis varius urna sed sem tempor, sit amet fermentum nibh auctor. Praesent lorem arcu, egestas non ante quis, placerat pellentesque lectus.Vestibulum lacinia ipsum quis venenatis tristique. Vivamus suscipit, libero eu fringilla egestas, orci urna commodo arcu, vel gravida turpis ipsum molestie nibh. Donec cursus eu ante sagittis ultrices. Phasellus id sagittis risus. Mauris dapibus neque faucibus, tempor ligula vel, cursus ante. Donec faucibus gravida porta. Nullam egestas est quis aliquam feugiat. Sed eget metus diam. Cras eget placerat libero.' } </div> </Collapsible.Content> </Collapsible> </div> ) export default CollapsibleColor
The icon
prop allows you to customize your icon sets by passing it an array of any comma-separated pair of icon values. The first icon value will replace the kit's default icon when collapsed (chevron-down), and the second value will replace the default icon when expanded (chevron-up). icon
also allows you to pass it a single icon as a string, in which case the icon will not toggle with the collapsible state.
import React from 'react' import { Collapsible } from 'playbook-ui' const CollapsibleIcons = (props) => { return ( <> <Collapsible icon={['plus','minus']} iconColor='white' > <Collapsible.Main> <div>{'Main Section'}</div> </Collapsible.Main> <Collapsible.Content> <div> { 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. In vel erat sed purus hendrerit viverra. Duis et vestibulum metus. Sed consequat ut ante non vehicula. Etiam nunc massa, pharetra vel quam id, posuere rhoncus quam. Quisque imperdiet arcu enim, nec aliquet justo auctor eget. Curabitur in metus nec nunc rhoncus faucibus vitae ac elit. Nulla facilisi. Vestibulum quis pretium nulla. Nulla ut accumsan velit. Duis varius urna sed sem tempor, sit amet fermentum nibh auctor. Praesent lorem arcu, egestas non ante quis, placerat pellentesque lectus.Vestibulum lacinia ipsum quis venenatis tristique. Vivamus suscipit, libero eu fringilla egestas, orci urna commodo arcu, vel gravida turpis ipsum molestie nibh. Donec cursus eu ante sagittis ultrices. Phasellus id sagittis risus. Mauris dapibus neque faucibus, tempor ligula vel, cursus ante. Donec faucibus gravida porta. Nullam egestas est quis aliquam feugiat. Sed eget metus diam. Cras eget placerat libero.' } </div> </Collapsible.Content> </Collapsible> </> ) } export default CollapsibleIcons
The collapsed
prop allows you to toggle the collapsible with external controls (like buttons) when used in conjunction with our useCollapsible
hook.
NOTE: you must import and declare the useCollapsible
hook then pass its state to the collapsed prop of any Collapsible you wish to manage with the external control. See our code example for details.
import React from 'react' import { Collapsible, useCollapsible, Button } from 'playbook-ui'import PropTypes from 'prop-types'; const CollapsibleState = (props) => { const [isCollapsed, setIsCollapsed] = useCollapsible(true) return ( <> <Button dark={props.dark} onClick={() => setIsCollapsed(!isCollapsed)} padding="none" variant="link" > {isCollapsed ? "Expand All" : "Collapse All"} </Button> <Collapsible collapsed={isCollapsed} icon={["plus", "minus"]} iconColor='white' padding="none" > <Collapsible.Main padding="sm" > <div>{"Main Section"}</div> </Collapsible.Main> <Collapsible.Content> <div> { "Lorem ipsum dolor sit amet, consectetur adipiscing elit. In vel erat sed purus hendrerit viverra. Duis et vestibulum metus. Sed consequat ut ante non vehicula. Etiam nunc massa, pharetra vel quam id, posuere rhoncus quam. Quisque imperdiet arcu enim, nec aliquet justo auctor eget. Curabitur in metus nec nunc rhoncus faucibus vitae ac elit." } </div> </Collapsible.Content> </Collapsible> <Collapsible collapsed={isCollapsed} icon={["plus", "minus"]} iconColor='white' padding="none" > <Collapsible.Main padding="sm" > <div>{"Main Section"}</div> </Collapsible.Main> <Collapsible.Content> <div> { "Lorem ipsum dolor sit amet, consectetur adipiscing elit. In vel erat sed purus hendrerit viverra. Duis et vestibulum metus. Sed consequat ut ante non vehicula. Etiam nunc massa, pharetra vel quam id, posuere rhoncus quam. Quisque imperdiet arcu enim, nec aliquet justo auctor eget. Curabitur in metus nec nunc rhoncus faucibus vitae ac elit." } </div> </Collapsible.Content> </Collapsible> <Collapsible collapsed={isCollapsed} icon={["plus", "minus"]} iconColor='white' padding="none" > <Collapsible.Main padding="sm" > <div>{"Main Section"}</div> </Collapsible.Main> <Collapsible.Content> <div> { "Lorem ipsum dolor sit amet, consectetur adipiscing elit. In vel erat sed purus hendrerit viverra. Duis et vestibulum metus. Sed consequat ut ante non vehicula. Etiam nunc massa, pharetra vel quam id, posuere rhoncus quam. Quisque imperdiet arcu enim, nec aliquet justo auctor eget. Curabitur in metus nec nunc rhoncus faucibus vitae ac elit." } </div> </Collapsible.Content> </Collapsible> </> ) } CollapsibleState.propTypes = { dark: PropTypes.bool, } export default CollapsibleState
Optionally replace your Collapsible.Main
with any component to customize your Main section's contents and/or style. This gives you full control over that subcomponent. For example, here we are using global props to make that custom Main 'sticky' on scroll.
NOTE: Custom main sections requires the useCollapsible
hook to ensure the collapsible's toggle action works correctly.
import React from 'react' import { Collapsible, useCollapsible, Flex, Title, List, ListItem } from 'playbook-ui'import PropTypes from 'prop-types' const CollapsibleCustomMain = (props) => { const [isCollapsed, setIsCollapsed] = useCollapsible(true) return ( <> <Collapsible collapsed={isCollapsed}> <Flex align="center" cursor="pointer" gap="sm" htmlOptions={{onClick:() => setIsCollapsed(!isCollapsed)}} justify="between" position="sticky" top="0" > <Title dark={props.dark} size={4} text="Custom Main Section" /> </Flex> <Collapsible.Content padding="none"> <div> <List> <ListItem align="stretch" flexDirection="column" > {"Checklist item"} </ListItem> <ListItem align="stretch" flexDirection="column" > {"Checklist item"} </ListItem> <ListItem align="stretch" flexDirection="column" > {"Checklist item"} </ListItem> <ListItem align="stretch" flexDirection="column" > {"Checklist item"} </ListItem> <ListItem align="stretch" flexDirection="column" > {"Checklist item"} </ListItem> </List> </div> </Collapsible.Content> </Collapsible> </> ) } CollapsibleCustomMain.propTypes = { dark: PropTypes.bool, } export default CollapsibleCustomMain
When using a custom Main Section, you can also use the optional Collapsible.Icon
.
NOTE: The optional icon subcomponent must receive the collapsed
state of the collapsible in order to toggle correctly. It also accepts all icon-related props (icon
, size
, and color
) for further customization. If none of these are specified, the default icon will be rendered.
import React from 'react' import { Collapsible, useCollapsible, Flex, Title, List, ListItem } from 'playbook-ui'import PropTypes from 'prop-types' const CollapsibleCustomMainWithIcon = (props) => { const [isCollapsed, setIsCollapsed] = useCollapsible(true) return ( <> <Collapsible collapsed={isCollapsed}> <Flex align="center" cursor="pointer" gap="sm" htmlOptions={{onClick:() => setIsCollapsed(!isCollapsed)}} justify="between" position="sticky" top="0" > <Title dark={props.dark} size={4} text="Custom Main Section" /> <Collapsible.Icon collapsed={isCollapsed} /> </Flex> <Collapsible.Content padding="none" > <div> <List> <ListItem align="stretch" flexDirection="column" > {"Checklist item"} </ListItem> <ListItem align="stretch" flexDirection="column" > {"Checklist item"} </ListItem> <ListItem align="stretch" flexDirection="column" > {"Checklist item"} </ListItem> <ListItem align="stretch" flexDirection="column" > {"Checklist item"} </ListItem> <ListItem align="stretch" flexDirection="column" > {"Checklist item"} </ListItem> </List> </div> </Collapsible.Content> </Collapsible> </> ) } CollapsibleCustomMainWithIcon.propTypes = { dark: PropTypes.bool, } export default CollapsibleCustomMainWithIcon
import React from 'react' import { Collapsible } from 'playbook-ui' const CollapsibleNoIcon = (props) => ( <Collapsible icon="none" > <Collapsible.Main> <div>{'Main Section'}</div> </Collapsible.Main> <Collapsible.Content> <div> { 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. In vel erat sed purus hendrerit viverra. Duis et vestibulum metus. Sed consequat ut ante non vehicula. Etiam nunc massa, pharetra vel quam id, posuere rhoncus quam. Quisque imperdiet arcu enim, nec aliquet justo auctor eget. Curabitur in metus nec nunc rhoncus faucibus vitae ac elit. Nulla facilisi. Vestibulum quis pretium nulla. Nulla ut accumsan velit. Duis varius urna sed sem tempor, sit amet fermentum nibh auctor. Praesent lorem arcu, egestas non ante quis, placerat pellentesque lectus.Vestibulum lacinia ipsum quis venenatis tristique. Vivamus suscipit, libero eu fringilla egestas, orci urna commodo arcu, vel gravida turpis ipsum molestie nibh. Donec cursus eu ante sagittis ultrices. Phasellus id sagittis risus. Mauris dapibus neque faucibus, tempor ligula vel, cursus ante. Donec faucibus gravida porta. Nullam egestas est quis aliquam feugiat. Sed eget metus diam. Cras eget placerat libero.' } </div> </Collapsible.Content> </Collapsible> ) export default CollapsibleNoIcon
Overlays help shift focus by dimming or masking background content. This kit supports gradient and solid color modes, with adjustable opacity to suit the context.
import React from 'react' import { Overlay, Table } from 'playbook-ui' const TableExample = () => { return ( <Table size="sm"> <thead> <tr> <th>{'Column 1'}</th> <th>{'Column 2'}</th> <th>{'Column 3'}</th> <th>{'Column 4'}</th> <th>{'Column 5'}</th> </tr> </thead> <tbody> {Array.from({ length: 7 }, (_, index) => ( <tr key={index}> {Array.from({ length: 5 }, (_, columnIndex) => ( <td key={columnIndex}>{`Value ${columnIndex + 1}`}</td> ))} </tr> ))} </tbody> </Table> ) } const OverlayDefault = () => ( <> <Overlay> <TableExample /> </Overlay> </> ) export default OverlayDefault
By default, the overlay is rendered as a gradient. Setting the gradient
prop to false
renders the overlay as a solid color. You can adjust the transparency of the solid overlay by using the opacity
prop.
import React from 'react' import { Overlay, Image, Flex } from 'playbook-ui' const OverlayGradientOpacity = () => ( <Flex justify="around" wrap > <Overlay gradient={false} marginBottom="xxs" opacity="opacity_2" > <Image alt="picture of a misty forest" display="block" maxWidth="100%" url="https://unsplash.it/500/400/?image=634" /> </Overlay> <Overlay gradient={false} marginBottom="xxs" opacity="opacity_8" > <Image alt="picture of a misty forest" display="block" maxWidth="100%" url="https://unsplash.it/500/400/?image=634" /> </Overlay> </Flex> ) export default OverlayGradientOpacity
The color
prop is used to change the color of the solid or gradient mask. Gradient overlays always start opaque and fade to transparent.
NOTE: Images are set to display: block
to remove the default inline spacing caused by line height. This ensures the image fully fills the container without unexpected gaps.
import React from 'react' import { Overlay, Image, Flex } from 'playbook-ui' const OverlayColor = () => ( <Flex justify="around" wrap > <Overlay color="black" marginBottom="xxs" > <Image alt="picture of a misty forest" display="block" size="xl" url="https://unsplash.it/500/400/?image=634" /> </Overlay> <Overlay color="black" gradient={false} marginBottom="xxs" opacity="opacity_4" > <Image alt="picture of a misty forest" display="block" size="xl" url="https://unsplash.it/500/400/?image=634" /> </Overlay> <Overlay color="error" marginBottom="xxs" > <Image alt="picture of a misty forest" display="block" size="xl" url="https://unsplash.it/500/400/?image=634" /> </Overlay> <Overlay color="error" gradient={false} marginBottom="xxs" opacity="opacity_4" > <Image alt="picture of a misty forest" display="block" size="xl" url="https://unsplash.it/500/400/?image=634" /> </Overlay> </Flex> ) export default OverlayColor
The optional layout
prop accepts the position
and size
of the overlay as a key:value pair.
The position
key accepts bottom
(default), top
, y
(for both top and bottom) right
, left
, or x
(for both left and right), which sets the side(s) where the color
overlay starts. The direction of the overlay is always toward the opposite side of the position. For example, the default position of bottom
starts the overlay on the bottom edge of your container and extends it toward the opposite side: the top.
The size
value is full
(100%) by default, but accepts our spacing tokens or a percentage value as a string, and literally translates to how much of the container is covered by the overlay(s).
import React from 'react' import { Overlay, Table } from 'playbook-ui' const TableExample = () => { return ( <Table size="sm"> <thead> <tr> <th>{'Column 1'}</th> <th>{'Column 2'}</th> <th>{'Column 3'}</th> <th>{'Column 4'}</th> <th>{'Column 5'}</th> </tr> </thead> <tbody> {Array.from({ length: 7 }, (_, index) => ( <tr key={index}> {Array.from({ length: 5 }, (_, columnIndex) => ( <td key={columnIndex}>{`Value ${columnIndex + 1}`}</td> ))} </tr> ))} </tbody> </Table> ) } const OverlayLayout = () => ( <> <Overlay layout={{ y: "xl" }}> <TableExample /> </Overlay> </> ) export default OverlayLayout
Optionally, you can pass multi-directional options (x
or y
) to the position
key, which creates multiple overlays.
Your color
is still applied as the starting edge to both overlays, and each mask will fade to transparent moving toward its opposite edge, ending at the size
value you set.
NOTE: Multi-directional overlays share the available container space, so passing full
or a percentage string greater than 50% to a multi-directional overlay will cause your masks to overlap at the midline of your container. As a best practice, we do not recommend exceeding a percentage size of 25% when using multi-directional overlays.
import React from 'react' import { Overlay, Card, Flex, FlexItem } from 'playbook-ui' const InlineCardsExample = () => { return ( <Flex columnGap="lg" orientation="row" overflowX="auto" > {Array.from({ length: 15 }, (_, index) => ( <FlexItem key={index}> <Card>{"Card Content"}</Card> </FlexItem> ))} </Flex> ) } const OverlayMultiDirectional = () => ( <> <Overlay color="card_light" layout={{"x": "xl"}} > <InlineCardsExample /> </Overlay> </> ) export default OverlayMultiDirectional
Pass the dynamic
prop to make the overlay render while the scrollbar isn't at either end on the scrollbar.
import React, { forwardRef } from 'react' import { Overlay, Card, Flex, FlexItem } from 'playbook-ui' const InlineCardsExample = forwardRef(function InlineCardsExample(ref) { return ( <Flex columnGap="lg" orientation="row" ref={ref} > {Array.from({ length: 15 }, (_, index) => ( <FlexItem key={index}> <Card>{"Card Content"}</Card> </FlexItem> ))} </Flex> ) }) const OverlayVerticalDynamicMultiDirectional = () => ( <> <Overlay color="card_light" dynamic layout={{"x": "xl"}} > <InlineCardsExample /> </Overlay> </> ) export default OverlayVerticalDynamicMultiDirectional
To toggle an overlay, add a button with an event handler. Remove the overlay container to reveal the underlying content. Re-wrap the overlay container to add the overlay back.
/* eslint-disable react/no-multi-comp */ import React, { useState } from "react"; import { Overlay, Button, Table } from 'playbook-ui' const TableExample = () => { return ( <Table size="sm"> <thead> <tr> <th>{"Column 1"}</th> <th>{"Column 2"}</th> <th>{"Column 3"}</th> <th>{"Column 4"}</th> <th>{"Column 5"}</th> </tr> </thead> <tbody> {Array.from({ length: 7 }, (_, index) => ( <tr key={index}> {Array.from({ length: 5 }, (_, columnIndex) => ( <td key={columnIndex}>{`Value ${columnIndex + 1}`}</td> ))} </tr> ))} </tbody> </Table> ); }; const OverlayToggle = () => { const [showOverlay, setShowOverlay] = useState(true); return ( <> {showOverlay ? ( <> <Overlay overflow="hidden"> <div style={{ height: 200 }}> <TableExample /> </div> </Overlay> <Button fullWidth icon="chevron-down" iconRight key="chevron-down" onClick={() => setShowOverlay(false)} text="Show More" variant="link" /> </> ) : ( <> <TableExample /> <Button fullWidth icon="chevron-up" iconRight key="chevron-up" onClick={() => setShowOverlay(true)} text="Show Less" variant="link" /> </> )} </> ); }; export default OverlayToggle;
Pass the scrollBarNone
prop to hide the scrollbar from view. This is particularly helpful for small containers where the scrollbar may occupy too much space.
import React from 'react' import { Overlay, Card, Flex, FlexItem } from 'playbook-ui' const InlineCardsExample = () => { return ( <Flex columnGap="lg" orientation="row" overflowX="auto" > {Array.from({ length: 15 }, (_, index) => ( <FlexItem key={index}> <Card>{"Card Content"}</Card> </FlexItem> ))} </Flex> ) } const OverlayHideScrollBar = () => ( <> <Overlay color="card_light" layout={{"x": "xl"}} scrollBarNone > <InlineCardsExample /> </Overlay> </> ) export default OverlayHideScrollBar
To enable the overlay to cover the full size of your screen, you can pass the fullScreen
prop. You can also pass an opacity along with it.
import React, { useState } from 'react' import { Overlay, Button, FixedConfirmationToast } from 'playbook-ui' const OverlayFullscreenOpacity = () => { const [openOpacity40, setOpenOpacity40] = useState(false) const [openOpacity80, setOpenOpacity80] = useState(false) const handleClickOpacity40 = () => { setOpenOpacity40(true) } const handleCloseOpacity40 = () => { setOpenOpacity40(false) } const handleClickOpacity80 = () => { setOpenOpacity80(true) } const handleCloseOpacity80 = () => { setOpenOpacity80(false) } return ( <> <div> <Button onClick={handleClickOpacity40} text="40% Opacity" variant="secondary" /> {' '} <Button onClick={handleClickOpacity80} text="80% Opacity" variant="secondary" /> {openOpacity40 && ( <Overlay fullScreen gradient={false} opacity="opacity_4" > <FixedConfirmationToast closeable horizontal='center' onClose={handleCloseOpacity40} open={openOpacity40} status="tip" text='Fullscreen Overlay at 40% Opacity.' vertical='top' /> </Overlay> )} {openOpacity80 && ( <Overlay fullScreen gradient={false} opacity="opacity_8" > <FixedConfirmationToast closeable display="block" horizontal='center' onClose={handleCloseOpacity80} open={openOpacity80} status="tip" text='Fullscreen Overlay at 80% Opacity.' vertical='top' /> </Overlay> )} </div> </> ) } export default OverlayFullscreenOpacity
The fullScreen
prop also allows you to use color
along with it.
import React, { useState } from 'react' import { Overlay, Button, FixedConfirmationToast } from 'playbook-ui' const OverlayFullscreenBackground = () => { const [openBackground, setOpenBackground] = useState(false) const handleClickBackground = () => { setOpenBackground(true) } const handleCloseBackground = () => { setOpenBackground(false) } return ( <> <div> <Button onClick={handleClickBackground} text="Background Dark" variant="secondary" /> {openBackground && ( <Overlay color="bg_dark" fullScreen gradient={false} opacity="opacity_4" > <FixedConfirmationToast closeable horizontal='center' onClose={handleCloseBackground} open={openBackground} status="tip" text='Fullscreen Overlay with color set to Background Dark.' vertical='top' /> </Overlay> )} </div> </> ) } export default OverlayFullscreenBackground
The Draggable kit gives you a full subcomponent structure that allows it to be used with almost any kits.
DraggableProvider
= This provider manages all settings that allows drag and drop to function and must be used as the outermost wrapper. It has 2 REQUIRED props: initialItems
(initial data) and onReorder
(function that returns mutated data as items are reordered via drag and drop). Devs must manage state as shown.
Draggable.Container
= This specifies the container within which items can be dropped.
Draggable.Item
= This specifies the items that can be dragged and dropped. dragId
is a REQUIRED prop for Draggable.Item.
import React, { useState } from "react"; import { Flex, Image, Draggable, DraggableProvider } from 'playbook-ui' // Initial items to be dragged const data = [ { id: "21", url: "https://unsplash.it/500/400/?image=633", }, { id: "22", url: "https://unsplash.it/500/400/?image=634", }, { id: "23", url: "https://unsplash.it/500/400/?image=637", }, ]; const DraggableDefault = (props) => { const [initialState, setInitialState] = useState(data); return ( <> <DraggableProvider initialItems={data} onReorder={(items) => setInitialState(items)} > <Draggable.Container> <Flex> {initialState.map(({ id, url }) => ( <Draggable.Item dragId={id} key={id} > <Image alt={id} margin="xs" size="md" url={url} /> </Draggable.Item> ))} </Flex> </Draggable.Container> </DraggableProvider> </> ); }; export default DraggableDefault;
For a simplified version of the Draggable API for the List kit, you can do the following:
Use DraggableProvider
and manage state as shown.
The List kit is optimized to work with the draggable kit. To enable drag, use the enableDrag
prop on List kit AND dragId
prop on ListItem. An additional optional boolean prop (set to true by default) of dragHandle
is also available on List kit to show the drag handle icon.
import React, { useState } from "react"; import { DraggableProvider, List, ListItem } from 'playbook-ui' // Initial items to be dragged const data = [ { id: "31", text: "Philadelphia", }, { id: "32", text: "New Jersey", }, { id: "33", text: "Maryland", }, { id: "34", text: "Connecticut", }, ]; const DraggableWithList = (props) => { const [initialState, setInitialState] = useState(data); return ( <> <DraggableProvider initialItems={data} onReorder={(items) => setInitialState(items)} > <List enableDrag > {initialState.map(({ id, text }) => ( <ListItem dragId={id} key={id} > {text} </ListItem> ))} </List> </DraggableProvider> </> ); }; export default DraggableWithList;
For a simplified version of the Draggable API for the SelectableList kit, you can do the following:
Use DraggableProvider
and manage state as shown.
The SelectableList kit is optimized to work with the draggable kit. To enable drag, use the enableDrag
prop on SelectableList kit AND dragId
prop on SelectableList.Item. An additional optional boolean prop (set to true by default) of dragHandle
is also available on SelectableList kit to show the drag handle icon.
import React, { useState } from "react"; import { SelectableList, DraggableProvider } from 'playbook-ui' // Initial items to be dragged const data = [ { id: "41", text: "Task 1", }, { id: "42", text: "Task 2", }, { id: "43", text: "Task 3", }, { id: "44", text: "Task 4", }, ]; const DraggableWithSelectableList = (props) => { const [initialState, setInitialState] = useState(data); return ( <> <DraggableProvider initialItems={data} onReorder={(items) => setInitialState(items)} > <SelectableList enableDrag variant="radio" > {initialState.map(({ id, text }) => ( <SelectableList.Item dragId={id} key={id} label={text} name="radio-test" value={id} /> ))} </SelectableList> </DraggableProvider> </> ); }; export default DraggableWithSelectableList
For a simplified version of the Draggable API for the Card kit, you can do the following:
Use DraggableProvider
and manage state as shown.
Draggable.Container
creates the container within which the cards can be dragged and dropped.
The Card kit is optimized to work with the draggable kit. To enable drag, use the draggableItem
and dragId
props on the Card kit as shown. An additional optional boolean prop (set to true by default) of dragHandle
is also available to show the drag handle icon.
import React, { useState } from "react"; import { Flex, Draggable, DraggableProvider, Badge, Title, Icon, Caption, Card } from 'playbook-ui' // Initial items to be dragged const data = [ { id: "21", text: "Joe Black", }, { id: "22", text: "Nancy White", }, { id: "23", text: "Bill Green", }, ]; const DraggableWithCards = (props) => { const [initialState, setInitialState] = useState(data); return ( <DraggableProvider initialItems={data} onReorder={(items) => setInitialState(items)} > <Draggable.Container > {initialState.map(({ id, text }) => ( <Card dragId={id} draggableItem highlight={{ color: "primary", position: "side" }} key={id} marginBottom="xs" padding="xs" > <Flex alignItems="stretch" flexDirection="column" > <Flex gap="xs"> <Title size={4} text={text} /> <Badge text="35-12345" variant="primary" /> </Flex> <Caption size="xs" text="8:00A • Township Name • 90210" /> <Flex gap="xxs" spacing="between" > <Flex gap="xxs"> <Caption color="error" size="xs" > <Icon icon="house-circle-exclamation" /> </Caption> <Caption color="success" size="xs"> <Icon icon="file-circle-check" /> </Caption> </Flex> <Flex> <Badge rounded text="Schedule QA" variant="warning" /> <Badge rounded text="Flex" variant="primary" /> <Badge rounded text="R99" variant="primary" /> </Flex> </Flex> </Flex> </Card> ))} </Draggable.Container> </DraggableProvider> ); }; export default DraggableWithCards;
The draggable kit can also be used in conjunction with the table kit to create draggable table rows. To do this:
DraggableProvider
and manage state as shown. draggableContainer
prop on the Table.Body to designate it as the Draggable ContainerdraggableItem
prop on the Table.Row to designate it as the Draggable Item. Make sure to also pass id to the dragId
prop here. We recommending using the default dropZone type
with the Table kit.
import React, { useState } from "react"; import { Flex, DraggableProvider, Avatar, Body, Table } from 'playbook-ui' // Initial items to be dragged const data = [ { id: "1", task: "Task 1", assignee_name: "Terry Miles", assignee_img: "https://randomuser.me/api/portraits/men/44.jpg", }, { id: "2", task: "Task 2", assignee_name: "Sophia Miles", assignee_img: "https://randomuser.me/api/portraits/women/8.jpg", }, { id: "3", task: "Task 3", assignee_name: "Alice Jones", assignee_img: "https://randomuser.me/api/portraits/women/10.jpg", }, { id: "4", task: "Task 4", assignee_name: "Mike James", assignee_img: "https://randomuser.me/api/portraits/men/8.jpg", }, { id: "5", task: "Task 5", assignee_name: "James Guy", assignee_img: "https://randomuser.me/api/portraits/men/18.jpg", } ]; const DraggableWithTableReact = (props) => { const [initialState, setInitialState] = useState(data); return ( <> <DraggableProvider initialItems={data} onReorder={(items) => setInitialState(items)} > <Table responsive="none" size="sm" > <Table.Head> <Table.Row> <Table.Header>{"id"}</Table.Header> <Table.Header>{"name"}</Table.Header> <Table.Header>{"task number"}</Table.Header> </Table.Row> </Table.Head> <Table.Body draggableContainer> {initialState.map(({ id, task, assignee_name, assignee_img }) => ( <Table.Row dragId={id} draggableItem key={id} > <Table.Cell>{id}</Table.Cell> <Table.Cell> <Flex align="center"> <Avatar imageUrl={assignee_img} size="xs" /> <Body paddingLeft="xxs" text={assignee_name} /> </Flex> </Table.Cell> <Table.Cell>{task}</Table.Cell> </Table.Row> ))} </Table.Body> </Table> </DraggableProvider> </> ); }; export default DraggableWithTableReact;
The Draggable kit can also be used to achieve more complex, multiple container functionality as shown here. This complex usage requires the full subcomponent structure.
import React, { useState } from "react"; import { Flex, Draggable, DraggableProvider, Badge, Title, Caption, Card, FlexItem, Avatar, Body } from 'playbook-ui' // Initial groups to drag between const containers = ["To Do", "In Progress", "Done"]; // Initial items to be dragged const data = [ { id: "11", container: "To Do", title: "Task 1", description: "Bug fixes", assignee_name: "Terry Miles", assignee_img: "https://randomuser.me/api/portraits/men/44.jpg", }, { id: "12", container: "To Do", title: "Task 2", description: "Documentation", assignee_name: "Sophia Miles", assignee_img: "https://randomuser.me/api/portraits/women/8.jpg", }, { id: "13", container: "In Progress", title: "Task 3", description: "Add a variant", assignee_name: "Alice Jones", assignee_img: "https://randomuser.me/api/portraits/women/10.jpg", }, { id: "14", container: "To Do", title: "Task 4", description: "Add jest tests", assignee_name: "Mike James", assignee_img: "https://randomuser.me/api/portraits/men/8.jpg", }, { id: "15", container: "Done", title: "Task 5", description: "Alpha testing", assignee_name: "James Guy", assignee_img: "https://randomuser.me/api/portraits/men/18.jpg", }, { id: "16", container: "In Progress", title: "Task 6", description: "Release", assignee_name: "Sally Jones", assignee_img: "https://randomuser.me/api/portraits/women/28.jpg", }, ]; const DraggableMultipleContainer = (props) => { const [initialState, setInitialState] = useState(data); const badgeProperties = (container) => { switch (container) { case "To Do": return { text: "queue", color: "warning" }; case "In Progress": return { text: "progress", color: "primary" }; default: return { text: "done", color: "success" }; } }; return ( <DraggableProvider initialItems={data} onReorder={(items) => setInitialState(items)} > <Flex justifyContent="center" > {containers?.map((container) => ( <Draggable.Container container={container} htmlOptions={{style:{ width: "200px", height: "70vh"}}} key={container} padding="sm" > <Caption textAlign="center">{container}</Caption> <Flex alignItems="stretch" orientation="column" > {initialState .filter((item) => item.container === container) .map( ({ assignee_img, assignee_name, description, id, title, }) => ( <Draggable.Item container={container} dragId={id} key={id} > <Card marginBottom="sm" padding="sm" > <Flex justify="between"> <FlexItem> <Flex> <Avatar imageUrl={assignee_img} name={assignee_name} size="xxs" /> <Title paddingLeft="xs" size={4} text={title} /> </Flex> </FlexItem> <Badge marginLeft="sm" rounded text={badgeProperties(container).text} variant={badgeProperties(container).color} /> </Flex> <Body paddingTop="xs" text={description} /> </Card> </Draggable.Item> ) )} </Flex> </Draggable.Container> ))} </Flex> </DraggableProvider> ); }; export default DraggableMultipleContainer;
The Draggable kit lets you customize the style of drop zones that appear when dragging an item.
By default, drop zones are in the "ghost" style, but you can also choose from "shadow," "outline," and "line."
When using the "line" type, make sure to set the appropriate direction
attribute within the dropZone
prop based on the orientation of your draggable view. By default, this is set to "vertical," but it can also be adjusted to "horizontal." Note that the direction attribute only applies to the "line" type and does not affect other drop zone styles. For more on the "line" style in particular, check out the Draggable Drop Zones Line doc example.
import React, { useState } from "react"; import { Body, Flex, FlexItem, Card, Caption, Draggable, DraggableProvider } from 'playbook-ui' // Initial items to be dragged const dataShadow = [ { id: "51", text: "Task 1", }, { id: "52", text: "Task 2", }, { id: "53", text: "Task 3", }, ]; const dataOutline = [ { id: "61", text: "Task 1", }, { id: "62", text: "Task 2", }, { id: "63", text: "Task 3", }, ]; const dataLine = [ { id: "71", text: "Task 1", }, { id: "72", text: "Task 2", }, { id: "73", text: "Task 3", }, ]; const DraggableDropZones = (props) => { const [initialShadowState, setInitialShadowState] = useState(dataShadow); const [initialOutlineState, setInitialOutlineState] = useState(dataOutline); const [initialLineState, setInitialLineState] = useState(dataLine); return ( <> <Flex justify="between" > <FlexItem marginRight="xl"> <DraggableProvider dropZone={{type: "shadow"}} initialItems={dataShadow} onReorder={(items) => setInitialShadowState(items)} > <Caption marginBottom="xs" text="Shadow" textAlign="center" /> <Draggable.Container htmlOptions={{style:{ width: "200px"}}} > {initialShadowState.map(({ id, text }) => ( <Card dragId={id} draggableItem key={id} marginBottom="xs" padding="xs" > <Flex alignItems="stretch" flexDirection="column" > <Body text={text} /> </Flex> </Card> ))} </Draggable.Container> </DraggableProvider> </FlexItem> <FlexItem marginRight="xl"> <DraggableProvider dropZone={{type: "outline"}} initialItems={dataOutline} onReorder={(items) => setInitialOutlineState(items)} > <Caption marginBottom="xs" text="Outline" textAlign="center" /> <Draggable.Container htmlOptions={{style:{ width: "200px"}}} > {initialOutlineState.map(({ id, text }) => ( <Card dragId={id} draggableItem key={id} marginBottom="xs" padding="xs" > <Flex alignItems="stretch" flexDirection="column" > <Body text={text} /> </Flex> </Card> ))} </Draggable.Container> </DraggableProvider> </FlexItem> <FlexItem> <DraggableProvider dropZone={{type: "line"}} initialItems={dataLine} onReorder={(items) => setInitialLineState(items)} > <Caption marginBottom="xs" text="Line" textAlign="center" /> <Draggable.Container htmlOptions={{style:{ width: "200px"}}} > {initialLineState.map(({ id, text }) => ( <Card dragId={id} draggableItem key={id} marginBottom="xs" padding="xs" > <Flex alignItems="stretch" flexDirection="column" > <Body text={text} /> </Flex> </Card> ))} </Draggable.Container> </DraggableProvider> </FlexItem> </Flex> </> ); }; export default DraggableDropZones;
The default color
for Draggable kit drop zones is "neutral", with "primary" or "purple" as additional options. When type
is set to "line", the default color is "primary" and "purple" is the only other option.
import React, { useState } from "react"; import { Flex, Image, Caption, Draggable, DraggableProvider } from 'playbook-ui' // Initial items to be dragged const dataPrimary = [ { id: "81", url: "https://unsplash.it/500/400/?image=633", }, { id: "82", url: "https://unsplash.it/500/400/?image=634", }, { id: "83", url: "https://unsplash.it/500/400/?image=637", }, ]; const dataPurple = [ { id: "91", url: "https://unsplash.it/500/400/?image=633", }, { id: "92", url: "https://unsplash.it/500/400/?image=634", }, { id: "93", url: "https://unsplash.it/500/400/?image=637", }, ]; const DraggableDropZonesColors = (props) => { const [initialPrimaryState, setInitialPrimaryState] = useState(dataPrimary); const [initialPurpleState, setInitialPurpleState] = useState(dataPurple); return ( <> <Caption marginBottom="xs" text="Primary" /> <DraggableProvider dropZone={{type: "shadow", color: "primary"}} initialItems={dataPrimary} onReorder={(items) => setInitialPrimaryState(items)} > <Draggable.Container> <Flex> {initialPrimaryState.map(({ id, url }) => ( <Draggable.Item dragId={id} key={id} marginRight="sm" > <Image alt={id} size="md" url={url} /> </Draggable.Item> ))} </Flex> </Draggable.Container> </DraggableProvider> <Caption marginBottom="xs" text="Purple" /> <DraggableProvider dropZone={{type: "outline", color: "purple"}} initialItems={dataPurple} onReorder={(items) => setInitialPurpleState(items)} > <Draggable.Container> <Flex> {initialPurpleState.map(({ id, url }) => ( <Draggable.Item dragId={id} key={id} marginRight="sm" > <Image alt={id} size="md" url={url} /> </Draggable.Item> ))} </Flex> </Draggable.Container> </DraggableProvider> </> ); }; export default DraggableDropZonesColors;
When using the "line" style, make sure to set the appropriate direction
attribute within the dropZone
prop based on the orientation of your draggable view. By default, this is set to "vertical," but it can also be adjusted to "horizontal." Note that the direction attribute only applies to the "line" style and does not affect other drop zone styles. The default color
for "line" is "primary" and "purple" is the only alternative color option.
The length of the line is calculated based off of the width (for "vertical") or height (for "horizontal") of the parent container holding the draggable items.
Additionally, if the parent container of the DraggableProvider
/DraggableContainer
(or a subcontainer within) does not have a set height (for "vertical") or width (for "horizontal"), like the Draggable Drop Zones doc example does, elements on the page may jump up (for "vertical") or to the left (for "horizontal") when an item is actively being dragged. To prevent this, give a parent element a fixed height (for "vertical") or width (for "horizontal") as demonstrated in this doc example.
import React, { useState } from "react"; import { Flex, Caption, Draggable, DraggableProvider, Image } from 'playbook-ui' const dataLineVertical = [ { id: "211", url: "https://unsplash.it/500/400/?image=633", }, { id: "212", url: "https://unsplash.it/500/400/?image=634", }, { id: "213", url: "https://unsplash.it/500/400/?image=637", }, ]; const dataLineHorizontal = [ { id: "2111", url: "https://unsplash.it/500/400/?image=633", }, { id: "2122", url: "https://unsplash.it/500/400/?image=634", }, { id: "2133", url: "https://unsplash.it/500/400/?image=637", }, ]; const DraggableDropZones = (props) => { const [initialLineVerticalState, setInitialLineVerticalState] = useState(dataLineVertical); const [initialLineHorizontalState, setInitialLineHorizontalState] = useState(dataLineHorizontal); return ( <> <Caption marginBottom="xs" marginTop="xl" text="Vertical" /> <DraggableProvider dropZone={{ type: "line", color: "purple" }} initialItems={dataLineVertical} onReorder={(items) => setInitialLineVerticalState(items)} > <Draggable.Container> <Flex flexDirection="column" height="367px" > {initialLineVerticalState.map(({ id, url }) => ( <Draggable.Item dragId={id} key={id} marginBottom="sm" > <Image alt={id} size="md" url={url} /> </Draggable.Item> ))} </Flex> </Draggable.Container> </DraggableProvider> <Caption marginBottom="xs" marginTop="xl" text="Horizontal" /> <Flex> <DraggableProvider dropZone={{ type: "line", direction: "horizontal" }} initialItems={dataLineHorizontal} onReorder={(items) => setInitialLineHorizontalState(items)} > <Draggable.Container htmlOptions={{style:{ width: "285px"}}} > <Flex alignItems="stretch" flexDirection="row" height="110px" > {initialLineHorizontalState.map(({ id, url }) => ( <Draggable.Item dragId={id} key={id} marginRight="sm" > <Image alt={id} size="md" url={url} /> </Draggable.Item> ))} </Flex> </Draggable.Container> </DraggableProvider> </Flex> </> ); }; export default DraggableDropZones;
You can add drag event listeners for onDrag
, onDragEnd
, onDragEnter
, onDragLeave
, onDragOver
, onDragStart
, and onDrop
.
import React, { useState } from "react"; import { Flex, Image, Draggable, DraggableProvider } from 'playbook-ui' const data = [ { id: "100", url: "https://unsplash.it/500/400/?image=638", }, { id: "200", url: "https://unsplash.it/500/400/?image=639", }, { id: "300", url: "https://unsplash.it/500/400/?image=640", }, ]; const DraggableDefault = (props) => { const [initialState, setInitialState] = useState(data); return ( <> <DraggableProvider initialItems={data} onReorder={(items) => setInitialState(items)} > <Draggable.Container> <Flex> {initialState.map(({ id, url }) => ( <Draggable.Item dragId={id} key={id} onDrag={() => console.log(`${id} drag!`)} onDragEnd={() => console.log(`${id} drag end!`)} onDragEnter={() => console.log(`${id} drag enter!`)} onDragLeave={() => console.log(`${id} drag leave!`)} onDragOver={() => console.log(`${id} drag over!`)} onDragStart={() => console.log(`${id} drag start!`)} onDrop={() => console.log(`${id} drop!`)} > <Image alt={id} margin="xs" size="md" url={url} /> </Draggable.Item> ))} </Flex> </Draggable.Container> </DraggableProvider> </> ); }; export default DraggableDefault;