import { Story, Canvas, ArgTypes, Meta } from '@storybook/addon-docs/blocks';
import * as FlexGridStories from './FlexGrid.stories';
import { stackblitzPrefillConfig } from '../../../previewer/codePreviewer';

<Meta isTemplate />

# FlexGrid

[Source code](https://github.com/carbon-design-system/carbon/tree/main/packages/react/src/components/Grid)
&nbsp;|&nbsp;
[Usage guidelines](https://carbondesignsystem.com/elements/2x-grid/overview/)

{/* prettier-ignore-start */}

{/* <!-- START doctoc generated TOC please keep comment here to allow auto update --> <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> */}

## Table of Contents

- [Overview](#overview)
- [Gutter modes](#gutter-modes)
  - [Wide grid](#wide-grid)
  - [Narrow grid](#narrow-grid)
  - [Condensed grid](#condensed-grid)
  - [Mix-and-match](#mix-and-match)
- [Auto columns](#auto-columns)
- [Offset columns](#offset-columns)
- [Component API](#component-api)
  - [Using the `as` prop](#using-the-as-prop)
- [FAQ](#faq)
  - [How can I hide columns at a certain breakpoint?](#how-can-i-hide-columns-at-a-certain-breakpoint)
  - [Can I nest FlexGrid components?](#can-i-nest-flexgrid-components)
  - [Why are the FlexGrid styles not working?](#why-are-the-flexgrid-styles-not-working)
- [Feedback](#feedback)

{/* <!-- END doctoc generated TOC please keep comment here to allow auto update --> */}

{/* prettier-ignore-end */}

Carbon's grid components help developers use the
[2x Grid](https://carbondesignsystem.com/elements/2x-grid/overview/). The
project provides `FlexGrid`, `Row`, and `Column` components which can be used to
build a variety of layouts. You can import these components from
`@carbon/react`:

```js
import { FlexGrid, Row, Column } from '@carbon/react';
```

```scss
/* FlexGrid styles are not emitted by default, the feature flag must be turned on */

@use '@carbon/react' with (
  $use-flexbox-grid: true
);
```

<Canvas
  of={FlexGridStories.ResponsiveGrid}
  additionalActions={[
    {
      title: 'Open in Stackblitz',
      onClick: () => stackblitzPrefillConfig(FlexGridStories.ResponsiveGrid),
    },
  ]}
/>

## Overview

Every layout starts with the `FlexGrid` component. You can specify a `FlexGrid`
at the top-level of your project, or at different depths provided that it can
span 100% width of its container.

Next, you will use a combination of `Row` and `Column`. You can have multiple
`Row` components in a `FlexGrid`, and multiple `Column` components in a `Row`.
Each `Row` will contain all the `Column` components provided to it, as long as
they don't span more columns than the total number of columns in the grid.

To specify how many columns the `Column` component should span, you can use the
`sm`, `md`, `lg`, `xlg`, or `max` props. These props are shorthand versions of
the names given to each of the breakpoints defined by the
[2x Grid](https://carbondesignsystem.com/elements/2x-grid/overview/#breakpoints).
In the example below, we will use the `lg` prop for the large breakpoint and the
number `4` to specify that each `Column` component should span 4 columns at that
breakpoint.

```js
import { FlexGrid, Row, Column } from '@carbon/react';

function MyComponent() {
  return (
    <FlexGrid>
      <Row>
        <Column lg={4}>Span 4 of 12</Column>
        <Column lg={4}>Span 4 of 12</Column>
        <Column lg={4}>Span 4 of 12</Column>
        <Column lg={4}>Span 4 of 12</Column>
      </Row>
    <FlexGrid>
  );
}
```

You can pair up multiple breakpoint props to specify how many columns the
`Column` component should span at different break points. In the example below,
we will use the `sm`, `md`, and `lg` prop to specify how many columns the
`Column` components should span at the small, medium, and large breakpoints.

<Canvas
  of={FlexGridStories.ResponsiveGrid}
  additionalActions={[
    {
      title: 'Open in Stackblitz',
      onClick: () => stackblitzPrefillConfig(FlexGridStories.ResponsiveGrid),
    },
  ]}
/>

## Gutter modes

There are several
[gutter modes](https://carbondesignsystem.com/elements/2x-grid/overview/#gutters)
that you can use depending on the layout effect you're looking to achieve. By
default, `FlexGrid` uses the wide gutter mode with a 32px gutter. However, you
can use the `narrow` or `condensed` props to enable the narrow and condensed
grid modes, respectively.

The same way that you can pass in `narrow` or `condensed` to the `FlexGrid`
component, you can also pass in `narrow` or `condensed` to a `Row` component to
enable a certain gutter mode but only for a row. This can be useful when you
need to mix-and-match certain gutter modes to achieve a particular layout.

### Wide grid

<Canvas
  of={FlexGridStories.FullWidth}
  additionalActions={[
    {
      title: 'Open in Stackblitz',
      onClick: () => stackblitzPrefillConfig(FlexGridStories.FullWidth),
    },
  ]}
/>

### Narrow grid

<Canvas
  of={FlexGridStories.Narrow}
  additionalActions={[
    {
      title: 'Open in Stackblitz',
      onClick: () => stackblitzPrefillConfig(FlexGridStories.Narrow),
    },
  ]}
/>

### Condensed grid

<Canvas
  of={FlexGridStories.Condensed}
  additionalActions={[
    {
      title: 'Open in Stackblitz',
      onClick: () => stackblitzPrefillConfig(FlexGridStories.Condensed),
    },
  ]}
/>

### Mix-and-match

<Canvas
  of={FlexGridStories.MixedGutterModes}
  additionalActions={[
    {
      title: 'Open in Stackblitz',
      onClick: () => stackblitzPrefillConfig(FlexGridStories.MixedGutterModes),
    },
  ]}
/>

## Auto columns

In some situations, you may want your content to span a specific proportion of
the grid without having to calculate it across every breakpoint. A common
use-case for this is if you have a row of four cards and want each to span 25%
width each.

In these situations, you can make use of the auto columns feature of the
`Column` component. Auto columns is enabled when you do not provide any
breakpoint props, and it will automatically set each column to a percentage of
the total available width.

For example, if you have on `Column` component it would span 100%, two `Column`
components would span 50% each, four `Column` components would span 25% each,
and so on.

<Canvas
  of={FlexGridStories.AutoColumns}
  additionalActions={[
    {
      title: 'Open in Stackblitz',
      onClick: () => stackblitzPrefillConfig(FlexGridStories.AutoColumns),
    },
  ]}
/>

## Offset columns

You can offset your `Column` components by a specific amount of columns using
the object form for each breakpoint prop. This specific prop type allows you to
pass in an object to each breakpoint prop and this object has two keys, `span`
and `offset`, which allow you to specify the total numbers of columns the
`Column` component spans, and how many columns to offset it by.

You can specify either prop in this object form, and can mix-and-match across
breakpoints. For example, the following snippet will have the `Column` component
span two columns at the small breakpoint and then four columns at the medium
breakpoint. At the medium breakpoint, it will be offset by two columns.

```jsx
<Column sm={2} md={{ span: 4, offset: 2 }} />
```

<Canvas
  of={FlexGridStories.Offset}
  additionalActions={[
    {
      title: 'Open in Stackblitz',
      onClick: () => stackblitzPrefillConfig(FlexGridStories.Offset),
    },
  ]}
/>

## Component API

<ArgTypes />

### Using the `as` prop

By default, `FlexGrid`, `Row`, and `Column` will render as a `div`. However, you
can use the `as` prop to change this to another HTML element, or a custom
component from your project.

In the example below, we use the `as` prop on `Row` to change it from a `div` to
a `section`. Similarly, we use the `as` prop on `Column` to change it from a
`div` to an `article`.

```jsx
import { FlexGrid, Row, Column } from '@carbon/react';

function MyComponent() {
  return (
    <FlexGrid>
      <Row as="section">
        <Column as="article">Example content</Column>
        <Column as="article">Example content</Column>
        <Column as="article">Example content</Column>
        <Column as="article">Example content</Column>
      </Row>
    </FlexGrid>
  );
}
```

You can also provide a custom component to the `as` prop. This custom component
should accept all props passed to it, like a class name for the column.

```jsx
import { FlexGrid, Row, Column } from '@carbon/react';

function Article({ children, ...rest }) {
  return <article {...rest}>{children}</article>;
}

function CustomColumn({ children, ...rest }) {
  return <Column as={Article} {...rest}>{children}</Column:
}

function MyComponent() {
  return (
    <FlexGrid>
      <Row>
        <CustomColumn>Example content</Column>
        <CustomColumn>Example content</Column>
        <CustomColumn>Example content</Column>
        <CustomColumn>Example content</Column>
      </Row>
    <FlexGrid>
  );
}
```

## FAQ

### How can I hide columns at a certain breakpoint?

To hide a column at a specific breakpoint, you should specify 0 for the span of
the column at that particular breakpoint. For example, you can use the following
two forms for specifying column span and pass in 0 to either to hide the column
at the small breakpoint.

```jsx
<Column sm={0} />
<Column sm={{ span: 0 }} />
```

### Can I nest FlexGrid components?

`FlexGrid` does not support nested grids. For nested grids, use the `Grid`
(`CSSGrid`) component.

### Why are the FlexGrid styles not working?

FlexGrid styles are not emitted by default. You must opt in to emitting the
styling via one of the following options:

```scss
/* Option 1: Turn on the feature flag */

@use '@carbon/react' with (
  $use-flexbox-grid: true
);
```

```scss
/* Option 2: Use the flexgrid module */

@use '@carbon/react/scss/grid/flexbox';
```

```scss
/* Option 3: Use the grid module and call the flex-grid mixin */

@use '@carbon/react/scss/grid';
@include grid.flex-grid();
```

## Feedback

Help us improve this component by providing feedback, asking questions on Slack,
or updating this file on
[GitHub](https://github.com/carbon-design-system/carbon/edit/main/packages/react/src/components/Grid/Grid.mdx).
