Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/temzasse/styled-layout
๐ Simple responsive layout components based on styled-components.
https://github.com/temzasse/styled-layout
css-in-jss design-systems layout reactjs styled-components
Last synced: 19 days ago
JSON representation
๐ Simple responsive layout components based on styled-components.
- Host: GitHub
- URL: https://github.com/temzasse/styled-layout
- Owner: Temzasse
- License: mit
- Created: 2020-04-19T09:33:17.000Z (over 4 years ago)
- Default Branch: master
- Last Pushed: 2023-01-06T03:46:17.000Z (almost 2 years ago)
- Last Synced: 2024-10-25T09:50:11.099Z (21 days ago)
- Topics: css-in-jss, design-systems, layout, reactjs, styled-components
- Language: TypeScript
- Homepage: https://temzasse.github.io/styled-layout/
- Size: 2.42 MB
- Stars: 4
- Watchers: 3
- Forks: 1
- Open Issues: 26
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
๐ Styled Layout
ยท
Simple responsive layout components
ยท
## Motivation
### The problem
There are many approaches to handling layout in todays user interfaces on the Web. We have come from using floats and clearfixes to flexbox and grids in CSS to achieve fluid and flexible layouts that are responsive across various device sizes.
The rise of design systems has brought forth the shortcomings of the layout approaches we have been using so far. For example the most common way to create white space between UI components is to attach margins directly to components via class names. This approach is far from perfect and has multiple issues:
1. Changing the position of components is hard since it requires moving the attached margin to another component
2. How do you decide which component should have the spacing attached to it? (margin-left or margin-right?)
3. It's impossible to know what the spacing is just by looking at the render method - instead you have to peak in the CSS level to know where the margins are attached.
4. Components are too context-aware and thus not properly reusable### The solution
When you shift your thinking away from attaching spacing directly to components to treating layout and spacing inside your UI as components themselves you open the door for a whole new world of layout management. By using layout components, such as `Stack` or `Spacer`, your move the higher level responsibility of handling the layout to a separate component while still being able to have lower level control over the spacing between components. In this way you are able to design your other components in a reusable manner without having to think about the context they appear in and the white space around them.
### Inspirational resources
- [Margin considered harmful](https://mxstbr.com/thoughts/margin)
- [Layout-isolated components](https://visly.app/blog/layout-isolated-components)
- [Braid Design System | Layout](https://seek-oss.github.io/braid-design-system/foundations/layout)
- [Every Layout | Stack](https://every-layout.dev/layouts/stack/)## Getting started
### Installation
First, install the library.
```sh
npm install styled-layout
```or with Yarn:
```sh
yarn add styled-layout
```### Prerequisites
In order to use the layout components we first need to add spacing units/tokens to the theme. The tokens need to be added inside an object called `spacing` and there needs to be at least one spacing unit called `default` but other than that the units can be named based on any naming convention you are most comfortable with.
> If you are not familiar with styled-components theme setup with TypeScript you can read about it [here](https://styled-components.com/docs/api#typescript).
```ts
import { DefaultTheme } from 'styled-components';export const theme: DefaultTheme = {
spacing: {
none: '0px',
xxsmall: '2px',
xsmall: '4px',
small: '8px',
normal: '16px',
default: '16px',
medium: '24px',
large: '32px',
xlarge: '48px',
xxlarge: '64px',
},
// ... other theme values ...
};
``````jsx
import { ThemeProvider } from 'styled-components';
import { theme } from './theme';const App = () => {
{/* Components */};
};
```## Basic usage
```jsx
import React from 'react';
import styled from 'styled-components';
import { Stack, Spacer } from 'styled-layout';const Component = () => (
Basic stack
Item 1
Item 2
Item 3
Item 4
)
```Check the available props for each layout component in the [Components](#Components) section.
You can also take a look at the [example](example/components/Main.tsx) folder for more comprehensive usage of the layout components.
## Dividers
Dividers allow you to create visually more distinct separation between elements inside a stack. You can add dividers to a Stack via the `dividers` prop that, in it's most basic form, accepts a boolean to toggle the dividers on or off.
```jsx
import React from 'react';
import styled from 'styled-components';
import { Stack } from 'styled-layout';const Component = () => (
Item 1
Item 2
Item 3
Item 4
);
```You can control the divider color by defining a color called `divider` in your theme under `colors` (otherwise the default color for the divider line is `#ddd`). However, it is quite common that you need more color options for your dividers which is why you can easily use any color by adding more colors to your theme and referencing them in the divider's `color` prop.
```jsx
// theme.ts
import { DefaultTheme } from 'styled-components';export const theme: DefaultTheme = {
colors: {
primary: 'tomato',
divider: '#eee', // default color for all dividers
'grey-10': '#f5f5f5',
'grey-30': '#eeeeee',
'grey-50': '#dddddd',
'grey-70': '#888888',
'grey-90': '#444444',
// ... other colors ...
},
};// component.tsx
import React from 'react';
import { Stack } from 'styled-layout';const Component = () => (
<>
Item 1
Item 2
Item 3
Item 4
>
);
```In certain cases you might need a more fined grained control over the dividers inside a stack. If you render a `Divider` component inside a `Stack` component that divider will overwrite the default divider that would otherwise appear in it's place.
```jsx
import React from 'react';
import styled from 'styled-components';
import { Stack, Divider } from 'styled-layout';const Component = () => (
Item 1
Item 2
Item 3
Item 4
);
```## Media queries
Media queries are commonly used to create responsive styles for components. In most cases you don't need to write media queries by yourself when using styled-layout but instead you can utilize a more ergonomic way of defining responsive styles: responsive props. You might have seen these kind of responsive props in the wild where the props are passed as an array, eg. in [styled-system](https://styled-system.com/responsive-styles/). Instead of using the array syntax for responsive props styled-layout uses an alternative [object syntax](https://styled-system.com/responsive-styles/#using-objects).
Start by defining the breakpoints that are part of your design system. The name of the each breakpoint is totally up to you to decide - they can be eg. _phone | tablet | desktop | monitor_ or if you fancy more Bootstrap like names _sm | md | lg | xl_.
```js
const breakpoints = {
phone: { min: 0, max: 767 },
tablet: { min: 768, max: 1023 },
desktop: { min: 1024, max: 1279 },
monitor: { min: 1280, max: Infinity },
};
```You can optionally add `Up/Down` variants for your breakpoints by omiting the other min/max value.
```js
const baseBreakpoints = {
phone: { min: 0, max: 767 },
tablet: { min: 768, max: 1023 },
desktop: { min: 1024, max: 1279 },
monitor: { min: 1280, max: Infinity },
};const breakpoints = {
...baseBreakpoints,
tabletDown: { max: baseBreakpoints.tablet.max },
tabletUp: { min: baseBreakpoints.tablet.min },
desktopDown: { max: baseBreakpoints.desktop.max },
desktopUp: { min: baseBreakpoints.desktop.min },
};
```Finally, create a `media` utility and add it to your theme. Note that we are also exporting the media helper here since it's quite a handy tool to use in your custom styled components too.
```js
import { DefaultTheme } from 'styled-components';
import { createMediaQuery } from 'styled-layout';export const media = createMediaQuery(breakpoints);
export const theme: DefaultTheme = {
breakpoints,
media,
// ...other theme values ...
};
```This will enable responsive props for _all_ components in styled-layout. The default value in the responsive prop object is represented by `_` key and the other fields come from the breakpoints that were added to the theme.
```jsx
import { Stack, Spacer } from 'styled-layout';
Responsive props
No need to add your own media queries ๐
;
```We can also the `media` helper that we exported earlier in any styled component.
```jsx
import styled from 'styled-components';
import { media } from './theme';const CustomComponent = styled.div`
padding: ${p => p.theme.spacing.large};${media.phone`
padding: ${p => p.theme.spacing.normal};
`}
`;
```You might be asking why we are using the exported `media` helper instead of the one we put in the theme.
That's a good question.
For some reason CSS syntax highlighting only works when we are directly using the media helper. So, by using `${media.phone}` instead of `${p => p.theme.media.phone}` the CSS is highlighted correctly (at least in VSCode). However, the CSS autocompletion doesn't seem to work in either case ๐
## Components
### `Stack`
| Prop | Type | Default | Note |
| --------- | ------------- | ------------ | ----------------------------------------------- |
| `axis` | `'x'` / `'y'` | `'y'` | |
| `spacing` | `string` | `'default'` | Based on spacing tokens in theme |
| `fluid` | `boolean` | `false` | Determines whether the stack items should wrap. |
| `align` | `string` | `flex-start` | Use any flexbox `align-items` value. |
| `justify` | `string` | `flex-start` | Use any flexbox `justify-content` value. |### `Spacer`
| Prop | Type | Default | Note |
| ------ | ------------- | ----------- | -------------------------------- |
| `axis` | `'x'` / `'y'` | `'y'` | |
| `size` | `string` | `'default'` | Based on spacing tokens in theme |### `Divider`
| Prop | Type | Default | Note |
| ------- | -------- | ----------- | --------------------------------------------------------- |
| `size` | `string` | `'default'` | Based on spacing tokens in theme. |
| `color` | `string` | `'divider'` | Based on color tokens in theme (or `#ddd` without theme). |## Utilities
### `createMediaQuery`
```ts
interface BreakpointRange {
min: number;
max: number;
}type Breakpoints = {
[breakpoint: string]:
| BreakpointRange
// Up variant
| Omit
// Down variant
| Omit;
};const breakpoints: Breakpoints = {
/* Add your breakpoints */
};const media = createMediaQuery(breakpoints);
```## License
MIT.