Skip to content

mikeyamadeo/react-ditto

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

72 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

react-ditto

Transform layout to take whatever form you please without leaving the render method.

Why I Exist

Layout is it's own beast: When it comes to styling, the thought process around approaching layout is a different one from adding stylistic elements like colors, font, animations, etc. Having a set a primitives around this can allow this thought process to do it's thing.

Constraints ftw: react-ditto has contraints (like spacing values) built into it that help enforce design consistency. Instead of eyeball guessing how much padding is in a design and littering the codebase with differing px and em values, trust the constraints to do the work in order to free your brain and ensure visual consistency.

Never leave the render method: one reason css-in-js is great because you don't have to context switch between your component file and stylesheet. But aren't we still context switching as we scroll between styles and the render method even if it's in the same file? react-ditto enables the reader to know what the component looks like and the writer to make changes without leaving the render method.

Quick L👀ks

Example set 1: Intro to layout or "axis" api by getting our Psyducks in a row

import { Row } from 'react-ditto'

// align psyducks in a row
const Psyducks = () =>
  <Row>
    <Psyduck /> <Psyduck /> <Psyduck /> <Psyduck />
  </Row>

import { Row } from 'react-ditto'

// center the row of psyducks along the x axis
const Psyducks = () =>
  <Row x>
   <Psyduck /> <Psyduck /> <Psyduck /> <Psyduck />
  </Row>

import { Row } from 'react-ditto'

// absolutely center the row of psyducks along both x & y axis
const Psyducks = () =>
  <Row x y>
   <Psyduck /> <Psyduck /> <Psyduck /> <Psyduck />
  </Row>

import { Row } from 'react-ditto'

// center along y axis while placing space _between_ row of psyducks
const Psyducks = () =>
  <Row y space='between'>
   <Psyduck /> <Psyduck /> <Psyduck /> <Psyduck />
  </Row>

import { Row } from 'react-ditto'

// center along y axis while placing space _around_ row of psyducks
const Psyducks = () =>
  <Row y space='around'>
   <Psyduck /> <Psyduck /> <Psyduck /> <Psyduck />
  </Row>

import { Col } from 'react-ditto'

// render psyducks as a column (with space _around_) and center along the x axis
const Psyducks = () =>
  <Col x space='around'>
   <Psyduck /> <Psyduck /> <Psyduck /> <Psyduck />
  </Col>

import { Col } from 'react-ditto'

// render psyducks in a column (with space _around_) and wrap as room requires
const Psyducks = () =>
  <Col space='around' wrap>
   <Psyduck /> <Psyduck /> <Psyduck /> <Psyduck />
  </Col>

Example set 2: Getting a flavor for the spacing api by helping Snorlax protect his candy

First, let's get as far away from Haunter as we can by applying large left margin margin

import { Box } from 'react-ditto'

// apply size level giant (++) margin to the left
const SnorlaxAndCandy = () =>
  <Box ml='++'>
   <Snorlax />
   <Candy />
  </Box>

Now we'll give Snorlax some breathing room from Zapdos and Sandslash by applying top and bottom padding

import { Box } from 'react-ditto'

// apply size level 3 (scale from 0-5) amount of padding to top (pt) and bottom (pb)
const SnorlaxAndCandy = () =>
  <Box x pt='+' pb='+'>
   <Snorlax />
   <Candy />
  </Box>

Finally, ever use the padding shorthand to apply it only vertically or horizonally (e.g. padding: 10px 0)? You can do similarly here. Let's apply this snorlax's vertical padding via shorthand:

import { Row } from 'react-ditto'

// apply padding along the 'y' axis
const SnorlaxAndCandy = () =>
  <Row py='+'>
   <Snorlax />
   <Candy />
  </Row>

This shorthand works for both margin and padding.

Example set 3: Putting it all together

Let's say we want to render our pokemon go team:

PokemonListUI

import React from 'react'
import { render } from 'react-dom'
import { Box, Row, Col } from 'react-ditto'
import { pokemon } from './examples/data'

const HealthBar = ({percentHealth}) =>
  <Box width='100%' height='6px'>
    <Box width={`${percentHealth}%`} height='100%'
      css={{backgroundColor: percentHealth < 25
        ? '#d34f4f' // red
        : percentHealth < 50
        ? '#f4d554' // yellow
        : '#6deeb6' // green
      }} />
  </Box>

const PokemonList = ({pokemon}) =>
  <Row wrap space='between' px tag='ul' maxWidth='380px'>
    {pokemon.map(p =>
      <Col x px='-' my tag='li' >
        <h2>cp { p.cp }</h2>
        <img src={ p.img } height='90px' />
        <Box tag='h4' mb1>{ p.name }</Box>
        <HealthBar percentHealth={ (p.health / p.maxHealth) * 100 } />
      </Col>
    )}
  </Row>

render(<PokemonList pokemon={pokemon} />, document.getElementById('root'))

API

react-ditto is now built on top of glamorous to use its jsxstyle inspired api.

So in addition to react-ditto's layout shorthand... you can use glamorous goodness

import { Row } from 'react-ditto'

const DittoAndGlamorous = () => 
  <Box x y pt height='50em' color='blue' css={{':hover': { color: 'green' }}>
    I am absolutely centered with top padding. Green when hovered over, and blue when not.
  </Box>
const api = {

  // layout api
  x: axisPropTypes,
  y: axisPropTypes,
  space: PropTypes.oneOf([
    'between',  // |x  x  x|
    'around'    // | x x x |
  ]),
  start: PropTypes.oneOf([
    'end'       // |      X|
  ]),
  wrap: ProptTypes.oneOf([
    false,      // squish all chilrdren to fit space
    true,       // overflow children underneath
    'reverse'   // overflow children above
  ]),
  reverse: PropTypes.onOf({
    true,
    false
  })

  // spacing api
  p: spacingPropTypes,       // padding
  pt: spacingPropTypes,      // padding top
  pr: spacingPropTypes,      // padding right
  pb: spacingPropTypes,      // padding bottom
  pl: spacingPropTypes,      // padding left
  px: spacingPropTypes,      // horizontal padding
  py: spacingPropTypes,      // vertical padding

  m: spacingPropTypes,       // margin
  mt: spacingPropTypes,      // margin top
  mr: spacingPropTypes,      // margin right
  mb: spacingPropTypes,      // margin bottom
  ml: spacingPropTypes,      // margin left
  mx: spacingPropTypes,      // horizontal margin
  my: spacingPropTypes,      // vertical margin

  // sizing api
  size: sizingPropTypes,

  height: sizingPropTypes,
  maxHeight: sizingPropTypes,
  minHeight: sizingPropTypes,

  width: sizingPropTypes,
  maxWidth: sizingPropTypes,
  minWidth sizingPropTypes,

}

const spacingPropTypes = PropTypes.oneOf([
  0, '0',       // none
  '--',         // tiny
  '-',          // small
  true,         // standard
  '+',          // big
  '++'          // giant
])

const axisPropTypes = PropTypes.oneOf([
  false,        // (Default) place at "start" of given axis (far left [x] or top [y])
  true,         // center across given axis
  'end'        // place at "end" of given axis (far right [x] or bottom [y])
])

const sizingPropTypes = PropTypes.string

Configuration

By default react-ditto has a base space value of 6px and the scale is based on fibonacci resulting in:

{
  '--': '6px',
  '-': '12px',
  '': '18px',
  '+': '30px',
  '++': '48px'
}

You can configure your own thusly:

// Layout.js

import { cloneNewDitto } from 'react-ditto'

const Layout = cloneNewDitto({
  baseSpace: 8
})

export const Box = Layout.Box
export const Row = Layout.Row
export const Col = Layout.Col

resulting in the following spacing values:

{
  '--': '8px',
  '-': '16px',
  '': '24px',
  '+': '40px',
  '++': '64px'
}

If you're looking for further configuration (ex: don't like the -, --, +, ++ api for spacing?), open an issue and we'll see about getting you taken care of.

About

Component layout and spacing utility for rendering UI with react

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors