Transitions
Animate mounting and unmounting with native Collapse, Fade, Grow, Slide or Zoom.
This guide covers Material UI Core with the default Emotion engine; extensions and additional demos are explicitly classified.
Use case and business boundary
Child refs and lifecycles must remain compatible; respect reduced motion and do not keep hidden heavy engines running.
Native composition and scope
Collapse, Fade, Grow, Slide, Zoom
Preserve native Material UI composition and types; do not substitute JGuang UI/Base UI/Radix APIs. Example entries are not extra components.
Native installation and initialization
npm install @mui/material@9.4.0 @emotion/react@11.14.0 @emotion/styled@11.14.1
Use native npm and Emotion, not an invented JGuang UI Registry URL. Place examples inside native ThemeProvider; choose CssBaseline or ScopedCssBaseline for the project. Inspect React, existing providers, lockfile and SSR first. Never overwrite files or conceal peer conflicts. This batch verified React 19.2.8; React 18 and below require matching react-is. See the included bilingual setup guide.
Practical native parameters
These selected parameters are not a flattened universal API. Preserve the native declaring owner, slot structure, nullable values and generics.
| Owner.prop | Practical role | Declaration source |
|---|---|---|
Collapse.in | Native transition enter/exit state, not loading or selection. | Collapse |
Collapse.timeout | Native transition duration or supported duration object in milliseconds. | Collapse |
Fade.in | Native transition enter/exit state, not loading or selection. | Fade |
Slide.direction | Owning native direction enum; layout, sorting and transition directions differ. | Slide |
Zoom.in | Native transition enter/exit state, not loading or selection. | Zoom |
Runnable native examples
Machine keys select example entries, not universal variant props. Native demo JSX/data stay unchanged; JGuang-authored acceptance fixtures are explicitly labelled.
- Collapse ·
SimpleCollapse· upstream native demo - Fade ·
SimpleFade· upstream native demo - Grow ·
SimpleGrow· upstream native demo - Slide ·
SimpleSlide· upstream native demo - Slide relative to a container ·
SlideFromContainer· upstream native demo - Zoom ·
SimpleZoom· upstream native demo
Explicitly unsupported additional examples
These remain in the upstream inventory, not silently skipped or presented as working previews. Additional dependency/framework acceptance is required.
- TransitionGroup ·
TransitionGroupExample:react-transition-group
Actual usage example
Unmodified pinned native demo; copy its required local helper files together.
import * as React from 'react';
import Box from '@mui/material/Box';
import Switch from '@mui/material/Switch';
import Paper from '@mui/material/Paper';
import Collapse from '@mui/material/Collapse';
import FormControlLabel from '@mui/material/FormControlLabel';
const icon = (
<Paper sx={{ m: 1, width: 100, height: 100 }} elevation={4}>
<svg width="100" height="100">
<Box
component="polygon"
points="0,100 50,00, 100,100"
sx={(theme) => ({
fill: theme.palette.common.white,
stroke: theme.palette.divider,
strokeWidth: 1,
})}
/>
</svg>
</Paper>
);
export default function SimpleCollapse() {
const [checked, setChecked] = React.useState(false);
const handleChange = () => {
setChecked((prev) => !prev);
};
return (
<Box sx={{ height: 300 }}>
<FormControlLabel
control={<Switch checked={checked} onChange={handleChange} />}
label="Show"
/>
<Box
sx={{
'& > :not(style)': {
display: 'flex',
justifyContent: 'space-around',
height: 120,
width: 250,
},
}}
>
<div>
<Collapse in={checked}>{icon}</Collapse>
<Collapse in={checked} collapsedSize={40}>
{icon}
</Collapse>
</div>
<div>
<Box sx={{ width: '50%' }}>
<Collapse orientation="horizontal" in={checked}>
{icon}
</Collapse>
</Box>
<Box sx={{ width: '50%' }}>
<Collapse orientation="horizontal" in={checked} collapsedSize={40}>
{icon}
</Collapse>
</Box>
</div>
</Box>
</Box>
);
}
Example dependency boundaries
react, @mui/material/Box, @mui/material/Switch, @mui/material/Paper, @mui/material/Collapse, @mui/material/FormControlLabel, @mui/material/Fade, @mui/material/Grow, @mui/material/Slide, @mui/material/Zoom
Direct Icons/System/Utils example imports require their matching 9.4.0 packages. Relative data/helpers are part of the example closure, not extra components. Remote images and simulated operations do not supply a backend.
Pinned upstream API metadata reference
These tables retain the upstream metadata, not a newly inferred generic type system. Conditional generics, inherited props and callback details are defined by the source declarations below. Theme defaults may override metadata defaults.
Collapse
import Collapse from '@mui/material/Collapse';
import { Collapse } from '@mui/material';
Native inheritance: Transition. Parent/DOM props are not fabricated as additional own props.
| Prop | Required | Upstream metadata type / constraint | Metadata default |
|---|---|---|---|
addEndListener | no | func | — |
children | no | node | — |
classes | no | object | — |
collapsedSize | no | number | string | '0px' |
component | no | element type | — |
disablePrefersReducedMotion | no | bool | false |
easing | no | { enter?: string, exit?: string } | string | — |
in | no | bool | — |
orientation | no | 'horizontal' | 'vertical' | 'vertical' |
slotProps | no | { root?: func | object, wrapper?: func | object, wrapperInner?: func | object } | {} |
slots | no | { root?: elementType, wrapper?: elementType, wrapperInner?: elementType } | {} |
sx | no | Array<func | object | bool> | func | object | — |
timeout | no | 'auto' | number | { appear?: number, enter?: number, exit?: number } | duration.standard |
Fade
import Fade from '@mui/material/Fade';
import { Fade } from '@mui/material';
Native inheritance: Transition. Parent/DOM props are not fabricated as additional own props.
| Prop | Required | Upstream metadata type / constraint | Metadata default |
|---|---|---|---|
children | yes | element | — |
addEndListener | no | func | — |
appear | no | bool | true |
disablePrefersReducedMotion | no | bool | false |
easing | no | { enter?: string, exit?: string } | string | — |
in | no | bool | — |
timeout | no | number | { appear?: number, enter?: number, exit?: number } | { enter: theme.transitions.duration.enteringScreen, exit: theme.transitions.duration.leavingScreen, } |
Grow
import Grow from '@mui/material/Grow';
import { Grow } from '@mui/material';
Native inheritance: Transition. Parent/DOM props are not fabricated as additional own props.
| Prop | Required | Upstream metadata type / constraint | Metadata default |
|---|---|---|---|
children | yes | element | — |
addEndListener | no | func | — |
appear | no | bool | true |
disablePrefersReducedMotion | no | bool | false |
easing | no | { enter?: string, exit?: string } | string | — |
in | no | bool | — |
timeout | no | 'auto' | number | { appear?: number, enter?: number, exit?: number } | 'auto' |
Slide
import Slide from '@mui/material/Slide';
import { Slide } from '@mui/material';
Native inheritance: Transition. Parent/DOM props are not fabricated as additional own props.
| Prop | Required | Upstream metadata type / constraint | Metadata default |
|---|---|---|---|
children | yes | element | — |
addEndListener | no | func | — |
appear | no | bool | true |
container | no | HTML element | func | — |
direction | no | 'down' | 'left' | 'right' | 'up' | 'down' |
disablePrefersReducedMotion | no | bool | false |
easing | no | { enter?: string, exit?: string } | string | { enter: theme.transitions.easing.easeOut, exit: theme.transitions.easing.sharp, } |
in | no | bool | — |
timeout | no | number | { appear?: number, enter?: number, exit?: number } | { enter: theme.transitions.duration.enteringScreen, exit: theme.transitions.duration.leavingScreen, } |
Zoom
import Zoom from '@mui/material/Zoom';
import { Zoom } from '@mui/material';
Native inheritance: Transition. Parent/DOM props are not fabricated as additional own props.
| Prop | Required | Upstream metadata type / constraint | Metadata default |
|---|---|---|---|
children | yes | element | — |
addEndListener | no | func | — |
appear | no | bool | true |
disablePrefersReducedMotion | no | bool | false |
easing | no | { enter?: string, exit?: string } | string | — |
in | no | bool | — |
timeout | no | number | { appear?: number, enter?: number, exit?: number } | { enter: theme.transitions.duration.enteringScreen, exit: theme.transitions.duration.leavingScreen, } |
Native source declarations
Declarations/imports are extracted from pinned source without flattening unions or external inheritance. Original English comments/types are source reference, not a claim of translated upstream prose. Shared types stay in their native packages.
vendor/src/Collapse/Collapse.d.ts
import * as React from 'react';
import { SxProps } from '@mui/system';
import { Theme } from '../styles';
import { InternalStandardProps as StandardProps } from '../internal';
import { TransitionProps, TransitionStatus } from '../transitions/types';
import { CollapseClasses } from './collapseClasses';
import { CreateSlotsAndSlotProps, SlotProps } from '../utils/types';
export interface CollapseSlots {
/**
* The component that renders the root.
* @default 'div'
*/
root?: React.ElementType | undefined;
/**
* The component that renders the wrapper.
* @default 'div'
*/
wrapper?: React.ElementType | undefined;
/**
* The component that renders the inner wrapper.
* @default 'div'
*/
wrapperInner?: React.ElementType | undefined;
}
export interface CollapseRootSlotPropsOverrides {}
export interface CollapseWrapperSlotPropsOverrides {}
export interface CollapseWrapperInnerSlotPropsOverrides {}
export type CollapseSlotsAndSlotProps = CreateSlotsAndSlotProps<
CollapseSlots,
{
root: SlotProps<'div', CollapseRootSlotPropsOverrides, CollapseOwnerState>;
wrapper: SlotProps<'div', CollapseWrapperSlotPropsOverrides, CollapseOwnerState>;
wrapperInner: SlotProps<'div', CollapseWrapperInnerSlotPropsOverrides, CollapseOwnerState>;
}
>;
export interface CollapseProps
extends StandardProps<TransitionProps, 'timeout'>, CollapseSlotsAndSlotProps {
/**
* Add a custom transition end trigger.
* Use it when you need custom logic to decide when the transition has ended.
* Note: Timeouts are still used as a fallback if provided.
*
* @param {HTMLElement} node The transitioning DOM node.
* @param {Function} done Call this when the transition has finished.
*/
addEndListener?: TransitionProps['addEndListener'] | undefined;
/**
* The content node to be collapsed.
*/
children?: React.ReactNode;
className?: string | undefined;
/**
* Override or extend the styles applied to the component.
*/
classes?: Partial<CollapseClasses> | undefined;
/**
* The width (horizontal) or height (vertical) of the container when collapsed.
* @default '0px'
*/
collapsedSize?: string | number | undefined;
/**
* The component used for the root node.
* Either a string to use a HTML element or a component.
*/
component?: React.ElementType<TransitionProps> | undefined;
/**
* If `true`, the transition ignores `theme.motion.reducedMotion` and keeps its normal timing.
* @default false
*/
disablePrefersReducedMotion?: boolean | undefined;
/**
* The transition timing function.
* You may specify a single easing or a object containing enter and exit values.
*/
easing?: TransitionProps['easing'] | undefined;
/**
* If `true`, the component will transition in.
*/
in?: boolean | undefined;
/**
* The transition orientation.
* @default 'vertical'
*/
orientation?: 'horizontal' | 'vertical' | undefined;
/**
* The duration for the transition, in milliseconds.
* You may specify a single timeout for all transitions, or individually with an object.
*
* Set to 'auto' to automatically calculate transition time based on height.
* @default duration.standard
*/
timeout?: TransitionProps['timeout'] | 'auto' | undefined;
/**
* The system prop that allows defining system overrides as well as additional CSS styles.
*/
sx?: SxProps<Theme> | undefined;
}
export interface CollapseOwnerState extends CollapseProps {
state: TransitionStatus;
}
export default function Collapse(props: CollapseProps): React.JSX.Element;
vendor/src/Fade/Fade.d.ts
import * as React from 'react';
import { TransitionProps } from '../transitions/types';
export interface FadeProps extends Omit<TransitionProps, 'children'> {
/**
* Add a custom transition end trigger.
* Use it when you need custom logic to decide when the transition has ended.
* Note: Timeouts are still used as a fallback if provided.
*
* @param {HTMLElement} node The transitioning DOM node.
* @param {Function} done Call this when the transition has finished.
*/
addEndListener?: TransitionProps['addEndListener'] | undefined;
/**
* Perform the enter transition when it first mounts if `in` is also `true`.
* Set this to `false` to disable this behavior.
* @default true
*/
appear?: boolean | undefined;
/**
* A single child content element.
*/
children: React.ReactElement<unknown, any>;
/**
* If `true`, the transition ignores `theme.motion.reducedMotion` and keeps its normal timing.
* @default false
*/
disablePrefersReducedMotion?: boolean | undefined;
/**
* The transition timing function.
* You may specify a single easing or a object containing enter and exit values.
*/
easing?: TransitionProps['easing'] | undefined;
/**
* If `true`, the component will transition in.
*/
in?: boolean | undefined;
ref?: React.Ref<unknown> | undefined;
/**
* The duration for the transition, in milliseconds.
* You may specify a single timeout for all transitions, or individually with an object.
* @default {
* enter: theme.transitions.duration.enteringScreen,
* exit: theme.transitions.duration.leavingScreen,
* }
*/
timeout?: TransitionProps['timeout'] | undefined;
}
export default function Fade(props: FadeProps): React.JSX.Element;
vendor/src/Grow/Grow.d.ts
import * as React from 'react';
import { TransitionProps } from '../transitions/types';
export interface GrowProps extends Omit<TransitionProps, 'timeout'> {
/**
* Add a custom transition end trigger.
* Use it when you need custom logic to decide when the transition has ended.
* Note: Timeouts are still used as a fallback if provided.
*
* @param {HTMLElement} node The transitioning DOM node.
* @param {Function} done Call this when the transition has finished.
*/
addEndListener?: TransitionProps['addEndListener'] | undefined;
/**
* Perform the enter transition when it first mounts if `in` is also `true`.
* Set this to `false` to disable this behavior.
* @default true
*/
appear?: boolean | undefined;
/**
* A single child content element.
*/
children: React.ReactElement<unknown, any>;
/**
* If `true`, the transition ignores `theme.motion.reducedMotion` and keeps its normal timing.
* @default false
*/
disablePrefersReducedMotion?: boolean | undefined;
/**
* The transition timing function.
* You may specify a single easing or a object containing enter and exit values.
*/
easing?: TransitionProps['easing'] | undefined;
/**
* If `true`, the component will transition in.
*/
in?: boolean | undefined;
ref?: React.Ref<unknown> | undefined;
/**
* The duration for the transition, in milliseconds.
* You may specify a single timeout for all transitions, or individually with an object.
*
* Set to 'auto' to automatically calculate transition time based on height.
* @default 'auto'
*/
timeout?: TransitionProps['timeout'] | 'auto' | undefined;
}
export default function Grow(props: GrowProps): React.JSX.Element;
vendor/src/Slide/Slide.d.ts
import * as React from 'react';
import { TransitionProps } from '../transitions/types';
export interface SlideProps extends TransitionProps {
/**
* Add a custom transition end trigger.
* Use it when you need custom logic to decide when the transition has ended.
* Note: Timeouts are still used as a fallback if provided.
*
* @param {HTMLElement} node The transitioning DOM node.
* @param {Function} done Call this when the transition has finished.
*/
addEndListener?: TransitionProps['addEndListener'] | undefined;
/**
* Perform the enter transition when it first mounts if `in` is also `true`.
* Set this to `false` to disable this behavior.
* @default true
*/
appear?: boolean | undefined;
/**
* A single child content element.
*/
children: React.ReactElement<unknown, any>;
/**
* An HTML element, or a function that returns one.
* It's used to set the container the Slide is transitioning from.
*/
container?: null | Element | ((element: Element) => Element) | undefined;
/**
* If `true`, the transition ignores `theme.motion.reducedMotion` and keeps its normal timing.
* @default false
*/
disablePrefersReducedMotion?: boolean | undefined;
/**
* Direction the child node will enter from.
* @default 'down'
*/
direction?: 'left' | 'right' | 'up' | 'down' | undefined;
/**
* The transition timing function.
* You may specify a single easing or a object containing enter and exit values.
* @default {
* enter: theme.transitions.easing.easeOut,
* exit: theme.transitions.easing.sharp,
* }
*/
easing?: TransitionProps['easing'] | undefined;
/**
* If `true`, the component will transition in.
*/
in?: TransitionProps['in'] | undefined;
ref?: React.Ref<unknown> | undefined;
/**
* The duration for the transition, in milliseconds.
* You may specify a single timeout for all transitions, or individually with an object.
* @default {
* enter: theme.transitions.duration.enteringScreen,
* exit: theme.transitions.duration.leavingScreen,
* }
*/
timeout?: TransitionProps['timeout'] | undefined;
}
export default function Slide(props: SlideProps): React.JSX.Element;
vendor/src/Zoom/Zoom.d.ts
import * as React from 'react';
import { TransitionProps } from '../transitions/types';
export interface ZoomProps extends TransitionProps {
/**
* Add a custom transition end trigger.
* Use it when you need custom logic to decide when the transition has ended.
* Note: Timeouts are still used as a fallback if provided.
*
* @param {HTMLElement} node The transitioning DOM node.
* @param {Function} done Call this when the transition has finished.
*/
addEndListener?: TransitionProps['addEndListener'] | undefined;
/**
* Perform the enter transition when it first mounts if `in` is also `true`.
* Set this to `false` to disable this behavior.
* @default true
*/
appear?: boolean | undefined;
/**
* A single child content element.
*/
children: React.ReactElement<unknown, any>;
/**
* If `true`, the transition ignores `theme.motion.reducedMotion` and keeps its normal timing.
* @default false
*/
disablePrefersReducedMotion?: boolean | undefined;
/**
* The transition timing function.
* You may specify a single easing or a object containing enter and exit values.
*/
easing?: TransitionProps['easing'] | undefined;
/**
* If `true`, the component will transition in.
*/
in?: boolean | undefined;
ref?: React.Ref<unknown> | undefined;
/**
* The duration for the transition, in milliseconds.
* You may specify a single timeout for all transitions, or individually with an object.
* @default {
* enter: theme.transitions.duration.enteringScreen,
* exit: theme.transitions.duration.leavingScreen,
* }
*/
timeout?: TransitionProps['timeout'] | undefined;
}
export default function Zoom(props: ZoomProps): React.JSX.Element;
Post-install acceptance
Run strict types, production build and real interactions. Check keyboard labels/focus, disabled/error/read-only semantics where natively supported, both themes, narrow screens and reduced motion. Verify callbacks against the real host data; do not declare installation complete from copying a prompt. Initialization fixtures also require server HTML and warning-free hydration.
Source and license
https://github.com/mui/material-ui/tree/809a7717b4c050ba3f69b75300689f07c050a16e
MIT · @mui/material@9.4.0. Vendor originals and license are preserved. Full original upstream prose remains in vendor/docs and is not represented as fully translated.