Skip to content

Commit f69643d

Browse files
Revert "Revert "fix(ADA-3337): Change tabbing order inside player"" (#1201)
Reverts #1200 This fixes https://kaltura.atlassian.net/browse/ADA-3337. It changes the tabbing order inside the player, moving the Seekbar between the leftControls and rightControls and the top-bar after the bottom-bar. To accomplish this, it is using css property order, that modifies the visual order of the items. It is adding a "Skip seekbar" buttons(only for keyboard navigation users), that are moving the focus out of the seekbar. One before and one after the seekbar, depending of the direction of entering the seekbar using keyboard navigation. Figma file for buttons: https://www.figma.com/design/8yTuCnuVHLYTFp89w7z05J/%F0%9F%93%BA-Player-v7?node-id=30852-2852&t=EeFHBXo43ipJGgQz-1
1 parent cadaf8d commit f69643d

12 files changed

Lines changed: 352 additions & 72 deletions

File tree

src/components/bottom-bar/_bottom-bar.scss

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
transition:
1616
#{$hover-animation-time}ms opacity ease-in-out,
1717
0ms padding linear #{$hover-animation-time}ms;
18+
order: 3;
1819

1920
&.hide {
2021
display: none;
@@ -23,7 +24,7 @@
2324
.controls-container {
2425
display: flex;
2526
flex-direction: row;
26-
flex-wrap: nowrap;
27+
flex-wrap: wrap;
2728
justify-content: space-between;
2829
width: 100%;
2930
position: relative;
@@ -33,18 +34,32 @@
3334
flex-shrink: 0;
3435
text-align: left;
3536
pointer-events: none;
37+
order: 1;
38+
z-index: 1;
3639

3740
.control-button-container:first-child {
3841
margin-left: 0px;
3942
}
4043
}
4144

45+
.center-controls {
46+
width: 100%;
47+
order: 0;
48+
pointer-events: none;
49+
& > * {
50+
pointer-events: auto;
51+
}
52+
}
53+
4254
.right-controls {
4355
display: flex;
4456
flex-wrap: nowrap;
4557
flex-grow: 0;
4658
text-align: left;
4759
pointer-events: none;
60+
order: 2;
61+
z-index: 1;
62+
margin-left: auto;
4863

4964
.control-button-container:last-child {
5065
margin-right: 0px;
@@ -79,28 +94,24 @@
7994
}
8095

8196
&.size-ty {
82-
.controls-container {
83-
display: block;
84-
.left-controls {
85-
display: none;
86-
}
87-
.right-controls {
88-
display: block;
89-
float: right;
90-
}
91-
}
92-
.control-button-container {
93-
display: none;
94-
margin: 0;
95-
}
96-
}
97-
98-
&.size-xs {
9997
.bottom-bar {
10098
.controls-container {
101-
.right-controls {
99+
display: block;
100+
.left-controls {
102101
display: none;
103102
}
103+
.center-controls {
104+
width: calc(100% - 50px);
105+
float: left;
106+
}
107+
.right-controls {
108+
display: block;
109+
float: right;
110+
}
111+
}
112+
.control-button-container {
113+
display: none;
114+
margin: 0;
104115
}
105116
}
106117
}

src/components/bottom-bar/bottom-bar-utils.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,12 @@ export function filterControlsByPriority(
55
currentControlWidth: number,
66
lowerPriorityControls: string[][]
77
): string[] {
8-
const numOfOverflowControls = Math.ceil((currentMinBreakPointWidth - currentBarWidth) / currentControlWidth) || 1;
8+
// Add 20% buffer to account for spacing/margins between controls
9+
const overflow = currentMinBreakPointWidth - currentBarWidth;
10+
if (overflow <= 0) return [];
11+
12+
const adjustedOverflow = overflow * 1.2;
13+
const numOfOverflowControls = Math.max(1, Math.ceil(adjustedOverflow / currentControlWidth));
914
const controlsToRemove = lowerPriorityControls.flat().slice(0, numOfOverflowControls);
1015
const priorityPair: string[] = [...lowerPriorityControls].reverse().find(p => p.length > 1)!;
1116
if (controlsToRemove[controlsToRemove.length - 1] === priorityPair?.[0]) {

src/components/bottom-bar/bottom-bar.tsx

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ const COMPONENT_NAME = 'BottomBar';
5959
class BottomBar extends Component<any, any> {
6060
private bottomBarContainerRef: RefObject<HTMLDivElement> = createRef<HTMLDivElement>();
6161
private leftControlsRef: RefObject<HTMLDivElement> = createRef<HTMLDivElement>();
62+
private rightControlsRef: RefObject<HTMLDivElement> = createRef<HTMLDivElement>();
6263
private presetControls: {[controlName: string]: boolean} = {};
6364
private resizeObserver!: ResizeObserver;
6465

@@ -122,7 +123,9 @@ class BottomBar extends Component<any, any> {
122123
}
123124

124125
private _getControlsWidth = (): number => {
125-
return Array.from(this.bottomBarContainerRef.current!.childNodes).reduce((total, child: HTMLElement) => total + child.offsetWidth, 0);
126+
const leftControlsWidth = this.leftControlsRef.current?.offsetWidth || 0;
127+
const rightControlsWidth = this.rightControlsRef.current?.offsetWidth || 0;
128+
return leftControlsWidth + rightControlsWidth;
126129
};
127130

128131
// eslint-disable-next-line require-jsdoc
@@ -218,7 +221,6 @@ class BottomBar extends Component<any, any> {
218221
<div className={style.bottomBarArea}>
219222
<PlayerArea shouldUpdate={true} name={'BottomBar'}>
220223
{shouldRenderTimeDisplay && <TimeDisplayPlaybackContainer />}
221-
{props.children}
222224
</PlayerArea>
223225
</div>
224226
<div ref={this.bottomBarContainerRef} className={style.controlsContainer}>
@@ -234,8 +236,12 @@ class BottomBar extends Component<any, any> {
234236
)}
235237
</PlayerArea>
236238
</div>
237-
<PlayerArea shouldUpdate={true} name={'BottomBarCenterControls'} />
238-
<div className={style.rightControls}>
239+
<div className={style.centerControls}>
240+
<PlayerArea shouldUpdate={true} name={'BottomBarCenterControls'}>
241+
{props.children}
242+
</PlayerArea>
243+
</div>
244+
<div ref={this.rightControlsRef} className={style.rightControls}>
239245
<PlayerArea shouldUpdate={true} name={'BottomBarRightControls'}>
240246
{props.rightControls &&
241247
props.rightControls.map(

src/components/icon/icon.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,10 @@
7777
'<path fill="#{$color}" d="M768 625.124v-354.531l-352 135.385v330.022c0 70.692-57.308 128-128 128s-128-57.308-128-128c0-70.692 57.308-128 128-128 23.314 0 45.173 6.233 64 17.124v-241.124c0-13.241 8.155-25.114 20.513-29.867l416-160c20.96-8.062 43.487 7.41 43.487 29.867v512c0 70.692-57.308 128-128 128s-128-57.308-128-128c0-70.692 57.308-128 128-128 23.314 0 45.173 6.233 64 17.124zM288 800c35.346 0 64-28.654 64-64s-28.654-64-64-64c-35.346 0-64 28.654-64 64s28.654 64 64 64zM704 800c35.346 0 64-28.654 64-64s-28.654-64-64-64c-35.346 0-64 28.654-64 64s28.654 64 64 64z" />',
7878
arrowDown:
7979
'<path fill="#{$color}" d="M301.255 338.745c-24.994-24.994-65.516-24.994-90.51 0s-24.994 65.516 0 90.51l256 256c24.994 24.994 65.516 24.994 90.51 0l256-256c24.994-24.994 24.994-65.516 0-90.51s-65.516-24.994-90.51 0l-210.745 210.745-210.745-210.745z" />',
80+
chevronLeft:
81+
'<path fill="#{$color}" d="M10.4714 3.52827C10.7117 3.76859 10.7302 4.14675 10.5269 4.40827L10.4714 4.47108L6.94334 7.99967L10.4714 11.5283C10.7117 11.7686 10.7302 12.1467 10.5269 12.4083L10.4714 12.4711C10.2311 12.7114 9.85294 12.7299 9.59141 12.5265L9.52861 12.4711L5.52861 8.47108C5.28828 8.23076 5.2698 7.8526 5.47315 7.59107L5.52861 7.52827L9.52861 3.52827C9.78896 3.26792 10.2111 3.26792 10.4714 3.52827Z"/>',
82+
chevronRight:
83+
'<path fill="#{$color}" d="M5.52861 3.52827C5.28828 3.76859 5.2698 4.14675 5.47315 4.40827L5.52861 4.47108L9.05666 7.99967L5.52861 11.5283C5.28828 11.7686 5.2698 12.1467 5.47315 12.4083L5.52861 12.4711C5.76893 12.7114 6.14706 12.7299 6.40859 12.5265L6.47139 12.4711L10.4714 8.47108C10.7117 8.23076 10.7302 7.8526 10.5269 7.59107L10.4714 7.52827L6.47139 3.52827C6.21104 3.26792 5.78896 3.26792 5.52861 3.52827Z"/>',
8084
startOver:
8185
'<path fill="#{$color}" d="M255.271 339.053c94.182-126.513 270.298-165.203 410.222-84.418 150.758 87.040 202.411 279.813 115.371 430.571s-279.813 202.411-430.571 115.371c-61.424-35.463-107.948-89.4-134.169-153.673-7.677-18.818-29.156-27.85-47.974-20.173s-27.85 29.156-20.173 47.974c32.339 79.269 89.818 145.906 165.517 189.611 185.96 107.364 423.747 43.649 531.111-142.311s43.649-423.747-142.311-531.111c-172.433-99.554-389.428-52.014-505.682 103.69l-27.226-78.49c-6.66-19.202-27.626-29.368-46.828-22.708s-29.368 27.626-22.708 46.828l52.434 151.164c5.36 15.452 20.275 25.513 36.61 24.694l159.799-8.011c20.299-1.018 35.929-18.298 34.911-38.596s-18.298-35.929-38.596-34.911l-89.738 4.499z" />',
8286
seekEnd:

src/components/icon/icon.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ const IconType = {
2424
SpeedUp: 'speed-up',
2525
Audio: 'audio',
2626
ArrowDown: 'arrow-down',
27+
ChevronLeft: 'chevron-left',
28+
ChevronRight: 'chevron-right',
2729
StartOver: 'start-over',
2830
SeekEnd: 'seek-end',
2931
Rewind: 'rewind',
@@ -269,6 +271,12 @@ class Icon extends Component<any, any> {
269271
case IconType.ArrowDown:
270272
return <i className={[style.icon, style.iconArrowDown].join(' ')} />;
271273

274+
case IconType.ChevronLeft:
275+
return <i className={[style.icon, style.iconChevronLeft].join(' ')} />;
276+
277+
case IconType.ChevronRight:
278+
return <i className={[style.icon, style.iconChevronRight].join(' ')} />;
279+
272280
case IconType.StartOver:
273281
return <i className={[style.icon, style.iconStartOver].join(' ')} />;
274282

src/components/interactive-area/_interactive-area.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
margin: #{$gui-gutter}px;
99
transition: margin #{$hover-animation-time}ms ease-in-out;
1010
flex: 1;
11+
order: 2;
1112
}
1213
.player {
1314
&.size-sm {

src/components/seekbar/_seekbar.scss

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,7 @@
146146
padding: 12px 0;
147147
cursor: pointer;
148148
position: relative;
149-
float: left;
150-
width: calc(100% - 45px);
149+
width: 100%;
151150
margin: 1px 0;
152151

153152
.frame-preview {
@@ -158,3 +157,58 @@
158157
bottom: $progress-bar-height + 12px;
159158
}
160159
}
160+
161+
.player .seekbar-container {
162+
display: flex;
163+
align-items: center;
164+
position: relative;
165+
width: 100%;
166+
167+
.skip-seekbar-button {
168+
position: absolute;
169+
left: 0;
170+
bottom: 100%;
171+
display: flex;
172+
height: 36px;
173+
padding: 8px;
174+
align-items: center;
175+
gap: 4px;
176+
border: none;
177+
border-radius: var(--Roundness-1, 4px);
178+
background: var(--B-60, rgba(0, 0, 0, 0.60));
179+
color: var(--W-100, #FFF);
180+
font-family: Lato, sans-serif;
181+
font-size: 14px;
182+
font-style: normal;
183+
font-weight: 700;
184+
line-height: normal;
185+
white-space: nowrap;
186+
z-index: 10;
187+
cursor: pointer;
188+
189+
// Hide button visually but keep it in the tab order
190+
opacity: 0;
191+
pointer-events: none;
192+
193+
// Show on keyboard focus
194+
&:focus {
195+
opacity: 1;
196+
pointer-events: auto;
197+
outline: 2px solid #2684FF;
198+
box-shadow: 0 0 0 2px white;
199+
outline-offset: 1px;
200+
}
201+
}
202+
203+
.skip-button-icon {
204+
display: flex;
205+
width: 16px;
206+
height: 16px;
207+
align-items: center;
208+
justify-content: center;
209+
}
210+
211+
.seek-bar {
212+
flex: 1;
213+
}
214+
}

0 commit comments

Comments
 (0)