-
Notifications
You must be signed in to change notification settings - Fork 7.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: add skip forward/backward buttons #8147
feat: add skip forward/backward buttons #8147
Conversation
Codecov Report
@@ Coverage Diff @@
## main #8147 +/- ##
==========================================
+ Coverage 82.02% 82.14% +0.11%
==========================================
Files 110 112 +2
Lines 7344 7391 +47
Branches 1773 1782 +9
==========================================
+ Hits 6024 6071 +47
Misses 1320 1320
📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more |
The numbers on the icons are pretty illegible at the default size of the controls. That may well be flagged in an acessiblity audit. |
Do you know if there's a good way to fix that? |
I think it needs to be different icons that are readble at that size, or plain arrows. The control text could (and for accessibility probably should) state the increment to be skipped by. |
The icons used here are from the standard Material Design set. Unless we jerry-rig a solution with existing videojs font icons, we'd need to decide on brand new ones and then update the font repo with them to then be used here, which seems outside the scope of the changes described. @mister-ben The empty round arrow icon is already used for replay UI and plain arrows are not descriptive of the intended action here. Are there any other icons from the Material Design or Font Awesome collections that you would recommend for legibility? |
I've seen the rewind / fast forward icons used for this in OTT apps, but they are also problematic as they can be understood as changing the playback rate. Some also use a similar looped arrow with a double arrowhead, but there's no such icon in Material Icons or Font Awesome. Netflix is like this. (They also show numbers, but have the icons large enough for this to work.) Here I used rotated arrows to distinguish them from replay. Maybe showing the number, larger, when the button has focus could work? If we really want numbers they need to be readable, I might try tweaking the SVG icons. It might be easier if we could consider using "restart alt" from Material icons for replay with a fuller, broken loop. |
Here's one idea, modifying Material Icons's SVG |
That looks great - thank you for the suggestion! Is it ok if I use that? |
Love that icon idea. @usmanonazim Are you comfy with modifying SVGs? You have the tools to do so? |
Thinking about it, the icon could just be that partial arrow, and the number can be text. That's a lot less SVG work, we don't have to impose the increments that can be used, and the number can be localised for languages that don't use "arabic numerals", like actual arabic numbers. |
Just to clarify, do you mean that the icon used would just be the partial arrow, and then the control text would specify the number, or that the number would go underneath the arrow icon? If it's the second one, setting a number that's too large (ie 1000) could ruin the look of the icon right? |
The control text should be something useful for screenreaders, like "skip back 10 seconds". I've updated the codepen example with a version that adds a span for the number, with aria-hidden so it's not read out, and can be localised to match the player language. You're right, a high number won't work well. Maybe accept =< 99? |
You'd also have to consider dynamic typeface sizing/interactions within an SVG icon, which gets finicky, especially with hover effects, etc. For the purposes of the intended work here, it may be best to implement the expected icons with the 5, 10, and 30 increments as SVGs and then build a more expanded solution later down the line. |
I agree - I've created a codepen example with the new icons. @mister-ben @roman-bc-dev please let me know what you think of them 😄 |
Nice. Are we sticking with SVG or getting these into the font? (In general I'd prefer to move to SVG directly). |
I was planning to replace the existing icons for |
I've now created a PR in videojs/font to update the existing icons: videojs/font#49 |
this.skipTime = this.getSkipBackwardTime(); | ||
|
||
if (this.skipTime && this.validOptions.includes(this.skipTime)) { | ||
this.controlText(`Skip backward ${this.skipTime} seconds`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This way means the translation file need a translation for each allowed increment. It's relatively manageable with 3 permitted values, but it is possible to use a variable in these translations: this.localize('Skip backward {seconds} seconds', [this.skipTime])
Either way there should be at least an entry for each string in en.json, so there's a template to translate from.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree.
It should be safe to pass a pre-localized string to controlText
, like:
this.controlText(this.localize('Skip backward {seconds} seconds', [this.skipTime]));
The reason for this is that translators will want a tokenized static string. The {seconds}
token tells them what sort of value to expect in that position.
Then the en.json
should have a new entry:
"Skip backward {seconds} seconds": "Skip backward {seconds} seconds"
The reason to include these in en.json
is that is used as a reference by the script that parses out missing translations.
EDIT: adding a bit more context here...
The controlText
method will pass the string through localize
again, but this will be a pass-thru because the replacement of {seconds}
will have already happened. It's unlikely there would be a matching localization key for something like Skip backward 1 seconds
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh ok thank you for the explanation! How does translation normally work - am I only expected to add this to en.json
and then translators can add the translations to the other json
files?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The deploy preview is looking good! Just the note about translations. At the least there should be an en.json. If swithcing to variables is complicated we can tackle that later (and there's an issue with variables and languagechange event that is out of scope for this PR).
Could you also add a link to the sandbox page in /index.html?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great, Usman! I think just addressing the localization thing should be all that's needed.
this.skipTime = this.getSkipBackwardTime(); | ||
|
||
if (this.skipTime && this.validOptions.includes(this.skipTime)) { | ||
this.controlText(`Skip backward ${this.skipTime} seconds`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree.
It should be safe to pass a pre-localized string to controlText
, like:
this.controlText(this.localize('Skip backward {seconds} seconds', [this.skipTime]));
The reason for this is that translators will want a tokenized static string. The {seconds}
token tells them what sort of value to expect in that position.
Then the en.json
should have a new entry:
"Skip backward {seconds} seconds": "Skip backward {seconds} seconds"
The reason to include these in en.json
is that is used as a reference by the script that parses out missing translations.
EDIT: adding a bit more context here...
The controlText
method will pass the string through localize
again, but this will be a pass-thru because the replacement of {seconds}
will have already happened. It's unlikely there would be a matching localization key for something like Skip backward 1 seconds
.
this.skipTime = this.getSkipForwardTime(); | ||
|
||
if (this.skipTime && this.validOptions.includes(this.skipTime)) { | ||
this.controlText(`Skip forward ${this.skipTime} seconds`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comment here about localization.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've now moved the control text strings from skip-forward
and skip-backward
to en.json
for localization.
I've added the link to the sandbox page now 😁 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks Usman!
* remove duplicate icons from icon example * create initial forward and back button classes * add logic for back/forward buttons on click * change icon used based on option passed into player * move logic from forward and back buttons into one component * add jsdoc comments for clarity * create initial test file * refactor button logic into separate files * update skip button example and add test files * test both the forward and backward buttons * test handleClick fns for both forward and backward btns * update skip buttons example * update jsdocs for skip backward and forward buttons * make control text accessible and use seekableEnd/Start when skipping forward/back * update font version to use updated icons * set control text only if config is valid * add link to sandbox page & use localization * update translations needed
Description
With the upgrade to videojs font 4.0.0, font icons for skipping forward and backward have been introduced. This PR adds the option to add a skip forward or skip backward button to the control bar. These buttons are placed after the
PlayToggle
and before theVolumeControl
, as shown in the image below.The user also has the option to enable only one of the two skip buttons, as shown in the image below.
Code pen example with all icons: https://codepen.io/usmanomar/pen/MWqjWjj
Relevant docs: videojs/videojs.com#167
Options Description
controlBar.skipButtons.forward
The number of seconds forward that should be skipped on button click (can be 5, 10, or 30)
controlBar.skipButtons.backward
The number of seconds backward that should be skipped on button click (can be 5, 10 or 30)
Specific Changes proposed
SkipForward
button that skips forward through a video a configurable amount of secondsSkipBackward
button skips backward through a video a configurable amount of secondsvjs-icon-forward-x
andvjs-icon-replay-x
for theSkipForward
andSkipBackward
buttons respectivelyRequirements Checklist
sandbox/skip-buttons.html.example
)