just-box v0.3.0
just-box
Just-Box helps you create universal layouts in your React and React-Native apps. It's based on Daniel Steigerwald idea implemented in este boilerplate. just-box is a less opinionated standalone version with some additions and tweaks.
| web | ios | android |
|---|---|---|
![]() | ![]() | ![]() |
Installation
yarn add just-box
// or
npm install -S just-boxSetup
Before you start creating layouts you have to answer two questions.
pxorremunits as a default.- If you will use
remunit, what is base font size?
Now you have to configure just-box. To do this you will use a special Box called ConfigBox.
WEB
import { ConfigBox } from 'just-box';
import renderer from 'just-box/lib/webRenderer';
const App = ({ children }) => (
<ConfigBox unit="rem" baseSize={16} box="div" text="span" renderer={renderer}>
{children}
</ConfigBox>
)NATIVE
import { ConfigBox } from 'just-box';
import renderer from 'just-box/lib/nativeRenderer';
const App = ({ children }) => (
<ConfigBox unit="rem" baseSize={16} box={View} text={Text} renderer={renderer}>
{children}
</ConfigBox>
)You may have noticed box and text props. These are actual HTML tags / React Components that just-box will use.
You also need a style tag in you document. If you don't want to play with custom mount nodes and stuff just add in a head section of your document:
<style id="stylesheet"></style>What about React Native?
Right. I said
"(…) you create universal layouts (…)"
In fact all you have to do is change box and text props while there are no HTML tags in React Native.
import { View, Text } from 'react-native';
//...
<ConfigBox unit="rem" baseSize={16} box={View} text={Text}>Yes! You can use rem units in react-native.
Usage
Ok, lets talk about Box component.
import { Box } from 'just-box';When you're building new applications you care about two things: layout and styles. just-box will help you with both aspects but it's focused on layout. That's why Box component has ~50 props that you probably use to create layouts. That's why you can write something like:
<Box margin={1} paddingBottom={.5} position="absolute">{/*...*/}</Box>This box will have margin="1rem", padding-bottom=.5rem and position=absolute.
So, for example, to create two boxes in one line you can write:
<Box display="flex" flexDirection="row">
<Box flex={1}>Hello</Box>
<Box flex={1}>World</Box>
</Box>You can find full list of supported props in Box.js file.
How does it works? Every prop will be converted into a CSS class with fela. You don't have to think about it at all. In web classes will be reused. In React Native stuff will work like normal styles.
Styles (inline styles)
Ok, you can set around 50 layout related props but what about styles. Well, there is a style prop but it does not work like a regular style attribute. just-box uses fela to create CSS. I've decided that styles will be converted into css-classes just like other props.
<Box margin={1} style={{ backgroundColor: 'red' }} />Will not generate style attribute. You will get some some classes generated with fela.
But this approach it not good in some cases. For example reactvirtualized must set up some styles to work. But still, those elements are just Boxes. Thats why just-box introduces concept of isotope.
You may remember this word from chemistry.
Isotopes are variants of a particular chemical element which differ in neutron number.
In meme world you will define isotopes with:

With this knowledge:
<Box
margin={1}
padding={Math.random()}
style={{
backgroundColor: 'red',
opacity: Math.random(),
}}
isotope={['padding', 'opacity']}
/>You will get something like:
.a { margin: 1rem }
.b { background-color: red }and
style = {
opacity: 0.234561,
padding: 0.765432,
}There are few things to remember.
styleis more important thanpropsif
keyexists inpropsandstyleit will be removed fromprops<Box padding={1} style={{ padding: 2 }} /> // this will create only // .a { padding: 2rem } // instead of // .a { padding: 1rem } // .b { padding: 2rem }if
keyexists inisotopearray it will be removed frompropsandstyles
Text
There is another component in just-box - Text . But Text is just a Box with some additional props. You can find them in Text.js file. Text is quite Important in case you're creating web + native app. In react-native you always have to wrap string with Text component.
import { Box, Text } from 'just-box';
() => App ({ children }) => (
<Box margin={1}>
<Text fontSize={1} color="blue" padding={.5}>Hello</Text>
</Box>
)Units
You can user rem or px as a default unit. But there are cases where px are required.
<Box borderWidth={1} {...props} />If your default unit is rem you will get 16px border. What should yo do?
Web + Native solution
You can use unit function.
import { unit } from 'just-box';
// default unit is `rem` & baseSize is 16
const i = unit(1)Now what can you do with i.
i.px will return 1px in web and 1 (number) in native
i.rem will return 1rem in web and 16 (number) in native
i.v will return 1(number) in web and 1(number) in native
So in case you're using rem and you want 1px you can write:
<Box borderWidth={unit(1).px} {...props} />Web solution
Just write 1px as a string and you're all set.
Platform specific styles
We would like universal components, but there are style implementations that not the same. In react native we have marginVertical or paddingHorizontal. There is this display CSS rulethat is not supported in native.
just-box has simple utility for that. It converts, omit, or change platform specific rules (web -> native and native -> web). It's not perfect, and quite small, but good for a start.
You can always deal with these types of styles on your own.
// Button.js
export default ({ children }) => (
<Box paddingHorizontal={1}>{children}</Box>
)
// Button.web.js
export default ({ children }) => (
<Button paddingLeft={1} paddingRight={1}>{children}</Button>
)Custom Box ,as prop
In case you want to use a custom component as a Box (or Text) you can use as prop. It accepts string or Component. All you have to do is accept className and style prop from Box component.
<Box as="section" padding={1}>Hello</Box>
<Text as={MegaText}>Hello</Text>FlexBox
FlexBox is cool. So I decided to add FlexBox component into just-box. It works just like nomal Box but it has some extra props. You will find all of them in FlexBox.js file.
<ConfigBox unit="rem" baseSize={16} box="div" text="span">
<FlexBox row>
<FlexBox f1 column>
<FlexBox justifyEnd>just</FlexBox>
<FlexBox padding={1}>box</FlexBox>
</FlexBox>
<FlexBox f2>World</FlexBox>
<FlexBox f1>!</FlexBox>
</FlexBox>
</ConfigBox>f1 and f2 are just shortcuts for flex=1 and flex=2. You have also f3 and f4.
ConfigBox
Lets back to ConfigBox. Here are all the props you can set:
unit - rem or px. rem by default
baseSize - default 16
box - Box component. In 99% of cases should be "div" in web and View in Native.
text - Text component. In 99% of cases should be "span" in web and Text in Native.
defaultBoxStyles - you can provide some default styles for all Boxes (but not Text). It might be useful to mimic React-Native default styles:
const styles = {
display: 'flex',
position: 'relative',
flexDirection: 'column',
};defaultTextstyles - ^ but for Text
renderer - custom fela rendered object. By default just-box uses fela with two plugins fela-plugin-prefixer and fela-plugin-fallback-value. You can also import defaultFelaRenderer from 'just-box' in your app to set up, for example server-side rendering. After that just pass it with this prop.
getFelaMountNode - valid only for Web. Fela has to render styles somewhere. So it requires a style tag. You can provide a custom function for that.


