Transition
Enter, exit, and shared-element motion between pages.
SlideTransition describes what happens when the active Page changes. There
is no default animation: pages snap unless the deck exports a transition or an
incoming page defines its own override.
import type { Page, SlideTransition } from '@open-slide/core';
const Cover: Page = () => <section>…</section>;
const Agenda: Page = () => <section>…</section>;
export const transition: SlideTransition = {
duration: 220,
exit: {
duration: 140,
easing: 'cubic-bezier(0.4, 0, 1, 1)',
keyframes: [
{ opacity: 1, transform: 'translateY(0)' },
{ opacity: 0, transform: 'translateY(-4px)' },
],
},
enter: {
duration: 220,
delay: 80,
easing: 'cubic-bezier(0, 0, 0.2, 1)',
keyframes: [
{ opacity: 0, transform: 'translateY(6px)' },
{ opacity: 1, transform: 'translateY(0)' },
],
},
};
export default [Cover, Agenda] satisfies Page[];prefers-reduced-motion: reduce is honored automatically.
Where It Lives
There are two declaration surfaces:
export const transitionin the slide module sets the deck default.Page.transition = …sets an override for one page.
The incoming page wins. Navigating Cover → Agenda uses
Agenda.transition ?? module.transition; the selected exit runs on
Cover, and enter runs on Agenda. Navigating backward uses the page you
are returning to.
const Cover: Page = () => <section>…</section>;
const Agenda: Page = () => <section>…</section>;
export const transition: SlideTransition = {
duration: 220,
enter: {
keyframes: [{ opacity: 0 }, { opacity: 1 }],
},
};
Agenda.transition = {
duration: 320,
enter: {
keyframes: [
{ opacity: 0, transform: 'scale(0.98)' },
{ opacity: 1, transform: 'scale(1)' },
],
},
};Direction
During a page transition, the wrapper exposes:
| Surface | Forward | Backward |
|---|---|---|
--osd-dir | 1 | -1 |
data-osd-dir | forward | backward |
Use it when motion has a literal direction:
{
transform: 'translateX(calc(var(--osd-dir, 1) * 8px))',
}Most decks should keep a single restrained motion family: short duration, subtle distance, opacity included, and no different transition vocabulary on every page.
Shared Elements
SlideTransition.sharedElements enables SharedElement
matching for objects that should visually continue across two pages.
export const transition: SlideTransition = {
duration: 600,
sharedElements: {
duration: 600,
easing: 'cubic-bezier(0.22, 1, 0.36, 1)',
},
};For the full schema and a reusable family of examples, see SlideTransition.