N/A

FeatureGrid

Render a complete feature section from app-owned feature data.

Feature sections

A complete grid for product capabilities

Render a polished feature section from app-owned data while keeping icons, routes, analytics, and content sources under your control.

Composable blocks

Ship complete sections without moving product copy, route decisions, or data ownership into the registry item.

App-owned content

Pass the exact feature list your product needs, from static arrays, CMS records, or localized copy.

Route-ready links

Link selected features to deeper docs or marketing pages while preserving your app's navigation model.

Analytics friendly

Keep click tracking and campaign metadata in your app instead of coupling the block to one analytics tool.

Discovery surfaces

Use the same data shape for landing pages, onboarding screens, docs overviews, and searchable feature indexes.

Safe external links

Blank-target feature links receive a safe default rel while still allowing app-specific rel overrides.

Installation

pnpm dlx shadcn-vue@latest add "https://ui.stackhacker.io/r/feature-grid.json"

Usage

<script setup lang="ts">
import type { Component } from 'vue'
import { Blocks, Route, Search } from 'lucide-vue-next'
import { FeatureGrid, type FeatureGridItem } from '@/components/feature-grid'

const features: FeatureGridItem[] = [
  {
    id: 'blocks',
    title: 'Composable blocks',
    description: 'Ship complete sections while keeping product data in your app.'
  },
  {
    id: 'routing',
    title: 'Route-ready links',
    description: 'Link selected features to deeper pages without coupling the block to Nuxt routing.',
    href: '/features'
  },
  {
    id: 'search',
    title: 'Discovery surfaces',
    description: 'Use the same data shape for landing pages, docs overviews, and searchable indexes.'
  }
]

const icons: Partial<Record<string, Component>> = {
  blocks: Blocks,
  routing: Route,
  search: Search
}

function featureIcon(item: FeatureGridItem) {
  return item.id ? icons[item.id] : undefined
}
</script>

<template>
  <FeatureGrid
    headline="Feature sections"
    title="Product capabilities at a glance"
    description="Render a polished feature section from app-owned data."
    :items="features"
  >
    <template #icon="{ item }">
      <component v-if="featureIcon(item)" :is="featureIcon(item)" class="size-5" aria-hidden="true" />
    </template>
  </FeatureGrid>
</template>

FeatureGrid vs FeatureCard

FeatureGrid owns the full marketing section: optional headline, title, description, responsive grid layout, and repeated feature items. Use it when you want to install a complete section that can drop into a landing page, docs overview, or product page.

FeatureCard remains the smaller card primitive for one-off feature, content, or navigation cards. Use it when your app already owns the surrounding section layout or when you need to compose custom grids by hand.

App-Owned Feature Data

Your app owns the items array, route generation, analytics events, active states, CMS mapping, localization, and icon rendering. The component intentionally does not accept Nuxt Icon string names, require NuxtLink, or install an icon package.

Pass icon markup through the scoped icon slot. That keeps the block portable across Lucide, Nuxt Icon, custom SVGs, or no icons at all.

When an item has href, it renders as an anchor. When href is omitted, it renders static article content. For target="_blank", the component adds rel="noopener noreferrer" unless you provide a custom rel value.

Examples

Default

Feature sections

A complete grid for product capabilities

Render a polished feature section from app-owned data while keeping icons, routes, analytics, and content sources under your control.

Composable blocks

Ship complete sections without moving product copy, route decisions, or data ownership into the registry item.

App-owned content

Pass the exact feature list your product needs, from static arrays, CMS records, or localized copy.

Route-ready links

Link selected features to deeper docs or marketing pages while preserving your app's navigation model.

Analytics friendly

Keep click tracking and campaign metadata in your app instead of coupling the block to one analytics tool.

Discovery surfaces

Use the same data shape for landing pages, onboarding screens, docs overviews, and searchable feature indexes.

Safe external links

Blank-target feature links receive a safe default rel while still allowing app-specific rel overrides.

API Reference

Props

PropTypeDefaultDescription
headlinestringOptional eyebrow label shown above the section title.
titlestringOptional section title.
descriptionstringOptional section description.
itemsFeatureGridItem[][]Feature items supplied by your app.
columns2 | 3 | 43Responsive column count for large screens.
classstringAdditional CSS classes for the section.

Types

interface FeatureGridItem {
  id?: string
  title: string
  description?: string
  href?: string
  target?: HTMLAnchorElement['target']
  rel?: string
}

Slots

SlotPropsDescription
icon{ item: FeatureGridItem }Optional icon markup rendered above each item title.