MKT UI
Sections

Service grid (icons)

A grid of services or capabilities, each with an icon.

Open preview (opens in a new tab)

Installation

npx shadcn@latest add http://localhost:3000/r/services-icon-grid.json

MKT UI is not published yet, so this points at your local development server. Set NEXT_PUBLIC_REGISTRY_URL to the deployed origin to show the public command.

Also installs: container, section, section-heading, service-card.

Usage

import { Droplets, Gauge, Wrench } from "lucide-react";
import { ServicesIconGrid } from "@/components/services-icon-grid";

<ServicesIconGrid
  eyebrow="What we do"
  title="Residential and small commercial plumbing"
  description="Straightforward pricing on the jobs we are called out for most."
  surface="muted"
  services={[
    {
      id: "emergency",
      title: "Emergency repairs",
      description: "Burst pipes, major leaks, and blocked drains.",
      icon: <Droplets />,
      price: "From $149 call-out",
      inclusions: ["Same-day weekday slots", "Upfront price before work starts"],
    },
    {
      id: "leak-detection",
      title: "Leak detection",
      description: "Acoustic and thermal detection for slab and wall leaks.",
      icon: <Gauge />,
      href: "/services/leak-detection",
    },
  ]}
/>

Props

PropTypeDefaultDescription
title (required)ReactNodeSection heading.
services (required)ServiceItem[]The services. Each needs a stable `id`, which doubles as the anchor target.
eyebrowReactNodeShort label above the heading.
descriptionReactNodeOne or two sentences under the heading.
columns2 | 3 | 43Columns on wide screens. Two on tablet, always one on mobile.
align"start" | "center""start"Heading alignment. The grid itself is unaffected.
actionReactNodeOptional action under the grid, e.g. "See all services".
headingAs"h1" | "h2" | "h3""h2"Heading level. Set it to match the page outline.
surface"default" | "muted" | "brand" | "inverted""default"Background treatment.

ServiceItem

PropTypeDefaultDescription
id (required)stringStable key, also used as the list item's DOM id so you can link to it.
title (required)stringWhat a customer would call this service.
description (required)stringOne or two sentences on what it covers.
iconReactNodeA Lucide icon element. Rendered decoratively and hidden from screen readers.
hrefstringTurns the whole card into one link to a service detail page.
pricestringPrice or starting price, e.g. "From $149".
inclusionsstring[]Three or four bullets on what is included.

Behavior

The grid is a <ul>. That tells a screen-reader user how many services there are before they start reading them — which is exactly the question someone is asking when they land on a services section.

A card with href is a single link, not a card containing a "Learn more" link. That gives a much larger tap target on a phone and produces one tab stop per card instead of making a keyboard user tab through the list twice.

Cards stretch to equal height within a row, so a service with a longer description does not leave its neighbors floating.

Limitations

  • Icon-only. The image and compact linked-card variants (services-image-grid, services-compact) are not implemented yet.
  • columns={4} gets tight below about 1280px with long service names. Three is the safer default for service businesses.
  • No built-in filtering or category grouping.
  • Composition — where a services section sits in a page

On this page