← alle entries

feature-split

FC-0110Sectiesfeature-imageblockv1.0.0

Eén kenmerk in twee helften: een badge, kop en toelichting naast een groot beeld (slot), links of rechts; smal komt het beeld boven de tekst. Het lichtste inhoudsblok van een landingspagina.

zelfde component — andere tokens
Platform

Dit is het begin van iets nieuws

Een klein bedrijf runnen is al zwaar genoeg. Laat verouderde, omslachtige processen los — wij maken handel eenvoudiger en sneller dan ooit.

blocks/feature/feature-split.tsx
/**
 * FeatureSplit — één kenmerk in twee helften: links (of rechts) een badge,
 * een kop en een toelichting, ernaast een groot beeld (slot). Smal komt
 * het beeld boven de tekst. Het lichtste inhoudsblok van een landingspagina.
 *
 * Geoogst uit 21st.dev Feature with image (tommyjepsen): de shadcn Badge
 * (cva) → een pil op --primary, de lege bg-muted-placeholder → `image`-slot,
 * container/py-40 → padding-props, lorem → slots. Statisch.
 */

import type * as React from "react";

export interface FeatureSplitProps extends Omit<React.HTMLAttributes<HTMLElement>, "title" | "children"> {
  badge?: React.ReactNode;
  title: React.ReactNode;
  description?: React.ReactNode;
  /** Het beeld (img/video/element); vult een 16:9-vlak. */
  image?: React.ReactNode;
  /** Beeld links (standaard) of rechts van de tekst. */
  imageSide?: "left" | "right";
  /** Extra inhoud onder de toelichting (bv. een knop). */
  action?: React.ReactNode;
}

export function FeatureSplit({ badge, title, description, image, imageSide = "left", action, className, ...rest }: FeatureSplitProps) {
  return (
    <section {...rest} className={["fp-feature", imageSide === "right" ? "fp-feature--rechts" : "", className].filter(Boolean).join(" ")}>
      <div className="fp-feature__beeld">{image}</div>
      <div className="fp-feature__tekst">
        {badge && <span className="fp-feature__badge">{badge}</span>}
        <h2 className="fp-feature__titel">{title}</h2>
        {description && <p className="fp-feature__toelichting">{description}</p>}
        {action && <div className="fp-feature__actie">{action}</div>}
      </div>
    </section>
  );
}
blocks/feature/feature.css
/** FeatureSplit — importeren in de app-root (registry-site: app/globals.css). */

.fp-feature {
  display: flex; flex-direction: column-reverse; gap: 2.5rem; width: 100%; max-width: 72rem; margin: 0 auto; box-sizing: border-box; padding: 3rem 1.5rem;
  background: var(--background); color: var(--foreground);
}
@media (min-width: 64rem) {
  .fp-feature { flex-direction: row; align-items: center; padding: 5rem 1.5rem; }
  .fp-feature--rechts { flex-direction: row-reverse; }
  .fp-feature__tekst { padding-left: 5rem; }
  .fp-feature--rechts .fp-feature__tekst { padding-left: 0; padding-right: 5rem; }
}
.fp-feature__beeld { flex: 1 1 0; aspect-ratio: 16 / 9; overflow: hidden; border-radius: calc(var(--radius) * 1.5); background: var(--muted); }
.fp-feature__beeld > * { width: 100%; height: 100%; object-fit: cover; display: block; }
.fp-feature__tekst { flex: 1 1 0; display: flex; flex-direction: column; gap: 1rem; align-items: flex-start; }
.fp-feature__badge { display: inline-flex; align-items: center; padding: 0.125rem 0.625rem; border-radius: 999px; font: inherit; font-size: 0.75rem; font-weight: 600; background: var(--primary); color: var(--primary-foreground); }
.fp-feature__titel { margin: 0; max-width: 36rem; font: inherit; font-weight: 400; font-size: clamp(1.5rem, 3.6vw, 3rem); line-height: 1.1; letter-spacing: -0.03em; }
.fp-feature__toelichting { margin: 0; max-width: 28rem; font: inherit; font-size: 1.125rem; line-height: 1.6; letter-spacing: -0.01em; color: var(--muted-foreground); }
.fp-feature__actie { margin-top: 0.5rem; }