Component

Flexible Layout

The only pattern you need to boost UI development. These are components that abstract flexbox model and turn it into intuitive interface with sufficient props.

Let’s see some example. we will start with simple ui, I will call it BasicProfile. It has Avatar and 2 Typography.

image

Here is the code I built it from scratch

import Avatar from '@material-ui/core/Avatar'
import { makeStyles } from '@material-ui/core/styles'

const useBasicProfileStyles = makeStyles({
   root: {     display: 'flex',     alignItems: 'center',   },   info: {     marginRight: 12,   },   avatar: {
     borderRadius: 8,
     backgroundColor: '#495869'
   },
   overline: {
     fontSize: 10,
     textTransform: 'uppercase',
     letterSpacing: 1,
     color: '#8D9CAD',
   },
   name: {
     fontSize: 14,
     fontWeight: 500,
     color: '#495869',
   }
 })

const BasicProfile = () => {
  const styles = useBasicProfileStyles()
  return (
    <div className={styles.root}>
      <Avatar className={styles.avatar}>S</Avatar>
      <div className={styles.info}>
        <Typography className={styles.overline}>
          CREATOR
        </Typography>
        <Typography className={styles.name}>
          siriwatknp
        </Typography>
      </div>
    </div>
  )
}

Building ui like this one time in your life is okay, but the second time? I don’t think so, because you will need to create div and specify it as flex, add alignItems: center to it and also the worst part, assign marginLeft or marginRight to create gap between flex item. 😤

That’s enough. Let’s do it one more time with Row & Item.

import { Row, Item } from '@mui-treasury/components/flex'

const BasicProfile = props => {
  // same styles
  const styles = useBasicProfileStyles()
  return (
    <Row gap={1.5} {...props}>
      <Avatar className={styles.avatar}>S</Avatar>
      <Item position={'middle'}>
        <Typography className={styles.overline}>
          CREATOR
        </Typography>
        <Typography className={styles.name}>
          siriwatknp
        </Typography>
      </Item>
    </Row>
  )
}

Row is flex by default with flex-direction: row, it can accept gap props to specify gap between its children. 1.5 is unit related to material-ui spacing spec, but you can also use string like 1rem.

For Item, it is a simple div with some props that works with flexbox, one of them is position (not css position). When you view the design, you can tell without having css knowledge which position you want to place the item. I want that experience when using this component, that’s why all you need to do is specify the position of the item and it will take care of the rest.

image

In this case, I want the Item that wrap 2 typography to stay in the middle of this Row.

Let’s make something more fancy.

image

As you can see on the right hand-side of the picture, it looks like a Column layout rather than a Row. Let’s see the code.

import { Column, Item } from '@mui-treasury/components/flex'

const Card = () => (
  <Column className={styles.card} gap={1.5}>
    <Item>Card Header</Item>
    <Item>
      <Box minHeight={200} bgcolor={'#F4F7FA'} borderRadius={8}>
  
      </Box>
    </Item>
    <Item>Basic Profile</Item>  </Column>
)

Replace <Item>Basic Profile</Item> with BasicProfile that we have earlier.

import { Row, Column, Item } from '@mui-treasury/components/flex'

const Card = () => (
  <Column className={styles.card} gap={1.5}>
    <Item>Card Header</Item>
    <Item>
      <Box minHeight={200} bgcolor={'#F4F7FA'} borderRadius={8}>
  
      </Box>
    </Item>
    <Row gap={'inherit'} {...props}>      <Avatar className={styles.avatar}>S</Avatar>      <Item position={'middle'}>        <Typography className={styles.overline}>          CREATOR        </Typography>        <Typography className={styles.name}>          siriwatknp        </Typography>      </Item>    </Row>  </Column>
)

gap can be inherit from the nearest Row or Column. By saying inherit, it will apply to their direct Items.

In this example, Column ==gap(1.5)==> Row ==gap(inherit = 1.5)==> Item

Then we can achieve the same thing for CardHeader with this.

import { Row, Column, Item } from '@mui-treasury/components/flex'

const Card = () => (
  <Column className={styles.card} gap={1.5}>
    <Row>      <Item>        <Typography className={styles.title}>          <b>Firebase</b>        </Typography>        <Typography className={styles.subheader}>          Similar to firebase theme        </Typography>      </Item>      <Item position={'right'} mr={-0.5}>        <IconButton>          <CallMade />       </IconButton>      </Item>    </Row>    <Item>
      <Box minHeight={200} bgcolor={'#F4F7FA'} borderRadius={8}>
  
      </Box>
    </Item>
    <Row gap={'inherit'} {...props}>
      <Avatar className={styles.avatar}>S</Avatar>
      <Item position={'middle'}>
        <Typography className={styles.overline}>
          CREATOR
        </Typography>
        <Typography className={styles.name}>
          siriwatknp
        </Typography>
      </Item>
    </Row>
  </Column>
)

Row & Column internally are Item that contain react context inside.

By using this approach, we can swap order to achieve different direction without pain!

image

import { Row, Column, Item } from '@mui-treasury/components/flex'

const Card = () => (
  <Row className={styles.card} gap={1.5}>
    <Item grow>      <Box minHeight={200} bgcolor={'#F4F7FA'} borderRadius={8}>
  
      </Box>
    </Item>
    <Column gap={'inherit'}>
      <Row>
        <Item>
          <Typography className={styles.title}>
            <b>Firebase</b>
         </Typography>
         <Typography className={styles.subheader}>
           Similar to firebase theme
         </Typography>
        </Item>
        <Item position={'right'} mr={-0.5}>
          <IconButton>
            <CallMade />
          </IconButton>
        </Item>
      </Row>
      <Row gap={'inherit'} position={'bottom'}>
        <Avatar className={styles.avatar}>S</Avatar>
        <Item position={'middle'}>
          <Typography className={styles.overline}>
            CREATOR
          </Typography>
          <Typography className={styles.name}>
            siriwatknp
          </Typography>
        </Item>
      </Row>
    </Column>
  </Row>
)

Finally, Row Column & Item accept grow and shrink to stretch or keep size unchanged.