experimental
Firefox Cube
An isometric stack of nine 3D blocks built purely from skewed <span>s and their ::before/::after faces — no images, no JS (server component). A continuous hue-rotate gives the greyscale stack a slow ambient shimmer; hovering any block snaps it to --cube-accent (default --primary) with a soft glow, then fades back over 1.5s. The three faces derive from --cube-shade (default --foreground) via color-mix so the stack stays legible on any theme. Decorative (role=img). Original by Greg Vissing (public CodePen, MIT), curated from a uiverse.io repost by csemszepp.
Ported from Greg Vissing (MIT)
Install
1. Register the namespace (once per project):
json
// components.json — register the @bottega namespace once
{
"registries": {
"@bottega": { "url": "https://bottega.ariacode.ca/r/{name}.json" }
}
}2. Add the component:
bash
npx shadcn add @bottega/firefox-cubeUsage
Usagetsx
<FirefoxCube />Props
| Prop | Type | Default | Description |
|---|---|---|---|
| label | string | Animated isometric cube | Accessible label for the decorative stack. Default "Animated isometric cube". |
Source
firefox-cube.tsxtsx
import type React from "react";
import styles from "./firefox-cube.module.css";
export interface FirefoxCubeProps extends React.HTMLAttributes<HTMLDivElement> {
/** Accessible label for the decorative stack. Default "Animated isometric cube". */
label?: string;
}
// Three offset cubes; each cube is three columns; each column stacks three
// blocks. Geometry is driven by the --x / --y / --i custom props the CSS reads.
const COLUMNS = [-1, 0, 1] as const;
const DEPTHS = [3, 2, 1] as const;
/**
* Firefox Cube — an isometric stack of nine 3D blocks built purely from skewed
* `<span>`s and their `::before` / `::after` faces (no images, no JS, server
* component). A continuous hue-rotate gives the stack a slow ambient shimmer;
* hovering any block snaps it to `--cube-accent` (default `--primary`) with a
* glow, then fades back over 1.5s. Faces derive from `--cube-shade`
* (default `--foreground`) so the stack stays legible on any theme.
*
* Decorative: rendered as role="img". The hue-rotate is removed under
* prefers-reduced-motion (see the module CSS).
*
* Ported from a uiverse.io card by csemszepp, originally a CodePen by Greg Vissing.
*/
export function FirefoxCube({
label = "Animated isometric cube",
className = "",
...props
}: FirefoxCubeProps) {
return (
<div
role="img"
aria-label={label}
className={[styles.root, className].filter(Boolean).join(" ")}
{...props}
>
{[0, 1, 2].map((cube) => (
<div key={cube} className={styles.cube}>
{COLUMNS.map((x) => (
<div
key={x}
className={styles.col}
style={{ "--x": x, "--y": 0 } as React.CSSProperties}
>
{DEPTHS.map((i) => (
<span
key={i}
className={styles.block}
style={{ "--i": i } as React.CSSProperties}
/>
))}
</div>
))}
</div>
))}
</div>
);
}
Dependencies
- @bottega/tokens