Skip to content

Commit

Permalink
Merge pull request #7 from flowplayer/chore/PLAY-601/components
Browse files Browse the repository at this point in the history
chore(PLAY-601): accessibility enhancements
  • Loading branch information
alexarassat authored Sep 25, 2024
2 parents 4bd864a + a7971cd commit eda40af
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 87 deletions.
4 changes: 2 additions & 2 deletions packages/live-ui/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,12 +127,12 @@ export default class LiveUiMiddle extends HTMLElement{
const start = document.createElement("button")
start.classList.add("fp-live-start")
start.textContent = player.i18n("core.watch_beginning", "Watch from beginning")
this.setAttribute("aria-label", player.i18n("core.watch_live_start", "Watch from beginning"))
start.setAttribute("aria-label", player.i18n("core.watch_live_start", "Watch from beginning"))

const live = document.createElement("button")
live.classList.add("fp-live-edge")
live.textContent = player.i18n("core.watch_live", "Watch live")
this.setAttribute("aria-label", player.i18n("core.watch_live", "Watch live"))
live.setAttribute("aria-label", player.i18n("core.watch_live", "Watch live"))

;[start, live].forEach((button)=> {
button.onclick = (e) => {
Expand Down
26 changes: 14 additions & 12 deletions packages/vertical-volume-bar/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,24 @@
position: relative;
}

.fp-volume-control-vertical .fp-volume-vertical {
.fp-volume-control-vertical .fp-volume-wrapper {
position: absolute;
cursor: pointer;
opacity: 0;
padding: 0.5em;
left: -0.4em;
bottom: 1.3em;
display: flex;
visibility: hidden;
bottom: 1em;
height: 10em;
left: -0.8em;
justify-content: center;
align-items: center;
flex-direction: column;
z-index: 1;
}

.fp-volume-control-vertical .fp-volume-vertical:focus {
opacity: 1;
.fp-volume-control-vertical .fp-volume-vertical {
flex: 1;
margin-bottom: 1em;
padding: 0 1em;
}

.fp-volume-control-vertical .fp-volume-container {
Expand All @@ -29,7 +35,7 @@
}

.fp-volume-control-vertical .fp-dragger {
left: -0.29em;
left: -0.24em;
}

.fp-volume-control-vertical .fp-volume-mute-unmute {
Expand All @@ -39,7 +45,3 @@
.fp-volume-control-vertical .fp-volume-mute-unmute:after {
padding-bottom: 0.7em;
}

.fp-volume-control-vertical .fp-volume-mute-unmute:focus + .fp-volume-vertical {
opacity: 1;
}
156 changes: 83 additions & 73 deletions packages/vertical-volume-bar/index.ts
Original file line number Diff line number Diff line change
@@ -1,85 +1,95 @@
import { install } from "../../shared/install"
import { type Player } from "@flowplayer/player"
import {install} from "../../shared/install"
import {type Player} from "@flowplayer/player"
import "./index.css"
import {CLICK, VOLUME_CHANGE} from "@flowplayer/player/core/events"
import support from "../utils"
import { SliderStates, makeSlider } from "./slider"
import {SliderStates, makeSlider} from "./slider"


export default class VerticalVolume extends HTMLElement {

constructor(player: Player) {
super()
this.classList.add("fp-volume-control-vertical")

const volume_icon = player.createComponents(flowplayer.defaultElements.VOLUME_ICON)[0]
volume_icon.addEventListener(CLICK, _ => player.toggleMute())
this.append(volume_icon)

if (support().ios || support().android) return

const volumeBar = this.createVolumeBar(player)
makeSlider(volumeBar, {onseek: this.onVolumeBarSeek.bind(this, player)})
this.append(volumeBar)

player.on(VOLUME_CHANGE, () => {
const muted = (player.volume == 0) || player.muted
if (muted) this.adjustVolumeSlider(player, 0, volumeBar)

const ui_opt = player.opt("ui")
if (!this.classList.contains(SliderStates.GRABBING) && !(muted && typeof ui_opt === "number" && (4 & ui_opt) > 0)) {
constructor(player: Player) {
super()
this.classList.add("fp-volume-control-vertical")

const volume_icon = player.createComponents(flowplayer.defaultElements.VOLUME_ICON)[0]
volume_icon.addEventListener(CLICK, _ => player.toggleMute())
this.append(volume_icon)

if (support().ios || support().android) return

const volumeBar = this.createVolumeBar(player)
this.append(volumeBar)

volume_icon.addEventListener("pointerenter", _ => volumeBar.style.visibility = "visible")
this.addEventListener("pointerleave", _ => volumeBar.style.visibility = "hidden")
this.addEventListener("focusin", ()=> volumeBar.style.visibility = "visible")
this.addEventListener("focusout", ()=> {
setTimeout(()=> {
if (document.activeElement !== volumeBar) volumeBar.style.visibility = "hidden"
}, 0)
})
}

createVolumeBar(player: Player) {
const volumeWrapper = document.createElement("div")
volumeWrapper.classList.add("fp-volume-wrapper")
volumeWrapper.setAttribute("tabindex", "0")
volumeWrapper.setAttribute("role", "slider")
volumeWrapper.setAttribute("aria-valuemin", "0")
volumeWrapper.setAttribute("aria-valuemax", "1")
volumeWrapper.setAttribute("aria-label", player.i18n("core.volume", "volume"))
player.on(VOLUME_CHANGE, this.onVolumeChange.bind(this, player, volumeWrapper))

const volumeBar = document.createElement("div")
volumeBar.setAttribute("aria-hidden", "true")
volumeBar.classList.add("fp-volume-vertical")
makeSlider(volumeBar, {onseek: this.onVolumeBarSeek.bind(this, player)})

const container = document.createElement("div")
container.classList.add("fp-volume-container")

const volume = document.createElement("div")
volume.classList.add("fp-volume-progress", "fp-color", "use-drag-handle")

const dragger = document.createElement("div")
dragger.classList.add("fp-dragger", "fp-color")

volume.append(dragger)
volumeBar.append(container)
container.append(volume)
volumeWrapper.append(volumeBar)

return volumeWrapper
}

onVolumeBarSeek(player: Player, volumeBar: HTMLElement, amount: number) {
player._storage.setItem("volume", (player.volume = amount / 100).toString())
this.adjustVolumeSlider(player, player.volume, volumeBar)
}
})

volume_icon.addEventListener("pointerenter", _ => volumeBar.style.opacity = "1")
this.addEventListener("pointerleave", _ => volumeBar.style.opacity = "0")
}

createVolumeBar(player: Player) {
const volumeBar = document.createElement("div")
volumeBar.classList.add("fp-volume-vertical")
volumeBar.setAttribute("tabindex", "0")
volumeBar.setAttribute("role", "slider")
volumeBar.setAttribute("aria-valuemin", "0")
volumeBar.setAttribute("aria-valuemax", "1")
volumeBar.setAttribute("aria-label", player.i18n("core.volume", "volume"))

const container = document.createElement("div")
container.setAttribute("aria-hidden", "true")
container.classList.add("fp-volume-container")

const volume = document.createElement("div")
volume.classList.add("fp-volume-progress", "fp-color", "use-drag-handle")

const dragger = document.createElement("div")
dragger.classList.add("fp-dragger", "fp-color")


volume.append(dragger)
volumeBar.append(container)
container.append(volume)

return volumeBar
}

onVolumeBarSeek(player: Player, volumeBar: HTMLElement, amount: number) {
player._storage.setItem("volume", (player.volume = amount / 100).toString())
this.adjustVolumeSlider(player, player.volume, volumeBar)

if (amount < 0) return
player.muted = false
player._storage.removeItem("mute")
}

adjustVolumeSlider(player: Player, amount: number, volume_bar: HTMLElement) {
volume_bar.setAttribute("aria-valuenow", amount.toString())
volume_bar.setAttribute("aria-valuetext", Math.round(amount * 100) + "%")

const progress = this.querySelector(".fp-volume-progress") as HTMLDivElement
if(!progress) return
progress.style.height = player.muted ? "0" : Math.round(amount * 100) + "%"
}
if (amount < 0) return
player.muted = false
player._storage.removeItem("mute")
}

adjustVolumeSlider(player: Player, amount: number, volume_bar: HTMLElement) {
volume_bar.setAttribute("aria-valuenow", amount.toString())
volume_bar.setAttribute("aria-valuetext", Math.round(amount * 100) + "%")

const progress = this.querySelector(".fp-volume-progress") as HTMLDivElement
if (!progress) return
progress.style.height = player.muted ? "0" : Math.round(amount * 100) + "%"
}

onVolumeChange(player: Player, volumeBar: HTMLElement) {
const muted = player.volume == 0 || player.muted
if (muted) this.adjustVolumeSlider(player, 0, volumeBar)

const ui_opt = player.opt("ui")
if (!this.classList.contains(SliderStates.GRABBING) && !(muted && typeof ui_opt === "number" && (4 & ui_opt) > 0)) {
this.adjustVolumeSlider(player, player.volume, volumeBar)
}
}
}

install("flowplayer-volume-control", "vertical-volume-bar", VerticalVolume)

0 comments on commit eda40af

Please sign in to comment.