Skip to content

Commit

Permalink
feat: add range CSS parts (#990)
Browse files Browse the repository at this point in the history
fix #921, fix #983

- Brushed up mobile example
https://media-chrome-git-fork-luwes-range-css-parts-mux.vercel.app/examples/vanilla/mobile.html
- Removes the background element, we can use the track element for
setting the CSS background.
- Adds CSS parts: `thumb`, `track`, `progress`, `buffered`.
- `--media-range-track-color` CSS var is removed from JS docs, this was
left over from the old structure with CSS linear-gradient where it
represented the color of the range section on the right of the thumb.

1. a smooth track height transition on hover looks like

```css
  media-time-range::part(track) {
    transition: transform 0.2s;
    transform: scaleY(1);
  }

  media-time-range:hover::part(track) {
    transform: scaleY(1.5);
  }
```

2. adding border-radius to track buffered and track progress elements

```css
media-time-range::part(buffered),
media-time-range::part(progress) {
  border-radius: 9999px;
}
```
  • Loading branch information
luwes authored Oct 4, 2024
1 parent 92542f9 commit 4c6298f
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 63 deletions.
59 changes: 25 additions & 34 deletions examples/vanilla/mobile.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,10 @@
<title>Media Chrome Mobile Video Usage Example</title>
<script type="module" src="../../dist/index.js"></script>
<style>
body {
width: 100vw;
height: 100vh;
margin: 0px;
}

/** add styles to prevent CLS (Cumulative Layout Shift) */
media-controller:not([audio]) {
display: block; /* expands the container if preload=none */
max-width: 320px; /* allows the container to shrink if small */
max-width: 375px; /* allows the container to shrink if small */
aspect-ratio: 16 / 9; /* set container aspect ratio if preload=none */
}

Expand Down Expand Up @@ -43,18 +37,15 @@
display: flex;
flex-flow: row nowrap;
align-items: center;
justify-content: space-evenly;
justify-content: center;
gap: 6%;
margin: -5% auto 0;
width: 60%;
}

*[slot='centered-chrome'] {
margin: 0 15%;
--media-control-hover-background: none;
--media-control-background: none;
}

*[slot='centered-chrome']
:is(media-play-button, media-seek-backward-button, media-seek-forward-button) {
padding: 0px;
*[slot='centered-chrome'] [role='button'] {
border-radius: 50%;
aspect-ratio: 1;
}

*[slot='centered-chrome'] media-play-button {
Expand All @@ -64,20 +55,22 @@
*[slot='centered-chrome']
:is(media-seek-backward-button, media-seek-forward-button) {
width: 15%;
padding: 8px;
}

.seek-control-bar {
padding: 0 5px;
}

.seek-control-bar > * {
media-time-range {
--media-range-track-height: 5px;
--media-range-track-backdrop-filter: blur(5px);
--media-range-padding: 0;
--media-range-thumb-opacity: 0;
background: none;
height: auto;
padding: 0px;
height: var(--media-range-track-height);
width: 100%;
}

.seek-control-bar > media-time-range {
padding-right: 5px;
.spacer {
background: rgb(20 20 30 / .7);
flex-grow: 1;
}
</style>
</head>
Expand All @@ -87,7 +80,7 @@ <h1>Media Chrome Standard Mobile Video Usage Example</h1>
<media-controller autohide="2" defaultduration="134">
<video
slot="media"
src="https://stream.mux.com/DS00Spx1CV902MCtPj5WknGlR102V5HFkDe/high.mp4"
src="https://stream.mux.com/Sc89iWAyNkhJ3P1rQ02nrEdCFTnfT01CZ2KmaEcxXfB008/high.mp4"
preload="none"
muted
crossorigin
Expand All @@ -97,25 +90,23 @@ <h1>Media Chrome Standard Mobile Video Usage Example</h1>
label="thumbnails"
default
kind="metadata"
src="https://image.mux.com/DS00Spx1CV902MCtPj5WknGlR102V5HFkDe/storyboard.vtt"
src="https://image.mux.com/Sc89iWAyNkhJ3P1rQ02nrEdCFTnfT01CZ2KmaEcxXfB008/storyboard.vtt"
/>
</video>
<media-poster-image
slot="poster"
src="https://image.mux.com/DS00Spx1CV902MCtPj5WknGlR102V5HFkDe/thumbnail.jpg"
placeholdersrc="data:image/jpeg;base64,/9j/2wBDAAUDBAQEAwUEBAQFBQUGBwwIBwcHBw8LCwkMEQ8SEhEPERETFhwXExQaFRERGCEYGh0dHx8fExciJCIeJBweHx7/2wBDAQUFBQcGBw4ICA4eFBEUHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh7/wAARCAASACADASIAAhEBAxEB/8QAGgABAAIDAQAAAAAAAAAAAAAAAAMEAgUGCP/EACkQAAEDAgMIAgMAAAAAAAAAAAEAAgMEBgUREgcUITFSkZTRQaEiscH/xAAYAQACAwAAAAAAAAAAAAAAAAAABQIDBv/EAB0RAAICAQUAAAAAAAAAAAAAAAABAgMFERUxwfD/2gAMAwEAAhEDEQA/AOZh2P2k/LOhq/Lf7VuPYvZxLQ6iqgXchvrxn9rpY7ojYCBU0IJ5HU3h9rU3NcGJVcVNJh2K4fDPTztlbm5reGRDhnxIzBPwkUc9RJ6dDHaLYojj2HWYeeH1nmSe1OzYXZJ54fW+ZJ7VeWrbO4SPuedpI/IOnB/TgsxJh4yIuGYu+TvAH9UXnafItWJmuTy1oZ0t7JoZ0t7Ii0InGhnS3smhnS3siIA//9k="
src="https://image.mux.com/Sc89iWAyNkhJ3P1rQ02nrEdCFTnfT01CZ2KmaEcxXfB008/thumbnail.webp?time=13"
></media-poster-image>
<div slot="centered-chrome" class="centered-controls-overlay">
<media-seek-backward-button></media-seek-backward-button>
<media-play-button></media-play-button>
<media-seek-forward-button></media-seek-forward-button>
</div>
<media-control-bar class="seek-control-bar">
<media-time-range></media-time-range>
<media-time-display showduration remaining></media-time-display>
</media-control-bar>
<media-time-range></media-time-range>
<media-control-bar>
<media-mute-button></media-mute-button>
<media-time-display showduration remaining></media-time-display>
<div class="spacer"></div>
<media-playback-rate-button></media-playback-rate-button>
<media-pip-button></media-pip-button>
<media-fullscreen-button></media-fullscreen-button>
Expand Down
40 changes: 13 additions & 27 deletions src/js/media-chrome-range.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,32 +130,22 @@ template.innerHTML = /*html*/ `
will-change: transform;
}
#background,
#track {
border-radius: var(--media-range-track-border-radius, 1px);
position: absolute;
width: 100%;
height: 100%;
}
#background {
background: var(--media-range-track-background, rgb(255 255 255 / .2));
backdrop-filter: var(--media-range-track-background-backdrop-filter);
-webkit-backdrop-filter: var(--media-range-track-background-backdrop-filter);
}
#track {
border-radius: var(--media-range-track-border-radius, 1px);
border: var(--media-range-track-border, none);
outline: var(--media-range-track-outline);
outline-offset: var(--media-range-track-outline-offset);
backdrop-filter: var(--media-range-track-backdrop-filter);
-webkit-backdrop-filter: var(--media-range-track-backdrop-filter);
box-shadow: var(--media-range-track-box-shadow, none);
position: absolute;
width: 100%;
height: 100%;
overflow: hidden;
}
#progress,
#highlight,
#pointer {
position: absolute;
height: 100%;
Expand Down Expand Up @@ -207,7 +197,6 @@ template.innerHTML = /*html*/ `
height: var(--media-range-segment-hover-height, 7px);
}
#background,
#track {
clip-path: url(#segments-clipping);
}
Expand Down Expand Up @@ -239,14 +228,12 @@ template.innerHTML = /*html*/ `
<div id="container">
<div id="startpoint"></div>
<div id="endpoint"></div>
<div id="appearance" part="appearance">
<div id="background"></div>
<div id="track">
<div id="highlight"></div>
<div id="appearance">
<div id="track" part="track">
<div id="pointer"></div>
<div id="progress"></div>
<div id="progress" part="progress"></div>
</div>
<div id="thumb"></div>
<div id="thumb" part="thumb"></div>
<svg id="segments"><clipPath id="segments-clipping"></clipPath></svg>
</div>
<input id="range" type="range" min="0" max="1" step="any" value="0">
Expand All @@ -260,7 +247,9 @@ template.innerHTML = /*html*/ `
* @attr {boolean} disabled - The Boolean disabled attribute makes the element not mutable or focusable.
* @attr {string} mediacontroller - The element `id` of the media controller to connect to (if not nested within).
*
* @csspart appearance - The appearance of the range containing the background, track and thumb.
* @csspart track - The runnable track of the range.
* @csspart progress - The progress part of the track.
* @csspart thumb - The thumb of the range.
*
* @cssproperty --media-primary-color - Default color of range bar.
* @cssproperty --media-secondary-color - Default color of range background.
Expand All @@ -285,8 +274,8 @@ template.innerHTML = /*html*/ `
* @cssproperty --media-range-thumb-transform - `transform` of range thumb.
* @cssproperty --media-range-thumb-opacity - `opacity` of range thumb.
*
* @cssproperty [--media-range-bar-color = var(--media-primary-color, rgb(238 238 238))] - `color_value` of range bar (elapsed progress).
* @cssproperty [--media-range-track-color = transparent] - `color_value` of range track (remaining progress).
* @cssproperty [--media-range-bar-color = var(--media-primary-color, rgb(238 238 238))] - `background` of range progress.
* @cssproperty --media-range-track-background - `background` of range track background.
* @cssproperty --media-range-track-backdrop-filter - `backdrop-filter` of range track.
* @cssproperty --media-range-track-width - `width` of range track.
* @cssproperty --media-range-track-height - `height` of range track.
Expand All @@ -299,9 +288,6 @@ template.innerHTML = /*html*/ `
* @cssproperty --media-range-track-translate-x - `translate` x-coordinate of range track.
* @cssproperty --media-range-track-translate-y - `translate` y-coordinate of range track.
*
* @cssproperty --media-range-track-background - `background` of range track background.
* @cssproperty --media-range-track-background-backdrop-filter - `backdrop-filter` of range track background.
*
* @cssproperty --media-time-range-hover-display - `display` of range hover zone.
* @cssproperty --media-time-range-hover-bottom - `bottom` of range hover zone.
* @cssproperty --media-time-range-hover-height - `height` of range hover zone.
Expand Down
11 changes: 9 additions & 2 deletions src/js/media-time-range.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,11 @@ template.innerHTML = /*html*/ `
contain: layout;
}
#highlight {
#buffered {
background: var(--media-time-range-buffered-color, rgb(255 255 255 / .4));
position: absolute;
height: 100%;
will-change: width;
}
#preview-rail,
Expand Down Expand Up @@ -335,6 +338,7 @@ const calcTimeFromRangeValue = (
* @attr {string} mediapreviewimage - (read-only) Set to the timeline preview image URL.
* @attr {string} mediapreviewtime - (read-only) Set to the timeline preview time.
*
* @csspart buffered - A CSS part that selects the buffered bar element.
* @csspart box - A CSS part that selects both the preview and current box elements.
* @csspart preview-box - A CSS part that selects the preview box element.
* @csspart current-box - A CSS part that selects the current box element.
Expand Down Expand Up @@ -421,6 +425,9 @@ class MediaTimeRange extends MediaChromeRange {

this.container.appendChild(template.content.cloneNode(true));

const track = this.shadowRoot.querySelector('#track');
track.insertAdjacentHTML('afterbegin', '<div id="buffered" part="buffered"></div>');

this.#boxes = this.shadowRoot.querySelectorAll('[part~="box"]');
this.#previewBox = this.shadowRoot.querySelector('[part~="preview-box"]');
this.#currentBox = this.shadowRoot.querySelector('[part~="current-box"]');
Expand Down Expand Up @@ -708,7 +715,7 @@ class MediaTimeRange extends MediaChromeRange {
relativeBufferedEnd = 1;
}

const { style } = getOrInsertCSSRule(this.shadowRoot, '#highlight');
const { style } = getOrInsertCSSRule(this.shadowRoot, '#buffered');
style.setProperty('width', `${relativeBufferedEnd * 100}%`);
}

Expand Down

0 comments on commit 4c6298f

Please sign in to comment.