Op Art Hero

Opticians and frame makers

Look closer. It moves when you do.

Frames cut by hand from single sheets of acetate, and eye tests that take the full hour. Come in and see the world in sharper lines.

About this block

Op Art HeroPRO

A split hero with a large sans headline, an intro, an Arrow Pill and an underline link beside the op-art background component, a live WebGL field in the spirit of Bridget Riley: dense parallel lines ripple in slow waves and swell from thin to heavy across the canvas, bulging around the cursor or a wandering focus. Every field setting passes through the art prop; ink and paper follow the theme, lines stay crisp at any size, it pauses offscreen, holds a still frame for reduced motion and falls back to CSS stripes without WebGL.

Hero201: Op Art Hero

A split hero with a large sans headline, an intro and two buttons on the left, and a live WebGL field from the op-art component on the right: dense parallel lines that ripple in slow waves, swell from thin to heavy and bulge around the cursor or a wandering focus.

Upgrade to Pro

Pro blocks install through the shadcn CLI with your license key and ship their full source. Docs and live previews stay open to everyone, so you can read every block's details first.

Upgrade Now

Installation

Swap YOUR_EMAIL and YOUR_KEY for the email and license key on your account. Find your license key on your account page.

Radix flavor

bash
npx shadcn add "https://ui.beste.co/r/hero201?email=YOUR_EMAIL&license_key=YOUR_KEY"

Base UI flavor

bash
npx shadcn add "https://ui.beste.co/r-base/hero201?email=YOUR_EMAIL&license_key=YOUR_KEY"

This installs the block to components/beste/block/hero201.tsx plus the op-art background and the button23 and button2 buttons it uses.

Quick start

The installed file exports hero201Demo alongside the block: the exact props behind the preview above. Spread it to get a working hero in one line.

tsx
import { Hero201, hero201Demo } from "@/components/beste/block/hero201";

export default function Page() {
  return <Hero201 {...hero201Demo} />;
}

Then replace the demo with your own props. Written out, a trimmed setup looks like this:

tsx
import { Hero201 } from "@/components/beste/block/hero201";

export default function Page() {
  return (
    <Hero201
      eyebrow="Opticians and frame makers"
      heading="Look closer. It moves when you do."
      description="Frames cut by hand from single sheets of acetate, and eye tests that take the full hour."
      buttons={[
        { label: "Book an eye test", href: "/book" },
        { label: "See the frames", href: "/frames" },
      ]}
      art={{ inkColor: "var(--foreground)", paperColor: "var(--background)", lines: 34, pull: 0.5 }}
    />
  );
}

Props

PropTypeDefaultDescription
eyebrowstring–Small line above the heading
headingstring–Headline, rendered as the page h1
descriptionstring–Intro under the heading
buttonsActionButton[][]The first renders as a dark Button23 arrow pill, the rest as Button2 underline links
artOmit<OpArtProps, "className" | "children">–Forwards the OpArt component's props: inkColor, paperColor, lines, angle, wave, weight, contrast, speed, interactive, pull, paused
classNamestring–Extra classes for the outer <section>
ts
type ActionButton = {
  label: string;
  href: string;
};

Behavior notes

  • From lg the text takes 5 of 12 columns and the field 7, at least max(640px, 100svh - 78px) tall; below lg the field stacks under the text at 4/3, then 16/10 from sm.
  • A 96px gradient from background softens the seam between text and field on large screens.
  • inkColor and paperColor accept CSS variables, so the demo's var(--foreground) and var(--background) follow the theme in light and dark mode.
  • The loop pauses offscreen or in a hidden tab, and the pixel ratio is capped at 2 and lowered when frames run slow.
  • With reduced motion, the field draws a single still frame and the text skips its rise-in. Without WebGL, it falls back to CSS stripes.

More Hero blocks

View all Hero
PRO

hero196

Liquid Chrome Hero

PRO

hero157

Full-Bleed Canvas Hero

PRO

hero166

Split Headline Hero

Get Pro access