From edb9b8315375c7db648b83ade21f466dbd107f80 Mon Sep 17 00:00:00 2001 From: Matei Stanca <i@ambientimpact.com> Date: Thu, 28 Nov 2024 10:02:02 -0500 Subject: [PATCH] Issue #3488464: Added documentation to new progress bar CSS and JS. --- .../progress-bar-delay/progress-bar-delay.js | 56 ++++++++ components/progress-bar/progress-bar.css | 37 ++++- components/progress-bar/progress-bar.js | 134 +++++++++++++++++- 3 files changed, 220 insertions(+), 7 deletions(-) diff --git a/components/progress-bar-delay/progress-bar-delay.js b/components/progress-bar-delay/progress-bar-delay.js index 7db6b29..3864337 100644 --- a/components/progress-bar-delay/progress-bar-delay.js +++ b/components/progress-bar-delay/progress-bar-delay.js @@ -12,14 +12,37 @@ 'use strict'; + /** + * Represents a progress bar delay wrapper. + */ class ProgressBarDelay { + /** + * Time in milliseconds before the progress bar is shown. + * + * @type {Number} + */ #delay = 0; + /** + * The visit timeout ID, if any. + * + * @type {Number|null} + */ #visitTimeout = null; + /** + * The form submit timeout ID, if any. + * + * @type {Number|null} + */ #formTimeout = null; + /** + * The progress bar instance that we're wrapping. + * + * @type {ProgressBar} + */ #progressBar; constructor(delay, progressBar) { @@ -30,6 +53,15 @@ } + /** + * Start the timeout to show the progress bar. + * + * @param {Number|null} timeoutId + * An existing timeout ID, if any. + * + * @return {Number} + * A new timeout ID. + */ showAfterDelay(timeoutId) { if (timeoutId !== null) { @@ -44,6 +76,13 @@ } + /** + * Hide the progress bar and cancel an existing timeout, if any. + * + * @param {Number|null} timeoutId + * + * @return {null} + */ hideAndCancelDelay(timeoutId) { if (timeoutId === null) { @@ -62,18 +101,27 @@ } + /** + * Show the progress bar after a delay for non-form submission visits. + */ showVisitAfterDelay() { this.#visitTimeout = this.showAfterDelay(this.#visitTimeout); } + /** + * Hide the progress bar for non-form submission visits. + */ hideVisit() { this.#visitTimeout = this.hideAndCancelDelay(this.#visitTimeout); } + /** + * Show the progress bar after a delay for form submissions. + */ showFormAfterDelay() { // Unlike the visit progress bar, we prefer to not replace an existing @@ -89,12 +137,20 @@ } + /** + * Hide the progress bar for form submissions. + */ hideForm() { this.#formTimeout = this.hideAndCancelDelay(this.#formTimeout); } + /** + * Get the progress bar instance we're wrapping. + * + * @return {ProgressBar} + */ get progressBar() { return this.#progressBar; } diff --git a/components/progress-bar/progress-bar.css b/components/progress-bar/progress-bar.css index ebb39c2..785582b 100644 --- a/components/progress-bar/progress-bar.css +++ b/components/progress-bar/progress-bar.css @@ -1,24 +1,57 @@ :root { - /* Drupal blue. */ + /** + * The progress bar colour. + * + * Defaults to Drupal blue. + * + * @type {Color} + */ --refreshless-progress-bar-colour: #0678be; + /** + * The progress bar thickness. + * + * @type {Number} + */ --refreshless-progress-bar-thickness: 3px; - /* Themes should override this to a more sensible value. */ + /** + * The progress bar z-index. + * + * Themes should override this to a more sensible value. + * + * @type {Number} + */ --refreshless-progress-bar-z-index: 2147483647; + /** + * The progress bar minimum/start value. + * + * This should be a percentage. + * + * @type {Number} + */ --refreshless-progress-bar-start: 10%; + /** + * Progress bar width transition. + */ --refreshless-progress-bar-width-transition: width var(--refreshless-progress-bar-transition-duration) ease-out; + /** + * Progress bar opacity transition out. + */ --refreshless-progress-bar-opacity-transition-out: opacity calc(var(--refreshless-progress-bar-transition-duration) / 2) calc(var(--refreshless-progress-bar-transition-duration) / 2) ease-in; + /** + * Progress bar opacity transition in. + */ --refreshless-progress-bar-opacity-transition-in: opacity calc(var(--refreshless-progress-bar-transition-duration) / 2) diff --git a/components/progress-bar/progress-bar.js b/components/progress-bar/progress-bar.js index 2c7ed8a..b00862f 100644 --- a/components/progress-bar/progress-bar.js +++ b/components/progress-bar/progress-bar.js @@ -29,35 +29,92 @@ } + /** + * CSS custom property base name. + * + * @type {String} + */ const customPropertyBase = '--refreshless-progress-bar'; + /** + * Name of the CSS custom property containing the transition duration. + * + * The value will be a time in ms. + * + * @type {String} + */ const durationCustomProperty = `${customPropertyBase}-transition-duration`; + /** + * Name of the CSS custom property containing the progress bar delay. + * + * The value will be a time in ms. + * + * @type {String} + */ const delayCustomProperty = `${customPropertyBase}-delay`; + /** + * Name of the CSS custom property containing the current progress bar value. + * + * The value will be float between 0 and 1, inclusive. + * + * @type {String} + */ const valueCustomProperty = `${customPropertyBase}-value`; - const html = document.documentElement; - /** - * The once() identifier for attaching the progress bar. + * The <html> element. * - * @type {String} + * @type {HTMLHtmlElement} */ - const onceName = 'refreshless-turbo-progress-bar'; + const html = document.documentElement; + /** + * Represents a progress bar. + */ class ProgressBar { + /** + * The progress bar HTML element. + * + * @type {HTMLElement} + */ #element; + /** + * Whether the progress bar is currently in the processing of hiding. + * + * @type {Boolean} + */ #hiding = false; + /** + * The current value of the progress bar, from 0 to 1, inclusive. + * + * @type {Number} + */ #value = 0; + /** + * Whether the progress bar is currently visible. + * + * @type {Boolean} + */ #visible = false; + /** + * The trickle interval ID, or null if one is not active. + * + * @type {Number|null} + */ #trickleInterval = null; + /** + * The progress bar transition duration, in milliseconds. + * + * @type {Number} + */ #transitionDuration = 300; constructor() { @@ -68,6 +125,9 @@ } + /** + * Show the progress bar if not already visible. + */ show() { if (this.#visible === true) { @@ -80,6 +140,9 @@ } + /** + * Hide the progress bar if visible and not already hiding. + */ hide() { if (!(this.#visible === true && this.#hiding === false)) { @@ -100,6 +163,9 @@ } + /** + * Set the progress bar as active, causing CSS to transition it in. + */ #setActive() { this.#element.classList.add( @@ -108,6 +174,9 @@ } + /** + * Set the progress bar as inactive, causing CSS to transition it out. + */ #setInactive() { this.#element.classList.remove( @@ -116,6 +185,12 @@ } + /** + * Transition the progress bar out. + * + * @return {Promise} + * A Promise that resolves when the transition is considered complete. + */ #transitionOut() { this.#setInactive(); @@ -128,6 +203,15 @@ } + /** + * Explicitly set the progress bar to a value. + * + * @param {Number} value + * A number between 0 and 1, inclusive. + * + * @throws If value is NaN, or if the value is less than 0 or greater than + * 1. + */ setValue(value) { if (Number.isNaN(value)) { @@ -144,6 +228,9 @@ } + /** + * Install the progress bar in the document and set various properties. + */ install() { html.style.setProperty( @@ -170,6 +257,9 @@ } + /** + * Uninstall the progress bar from the document and remove properties. + */ uninstall() { if (this.#element.parentNode) { @@ -182,6 +272,9 @@ } + /** + * Start the trickling animation. + */ startTrickling() { if (this.#trickleInterval !== null) { @@ -194,6 +287,9 @@ } + /** + * Stop the trickling animation. + */ stopTrickling() { window.clearInterval(this.#trickleInterval); @@ -202,10 +298,18 @@ } + /** + * Trickle animation interval callback. + * + * This generates a random value to give the trickle the irregular movement. + */ trickle = () => { this.setValue(Math.min(1, this.#value + Math.random() / 100)); } + /** + * Update the progress bar element's value with the current value. + */ async refresh() { await new Promise(requestAnimationFrame); @@ -214,6 +318,11 @@ } + /** + * Finish/complete the progress bar to 100% and start hiding it. + * + * @return {[type]} [description] + */ finish() { this.setValue(1); @@ -222,14 +331,29 @@ } + /** + * Get the current value of the progress bar. + * + * @return {Number} + */ get value() { return this.#value; } + /** + * Get the progress bar HTML element. + * + * @return {HTMLElement} + */ get element() { return this.#element; } + /** + * Get the progress bar transition value. + * + * @return {Number} + */ get transitionDuration() { return this.#transitionDuration; } -- GitLab