Skip to content

Commit 1be676a

Browse files
committed
fix(player): prefer setting attrs on spinner elements
1 parent 0cd3d49 commit 1be676a

4 files changed

Lines changed: 72 additions & 35 deletions

File tree

packages/react/src/components/ui/spinner.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ export interface RootProps
99
React.RefAttributes<SVGElement | SVGSVGElement> {
1010
/**
1111
* The horizontal (width) and vertical (height) length of the spinner.
12+
*
13+
* @defaultValue 96
1214
*/
1315
size?: number;
1416
}
@@ -24,7 +26,7 @@ export interface RootProps
2426
* ```
2527
*/
2628
const Root = React.forwardRef<SVGElement | SVGSVGElement, RootProps>(
27-
({ size, children, ...props }: RootProps, forwardRef) => {
29+
({ size = 96, children, ...props }: RootProps, forwardRef) => {
2830
return (
2931
<svg
3032
width={size}
@@ -51,7 +53,7 @@ export interface TrackProps
5153
React.RefAttributes<SVGCircleElement> {}
5254

5355
const Track = React.forwardRef<SVGCircleElement, TrackProps>(
54-
({ width, children, ...props }, ref) => (
56+
({ width = 8, children, ...props }, ref) => (
5557
<circle
5658
cx="60"
5759
cy="60"
@@ -81,7 +83,7 @@ export interface TrackFillProps
8183
}
8284

8385
const TrackFill = React.forwardRef<SVGCircleElement, TrackFillProps>(
84-
({ width, fillPercent = 50, children, ...props }, ref) => (
86+
({ width = 8, fillPercent = 50, children, ...props }, ref) => (
8587
<circle
8688
cx="60"
8789
cy="60"

packages/vidstack/player/styles/default/buffering.css

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,22 +19,22 @@
1919

2020
:where(.vds-buffering-indicator)
2121
:where(.vds-buffering-icon, svg.vds-buffering-spinner, .vds-buffering-spinner svg) {
22-
width: var(--media-buffering-size, 84px) !important;
23-
height: var(--media-buffering-size, 84px) !important;
22+
width: var(--media-buffering-size, 96px);
23+
height: var(--media-buffering-size, 96px);
2424
}
2525

2626
:where(.vds-buffering-indicator) :where(.vds-buffering-track, circle[data-part='track']) {
27-
color: var(--media-buffering-track-color, #f5f5f5) !important;
27+
color: var(--media-buffering-track-color, #f5f5f5);
2828
opacity: var(--media-buffering-track-opacity, 0.25);
29-
stroke-width: var(--media-buffering-track-width, 8) !important;
29+
stroke-width: var(--media-buffering-track-width, 8);
3030
}
3131

3232
:where(.vds-buffering-indicator) :where(.vds-buffering-track-fill, circle[data-part='track-fill']) {
33-
color: var(--media-buffering-track-fill-color, var(--media-brand)) !important;
33+
color: var(--media-buffering-track-fill-color, var(--media-brand));
3434
opacity: var(--media-buffering-track-fill-opacity, 0.75);
35-
stroke-width: var(--media-buffering-track-fill-width, 9) !important;
35+
stroke-width: var(--media-buffering-track-fill-width, 9);
3636
stroke-dasharray: 100;
37-
stroke-dashoffset: var(--media-buffering-track-fill-offset, 50) !important;
37+
stroke-dashoffset: var(--media-buffering-track-fill-offset, 50);
3838
}
3939

4040
:where([data-buffering]) :where(.vds-buffering-icon, .vds-buffering-spinner) {

packages/vidstack/player/styles/default/layouts/video.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,7 @@
375375
--media-button-hover-transform: translateY(25%);
376376
border-radius: 100%;
377377
pointer-events: auto;
378-
margin-bottom: 2.5%;
378+
margin-bottom: 2px;
379379
width: var(--video-sm-play-button-size, 40px);
380380
height: var(--video-sm-play-button-size, 40px);
381381
transform: var(--video-sm-play-button-transform, translateY(25%));

packages/vidstack/src/elements/define/spinner-element.ts

Lines changed: 59 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,80 @@
11
import { html } from 'lit-html';
2+
import { Component, effect } from 'maverick.js';
3+
import { Host } from 'maverick.js/element';
4+
import { setAttribute } from 'maverick.js/std';
25

6+
import { requestScopedAnimationFrame } from '../../utils/dom';
37
import { LitElement } from '../lit/lit-element';
48

9+
export interface SpinnerProps {
10+
/**
11+
* The horizontal (width) and vertical (height) length of the spinner.
12+
*/
13+
size: number;
14+
/**
15+
* The width of the spinner track and track fill.
16+
*/
17+
trackWidth: number;
18+
/**
19+
* The percentage of the spinner track that should be filled.
20+
*/
21+
fillPercent: number;
22+
}
23+
24+
export class Spinner extends Component<SpinnerProps> {
25+
static props: SpinnerProps = {
26+
size: 96,
27+
trackWidth: 8,
28+
fillPercent: 50,
29+
};
30+
31+
protected override onConnect(el: HTMLElement): void {
32+
requestScopedAnimationFrame(() => {
33+
if (!this.connectScope) return;
34+
35+
const root = el.querySelector('svg')!,
36+
track = root.firstElementChild as SVGCircleElement,
37+
trackFill = track.nextElementSibling as SVGCircleElement;
38+
39+
effect(this._update.bind(this, root, track, trackFill));
40+
});
41+
}
42+
43+
private _update(root: SVGSVGElement, track: SVGCircleElement, trackFill: SVGCircleElement) {
44+
const { size, trackWidth, fillPercent } = this.$props;
45+
setAttribute(root, 'width', size());
46+
setAttribute(root, 'height', size());
47+
setAttribute(track, 'stroke-width', trackWidth());
48+
setAttribute(trackFill, 'stroke-width', trackWidth());
49+
setAttribute(trackFill, 'stroke-dashoffset', 100 - fillPercent());
50+
}
51+
}
52+
553
/**
654
* @docs {@link https://www.vidstack.io/docs/wc/player/components/display/buffering-indicator}
755
* @example
856
* ```html
9-
* <media-spinner></media-spinner>
57+
* <!-- default values below -->
58+
* <media-spinner size="84" track-width="8" fill-percent="50"></media-spinner>
1059
* ```
1160
* @example
1261
* ```css
13-
* media-spinner {
14-
* --size: 84px;
15-
* --track-width: 8px;
16-
* --track-color: rgb(255 255 255 / 0.5);
17-
* --track-fill-color: white;
18-
* --track-fill-percent: 50;
62+
* media-spinner [data-part="track"] {
63+
* color: rgb(255 255 255 / 0.5);
64+
* }
65+
*
66+
* media-spinner [data-part="track-fill"] {
67+
* color: white;
1968
* }
2069
* ```
2170
*/
22-
export class MediaSpinnerElement extends LitElement {
71+
export class MediaSpinnerElement extends Host(LitElement, Spinner) {
2372
static tagName = 'media-spinner';
2473

2574
render() {
2675
return html`
27-
<svg
28-
fill="none"
29-
viewBox="0 0 120 120"
30-
aria-hidden="true"
31-
data-part="root"
32-
style="width: var(--size); height: var(--size)"
33-
>
34-
<circle
35-
cx="60"
36-
cy="60"
37-
r="54"
38-
stroke="currentColor"
39-
data-part="track"
40-
style="color: var(--track-color); stroke-width: var(--track-width);"
41-
></circle>
76+
<svg fill="none" viewBox="0 0 120 120" aria-hidden="true" data-part="root">
77+
<circle cx="60" cy="60" r="54" stroke="currentColor" data-part="track"></circle>
4278
<circle
4379
cx="60"
4480
cy="60"
@@ -47,7 +83,6 @@ export class MediaSpinnerElement extends LitElement {
4783
pathLength="100"
4884
stroke-dasharray="100"
4985
data-part="track-fill"
50-
style="color: var(--track-fill-color); stroke-width: var(--track-width); stroke-dashoffset: calc(100 - var(--track-fill-percent, 50));"
5186
></circle>
5287
</svg>
5388
`;

0 commit comments

Comments
 (0)