raam (estonian) ˈrɑːm n. frame.
Beautifully boring cosmetic-free React.js components for structure and layout.
Use raam's layout primitives to build resilient theme-driven designs fast.
A Flex-based layout that renders and 'wraps' children inline spaced
by the defined gap
.
Here gap
is accessing the value from theme.space[3]
.
// import { Wrap } from "raam";
// import { Box } from "your-components";
<Wrap gap={3}>
{Array.from({ length: 32 }).map((item, i) => (
<Box
key={i}
sx={{
width: "2rem",
height: "2rem",
backgroundColor: "primary",
filter: i > 0 && `hue-rotate(${i * 2}deg)`,
}}
/>
))}
</Wrap>
As the gap
prop is powered by Styled System, you have the ability to create responsive styles.
Here gap
is accessing the value from theme.space[3]
, then
theme.space[4]
at breakpoint[1]
etc.
// import { Wrap } from "raam";
// import { Box } from "your-components";
<Wrap gap={[2, 3, 4]}>
{Array.from({ length: 32 }).map((item, i) => (
<Box
key={i}
sx={{
width: "2rem",
height: "2rem",
backgroundColor: "primary",
filter: i > 0 && `hue-rotate(${i * 2}deg)`,
}}
/>
))}
</Wrap>
Let's take a look at a more real-world example; a "tag"-list at the bottom of an article:
Stack
, not the Wrap
directly.Wrap
uses the shared configuration to render our ul
with li
children:// import { Stack, Wrap } from "raam";
// import { Box, Heading, Link } from "your-components";
<Stack padding={3}>
<Heading as="h2">Tags</Heading>
<Wrap as="ul">
{Array.from({ length: 8 }, (v, k) => k + 1).map(item => (
<Link key={item} href={`#list-item-${item}`}>
Tag {item}
</Link>
))}
</Wrap>
</Stack>
If you'd rather let items flow elegantly in a single line, make use of Inline
.
Scroll behaviour can be removed with an overflow: 'hidden'
.
// import { Inline } from "raam";
// import { Box } from "your-components";
<Inline gap={3}>
{Array.from({ length: 32 }).map((item, i) => (
<Box
key={i}
sx={{
width: "2rem",
height: "2rem",
backgroundColor: "primary",
filter: i > 0 && `hue-rotate(${i * 2}deg)`,
}}
/>
))}
</Inline>
or with some more chaotic values…
// import { Inline } from "raam";
// import { Box } from "your-components";
() => {
const size = () => `${Math.floor(Math.random() * 4) + 1}rem`;
return (
<Inline gap={3} flexWrap="nowrap">
{Array.from({ length: 32 }).map((item, i) => (
<Box
key={i}
sx={{
width: size(),
height: size(),
backgroundColor: "primary",
filter: i > 0 && `hue-rotate(${i * 2}deg)`,
}}
/>
))}
</Inline>
);
};
Popularised by Seek's "Braid", a Flex-based layout that renders children on top of each other, spaced by the defined gap
.
// import { Stack } from "raam";
// import { Box } from "your-components";
<Stack gap={3}>
{Array.from({ length: 4 }).map((item, i) => (
<Box key={i} sx={{ height: "2rem", backgroundColor: "primary" }} />
))}
</Stack>
"Hold up, why don't you just…"
- "…use
display: grid;
"
Grid is fantastic for page layouts, but has its caveats for a 'simple'Stack
:
- It doesn't behave reliably for all elements (e.g.
fieldset
)- Can lead to 'blow out'.
- "…make
Inline
andStack
one component"?
↓
A display: flex;
-based layout primitive that aims to address the gap
.
Stack
, Wrap
and Inline
are all effectively "presets" of Flex. Don't like that? It's OK, you can use Flex
directly without opinionated defaults.
TL;DR: Mind the Gap
At the time of raam's release, usage of gap
in flex-based layouts is only supported by Firefox. To address this shortcoming, fallbacks are used:
nowrap
based layouts, margins are used in a single direction excluding the first-child.wrap
based layouts, negative margins are used on the outer component to counteract margins inside.A layout primitive to control vertical rhythm and flow for typographic content.
⚠ WIP
This project is in development and comes with caveats:
npm i raam --save
or
yarn add raam
All components use a shared set of props
:
gap
: a dynamic prop that aims to resolve the lack of gap
support for display: flex;
in most browsers.
It accepts a key from theme.space
(as a string or number), but if that's not found it'll render the provided string (e.g. em
or rem
) or number as a px
value.
Color, Space and Flexbox (excluding order
, alignSelf
and justifySelf
) props from Styled System.
as
: change the HTML element rendered (via Emotion).
raam makes an opinionated choice on how to render a component's children based on the element provided:
as | children rendered as |
---|---|
div (default) | div |
ol | li (with list-style-type reset) |
ul | li (with list-style-type reset) |
span | span |
p | span |
h1 -h6 | span |
css
: apply styles to the component (via Emotion).
Note: Use with caution, modifying the margin/padding may not behave as expected.
sx
: apply themed styles to the component (via Theme UI).
Note: Heavily recommended to install Theme UI before using. As with css
, use with caution.
Without these projects/people, this project wouldn't exist…