Skip to main content
Fills define how a shape or layer is painted. Every fill builder in @abloatai/decks returns a Fill object that you place in a layer’s fills array. Fills are composited from bottom to top — so the first entry in the array sits at the back and each subsequent entry layers on top — giving you the same stacking model as Figma. The SDK ships six builders covering the four fill types: 'solid', 'gradient', 'image', and 'shader'.
import {
  shape,
  solidFill,
  linearGradient,
  radialGradient,
  meshGradient,
  imageFill,
  shaderFill,
} from '@abloatai/decks';

solidFill

solidFill(color, opacity?) returns a flat, single-color fill. Pass any CSS color string — hex, rgb(), rgba(), or a theme CSS variable — and an optional opacity multiplier between 0 and 1.
// Opaque brand color
solidFill('#5B4CF5')

// 50 % transparent via rgba + opacity shorthand
solidFill('rgba(91,76,245,0.5)', 0.5)

// Theme token reference
solidFill('var(--slide-brand)')
You can use colorRef('brand') from @abloatai/decks to produce 'var(--slide-brand)' without typing the CSS variable name by hand.

linearGradient

linearGradient(stops, opts?) sweeps a gradient along a straight line at angle degrees (default 180, which runs top→bottom). Each stop is a { color, at? } object where at is a 01 position along the gradient axis.
stops
{ color: string; at?: number }[]
required
Gradient color stops in order. Omit at to let the browser distribute stops evenly.
opts.angle
number
Angle in degrees. 0 = bottom→top, 90 = left→right, 180 = top→bottom (default), 270 = right→left.
opts.opacity
number
Overall fill opacity from 0 to 1. Defaults to 1.
// Two-stop diagonal gradient
linearGradient(
  [{ color: '#5B4CF5' }, { color: '#EEF0FF' }],
  { angle: 135 },
)

// Three-stop top-to-bottom with explicit positions
linearGradient(
  [
    { color: '#0066CC', at: 0 },
    { color: '#5B4CF5', at: 0.5 },
    { color: '#EEF0FF', at: 1 },
  ],
  { angle: 180, opacity: 0.9 },
)

radialGradient

radialGradient(stops, opts?) radiates outward from a center point. The optional at option is an [x, y] pair in 01 canvas coordinates ([0.5, 0.5] is the center).
stops
{ color: string; at?: number }[]
required
Color stops along the radial axis from center to edge.
opts.at
[number, number]
Center of the gradient as [x, y] fractions of the fill box. Defaults to the CSS default (centered).
opts.opacity
number
Overall fill opacity from 0 to 1. Defaults to 1.
// White center fading to brand color, centered
radialGradient([
  { color: '#fff', at: 0 },
  { color: '#5B4CF5', at: 1 },
])

// Off-center glow in the top-left quadrant
radialGradient(
  [{ color: '#EEF0FF', at: 0 }, { color: 'transparent', at: 1 }],
  { at: [0.2, 0.2] },
)

meshGradient

meshGradient(points, opts?) layers multiple positioned radial blobs to create a soft, organic mesh effect — the kind of blurred color-cloud background common in modern design. Each point is an { color, at, radius? } object where at is an [x, y] position in 01 coordinates and radius controls the blob’s spread as a fraction of the fill box (default 0.5).
points
{ color: string; at: [number, number]; radius?: number }[]
required
Positioned color blobs. Each renders as a radial gradient and all layers are composited together.
opts.background
string
An optional CSS color placed behind all the blobs as a solid base.
opts.opacity
number
Overall fill opacity from 0 to 1. Defaults to 1.
meshGradient(
  [
    { color: '#5B4CF5', at: [0.15, 0.2],  radius: 0.55 },
    { color: '#6EE7F9', at: [0.75, 0.15], radius: 0.45 },
    { color: '#EEF0FF', at: [0.5,  0.85], radius: 0.6  },
  ],
  { background: '#0D0B1F' },
)
meshGradient compiles to stacked radial-gradient CSS layers. It works in every modern browser without any runtime dependency.

imageFill

imageFill(url, opts?) stretches an image over the fill box. Use ablo.images.upload() to get a hosted URL for local files before passing it here.
url
string
required
A fully-qualified https:// URL for the image. Must be one of the accepted MIME types: JPEG, PNG, GIF, WebP, SVG, or AVIF.
opts.objectFit
'cover' | 'contain' | 'fill'
How the image fits its box. 'cover' (default renderer behavior) crops to fill; 'contain' letterboxes; 'fill' stretches without preserving aspect ratio.
opts.opacity
number
Overall fill opacity from 0 to 1. Defaults to 1.
// Full-bleed cover image
imageFill('https://cdn.example.com/hero.jpg')

// Contained image at 80% opacity
imageFill('https://cdn.example.com/logo.png', {
  objectFit: 'contain',
  opacity: 0.8,
})

shaderFill

shaderFill(input, opacity?) applies an animated WebGL gradient powered by a named preset. The shader runs in the Ablo renderer and produces smooth, continuously animating backgrounds — no extra dependencies required on your end.
input.preset
ShaderPreset
required
One of 'aurora', 'ocean', 'sunset', 'ember', 'midnight', 'mint', 'candy', or 'custom'.
input.colors
{ color1: string; color2: string; color3: string }
required
Three CSS color strings that the shader blends together. Exact behavior varies by preset.
input.speed
number
Animation playback speed. Defaults to 0.2.
input.density
number
Pattern density / frequency. Defaults to 1.3.
input.animate
boolean
Whether the shader animates. Set to false for a static snapshot. Defaults to true.
opacity
number
Overall fill opacity from 0 to 1. Defaults to 1.
shaderFill({
  preset: 'aurora',
  colors: {
    color1: '#5B4CF5',
    color2: '#6EE7F9',
    color3: '#EEF0FF',
  },
  speed: 0.3,
  animate: true,
})

Using fills on shapes

The fills field on a shape layer accepts an array of Fill objects. The fills composite bottom-to-top, so you can combine a solid base with a gradient or image overlay in a single layer.
import { shape, meshGradient, solidFill } from '@abloatai/decks';

const heroBackground = shape({
  shape: 'rectangle',
  fills: [
    // Base color sits at the bottom of the stack
    solidFill('#0D0B1F'),
    // Mesh gradient composited on top
    meshGradient(
      [
        { color: '#5B4CF5', at: [0.15, 0.2],  radius: 0.55 },
        { color: '#6EE7F9', at: [0.8,  0.15], radius: 0.45 },
        { color: '#EEF0FF', at: [0.5,  0.9],  radius: 0.6  },
      ],
      { opacity: 0.7 },
    ),
  ],
  at: { x: 0, y: 0, w: 1920, h: 1080 },
});
Image fills require a hosted URL. Passing a data: URI or a local file path will fail schema validation. Upload the file first with ablo.images.upload() and use the returned URL.