@ndla/ui 37.1.3 → 38.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. package/es/Article/Article.js +2 -2
  2. package/es/Article/ArticleHeaderWrapper.js +4 -7
  3. package/es/Article/ArticleNotions.js +16 -17
  4. package/es/Article/ArticleSideBar.js +4 -5
  5. package/es/AudioPlayer/Controls.js +173 -255
  6. package/es/CompetenceGoals/CompetenceGoalsDialog.js +12 -25
  7. package/es/Filter/FilterButtons.js +12 -14
  8. package/es/Filter/FilterListPhone.js +2 -4
  9. package/es/Footer/index.js +1 -2
  10. package/es/LearningPaths/LearningPathMenuModalWrapper.js +10 -6
  11. package/es/Masthead/MastheadSearchModal.js +56 -47
  12. package/es/MyNdla/SettingsMenu.js +6 -6
  13. package/es/NDLAFilm/AboutNdlaFilm.js +3 -3
  14. package/es/ResourcesWrapper/ResourcesTopicTitle.js +19 -23
  15. package/es/SearchTypeResult/PopupFilter.js +14 -20
  16. package/es/SearchTypeResult/components/ItemContexts.js +10 -21
  17. package/es/Topic/Topic.js +23 -23
  18. package/es/User/index.js +1 -3
  19. package/es/index.js +1 -3
  20. package/es/locale/messages-en.js +1 -0
  21. package/es/locale/messages-nb.js +1 -0
  22. package/es/locale/messages-nn.js +1 -0
  23. package/es/locale/messages-se.js +1 -0
  24. package/es/locale/messages-sma.js +1 -0
  25. package/lib/Article/Article.d.ts +2 -2
  26. package/lib/Article/Article.js +2 -2
  27. package/lib/Article/ArticleHeaderWrapper.d.ts +3 -2
  28. package/lib/Article/ArticleHeaderWrapper.js +4 -7
  29. package/lib/Article/ArticleNotions.js +17 -21
  30. package/lib/Article/ArticleSideBar.js +5 -9
  31. package/lib/AudioPlayer/Controls.d.ts +2 -2
  32. package/lib/AudioPlayer/Controls.js +173 -255
  33. package/lib/CompetenceGoals/CompetenceGoalsDialog.d.ts +3 -14
  34. package/lib/CompetenceGoals/CompetenceGoalsDialog.js +11 -26
  35. package/lib/Filter/FilterButtons.js +13 -15
  36. package/lib/Filter/FilterListPhone.js +3 -5
  37. package/lib/Footer/index.d.ts +1 -2
  38. package/lib/Footer/index.js +0 -7
  39. package/lib/LearningPaths/LearningPathMenuModalWrapper.js +9 -8
  40. package/lib/Masthead/MastheadSearchModal.d.ts +1 -1
  41. package/lib/Masthead/MastheadSearchModal.js +58 -46
  42. package/lib/MyNdla/SettingsMenu.js +5 -5
  43. package/lib/NDLAFilm/AboutNdlaFilm.js +2 -2
  44. package/lib/ResourcesWrapper/ResourcesTopicTitle.js +20 -27
  45. package/lib/SearchTypeResult/PopupFilter.js +14 -20
  46. package/lib/SearchTypeResult/components/ItemContexts.js +10 -21
  47. package/lib/Topic/Topic.js +22 -22
  48. package/lib/User/index.d.ts +0 -2
  49. package/lib/User/index.js +1 -13
  50. package/lib/index.d.ts +1 -3
  51. package/lib/index.js +1 -20
  52. package/lib/locale/messages-en.d.ts +1 -0
  53. package/lib/locale/messages-en.js +1 -0
  54. package/lib/locale/messages-nb.d.ts +1 -0
  55. package/lib/locale/messages-nb.js +1 -0
  56. package/lib/locale/messages-nn.d.ts +1 -0
  57. package/lib/locale/messages-nn.js +1 -0
  58. package/lib/locale/messages-se.d.ts +1 -0
  59. package/lib/locale/messages-se.js +1 -0
  60. package/lib/locale/messages-sma.d.ts +1 -0
  61. package/lib/locale/messages-sma.js +1 -0
  62. package/package.json +16 -17
  63. package/src/Article/Article.tsx +4 -4
  64. package/src/Article/ArticleHeaderWrapper.tsx +12 -18
  65. package/src/Article/ArticleNotions.tsx +7 -8
  66. package/src/Article/ArticleSideBar.tsx +3 -3
  67. package/src/AudioPlayer/Controls.tsx +146 -300
  68. package/src/CompetenceGoals/CompetenceGoalsDialog.tsx +13 -38
  69. package/src/Filter/FilterButtons.tsx +4 -5
  70. package/src/Filter/FilterListPhone.tsx +3 -4
  71. package/src/Footer/index.ts +1 -2
  72. package/src/LearningPaths/LearningPathMenuModalWrapper.tsx +10 -6
  73. package/src/Masthead/MastheadSearchModal.tsx +48 -74
  74. package/src/MyNdla/SettingsMenu.tsx +3 -3
  75. package/src/NDLAFilm/AboutNdlaFilm.tsx +3 -3
  76. package/src/ResourcesWrapper/ResourcesTopicTitle.tsx +4 -8
  77. package/src/SearchTypeResult/PopupFilter.tsx +6 -11
  78. package/src/SearchTypeResult/components/ItemContexts.tsx +4 -21
  79. package/src/Topic/Topic.tsx +7 -7
  80. package/src/User/index.ts +0 -2
  81. package/src/index.ts +1 -3
  82. package/src/locale/messages-en.ts +1 -0
  83. package/src/locale/messages-nb.ts +1 -0
  84. package/src/locale/messages-nn.ts +1 -0
  85. package/src/locale/messages-se.ts +1 -0
  86. package/src/locale/messages-sma.ts +1 -0
  87. package/es/Figure/FigureLicenseDialogContent.js +0 -75
  88. package/es/Footer/FooterAuth.js +0 -110
  89. package/es/Masthead/MastheadAuthModal.js +0 -50
  90. package/es/SearchTypeResult/SearchNotionItem.js +0 -208
  91. package/es/User/AuthModal.js +0 -116
  92. package/lib/Figure/FigureLicenseDialogContent.d.ts +0 -22
  93. package/lib/Figure/FigureLicenseDialogContent.js +0 -80
  94. package/lib/Footer/FooterAuth.d.ts +0 -10
  95. package/lib/Footer/FooterAuth.js +0 -114
  96. package/lib/Masthead/MastheadAuthModal.d.ts +0 -13
  97. package/lib/Masthead/MastheadAuthModal.js +0 -56
  98. package/lib/SearchTypeResult/SearchNotionItem.d.ts +0 -29
  99. package/lib/SearchTypeResult/SearchNotionItem.js +0 -215
  100. package/lib/User/AuthModal.d.ts +0 -22
  101. package/lib/User/AuthModal.js +0 -124
  102. package/src/Figure/FigureLicenseDialogContent.tsx +0 -80
  103. package/src/Footer/FooterAuth.tsx +0 -104
  104. package/src/Masthead/MastheadAuthModal.tsx +0 -62
  105. package/src/SearchTypeResult/SearchNotionItem.tsx +0 -228
  106. package/src/User/AuthModal.tsx +0 -123
@@ -8,178 +8,85 @@
8
8
 
9
9
  import React, { useEffect, useRef, useState } from 'react';
10
10
  import styled from '@emotion/styled';
11
- import { Menu, MenuButton, MenuItem, MenuPopover, MenuItems, MenuItemProps } from '@reach/menu-button';
12
- import { SliderInput, SliderTrack, SliderRange, SliderHandle, SliderOrientation } from '@reach/slider';
11
+ import { Root, Trigger, Item, Content, DropdownMenuPortal } from '@radix-ui/react-dropdown-menu';
12
+ import { Root as SliderRoot, Track, Range, SliderThumb } from '@radix-ui/react-slider';
13
+ import { Root as PopoverRoot, PopoverContent, PopoverTrigger, PopoverPortal } from '@radix-ui/react-popover';
13
14
  import { Play, Pause, VolumeUp } from '@ndla/icons/common';
14
15
  import { breakpoints, colors, fonts, misc, mq, spacing } from '@ndla/core';
15
16
  import { useTranslation } from 'react-i18next';
16
17
  import { Back15, Forward15 } from '@ndla/icons/action';
18
+ import { ButtonV2, IconButtonV2 } from '@ndla/button';
17
19
 
18
20
  const ControlsWrapper = styled.div`
19
21
  border: 1px solid ${colors.brand.lighter};
20
22
  display: flex;
21
23
  align-items: center;
22
24
  justify-content: center;
23
- background: #ffffff;
25
+ background: ${colors.white};
24
26
  font-family: ${fonts.sans};
27
+ gap: ${spacing.xsmall};
28
+ padding: ${spacing.small} ${spacing.normal};
25
29
  ${mq.range({ until: breakpoints.tabletWide })} {
26
- flex-wrap: wrap;
27
- }
28
- padding: ${spacing.small};
29
- ${mq.range({ from: breakpoints.tabletWide })} {
30
- padding: ${spacing.small} ${spacing.normal};
30
+ display: grid;
31
+ padding: ${spacing.small};
32
+ grid-template-columns: 1fr repeat(5, auto) 1fr;
33
+ grid-template-areas:
34
+ 'track track track track track track track'
35
+ '. speed backwards play forwards volume .';
31
36
  }
32
37
  `;
33
38
 
34
- const PlayButton = styled.button`
35
- background: ${colors.brand.lighter};
36
- border: none;
37
- display: flex;
38
- align-items: center;
39
- justify-content: center;
40
- padding: 0;
41
- cursor: pointer;
42
- color: ${colors.brand.primary};
43
- width: 55px;
44
- height: 55px;
45
- border-radius: 50%;
46
- transition: ${misc.transition.default};
47
- margin-right: ${spacing.small};
39
+ const PlayButton = styled(IconButtonV2)`
48
40
  ${mq.range({ until: breakpoints.tabletWide })} {
49
- order: 4;
50
- margin-left: ${spacing.small};
51
- }
52
-
53
- &:hover,
54
- &:active,
55
- &:focus {
56
- background: ${colors.brand.primary};
57
- color: #ffffff;
58
- }
59
-
60
- .c-icon {
61
- width: 24px;
62
- height: 24px;
41
+ grid-area: play;
63
42
  }
64
43
  `;
65
44
 
66
- const ForwardRewindButton = styled.button`
67
- background-color: inherit;
68
- background-position: center;
69
- background-repeat: no-repeat;
70
- width: 42px;
71
- height: 42px;
72
- border: 0;
73
- border-radius: 50%;
74
- cursor: pointer;
75
- font-weight: bold;
76
- font-size: 9px;
77
- line-height: 23px;
78
- color: ${colors.brand.dark};
79
- font-family: ${fonts.sans};
80
- transition: ${misc.transition.default};
81
-
82
- &:hover {
83
- background-color: ${colors.brand.greyLighter};
84
- }
85
- `;
86
-
87
- const Forward15SecButton = styled(ForwardRewindButton)`
88
- svg {
89
- fill: ${colors.brand.primary};
90
- width: 24px;
91
- height: 24px;
92
- }
45
+ const Forward15SecButton = styled(IconButtonV2)`
93
46
  ${mq.range({ until: breakpoints.tabletWide })} {
94
- order: 3;
47
+ grid-area: forwards;
95
48
  }
96
49
  `;
97
- const Back15SecButton = styled(ForwardRewindButton)`
98
- svg {
99
- fill: ${colors.brand.primary};
100
- width: 24px;
101
- height: 24px;
102
- }
50
+ const Back15SecButton = styled(IconButtonV2)`
103
51
  ${mq.range({ until: breakpoints.tabletWide })} {
104
- order: 5;
52
+ grid-area: backwards;
105
53
  }
106
54
  `;
107
55
 
108
- const SpeedWrapper = styled.div`
109
- position: relative;
110
- display: flex;
111
- justify-content: center;
56
+ const SpeedButton = styled(ButtonV2)`
112
57
  ${mq.range({ until: breakpoints.tabletWide })} {
113
- order: 2;
114
- }
115
- `;
116
- const SpeedButton = styled(MenuButton)`
117
- height: 32px;
118
- border: 0;
119
- background: none;
120
- cursor: pointer;
121
- font-weight: 600;
122
- font-size: 12px;
123
- text-align: center;
124
- width: 52px;
125
- &:hover,
126
- &:active,
127
- &:focus,
128
- &[aria-expanded='true'] {
129
- background: ${colors.brand.greyLighter};
130
- border-radius: 27px;
131
- color: ${colors.text.primary};
58
+ grid-area: speed;
132
59
  }
133
60
  `;
134
61
 
135
- const SpeedMenu = styled(MenuPopover)`
136
- position: absolute;
137
- bottom: 36px;
138
- z-index: 99;
139
- `;
140
-
141
- const SpeedList = styled(MenuItems)`
142
- background: #ffffff;
62
+ const SpeedList = styled(Content)`
63
+ background: ${colors.white};
143
64
  border: 1px solid ${colors.brand.lighter};
144
- border-radius: 5px;
65
+ border-radius: ${misc.borderRadius};
145
66
  padding: 5px 10px;
146
67
  display: flex;
147
68
  flex-direction: column;
148
69
  justify-content: center;
149
- align-items: stretch;
150
70
  `;
151
71
 
152
- interface SpeedValueButtonProps extends MenuItemProps {
153
- selected?: boolean;
154
- }
155
-
156
- const SpeedValueButton = styled(MenuItem)<SpeedValueButtonProps>`
72
+ const SpeedValueButton = styled(Item)`
157
73
  height: 28px;
158
- position: relative;
159
- background: none;
160
- border: 0;
161
74
  padding: 0 14px;
162
75
  cursor: pointer;
163
- font-weight: 600;
164
- font-size: 14px;
76
+ font-weight: ${fonts.weight.semibold};
77
+ ${fonts.sizes('14px')};
165
78
  color: ${colors.text.light};
166
79
  display: flex;
167
80
  justify-content: center;
168
- align-items: center;
169
81
  &:hover,
170
82
  &:active,
171
83
  &:focus,
172
- &[data-selected] {
84
+ &[data-highlighted] {
173
85
  background: ${colors.brand.greyLighter};
174
86
  border-radius: 5px;
87
+ outline: none;
175
88
  color: ${colors.text.primary};
176
89
  }
177
- ${(props) =>
178
- props.selected &&
179
- `
180
- color: ${colors.text.primary};
181
-
182
- `}
183
90
  `;
184
91
 
185
92
  const SpeedSelectedMark = styled.span`
@@ -187,145 +94,105 @@ const SpeedSelectedMark = styled.span`
187
94
  background: #d1372e;
188
95
  width: 6px;
189
96
  height: 6px;
190
- display: inline-block;
191
- align-self: flex-start;
192
97
  margin: 6px 0 0 2px;
193
98
  `;
194
99
 
195
100
  const Time = styled.div`
196
- font-size: 16px;
101
+ ${fonts.sizes('16px')};
197
102
  `;
198
103
 
199
104
  const ProgressWrapper = styled.div`
200
- flex: 1 1 auto;
105
+ flex: 1;
201
106
  display: flex;
202
107
  align-items: center;
203
- margin: 0 ${spacing.small};
108
+ gap: ${spacing.small};
204
109
  ${mq.range({ until: breakpoints.tabletWide })} {
205
- order: 1;
206
- width: 100%;
207
- margin: 0;
208
- margin-bottom: ${spacing.normal};
110
+ grid-area: track;
209
111
  }
210
112
  `;
211
- const SliderWrapper = styled.div`
113
+
114
+ const SliderWrapper = styled(SliderRoot)`
212
115
  cursor: pointer;
213
- flex: 1 1 auto;
214
- margin: 0 ${spacing.small};
116
+ flex: 1;
117
+ position: relative;
118
+ display: flex;
119
+ align-items: center;
120
+ user-select: none;
121
+ touch-action: none;
215
122
  `;
216
123
 
217
- const ProgressBackground = styled(SliderTrack)`
124
+ const StyledTrack = styled(Track)`
218
125
  height: 4px;
219
126
  width: 100%;
220
127
  background: ${colors.brand.lighter};
221
128
  border-radius: 7px;
222
129
  `;
223
130
 
224
- const ProgressPlayed = styled(SliderRange)`
131
+ const StyledRange = styled(Range)`
132
+ position: absolute;
225
133
  height: 4px;
226
134
  background: #5cbc80;
227
135
  border-radius: 7px;
228
136
  `;
229
137
 
230
- const ProgressHandle = styled(SliderHandle)`
138
+ const StyledThumb = styled(SliderThumb)`
139
+ display: block;
231
140
  width: 20px;
232
141
  height: 20px;
233
142
  background: #5cbc80;
234
143
  border-radius: 50%;
235
- top: -8px;
236
- `;
237
-
238
- const VolumeWrapper = styled.div`
239
- position: relative;
240
- display: flex;
241
- justify-content: center;
242
- ${mq.range({ until: breakpoints.tabletWide })} {
243
- order: 6;
244
- }
144
+ outline: none;
245
145
  `;
246
146
 
247
- const WardButtonWrapper = styled.div<{ order: number }>`
147
+ const VolumeWrapper = styled(PopoverRoot)`
248
148
  position: relative;
249
149
  display: flex;
250
150
  justify-content: center;
251
151
  ${mq.range({ until: breakpoints.tabletWide })} {
252
- ${(props) =>
253
- `
254
- order: ${props.order};
255
- `}
256
- }
257
- `;
258
-
259
- const VolumeButton = styled(MenuButton)`
260
- background-color: inherit;
261
- width: 48px;
262
- height: 48px;
263
- border-radius: 50%;
264
- border: 0;
265
- background-position: center;
266
- background-repeat: no-repeat;
267
- cursor: pointer;
268
-
269
- svg {
270
- fill: ${colors.brand.primary};
271
- width: 32px;
272
- height: 32px;
273
- }
274
-
275
- &:hover,
276
- &:active,
277
- &:focus,
278
- &[aria-expanded='true'] {
279
- background-color: ${colors.brand.greyLighter};
152
+ grid-area: volume;
280
153
  }
281
154
  `;
282
155
 
283
- const VolumeMenu = styled(MenuPopover)`
284
- position: absolute;
285
- bottom: 52px;
286
- z-index: 99;
287
- `;
288
-
289
- const VolumeList = styled.div`
156
+ const VolumeList = styled(PopoverContent)`
290
157
  box-shadow: 0 14px 20px -5px rgba(32, 88, 143, 0.17);
291
158
  border-radius: 60px;
292
- background: #ffffff;
159
+ background: ${colors.white};
160
+ padding: ${spacing.small};
293
161
  border: 1px solid ${colors.brand.lighter};
294
- display: flex;
295
- flex-direction: column;
296
- justify-content: center;
297
- width: 32px;
298
162
  height: 128px;
299
163
  `;
300
164
 
301
- const VolumeSliderWrapper = styled.div`
165
+ const VolumeSliderWrapper = styled(SliderRoot)`
302
166
  cursor: pointer;
303
- flex: 1 1 auto;
167
+ height: 100%;
168
+ position: relative;
304
169
  display: flex;
305
- justify-content: center;
306
- padding: 16px 0;
170
+ flex-direction: column;
171
+ align-items: center;
172
+ user-select: none;
173
+ touch-action: none;
307
174
  `;
308
175
 
309
- const VolumeSliderBackground = styled(SliderTrack)`
176
+ const VolumeSliderBackground = styled(Track)`
310
177
  height: 100%;
311
178
  width: 5px;
312
179
  background: ${colors.brand.lighter};
313
180
  border-radius: 7px;
314
181
  `;
315
182
 
316
- const VolumeSliderSelected = styled(SliderRange)`
183
+ const VolumeSliderSelected = styled(Range)`
184
+ position: absolute;
317
185
  width: 5px;
318
186
  background: ${colors.brand.secondary};
319
187
  border-radius: 7px;
320
- bottom: 0;
321
188
  `;
322
189
 
323
- const VolumeSliderHandle = styled(SliderHandle)`
190
+ const VolumeSliderHandle = styled(SliderThumb)`
191
+ display: block;
324
192
  width: 20px;
325
193
  height: 20px;
326
194
  background: ${colors.brand.primary};
327
195
  border-radius: 50%;
328
- left: -8px;
329
196
  `;
330
197
 
331
198
  const formatTime = (seconds: number) => {
@@ -338,16 +205,15 @@ const formatTime = (seconds: number) => {
338
205
 
339
206
  const speedValues = [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2];
340
207
 
341
- type Props = {
208
+ interface Props {
342
209
  src: string;
343
210
  title: string;
344
- };
211
+ }
345
212
 
346
213
  const Controls = ({ src, title }: Props) => {
347
214
  const { t } = useTranslation();
348
215
  const [speedValue, setSpeedValue] = useState(1);
349
216
  const [volumeValue, setVolumeValue] = useState(100);
350
- const [sliderValue, setSliderValue] = useState(0);
351
217
  const [currentTime, setCurrentTime] = useState(0);
352
218
  const [remainingTime, setRemainingTime] = useState(0);
353
219
  const [playing, setPlaying] = useState(false);
@@ -364,8 +230,6 @@ const Controls = ({ src, title }: Props) => {
364
230
  const audioElement = audioRef.current;
365
231
  const handleTimeUpdate = () => {
366
232
  const { currentTime, duration } = audioElement;
367
- const percent = Math.round((currentTime / duration) * 100);
368
- setSliderValue(percent);
369
233
  setCurrentTime(Math.round(currentTime));
370
234
  setRemainingTime(Math.round(duration - currentTime));
371
235
  };
@@ -374,7 +238,6 @@ const Controls = ({ src, title }: Props) => {
374
238
  const { currentTime, duration } = audioElement;
375
239
  setCurrentTime(Math.round(currentTime));
376
240
  setRemainingTime(Math.round(duration - currentTime));
377
- setRemainingTime(Math.round(duration - currentTime));
378
241
  };
379
242
 
380
243
  const handleTimeEnded = () => {
@@ -410,16 +273,16 @@ const Controls = ({ src, title }: Props) => {
410
273
  }
411
274
  };
412
275
 
413
- const handleSliderChange = (value: number) => {
276
+ const handleSliderChange = (value: number[]) => {
414
277
  if (audioRef.current) {
415
- audioRef.current.currentTime = (value / 100) * audioRef.current.duration;
278
+ audioRef.current.currentTime = value[0];
416
279
  }
417
280
  };
418
281
 
419
- const handleVolumeSliderChange = (value: number) => {
282
+ const handleVolumeSliderChange = (values: number[]) => {
420
283
  if (audioRef.current) {
421
- audioRef.current.volume = value / 100;
422
- setVolumeValue(value);
284
+ audioRef.current.volume = values[0] / 100;
285
+ setVolumeValue(values[0]);
423
286
  }
424
287
  };
425
288
 
@@ -428,112 +291,95 @@ const Controls = ({ src, title }: Props) => {
428
291
  {/* eslint-disable-next-line jsx-a11y/media-has-caption */}
429
292
  <audio ref={audioRef} src={src} title={title} preload="metadata" />
430
293
  <ControlsWrapper>
431
- <PlayButton type="button" onClick={togglePlay} title="play" aria-label="play">
432
- <span aria-hidden>
433
- {playing ? (
434
- <Pause role="img" aria-label="Pause" title="Pause" />
435
- ) : (
436
- <Play role="img" aria-label="Play" title="Play" />
437
- )}
438
- </span>
294
+ <PlayButton
295
+ aria-label={t(playing ? t('audio.pause') : t('audio.play'))}
296
+ colorTheme="lighter"
297
+ size="normal"
298
+ onClick={togglePlay}
299
+ >
300
+ {playing ? <Pause /> : <Play />}
439
301
  </PlayButton>
440
- <WardButtonWrapper order={3}>
441
- <Back15SecButton
442
- type="button"
443
- title={t('audio.controls.rewind15sec')}
444
- aria-label={t('audio.controls.rewind15sec')}
445
- onClick={() => {
446
- onSeekSeconds(-15);
447
- }}
448
- >
449
- <Back15 />
450
- </Back15SecButton>
451
- </WardButtonWrapper>
452
-
453
- <SpeedWrapper>
454
- <Menu>
302
+ <Back15SecButton
303
+ variant="ghost"
304
+ colorTheme="greyLighter"
305
+ title={t('audio.controls.rewind15sec')}
306
+ aria-label={t('audio.controls.rewind15sec')}
307
+ onClick={() => onSeekSeconds(-15)}
308
+ >
309
+ <Back15 />
310
+ </Back15SecButton>
311
+
312
+ <Root>
313
+ <Trigger asChild>
455
314
  <SpeedButton
456
- type="button"
457
- as="button"
315
+ shape="pill"
316
+ variant="ghost"
317
+ size="normal"
318
+ colorTheme="greyLighter"
458
319
  title={t('audio.controls.selectSpeed')}
459
320
  aria-label={t('audio.controls.selectSpeed')}
460
321
  >
461
322
  {speedValue}x
462
323
  </SpeedButton>
463
- <SpeedMenu as="div" portal={false}>
464
- <div>
465
- <SpeedList as="div">
466
- {speedValues.map((speed) => (
467
- <SpeedValueButton
468
- type="button"
469
- //@ts-ignore
470
- as="button"
471
- key={speed}
472
- selected={speed === speedValue}
473
- onSelect={() => {
474
- setSpeedValue(speed);
475
- }}
476
- >
477
- {speed}x{speed === speedValue && <SpeedSelectedMark />}
478
- </SpeedValueButton>
479
- ))}
480
- </SpeedList>
481
- </div>
482
- </SpeedMenu>
483
- </Menu>
484
- </SpeedWrapper>
485
- <WardButtonWrapper order={5}>
486
- <Forward15SecButton
487
- type="button"
488
- title={t('audio.controls.forward15sec')}
489
- aria-label={t('audio.controls.forward15sec')}
490
- onClick={() => {
491
- onSeekSeconds(15);
492
- }}
493
- >
494
- <Forward15 />
495
- </Forward15SecButton>
496
- </WardButtonWrapper>
324
+ </Trigger>
325
+ <DropdownMenuPortal>
326
+ <SpeedList side="top">
327
+ {speedValues.map((speed) => (
328
+ <SpeedValueButton key={speed} onSelect={() => setSpeedValue(speed)}>
329
+ {speed}x{speed === speedValue && <SpeedSelectedMark />}
330
+ </SpeedValueButton>
331
+ ))}
332
+ </SpeedList>
333
+ </DropdownMenuPortal>
334
+ </Root>
335
+ <Forward15SecButton
336
+ colorTheme="greyLighter"
337
+ variant="ghost"
338
+ title={t('audio.controls.forward15sec')}
339
+ aria-label={t('audio.controls.forward15sec')}
340
+ onClick={() => onSeekSeconds(15)}
341
+ >
342
+ <Forward15 />
343
+ </Forward15SecButton>
497
344
  <ProgressWrapper>
498
345
  <Time>{formatTime(currentTime)}</Time>
499
- <SliderWrapper>
500
- <SliderInput onChange={handleSliderChange} value={sliderValue}>
501
- <ProgressBackground as="div">
502
- <ProgressPlayed as="div" />
503
- <ProgressHandle as="div" />
504
- </ProgressBackground>
505
- </SliderInput>
346
+ <SliderWrapper
347
+ value={[audioRef.current?.currentTime ?? 0]}
348
+ defaultValue={[0]}
349
+ step={1}
350
+ max={audioRef.current?.duration ?? 0}
351
+ onValueChange={handleSliderChange}
352
+ >
353
+ <StyledTrack>
354
+ <StyledRange />
355
+ </StyledTrack>
356
+ <StyledThumb />
506
357
  </SliderWrapper>
507
358
  <Time>-{formatTime(remainingTime)}</Time>
508
359
  </ProgressWrapper>
509
360
  <VolumeWrapper>
510
- <Menu>
511
- {/* @ts-ignore */}
512
- <VolumeButton
513
- type="button"
514
- as="button"
515
- title={t('audio.controls.adjustVolume')}
516
- aria-label={t('audio.controls.adjustVolume')}
517
- >
361
+ <PopoverTrigger asChild>
362
+ <IconButtonV2 variant="ghost" colorTheme="greyLighter" aria-label={t('audio.controls.adjustVolume')}>
518
363
  <VolumeUp />
519
- </VolumeButton>
520
- <VolumeMenu as="div" portal={false}>
521
- <VolumeList>
522
- <VolumeSliderWrapper>
523
- <SliderInput
524
- orientation={SliderOrientation.Vertical}
525
- onChange={handleVolumeSliderChange}
526
- value={volumeValue}
527
- >
528
- <VolumeSliderBackground as="div">
529
- <VolumeSliderSelected as="div" />
530
- <VolumeSliderHandle as="div" />
531
- </VolumeSliderBackground>
532
- </SliderInput>
533
- </VolumeSliderWrapper>
534
- </VolumeList>
535
- </VolumeMenu>
536
- </Menu>
364
+ </IconButtonV2>
365
+ </PopoverTrigger>
366
+ <PopoverPortal>
367
+ <VolumeList side="top">
368
+ <VolumeSliderWrapper
369
+ orientation="vertical"
370
+ value={[volumeValue]}
371
+ min={0}
372
+ defaultValue={[100]}
373
+ step={1}
374
+ onValueChange={handleVolumeSliderChange}
375
+ >
376
+ <VolumeSliderBackground>
377
+ <VolumeSliderSelected />
378
+ </VolumeSliderBackground>
379
+ <VolumeSliderHandle />
380
+ </VolumeSliderWrapper>
381
+ </VolumeList>
382
+ </PopoverPortal>
537
383
  </VolumeWrapper>
538
384
  </ControlsWrapper>
539
385
  </div>