Skip to content
6

Feature 9

Catalog bento on a hairline grid: a wide opening cell, four single cells and a full-width closing cell, each with a large faded icon that warms on hover, a title, a clamped description and a crosshair frame that clips at the cell edge.

Preview

Installation

npx shadcn@latest add https://hirael.com/r/feature-09.json

Code

components/blocks/feature-09.tsx
'use client';

import { Bell, CalendarClock, FlaskConical, Hammer, Rocket, Sparkles } from 'lucide-react';

import { cn } from '@/lib/utils';
import { Badge } from '@/registry/hirael/bases/radix/ui/badge';

const CELLS = [
  {
    icon: Hammer,
    title: 'Build',
    description: 'Compile, bundle and containerize with per-branch caches that survive between runs.',
    className: 'md:col-span-2',
  },
  {
    icon: FlaskConical,
    title: 'Test',
    description: 'Split suites across parallel runners and merge the reports back into one view.',
  },
  {
    icon: Rocket,
    title: 'Deploy',
    description: 'Gate releases on approvals, roll out per environment, roll back from the graph.',
  },
  {
    icon: Bell,
    title: 'Notify',
    description: 'Route failures to the people who can fix them, not a channel everyone mutes.',
  },
  {
    icon: CalendarClock,
    title: 'Schedule',
    description: 'Nightly builds, weekly cleanups and cron-style triggers without a separate service.',
  },
  {
    icon: Sparkles,
    title: 'More on the way',
    description:
      'Matrix expansion, reusable sub-graphs and self-hosted runners are in progress. The catalog grows without config changes.',
    className: 'md:col-span-3',
  },
];

/** Crosshair frame: lines extend past the padded box and clip at the cell edge. */
const CellFrame = () => {
  return (
    <div className="pointer-events-none absolute inset-[calc(var(--box-padding)-1px)] z-0">
      <div className="absolute start-1/2 top-0 h-px w-[200%] bg-border ltr:-translate-x-1/2 rtl:translate-x-1/2" />
      <div className="absolute bottom-0 start-1/2 h-px w-[200%] bg-border ltr:-translate-x-1/2 rtl:translate-x-1/2" />
      <div className="absolute start-0 top-1/2 h-[200%] w-px -translate-y-1/2 bg-border" />
      <div className="absolute end-0 top-1/2 h-[200%] w-px -translate-y-1/2 bg-border" />
    </div>
  );
};

const Feature09 = () => {
  return (
    <section
      data-slot="feature"
      className="flex w-full flex-col justify-center gap-12 bg-background px-6 py-16 md:px-10 md:py-24"
    >
      <div data-slot="feature-header" className="mx-auto flex max-w-3xl flex-col items-center gap-4 text-center">
        <Badge
          variant="outline"
          className="rounded-full bg-card/70 px-4 py-1.5 font-mono text-[10px] uppercase tracking-[0.14em] text-muted-foreground"
        >
          Step catalog
        </Badge>
        <h2 className="font-serif text-3xl font-medium tracking-tight md:text-4xl lg:text-5xl">
          One graph, every stage
        </h2>
        <p className="text-base leading-relaxed text-muted-foreground md:text-lg">
          Steps are typed, so the canvas knows what connects to what. Pick a stage, wire it in, and the pipeline stays
          legible.
        </p>
      </div>

      <div className="mx-auto grid w-full max-w-6xl grid-cols-1 gap-px bg-border p-px md:grid-cols-3">
        {CELLS.map((cell) => (
          <div
            key={cell.title}
            data-slot="feature-cell"
            className={cn(
              'relative flex flex-col justify-between overflow-hidden bg-background p-(--box-padding) [--box-padding:1rem]',
              cell.className,
            )}
          >
            <div className="z-1 size-full">
              <div className="group relative flex size-full min-h-32 items-center justify-center overflow-hidden">
                <cell.icon
                  aria-hidden
                  className="size-14 stroke-[1.2] text-muted-foreground/50 transition-colors duration-300 group-hover:text-warm"
                />
              </div>
            </div>
            <div className="relative min-h-24 p-3">
              <h3 className="mb-1 text-base font-semibold text-foreground md:text-lg">{cell.title}</h3>
              <p className="line-clamp-2 text-pretty text-sm leading-relaxed text-muted-foreground">
                {cell.description}
              </p>
              <div className="absolute start-1/2 top-0 h-px w-screen bg-border ltr:-translate-x-1/2 rtl:translate-x-1/2" />
            </div>
            <CellFrame />
          </div>
        ))}
      </div>
    </section>
  );
};

export default Feature09;

Dependencies

shadcn registry

badge

npm

lucide-react

Shipped