Skip to content

Commit 9d9b773

Browse files
authored
docs(react-drawer): add example on how to customize the Drawer motion (#33784)
1 parent a17aac2 commit 9d9b773

File tree

3 files changed

+181
-3
lines changed

3 files changed

+181
-3
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
import {
2+
Button,
3+
DrawerBody,
4+
DrawerHeader,
5+
DrawerHeaderTitle,
6+
InlineDrawer,
7+
createPresenceComponent,
8+
makeStyles,
9+
motionTokens,
10+
tokens,
11+
} from '@fluentui/react-components';
12+
import { Dismiss24Regular } from '@fluentui/react-icons';
13+
import * as React from 'react';
14+
15+
const drawerWidth = '320px';
16+
const drawerMargin = tokens.spacingVerticalM;
17+
18+
const useStyles = makeStyles({
19+
root: {
20+
border: '2px solid #ccc',
21+
overflow: 'hidden',
22+
position: 'relative',
23+
24+
display: 'flex',
25+
height: '480px',
26+
backgroundColor: tokens.colorNeutralBackground1,
27+
},
28+
29+
drawer: {
30+
width: drawerWidth,
31+
border: '1px solid',
32+
},
33+
34+
content: {
35+
flex: '1',
36+
padding: '16px',
37+
display: 'grid',
38+
justifyContent: 'flex-start',
39+
alignItems: 'flex-start',
40+
gap: tokens.spacingVerticalM,
41+
gridAutoRows: 'max-content',
42+
boxSizing: 'border-box',
43+
position: 'absolute',
44+
inset: 0,
45+
backgroundColor: tokens.colorNeutralBackground1,
46+
border: `1px solid ${tokens.colorNeutralBackground1}`,
47+
},
48+
});
49+
50+
/*
51+
* Create a custom DrawerMotion component that animates the drawer surface.
52+
*/
53+
const DrawerMotion = createPresenceComponent(() => {
54+
const keyframes = [
55+
{
56+
opacity: 0,
57+
transform: 'translate3D(-100%, 0, 0)',
58+
margin: 0,
59+
backgroundColor: tokens.colorNeutralBackground1,
60+
borderColor: tokens.colorNeutralBackground1,
61+
borderRadius: 0,
62+
},
63+
{
64+
opacity: 1,
65+
transform: 'translate3D(0, 0, 0)',
66+
margin: drawerMargin,
67+
backgroundColor: tokens.colorNeutralBackground3,
68+
borderColor: tokens.colorNeutralBackground4,
69+
borderRadius: tokens.borderRadiusXLarge,
70+
},
71+
];
72+
73+
return {
74+
enter: {
75+
keyframes,
76+
duration: motionTokens.durationNormal,
77+
easing: motionTokens.curveDecelerateMin,
78+
},
79+
exit: {
80+
keyframes: [...keyframes].reverse(),
81+
duration: motionTokens.durationSlow,
82+
easing: motionTokens.curveAccelerateMin,
83+
},
84+
};
85+
});
86+
87+
/*
88+
* Create a custom ContentMotion component that animates the content element.
89+
*/
90+
const ContentMotion = createPresenceComponent(() => {
91+
const keyframes = [
92+
{
93+
transform: 'translate3D(0, 0, 0)',
94+
width: '100%',
95+
margin: 0,
96+
backgroundColor: tokens.colorNeutralBackground1,
97+
borderColor: tokens.colorNeutralBackground1,
98+
borderRadius: 0,
99+
},
100+
{
101+
transform: `translate3D(calc(${drawerWidth} + ${drawerMargin} * 2), 0, 0)`,
102+
width: `calc(100% - ${drawerWidth} - ${drawerMargin} * 3)`,
103+
margin: `${drawerMargin} 0`,
104+
backgroundColor: tokens.colorNeutralBackground3,
105+
borderColor: tokens.colorNeutralBackground4,
106+
borderRadius: tokens.borderRadiusXLarge,
107+
},
108+
];
109+
110+
return {
111+
enter: {
112+
keyframes,
113+
duration: motionTokens.durationGentle,
114+
easing: motionTokens.curveDecelerateMin,
115+
},
116+
exit: {
117+
keyframes: [...keyframes].reverse(),
118+
duration: motionTokens.durationGentle,
119+
easing: motionTokens.curveAccelerateMin,
120+
},
121+
};
122+
});
123+
124+
export const MotionCustom = () => {
125+
const styles = useStyles();
126+
const [isOpen, setIsOpen] = React.useState(false);
127+
128+
return (
129+
<div className={styles.root}>
130+
<InlineDrawer
131+
className={styles.drawer}
132+
// Override motion settings for the drawer surface
133+
surfaceMotion={{ children: (_, props) => <DrawerMotion {...props} /> }}
134+
separator
135+
open={isOpen}
136+
>
137+
<DrawerHeader>
138+
<DrawerHeaderTitle
139+
action={
140+
<Button
141+
appearance="subtle"
142+
aria-label="Close"
143+
icon={<Dismiss24Regular />}
144+
onClick={() => setIsOpen(false)}
145+
/>
146+
}
147+
>
148+
Default Drawer
149+
</DrawerHeaderTitle>
150+
</DrawerHeader>
151+
152+
<DrawerBody>
153+
<p>Drawer content</p>
154+
</DrawerBody>
155+
</InlineDrawer>
156+
157+
<ContentMotion visible={isOpen}>
158+
<div className={styles.content}>
159+
<Button appearance="primary" onClick={() => setIsOpen(!isOpen)}>
160+
Toggle Drawer
161+
</Button>
162+
163+
<p>Drawer content</p>
164+
</div>
165+
</ContentMotion>
166+
</div>
167+
);
168+
};
169+
170+
MotionCustom.parameters = {
171+
docs: {
172+
description: {
173+
story:
174+
'Drawer animations can be customized using the [Motion APIs](?path=/docs/motion-apis-createpresencecomponent--docs), together with the `surfaceMotion` prop.',
175+
},
176+
},
177+
};

packages/react-components/react-drawer/stories/src/Drawer/DrawerMotionDisabled.stories.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ MotionDisabled.parameters = {
102102
docs: {
103103
description: {
104104
story:
105-
'To disable the Drawer transition animation, you can use a custom style to set `transitionDuration` to `0ms`.',
105+
'To disable the Drawer transition animation, you can set both `surfaceMotion` and `backdropMotion` props of the Drawer to `null`.',
106106
},
107107
},
108108
};

packages/react-components/react-drawer/stories/src/Drawer/index.stories.tsx

+3-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
DrawerHeader,
77
DrawerHeaderTitle,
88
DrawerHeaderNavigation,
9+
DrawerFooter,
910
} from '@fluentui/react-drawer';
1011
import descriptionMd from './DrawerDescription.md';
1112
import bestPracticesMd from './DrawerBestPractices.md';
@@ -22,8 +23,7 @@ export { Separator } from './DrawerSeparator.stories';
2223
export { WithTitle } from './DrawerWithTitle.stories';
2324
export { WithNavigation } from './DrawerWithNavigation.stories';
2425
export { WithScroll } from './DrawerWithScroll.stories';
25-
// @TODO: enable when react-motion is stable
26-
// export { MotionCustom } from './DrawerMotionCustom.stories';
26+
export { MotionCustom } from './DrawerMotionCustom.stories';
2727
export { MotionDisabled } from './DrawerMotionDisabled.stories';
2828
export { MultipleLevels } from './DrawerMultipleLevels.stories';
2929
export { AlwaysOpen } from './DrawerAlwaysOpen.stories';
@@ -41,6 +41,7 @@ export default {
4141
DrawerHeaderTitle,
4242
DrawerHeaderNavigation,
4343
DrawerBody,
44+
DrawerFooter,
4445
},
4546
parameters: {
4647
docs: {

0 commit comments

Comments
 (0)