@@ -10,6 +10,7 @@ import {
10
10
RadioGroup ,
11
11
Radio ,
12
12
motionTokens ,
13
+ Button ,
13
14
} from '@fluentui/react-components' ;
14
15
import { Rotate } from '@fluentui/react-motion-components-preview' ;
15
16
import { Axis3D } from '../../../library/src/atoms/rotate-atom' ;
@@ -20,30 +21,68 @@ const useClasses = makeStyles({
20
21
container : {
21
22
display : 'grid' ,
22
23
gridTemplate : `"controls ." "card card" / 1fr 1fr` ,
23
- gap : `${ tokens . spacingVerticalXL } ${ tokens . spacingHorizontalMNudge } ` , // 20px 10px
24
- // perspective: '1000px',
24
+ gap : `${ tokens . spacingVerticalXL } ${ tokens . spacingHorizontalMNudge } ` ,
25
25
overflow : 'clip' ,
26
26
} ,
27
27
card : {
28
28
gridArea : 'card' ,
29
- padding : tokens . spacingHorizontalMNudge , // 10px
29
+ padding : tokens . spacingHorizontalMNudge ,
30
30
} ,
31
31
controls : {
32
32
display : 'flex' ,
33
33
flexDirection : 'column' ,
34
34
gridArea : 'controls' ,
35
-
36
35
border : `${ tokens . strokeWidthThicker } solid ${ tokens . colorNeutralForeground3 } ` ,
37
36
borderRadius : tokens . borderRadiusMedium ,
38
37
boxShadow : tokens . shadow16 ,
39
- padding : tokens . spacingHorizontalMNudge , // 10px
38
+ padding : tokens . spacingHorizontalL ,
39
+ gap : tokens . spacingVerticalL ,
40
40
} ,
41
- field : {
41
+ controlSection : {
42
+ display : 'flex' ,
43
+ flexDirection : 'column' ,
44
+ gap : tokens . spacingVerticalM ,
45
+ } ,
46
+ sectionHeader : {
47
+ fontSize : tokens . fontSizeBase200 ,
48
+ fontWeight : tokens . fontWeightSemibold ,
49
+ color : tokens . colorNeutralForeground2 ,
50
+ marginBottom : tokens . spacingVerticalXS ,
51
+ borderBottom : `1px solid ${ tokens . colorNeutralStroke2 } ` ,
52
+ paddingBottom : tokens . spacingVerticalXS ,
53
+ } ,
54
+ toggleGroup : {
55
+ display : 'grid' ,
56
+ gridTemplateColumns : '1fr 1fr' ,
57
+ gap : tokens . spacingHorizontalM ,
58
+ } ,
59
+ ctaButton : {
42
60
flex : 1 ,
43
61
} ,
62
+ field : {
63
+ display : 'flex' ,
64
+ flexDirection : 'column' ,
65
+ gap : tokens . spacingVerticalXS ,
66
+ } ,
67
+ sliderField : {
68
+ display : 'flex' ,
69
+ flexDirection : 'column' ,
70
+ gap : tokens . spacingVerticalXS ,
71
+ } ,
44
72
sliderWrapper : {
45
73
display : 'flex' ,
46
74
alignItems : 'center' ,
75
+ gap : tokens . spacingHorizontalS ,
76
+ } ,
77
+ sliderLabel : {
78
+ fontSize : tokens . fontSizeBase200 ,
79
+ fontWeight : tokens . fontWeightMedium ,
80
+ color : tokens . colorNeutralForeground1 ,
81
+ } ,
82
+ valueDisplay : {
83
+ fontSize : tokens . fontSizeBase100 ,
84
+ color : tokens . colorNeutralForeground2 ,
85
+ fontFamily : tokens . fontFamilyMonospace ,
47
86
} ,
48
87
} ) ;
49
88
@@ -78,75 +117,94 @@ export const Default = (props: React.ComponentProps<typeof Rotate>) => {
78
117
return (
79
118
< div className = { classes . container } style = { { perspective } } >
80
119
< div className = { classes . controls } >
81
- < Field className = { classes . field } >
82
- < Switch label = "Visible" checked = { visible } onChange = { ( ) => setVisible ( v => ! v ) } />
83
- </ Field >
84
-
85
- < Field className = { classes . field } >
86
- < Switch
87
- label = "Autoplay"
88
- checked = { autoplay }
89
- onChange = { ( ) => {
90
- if ( ! autoplay ) {
91
- setVisible ( ! visible ) ;
92
- }
93
- return setAutoplay ( v => ! v ) ;
94
- } }
95
- />
96
- </ Field >
120
+ { /* Animation Controls Section */ }
121
+ < div className = { classes . controlSection } >
122
+ < div className = { classes . toggleGroup } >
123
+ < Button className = { classes . ctaButton } appearance = "primary" size = "large" onClick = { ( ) => setVisible ( v => ! v ) } >
124
+ { visible ? 'Hide' : 'Show' }
125
+ </ Button >
126
+ < Field >
127
+ < Switch
128
+ label = "Autoplay"
129
+ checked = { autoplay }
130
+ onChange = { ( ) => {
131
+ if ( ! autoplay ) {
132
+ setVisible ( ! visible ) ;
133
+ }
134
+ return setAutoplay ( v => ! v ) ;
135
+ } }
136
+ />
137
+ </ Field >
138
+ </ div >
139
+ </ div >
97
140
98
- < Field className = { classes . field } >
99
- < Label > Rotation Axis</ Label >
100
- < RadioGroup value = { axis } onChange = { ( _ , data ) => setAxis ( data . value as Axis3D ) } layout = "horizontal" >
101
- < Radio value = "x" label = "x" />
102
- < Radio value = "y" label = "y" />
103
- < Radio value = "z" label = "z" />
104
- </ RadioGroup >
105
- </ Field >
141
+ { /* Rotation Settings Section */ }
142
+ < div className = { classes . controlSection } >
143
+ < Field className = { classes . field } >
144
+ < Label className = { classes . sliderLabel } > Rotation Axis</ Label >
145
+ < RadioGroup value = { axis } onChange = { ( _ , data ) => setAxis ( data . value as Axis3D ) } layout = "horizontal" >
146
+ < Radio value = "x" label = "X-axis" />
147
+ < Radio value = "y" label = "Y-axis" />
148
+ < Radio value = "z" label = "Z-axis" />
149
+ </ RadioGroup >
150
+ </ Field >
106
151
107
- < label htmlFor = { enterAngleSliderId } > Enter Angle: { angle } °</ label >
108
- < div className = { classes . sliderWrapper } >
109
- < Label aria-hidden > { angleMin } </ Label >
110
- < Slider
111
- min = { angleMin }
112
- max = { angleMax }
113
- defaultValue = { angle }
114
- id = { enterAngleSliderId }
115
- onChange = { ( _ , data ) => {
116
- setEnterAngle ( data . value ) ;
117
- } }
118
- />
119
- < Label aria-hidden > { angleMax } </ Label >
152
+ < Field className = { classes . sliderField } >
153
+ < div style = { { display : 'flex' , justifyContent : 'space-between' , alignItems : 'center' } } >
154
+ < Label htmlFor = { enterAngleSliderId } className = { classes . sliderLabel } >
155
+ Enter Angle
156
+ </ Label >
157
+ < span className = { classes . valueDisplay } > { angle } °</ span >
158
+ </ div >
159
+ < Slider
160
+ min = { angleMin }
161
+ max = { angleMax }
162
+ defaultValue = { angle }
163
+ id = { enterAngleSliderId }
164
+ onChange = { ( _ , data ) => {
165
+ setEnterAngle ( data . value ) ;
166
+ } }
167
+ />
168
+ </ Field >
120
169
</ div >
121
170
122
- < Label htmlFor = { durationSliderId } > duration: { duration } </ Label >
123
- < div className = { classes . sliderWrapper } >
124
- < Label aria-hidden > { durationMin } </ Label >
125
- < Slider
126
- min = { durationMin }
127
- max = { durationMax }
128
- defaultValue = { motionTokens . durationUltraSlow } // 500ms
129
- id = { durationSliderId }
130
- onChange = { ( _ , data ) => {
131
- setDuration ( data . value ) ;
132
- } }
133
- />
134
- < Label aria-hidden > { durationMax } </ Label >
135
- </ div >
171
+ { /* Timing & Perspective Section */ }
172
+ < div className = { classes . controlSection } >
173
+ < Field className = { classes . sliderField } >
174
+ < div style = { { display : 'flex' , justifyContent : 'space-between' , alignItems : 'center' } } >
175
+ < Label htmlFor = { durationSliderId } className = { classes . sliderLabel } >
176
+ Duration
177
+ </ Label >
178
+ < span className = { classes . valueDisplay } > { duration } ms</ span >
179
+ </ div >
180
+ < Slider
181
+ min = { durationMin }
182
+ max = { durationMax }
183
+ defaultValue = { motionTokens . durationUltraSlow }
184
+ id = { durationSliderId }
185
+ onChange = { ( _ , data ) => {
186
+ setDuration ( data . value ) ;
187
+ } }
188
+ />
189
+ </ Field >
136
190
137
- < Label htmlFor = { perspectiveSliderId } > perspective: { perspective } </ Label >
138
- < div className = { classes . sliderWrapper } >
139
- < Label aria-hidden > { perspectiveMin } </ Label >
140
- < Slider
141
- min = { perspectiveMin }
142
- max = { perspectiveMax }
143
- defaultValue = { 1000 }
144
- id = { perspectiveSliderId }
145
- onChange = { ( _ , data ) => {
146
- setPerspective ( `${ data . value } px` ) ;
147
- } }
148
- />
149
- < Label aria-hidden > { perspectiveMax } </ Label >
191
+ < Field className = { classes . sliderField } >
192
+ < div style = { { display : 'flex' , justifyContent : 'space-between' , alignItems : 'center' } } >
193
+ < Label htmlFor = { perspectiveSliderId } className = { classes . sliderLabel } >
194
+ Perspective
195
+ </ Label >
196
+ < span className = { classes . valueDisplay } > { perspective } </ span >
197
+ </ div >
198
+ < Slider
199
+ min = { perspectiveMin }
200
+ max = { perspectiveMax }
201
+ defaultValue = { 1000 }
202
+ id = { perspectiveSliderId }
203
+ onChange = { ( _ , data ) => {
204
+ setPerspective ( `${ data . value } px` ) ;
205
+ } }
206
+ />
207
+ </ Field >
150
208
</ div >
151
209
</ div >
152
210
0 commit comments