Progresso

Usa uma barra determinada sempre que souberes quanto falta — é a única que diz alguma coisa ao leitor. Omite value e a barra passa a animar-se, o que diz «ainda a trabalhar» e mais nada.

Determinada

stack({ gap: 'lg' },
  progress({ value: 25 }),
  progress({ value: 60 }),
  progress({ value: 100 }),
)

Indeterminada

progress()

Uma barra sem label leva aria-hidden — um papel progressbar sem nome acessível não diz nada a um leitor de ecrã, por isso uma barra sem etiqueta é tratada como decoração. Dá nome a tudo o que o leitor deva acompanhar.

Etiquetas

Uma etiqueta nomeia o que está a acontecer; showValue acrescenta a percentagem à direita.

A renderizar páginas72%
A otimizar imagens50%
À espera da publicação
stack({ gap: 'lg' },
  progress({ value: 72, label: 'A renderizar páginas', showValue: true }),
  progress({ value: 30, max: 60, label: 'A otimizar imagens', showValue: true }),
  progress({ label: 'À espera da publicação' }),
)

Cores e altura

Passou80%
Degradado45%
A falhar20%
stack({ gap: 'lg' },
  progress({ value: 80, color: 'success', label: 'Passou', showValue: true }),
  progress({ value: 45, color: 'warning', label: 'Degradado', showValue: true }),
  progress({ value: 20, color: 'danger', label: 'A falhar', showValue: true }),
  progress({ value: 60, color: 'neutral', height: 'xs' }),
  progress({ value: 60, color: 'primary', height: '1rem' }),
)

Uma escala que não seja 100

max deixa-te passar os números em bruto — páginas construídas sobre páginas totais — em vez de calculares primeiro uma percentagem.

118 de 169 páginas70%
progress({ value: 118, max: 169, label: '118 de 169 páginas', showValue: true })

Movê-la a partir do browser

Uma barra é HTML renderizado no servidor: a percentagem é uma propriedade personalizada no preenchimento e um número em aria-valuenow, e nada na página muda qualquer um dos dois por si. Dá à barra um id e setProgress move os dois em conjunto — o preenchimento, o valor anunciado e a percentagem ao lado da etiqueta.

import { setProgress } from 'sitelo/ui/client'

const request = new XMLHttpRequest()

request.upload.addEventListener('progress', (event) => {
  setProgress('upload', event.loaded, { max: event.total })
})

O máximo fica guardado, por isso as chamadas seguintes são só um valor. Ou chega ao módulo como os componentes chegam aos deles, e salta o bundle por completo:

button({ onclick: "import('/su/progress.js').then(m=>m.set('upload',100))" }, 'Terminar')

Passar null — ou qualquer coisa que não seja um número finito — devolve a barra à animação indeterminada, por isso trabalho que deixa de dar números não precisa de um caso à parte. getProgress() lê o valor atual de volta, na escala da própria barra.

Experimenta

Esta página carrega o runtime, por isso os botões abaixo movem mesmo a barra.

A enviar0%
stack({ gap: 'md' },
  progress({ id: 'demo-progress', value: 0, label: 'A enviar', showValue: true }),
  stack({ direction: 'row', gap: 'sm', wrap: true },
    button({ size: 'sm', variant: 'outline', onclick: "import('/su/progress.js').then(m=>m.set('demo-progress',0))" }, 'Reiniciar'),
    button({ size: 'sm', variant: 'outline', onclick: "import('/su/progress.js').then(m=>m.set('demo-progress',35))" }, '35%'),
    button({ size: 'sm', variant: 'outline', onclick: "import('/su/progress.js').then(m=>m.set('demo-progress',80))" }, '80%'),
    button({ size: 'sm', variant: 'outline', onclick: "import('/su/progress.js').then(m=>m.set('demo-progress',100))" }, 'Concluído'),
    button({ size: 'sm', variant: 'ghost', onclick: "import('/su/progress.js').then(m=>m.set('demo-progress',null))" }, 'Desconhecido'),
  ),
)

Uma barra sem etiqueta também se move, mas continua aria-hidden — foi renderizada sem nome de propósito, e anunciar-lhe um valor agora poria uma progressbar sem nome na árvore de acessibilidade.

Indicador giratório

Não há um componente indicador — o indicador é um ícone, e spin é o que o faz girar. Como qualquer ícone, é dimensionado em em, por isso combina com o texto ao lado sem que lhe digam um tamanho.

stack({ direction: 'row', gap: 'lg', align: 'center' },
  icon('spinner', { spin: true, size: 'sm' }),
  icon('spinner', { spin: true }),
  icon('spinner', { spin: true, size: 'lg' }),
)

O indicador em contexto

Dá um label a um indicador isolado para ele ser anunciado. O que está dentro de um botão não precisa — o botão já diz o que está a fazer.

A ir buscar a última construção…

stack({ gap: 'md' },
  stack({ direction: 'row', gap: 'sm', align: 'center' },
    icon('spinner', { spin: true, label: 'A carregar' }),
    text({ variant: 'small', tone: 'muted' }, 'A ir buscar a última construção…'),
  ),
  stack({ direction: 'row', gap: 'sm' },
    button({ loading: true }, 'A publicar'),
    button({ variant: 'outline', loading: true }, 'A verificar ligações'),
  ),
)

Props

progress() — exportado também como progressBar:

PropTipoPredefiniçãoDescrição
valuenumber—Até onde vai. Omite-o para a animação indeterminada.
maxnumber100Que valor conta como completo.
color'primary' | 'neutral' | 'success' | 'warning' | 'danger''primary'Cor do preenchimento.
labelChild—Texto por cima da barra; também o seu nome acessível.
showValuebooleanfalseMostrar a percentagem ao lado da etiqueta.
heightSpace'0.5rem'Espessura da barra.

setProgress() de sitelo/ui/client:

PropTipoPredefiniçãoDescrição
targetElement | string—A barra, ou o id de uma. Se nenhum elemento tiver esse id, é tentado como seletor.
valuenumber | null—Para onde a mover. null devolve-a à animação indeterminada.
options.maxnumber100O que conta como completo. Fica guardado para as chamadas seguintes.

O indicador não tem props próprias — é icon('spinner', { spin: true }), e aceita o que icon() aceitar.