Glow Tile

ProBackgrounds3DWebGLpowered by @vectorvesper/motion

A wall of bevelled tiles clustered around the edges of the frame, lit so the rim colour catches as they move. The pointer pushes them on a spring — a rolling wave, a flip, or a press inward. The whole wall is one draw call, and the frame loop drops off entirely once the tiles settle.

Glow Tile

Included with membership

Members install Glow Tile with one command and get the full source, the usage code and the Framer remix, licensed for client work. One membership covers the whole library and the CLI.

When to use it

A backdrop for something else — a hero, a login panel, a section header, a footer. The tiles deliberately avoid the centre, so it is built to sit behind copy rather than to be looked at directly. Reach for it when a page needs a surface with some depth and you have a wide, reasonably tall area to give it.

  • Put your content in children and keep it near the centre. The layouts cluster tiles at the edges and corners precisely to leave that space clear.
  • Add pointer-events-auto to anything in children that has to be clickable. The overlay is pointer-transparent by default so the tiles still receive the pointer.
  • Start from a theme and override single colours from there. Each preset sets the background, the tiles and all four lights together, so they stay in balance.
  • Move lightPosition and rimPosition to aim the sheen rather than reaching for more intensity. Both apply to the existing rig, so they are cheap to animate or bind to a control.
  • Give it width. The column count comes from the container's aspect, so a wide box gets a proper wall and a narrow one gets a column of tiles.
  • Treat rimColor as the brand dial. It is the light that reads on the bevels, and it changes the character of the wall more than tileColor does.

Avoid:

  • Do not use maxTiles to thin the wall out. It truncates the list rather than sampling it, and because tiles are generated top row first, a low cap removes the bottom of the design and leaves the top intact.
  • Do not set both rimColor and glowColor. glowColor wins, and the other silently does nothing.
  • Do not raise maxDisplacement much past the default with mode="flip". Flip already rotates a full half-turn, and adding travel on top makes tiles pass through their neighbours.
  • Do not put it in a short container. It holds a 500px floor, and below roughly that the row count bottoms out and the clusters meet in the middle where your content is.
  • Do not expect the wave to keep moving on its own. Every mode is driven by the pointer — with the pointer away, the wall is still by design.

Props

A wall of bevelled tiles, clustered around the edges of the frame and left open through the middle so your content sits in the gap. A key light in front, cross-fills from either side and a rim light raking up from below pick out the bevels as the pointer passes and pushes them on a spring. Three responses: a flip, a rolling wave, or a press inward. The whole wall is a single draw call, and once the springs settle it leaves the frame loop entirely rather than idling.

<GlowTile />

The tile wall, its lighting and the pointer response. Paints its own background and fills its container.

PropTypeDefaultDescription
layout"tetris" | "cascade""tetris"How the tiles are arranged. "tetris" is dense stepped clusters hugging all four corners and the mid-edges; "cascade" is sparser and more scattered, with floating tiles along a diagonal.
mode"wave" | "flip" | "depress""flip"What the pointer does to them. "flip" turns tiles over as it passes, "wave" rolls a ripple outward from the cursor, "depress" pushes them straight back into the wall.
theme"obsidian" | "paper" | "emerald" | "solar""paper"Colour preset. Sets the background, tile colour and all four lights at once — paper is off-white with a cool blue key, obsidian is near-black with a blue rim, emerald and solar are dark with green and amber rims.
tileScalenumber1.0Size of one tile. Larger tiles mean fewer of them, since the grid is fitted to the container.
gapnumber0.16Space between tiles, in scene units. Also affects how many fit, so it changes density as well as spacing.
maxTilesnumber—Hard cap on the tile count. Truncates rather than samples — see the note in Don't.
influenceRadiusnumber2.4How far the cursor's effect reaches, in scene units. Widen it for a softer, larger swell.
maxDisplacementnumber0.40How far a tile travels at full engagement. Tiles are 0.08 deep, so this is several times their own thickness.
tensionnumber0.18Spring stiffness — how hard a tile is pulled toward where the cursor wants it.
dampingnumber0.80How much speed survives each frame. Lower settles faster and flatter; higher keeps tiles ringing after the cursor has gone.
tileColorstringtheme presetTile face colour, overriding the theme's.
backgroundColorstringtheme presetColour behind the wall, overriding the theme's.
lightColorstringtheme presetThe key light, which sets the overall brightness and the direction the tiles look lit from.
lightPosition[number, number, number][0, 8, 12]Where the key light sits, as [x, y, z]. In front and above by default, which is what spreads the sheen across the perimeter clusters rather than one corner. Moving it does not rebuild the scene.
rimColorstringtheme presetThe rim light, thrown from below and behind. This is the colour that reads on the bevels and gives the wall its glow.
rimPosition[number, number, number][0, -8, 0.5]Where the rim light sits, as [x, y, z]. Below and almost level with the wall, so it rakes across the bevels — push z negative to throw it behind them instead.
glowColorstring—Alias for rimColor. If both are set, this one wins.
childrenReact.ReactNode—Overlay content, rendered above the wall in a pointer-transparent layer. Anything interactive needs pointer-events-auto of its own.
disableAdaptiveQualitybooleanfalseRenders at full pixel density regardless of what the device probe reports. Left off, weaker hardware is capped a step or two down.
classNamestring""Applied to the wrapper.
styleReact.CSSProperties—Inline styles merged onto the wrapper, after backgroundColor.
mount"auto" | "eager""auto"When to build the wall. The default waits until the page has frame headroom to spare. Set "eager" to start immediately. Note this defaults the opposite way from the components that build a 3D scene: those start eagerly and take "auto" to defer. Both mean the same thing by "auto" — let the runtime pick the moment — the default just matches what each component already did. Neither setting takes it off the shared frame loop or overrides the reduced-motion preference.

<FacadeLayout />

type

Tile arrangement: "tetris" or "cascade".

<FacadeMode />

type

Pointer response: "wave", "flip" or "depress".

<FacadeTheme />

type

Colour preset: "obsidian", "paper", "emerald" or "solar".

It reads the visitor's reduced-motion preference and holds the wall flat — the tiles stop responding to the pointer and stay where they are. What remains is a lit, bevelled surface, which is most of what the component is for. It also goes to sleep straight away in that state rather than waiting for the pointer to leave.
The entire wall is one instanced draw call however many tiles it holds, so tile count is cheap. The larger saving is that it does not idle: once the springs settle and the pointer is away, it leaves the shared frame loop completely and costs nothing until the pointer comes back. It also drops pixel density on weaker hardware, which disableAdaptiveQuality turns off.
The grid is fitted to the container rather than the window, and it watches its own box, so it stays correct inside a panel that resizes on its own. Column and row counts come from the container's aspect ratio; when they change the wall is rebuilt so the clusters stay attached to the corners, and when they do not, a resize only moves the camera.
Client component. It opens a 3D drawing context on mount — import it dynamically with ssr: false if your route renders on the server.
It draws on the shared frame loop rather than starting one of its own, so putting several animated components on a page costs one callback, not one each, and the scheduler can set decorative work aside when frames get tight. The wall goes to sleep when nothing is moving — it leaves the loop entirely rather than returning early from a callback, so an idle facade is genuinely off the frame budget rather than merely cheap. Tile detail follows the device tier, decided once for the whole page.
Back to all components