From 113078df77144bcb0f04885394bbdfc869c4e46d Mon Sep 17 00:00:00 2001 From: edwinbradford Date: Fri, 8 Nov 2024 10:58:10 +0000 Subject: [PATCH] Update src css components to 18.9.0 Update multiple css component and sandbox examples. 1. Merge 18.9.0 from upstream. 2. Merge css for spatial navigation. 3. Merge css for experimental svgs. 4. Merge css for audio only mode. 5. Replace absolute layout of controlbar children with flexbox. 6. Add controlbar flexwrap component javascript and css. 7. Add time and pad time javascript and css. 8. Update big play and play pause positioning. --- sandbox/combined-tracks.html.example | 198 +++++++++-- sandbox/index.html.example | 162 ++++++++- src/css/_private-variables.scss | 41 ++- src/css/_utilities.scss | 17 +- src/css/components/_big-play.scss | 37 +- src/css/components/_button.scss | 27 +- src/css/components/_captions-settings.scss | 92 ++--- src/css/components/_captions.scss | 48 +-- src/css/components/_control-bar.scss | 81 +++-- src/css/components/_control-spacer.scss | 5 + src/css/components/_control.scss | 38 +- src/css/components/_descriptions.scss | 48 +-- src/css/components/_error.scss | 38 +- src/css/components/_fullscreen.scss | 22 +- src/css/components/_layout.scss | 106 ++++-- src/css/components/_live.scss | 77 ++-- src/css/components/_modal-dialog.scss | 6 +- src/css/components/_picture-in-picture.scss | 20 +- src/css/components/_play-pause.scss | 80 +++-- src/css/components/_progress.scss | 317 ++++++++--------- src/css/components/_slider.scss | 13 +- src/css/components/_subs-caps.scss | 128 +++---- src/css/components/_time.scss | 51 +-- src/css/components/_volume.scss | 375 +++++++++----------- src/css/components/menu/_menu-inline.scss | 29 +- 25 files changed, 1178 insertions(+), 878 deletions(-) diff --git a/sandbox/combined-tracks.html.example b/sandbox/combined-tracks.html.example index 511ebfebb8..6cacfef0e1 100644 --- a/sandbox/combined-tracks.html.example +++ b/sandbox/combined-tracks.html.example @@ -2,44 +2,143 @@ + Video.js Sandbox - + + + -
-

You can use /sandbox/ for writing and testing your own code. Nothing in /sandbox/ will get checked into the repo, except files that end in .example (so don't edit or add those files). To get started run `npm start` and open the combined-tracks.html

-
npm start
-
open http://localhost:9999/sandbox/combined-tracks.html
-
- - -

This player has the captions-only captionsButton, the subtiles-only subtitlesButton and the subsCapsButton which shows both kinds. Typically you'll use either just the subsCapsButton alone, or one or both of the captionsButton and subtitlesButton.

+ - diff --git a/sandbox/index.html.example b/sandbox/index.html.example index 80ebf99678..c6b0ac73ea 100644 --- a/sandbox/index.html.example +++ b/sandbox/index.html.example @@ -1,37 +1,169 @@ - + + Video.js Sandbox + + + + + -
-

You can use /sandbox/ for writing and testing your own code. Nothing in /sandbox/ will get checked into the repo, except files that end in .example (so don't edit or add those files). To get started run `npm start` and open the index.html

-
npm start
-
open http://localhost:9999/sandbox/index.html
-
- + poster="https://vjs.zencdn.net/v/oceans.png" + > - +

To view this video please enable JavaScript, and consider upgrading to a web browser that supports HTML5 video

- + /* Add a custom component to wrap control bar child flex items, + * cf. player control bar children below + */ + const Component = videojs.getComponent('Component'); + class neueWrap extends Component { + constructor(player, options) { + super(player, options); + this.addClass('vjs-neue-wrap'); // Add any classes you want + } + } + videojs.registerComponent('neueWrap', neueWrap); + + /* Pad time with leading zeros, + * cf. player ready function below + */ + function formatTimeWithLeadingZeros(seconds) { + const minutes = Math.floor(seconds / 60); + const remainingSeconds = Math.floor(seconds % 60); + return `${minutes < 10 ? '0' : ''}${minutes}:${remainingSeconds < 10 ? '0' : ''}${remainingSeconds}`; + } + + var player = videojs('videojsElement', { + autoplay: false, + controls: true, + loop: false, + muted: false, + preload: 'auto', + responsive: true, + fluid: true, // (1) or... + // fill: true, // (2) or... + // aspectRatio: '16:9', // (3) + // audioOnlyMode: true, + spatialNavigation: { + enabled: true, + horizontalSeek: true + }, + // Breakpoints require responsive: true + breakpoints: { + tiny: 300, + xsmall: 400, + small: 500, + medium: 600, + large: 700, + xlarge: 800, + huge: 900 + }, + html5: { + nativeTextTracks: false, + nativeControlsForTouch: false, + nativeAudioTracks: false, + nativeVideoTracks: false, + }, + inactivityTimeout: 1000, + controlBar: { + // children in flex order + children: [ + 'playToggle', + { + name: 'volumePanel', + inline: true // Horizontal + }, + 'customControlSpacer', + 'playbackRateMenuButton', + 'chaptersButton', + 'descriptionsButton', + 'subtitlesButton', + 'captionsButton', + 'subsCapsButton', + 'audioTrackButton', + 'pictureInPictureToggle', + 'fullscreenToggle', + 'neueWrap', // Custom flexwrap component + 'currentTimeDisplay', + 'timeDivider', + 'durationDisplay', + 'progressControl', + 'liveDisplay', + 'seekToLive', + { + name: 'remainingTimeDisplay', + displayNegative: false + }, + ], + }, + }); + /* Show big play button when paused and time controls, + * cf. https://github.com/videojs/video.js/pull/8833 + */ + player.addClass( + 'vjs-normalise-time-controls', + 'vjs-show-big-play-button-on-pause' + ); + player.ready(function() { + // Start spatial navigation e.g. pointer devices + player.spatialNavigation.start(); + + // Pad time with leading zeros + const currentTimeDisplay = player.controlBar.currentTimeDisplay; + const remainingTimeDisplay = player.controlBar.remainingTimeDisplay; + + currentTimeDisplay.el().innerText = formatTimeWithLeadingZeros(0); + remainingTimeDisplay.el().innerText = formatTimeWithLeadingZeros(player.duration()); + + currentTimeDisplay.updateContent = function() { + const currentTime = player.currentTime(); + this.el().innerText = formatTimeWithLeadingZeros(currentTime); + }; + + remainingTimeDisplay.updateContent = function() { + const remainingTime = player.remainingTime(); + this.el().innerText = formatTimeWithLeadingZeros(Math.abs(remainingTime)); + }; + }); + // player.createModal('foo'); + console.log(player.language()); + diff --git a/src/css/_private-variables.scss b/src/css/_private-variables.scss index dc36b05134..cf1e1b114b 100644 --- a/src/css/_private-variables.scss +++ b/src/css/_private-variables.scss @@ -1,22 +1,29 @@ -// Global -$text-font-family: Consolas, Lucida Console, Lucida Sans Typewriter, monospace !default; -$text-em-size: 10px; - -// Colors -$accent-color: #e50000; +// Text, icons, hover states $primary-foreground-color: #e6e6e6 !default; + +// Control backgrounds (control bar, big play, menus) $primary-background-color: #1a1a1a !default; +$primary-background-transparency: 0.4 !default; // Used for progress holder + +// Hover states, slider backgrounds +$secondary-background-color: lighten($primary-background-color, 33%) !default; +$secondary-background-transparency: 0.5 !default; + +$accent-color: #e50000; + $menu-text-color: #999; $menu-text-color-highlight: #ccc; $menu-background-color-highlight: #666 !default; $menu-background-color: #333 !default; // menus -// Transparency -$primary-background-transparency: 0.4 !default; // Used for progress holder -$secondary-background-transparency: 0.4 !default; // Not used for AV Neue theme +// Text +$text-font-family: Consolas, Lucida Console, Lucida Sans Typewriter, monospace !default; +$text-em-size: 10px; -// Filters -$filter-drop-shadow: drop-shadow(0px 0px 1px rgba(0, 0, 0, 0.5)); +// Big play button +// Using the '--' naming for component-specific styles +$big-play-button--width: 6.4em !default; +$big-play-button--height: 6.4em !default; // Progress and sliders $slider-height: 0.2em; // Slider height @@ -26,17 +33,10 @@ $slider-handle-height-increase: 8; // Handle height is this factor bigger than $ $slider-hover-height: 8; // Height of progress bar hover area $progress-bar-margin: 5.4em; // Side margins for progress bar -// Big play button -// Using the '--' naming for component-specific styles -$big-play-button--width: 6.4em !default; -$big-play-button--height: 6.4em !default; - - // Loading vjs-spinner-fade $loading-spinner-size: $big-play-button--width; $loading-spinner-stroke: 4px; - // Controls $controls-margin: 2.4em; $control-button-height: 1.8em; @@ -59,9 +59,12 @@ $modal-text-line-height: 1.5; // Menus $menu-popup-width: 16em; +// Filters +$filter-drop-shadow: drop-shadow(0px 0px 1px rgba(0, 0, 0, 0.5)); + // Animations $icon-highlight-time: 0ms; $icon-unhighlight-time: 0ms; $icon-fade-in-time: 0ms; $icon-fade-out-time: 1000ms; -$slider-handle-resize-time: 500ms; +$slider-handle-resize-time: 250ms; diff --git a/src/css/_utilities.scss b/src/css/_utilities.scss index 3f83315f0e..6969a82c0b 100644 --- a/src/css/_utilities.scss +++ b/src/css/_utilities.scss @@ -1,4 +1,3 @@ -// AV Neue theme does not use gradients @import "utilities/linear-gradient"; @mixin background-color-with-alpha($color, $alpha) { @@ -32,14 +31,14 @@ animation: $string; } -@mixin display-flex($alignment: "", $justification: "") { +@mixin display-flex($alignment: '', $justification: '') { display: flex; - @if $alignment != "" { + @if $alignment != '' { align-items: $alignment; } - @if $justification != "" { + @if $justification != '' { justify-content: $justification; } } @@ -60,7 +59,7 @@ } // https://developer.mozilla.org/en-US/docs/Web/CSS/box-shadow -@mixin box-shadow($string: 0 0 1em rgba(0, 0, 0, 0.25)) { +@mixin box-shadow ($string: 0 0 1em rgba(0, 0, 0, 0.25)) { box-shadow: $string; } @@ -81,7 +80,13 @@ text-align: center; } -// AV Neue theme uses filters for SVG drop shadows +// Neue spatial highlight style +%neue-spatial { + filter: drop-shadow(0 0 8px white); + outline: none; +} + +// Neue SVG drop shadows @mixin filter($filter) { filter: $filter; } diff --git a/src/css/components/_big-play.scss b/src/css/components/_big-play.scss index 67b3193d4f..fda2e5f37d 100644 --- a/src/css/components/_big-play.scss +++ b/src/css/components/_big-play.scss @@ -1,15 +1,11 @@ -@use "sass:math"; - // Big play button shape and triangle .video-js .vjs-big-play-button { + display: block; position: absolute; - top: 50%; - left: 50%; - z-index: 0; // AV Neue play button behind when playing + inset: 0; width: $big-play-button--width; height: $big-play-button--height; - margin-top: math.div($big-play-button--height, -2); - margin-left: math.div($big-play-button--width, -2); + margin: auto; // Center vertically and horizontally padding: 0; cursor: pointer; opacity: 1; @@ -31,9 +27,14 @@ } } -// Allow people that hate their poster image to center the big play button. -.vjs-big-play-centered .vjs-big-play-button { - // AV Neue theme play button is already centered by default +.vjs-big-play-button .vjs-svg-icon { + width: 1em; + height: 1em; + position: absolute; + top: 50%; + left: 50%; + line-height: 1; + transform: translate(-50%, -50%); } // Play button hover changes @@ -46,26 +47,14 @@ } } -// Hide if controls are disabled or native controls are used. +// Hide if controls are disabled, the video is playing, or native controls are used. .vjs-controls-disabled .vjs-big-play-button, +.vjs-has-started .vjs-big-play-button, .vjs-using-native-controls .vjs-big-play-button, .vjs-error .vjs-big-play-button { display: none; } -// Hide if the video is playing -.vjs-has-started .vjs-big-play-button { - pointer-events: none; - opacity: 0; -} - -// Show if the video is paused -.video-js.vjs-paused .vjs-big-play-button { - z-index: 10; // AV Neue play button in front when paused - pointer-events: all; - opacity: 1; -} - // Show big play button if video is paused and .vjs-show-big-play-button-on-pause is set on video element .vjs-has-started.vjs-paused.vjs-show-big-play-button-on-pause .vjs-big-play-button { diff --git a/src/css/components/_button.scss b/src/css/components/_button.scss index 8db506db14..780114ca43 100644 --- a/src/css/components/_button.scss +++ b/src/css/components/_button.scss @@ -1,24 +1,39 @@ .video-js button { + background: none; + border: none; + color: inherit; display: inline-block; + margin: 0; padding: 0; overflow: visible; // IE8 font-family: inherit; font-size: inherit; // IE in general. WTF. line-height: inherit; - text-decoration: none; text-transform: none; - color: inherit; - border: none; - background: none; + text-decoration: none; transition: none; + // Chrome < 83 -webkit-appearance: none; - -moz-appearance: none; appearance: none; } -.vjs-control .vjs-button { +// Replacement for focus in case spatial navigation is enabled +.video-js.vjs-spatial-navigation-enabled .vjs-button:focus { + @extend %neue-spatial; +} + +// Control bar grandchild buttons +.vjs-control.vjs-button .vjs-button { width: 100%; height: 100%; } + +// Control bar child buttons +.vjs-control.vjs-button { + // Don't scale buttons down on tiny screens + width: $control-button-width; + min-width: $control-button-width; + height: $control-button-height; +} diff --git a/src/css/components/_captions-settings.scss b/src/css/components/_captions-settings.scss index 8dd1529d06..d153f7c013 100644 --- a/src/css/components/_captions-settings.scss +++ b/src/css/components/_captions-settings.scss @@ -14,11 +14,10 @@ } } -// Layout divs -.vjs-text-track-settings .vjs-modal-dialog-content { - // Disabled. Layout is vertical for AV Neue theme - // display: table; -} +// // Layout divs +// .vjs-text-track-settings .vjs-modal-dialog-content { +// display: table; +// } .vjs-text-track-settings .vjs-track-settings-colors { margin-bottom: 1.6em; @@ -28,44 +27,47 @@ margin-bottom: 2.4em; } -.vjs-text-track-settings .vjs-track-settings-controls { - // -} - -/* -// code that will only run if CSS Grid is supported by the browser -@supports (display: grid) { - .vjs-text-track-settings .vjs-modal-dialog-content { - display: grid; - grid-template-columns: 1fr 1fr; - grid-template-rows: 1fr; - // Flex and Grid for Firefox, IE, and Edge remove the bottom padding/margin in a container as size decreases - // so we add bottom padding/margin to the last item in the grid instead of here - // see https://stackoverflow.com/a/23754080 - padding: 20px 24px 0px 24px; - } - - // see the comment for padding above - .vjs-track-settings-controls .vjs-default-button { - margin-bottom: 20px; - } - - .vjs-text-track-settings .vjs-track-settings-controls { - // make this take up both columns - grid-column: 1 / -1; - } - - // 1 column for small players - .vjs-layout-small .vjs-text-track-settings .vjs-modal-dialog-content , - .vjs-layout-x-small .vjs-text-track-settings .vjs-modal-dialog-content, - .vjs-layout-tiny .vjs-text-track-settings .vjs-modal-dialog-content { - grid-template-columns: 1fr; - } - -} -*/ +// .vjs-text-track-settings .vjs-track-settings-controls { +// text-align: right; +// vertical-align: bottom; +// } + +// // code that will only run if CSS Grid is supported by the browser +// @supports (display: grid) { +// .vjs-text-track-settings .vjs-modal-dialog-content { +// display: grid; +// grid-template-columns: 1fr 1fr; +// grid-template-rows: 1fr; +// // Flex and Grid for Firefox, IE, and Edge remove the bottom padding/margin in a container as size decreases +// // so we add bottom padding/margin to the last item in the grid instead of here +// // see https://stackoverflow.com/a/23754080 +// padding: 20px 24px 0px 24px; +// } + +// // see the comment for padding above +// .vjs-track-settings-controls .vjs-default-button { +// margin-bottom: 20px; +// } + +// .vjs-text-track-settings .vjs-track-settings-controls { +// // make this take up both columns +// grid-column: 1 / -1; +// } + +// // 1 column for small players +// .vjs-layout-small .vjs-text-track-settings .vjs-modal-dialog-content , +// .vjs-layout-x-small .vjs-text-track-settings .vjs-modal-dialog-content, +// .vjs-layout-tiny .vjs-text-track-settings .vjs-modal-dialog-content { +// grid-template-columns: 1fr; +// } + +// } // Form elements +// .vjs-text-track-settings select { +// font-size: inherit; +// } + .vjs-track-setting > select { margin-right: 1em; margin-bottom: 0.5em; @@ -84,9 +86,11 @@ font-family: inherit; font-size: 1em; } - span { - display: inline-block; - } +} + +.vjs-text-track-settings fieldset span { + display: inline-block; + // padding: 0 .6em .8em; } // style the second select for text colors diff --git a/src/css/components/_captions.scss b/src/css/components/_captions.scss index 781323dd53..caf74a2eac 100644 --- a/src/css/components/_captions.scss +++ b/src/css/components/_captions.scss @@ -1,28 +1,30 @@ -.video-js .vjs-captions-button { - span.vjs-icon-placeholder { +.video-js .vjs-captions-button .vjs-icon-placeholder { + display: block; + position: relative; // Required for positioning of pseudo content + width: 100%; + height: 100%; + background-size: contain; + @extend .icon-closed-captions; + &:before { display: block; - position: relative; // Required for positioning of pseudo content - width: 100%; - height: 100%; - background-size: contain; - @extend .icon-closed-captions; + position: absolute; + top: 0; + left: 0; + width: inherit; + height: inherit; + content: ""; + opacity: 0; + @extend .icon-closed-captions-highlight; + @include transition(opacity $icon-unhighlight-time); + } + &:hover { &:before { - display: block; - position: absolute; - top: 0; - left: 0; - width: inherit; - height: inherit; - content: ""; - opacity: 0; - @extend .icon-closed-captions-highlight; - @include transition(opacity $icon-unhighlight-time); - } - &:hover { - &:before { - opacity: 1; - @include transition(opacity $icon-highlight-time); - } + opacity: 1; + @include transition(opacity $icon-highlight-time); } } } + +.video-js.vjs-audio-only-mode .vjs-captions-button { + display: none; +} diff --git a/src/css/components/_control-bar.scss b/src/css/components/_control-bar.scss index c36fe40e28..b0466b0f99 100644 --- a/src/css/components/_control-bar.scss +++ b/src/css/components/_control-bar.scss @@ -1,32 +1,48 @@ -// Container for all the buttons except the big play button -// Covers the video .video-js .vjs-control-bar { + display: none; + flex-direction: row; + align-content: space-between; + flex-wrap: wrap; + gap: $control-button-spacing; position: absolute; - top: $controls-margin; - right: $controls-margin; - bottom: $controls-margin; - left: $controls-margin; - width: auto; - // background-color: rgba(255,255,0,0.5); // yellow debug background - pointer-events: none; // Stop overlay from preventing buttons below from working - @include display-flex( flex-start, flex-end); - - // will target parent vjs-button divs but not child vjs-button buttons - .vjs-control.vjs-button { - width: $control-button-width; // don't allow buttons to scale down on tiny screens - min-width: $control-button-width; // don't allow buttons to scale down on tiny screens - height: $control-button-height; - margin-left: $control-button-spacing; - &:first-child { - margin-left: 0; - } - } -} - -// Video has started playing -.vjs-has-started .vjs-control-bar { + inset: $controls-margin; + pointer-events: none; // Don't block nested buttons +} + +/* Flex wrap control bar children at the custom neueWrap component + */ +.video-js .vjs-neue-wrap { + width: 100%; + height: 0; +} + +/* Show controls before .vjs-has-started + * cf. https://github.com/videojs/video.js/issues/5143 + */ +.video-js:not(.vjs-has-started) .vjs-control-bar { + display: flex; +} + +.video-js.vjs-spatial-navigation-enabled .vjs-control-bar { + gap: $control-button-spacing; +} + +// Locks the display only if: +// - controls are not disabled +// - native controls are not used +// - there is no error +.video-js:not(.vjs-controls-disabled, .vjs-using-native-controls, .vjs-error) .vjs-control-bar.vjs-lock-showing { + display: flex !important; +} + +// Video has started playing or we are in audioOnlyMode +.vjs-has-started .vjs-control-bar, +.vjs-audio-only-mode .vjs-control-bar { + @include display-flex; + visibility: visible; opacity: 1; - $trans: opacity 500ms; + + $trans: visibility 500ms, opacity 500ms; // Var needed because of comma @include transition($trans); } @@ -35,7 +51,11 @@ // Remain visible for screen reader and keyboard users visibility: visible; opacity: 0; - $trans: opacity 500ms; + // prevent a click/tap from interacting with vjs-lock-showing menu's + // or other controls while we are inactive/hidden + pointer-events: none; + + $trans: visibility 500ms, opacity 500ms; @include transition($trans); } @@ -47,7 +67,10 @@ display: none !important; } -// Don't hide the control bar if it's audio -.vjs-audio.vjs-has-started.vjs-user-inactive.vjs-playing .vjs-control-bar { +// Don't hide the control bar if it's audio or in audioOnlyMode +.vjs-audio.vjs-has-started.vjs-user-inactive.vjs-playing .vjs-control-bar, +.vjs-audio-only-mode.vjs-has-started.vjs-user-inactive.vjs-playing .vjs-control-bar { opacity: 1; + visibility: visible; + pointer-events: auto; } diff --git a/src/css/components/_control-spacer.scss b/src/css/components/_control-spacer.scss index 63e708386a..c3a55aa410 100644 --- a/src/css/components/_control-spacer.scss +++ b/src/css/components/_control-spacer.scss @@ -1,4 +1,9 @@ .video-js .vjs-custom-control-spacer { display: none; height: $control-button-height; + width: 4em; // Any custom width + + // Remove control button gap on each side + margin-inline: $control-button-spacing * -1; + } diff --git a/src/css/components/_control.scss b/src/css/components/_control.scss index c1155b5714..cc7d239a51 100644 --- a/src/css/components/_control.scss +++ b/src/css/components/_control.scss @@ -6,29 +6,37 @@ padding: 0; pointer-events: all; outline: none; - &:before { - // Not used for AV Neue theme? See VideoJS upstream. - /* - font-size: 1.8em; - line-height: 1.67; - text-align: center; - */ - } } +.video-js .vjs-control.vjs-visible-text { + width: auto; + padding-left: 1em; + padding-right: 1em; +} + +// .vjs-button > .vjs-icon-placeholder:before { +// font-size: 1.8em; +// line-height: 1.67; + +// @extend %icon-default; +// } + .vjs-button > .vjs-icon-placeholder { display: block; } -// Replacement for focus outline -.video-js .vjs-control:focus:before, -.video-js .vjs-control:hover:before, -.video-js .vjs-control:focus { - // Disabled for Neue - // text-shadow: 0em 0em 1em rgba($primary-foreground-color, 1); +.vjs-button > .vjs-svg-icon { + display: inline-block; } +// // Replacement for focus outline +// .video-js .vjs-control:focus:before, +// .video-js .vjs-control:hover:before, +// .video-js .vjs-control:focus { +// text-shadow: 0em 0em 1em rgba($primary-foreground-color, 1); +// } + // Hide control text visually, but have it available for screenreaders -.video-js .vjs-control-text { +.video-js *:not(.vjs-visible-text) > .vjs-control-text { @include hide-visually; } diff --git a/src/css/components/_descriptions.scss b/src/css/components/_descriptions.scss index 787364bd25..7e9832a168 100644 --- a/src/css/components/_descriptions.scss +++ b/src/css/components/_descriptions.scss @@ -1,28 +1,30 @@ -.video-js .vjs-descriptions-button { - span.vjs-icon-placeholder { +.video-js .vjs-descriptions-button .vjs-icon-placeholder { + display: block; + position: relative; // Required for positioning of pseudo content + width: 100%; + height: 100%; + background-size: contain; + @extend .icon-descriptions; + &:before { display: block; - position: relative; // Required for positioning of pseudo content - width: 100%; - height: 100%; - background-size: contain; - @extend .icon-descriptions; + position: absolute; + top: 0; + left: 0; + width: inherit; + height: inherit; + content: ""; + opacity: 0; + @extend .icon-descriptions-highlight; + @include transition(opacity $icon-unhighlight-time); + } + &:hover { &:before { - display: block; - position: absolute; - top: 0; - left: 0; - width: inherit; - height: inherit; - content: ""; - opacity: 0; - @extend .icon-descriptions-highlight; - @include transition(opacity $icon-unhighlight-time); - } - &:hover { - &:before { - opacity: 1; - @include transition(opacity $icon-highlight-time); - } + opacity: 1; + @include transition(opacity $icon-highlight-time); } } } + +.video-js.vjs-audio-only-mode .vjs-descriptions-button { + display: none; +} diff --git a/src/css/components/_error.scss b/src/css/components/_error.scss index 0755a6a077..7ac118848e 100644 --- a/src/css/components/_error.scss +++ b/src/css/components/_error.scss @@ -3,25 +3,21 @@ // see _modal-dialog.scss; } -/* - * Not used in AV Neue theme - * -.vjs-error .vjs-error-display:before { - color: #fff; - content: 'X'; - font-family: $text-font-family; - font-size: 4em; - left: 0; +// .vjs-error .vjs-error-display:before { +// color: #fff; +// content: 'X'; +// font-family: $text-font-family; +// font-size: 4em; +// left: 0; - // In order to center the play icon vertically we need to set the line height - // to the same as the button height - line-height: 1; - margin-top: -0.5em; - position: absolute; - text-shadow: 0.05em 0.05em 0.1em #000; - text-align: center; - top: 50%; - vertical-align: middle; - width: 100%; -} -*/ +// // In order to center the play icon vertically we need to set the line height +// // to the same as the button height +// line-height: 1; +// margin-top: -0.5em; +// position: absolute; +// text-shadow: 0.05em 0.05em 0.1em #000; +// text-align: center; +// top: 50%; +// vertical-align: middle; +// width: 100%; +// } diff --git a/src/css/components/_fullscreen.scss b/src/css/components/_fullscreen.scss index 20c98e783d..e7a25b85d0 100644 --- a/src/css/components/_fullscreen.scss +++ b/src/css/components/_fullscreen.scss @@ -1,6 +1,8 @@ .video-js .vjs-fullscreen-control { - span.vjs-icon-placeholder { - cursor: pointer; + cursor: pointer; + @include flex(none); + + .vjs-icon-placeholder { display: block; position: relative; // Required for positioning of pseudo content width: 100%; @@ -25,15 +27,19 @@ @include transition(opacity $icon-highlight-time); } } + } } +.video-js.vjs-audio-only-mode .vjs-fullscreen-control, +.vjs-pip-window .vjs-fullscreen-control { + display: none; +} + // Switch to the exit icon when the player is in fullscreen -.video-js.vjs-fullscreen .vjs-fullscreen-control { - span.vjs-icon-placeholder { - @extend .icon-fullscreen-exit; - &:before { - @extend .icon-fullscreen-exit-highlight; - } +.video-js.vjs-fullscreen .vjs-fullscreen-control .vjs-icon-placeholder { + @extend .icon-fullscreen-exit; + &:before { + @extend .icon-fullscreen-exit-highlight; } } diff --git a/src/css/components/_layout.scss b/src/css/components/_layout.scss index 2ff81ca7a3..2fe7f96ef4 100644 --- a/src/css/components/_layout.scss +++ b/src/css/components/_layout.scss @@ -1,9 +1,6 @@ @use "sass:math"; .video-js { - // display:inline-block would be closer to the video el's display:inline - // but it results in flash reloading when going into fullscreen [#2205] - // TODO: Still needed? display: block; // Make video.js videos align top when next to video elements vertical-align: top; @@ -50,17 +47,6 @@ box-sizing: inherit; } -/* Remove blue border highlighting for AV Neue */ -.video-js textarea:focus, -input:focus { - outline: none; -} - -/* Remove blue border highlighting for AV Neue */ -.video-js *:focus { - outline: none; -} - // List style reset .video-js ul { font-family: inherit; @@ -85,21 +71,38 @@ input:focus { // the user set AR injected into the header. .video-js.vjs-fluid, .video-js.vjs-16-9, -.video-js.vjs-4-3 { +.video-js.vjs-4-3, +.video-js.vjs-9-16, +.video-js.vjs-1-1 { width: 100%; max-width: 100%; +} + +.video-js.vjs-fluid:not(.vjs-audio-only-mode), +.video-js.vjs-16-9:not(.vjs-audio-only-mode), +.video-js.vjs-4-3:not(.vjs-audio-only-mode), +.video-js.vjs-9-16:not(.vjs-audio-only-mode), +.video-js.vjs-1-1:not(.vjs-audio-only-mode) { height: 0; } -.video-js.vjs-16-9 { +.video-js.vjs-16-9:not(.vjs-audio-only-mode) { @include apply-aspect-ratio(16, 9); } -.video-js.vjs-4-3 { +.video-js.vjs-4-3:not(.vjs-audio-only-mode) { @include apply-aspect-ratio(4, 3); } -.video-js.vjs-fill { +.video-js.vjs-9-16:not(.vjs-audio-only-mode) { + @include apply-aspect-ratio(9, 16); +} + +.video-js.vjs-1-1:not(.vjs-audio-only-mode) { + @include apply-aspect-ratio(1, 1); +} + +.video-js.vjs-fill:not(.vjs-audio-only-mode) { width: 100%; height: 100%; } @@ -114,13 +117,20 @@ input:focus { height: 100%; } -// Fullscreen Styles -body.vjs-full-window { +.video-js.vjs-audio-only-mode .vjs-tech { + display: none; +} + +// Fullscreen and Document Picture-in-Picture Styles +body.vjs-full-window, +body.vjs-pip-window { padding: 0; margin: 0; height: 100%; } -.vjs-full-window .video-js.vjs-fullscreen { + +.vjs-full-window .video-js.vjs-fullscreen, +body.vjs-pip-window .video-js { position: fixed; overflow: hidden; z-index: 1000; @@ -129,22 +139,41 @@ body.vjs-full-window { bottom: 0; right: 0; } -.video-js.vjs-fullscreen:not(.vjs-ios-native-fs) { + +.video-js.vjs-fullscreen:not(.vjs-ios-native-fs), +body.vjs-pip-window .video-js { width: 100% !important; height: 100% !important; // Undo any aspect ratio padding for fluid layouts padding-top: 0 !important; + // Older Safari (<= 15.6) needs display: block in fullscreen. + display: block; } .video-js.vjs-fullscreen.vjs-user-inactive { cursor: none; } -// Hide disabled or unsupported controls. -.vjs-hidden { - display: none !important; +.vjs-pip-container .vjs-pip-text { + position: absolute; + bottom: 10%; + font-size: 2em; + background-color: rgba(0, 0, 0, .7); + padding: .5em; + text-align: center; + width: 100% +} + +.vjs-layout-tiny.vjs-pip-container .vjs-pip-text, +.vjs-layout-x-small.vjs-pip-container .vjs-pip-text, +.vjs-layout-small.vjs-pip-container .vjs-pip-text { + bottom: 0; + font-size: 1.4em; } +// Hide disabled or unsupported controls. +.vjs-hidden { display: none !important; } + .vjs-disabled { opacity: 0.5; cursor: default; @@ -161,21 +190,34 @@ body.vjs-full-window { .vjs-lock-showing { display: block !important; - opacity: 1; - visibility: visible; + opacity: 1 !important; + visibility: visible !important; } // This optional paragraph inside the video tag can provide a message to users -// about what's required to play video when JavaScript is disabled +// about what's required to play video when JavaScript is disabled. + +/* Elements nested in the video tag only display if the video tag itself is + * unsupported, this style appears impossible to reproduce in Chrome. + */ .vjs-no-js { + position: absolute; + z-index: 1; + top: 0; + left: 0; + margin: 0; padding: $controls-margin; padding-right: $controls-margin * 3; - width: 640px; - height: 360px; - @extend .vjs-modal-dialog-content; + width: 100%; + height: 100%; + font-size: $modal-text-size; + font-family: $text-font-family; + line-height: $modal-text-line-height; + color: $primary-foreground-color; + background-color: $primary-background-color; } .vjs-no-js a, .vjs-no-js a:visited { - // Not used for Neue theme + color: $primary-foreground-color; } diff --git a/src/css/components/_live.scss b/src/css/components/_live.scss index 1b97434cd0..0d7fc17262 100644 --- a/src/css/components/_live.scss +++ b/src/css/components/_live.scss @@ -1,15 +1,20 @@ // css for the old live ui, assumes that the progress bar is hidden -// .video-js .vjs-live-control { -// @include display-flex(flex-start); -// @include flex(auto); -// font-size: 1em; -// line-height: 3em; -// } - -.vjs-no-flex .vjs-live-control { - display: table-cell; - width: auto; - text-align: left; +// Neue theme replaces text with a middot +.video-js .vjs-live-control { + @include display-flex(flex-start, center); + @include flex(auto); + @include border-radius(50%); + position: absolute; + bottom: 0; + left: 0; + height: 1.2em; + width: 1.2em; + background-color: $accent-color; + + // Hide "Live" string for Neue + .vjs-live-display { + display: none; + } } // hide the LiveDisplay when not live or when @@ -34,12 +39,6 @@ min-width: 4em; } -.vjs-no-flex .vjs-seek-to-live-control { - display: table-cell; - width: auto; - text-align: left; -} - // hide the SeekToLive button when not live and // when the liveui is not in use .video-js.vjs-live:not(.vjs-liveui) .vjs-seek-to-live-control, @@ -58,42 +57,22 @@ color: #888; } -// make the live circle red when at the live edge -.vjs-seek-to-live-control.vjs-control.vjs-at-live-edge .vjs-icon-placeholder { - color: red; -} - -// AV Neue theme replaces text with a middot -.video-js .vjs-live-control { - @include display-flex(flex-start, center); - @include flex(auto); - @include border-radius(50%); - position: absolute; - bottom: 0; // No current time text field for live - left: 0; - height: 1.4em; - width: 1.4em; - background-color: $accent-color; +.vjs-svg-icons-enabled .vjs-seek-to-live-control { + line-height: 0; } -// AV Neue theme does not show text -.vjs-live-display { - display: none; +.vjs-seek-to-live-control .vjs-svg-icon { + width: 1em; + height: 1em; + pointer-events: none; + fill: #888888; } -/* -.vjs-no-flex .vjs-live-control { - display: table-cell; - width: auto; - text-align: left; +// make the live circle red when at the live edge +.vjs-seek-to-live-control.vjs-control.vjs-at-live-edge .vjs-icon-placeholder { + color: $accent-color; } -// AV Neue theme does not use live display -.video-js .vjs-seek-to-live-control { - display: none; - position: absolute; - bottom: 0; // No current time text field for live - left: 0; +.vjs-seek-to-live-control.vjs-control.vjs-at-live-edge .vjs-svg-icon { + fill: $accent-color; } - -*/ \ No newline at end of file diff --git a/src/css/components/_modal-dialog.scss b/src/css/components/_modal-dialog.scss index 1c70cb9d06..293f68c773 100644 --- a/src/css/components/_modal-dialog.scss +++ b/src/css/components/_modal-dialog.scss @@ -18,9 +18,9 @@ // Reset box-sizing inside the modal dialog // But we don't use the IE fix above for AV Neue theme -.video-js .vjs-modal-dialog > * { - // box-sizing: border-box; -} +// .video-js .vjs-modal-dialog > * { +// box-sizing: border-box; +// } .vjs-modal-dialog .vjs-modal-dialog-content { // see .vjs-modal-dialog-content; diff --git a/src/css/components/_picture-in-picture.scss b/src/css/components/_picture-in-picture.scss index beeff5d455..0bbccc4c04 100644 --- a/src/css/components/_picture-in-picture.scss +++ b/src/css/components/_picture-in-picture.scss @@ -1,6 +1,7 @@ .video-js .vjs-picture-in-picture-control { - span.vjs-icon-placeholder { - cursor: pointer; + cursor: pointer; + @include flex(none); + .vjs-icon-placeholder { display: block; position: relative; // Required for positioning of pseudo content width: 100%; @@ -28,12 +29,15 @@ } } +.video-js.vjs-audio-only-mode .vjs-picture-in-picture-control, +.vjs-pip-window .vjs-picture-in-picture-control { + display: none; +} + // Switch to the exit icon when the player is in Picture-in-Picture -.video-js.vjs-picture-in-picture .vjs-picture-in-picture-control { - span.vjs-icon-placeholder { - @extend .icon-picture-in-picture-exit; - &:before { - @extend .icon-picture-in-picture-exit-highlight; - } +.video-js.vjs-picture-in-picture .vjs-picture-in-picture-control .vjs-icon-placeholder { + @extend .icon-picture-in-picture-exit; + &:before { + @extend .icon-picture-in-picture-exit-highlight; } } diff --git a/src/css/components/_play-pause.scss b/src/css/components/_play-pause.scss index 6855422a6f..922a9c2d0c 100644 --- a/src/css/components/_play-pause.scss +++ b/src/css/components/_play-pause.scss @@ -1,52 +1,54 @@ -@use "sass:math"; - -.video-js .vjs-control-bar .vjs-play-control.vjs-control.vjs-button { +.video-js .vjs-play-control { cursor: pointer; - position: absolute; // Remove from flex model for positioning - left: 50%; - top: 50%; + position: absolute; + inset: 0; + margin: auto; width: $big-play-button--width; height: $big-play-button--height; - margin-top: math.div($big-play-button--height * -1, 2); - margin-left: math.div($big-play-button--width * -1, 2); border-radius: 50%; backdrop-filter: blur(16px); } -.video-js .vjs-play-control { - z-index: 5; // Behind play button when video is not playing +// Collapse control bar to child height for Github ci tests +.video-js.vjs-audio-only-mode .vjs-play-control { + position: relative; + margin: 0; + width: $control-button-height; // This button is square (?) + min-width: unset; + height: $control-button-height; + border-radius: 0; + backdrop-filter: unset; +} + +// Hide play control when paused +.video-js.vjs-paused .vjs-play-control { + display: none; } -.video-js .vjs-play-control.vjs-playing { - z-index: 15; // In front of play button when video is playing - span.vjs-icon-placeholder { +// Show play control when playback starts +.video-js .vjs-play-control.vjs-playing .vjs-icon-placeholder { + display: block; + position: relative; // Required for positioning of pseudo content + width: 100%; + height: 100%; + background-size: contain; + @extend .icon-pause; + &:before { display: block; - position: relative; // Required for positioning of pseudo content - width: 100%; - height: 100%; - background-size: contain; - @extend .icon-pause; + position: absolute; + top: 0; + left: 0; + width: inherit; + height: inherit; + content: ""; + opacity: 0; + @extend .icon-pause-highlight; + @include transition(opacity $icon-unhighlight-time); + } + &:hover { &:before { - display: block; - position: absolute; - top: 0; - left: 0; - width: inherit; - height: inherit; - content: ""; - opacity: 0; - @extend .icon-pause-highlight; - @include transition(opacity $icon-unhighlight-time); - } - &:hover { - &:before { - opacity: 1; - @include transition(opacity $icon-highlight-time); - } + opacity: 1; + @include transition(opacity $icon-highlight-time); } } -} - -.video-js .vjs-play-control.vjs-ended { - z-index: 5; // Behind play button when video is has ended -} +} \ No newline at end of file diff --git a/src/css/components/_progress.scss b/src/css/components/_progress.scss index 0c2188f9f2..8bac51c1b8 100644 --- a/src/css/components/_progress.scss +++ b/src/css/components/_progress.scss @@ -3,49 +3,64 @@ // .vjs-progress-control / ProgressControl // // This is the container for all progress bar-related components/elements. -// Also acts as hover area -// Hide until play starts .video-js .vjs-progress-control { cursor: pointer; @include flex(auto); @include display-flex(center); - visibility: hidden; - position: absolute; - right: $progress-bar-margin; - bottom: 0; - left: $progress-bar-margin; - width: auto; - height: $text-time-size; - // background-color: rgba(255,255,0,0.5); // debug - pointer-events: all; // Make buttons clickable + min-width: 4em; touch-action: none; + visibility: hidden; opacity: 0; - background-color: transparent; + // background-color: rgba(255,255,0,0.5); // debug $transition-property: opacity $icon-highlight-time; @include transition($transition-property); } +.video-js .vjs-progress-control.disabled { + cursor: default; +} + .vjs-live .vjs-progress-control { display: none; } -// Height and position of progress bars -// Also acts as seek scrubber +.vjs-liveui .vjs-progress-control { + @include display-flex(center); +} + +// .vjs-progress-holder / SeekBar +// +// Box containing play and load progress bars. It also acts as seek scrubber. .video-js .vjs-progress-holder { + @include flex(auto); position: relative; - width: 100%; height: $slider-height; - margin: 0; - padding: 0; - cursor: pointer; - outline: 0; @include background-color-with-alpha( $primary-background-color, $primary-background-transparency ); } -// Height and position of drag handle +// .video-js .vjs-progress-control .vjs-progress-holder { + +// // This is one of the rare cases where we are using a pixel dimension. The +// // reason is that the progress holder font-size changes on hover. With the +// // default em-based margins, this means it gets narrower and causes issues +// // with mouseover behaviors/math. +// margin: 0 10px; +// } + +// // This increases the size of the progress holder so there is an increased +// // hit area for clicks/touches. +// .video-js .vjs-progress-control:hover .vjs-progress-holder { +// font-size: 1.666666666666666666em; +// } + +// .video-js .vjs-progress-control:hover .vjs-progress-holder.disabled { +// font-size: 1em; +// } + +// Progress bar and thumb .video-js .vjs-play-progress { height: 100%; background-color: $accent-color; @@ -68,15 +83,7 @@ } } -// Disabled. Not used for Neue theme -.vjs-has-started .vjs-play-progress { - &:before { - // - } -} - // Show progress bar -// Adjust height and position of progress bars and handle on hover .vjs-has-started .vjs-progress-control { visibility: visible; opacity: 1; @@ -99,25 +106,15 @@ } } -// Hide progress bar at end of video for aesthetics +// Hide progress bar at end of video .vjs-has-started.vjs-ended .vjs-progress-control { visibility: hidden; opacity: 0; } -// Buffer -.video-js .vjs-load-progress { - height: 100%; - @include background-color-with-alpha( - $accent-color, - $primary-background-transparency - ); -} - -// Current time tooltip -.video-js .vjs-progress-control:hover .vjs-time-tooltip, -.video-js .vjs-progress-control:hover .vjs-mouse-display:after, -.video-js .vjs-progress-control:hover .vjs-play-progress:after { +// Don't show progress bar tooltips +.video-js .vjs-time-tooltip, +.video-js .vjs-mouse-display { display: none; } @@ -129,148 +126,130 @@ .video-js .vjs-progress-holder .vjs-play-progress, .video-js .vjs-progress-holder .vjs-load-progress, .video-js .vjs-progress-holder .vjs-load-progress div { - display: block; position: absolute; - top: 0; - // Needed for IE6 - left: 0; - // updated by javascript during playback - width: 0; + display: block; height: 100%; margin: 0; padding: 0; + // updated by javascript during playback + width: 0; } -// Graphic under mouse when over progress bar -// Not used for Neue theme -/* -.video-js .vjs-mouse-display { - display: none; - @extend .vjs-icon-circle; - &:before { - display: none; - } -} -*/ -// Current Time "tooltip" -// By default this is hidden and only shown when hovering over the progress control - -// Not used for Neue theme -.video-js .vjs-time-tooltip, -.video-js .vjs-mouse-display:after, -.video-js .vjs-play-progress:after { - display: none; - /* - visibility: hidden; - position: absolute; - top: -2em; - right: -1.5em; - font-size: $text-time-size; - content: attr(data-current-time); - pointer-events: none; - color: $primary-foreground-color; - text-shadow: $text-time-shadow; - */ -} - -.video-js .vjs-time-tooltip, -.video-js .vjs-play-progress:before, -.video-js .vjs-play-progress:after { - //z-index: 1; -} - -.video-js .vjs-progress-control .vjs-keep-tooltips-inside:after { - display: none; -} - -/* - * These child elements of the load progress bar are not used for AV Neue theme - * -// there are child elements of the load progress bar that represent the -// specific time ranges that have been buffered -.video-js .vjs-load-progress div { - background: rgba($secondary-background-color, 0.75); -} -*/ - -// Graphic under mouse when over progress bar -// .vjs-time-tooltip is not used for AV Neue theme - -.video-js .vjs-time-tooltip { - display: none; - /* - display: inline-block; - position: relative; - right: -1.9em; - float: right; - height: 2.4em; - - // The font-size should translate to a consistent 10px for time tooltips in - // all states. This is tricky because the .vjs-progress-holder element - // changes its font-size when the .vjs-progress-control is hovered. - font-size: 1em; - padding: 6px 8px 8px 8px; - pointer-events: none; - position: absolute; - top: -3.4em; - visibility: hidden; - z-index: 1; - */ -} - -.video-js .vjs-progress-holder:focus .vjs-time-tooltip { - display: none; -} +// .video-js .vjs-play-progress { +// background-color: $primary-foreground-color; +// @extend .vjs-icon-circle; -.video-js .vjs-progress-control:hover .vjs-time-tooltip, -.video-js - .vjs-progress-control:hover - .vjs-progress-holder:focus - .vjs-time-tooltip { - display: none; +// // Progress handle +// &:before { +// font-size: 0.9em; +// position: absolute; +// right: -0.5em; +// line-height: .35em; +// z-index: 1; +// } +// } - // Ensure that we maintain a font-size of ~10px. - // font-size: 0.6em; - // visibility: visible; -} - -.video-js .vjs-progress-control.disabled:hover .vjs-time-tooltip { - // font-size: 1em; +// Remove content from play-progress when using SVGs. +.vjs-svg-icons-enabled .vjs-play-progress { + &:before { + content: none !important; + } } -// .vjs-mouse-display / MouseTimeDisplay are not used for AV Neue theme -// -// This element tracks the mouse position along the progress control and -// includes a tooltip, which displays the time at that point in the media. - -.video-js .vjs-progress-control .vjs-mouse-display { - display: none; - /* +.vjs-play-progress .vjs-svg-icon { position: absolute; + top: -0.35em; + right: -0.4em; + width: 0.9em; + height: 0.9em; + pointer-events: none; + line-height: 0.15em; z-index: 1; - width: 1px; - height: 100%; - background-color: #000; - */ } -.video-js .vjs-progress-control:hover .vjs-mouse-display { - display: none; +.video-js .vjs-load-progress { + background: rgba($accent-color, + $primary-background-transparency); } -.video-js.vjs-user-inactive .vjs-progress-control .vjs-mouse-display { - display: none; - /* - visibility: hidden; - opacity: 0; - $trans: visibility 1.0s, opacity 1.0s; - @include transition($trans); - */ +// There are child elements of the load progress bar that represent the +// specific time ranges that have been buffered. +.video-js .vjs-load-progress div { + background: rgba($secondary-background-color, 0.75); } -.vjs-mouse-display .vjs-time-tooltip { - /* - color: #fff; - @include background-color-with-alpha(#000, 0.8); - */ -} +// // .vjs-time-tooltip +// // +// // These elements are displayed above the progress bar. +// // +// // By default, they are hidden and only shown when hovering over the progress +// // control. +// .video-js .vjs-time-tooltip { +// @include background-color-with-alpha(#fff, 0.8); +// @include border-radius(0.3em); +// color: #000; + +// // By floating the tooltips to the right, their right edge becomes aligned +// // with the right edge of their parent element. However, in order to have them +// // centered, they must be pulled further to the right via positioning (e.g. +// // `right: -10px;`. This part is left to JavaScript. +// float: right; +// font-family: $text-font-family; + +// // The font-size should translate to a consistent 10px for time tooltips in +// // all states. This is tricky because the .vjs-progress-holder element +// // changes its font-size when the .vjs-progress-control is hovered. +// font-size: 1em; +// padding: 6px 8px 8px 8px; +// pointer-events: none; +// position: absolute; +// top: -3.4em; +// visibility: hidden; +// z-index: 1; +// } + +// .video-js .vjs-progress-holder:focus .vjs-time-tooltip { +// display: none; +// } + +// .video-js .vjs-progress-control:hover .vjs-time-tooltip, +// .video-js .vjs-progress-control:hover .vjs-progress-holder:focus .vjs-time-tooltip { +// display: block; + +// // Ensure that we maintain a font-size of ~10px. +// font-size: 0.6em; +// visibility: visible; +// } + +// .video-js .vjs-progress-control.disabled:hover .vjs-time-tooltip { +// font-size: 1em; +// } + +// // .vjs-mouse-display / MouseTimeDisplay +// // +// // This element tracks the mouse position along the progress control and +// // includes a tooltip, which displays the time at that point in the media. +// .video-js .vjs-progress-control .vjs-mouse-display { +// display: none; +// position: absolute; +// width: 1px; +// height: 100%; +// background-color: #000; +// z-index: 1; +// } + +// .video-js .vjs-progress-control:hover .vjs-mouse-display { +// display: block; +// } + +// .video-js.vjs-user-inactive .vjs-progress-control .vjs-mouse-display { +// visibility: hidden; +// opacity: 0; +// $trans: visibility 1.0s, opacity 1.0s; +// @include transition($trans); +// } + +// .vjs-mouse-display .vjs-time-tooltip { +// color: #fff; +// @include background-color-with-alpha(#000, 0.8); +// } diff --git a/src/css/components/_slider.scss b/src/css/components/_slider.scss index 332b6ce70b..ef598f4f97 100644 --- a/src/css/components/_slider.scss +++ b/src/css/components/_slider.scss @@ -5,12 +5,15 @@ padding: 0; margin: 0 0.45em 0 0.45em; - // Not used in AV Neue theme // @include background-color-with-alpha($secondary-background-color, $secondary-background-transparency); } -.video-js .vjs-slider:focus { - text-shadow: 0em 0em 1em rgba($primary-foreground-color, 1); +// .video-js .vjs-slider:focus { +// text-shadow: 0em 0em 1em rgba($primary-foreground-color, 1); +// @include box-shadow(0 0 1em $primary-foreground-color); +// } - @include box-shadow(0 0 1em $primary-foreground-color); -} +// Replacement for focus in case spatial navigation is enabled +.video-js.vjs-spatial-navigation-enabled .vjs-slider:focus { + @extend %neue-spatial; +} \ No newline at end of file diff --git a/src/css/components/_subs-caps.scss b/src/css/components/_subs-caps.scss index ea13ebe224..4be5cf1251 100644 --- a/src/css/components/_subs-caps.scss +++ b/src/css/components/_subs-caps.scss @@ -1,79 +1,83 @@ // North America uses 'CC' icon -.video-js:lang(en) .vjs-subs-caps-button, -.video-js:lang(fr-CA) .vjs-subs-caps-button { - span.vjs-icon-placeholder { +.video-js:lang(en) .vjs-subs-caps-button .vjs-icon-placeholder, +.video-js:lang(fr-CA) .vjs-subs-caps-button .vjs-icon-placeholder { + display: block; + position: relative; // Required for positioning of pseudo content + width: 100%; + height: 100%; + background-size: contain; + @extend .icon-closed-captions; + &:before { display: block; - position: relative; // Required for positioning of pseudo content - width: 100%; - height: 100%; - background-size: contain; - @extend .icon-closed-captions; + position: absolute; + top: 0; + left: 0; + width: inherit; + height: inherit; + content: ""; + opacity: 0; + @extend .icon-closed-captions-highlight; + @include transition(opacity $icon-unhighlight-time); + } + &:hover { &:before { - display: block; - position: absolute; - top: 0; - left: 0; - width: inherit; - height: inherit; - content: ""; - opacity: 0; - @extend .icon-closed-captions-highlight; - @include transition(opacity $icon-unhighlight-time); - } - &:hover { - &:before { - opacity: 1; - @include transition(opacity $icon-highlight-time); - } + opacity: 1; + @include transition(opacity $icon-highlight-time); } } } // ROW uses 'subtitles' // Double selector because @extend puts these rules above the captions icon -.video-js .vjs-subs-caps-button, -.video-js.video-js:lang(en-GB) .vjs-subs-caps-button, -.video-js.video-js:lang(en-IE) .vjs-subs-caps-button, -.video-js.video-js:lang(en-AU) .vjs-subs-caps-button, -.video-js.video-js:lang(en-NZ) .vjs-subs-caps-button { - span.vjs-icon-placeholder { +.video-js .vjs-subs-caps-button .vjs-icon-placeholder, +.video-js.video-js:lang(en-GB) .vjs-subs-caps-button .vjs-icon-placeholder, +.video-js.video-js:lang(en-IE) .vjs-subs-caps-button .vjs-icon-placeholder, +.video-js.video-js:lang(en-AU) .vjs-subs-caps-button .vjs-icon-placeholder, +.video-js.video-js:lang(en-NZ) .vjs-subs-caps-button .vjs-icon-placeholder { + display: block; + position: relative; // Required for positioning of pseudo content + width: 100%; + height: 100%; + background-size: contain; + @extend .icon-closed-captions; + &:before { display: block; - position: relative; // Required for positioning of pseudo content - width: 100%; - height: 100%; - background-size: contain; - @extend .icon-closed-captions; + position: absolute; + top: 0; + left: 0; + width: inherit; + height: inherit; + content: ""; + opacity: 0; + @extend .icon-closed-captions-highlight; + @include transition(opacity $icon-unhighlight-time); + } + &:hover { &:before { - display: block; - position: absolute; - top: 0; - left: 0; - width: inherit; - height: inherit; - content: ""; - opacity: 0; - @extend .icon-closed-captions-highlight; - @include transition(opacity $icon-unhighlight-time); - } - &:hover { - &:before { - opacity: 1; - @include transition(opacity $icon-highlight-time); - } + opacity: 1; + @include transition(opacity $icon-highlight-time); } } } -/* - * Not used for AV Neue theme - * -.video-js .vjs-subs-caps-button + .vjs-menu .vjs-captions-menu-item .vjs-menu-item-text .vjs-icon-placeholder { - vertical-align: middle; - display: inline-block; - margin-bottom: -0.1em; -} -*/ +// .vjs-subs-caps-button + .vjs-menu .vjs-captions-menu-item .vjs-svg-icon { +// width: 1.5em; +// height: 1.5em; +// } + +// .video-js .vjs-subs-caps-button + .vjs-menu .vjs-captions-menu-item .vjs-menu-item-text .vjs-icon-placeholder { +// vertical-align: middle; +// display: inline-block; +// margin-bottom: -0.1em; +// } + +// .video-js .vjs-subs-caps-button + .vjs-menu .vjs-captions-menu-item .vjs-menu-item-text .vjs-icon-placeholder:before { +// font-family: VideoJS; +// content: "\f10c"; +// font-size: 1.5em; +// line-height: inherit; +// } -.video-js .vjs-subs-caps-button + .vjs-menu .vjs-captions-menu-item .vjs-menu-item-text:before { - // Not used for AV Neue theme +.video-js.vjs-audio-only-mode .vjs-subs-caps-button { + display: none; } diff --git a/src/css/components/_time.scss b/src/css/components/_time.scss index b6d441a874..1e59be23d7 100644 --- a/src/css/components/_time.scss +++ b/src/css/components/_time.scss @@ -1,45 +1,32 @@ +@use "sass:math"; + .video-js .vjs-time-control { - display: flex; - align-items: center; - position: absolute; - bottom: 0; - width: $text-time-width; - height: 1em; + @include flex(none); font-size: $text-time-size; line-height: 1em; + width: auto; + height: 1em; + display: flex; + align-items: center; text-shadow: $text-time-shadow; } -.vjs-live .vjs-time-control { - display: none; -} - -.video-js .vjs-current-time { - justify-content: flex-start; - left: 0; -} - -.video-js .vjs-duration { - justify-content: flex-end; - right: 0; -} - -// Not used for Neue theme but hidden and centered -.video-js .vjs-remaining-time { +.vjs-live .vjs-time-control, +.vjs-live .vjs-time-divider, +.video-js .vjs-current-time, +.video-js .vjs-duration, +.video-js .vjs-time-divider { display: none; - margin: 0 auto; - background-color: #ff0; // Color for debug purposes } -// Hidden - not used for Neue theme .vjs-time-divider { - visibility: hidden; // Can't use display none on a flex item - // debug colour - // background-color: #00ff00; + // Remove control bar children gap + margin-inline: math.div($control-button-spacing, -2); } -.vjs-live .vjs-time-divider { - // Already the default, but we want to ensure when the player is live - // this hides in the same way as the other time controls for other skins - display: none; +/* Show time controls before playback, + * cf. https://github.com/videojs/video.js/pull/8833 + */ +.vjs-normalise-time-controls:not(.vjs-live) .vjs-time-control { + display: flex; } diff --git a/src/css/components/_volume.scss b/src/css/components/_volume.scss index 92b21af779..f59424dbe6 100644 --- a/src/css/components/_volume.scss +++ b/src/css/components/_volume.scss @@ -1,9 +1,10 @@ @use "sass:math"; .video-js .vjs-mute-control { - span.vjs-icon-placeholder { - cursor: pointer; - @include flex(none); + cursor: pointer; + @include flex(none); + + .vjs-icon-placeholder { display: block; position: relative; // Required for positioning of pseudo content width: 100%; @@ -32,30 +33,23 @@ } } -.video-js .vjs-mute-control.vjs-vol-0, -.video-js .vjs-volume-menu-button.vjs-vol-0 { - span.vjs-icon-placeholder { +.video-js .vjs-mute-control.vjs-vol-0 .vjs-icon-placeholder { + background-size: contain; + @extend .icon-mute; + &:before { background-size: contain; - @extend .icon-mute; - &:before { - background-size: contain; - @extend .icon-mute-highlight; - } + @extend .icon-mute-highlight; } } -.video-js .vjs-mute-control.vjs-vol-1, -.video-js .vjs-volume-menu-button.vjs-vol-1 { - span.vjs-icon-placeholder { - background-size: contain; - @extend .icon-volume; - } + +.video-js .vjs-mute-control.vjs-vol-1 .vjs-icon-placeholder { + background-size: contain; + @extend .icon-volume; } -.video-js .vjs-mute-control.vjs-vol-2, -.video-js .vjs-volume-menu-button.vjs-vol-2 { - span.vjs-icon-placeholder { - background-size: contain; - @extend .icon-volume; - } + +.video-js .vjs-mute-control.vjs-vol-2 .vjs-icon-placeholder { + background-size: contain; + @extend .icon-volume; } .video-js .vjs-volume-control { @@ -63,47 +57,54 @@ @include display-flex; } -.video-js .vjs-volume-panel .vjs-volume-control { - // display: none; // AV Neue 'display: none' is not animatable - opacity: 0; - $transition-property: opacity $icon-fade-out-time; - @include transition($transition-property); -} - -.video-js .vjs-volume-panel .vjs-volume-control.vjs-volume-horizontal { - width: 0; // AV Neue use instead of display: none - $transition-property: width 0ms $icon-fade-out-time; // AV Neue wait for fade out to end +.video-js .vjs-volume-control.vjs-volume-horizontal { + width: 0; + $transition-property: width 0ms $icon-fade-out-time; @include transition($transition-property); } -.video-js .vjs-volume-panel .vjs-volume-control.vjs-volume-vertical { - height: 0; // AV Neue use instead of display: none - $transition-property: width 0ms $icon-fade-out-time; // AV Neue wait for fade out to end +.video-js .vjs-volume-panel .vjs-volume-control { + visibility: visible; + opacity: 0; + $transition-property: opacity $icon-fade-out-time; @include transition($transition-property); } .video-js .vjs-volume-panel { &.vjs-hover .vjs-volume-control, &:active .vjs-volume-control, - &:focus .vjs-volume-control, + &:focus .vjs-volume-control, & .vjs-volume-control:active, - &.vjs-hover .vjs-mute-control ~ .vjs-volume-control, + &.vjs-hover .vjs-mute-control ~ .vjs-volume-control, & .vjs-volume-control.vjs-slider-active { - // AV Neue display volume slider - @include display-flex; + visibility: visible; + @include display-flex; // AV Neue display volume slider opacity: 1; position: relative; $transition-property: opacity $icon-fade-in-time; @include transition($transition-property); - &.vjs-volume-control.vjs-volume-horizontal { + &.vjs-volume-horizontal { width: $volume-menu-width; } - &.vjs-volume-control.vjs-volume-vertical { + &.vjs-volume-vertical { height: $volume-menu-height; } } + + // &.vjs-volume-panel-horizontal { + // &.vjs-hover, + // &:active, + // &.vjs-slider-active { + // width: 10em; + + // @include transition(width 0.1s); + // } + // &.vjs-mute-toggle-only { + // width: 4em; + // } + // } } // AV Neue increase volume slider handle size on hover @@ -118,15 +119,18 @@ } } -// Position Volume Slider Handle for horizontal menus -.video-js .vjs-volume-panel .vjs-volume-control.vjs-volume-horizontal { +// Position Volume Slider Handle for vertical menus +.video-js .vjs-volume-panel .vjs-volume-control.vjs-volume-vertical { + height: 0; + $transition-property: width 0ms $icon-fade-out-time; + @include transition($transition-property); &:hover, &:focus, &:active { .vjs-volume-bar .vjs-volume-level:before { - top: math.div(($slider-height * $slider-handle-height-increase), -2) + - math.div(($slider-height * $slider-height-increase), 2); // bar vertical center - handle radius - right: math.div( + left: math.div(($slider-height * $slider-handle-height-increase), -2) + + math.div(($slider-height * $slider-height-increase), 2); // bar horizontal center - handle radius + top: math.div( ($slider-height * $slider-handle-height-increase), -2 ); // handle radius @@ -134,15 +138,15 @@ } } -// Position Volume Slider Handle for vertical menus -.video-js .vjs-volume-panel .vjs-volume-control.vjs-volume-vertical { +// Position Volume Slider Handle for horizontal menus +.video-js .vjs-volume-panel .vjs-volume-control.vjs-volume-horizontal { &:hover, &:focus, &:active { .vjs-volume-bar .vjs-volume-level:before { - left: math.div(($slider-height * $slider-handle-height-increase), -2) + - math.div(($slider-height * $slider-height-increase), 2); // bar horizontal center - handle radius - top: math.div( + top: math.div(($slider-height * $slider-handle-height-increase), -2) + + math.div(($slider-height * $slider-height-increase), 2); // bar vertical center - handle radius + right: math.div( ($slider-height * $slider-handle-height-increase), -2 ); // handle radius @@ -152,16 +156,13 @@ .video-js .vjs-volume-panel { @include display-flex; - - /* AV Neue force volume controls to be the first item regardless of order in JavaScript instance parameters */ - - order: -1; + order: -1; // Override volume ordering in components margin-right: auto; } -.video-js .vjs-volume-bar { - // Not used for AV Neue theme -} +// .video-js .vjs-volume-bar { +// margin: 1.35em 0.45em; +// } .vjs-volume-bar.vjs-slider-horizontal { width: $volume-menu-width; @@ -204,6 +205,7 @@ .vjs-slider-vertical .vjs-volume-level { width: $slider-height; + // Volume handle &:before { left: ($slider-height * -2) + math.div($slider-height, 2); @@ -211,8 +213,25 @@ @include box-shadow(0 0 4px rgba(0, 0, 0, 0.4)); } } + +// Remove content from volume-level when using SVGs. +.vjs-svg-icons-enabled .vjs-volume-level { + &:before { + content: none; + } +} + +.vjs-volume-level .vjs-svg-icon { + position: absolute; + width: 0.9em; + height: 0.9em; + pointer-events: none; + z-index: 1; +} + .vjs-slider-horizontal .vjs-volume-level { height: $slider-height; + // Volume handle &:before { top: ($slider-height * -2) + math.div($slider-height, 2); @@ -221,13 +240,24 @@ } } -.video-js .vjs-control-bar .vjs-volume-panel.vjs-volume-panel-horizontal { +// here +// Update placement of circle icon when using SVG icons +.vjs-slider-horizontal .vjs-volume-level .vjs-svg-icon { + right: -0.3em; + transform: translateY(-50%); +} +.vjs-slider-vertical .vjs-volume-level .vjs-svg-icon { + top: -0.55em; + transform: translateX(-50%); +} + +.video-js .vjs-volume-panel.vjs-volume-panel-horizontal { flex-direction: row; justify-content: center; height: $control-button-height; } -.video-js .vjs-control-bar .vjs-volume-panel.vjs-volume-panel-vertical { +.video-js .vjs-volume-panel.vjs-volume-panel-vertical { flex-direction: column; justify-content: center; width: $control-button-width; @@ -242,143 +272,86 @@ width: 100%; } -// The volume menu button is like menu buttons (captions/subtitles) but works -// a little differently. It needs to be possible to tab to the volume slider -// without hitting space bar on the menu button. To do this we're not using -// display:none to hide the slider menu by default, and instead setting the -// width and height to zero. -.vjs-menu-button-popup.vjs-volume-menu-button .vjs-menu { - display: block; - width: 0; - height: 0; - border-top-color: transparent; -} - -.vjs-menu-button-popup.vjs-volume-menu-button-vertical .vjs-menu { - top: $control-button-height; - left: 0; -} -.vjs-menu-button-popup.vjs-volume-menu-button-horizontal .vjs-menu { - left: -2rem; -} - -.vjs-menu-button-popup.vjs-volume-menu-button .vjs-menu-content { - // Avoids unnecessary scrollbars in the menu content. Primarily noticed in Chrome on Linux. - overflow-x: hidden; - overflow-y: hidden; - width: 0; - height: 0; -} - -.vjs-volume-menu-button-vertical:hover .vjs-menu-content, -.vjs-volume-menu-button-vertical:focus .vjs-menu-content, -.vjs-volume-menu-button-vertical.vjs-slider-active .vjs-menu-content, -.vjs-volume-menu-button-vertical .vjs-lock-showing .vjs-menu-content { - @include display-flex(flex-end, center); - width: $control-button-width; - height: auto; - background-color: transparent !important; -} - -.vjs-volume-menu-button-horizontal:hover .vjs-menu-content, -.vjs-volume-menu-button-horizontal:focus .vjs-menu-content, -.vjs-volume-menu-button-horizontal .vjs-slider-active .vjs-menu-content, -.vjs-volume-menu-button-horizontal .vjs-lock-showing .vjs-menu-content { - width: auto; - height: $control-button-height; -} - -.vjs-volume-menu-button.vjs-menu-button-inline .vjs-menu-content { - background-color: transparent !important; - // An inline volume should never have a menu background color. - // This protects it from external changes to background colors. - @include display-flex(center, flex-start); -} - -// .vjs-volume-tooltip -// -// These elements are displayed above the volume bar. -// -// By default, they are hidden and only shown when hovering over the volume -// control. -.video-js .vjs-volume-tooltip { - @include background-color-with-alpha(#fff, 0.8); - @include border-radius(0.3em); - color: #000; - float: right; - font-family: $text-font-family; - font-size: 1em; - padding: 6px 8px 8px 8px; - pointer-events: none; - position: absolute; - top: -3.4em; - visibility: hidden; - z-index: 1; -} - -.video-js .vjs-volume-control:hover .vjs-volume-tooltip, -.video-js - .vjs-volume-control:hover - .vjs-progress-holder:focus - .vjs-volume-tooltip { - display: block; - font-size: 1em; - visibility: visible; -} - -.video-js .vjs-volume-vertical:hover .vjs-volume-tooltip, -.video-js - .vjs-volume-vertical:hover - .vjs-progress-holder:focus - .vjs-volume-tooltip { - left: 1em; - top: -12px; -} - -.video-js .vjs-volume-control.disabled:hover .vjs-volume-tooltip { - font-size: 1em; -} - -// .vjs-mouse-display / MouseVolumeLevelDisplay -// -// This element tracks the mouse position along the volume control and -// includes a tooltip, which displays the volume level. -.video-js .vjs-volume-control .vjs-mouse-display { - display: none; - position: absolute; - width: 100%; - height: 1px; - background-color: #000; - z-index: 1; -} - -.video-js .vjs-volume-horizontal .vjs-mouse-display { - width: 1px; - height: 100%; -} - -.vjs-no-flex .vjs-volume-control .vjs-mouse-display { - z-index: 0; -} - -.video-js .vjs-volume-control:hover .vjs-mouse-display { - display: block; -} - -.video-js.vjs-user-inactive .vjs-volume-control .vjs-mouse-display { - visibility: hidden; - opacity: 0; - $trans: - visibility 1s, - opacity 1s; - @include transition($trans); -} - -.video-js.vjs-user-inactive.vjs-no-flex .vjs-volume-control .vjs-mouse-display { - display: none; -} - -.vjs-mouse-display .vjs-volume-tooltip { - color: #fff; - @include background-color-with-alpha(#000, 0.8); -} +// .video-js .vjs-volume-vertical { +// width: 3em; +// height: 8em; +// bottom: 8em; + +// @include background-color-with-alpha($primary-background-color, $primary-background-transparency); +// } + +// .video-js .vjs-volume-horizontal .vjs-menu { +// left: -2em; +// } + +// // .vjs-volume-tooltip +// // +// // These elements are displayed above the volume bar. +// // +// // By default, they are hidden and only shown when hovering over the volume +// // control. +// .video-js .vjs-volume-tooltip { +// @include background-color-with-alpha(#fff, 0.8); +// @include border-radius(0.3em); +// color: #000; +// float: right; +// font-family: $text-font-family; +// font-size: 1em; +// padding: 6px 8px 8px 8px; +// pointer-events: none; +// position: absolute; +// top: -3.4em; +// visibility: hidden; +// z-index: 1; +// } + +// .video-js .vjs-volume-control:hover .vjs-volume-tooltip, +// .video-js .vjs-volume-control:hover .vjs-progress-holder:focus .vjs-volume-tooltip { +// display: block; +// font-size: 1em; +// visibility: visible; +// } + +// .video-js .vjs-volume-vertical:hover .vjs-volume-tooltip, +// .video-js .vjs-volume-vertical:hover .vjs-progress-holder:focus .vjs-volume-tooltip { +// left: 1em; +// top: -12px; +// } + +// .video-js .vjs-volume-control.disabled:hover .vjs-volume-tooltip { +// font-size: 1em; +// } + +// // .vjs-mouse-display / MouseVolumeLevelDisplay +// // +// // This element tracks the mouse position along the volume control and +// // includes a tooltip, which displays the volume level. +// .video-js .vjs-volume-control .vjs-mouse-display { +// display: none; +// position: absolute; +// width: 100%; +// height: 1px; +// background-color: #000; +// z-index: 1; +// } + +// .video-js .vjs-volume-horizontal .vjs-mouse-display { +// width: 1px; +// height: 100%; +// } + +// .video-js .vjs-volume-control:hover .vjs-mouse-display { +// display: block; +// } + +// .video-js.vjs-user-inactive .vjs-volume-control .vjs-mouse-display { +// visibility: hidden; +// opacity: 0; +// $trans: visibility 1.0s, opacity 1.0s; +// @include transition($trans); +// } + +// .vjs-mouse-display .vjs-volume-tooltip { +// color: #fff; +// @include background-color-with-alpha(#000, 0.8); +// } diff --git a/src/css/components/menu/_menu-inline.scss b/src/css/components/menu/_menu-inline.scss index 82e6af09d1..2858953310 100644 --- a/src/css/components/menu/_menu-inline.scss +++ b/src/css/components/menu/_menu-inline.scss @@ -3,21 +3,20 @@ overflow: hidden; } -// Not used for AV Neue theme. -.video-js .vjs-menu-button-inline:before { - // Icon pseudoelement has a different base font size (1.8em), so we need to - // account for that in the width. 4em (standard button width) divided by 1.8 - // to get the same button width as normal. - // width: 2.222222222em; -} - -// Hover state -.video-js .vjs-menu-button-inline:hover, -.video-js .vjs-menu-button-inline:focus, -.video-js .vjs-menu-button-inline.vjs-slider-active { - // This width is currently specific to the inline volume bar. - // width: 12em; -} +// .video-js .vjs-menu-button-inline:before { +// // Icon pseudoelement has a different base font size (1.8em), so we need to +// // account for that in the width. 4em (standard button width) divided by 1.8 +// // to get the same button width as normal. +// width: 2.222222222em; +// } + +// // Hover state +// .video-js .vjs-menu-button-inline:hover, +// .video-js .vjs-menu-button-inline:focus, +// .video-js .vjs-menu-button-inline.vjs-slider-active { +// // This width is currently specific to the inline volume bar. +// width: 12em; +// } .vjs-menu-button-inline .vjs-menu { opacity: 0;