# 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 feature grid is the classic marketing "three columns of icon + title + text" pattern: `.featureItem` blurbs on a small-size [Tiles](/components/tiles) list. The layout is container-responsive: columns appear as the nearest size container gets wider, so the count answers the space the grid actually has, not the viewport.

<Tiles size="sm">
  <FeatureItem title="Zero JavaScript">
    <Fragment slot="icon" set:html={check} />
    <p>Just an unordered list and the tiles you already have.</p>
  </FeatureItem>
  <FeatureItem title="Responsive by default">
    <Fragment slot="icon" set:html={check} />
    <p>1, 2, then n columns as its container 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>
</Tiles>

<div class="docs_oversizedTable">

| File                                         | Description                        | Source      |
| -------------------------------------------- | ---------------------------------- | ----------- |
| `component.featureItem.css`                  | Feature item styles                | [Github][1] |
| `FeatureItem.astro`                          | The Astro component                | [Github][2] |
| `--featureItem-*` block in `settings.ui.css` | Interface tokens (see table below) | [Github][3] |
| [Tiles](/components/tiles)                   | The container-responsive layout    | [Github][2] |

</div>

Depends on [Tiles](/components/tiles) for the layout. 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.featureItem.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
  class="docs_playgroundFull"
  template={`<ul class="{classes}"{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 tiles 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 its container 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="tiles"
  snippets={{
    check: { preview: check, code: "<svg>[…]</svg>" },
  }}
  controls={[
    {
      heading: "Layout",
      items: [
        {
          type: "select",
          name: "size",
          label: "Tile size",
          default: "sm",
          options: [
            { label: "sm (the pattern)", value: "sm", class: "tiles-sm" },
            { label: "md", value: "md", class: "" },
          ],
        },
      ],
    },
  ]}
/>

## HTML

One `.featureItem` per `<li>`, on a `.tiles-sm` list: small tiles, so its container thresholds sit lower and columns appear sooner than for card-sized ones. The count comes from the width of the column the list sits in; see [Tiles](/components/tiles) for the thresholds and the container rules.

```html
<ul class="tiles tiles-sm">
  <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 tiles 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

The list is the [Tiles](/components/tiles) component with `size="sm"`.

**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>
    <Tiles size="sm" class="docs_twoColTiles">
      <FeatureItem title="Pinned to two">
        <Fragment slot="icon" set:html={check} />
        <p>Pin the count with `--tiles-columns` on a class of yours when the thresholds shouldn't decide.</p>
      </FeatureItem>
      <FeatureItem title="No icon required">
        <p>Skip the `icon` slot and the box disappears.</p>
      </FeatureItem>
    </Tiles>

    ```astro
    ---
    import Tiles from "../components/Tiles.astro";
    import FeatureItem from "../components/FeatureItem.astro";
    import zap from "../assets/icons/zap.svg?raw";
    ---
    <Tiles size="sm" class="perks">
      <FeatureItem title="Pinned to two">
        <Fragment slot="icon" set:html={zap} />
        <p>Pin the count with `--tiles-columns` on a class of yours when the thresholds shouldn't decide.</p>
      </FeatureItem>
      <FeatureItem title="No icon required">
        <p>Skip the `icon` slot and the box disappears.</p>
      </FeatureItem>
    </Tiles>
    ```

    ```css
    .perks {
      --tiles-columns: 2;
    }
    ```

  </li>
</ul>
