The slide transition is usually used for creating a carousel which animates different panels into view horizontally.
The slide transition can be created by using a SlideContainer and Slide
components. The SlideContainer requires the transition direction prop and
each Slide requires an active state to trigger the transition.
"use client";
import { Box } from "@react-md/core/box/Box";
import { SegmentedButton } from "@react-md/core/segmented-button/SegmentedButton";
import { SegmentedButtonContainer } from "@react-md/core/segmented-button/SegmentedButtonContainer";
import { Slide } from "@react-md/core/transition/Slide";
import { SlideContainer, type SlideDirection } from "@react-md/core/transition/SlideContainer";
import { Typography } from "@react-md/core/typography/Typography";
import { type ReactElement, useState } from "react";
interface State {
page: 1 | 2 | 3;
direction: SlideDirection;
}
export default function SimpleExample(): ReactElement {
const [state, setState] = useState<State>({
page: 1,
direction: "forward",
});
const { page, direction } = state;
const setPage = (page: 1 | 2 | 3): void => {
setState((prev) => ({
page,
direction: prev.page < page ? "forward" : "backward",
}));
};
return (
<Box stacked fullWidth>
<SegmentedButtonContainer>
<SegmentedButton
selected={page === 1}
onClick={() => {
setPage(1);
}}
>
Page 1
</SegmentedButton>
<SegmentedButton
selected={page === 2}
onClick={() => {
setPage(2);
}}
>
Page 2
</SegmentedButton>
<SegmentedButton
selected={page === 3}
onClick={() => {
setPage(3);
}}
>
Page 3
</SegmentedButton>
</SegmentedButtonContainer>
<SlideContainer direction={direction}>
<Slide active={page === 1}>
<Typography type="headline-4">Page 1</Typography>
</Slide>
<Slide active={page === 2}>
<Typography type="headline-4">Page 2</Typography>
</Slide>
<Slide active={page === 3}>
<Typography type="headline-4">Page 3</Typography>
</Slide>
</SlideContainer>
</Box>
);
}
The slide transition can also be vertical instead of horizontal by enabling the vertical prop.
"use client";
import { Box } from "@react-md/core/box/Box";
import { SegmentedButton } from "@react-md/core/segmented-button/SegmentedButton";
import { SegmentedButtonContainer } from "@react-md/core/segmented-button/SegmentedButtonContainer";
import { Slide } from "@react-md/core/transition/Slide";
import { SlideContainer, type SlideDirection } from "@react-md/core/transition/SlideContainer";
import { Typography } from "@react-md/core/typography/Typography";
import { type ReactElement, useState } from "react";
interface State {
page: 1 | 2 | 3;
direction: SlideDirection;
}
export default function VerticalExample(): ReactElement {
const [state, setState] = useState<State>({
page: 1,
direction: "forward",
});
const { page, direction } = state;
const setPage = (page: 1 | 2 | 3): void => {
setState((prev) => ({
page,
direction: prev.page < page ? "forward" : "backward",
}));
};
return (
<Box stacked fullWidth>
<SegmentedButtonContainer>
<SegmentedButton
selected={page === 1}
onClick={() => {
setPage(1);
}}
>
Page 1
</SegmentedButton>
<SegmentedButton
selected={page === 2}
onClick={() => {
setPage(2);
}}
>
Page 2
</SegmentedButton>
<SegmentedButton
selected={page === 3}
onClick={() => {
setPage(3);
}}
>
Page 3
</SegmentedButton>
</SegmentedButtonContainer>
<SlideContainer direction={direction} vertical>
<Slide active={page === 1}>
<Typography>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec feugiat diam et mauris
dapibus bibendum. Praesent vehicula maximus egestas. Mauris lacinia lectus elit, quis
placerat massa egestas sit amet. Sed massa ex, commodo sed orci nec, accumsan sagittis
sem. Curabitur malesuada urna sit amet leo vehicula lobortis. Pellentesque habitant
morbi tristique senectus et netus et malesuada fames ac turpis egestas. Integer
fringilla tincidunt nunc, in efficitur nibh placerat quis. Vivamus a est quis nunc
vestibulum facilisis. Ut ut massa a ante ultricies imperdiet. Orci varius natoque
penatibus et magnis dis parturient montes, nascetur ridiculus mus. Ut viverra volutpat
ex, eu scelerisque tortor interdum non. Ut cursus mi id turpis tristique, sed fringilla
urna fermentum. Suspendisse potenti. Suspendisse hendrerit scelerisque porttitor. Duis
nisi dolor, ultrices quis fermentum ac, interdum eu nisl.
</Typography>
</Slide>
<Slide active={page === 2}>
<Typography>
Donec nec ultricies tellus. Suspendisse potenti. Cras condimentum, arcu tempus ornare
aliquet, purus elit bibendum justo, eu pretium mauris leo ac ligula. Sed imperdiet odio
in vulputate vestibulum. Integer vitae commodo elit. Phasellus gravida eros at dolor
varius, in tempor metus tincidunt. Nulla dictum nec mi in dignissim. Duis non mauris a
turpis posuere tempor ut vel eros. Donec volutpat velit sapien, et varius velit viverra
sit amet. Aenean id magna sit amet velit rutrum porta in a tortor. Integer vel feugiat
tortor. Nullam posuere, nulla ut viverra dignissim, eros quam mattis erat, eget pretium
felis erat non mi. Proin varius est id pretium volutpat. Aliquam erat volutpat.
</Typography>
</Slide>
<Slide active={page === 3}>
<Typography>
Mauris porta mauris et feugiat blandit. Sed placerat non mauris at ultrices. Fusce
malesuada sem ut nulla malesuada aliquam. Pellentesque fermentum aliquam lorem, at
semper ex facilisis ac. Fusce laoreet odio vitae sem dictum, at sagittis erat imperdiet.
Nullam lacinia tortor at diam tempus malesuada. Aliquam vitae euismod mi. Integer ac
enim commodo felis sollicitudin condimentum id at ex. Mauris lobortis est nunc, et
scelerisque eros malesuada vel.
</Typography>
</Slide>
</SlideContainer>
</Box>
);
}
When the Slide content have different heights, the layout might shift when
the animation completes to match the current content's height. If this
behavior isn't desired, check out the
useMaxTabPanelHeight hook and
Use Max Tab Panel Height demo.