Absolute stage
Full-frame surface with stable clipping and positioning.
Customize
import {Scene, Video} from "odori";
import {AbsoluteStage} from "../components/absolute-stage/absolute-stage";
<Video>
<Scene id="absolute-stage" duration="3s">
<AbsoluteStage
align="center"
padding={120}
showBounds={true}
/>
</Scene>
</Video>Installation
pnpm odori add component absolute-stagenpx odori add component absolute-stagebunx odori add component absolute-stageEdit the source in videos/components/absolute-stage/. Use odori diff to compare upstream changes and odori update to apply updates.
Copy these files into your project
videos/components/absolute-stage/absolute-stage.tsx
import type {CSSProperties, ReactNode} from "react";
import {Fill, useBrand, useDesignScale, useVideo} from "odori";
export type AbsoluteStageProps = {
children?: ReactNode;
/** Where the content sits inside the frame. */
align?: "center" | "start" | "end";
/** Inset from the frame edge, in design pixels. */
padding?: number;
/** Draw the frame edge, useful while composing. */
showBounds?: boolean;
style?: CSSProperties;
};
/**
* The plainest full-frame surface: predictable clipping, one alignment
* decision, and padding that scales with the format. Reach for this when a
* scene needs structure without the grid and glow of the branded stage.
*/
export const AbsoluteStage = ({children, align = "center", padding = 120, showBounds = false, style}: AbsoluteStageProps) => {
const brand = useBrand();
const scale = useDesignScale();
const {width, height} = useVideo();
return (
<Fill style={{background: brand.colors.background, overflow: "hidden", ...style}}>
<Fill
style={{
alignItems: "center",
display: "flex",
justifyContent: align === "center" ? "center" : align === "start" ? "flex-start" : "flex-end",
flexDirection: "column",
padding: padding * scale,
}}
>
{children}
</Fill>
{showBounds ? (
<Fill
style={{
border: `${2 * scale}px dashed ${brand.colors.border}`,
inset: padding * scale,
pointerEvents: "none",
}}
>
<span
style={{
color: brand.colors.muted,
fontFamily: brand.typography.mono,
fontSize: 22 * scale,
padding: 12 * scale,
}}
>
{width} x {height}
</span>
</Fill>
) : null}
</Fill>
);
};
videos/components/absolute-stage/absolute-stage.preview.tsx
import {defineComponentPreview} from "odori/preview";
import {AbsoluteStage} from "./absolute-stage";
export default defineComponentPreview({
title: "Absolute stage",
category: "Foundation",
description: "Full-frame surface with stable clipping and positioning.",
component: AbsoluteStage,
canvas: {width: 1920, height: 1080, duration: "3s"},
controls: {
align: {type: "select", defaultValue: "center", options: ["center", "start", "end"]},
padding: {type: "number", defaultValue: 120, min: 0, max: 320},
showBounds: {type: "boolean", defaultValue: true},
},
examples: [
{name: "Bounds", props: {showBounds: true, children: "Content sits here"}},
{name: "Clean", props: {showBounds: false, children: "Content sits here"}},
],
});
Add it to a scene
import {Scene, Video} from "odori";
import {AbsoluteStage} from "../components/absolute-stage/absolute-stage";
<Video>
<Scene id="absolute-stage" duration="3s">
<AbsoluteStage
align="center"
padding={120}
showBounds={true}
/>
</Scene>
</Video>Timing contract
Use these durations and content limits when composing a scene. Run odori test to check your video.
- Family
- Foundation
- Recommended duration
- 90 frames · 3s
- Minimum duration
- 24 frames · 0.8s
- Entrance
- 0 frames
- Exit
- 0 frames
- Reduced motion
- no motion of its own
- Requires
- sans font
- Content limits
- none
Props
| Prop | Type | Default | Required |
|---|---|---|---|
children | ReactNode | — | — |
alignWhere the content sits inside the frame. | "center" | "start" | "end" | "center" | — |
paddingInset from the frame edge, in design pixels. | number | 120 | — |
showBoundsDraw the frame edge, useful while composing. | boolean | false | — |
style | CSSProperties | — | — |
Related components
All componentsSafe areaFormat-aware title and action safety boundaries.Split layoutResponsive two-up composition for proof and explanation.StageThe shared backdrop: hairline grid, soft glow, and vignette.AccordionSections opening one at a time, the outgoing one closing as the next grows.Area chartFilled trend reveal for volume and cumulative change.Aurora veilFlowing curtains of colored light.