Skip to content
Template Empire
Browse components

Feature Rows

A free alternating feature section with scroll reveals for React and Next.js.

Ship with Relay

Everything between git push and production

Relay turns a commit into a deploy, a branch into a shareable preview, and production into something you can actually see.

Deploys

Push to production in under a minute

Every commit builds, runs your checks and ships to the edge automatically. Roll back to any previous release with one click, no redeploy needed.

  • 49s median from push to live
  • Zero-downtime releases by default

Previews

A URL for every branch

Each pull request gets its own isolated preview environment, seeded with production-shaped data and torn down on merge.

  • Updated on every push to the branch
  • Password-protected for outside reviewers

Observability

See every request end to end

Traces, logs and metrics are captured out of the box and linked to the deploy that produced them, so you can jump from a slow span straight to the code behind it.

  • P95 regressions flagged within minutes
  • 30 days of retention on every plan

Feature Rows is a free feature section React component for Next.js, built with Motion and styled with Tailwind. It lays out two to six rows of media and copy on an alternating two column grid, and reveals each row on its own trigger as it scrolls into view: the copy rises in first and the media slot follows a tenth of a second later.

You bring the rows as ordinary children marked with data-feature-row, data-feature-media and data-feature-copy; the component owns the layout and the reveal choreography. Even rows swap column order visually with CSS order only, so the DOM, reading and Tab order stay identical in every row. The authored HTML is the final visible state, which means crawlers, no-JS visitors and reduced-motion users always see every row immediately.

Install

Add the @te registry to your components.json once:

{
  "registries": {
    "@te": "https://templateempire.io/r/{name}.json"
  }
}

Then install the component:

npx shadcn@latest add @te/feat-rows

Usage

import { FeatureRows } from "@/components/feat-rows";

export default function Page() {
  return (
    <FeatureRows>
      <div data-feature-row>
        <div data-feature-media>
          <img src="/screens/deploys.png" alt="Deploy dashboard" />
        </div>
        <div data-feature-copy>
          <h3>Push to production in under a minute</h3>
          <p>Every commit builds, ships to the edge and can be rolled back.</p>
        </div>
      </div>
      <div data-feature-row>
        <div data-feature-media>
          <img src="/screens/previews.png" alt="Preview environments" />
        </div>
        <div data-feature-copy>
          <h3>A URL for every branch</h3>
          <p>Each pull request gets its own isolated preview environment.</p>
        </div>
      </div>
    </FeatureRows>
  );
}

Props

PropTypeDefaultDescription
childrenReactNoderequired2 to 6 row wrappers marked data-feature-row, each containing a data-feature-media slot and a data-feature-copy slot. Author the media slot first in every row.
classNamestringundefinedAdditional classes merged onto the section root.

Customisation

Feature Rows declares no tokens of its own; it is a layout and reveal frame that consumes the global semantic tokens through the Tailwind utilities on its root, and your row markup owns the card and media styling. Override spacing from the className prop, and retheme your rows through the same semantic tokens the rest of the library uses:

<FeatureRows className="gap-24 md:gap-32">
  {rows}
</FeatureRows>

/* rows styled with semantic tokens */
:root {
  --border: oklch(from var(--color-neutral-50) l c h / 0.16);
}

Frequently asked questions

Is Feature Rows free for commercial use?
Yes. Feature Rows is MIT licensed, so you can use it in personal and commercial projects without attribution.
Does Feature Rows affect performance or accessibility?
The reveal animates transform and opacity only, inside space each row has already reserved, so layout shift is zero. Each row reveals on its own trigger and runs once. Rows waiting below the fold are set to their starting state before the page first paints, so no row is ever seen visible and then hidden; they fade with opacity only and stay in the accessibility tree, and if focus lands in a row before its reveal, that row comes to rest at once so a focused link is never transparent. The alternation is CSS order only, keeping DOM, reading and Tab order identical in every row, the two column layout follows the section's own width rather than the viewport's, and with reduced motion enabled every row renders immediately with nothing animated or observed.
How do I control which side the media appears on?
Author the media slot first in every row. Odd rows show media on the left and copy on the right from the md breakpoint up, and even rows swap visually via CSS order, so the alternation is automatic. On mobile every row is a single column with media on top. To change the rhythm, reorder the rows themselves; the component never changes the DOM order inside a row.

Related components

Want the full page this belongs to?Template Empire builds complete Next.js templates with this motion system throughout. Browse the paid templates that pair with these free components.Explore Template Empire templates