Glow Tile
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.
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.
| Prop | Type | Default | Description |
|---|---|---|---|
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. |
tileScale | number | 1.0 | Size of one tile. Larger tiles mean fewer of them, since the grid is fitted to the container. |
gap | number | 0.16 | Space between tiles, in scene units. Also affects how many fit, so it changes density as well as spacing. |
maxTiles | number | — | Hard cap on the tile count. Truncates rather than samples — see the note in Don't. |
influenceRadius | number | 2.4 | How far the cursor's effect reaches, in scene units. Widen it for a softer, larger swell. |
maxDisplacement | number | 0.40 | How far a tile travels at full engagement. Tiles are 0.08 deep, so this is several times their own thickness. |
tension | number | 0.18 | Spring stiffness — how hard a tile is pulled toward where the cursor wants it. |
damping | number | 0.80 | How much speed survives each frame. Lower settles faster and flatter; higher keeps tiles ringing after the cursor has gone. |
tileColor | string | theme preset | Tile face colour, overriding the theme's. |
backgroundColor | string | theme preset | Colour behind the wall, overriding the theme's. |
lightColor | string | theme preset | The 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. |
rimColor | string | theme preset | The 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. |
glowColor | string | — | Alias for rimColor. If both are set, this one wins. |
children | React.ReactNode | — | Overlay content, rendered above the wall in a pointer-transparent layer. Anything interactive needs pointer-events-auto of its own. |
disableAdaptiveQuality | boolean | false | Renders at full pixel density regardless of what the device probe reports. Left off, weaker hardware is capped a step or two down. |
className | string | "" | Applied to the wrapper. |
style | React.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 />
typeTile arrangement: "tetris" or "cascade".
<FacadeMode />
typePointer response: "wave", "flip" or "depress".
<FacadeTheme />
typeColour preset: "obsidian", "paper", "emerald" or "solar".
ssr: false if your route renders on the server.