Lightweight React Linear Layout Component
Tags: showdev, react, javascript, component
Published: 2019-12-20 15:20:48

> ### TL;DR
> A layout component that arranges children in a single row or column using CSS flexbox and has some very nice custom CSS properties with which you can easily set gaps & item sizes.
>
> It's super small and super easy to use.
>
> Licensed under [ISC license](https://gitlab.com/bsara/react-linear-layout/blob/master/LICENSE).
>
> Storybook: https://bsara.gitlab.io/react-linear-layout/
> NPM & Docs: https://www.npmjs.com/package/react-linear-layout
> Responsive Version: https://www.npmjs.com/package/react-responsive-linear-layout

At it's core, `react-linear-layout` _(AKA `LinearLayout`)_ is basically a [CSS flexbox] (https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layout/Flexbox). As such, all flexbox properties are valid when styling a `LinearLayout`.

You may be asking yourself, _"If it's just a flexbox, then why not use a flexbox, why even use this component?"_ Well, I'm glad that you asked. The power of this component comes in its convenience:

- `LinearLayout` has some very nice **[CSS custom properties](#css-custom-properties)** that make styling item gaps _(I.E. margins)_ and sizing of elements quite a bit more convenient.
- `LinearLayout` comes with some sensible CSS defaults.
- In some ways, it makes the use of a linear layout more declarative _(like specifying the direction of the layout via a prop)_.

Let's see an example:

```jsx
import React from 'react';
import LinearLayout from 'react-linear-layout';

export default function MyComponent() {
  return (
    <LinearLayout>
      <div>Item 1</div>
      <div>Item 2</div>
      <div>Item 3</div>
    </LinearLayout>
  );
}
```

The code above with render the three divs one after another, in a horizontal line _(horizontal is the default direction)_. If we want to change the direction, we can specify the `direction` prop:

```jsx
import React from 'react';
import LinearLayout from 'react-linear-layout';

export default function MyComponent() {
  return (
    <LinearLayout direction="vertical">
      <div>Item 1</div>
      <div>Item 2</div>
      <div>Item 3</div>
    </LinearLayout>
  );
}
```

Now, the items will be stacked one on top of another when rendered.

By default, `LinearLayout` will span it's parent _(because it's CSS `display` property is set to `flex`)_. We can make the component render inline by specifying the `inline` prop:

```jsx
import React from 'react';
import LinearLayout from 'react-linear-layout';

export default function MyComponent() {
  return (
    <LinearLayout inline>
      <div>Item 1</div>
      <div>Item 2</div>
      <div>Item 3</div>
    </LinearLayout>
  );
}
```

## CSS Custom Properties

`LinearLayout` has a few CSS custom properties available that make styling the layout's children really easy. Most notable is `--linear-layout-item-gap`:

```jsx
import React from 'react';
import LinearLayout from 'react-linear-layout';
import styled from 'styled-components'; // NOTE: You're not required to use styled-components, I just chose it for the example...just because. :)

const StyledLinearLayout = styled(LinearLayout)`
  --linear-layout-item-gap: 10px;
`;

export default function MyComponent() {
  return (
    <StyledLinearLayout>
      <div>Item 1</div>
      <div>Item 2</div>
      <div>Item 3</div>
    </StyledLinearLayout>
  );
}
```

When rendered, the children of `StyledLinearLayout` will have a 10 pixel gap in between them. Also, that gap will be split between each item _(I.E. the right margin of `Item 1` will be`5px` and the left margin of `Item 2` will be `5px`)_.

If you want all of the items to be the same size, or if you want them to all have the same min/max size, then you can use any of these custom properties:

- `--linear-layout-item-size`
- `--linear-layout-item-min-size`
- `--linear-layout-item-max-size`

If `direction` is set to `"horizontal"`, then the width of all children will be effected. If `direction` is set to `"vertical"` then the height of all of the children will be effected.

## Default CSS of `LinearLayout`

There is some sensible default CSS applied to `LinearLayout`:

> **NOTE:** _You can always override any of these defaults via CSS._

- All content is justified to `flex-start`.
- `flex-wrap` is set to `nowrap`.
- `flex-grow` and `flex-shrink` of all children are both set to `0` _(this ensures that, by default, the list of items is rendered like any list you might expect rather than having each item take up a large portion of space)_

## Try It Out

There is both a CommonJS and ESM build distributed in the NPM package.

Feel free to try out the public storybook for `react-linear-layout` here:
https://bsara.gitlab.io/react-linear-layout

You can find the NPM package and docs here:
https://www.npmjs.com/package/react-linear-layout

Find the source here **(contributions are always welcome)**:
https://gitlab.com/bsara/react-linear-layout

The code is licensed under the [ISC license](https://gitlab.com/bsara/react-linear-layout/blob/master/LICENSE).

## Check out the responsive version!

I've also created a version that takes care of all of the margin/padding needed for creating a responsive list:
{% post bsara/lightweight-react-responsive-linear-layout-component-52cd %}