Curved Carousel
An immersive artwork cylinder with Image, Depth, Rounded and Video modes.
Install the component, then paste your configured usage. Your settings are included in the code below.
Pro source comes with Arclen UI Pro. See plans
| Property | Type | Default |
|---|---|---|
variantMode Selects the complete cylinder geometry and automatic media treatment. Geometry controls customize each mode proportionally. Options: A (A · Image), B (B · Depth), C (C · Rounded), D (D · Video) | select | "A" |
imagesArtwork sequence Bundled portrait-01 through portrait-08 keys or HTTPS images. Empty restores local artwork; invalid URLs are rejected. Minimum 0 itemsMaximum 12 itemsUp to 2048 characters per item | string-list | ["portrait-01","portrait-02","portrait-03","portrait-04","portrait-05","portrait-06","portrait-07","portrait-08"] |
titlesArtwork titles Minimum 0 itemsMaximum 12 itemsUp to 120 characters per item | string-list | ["Red round sunglasses portrait","Cobalt blazer portrait","Yellow paper crown portrait","Lilac padded hood portrait","Amber spectacles portrait","Apricot fluffy hat portrait","Coral sunglasses portrait","Yellow party hat portrait"] |
mediaModeMedia mode Automatic uses stills for A/B/C and matching bundled video loops for D. Override to use stills or configured video in any mode. Options: auto, images, video | select | "auto" |
videoSourcesVideo sequence Optional portrait-motion-01 through portrait-motion-08 keys or HTTPS URLs. Empty in Video mode restores matching bundled loops. At most nine projected-visible videos play. Minimum 0 itemsMaximum 12 itemsUp to 2048 characters per item | string-list | [] |
cardWidthCard width baseline Image-mode local width. Other modes scale their own measured plane width proportionally to this value. 120–320Step 1 | number | 303 |
cardHeightCard height baseline Image-mode local height. Other modes scale their own plane height proportionally to this value. 160–440Step 1 | number | 405 |
gapCard gap 8–64Step 1 | number | 24 |
curvatureCurvature 0.1–1Step 0.01 | number | 0.35 |
radiusCorner radius 0–80Step 1 | number | 20 |
speedTravel rate (turns/min) Full cylinder turns per minute. Hover slows Image, Depth and Rounded travel to 70%; Video retains its configured rate. 0–2Step 0.05 | number | 1.25 |
directionTravel direction Options: forward, reverse | select | "forward" |
autoplayAutoplay | boolean | true |
pausedPause playback | boolean | false |
backgroundStage color | color | "#000000" |
textColorText color | color | "#f5f3ef" |
headingCollection heading Optional custom collection copy. Empty keeps the stage clean. Up to 100 characters | text | "" |
eyebrowCollection label Optional custom collection copy. Empty keeps the stage clean. Up to 100 characters | text | "" |
fontCaption font Font for transport labels and optional custom copy. Options: system, serif, mono | select | "system" |
captionSizeControl text size Text size for transport and optional custom copy. 10–24Step 1 | number | 14 |
heightStandalone height Used only with standalone sizing. 320–1200Step 1 | number | 720 |
sizingSizing Options: fill, standalone | select | "fill" |
labelAccessible label Up to 160 characters | text | "Curved portrait collection" |
Curved Carousel
A portrait collection on a concave cylinder, with four working modes: Image, Depth, Rounded and Video. The centre recedes while the outer artworks lean toward the viewer. Drag the ring, use the transport buttons, or focus it and press Left / Right.
Installation
Keep src, assets and component.json together. The React wrapper imports its stylesheet and uses your application's React installation. The core has no runtime dependencies. It uses local original Arclen artwork and system fonts.
import { CurvedCarousel } from './curved-carousel/src/react';
export default function Collection() {
return <CurvedCarousel variant="A" sizing="standalone" height={900} />;
}Default sizing="fill" fills a parent with an explicit height. Use sizing="standalone" to apply height. className and style apply to the outer React wrapper. Edge artworks intentionally crop at the stage boundary. Small containers frame the cylinder proportionally while retaining usable controls.
Four modes
Selecting variant applies its complete cylinder geometry, including when all inspector defaults are supplied. The previews select only their mode. No preset geometry values are needed.
| Mode | Local artwork plane | Desktop cylinder | Compact cylinder | | --- | --- | --- | --- | | A · Image | 303 × 405 | 18 slots, radius 967, perspective 1800 | 9 slots, radius 450, perspective 700 | | B · Depth | 398 × 608 | 16 slots, radius 1237, perspective 500 | 8 slots, radius 550, perspective 500 | | C · Rounded | 310 × 473 | 10 slots, radius 520, perspective 700 | 10 slots, radius 520, perspective 700 | | D · Video | 303 × 430 | 18 slots, radius 967, perspective 1364 | 9 slots, radius 450, perspective 700 |
Desktop is 1200px and wider; compact is below 810px. Between them, A uses perspective 1500; B radius 1100; C perspective 600; D perspective 1500. Their centred clipping windows also adapt to the mode and width. Corner radius defaults to 20 local pixels in every mode. Rounded describes the stronger curved composition.
cardWidth and cardHeight are baseline sizing controls. The Image baseline is 303 × 405. Other modes scale their own plane proportionally: cardWidth={151.5} halves each mode's width. gap, curvature and radius remain independently adjustable in every mode. Custom copy is optional and empty by default.
<CurvedCarousel
variant="B"
sizing="standalone"
height={900}
cardWidth={280}
curvature={0.45}
radius={16}
/>Video
mediaMode="auto" uses stills for A/B/C and the eight matching bundled portrait loops for D. Each loop uses the same-number original artwork as its poster. Video is muted, inline and looped. No audio or third-party footage is included.
Use mediaMode="images" for a static-media version of any mode. Use mediaMode="video" with videoSources to configure video in another mode. Video sources accept portrait-motion-01 through portrait-motion-08, HTTPS URLs, or empty entries. An empty source list in D restores matching bundled loops. A custom HTTPS image without a matching bundled loop retains its still unless a video source is supplied.
<CurvedCarousel
variant="D"
sizing="standalone"
height={900}
videoSources={['portrait-motion-01', 'https://your-domain.example/space.mp4']}
/>At most three artworks nearest the stage centre may play. Other videos have their sources released and retain stills. This includes cropped edge videos while excluding hidden cylinder faces. Source keys stay compact in server markup; local video bytes are resolved only when a visible video is activated. Source integrations include assets/motion-clips.ts and all eight MP4 files. Static new URL(..., import.meta.url) entries let Vite and Next emit separate video assets without embedding video bytes in JavaScript; no MP4 loader configuration is required. The HTML package emits the same local video files. Bundled delivery files use 60 fps duplicate frames of the original 24 fps motion, with the same ten-second duration and no interpolation.
Pause, external suspension, offscreen observation and hidden documents stop playback. Reduced motion shows stills until an intentional Play action. Failure or autoplay denial returns to the matching still without repeated requests; intentional Play may retry. Missing and short companion lists keep geometry reserved. Updating or destroying a component releases replaced video sources and listeners.
Motion and input
Travel defaults to 1.25 cylinder turns per minute, or 7.5 degrees per second. Mouse hover slows Image, Depth and Rounded to 70%; Video retains its configured rate. speed={0} leaves manual navigation available.
Horizontal drag moves the cylinder by 0.2 degrees per pixel, then continues with decaying inertia without snapping. A new drag interrupts inertia immediately. Vertical touch gestures retain page scrolling; the component does not intercept wheel events. Arrow buttons use an interruptible approach of roughly 500ms. Reduced motion makes manual button selection immediate and removes release inertia. Hidden or suspended time is not replayed on resume.
Left / Right and Home apply only while the ring has focus. Transport buttons have visible keyboard focus and accessible labels. Automatic movement does not repeatedly announce selection changes. The titles list supplies artwork descriptions; missing titles become numbered labels.
HTML and vanilla JavaScript
The downloaded HTML package includes initialization, styles and local media. Source integrations use a bundler that supports TypeScript, CSS and WebP imports:
import { mount } from './curved-carousel/src/core';
import './curved-carousel/src/styles.css';
const host = document.querySelector<HTMLElement>('#collection')!;
const carousel = mount(host, { variant: 'D', sizing: 'standalone', height: 900 });
carousel.update({ variant: 'C', sizing: 'standalone', height: 900 });
carousel.pause();
carousel.resume();
carousel.destroy();render(settings, id?) returns escaped server markup. resolveSettings strictly validates known settings and rejects unknown keys. update replaces the complete configuration, resets selection and releases previous resources; omitted fields restore manifest defaults. Rejected updates leave the current instance intact. External pause / resume preserve the local Play/Pause choice. destroy removes owned listeners, observers, animation frames, media sources and markup. Instances own independent resources.
Controls
The manifest is authoritative. Empty images restores the eight included artworks; invalid URLs are rejected. Lists support at most 12 entries. height applies only to standalone sizing. Geometry defaults are mode baselines, rather than required preview presets. Optional custom heading and label are empty by default. Font and text size affect the transport and optional custom copy.
| Setting | Default | Range or options |
| --- | --- | --- |
| variant | "A" | A, B, C, D |
| images | 8 entries | 0–12 entries |
| titles | 8 entries | 0–12 entries |
| mediaMode | "auto" | auto, images, video |
| videoSources | [] | 0–12 entries |
| cardWidth | 303 | 120–320 |
| cardHeight | 405 | 160–440 |
| gap | 24 | 8–64 |
| curvature | 0.35 | 0.1–1 |
| radius | 20 | 0–80 |
| speed | 1.25 | 0–2 |
| direction | "forward" | forward, reverse |
| autoplay | true | true / false |
| paused | false | true / false |
| background | "#000000" | Six/eight-digit hex or transparent |
| textColor | "#f5f3ef" | Six/eight-digit hex or transparent |
| heading | "" | Up to 100 characters |
| eyebrow | "" | Up to 100 characters |
| font | "system" | system, serif, mono |
| captionSize | 14 | 10–24 |
| height | 720 | 320–1200 |
| sizing | "fill" | fill, standalone |
| label | "Curved portrait collection" | Up to 160 characters |
Rights
The portrait artwork and portrait videos are original Arclen assets supplied under the Arclen UI Pro licence. Artwork notices and hashes are in assets/ARTWORK-NOTICE.md, assets/ARTWORK-PROVENANCE.md and assets/ARTWORK-LICENSE.md. Motion creation details and licences are in assets/MOTION-PROVENANCE.md and assets/MOTION-LICENSE.md. assets/INVENTORY.json records included media hashes and byte sizes.
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.