Skip to content

Progress Ring Text Flow

Nest <text-flow> with data-percentage: the ring writes the rounded percentage into it, and the digits animate on every change.

Download Progress

%

Code

The following example assumes that you have imported the component and set up the theme.

Progress Ring
<div class="progress-container">
<h3 id="progress-ring-label">Download Progress</h3>
<sv-progress-ring id="progress-ring" aria-labelledby="progress-ring-label" value="0">
<p data-value-text>
<sv-text-flow data-percentage="0"></sv-text-flow>
<span>%</span>
</p>
</sv-progress-ring>
<div>
<button id="start-button" type="button" class="update-button">Start</button>
<button id="stop-button" type="button" class="update-button">Stop</button>
</div>
</div>
<script type="module">
32 collapsed lines
/** @type {HTMLButtonElement} */
const startButton = document.querySelector("#start-button");
/** @type {HTMLButtonElement} */
const stopButton = document.querySelector("#stop-button");
/** @type {ProgressRing} */
const progressRing = document.querySelector("#progress-ring");
/** @type {ReturnType<typeof setInterval> | undefined} */
let intervalId;
startButton.addEventListener("click", () => {
if (intervalId) {
clearInterval(intervalId);
progressRing.value = 0;
}
intervalId = setInterval(() => {
const currentValue = progressRing.value;
if (currentValue >= progressRing.max) {
clearInterval(intervalId);
return;
}
progressRing.value = currentValue + 1;
}, 200);
});
stopButton.addEventListener("click", () => {
clearInterval(intervalId);
});
</script>
<style>
.progress-container {
4 collapsed lines
display: flex;
flex-direction: column;
gap: 1em;
align-items: center;
}
sv-progress-ring {
--sv-track-thickness: 14px;
--sv-fill-thickness: 8px;
--sv-fill-linecap: none;
inline-size: 100%;
max-inline-size: 200px;
margin-block: 1em;
sv-text-flow {
--sv-anim-dur: 1s;
}
sv-text-flow::part(text),
span {
font-family: monospace;
font-size: 2rem;
}
}
.update-button {
7 collapsed lines
padding: 0.5em 2em;
margin-inline: 0.5em;
color: var(--sv-accent-content);
cursor: pointer;
background-color: var(--sv-accent);
border: none;
border-radius: var(--sv-bdr-rad-md);
}
</style>