Progress

The agnostic-astro package utilizes XElement under-the-hood in order to provide build-time Astro components. These build-time components will help your project get closer to realizing a mostly no client-side runtime…if you do it right, this should mean an all-green 100% Lighthouse performance score! Leverage the benefits of Islands architecture by sending mostly server built agnostic-astro components. Then, sprinkle client-hydrated ones only as needed.

Usage

Ensure you've installed the agnostic-astro npm package (note this installs depedency agnostic-css as well):

npm i agnostic-astro

and then import common.min.css from your “base layout” (you should only need to do this in once place as this is global CSS). This brings in the required CSS custom properties, reset, and properties:

import 'agnostic-css/public/css-dist/common.min.css';

Then you can import Astro Progress component:

import AgProgress from 'agnostic-astro/Progress.astro';

Here's the agnostic-astro Progress component in use:

<AgProgress class="mbs24 progress-el" max={100} value={0} />

Here's how you might implement the above functionality using only platform JavaScript:


  // This is just a demo of how you might control the progress
  // with your own application code
  const progressElement = document.querySelector('.progress-el');
  const playButton = document.querySelector('.start');
  const stopButton = document.querySelector('.stop');
  let requestAnimationID;
  let progress = 0;

  // Increments progress by 1 unit then issues RAF request
  const step = () => {
    playButton.disabled = true;
    stopButton.disabled = false;
    progress += 1;
    progressElement.setAttribute('value', progress.toString());
    if (progress === 100) {
      playButton.disabled = false;
      stopButton.disabled = true;
    } else if (progress < 100) {
      requestAnimationID = requestAnimationFrame(step);
    }
  }

  // Calls step and stores the RAF ID
  requestAnimationID = requestAnimationFrame(step);

  // Attaches the start aka play button click handler
  playButton.addEventListener('click', () => {
    // Circle back to zero if at end
    if (progress >= 100) {
      progress = 0;
    }
    requestAnimationID = requestAnimationFrame(step)
  })

  // Attaches the stop button click handler
  stopButton.addEventListener('click', () => {
    if (requestAnimationID) {
      cancelAnimationFrame(requestAnimationID)
      requestAnimationID = undefined
      // Re-enable the Play button
      playButton.disabled = false
      stopButton.disabled = true
    }
  })