A swim club and hotel in Mallorca
A 1960s lido with 24 rooms above the pool deck. Swim before breakfast, take lunch in the shade and stay until the tiles turn gold.
A bright full-bleed hero over the pool-caustics background component: pale hand-laid tiles and a navy lane mark refracted by the water, with sun-dappled caustic light drifting across them and ripples spreading wherever the cursor or a tap touches the surface. A light serif headline, a short intro and two Arrow Pill buttons sit at the bottom. Every pool setting passes through the pool prop; ripples start on their own when idle, the loop pauses offscreen, reduced motion shows one still frame and browsers without WebGL get a tiled CSS fallback.
A bright full-bleed hero over the pool-caustics WebGL surface, where pale tiles and a lane mark are refracted by water with drifting caustic light and ripples that spread from the cursor or a tap, with a serif headline, an intro and two arrow pill buttons at the bottom.
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.
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
npx shadcn add "https://ui.beste.co/r/hero205?email=YOUR_EMAIL&license_key=YOUR_KEY"Base UI flavor
npx shadcn add "https://ui.beste.co/r-base/hero205?email=YOUR_EMAIL&license_key=YOUR_KEY"This installs the block to components/beste/block/hero205.tsx plus the pool-caustics background and the button23 button it uses.
The installed file exports hero205Demo alongside the block: the exact props behind the preview above. Spread it to get a working hero in one line.
import { Hero205, hero205Demo } from "@/components/beste/block/hero205";
export default function Page() {
return <Hero205 {...hero205Demo} />;
}Then replace the demo with your own props. Written out, a trimmed setup looks like this:
import { Hero205 } from "@/components/beste/block/hero205";
export default function Page() {
return (
<Hero205
eyebrow="A swim club and hotel in Mallorca"
heading="Bright water, slow afternoons."
description="A 1960s lido with 24 rooms above the pool deck."
buttons={[
{ label: "Reserve a room", href: "/rooms" },
{ label: "Day passes", href: "/passes" },
]}
pool={{ tileColor: "var(--background)", laneColor: "#1a4a78", waterColor: "#8cd6e0", lane: true, rain: 0.5 }}
/>
);
}| Prop | Type | Default | Description |
|---|---|---|---|
eyebrow | string | – | Small line above the heading |
heading | string | – | Serif headline, rendered as the page h1 |
description | string | – | Intro on the left of the bottom row |
buttons | ActionButton[] | [] | Button23 arrow pills: the first solid primary, the rest outlined in the text color |
pool | Omit<PoolCausticsProps, "className" | "children"> | – | Forwards the PoolCaustics component's props: tileColor, groutColor, laneColor, waterColor, lightColor, tint, tileSize, lane, caustics, causticScale, refraction, colorSplit, speed, ripples, rain, interactive, paused |
className | string | – | Extra classes for the outer <section> |
type ActionButton = {
label: string;
href: string;
};max(640px, 100svh - 78px) tall and the copy is pushed to the bottom, over a background colored gradient that fades out 68% of the way up.foreground, background, primary), and the demo lays the pool tiles and grout on var(--background), so the hero follows light and dark mode. The lane, water and caustic light colors stay fixed as part of the art.rain rate and follow the cursor and taps when interactive is on.