# Feature Section v5

> Centered sans headline with a storytelling bento grid of four static cards, balanced title and body typography on muted surfaces.

A shadcn/ui block from the [@uiception](https://uiception.com/?utm_source=shadcn.exchange) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/uiception/feature-section-v5).

- Page, with a live preview: https://shadcn.exchange/r/uiception/feature-section-v5
- Screenshot: https://shadcn.exchange/shot/uiception/feature-section-v5/light.png
- Registry item: https://uiception.com/r/feature-section-v5.json
- Listed: 2026-10-13, source last changed 2026-10-13

## Install

```bash
npx shadcn@latest add https://shadcn.exchange/r/uiception/feature-section-v5.json
```

Run it in a project that has shadcn/ui set up. It adds the files below and installs what they depend on.

## Dependencies

- npm packages: `geist`

## Files

### `registry/new-york/blocks/feature-section-v5/page.tsx`

```tsx
import FeatureSectionV5 from "./components/feature-section-v5"

export default function Page() {
  return <FeatureSectionV5 />
}
```

### `registry/new-york/blocks/feature-section-v5/components/feature-section-v5.tsx`

```tsx
import { GeistSans } from "geist/font/sans"

import FeatureGrid from "./feature-grid"

export default function FeatureSectionV5() {
  return (
    <section
      className={`${GeistSans.className} py-4 text-foreground md:py-6`}
    >
      <div className="mx-auto max-w-6xl px-4">
        <div className="mx-auto mb-12 flex max-w-3xl flex-col items-center gap-4 text-center md:mb-14 lg:mb-16">
          <h2 className="text-4xl leading-[1.1] font-medium tracking-[-0.03em] lg:text-5xl">
            Less noise. More signal.
          </h2>
          <p className="max-w-xl text-3.75 leading-relaxed text-muted-foreground">
            Tools that help your team focus on the work that matters.
          </p>
        </div>
        <FeatureGrid />
      </div>
    </section>
  )
}
```

### `registry/new-york/blocks/feature-section-v5/components/feature-grid.tsx`

```tsx
import { cn } from "@/lib/utils"

import { featureSectionItems } from "../lib/features"

import "../styles/feature-grid.css"

const cellClassNames = [
  "sm:col-span-2 lg:col-span-1 lg:row-span-2 lg:col-start-1 lg:row-start-1",
  "lg:col-span-2 lg:col-start-2 lg:row-start-1",
  "sm:max-lg:col-span-1 lg:col-start-2 lg:row-start-2",
  "sm:max-lg:col-span-1 lg:col-start-3 lg:row-start-2",
] as const

export default function FeatureGrid() {
  return (
    <ul className="m-0 grid list-none grid-cols-1 gap-3 p-0 sm:grid-cols-2 lg:grid-cols-[1.15fr_1fr_1fr] lg:grid-rows-[minmax(11.25rem,auto)_minmax(11.25rem,auto)] lg:items-stretch">
      {featureSectionItems.map(({ id, title, description }, index) => (
        <li key={id} className={cn("flex min-w-0", cellClassNames[index])}>
          <div
            className={cn(
              "fsv5-card group relative flex min-h-0 w-full flex-1 flex-col items-start gap-2.5 overflow-hidden rounded-none bg-muted dark:bg-background p-5 pr-5.4 pb-5.4 text-foreground",
              index === 1 &&
                "grid grid-cols-[minmax(0,min(38ch,100%))] content-center justify-center justify-items-stretch gap-2.5 text-left lg:grid-cols-[minmax(0,min(54ch,94%))] lg:px-[clamp(1.25rem,2.5vw,1.85rem)] lg:py-5.4",
              index === 0 &&
                "lg:justify-center lg:gap-3.5 lg:px-6.4 lg:pt-6 lg:pb-6.6",
              (index === 2 || index === 3) &&
                "sm:max-lg:justify-start lg:justify-start lg:gap-2.5 lg:px-5 lg:pt-5 lg:pb-5.4"
            )}
          >
            <p
              className={cn(
                "fsv5-card-title m-0 w-full min-w-0 font-sans font-medium text-foreground",
                index === 0 &&
                  "text-xl leading-[1.15] tracking-[-0.015em] sm:text-5.5 lg:max-w-[14em] lg:text-6.5 lg:tracking-[-0.02em]",
                index === 1 &&
                  "text-lg leading-tight tracking-[-0.01em] lg:text-xl lg:leading-[1.2] lg:tracking-[-0.015em]",
                (index === 2 || index === 3) &&
                  "text-base leading-snug tracking-[-0.01em] text-pretty"
              )}
            >
              <span className="fsv5-card-title__ghost" aria-hidden="true">
                {title}
              </span>
              <span className="fsv5-card-title__label">{title}</span>
            </p>
            <p
              className={cn(
                "m-0 w-full min-w-0 font-sans text-sm leading-[1.55] text-muted-foreground max-sm:mt-0",
                index === 0 &&
                  "max-w-[min(38ch,100%)] text-3.75 leading-relaxed lg:mt-0 lg:max-w-[min(40ch,100%)] lg:text-base lg:leading-[1.65]",
                index === 1 &&
                  "mt-0 text-3.75 leading-relaxed lg:leading-[1.6]",
                (index === 2 || index === 3) && "mt-auto sm:max-lg:mt-0 lg:mt-0"
              )}
            >
              {description}
            </p>
          </div>
        </li>
      ))}
    </ul>
  )
}
```

### `registry/new-york/blocks/feature-section-v5/styles/feature-grid.css`

```css
.fsv5-card::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0.045;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.75' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23n)'/%3E%3C%2Fsvg%3E");
  background-repeat: repeat;
  background-size: 200px 200px;
}

.fsv5-card-title {
  position: relative;
  isolation: isolate;
}

.fsv5-card-title__ghost,
.fsv5-card-title__label {
  display: block;
  transform-origin: left center;
  transition:
    transform 480ms cubic-bezier(0.22, 1, 0.36, 1),
    opacity 480ms cubic-bezier(0.22, 1, 0.36, 1),
    filter 480ms cubic-bezier(0.22, 1, 0.36, 1),
    letter-spacing 480ms cubic-bezier(0.22, 1, 0.36, 1),
    text-shadow 480ms cubic-bezier(0.22, 1, 0.36, 1);
}

.fsv5-card-title__ghost {
  position: absolute;
  inset: 0;
  opacity: 0;
  filter: blur(10px);
  transform: scale(1);
  pointer-events: none;
  user-select: none;
}

.fsv5-card-title__label {
  position: relative;
  z-index: 1;
  transform: scale(1);
}

.group:hover .fsv5-card-title__ghost {
  opacity: 0.42;
  filter: blur(14px);
  transform: scale(1.06);
}

.group:hover .fsv5-card-title__label {
  transform: scale(1.04);
  letter-spacing: 0.012em;
  text-shadow: 0 0 28px color-mix(in oklab, var(--foreground) 14%, transparent);
}

@media (prefers-reduced-motion: reduce) {
  .fsv5-card-title__ghost,
  .fsv5-card-title__label {
    transition: none;
  }

  .group:hover .fsv5-card-title__ghost {
    opacity: 0;
    filter: none;
    transform: none;
  }

  .group:hover .fsv5-card-title__label {
    transform: none;
    letter-spacing: inherit;
    text-shadow: none;
  }
}
```

### `registry/new-york/blocks/feature-section-v5/lib/features.ts`

```ts
export type FeatureDefinition = {
  id: string
  title: string
  description: string
}

export const featureSectionItems: FeatureDefinition[] = [
  {
    id: "signal-over-noise",
    title: "Clear priorities",
    description: "The right updates reach the right people. Nothing else gets in the way.",
  },
  {
    id: "defaults-that-hold",
    title: "Smart defaults",
    description: "Sensible choices from day one so your team can move without second guessing.",
  },
  {
    id: "one-thread-per-outcome",
    title: "Shared context",
    description: "Decisions, files, and feedback stay with the work. No hunting across tools.",
  },
  {
    id: "quiet-reliability",
    title: "Quiet reliability",
    description: "When something needs attention, you get a clear signal and a path to fix it.",
  },
]
```
