# Feature Grid

> Part of mCSS (mcss.dev). Rendered page: https://mcss.dev/components/featuregrid

export const check = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="m9 12 2 2 4-4"/></svg>`;

The `.featureGrid` component is the classic marketing "three columns of icon + title + text" pattern, composed over the mCSS [grid system](/docs/global#grid).

<FeatureGrid>
  <FeatureItem title="Zero JavaScript">
    <Fragment slot="icon" set:html={check} />
    <p>Just an unordered list and the grid you already have.</p>
  </FeatureItem>
  <FeatureItem title="Responsive by default">
    <Fragment slot="icon" set:html={check} />
    <p>1, 2, then n columns as the viewport grows.</p>
  </FeatureItem>
  <FeatureItem title="Tokenized icons">
    <Fragment slot="icon" set:html={check} />
    <p>Icon box size and colors come from the theme.</p>
  </FeatureItem>
</FeatureGrid>

<div class="docs_oversizedTable">

| File                                         | Description                        | Source      |
| -------------------------------------------- | ---------------------------------- | ----------- |
| `component.featureGrid.css`                  | Feature grid + item styles         | [Github][1] |
| `FeatureGrid.astro`, `FeatureItem.astro`     | The Astro components               | [Github][2] |
| `--featureItem-*` block in `settings.ui.css` | Interface tokens (see table below) | [Github][3] |

</div>

Depends on `.grid` (`global.grid.css`), part of the mCSS core. Icons are yours to bring; [Lucide](https://lucide.dev/) is a great resource.

[1]: https://github.com/minimaldesign/mCSS/blob/main/src/styles/framework/component.featureGrid.css
[2]: https://github.com/minimaldesign/mCSS/tree/main/src/components
[3]: https://github.com/minimaldesign/mCSS/blob/main/src/styles/framework/settings.ui.css

## Playground

<Playground
  client:visible
  template={`<ul class="{classes}" col="1" col-md="2"{attrs}>
  <li class="featureItem">
    <div class="featureItem_icon" aria-hidden="true">{check}</div>
    <h3 class="featureItem_title">Zero JavaScript</h3>
    <div class="featureItem_text">
      <p>Just an unordered list and the grid you already have.</p>
    </div>
  </li>
  <li class="featureItem">
    <div class="featureItem_icon" aria-hidden="true">{check}</div>
    <h3 class="featureItem_title">Responsive by default</h3>
    <div class="featureItem_text">
      <p>1, 2, then n columns as the viewport grows.</p>
    </div>
  </li>
  <li class="featureItem">
    <div class="featureItem_icon" aria-hidden="true">{check}</div>
    <h3 class="featureItem_title">Tokenized icons</h3>
    <div class="featureItem_text">
      <p>Icon box size and colors come from the theme.</p>
    </div>
  </li>
</ul>`}
  baseClasses="featureGrid grid"
  snippets={{
    check: { preview: check, code: "<svg>[…]</svg>" },
  }}
  controls={[
    {
      heading: "Layout",
      items: [
        {
          type: "select",
          name: "cols",
          label: "Columns (from --lg)",
          default: "cols3",
          options: [
            { label: "2", value: "cols2", class: "", attr: 'col-lg="2"' },
            { label: "3", value: "cols3", class: "", attr: 'col-lg="3"' },
            { label: "4", value: "cols4", class: "", attr: 'col-lg="4"' },
          ],
        },
      ],
    },
  ]}
/>

## HTML

One item per `<li>`: one column on mobile, two from `--md`, and 2/3/4 (your pick) from `--lg`.

```html
<ul class="featureGrid grid" col="1" col-md="2" col-lg="3">
  <li class="featureItem">
    <div class="featureItem_icon" aria-hidden="true"><svg>[…]</svg></div>
    <h3 class="featureItem_title">Zero JavaScript</h3>
    <div class="featureItem_text">
      <p>Just an unordered list and the grid you already have.</p>
    </div>
  </li>
  <!-- more items… -->
</ul>
```

The icon box is `aria-hidden`: feature icons are decoration next to a real heading, so screen readers skip them.

### Custom properties

The following custom properties are available in [`settings.ui.css`](/docs/tokens#interface-tokens):

<div class="docs_oversizedTable">

| Property                              | Description                  |
| ------------------------------------- | ---------------------------- |
| `--featureItem-icon-box-size`         | Icon container width/height. |
| `--featureItem-icon-size`             | SVG width/height.            |
| `--featureItem-icon-color`            | Icon (stroke/fill) color.    |
| `--featureItem-icon-background-color` | Icon container background.   |
| `--featureItem-icon-border-radius`    | Icon container radius.       |

</div>

## Astro component

**FeatureGrid**

<div class="docs_oversizedTable">

| Prop    | Type     | Default     | Description                                                         |
| ------- | -------- | ----------- | ------------------------------------------------------------------- |
| `cols`  | `number` | `3`         | Columns from the `--lg` breakpoint: `2`, `3`, or `4`.               |
| `class` | `string` | `undefined` | Additional CSS classes, useful for [helper classes](/docs/helpers). |

</div>

**FeatureItem**

<div class="docs_oversizedTable">

| Prop         | Type     | Default     | Description                                  |
| ------------ | -------- | ----------- | -------------------------------------------- |
| `title`      | `string` | `undefined` | The item's `h3`.                             |
| `class`      | `string` | `undefined` | Additional CSS classes.                      |
| `titleClass` | `string` | `undefined` | Extra classes added to `.featureItem_title`. |
| `iconClass`  | `string` | `undefined` | Extra classes added to `.featureItem_icon`.  |

</div>

<div class="docs_oversizedTable">

| Slot      | Description                                      |
| --------- | ------------------------------------------------ |
| `icon`    | An SVG icon, rendered in the tokenized icon box. |
| (default) | The item's body text.                            |

</div>

## Examples

<ul class="docs_examples">
  <li>
    <FeatureGrid cols={2}>
      <FeatureItem title="Two columns">
        <Fragment slot="icon" set:html={check} />
        <p>Set `cols` for the large-screen column count.</p>
      </FeatureItem>
      <FeatureItem title="No icon required">
        <p>Skip the `icon` slot and the box disappears.</p>
      </FeatureItem>
    </FeatureGrid>

    ```astro
    ---
    import FeatureGrid from "../components/FeatureGrid.astro";
    import FeatureItem from "../components/FeatureItem.astro";
    import zap from "../assets/icons/zap.svg?raw";
    ---
    <FeatureGrid cols={2}>
      <FeatureItem title="Two columns">
        <Fragment slot="icon" set:html={zap} />
        <p>Set `cols` for the large-screen column count.</p>
      </FeatureItem>
      <FeatureItem title="No icon required">
        <p>Skip the `icon` slot and the box disappears.</p>
      </FeatureItem>
    </FeatureGrid>
    ```

  </li>
</ul>
