Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/cremalab/boxl
A layout primitive for the styled component age.
https://github.com/cremalab/boxl
layout react styled-components
Last synced: 7 days ago
JSON representation
A layout primitive for the styled component age.
- Host: GitHub
- URL: https://github.com/cremalab/boxl
- Owner: cremalab
- License: mit
- Created: 2018-11-25T20:45:03.000Z (about 6 years ago)
- Default Branch: develop
- Last Pushed: 2019-05-03T18:46:43.000Z (almost 6 years ago)
- Last Synced: 2024-10-07T09:05:23.632Z (4 months ago)
- Topics: layout, react, styled-components
- Language: TypeScript
- Homepage:
- Size: 1.01 MB
- Stars: 2
- Watchers: 22
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# B ❐ X L
A layout primitive for the [styled component](https://www.styled-components.com) age.
[![npm version](https://badge.fury.io/js/boxl.svg)](https://badge.fury.io/js/boxl)
[![Build Status](https://travis-ci.com/cremalab/boxl.svg?branch=develop)](https://travis-ci.com/cremalab/boxl)
[![codecov](https://codecov.io/gh/cremalab/boxl/branch/develop/graph/badge.svg)](https://codecov.io/gh/cremalab/boxl)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)## Installation
```shell
$ npm i boxl styled-components
```
>Built with [styled components](https://www.styled-components.com) which is required as a peer dependency## Usage
>Examples are written in TypeScript
### Define Components
Create components with the `boxl` function passing default props and styling. (All following examples use these components.)
```tsx
// Base.tsx
import { boxl } from "boxl"interface ParentProps {
withHeight?: boolean
}export const Parent = boxl.div({
css: styled => styled`
height: ${props => props.withHeight
? "449px"
: "auto"
};
background: white;
border: 8px solid black;
box-shadow: 12px -12px 0 0 black;
margin: 12px 12px 0 0;
padding: 20px;
`,
spacing: "14px",
})interface ChildProps {
secondary?: boolean
}export const Child = boxl.div({
css: styled => styled`
background: ${props =>
props.secondary ? "white" : "black"
};
border: 8px solid black;
color: ${props =>
props.secondary ? "white" : "black"
};
padding: 20px;
`,
})
```### Examples
#### `direction: vertical` (default)
![Example 001](.loki/reference/example_example_001.png)
```tsx
import React from "react"
import { Child, Parent } from "./Base"export const Example001 = () => (
)
```#### `direction: horizontal`
![Example 002](.loki/reference/example_example_002.png)
```tsx
import React from "react"
import { Child, Parent } from "./Base"export const Example002 = () => (
)
```## Theme Setup
First, follow [Styled Components](https://www.styled-components.com/docs/api#define-a-theme-interface) instructions on setting up a theme with TypeScript.
Once you have defined a theme, we must annotate `boxl` with it using the provided `Boxl` interface. A common pattern is to re-export the annotated `boxl` function for reuse.
```jsx
import { Boxl, boxl as b } from "boxl"
import { Theme } from "../types/Theme"export const boxl = b as Boxl
```## API
### `boxl`
`boxl` is a function that returns a `BoxlComponent`. There are two ways to use it:
1. Use predefined element methods:
```ts
boxl.div(BoxlProps)
```
> Available for all `JSX.IntrinsicElements`
2. Pass a component:
```ts
boxl(React.ComponentType)(BoxlProps)
```
> `React.ComponentType` is any function or class component#### Component Example
This allows another component to be passed for styling and is useful when you need to style a 3rd party component (e.g. react-router's ``).
![component: example 1](.loki/reference/example_example_Component001.png)
```tsx
import React, { SFC } from "react";
import {
boxl,
BoxlComponentProps
} from "boxl";
import { Parent } from "./Base";const SomeButton: SFC =
({boxlProps, ...props}) =>
;const MyButton = boxl(SomeButton)({
css: styled => styled`
background: hsl(200, 100%, 50%);
border-radius: 0.25em;
border: none;
color: white;
cursor: pointer;
font-size: 0.75em;
outline: none;
padding: 0.5em 1em;
&:active {
background: hsl(200, 100%, 40%);
}
&:hover {
background: hsl(200, 100%, 60%);
}
`,
})export const Component001 = () =>
Old Button
New Button
```### `BoxlProps`
These props may be passed as a default props object or to the returned component itself as JSX props.
>With the exception of `css`, each prop is defined as `BoxlProp`.
---
#### `alignHorizontal` - left | center | right
##### Description
Control horizontal alignment of children. If value is undefined, Child fills available Parent space.
##### Example: `center`
![alignHorizontal: example 1](.loki/reference/example_example_AlignHorizontal001.png)
```tsx
// AlignHorizontal.tsximport React from "react"
import { Child, Parent } from "./Base"export const AlignHorizontal001 = () =>
```---
#### `alignVertical` - top | center | bottom
##### Description
Aligns children vertically regardless of `direction`.
##### Example: `bottom`
![alignVertical: example 1](.loki/reference/example_example_AlignVertical001.png)
```tsx
// AlignVertical.tsx
import React from "react"
import { Child, Parent } from "./Base"export const AlignVertical001 = () =>
```
---#### `childGrow` - number
##### Description
Sets grow amount on all children equally. Useful in combination with `childWrap`.
##### Example
`childGrow={1}` causes Child components to fill available Parent space evenly if possible.
![childGrow: example 1](.loki/reference/example_example_ChildGrow001.png)
```tsx
// ChildGrow.tsx
import React from "react"
import { Child, Parent } from "./Base"export const ChildGrow001 = () =>
```
---#### `childIdealSize` - string (CSS length)
##### Description
Sets `idealSize` on all children. Useful in combination with `childWrap`.
##### Example
`childIdealSize="150px"` causes Child components to _prefer_ 150 pixel width if possible.
![childIdealSize: example 1](.loki/reference/example_example_ChildIdealSize001.png)
```tsx
import React from "react"
import { Child, Parent } from "./Base"export const ChildIdealSize001 = () =>
```
---#### `childWrap` - auto | even
##### Description
Allows Child components to wrap if needed.
##### Example 1: `childWrap="auto"`
![childWrap: example 1](.loki/reference/example_example_ChildWrap001.png)
```tsx
import React from "react"
import { Child, Parent } from "./Base"export const ChildWrap001 = () =>
```##### Example 2: `childWrap="auto"` with `childGrow={1}`
![childWrap: example 2](.loki/reference/example_example_ChildWrap002.png)
```tsx
import React from "react"
import { Child, Parent } from "./Base"export const ChildWrap002 = () =>
```##### Example 3: `childWrap="even"` with `childGrow={1}`
![childWrap: example 3](.loki/reference/example_example_ChildWrap003.png)
```tsx
import React from "react"
import { Child, Parent } from "./Base"export const ChildWrap003 = () =>
```
---#### `css`:
- string
- CSSObject
- template literal
- function passed a tagged template literal##### Description
Applies style to the component.
##### Example
![css: example 1](.loki/reference/example_example_Css001.png)
```tsx
import React from "react"
import { boxl } from "../../lib/boxl"
import { Parent } from "./Base"const StyleString = boxl.div({
css: "background: black; border-radius: 10px; height: 50px;",
});const StyleObject = boxl.div({
css: {
background: "black",
borderRadius: 10,
height: 50,
},
})const TemplateLiteral = boxl.div({
css: `
background: black;
border-radius: 10px;
height: 50px;
`,
})const TaggedTemplateLiteralFn = boxl.div({
css: styled => styled`
background: black;
border-radius: 10px;
height: 50px;
`,
})export const Style001 = () =>
```
---#### `direction` - vertical | horizontal
##### Description
Controls the direction that children flow.
##### Example 1: `"vertical"`
![direction: example 1](.loki/reference/example_example_Direction001.png)
```tsx
import React from "react"
import { Child, Parent } from "./Base"export const Direction001 = () =>
```##### Example 2: `"horizontal"`
![direction: example 2](.loki/reference/example_example_Direction002.png)
```tsx
import React from "react"
import { Child, Parent } from "./Base"export const Direction002 = () =>
```
---#### `grow` - number
##### Description
Determines how the component expands in relation to its parent and siblings.
##### Example
![grow: example 1](.loki/reference/example_example_Grow001.png)
```tsx
import React from "react"
import { Child, Parent } from "./Base"export const Grow001 = () =>
```
---#### `idealSize` - string (CSS length)
##### Description
Defines the preferred/ideal width or hight (depending on the parent's `direction`) of the component and may need to be combined with min-/max-/width via the css property to achieve the desired result.
If the parent direction is "vertical" (default), `idealSize` will affect the _height_ of the component. If the parent direction is "horizontal", `idealSize` will affect the _width_ of the component.
##### Example
![idealSize: example 1](.loki/reference/example_example_IdealSize001.png)
```tsx
import React from "react"
import { Child, Parent } from "./Base"export const IdealSize001 = () =>
```
---#### `spacing` - string (CSS length)
##### Description
Defines the space between children without affecting their distance from the edge of their parent.
##### Example
![spacing: example 1](.loki/reference/example_example_Spacing001.png)
```tsx
import React from "react"
import { Child, Parent } from "./Base"export const Spacing001 = () =>
```
---### `BoxlProp`
```ts
type BoxlProp =
| (A | undefined)
| (BoxlPropThemeFn)
| (BoxlPropMediaQuery);type BoxlPropThemeFn = (
props: BoxlPropsBaseThemed
) => BoxlProp;type BoxlPropMediaQuery
= {
[key: string]: BoxlProp;
};
```
`BoxlProp` is the union of three types:
1. `| (A | undefined)` - a primitive value (or undefined)
2. `| (BoxlPropThemeFn)` - a function that receives component props and returns `BoxlProp`
3. `| (BoxlPropMediaQuery)` - an object with keys corresponding to a media query string and values that are `BoxlProp`#### Example Usage:
```tsx
// alignHorizontal as A
const Example01 = boxl.div({
alignHorizontal: "left"
})interface Props {
foo: boolean
}// alignHorizontal as BoxlPropThemeFn
const Example02 = boxl.div({
alignHorizontal: props =>
props.foo ? "left" : "right",
})// alignHorizontal as BoxlPropMediaQuery
const Example03 = boxl.div({
alignHorizontal: {
"@media (max-width: 600px)": "left",
"@media (max-width: 800px)": props =>
props.foo ? "left" : "center",
},
})
```## Develop
- `npm i` install project and test app deps
- `npm start` starts storybook
- `npm test:unit` runs unit tests
- `npm test:visual` runs visual tests (requires storybook to be running e.g. `npm start`)
- `npm test:visual:watch` runs visual tests in watch mode
- `npm run build` compiles `dist/`
- `npm pack` generates `.tgz` for local testing