diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /toolkit/themes/shared/pictureinpicture | |
parent | Initial commit. (diff) | |
download | firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'toolkit/themes/shared/pictureinpicture')
-rw-r--r-- | toolkit/themes/shared/pictureinpicture/player.css | 648 | ||||
-rw-r--r-- | toolkit/themes/shared/pictureinpicture/texttracks.css | 74 |
2 files changed, 722 insertions, 0 deletions
diff --git a/toolkit/themes/shared/pictureinpicture/player.css b/toolkit/themes/shared/pictureinpicture/player.css new file mode 100644 index 0000000000..a2687f3771 --- /dev/null +++ b/toolkit/themes/shared/pictureinpicture/player.css @@ -0,0 +1,648 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +:root { + --player-bg-color: #000; + --player-control-icon-fill: #fff; + --player-control-item-half-width: clamp(calc(16px / 2), calc(10vmax / 2), calc(32px / 2)); + --player-control-item-height: clamp(16px, 10vmax, 32px); + --close-btn-fill-color: #000; + --controls-bottom-distance: 15px; + --controls-bottom-upper-height: 30px; + --scrubber-vertical-margin: 7px; + --resize-margin: 5px; + + background-color: var(--player-bg-color); + overflow: hidden; +} + +button::-moz-focus-inner { + border: 0; +} + +body { + margin: 0; +} + +body:fullscreen { + -moz-window-dragging: no-drag; +} + +.player-holder { + display: flex; + flex-direction: column; + height: 100vh; + overflow: hidden; +} + +browser { + flex: 1; +} + +#controls { + height: calc(100% - 2 * var(--resize-margin)); + left: 0; + position: absolute; + top: 0; + width: calc(100% - 2 * var(--resize-margin)); + margin: var(--resize-margin); + -moz-window-dragging: drag; +} + +#controls button { + appearance: none; + border: 0; + z-index: 1; +} + +#controls button:focus-visible, +#controls input:focus-visible, +.switch > input:focus-visible + .slider { + outline: 3px solid #0060DF; + box-shadow: 1px 2px 5px #000; +} + +/* Styling for background gradient. + * Opacity changes are handled separately under .control-item. + */ +#controls-bottom-gradient { + background: linear-gradient(0deg, #000000 -13.24%, rgba(0, 0, 0, 0) 90.44%); + position: absolute; + height: calc(var(--controls-bottom-distance) + 2 * var(--resize-margin) + var(--player-control-item-height) + var(--controls-bottom-upper-height) + var(--scrubber-vertical-margin)); + bottom: 0; + width: 100vw; + margin: 0 calc(-1 * var(--resize-margin)) calc(-1 * var(--resize-margin)) calc(-1 * var(--resize-margin)); + pointer-events: none; + -moz-window-dragging: drag; +} + +#controls-bottom { + position: absolute; + bottom: var(--controls-bottom-distance); + width: 100%; +} + +.controls-bottom-lower { + display: grid; + grid-template-columns: repeat(3, 1fr); + margin: 0 24px; +} + +.start-controls { + display: grid; + justify-self: start; +} + +.center-controls { + display: grid; + grid-template-columns: repeat(3, 1fr); + grid-template-areas: "seekbackward playpause seekforward"; + justify-self: center; + gap: 8px; +} + +.end-controls { + display: grid; + grid-template-columns: repeat(3, 1fr); + grid-template-areas: "audio closedcaption fullscreen"; + justify-self: end; + gap: 8px; +} + +.control-item { + -moz-window-dragging: no-drag; + transition: opacity 160ms linear, fill-opacity 160ms linear; + opacity: 0; + cursor: pointer; +} + +.control-button { + background-color: transparent; + border-radius: 4px; + /** + * Make the button dimensions a square proportional to one + * dimension of the window - in this case, the width dimension, + * since we suspect most videos are wider than they are tall. + */ + height: var(--player-control-item-height); + width: 10vmax; + max-width: 32px; + min-width: 16px; + -moz-context-properties: fill, fill-opacity; + fill: var(--player-control-icon-fill); + background-position: center; + background-size: 60%; + background-repeat: no-repeat; +} + +.control-button:hover:enabled { + background-color: rgba(255, 255, 255, .25); +} + +#controls:is([keying], [showing]) .control-button:disabled, +/* Only change opacity on hover events for non-fullscreen mode. + * Fullscreen mode uses the `showing` attribute instead. */ +body:not(:fullscreen) #controls:hover .control-button:disabled { + /* Set `fill-opacity` to the desired opacity in addition to full `opacity` + * to allow having the button's tooltip in full opacity even if the button is disabled. */ + fill-opacity: 0.4; + opacity: 1 !important; +} + +.control-item:focus-visible::after, +.control-item:hover::after { + content: attr(tooltip); + display: inline-block; + width: max-content; + position: relative; + padding: .4em .5em; + background: #000000; + color: #ffffff; + border-radius: 4px; + pointer-events: none; +} + +/* Since #controls is set to LTR, button tooltips would normally appear + * as LTR also for RTL locales. To fix this, set the .control-item's ::after + * to RTL based on the root directionality. + * Because of that, don't set logical properties for the next set of rules. */ +:root:dir(rtl) .control-item::after { + direction: rtl; +} + +/* Set the tooltip position for different playback controls */ + +.tooltip-under-controls:focus-visible::after, +.tooltip-under-controls:hover::after { + bottom: -3em; +} + +#close:focus-visible::after, +#close:hover::after, +#unpip[mac="true"]:focus-visible::after, +#unpip[mac="true"]:hover::after { + float: right; + transform: translateX(1em); +} + +#unpip:focus-visible::after, +#unpip:hover::after, +#close[mac="true"]:focus-visible::after, +#close[mac="true"]:hover::after { + float: left; + transform: translateX(-1em); +} + +.tooltip-over-controls:focus-visible::after, +.tooltip-over-controls:hover::after { + bottom: 3em; +} + +.inline-end-tooltip:focus-visible::after, +.inline-end-tooltip:hover::after { + float: right; + right: -1em; +} + +.inline-start-tooltip:focus-visible::after, +.inline-start-tooltip:hover::after { + float: left; + left: -1em; +} + +.center-tooltip:focus-visible::after, +.center-tooltip:hover::after { + right: 0.8em; + translate: calc(-50% + var(--player-control-item-half-width)); +} + +/* Since the unpip button icon is reversed for RTL locales, + * re-position the tooltip so that the tooltip remains in the original placement */ +:root:dir(rtl) #unpip:focus-visible::after, +:root:dir(rtl) #unpip:hover::after { + float: right; +} + +:root:dir(rtl) #unpip[mac="true"]:focus-visible::after, +:root:dir(rtl) #unpip[mac="true"]:hover::after { + float: left; +} + +/* Since the unpip icon is reversed for RTL locales, + * flip its tooltip back */ +:root:dir(rtl) #unpip:focus-visible::after, +:root:dir(rtl) #unpip:hover::after { + scale: -1 1; +} + +/* Set opacity for buttons and scrubber when controls are visible on the pip window and are not hovered over. + * For fullscreen mode, only apply opacity if there is a showing attribute. */ +body:not(:fullscreen) #controls:hover .control-item:not(:hover), +body:fullscreen #controls[showing]:hover .control-item:not(:hover), +#controls[donthide] .control-item { + opacity: 0.8; +} + +#controls[keying] .control-item, +#controls[showing] .control-item, +#controls:hover .control-item:hover { + opacity: 1; +} + +/* Background gradient is the only control item with a fixed opacity value. */ +#controls[keying] .control-item#controls-bottom-gradient, +#controls[showing] .control-item#controls-bottom-gradient, +#controls:hover .control-item#controls-bottom-gradient:hover +#controls[donthide] .control-item#controls-bottom-gradient { + opacity: 0.8; +} + +/* For readability, timestamp should maintain full opacity when visible */ +body:not(:fullscreen) #controls:hover #timestamp, +body:fullscreen #controls[showing]:hover { + opacity: 1; +} + +#close, +#unpip { + background-color: rgba(255, 255, 255, .8); + position: absolute; + fill: var(--close-btn-fill-color); +} + +#close:is(:hover, :focus-visible), +#unpip:is(:hover, :focus-visible) { + background-color: rgba(255, 255, 255, .9); +} + +#close { + background-image: url("chrome://global/skin/icons/close.svg"); + right: 10px; + top: 10px; +} + +#close[mac="true"] { + right: auto; + left: 10px; +} + +#unpip { + background-image: url("chrome://global/skin/media/picture-in-picture-closed.svg"); + left: 10px; + top: 10px; +} + +#unpip[mac="true"] { + right: 10px; + left: auto; +} + +#playpause { + grid-area: playpause; +} + +#audio { + grid-area: audio; +} + +#fullscreen { + grid-area: fullscreen; +} + +#controls.playing #playpause { + background-image: url("chrome://global/skin/media/pause-fill.svg"); +} + +#controls:not(.playing) #playpause { + background-image: url("chrome://global/skin/media/play-fill.svg"); +} + +#controls.muted #audio { + background-image: url("chrome://global/skin/media/audio-muted.svg"); +} + +#controls:not(.muted) #audio { + background-image: url("chrome://global/skin/media/audio.svg"); +} + +body:fullscreen #fullscreen { + background-image: url("chrome://global/skin/media/picture-in-picture-exit-fullscreen-button.svg"); + background-size: auto; +} + +body:not(:fullscreen) #fullscreen { + background-image: url("chrome://global/skin/media/picture-in-picture-enter-fullscreen-button.svg"); + background-size: auto; +} + +#seekBackward { + background-image: url("chrome://global/skin/media/picture-in-picture-seekBackward-button.svg"); + background-size: auto; + grid-area: seekbackward; +} + +#seekForward { + background-image: url("chrome://global/skin/media/picture-in-picture-seekForward-button.svg"); + background-size: auto; + grid-area: seekforward; +} + +:root:dir(rtl) #unpip { + transform: scaleX(-1); +} + +#closed-caption { + background-image: url("chrome://global/skin/media/closed-caption-settings-button.svg"); + color: white; + grid-area: closedcaption; +} + +.box { + -moz-window-dragging: no-drag; + background-color: #2B2A33; + text-align: start; + font-size: 1em; + width: 186px; + padding: 0 8px; + margin: 0; + border-radius: 8px; +} + +:root:dir(rtl) .box { + direction: rtl; +} + +.a11y-only { + visibility: hidden; + position: absolute; +} + +.hide { + display: none; +} + +.bold { + font-weight: 590; +} + +.box > input[type="radio"]{ + background-color: red; + fill: currentColor; +} + +.box label:not(.switch) { + color: white; + font-family: sans-serif; +} + +#subtitles-toggle-label { + width: fit-content; + padding: 8px; +} + +.panel { + position: absolute; + bottom: 40px; + user-select: none; + right: 24px; +} + +.panel-fieldset { + border: none; + margin-top: 8px; + padding-inline-start: 0; +} + +.panel-legend { + font-family: sans-serif; + color: white; + margin-top: 8px; + padding-inline-start: 0; +} + +.arrow { + border: 10px solid transparent; + border-top-color: #2B2A33; + width: 0; + height: 0; + inset-inline-start: 136px; + position: relative; +} + +.grey-line { + width: 100%; + height: 1px; + background: #8F8F9D; +} + +.font-size-selection { + margin-inline-start: 8px; + padding-inline-start: 8px; +} + +.font-size-selection-radio { + display: flex; + width: fit-content; + cursor: pointer; + padding-block: 8px; +} + +.font-size-selection-radio label { + cursor: pointer; +} + +.font-size-selection-radio > input[type="radio"] { + appearance: none; + width: 16px; + height: 16px; + border: 1px solid #8f8f9d; + border-radius: 50%; + margin: 0; + margin-inline-end: 6px; +} + +.font-size-selection-radio > input[type="radio"]:checked { + border: 4px solid #00ddff; +} + +.subtitle-grid { + display: grid; + grid-template-rows: auto; + grid-template-columns: auto 46px; + padding: 8px; +} + +.switch { + position: relative; + display: inline-block; + width: 32px; + height: 16px; + grid-column: 2; + margin: 8px; + cursor: pointer; +} + +.switch input { + opacity: 0; + width: 0; + height: 0; +} + +.slider { + position: absolute; + inset: 0; + transition: transform 250ms; + border-radius: 13px; + background-color: #55545f; +} + +.slider::before { + position: absolute; + content: ''; + height: 12px; + width: 12px; + inset-inline-start: 2px; + bottom: 2px; + background-color: #2B2A33; + transition: transform 250ms; + border-radius: 50%; +} + +input:checked + .slider { + background-color: #00ddff; +} + +input:checked + .slider::before { + transform: translateX(16px); +} + +:root:dir(rtl) input:checked + .slider::before { + transform: translateX(-16px); +} + +.font-size-overlay { + opacity: 0.4; + pointer-events: none; +} + +.controls-bottom-upper { + width: calc(100% - 38px); + height: var(--controls-bottom-upper-height); + margin: 0 19px; + display: grid; +} + +.scrubber-no-drag { + -moz-window-dragging: no-drag; + height: 16px; + margin: var(--scrubber-vertical-margin) 0; + display: grid; + justify-items: center; + align-items: center; + width: 100%; +} + +#scrubber { + width: 100%; + background-color: transparent; + padding: 6px; +} + +#scrubber::-moz-range-thumb { + border-radius: 14px; + background-color: #BFBFC9; + position: relative; + width: 8px; + height: 8px; + border: 3px solid #FFFFFF; + bottom: 24px; + padding: 0; +} + +#scrubber::-moz-range-track { + background-color: #969696; +} + +#scrubber::-moz-range-progress { + background-color: #FFFFFF; +} + +#scrubber, +#scrubber::-moz-range-track, +#scrubber::-moz-range-progress { + height: 4px; + border-radius: 10px; +} + +#timestamp { + align-self: center; + color: #FFFFFF; + cursor: default; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Ubuntu", "Helvetica Neue", sans-serif; + font-size: 0.9em; + user-select: none; + width: 16ch; + grid-area: timestamp; +} + +#timestamp::after { + background: unset; + content: unset; +} + +@media (height <= 325px), (width <= 475px) { + #closed-caption { + display: none; + } + + .end-controls { + grid-template-columns: repeat(2, 1fr); + grid-template-areas: "audio fullscreen"; + } +} + +@media (width <= 440px) { + #timestamp { + display: none; + } +} + +@media (width <= 350px) { + #fullscreen { + display: none; + } + + .end-controls { + grid-template-columns: repeat(1, 1fr); + grid-template-areas: "audio"; + } +} + +@media (height <= 200px) { + .scrubber-no-drag { + display: none; + } +} + +@media (width <= 300px) { + .scrubber-no-drag, + #seekForward, + #seekBackward, + .start-controls { + display: none; + } + + .controls-bottom-lower { + grid-template-columns: repeat(2, 1fr); + } + + .center-controls { + grid-template-columns: repeat(1, 1fr); + grid-template-areas: "playpause"; + } + + .end-controls { + justify-self: center; + } +} diff --git a/toolkit/themes/shared/pictureinpicture/texttracks.css b/toolkit/themes/shared/pictureinpicture/texttracks.css new file mode 100644 index 0000000000..ec7af4a7b4 --- /dev/null +++ b/toolkit/themes/shared/pictureinpicture/texttracks.css @@ -0,0 +1,74 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +:root { + --min-font-size: 14px; + --max-font-size: 40px; + --font-scale: 0.06; + --texttracks-bottom: calc(var(--font-scale) * 100vh); + + /* + * Move text tracks if they visually overlap with pip player controls + * New text tracks position is determined by adding together: + * 1) bottom distance of #controls + * 2) height of #controls-bottom, + * 3) border size of player controls buttons + * 4) hardcoded px value (to ensure consistent distance, regardless of pip window size) + * NOTE: if changing player.css values, change values here too. + */ + --resize-margin: 5px; + --player-controls-height: calc(100vh - 2 * var(--resize-margin)); + --player-controls-bottom-distance: calc(100vh - var(--player-controls-height)); + --player-controls-button-height: 10vmax; + --player-controls-button-max-height: 32px; + --player-controls-button-min-height: 16px; + --player-controls-button-outline-width: 2px; + --player-controls-scrubber-height: 0px; + --player-bottom-controls-height: calc(var(--player-controls-scrubber-height) + clamp(var(--player-controls-button-min-height), var(--player-controls-button-height), var(--player-controls-button-max-height))); + --distance-from-player-controls: 20px; + --texttracks-bottom-overlapped: calc(var(--player-controls-button-outline-width) + var(--player-controls-bottom-distance) + var(--player-bottom-controls-height) + var(--distance-from-player-controls)); +} + +#texttracks { + background-color: black; + opacity: 80%; + position: absolute; + text-align: center; + box-sizing: border-box; + color: white; + margin: 0; + display: block; + left: 50%; + transform: translateX(-50%); + padding: 8px; + max-width: calc(0.88 * 100vw); + bottom: var(--texttracks-bottom); + font-size: clamp(var(--min-font-size), calc(var(--font-scale) * 100vh), var(--max-font-size)); + line-height: clamp(14.4px, calc(var(--font-scale) * 1.2 * 100vh), 48px); + white-space: pre-line; + width: max-content; + font-family: sans-serif; + transition: bottom 0.3s; + transition-delay: 0.1s; +} + +#texttracks[overlap-video-controls] { + bottom: var(--texttracks-bottom-overlapped) +} + +#texttracks:empty { + visibility: hidden; +} + +@media (prefers-reduced-motion) { + #texttracks { + transition: none; + } +} + +@media screen and (max-width: 319px) { + #texttracks { + display: none; + } +} |