Back to components
Content

Feature List

A three-column feature list for product summaries and onboarding.

Page preview
Source
This is the component source that shadcn installs into a consuming project.
registry/default/feature-list/feature-list.tsx
import {
  BoxesIcon,
  FileJsonIcon,
  MonitorCheckIcon,
} from "lucide-react"

import { Badge } from "@/components/ui/badge"
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "@/components/ui/card"

const features = [
  {
    icon: BoxesIcon,
  },
  {
    icon: FileJsonIcon,
  },
  {
    icon: MonitorCheckIcon,
  },
] as const

type FeatureListItem = {
  title: string
  description: string
}

type FeatureListCopy = {
  badge: string
  title: string
  description: string
  features: [FeatureListItem, FeatureListItem, FeatureListItem]
}

type FeatureListProps = {
  copy?: FeatureListCopy
}

const defaultCopy: FeatureListCopy = {
  badge: "System",
  title: "Library building blocks",
  description:
    "Use this pattern for feature summaries, capability lists, or onboarding sections.",
  features: [
    {
      title: "Composable blocks",
      description: "Ship source-level components that can be edited in every consuming app.",
    },
    {
      title: "Registry output",
      description: "Build installable JSON artifacts that shadcn CLI can consume by URL.",
    },
    {
      title: "Preview first",
      description: "Keep a visual workbench so humans and AI tools can inspect available UI.",
    },
  ],
}

export function FeatureList({ copy = defaultCopy }: FeatureListProps) {
  return (
    <Card className="w-full max-w-2xl">
      <CardHeader>
        <Badge className="w-fit" variant="secondary">
          {copy.badge}
        </Badge>
        <CardTitle>{copy.title}</CardTitle>
        <CardDescription>
          {copy.description}
        </CardDescription>
      </CardHeader>
      <CardContent className="grid gap-3 md:grid-cols-3">
        {features.map((feature, index) => {
          const Icon = feature.icon
          const featureCopy = copy.features[index]

          return (
            <div
              key={featureCopy.title}
              className="flex min-w-0 flex-col gap-3 rounded-lg border bg-background p-4"
            >
              <div className="flex size-8 items-center justify-center rounded-lg bg-muted text-foreground">
                <Icon />
              </div>
              <div className="flex flex-col gap-1">
                <h3 className="text-sm font-medium">{featureCopy.title}</h3>
                <p className="text-sm leading-6 text-muted-foreground">
                  {featureCopy.description}
                </p>
              </div>
            </div>
          )
        })}
      </CardContent>
    </Card>
  )
}