# Split About with Gradient Strips

> Dark split section: a heading and two paragraphs on one side, and a full-bleed panel of nine painted gradient strips stepping from blue to coral under sandpaper grain on the other.

A shadcn/ui block from the [@01orbital](https://01orbital.dev/?utm_source=shadcn.exchange) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/01orbital/about-04).

- Page, with a live preview: https://shadcn.exchange/r/01orbital/about-04
- Screenshot: https://shadcn.exchange/shot/01orbital/about-04/light.png
- Registry item: https://01orbital.dev/r/about-04.json
- Categories: about
- Listed: 2026-11-01, source last changed 2026-11-01

## Install

```bash
npx shadcn@latest add https://shadcn.exchange/r/01orbital/about-04.json
```

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

## Dependencies

- Registry items: `@01orbital/grain`, `@01orbital/heading`, `@01orbital/section`

## Files

### `blocks/about/about-04/index.tsx`

```tsx
import { Heading } from "@/components/editorial/heading"
import {
  Section,
  SectionDescription,
  SectionHeader,
  SectionTitleGroup,
} from "@/components/editorial/section"
import { Grain } from "@/components/texture/grain"

// The copy: change text here, not in the markup.
const COPY = {
  title: "How the registry grows",
} as const

const PARAGRAPHS = [
  "The registry deploys on a schedule, not in bursts. New blocks land weekly, each reviewed against the same tokens and the same rules, so the collection compounds instead of sprawling.",
  "Growth is apportioned to support the people already building on it: every addition has to make the existing installs better, not just bigger.",
] as const

type Strip = {
  top: number
  black: string
  deep: string
  mid: string
  ledge: string
}

const STRIPS: Strip[] = [
  {
    top: 62,
    black: "oklch(0.07 0.02 260)",
    deep: "oklch(0.18 0.09 270)",
    mid: "oklch(0.32 0.10 250)",
    ledge: "oklch(0.96 0.02 250)",
  },
  {
    top: 55,
    black: "oklch(0.06 0.02 258)",
    deep: "oklch(0.35 0.15 260)",
    mid: "oklch(0.62 0.16 250)",
    ledge: "oklch(0.96 0.02 250)",
  },
  {
    top: 48,
    black: "oklch(0.06 0.02 278)",
    deep: "oklch(0.25 0.09 278)",
    mid: "oklch(0.50 0.14 276)",
    ledge: "oklch(0.96 0.02 276)",
  },
  {
    top: 41,
    black: "oklch(0.06 0.02 290)",
    deep: "oklch(0.33 0.12 290)",
    mid: "oklch(0.55 0.20 300)",
    ledge: "oklch(0.96 0.02 300)",
  },
  {
    top: 34,
    black: "oklch(0.06 0.02 320)",
    deep: "oklch(0.28 0.11 335)",
    mid: "oklch(0.50 0.22 320)",
    ledge: "oklch(0.96 0.02 320)",
  },
  {
    top: 27,
    black: "oklch(0.06 0.02 335)",
    deep: "oklch(0.24 0.10 338)",
    mid: "oklch(0.65 0.25 330)",
    ledge: "oklch(0.96 0.02 330)",
  },
  {
    top: 21,
    black: "oklch(0.06 0.02 350)",
    deep: "oklch(0.26 0.10 345)",
    mid: "oklch(0.70 0.22 350)",
    ledge: "oklch(0.96 0.02 350)",
  },
  {
    top: 15,
    black: "oklch(0.06 0.02 10)",
    deep: "oklch(0.30 0.12 15)",
    mid: "oklch(0.72 0.20 10)",
    ledge: "oklch(0.96 0.02 10)",
  },
  {
    top: 10,
    black: "oklch(0.06 0.02 30)",
    deep: "oklch(0.32 0.13 20)",
    mid: "oklch(0.74 0.135 38)",
    ledge: "oklch(0.96 0.02 38)",
  },
]

function stripPaint({ top, black, deep, mid, ledge }: Strip): string {
  const z = top - 3.6
  const fall = 100 - top
  const at = (n: number) => `${n.toFixed(2)}%`
  const stops = [
    `${black} 0%`,
    `${black} ${at(z * 0.32)}`,
    `${deep} ${at(z)}`,
    `${ledge} ${at(z)}`,
    `${ledge} ${at(z + 0.5)}`,
    `${deep} ${at(z + 0.5)}`,
    `${deep} ${at(z + 1.1)}`,
    `${ledge} ${at(z + 1.1)}`,
    `${ledge} ${at(z + 1.6)}`,
    `${deep} ${at(z + 1.6)}`,
    `${deep} ${at(z + 2.25)}`,
    `${ledge} ${at(z + 2.25)}`,
    `${ledge} ${at(z + 2.8)}`,
    `${deep} ${at(z + 2.8)}`,
    `${deep} ${at(top)}`,
    `${ledge} ${at(top)}`,
    `${ledge} ${at(top + 2.4)}`,
    `${mid} ${at(top + 2.4 + fall * 0.14)}`,
    `${deep} ${at(top + 2.4 + fall * 0.55)}`,
    `${black} 100%`,
  ]
  return `linear-gradient(180deg in oklab, ${stops.join(", ")})`
}

// The art column bleeds, so the section padding lives on the text column.
export default function About04() {
  return (
    <section className="dark grid bg-background text-foreground lg:grid-cols-2">
      <Section className="flex flex-col justify-center">
        <SectionHeader size="sm">
          <SectionTitleGroup>
            <Heading size="lg">{COPY.title}</Heading>
          </SectionTitleGroup>
          <SectionDescription render={<div />} className="grid gap-6">
            {PARAGRAPHS.map((text) => (
              <p key={text}>{text}</p>
            ))}
          </SectionDescription>
        </SectionHeader>
      </Section>

      <figure
        aria-hidden="true"
        className="relative isolate h-110 overflow-hidden lg:h-auto lg:min-h-160"
      >
        <span className="absolute inset-0 flex">
          {STRIPS.map((strip, i) => (
            <span
              key={i}
              className="block flex-1"
              style={{ background: stripPaint(strip) }}
            />
          ))}
        </span>
        <Grain variant="sandpaper" opacity={0.85} isolated={false} />
      </figure>
    </section>
  )
}
```
