Esikatselu
<ProgressBar aria-label="Edistymispalkki" value={47} valueText="47 %">
<ProgressBarDescription>
Valmiina <ProgressBarHighlight>47</ProgressBarHighlight> %
</ProgressBarDescription>
</ProgressBar>
Käyttötarkoitus
Kun toiminnon suorittamiseen kuluva aika on pitkä, voit näyttää etenemisen edistymispalkissa.
Edistymispalkki kertoo, että toiminto on käynnistetty ja prosessi etenee. Sen avulla käyttäjä voi saada myös arvion siitä, kuinka kauan prosessin suorittaminen kestää. Tämä lisää luottamusta järjestelmää kohtaan.
Edistymispalkki sopii käytettäväksi pitkäkestoisen toiminnon yhteydessä, jossa käyttäjä joutuu odottamaan toiminnon valmistumista. Tällaisia toimintoja ovat esimerkiksi tiedostojen lataaminen ja ohjelmistoasennukset.
- Käytä toiminnoille, joiden valmistuminen kestää pidempään kuin 10 sekuntia.
- Näytä edistymispalkki heti, kun odotusta vaativa toiminto on käynnistynyt.
- Näytä palkin yhteydessä etenemistä havainnollistava tekstivastine.
- Älä käytä toiminnoille, joiden valmistuminen kestää vain muutaman sekunnin. Käytä tällöin mieluummin Spinneriä tai Skeletonia.
- Älä käytä kuvaamaan sellaisen prosessin edistymistä, jossa vaaditaan käyttäjän toimenpiteitä (esim. hakemuksen täyttäminen).
Saavutettavuus
Komponentti toteuttaa saavutettavan edistymispalkin lisäämällä sille role="progressbar" roolin ja muut tarvittavat aria-attribuutit.
Edistymispalkki ei ole interaktiviinen elementti, joten siihen ei pääse käsiksi tabulaattorilla.
Edistymispalkille tulee antaa näkyvä nimilappu labelText-propilla tai ei-näkyvä nimilappu aria-label-attribuutilla. Lisäksi sille annetaan edistymistä kuvaava teksti.
Ruudunlukijat saattavat myös ilmoittaa edistymisestä äänimerkillä. NVDA ilmoittaa edistymisen äänimerkillä ainoastaan, jos valueText (aria-valuetext) on numeerinen. Muut ruudunlukijat ilmoittavat äänimerkillä edistymisestä silloin kun virtuaalikursori on edistymispalkin kohdalla.
Edistymisestä viestiminen ruudunlukijalle sopivin väliajoin jää sovelluksen toteutettavaksi. Sopiva aikaväli riippuu toteutuksesta. Tärkeää on että edistymisestä kerrotaan, mutta ei liian usein.
Alla on esimerkki, jossa edistymisen tila luetaan kuuden sekunnin välein. Lisäksi edistymisprosentti ilmoitetaan, kun edistyminen alkaa ja päättyy.
function ProgressBarExample() {
const [progress, setProgress] = useState(0);
const announceDelayMs = 6000;
const announceIntervalRef = useRef<ReturnType<typeof setTimeout>>(undefined);
const ariaLiveRef = useRef<HTMLDivElement>(null);
const maxValue = 100;
const progressDelayMs = 150;
const progressIntervalRef = useRef<ReturnType<typeof setTimeout>>(undefined);
const progressValueRef = useRef(0);
const { ariaLiveProps, announce } = useAriaLive(ariaLiveRef);
const startProgress = () => {
setProgress(1);
progressValueRef.current = 1;
announce(`Lähetetty ${progressValueRef.current} %`);
if (progressIntervalRef.current) {
clearInterval(progressIntervalRef.current);
}
if (announceIntervalRef.current) {
clearInterval(announceIntervalRef.current);
}
progressIntervalRef.current = setInterval(() => {
setProgress((prevProgress) => {
if (prevProgress < maxValue) {
progressValueRef.current = prevProgress + 1;
return prevProgress + 1;
} else {
announce("Lähetetty 100 %");
clearInterval(progressIntervalRef.current);
clearInterval(announceIntervalRef.current);
return prevProgress;
}
});
}, progressDelayMs);
announceIntervalRef.current = setInterval(() => {
if (progressValueRef.current < maxValue) {
announce(`Lähetetty ${progressValueRef.current} %`);
} else {
clearInterval(announceIntervalRef.current);
}
}, announceDelayMs);
};
useEffect(() => {
return () => {
clearInterval(progressIntervalRef.current);
clearInterval(announceIntervalRef.current);
};
}, []);
return (
<>
<Button appearance="outline" className="kds-mb-6" onClick={startProgress}>
Käynnistä
</Button>
<ProgressBar aria-label="Asiakirjojen lähetys" maxValue={maxValue} value={progress} valueText={`${progress} %`}>
<ProgressBarDescription>
Lähetetty <ProgressBarHighlight>{progress}</ProgressBarHighlight> %
</ProgressBarDescription>
</ProgressBar>
<div {...ariaLiveProps} />
</>
);
}
Edistymistä kuvaava teksti
Anna edistymiselle aina tekstivastine. Tekstivastineen tulisi kertoa mahdollisimman selkeästi siitä, minkä verran prosessi on edistynyt tai minkälainen odotusaika on jäljellä.
<>
<ProgressBar aria-label="Edistyminen" className="kds-mb-8" value={47} valueText="47 %">
<ProgressBarDescription>
Valmiina <ProgressBarHighlight>47</ProgressBarHighlight> %
</ProgressBarDescription>
</ProgressBar>
<ProgressBar
aria-label="Asiakirjojen lähetys"
className="kds-mb-8"
maxValue={15}
value={3}
valueText="3/15 asiakirjaa"
>
<ProgressBarDescription>
Lähetetty <ProgressBarHighlight>3/15</ProgressBarHighlight> asiakirjaa
</ProgressBarDescription>
</ProgressBar>
<ProgressBar aria-label="Edistyminen" value={25} valueText="25 %">
<ProgressBarDescription>
Jäljellä noin <ProgressBarHighlight>7</ProgressBarHighlight> minuuttia
</ProgressBarDescription>
</ProgressBar>
</>
Edistymispalkille voi antaa myös oman nimilapun.
<ProgressBar labelText="Tiedostojen lähetys" value={89} valueText="89 %">
<ProgressBarDescription>
Jäljellä noin <ProgressBarHighlight>2</ProgressBarHighlight> minuuttia
</ProgressBarDescription>
</ProgressBar>
Edistyminen
Edistymispalkin tulee ilmestyä heti, kun käyttäjä on käynnistää toiminnon, johon odottaminen liittyy.
Edistymispalkin tulee näyttää koko ajan prosessin edistymistä, eikä se saa pysähtyä. Pitkä pysähtyminen ilman selkeää syytä saa käyttäjän epäilemään järjestelmän toimivuutta.
function ProgressBarExample() {
const maxValue = 100;
const progressDelayMs = 100;
const progressIntervalRef = useRef<ReturnType<typeof setTimeout>>(undefined);
const [progress, setProgress] = useState(0);
const startProgress = () => {
setProgress(1);
if (progressIntervalRef.current) {
clearInterval(progressIntervalRef.current);
}
progressIntervalRef.current = setInterval(() => {
setProgress((prevProgress) => {
if (prevProgress < maxValue) {
return prevProgress + 1;
} else {
clearInterval(progressIntervalRef.current);
return prevProgress;
}
});
}, progressDelayMs);
};
useEffect(() => {
return () => {
clearInterval(progressIntervalRef.current);
};
}, []);
return (
<>
<Button appearance="outline" onClick={startProgress} className="kds-mb-6">
Käynnistä
</Button>
<ProgressBar aria-label="Lähetys" maxValue={maxValue} value={progress} valueText={`${progress} %`}>
<ProgressBarDescription>
Lähetetty <ProgressBarHighlight>{progress}</ProgressBarHighlight> %
</ProgressBarDescription>
</ProgressBar>
</>
);
}
Edistymispalkki voi edetä yksi hyppy kerrallaan silloin, kun edistyminen on vaiheittaista, kuten tiedostoja lähetettäessä.
function ProgressBarExample() {
const maxValue = 15;
const progressDelayMs = 1500;
const progressIntervalRef = useRef<ReturnType<typeof setTimeout>>(undefined);
const [progress, setProgress] = useState(0);
const startProgress = () => {
setProgress(1);
if (progressIntervalRef.current) {
clearInterval(progressIntervalRef.current);
}
progressIntervalRef.current = setInterval(() => {
setProgress((prevProgress) => {
if (prevProgress < maxValue) {
return prevProgress + 1;
} else {
clearInterval(progressIntervalRef.current);
return prevProgress;
}
});
}, progressDelayMs);
};
useEffect(() => {
return () => {
clearInterval(progressIntervalRef.current);
};
}, []);
return (
<>
<Button appearance="outline" onClick={startProgress} className="kds-mb-6">
Käynnistä
</Button>
<ProgressBar
animation="ease-in-out"
aria-label="Asiakirjojen lähetys"
maxValue={maxValue}
value={progress}
valueText={`${progress}/${maxValue} asiakirjaa`}
>
<ProgressBarDescription>
Lähetetty{" "}
<ProgressBarHighlight>
{progress}/{maxValue}
</ProgressBarHighlight>{" "}
asiakirjaa
</ProgressBarDescription>
</ProgressBar>
</>
);
}
Jos prosessin kokonaisaikaa on vaikea arvioida toiminnon käynnistyessä, voi edistymispalkki edetä ensin hitaammin ja kiihdyttää vauhtia tarvittaessa loppua kohden. Edistymisen hidastuminen lopussa sen sijaan saa aikaan epäluottamusta.
Edistymispalkki ei sovi käytettäväksi sellaisten toimintojen yhteydessä, joiden kestosta ei voida antaa minkäänlaista arviota.
Virhetilanteet
Virhetilanteissa edistymispalkista voi näyttää punaisen version. Virhetilanteessa tulee lisäksi aina näyttää myös virheilmoitus.
<>
<Alert variant="danger">
<Text mb={4}>
<strong>Asiakirjojen lähetys epäonnistui.</strong>
</Text>
<Text>Valitettavasti asiakirjojen lähetys ei onnistunut. Yritä hetken kuluttua uudelleen.</Text>
</Alert>
<ProgressBar aria-label="Asiakirjojen lähetys" maxValue={15} value={3} valueText="3" variant="danger">
<ProgressBarDescription>
Lähetetty <ProgressBarHighlight>3/15</ProgressBarHighlight> asiakirjaa
</ProgressBarDescription>
</ProgressBar>
</>
Pyöristetty edistymispalkki
Edistymispalkin reunojen pyöristys on toteutettavissa isRounded-propin avulla.
<ProgressBar aria-label="Pyöristetty edistymispalkki" isRounded value={45} valueText="45 %">
<ProgressBarDescription>
Valmiina <ProgressBarHighlight>45</ProgressBarHighlight> %
</ProgressBarDescription>
</ProgressBar>
Kokovaihtoehdot
Tiivistä edistysmispalkkia käytetään tarvittaessa asiantuntijakäyttöliittymissä.
<>
<ProgressBar className="kds-mb-8" labelText="Normaali edistymispalkki" value={45} valueText="45 %">
<ProgressBarDescription>
Valmiina <ProgressBarHighlight>45</ProgressBarHighlight> %
</ProgressBarDescription>
</ProgressBar>
<ProgressBar labelText="Tiivis edistymispalkki" size="xs" value={45} valueText="45 %">
<ProgressBarDescription>
Valmiina <ProgressBarHighlight>45</ProgressBarHighlight> %
</ProgressBarDescription>
</ProgressBar>
</>