Gradient Bars
An edge-anchored gradient field with a curved hill, flat fade or ascending ramp.
Install the component, then paste your configured usage. Your settings are included in the code below.
curl -fsS https://arclenui.dev/arclen-ui.mjs -o arclen-ui.mjs && node arclen-ui.mjs add gradient-bars --origin https://arclenui.dev --settings '{"variant":"hill","shape":"auto","barCount":45,"peakHeight":100,"gap":0,"spread":32,"angle":0,"anchor":"bottom","stops":"5","baseColor":"#020612","colorA":"#ffe2a0","colorB":"#ff985d","colorC":"#e56286","colorD":"#6a5abb","tipColor":"#030817","entry":"auto","entryDuration":0.8,"stagger":0.08,"pulse":0.3,"pulseDuration":2,"speed":1,"animate":true,"heightMode":"fill","fixedHeight":560,"radius":0}'import { GradientBars } from "@/components/gradient-bars";
export default function Example() {
return <GradientBars {...{
"variant": "hill",
"shape": "auto",
"barCount": 45,
"peakHeight": 100,
"gap": 0,
"spread": 32,
"angle": 0,
"anchor": "bottom",
"stops": "5",
"baseColor": "#020612",
"colorA": "#ffe2a0",
"colorB": "#ff985d",
"colorC": "#e56286",
"colorD": "#6a5abb",
"tipColor": "#030817",
"entry": "auto",
"entryDuration": 0.8,
"stagger": 0.08,
"pulse": 0.3,
"pulseDuration": 2,
"speed": 1,
"animate": true,
"heightMode": "fill",
"fixedHeight": 560,
"radius": 0
}} />;
}| Property | Type | Default |
|---|---|---|
variantDirection Options: hill (A · Curved hill), flat (B · Flat field), ramp (C · Ascending ramp) | select | "hill" |
shapeSilhouette Options: auto (Follow direction), hill (Curved hill), flat (Full height), ramp (Ascending ramp) | select | "auto" |
barCountBar count 3–96Step 1 | number | 45 |
peakHeightPeak height 20–100Step 1 | number | 100 |
gapBar gap 0–12Step 0.5 | number | 0 |
spreadGradient spread 0–80Step 1 | number | 32 |
angleGradient angle -90–90Step 1 | number | 0 |
anchorAnchor Options: bottom (Bottom), top (Top) | select | "bottom" |
stopsGradient stops Three uses First, Second and Gradient tip. Four adds Third. Five also adds Fourth. Options: 3 (Three stops), 4 (Four stops), 5 (Five stops) | select | "5" |
baseColorBackground | color | "#020612" |
colorAFirst color | color | "#ffe2a0" |
colorBSecond color | color | "#ff985d" |
colorCThird color Used by four- and five-stop gradients. | color | "#e56286" |
colorDFourth color Used by five-stop gradients. | color | "#6a5abb" |
tipColorGradient tip | color | "#030817" |
entryEntry order Options: auto (Follow direction), center (Center out), forward (Left to right), reverse (Right to left), together (Together) | select | "auto" |
entryDurationEntry duration 0.2–1.5Step 0.05 | number | 0.8 |
staggerEntry stagger 0–0.16Step 0.01 | number | 0.08 |
pulsePulse strength Fractional compression of the whole strip, including its color gradient. 0–0.5Step 0.01 | number | 0.3 |
pulseDurationPulse duration 1–8Step 0.1 | number | 2 |
speedMotion speed 0.25–2Step 0.05 | number | 1 |
animateAnimate | boolean | true |
heightModeHeight mode Options: fill (Fill container), fixed (Fixed height) | select | "fill" |
fixedHeightFixed height Applies when Height mode is Fixed height. 160–1200Step 10 | number | 560 |
radiusCorner radius 0–48Step 1 | number | 0 |
Gradient Bars
An edge-anchored field of colored strips with coordinated entry and subtle breathing motion. Choose a curved hill, a flat field or an ascending ramp. All artwork is generated by CSS.
React
import { GradientBars } from './components/gradient-bars';
<div style={{ height: 560 }}>
<GradientBars variant="ramp" barCount={7} stops="3"
colorA="#baffc6" colorB="#3454f1" tipColor="#121212" spread={0} pulse={0.17} />
</div>The React entry imports its CSS. Every setting is a regular prop; className, style and paused are also supported. This scene is decorative and has aria-hidden="true". Place meaningful text and controls outside it.
Use heightMode="fill" inside a container with a defined height. Use heightMode="fixed" fixedHeight={420} for a scene with its own height. Width follows the host. radius clips the scene, and anchor="top" turns the composition toward the top edge.
Directions and controls
The default curved hill uses an apricot-to-dusk palette with a charcoal tip and rises from the center outward. The flat preset uses 24 equal-height strips with a blue-to-pale four-stop gradient and left-to-right entry. The ramp preset uses seven broad strips, a green-to-blue-to-charcoal three-stop gradient and right-to-left entry. Its silhouette increases linearly from 10% to 100% height. All directions rise from their anchored edge; their entry order and silhouette differ. Direction controls shape and order; choose the complete preset to apply its count, palette and pulse settings.
shape="auto" and entry="auto" follow the direction. Override them to combine a silhouette with a different entry order. barCount changes the rhythm, peakHeight changes the silhouette's maximum height, and gap separates strips. In narrow hosts the gap is capped so bars retain at least 60% of the available width. spread fans the gradient angles across the field; angle turns all gradients together. stops selects three, four or five evenly spaced color stops in OKLCH. Three uses colorA, colorB and tipColor. Four adds colorC before the tip; five also adds colorD. The remaining color controls retain their values while unused, so increasing the stop count restores them. baseColor is the surrounding background. Browsers without OKLCH gradient support use the declared sRGB fallback.
entryDuration and stagger set entry timing in seconds. At the defaults, hill entry takes 0.8 seconds per strip with 0.08-second center-out delays. pulse changes breathing depth, and pulseDuration sets the duration of each alternating half-cycle. The default pulse compresses each complete strip from 100% to 70% of its resting scale over two seconds, then returns over two seconds. Each strip starts pulsing when its own entrance completes; there is no extra odd/even delay. The flat preset uses 24% compression; the ramp preset uses 17%. The selected pulse value applies directly in every direction. Strips keep the full layout height and use scale transforms for the silhouette, entry and pulse, so the whole gradient compresses with them. At zero gap, adjacent strips overlap by one pixel to avoid hairline seams. speed scales all timing together. Palette, height and timing updates preserve existing nodes; direction, shape, count and entry-order changes rebuild the strips and replay entry. Gradient stop-count and palette edits preserve the strip nodes. The generated settings table lists every default and bound.
HTML and vanilla
Copy the complete HTML bundle to your static host and use component.html with component.css and component.js. Relative URLs work under a subpath. Each host reads its own serialized settings.
import { mount, defaults } from './components/gradient-bars/src/core';
import './components/gradient-bars/src/styles.css';
const host = document.querySelector<HTMLElement>('#bars');
if (!host) throw new Error('Missing bars host');
const scene = mount(host, { variant: 'flat', pulse: 0.02 });
scene.update({ colorA: '#f4a261', spread: 48 });
scene.pause();
scene.resume();
scene.update(defaults);
// Call before removing or reusing the host:
scene.destroy();render(settings) provides complete server-rendered markup, and resolveSettings(unknown) validates before rendering. update merges partial patches into current settings. Unknown keys, fractional counts, unsafe colors and out-of-range numbers throw before the current scene changes. destroy() is idempotent, removes owned nodes/listeners/observers and restores the host's original children. It does not change host attributes or styles. Destroy before mounting another controller on the same host.
Accessibility and fallback
Reduced motion and animate={false} skip entry and show the complete still silhouette. pause() freezes entry and pulse at their current state. Native document-hidden and offscreen states pause both; visibility changes preserve manual pause. Without IntersectionObserver, document visibility and manual pause still work. Without matchMedia, CSS still honors reduced motion.
SSR and no-JavaScript markup display the settled composition. The HTML delivery also includes its rendered poster. The component owns no JavaScript animation frames or timers, does not fetch resources and has no GPU requirement.
Assets and rights
The strips, gradient palette and motion are original CSS artwork. There are no image, font or icon assets and no npm runtime dependencies. NOTICE records this inventory; LICENSE contains the source license.
The preview runs the component’s own JavaScript. It respects reduced motion and pauses when off screen. The HTML bundle includes a poster fallback.
Every setting in this panel comes from the component manifest. Preview size, pause and replay stay in the inspector.