Tracker
Últimos 30 dias
Emissões autorizadas
1.284
alta de 4% sobre o mês passado
- Dia 30: todas autorizadas
- Dia 29: todas autorizadas
- Dia 28: todas autorizadas
- Dia 27: todas autorizadas
- Dia 26: todas autorizadas
- Dia 25: todas autorizadas
- Dia 24: todas autorizadas
- Dia 23: todas autorizadas
- Dia 22: todas autorizadas
- Dia 21: todas autorizadas
- Dia 20: todas autorizadas
- Dia 19: todas autorizadas
- Dia 18: todas autorizadas
- Dia 17: todas autorizadas
- Dia 16: todas autorizadas
- Dia 15: todas autorizadas
- Dia 14: todas autorizadas
- Dia 13: todas autorizadas
- Dia 12: 3 rejeitadas
- Dia 11: fila acima do normal
- Dia 10: todas autorizadas
- Dia 9: todas autorizadas
- Dia 8: todas autorizadas
- Dia 7: todas autorizadas
- Dia 6: todas autorizadas
- Dia 5: todas autorizadas
- Dia 4: sem emissão
- Dia 3: todas autorizadas
- Dia 2: todas autorizadas
- Dia 1: todas autorizadas
import { Tracker } from '@rivocode/ui'Quando usar
A faixa de quadradinhos por período: as últimas 90 emissões, a disponibilidade do mês, a fila dos últimos dias.
Ela responde uma pergunta que o número sozinho não responde ("esteve sempre
assim, ou piorou ontem?") e por isso cabe dentro de um Stat, embaixo do
valor.
Cada quadrado carrega o próprio texto. Uma faixa de cor sem texto não existe para quem usa leitor de tela, e "verde, verde, vermelho" também não diz nada para quem enxerga: o que importa é qual dia foi o vermelho.
A dica é uma só. A faixa inteira é o alvo: o ponteiro corre por ela, uma marca fina acompanha o período lido e um único painel flutuante anda junto. Antes cada quadrado montava a própria dica, e um ano de emissões montava 365 delas para que no máximo uma aparecesse.
O teclado chega ao mesmo período. A faixa é uma parada de tabulação (uma só,
e não uma por quadrado): ao receber foco ela abre no período mais recente, as
setas caminham pelos períodos, Home e End vão às pontas e Esc fecha o
painel sem tirar o foco dali. O período lido pelo teclado é dito também numa
região viva, porque desenho não chega a quem ouve; o ponteiro fica calado ali,
para não encher a fila do leitor de tela com cada quadrado varrido.
O nome é dito uma vez
O texto de label sai num <p> que a fatia label pode mostrar, e o grupo o
toma por aria-labelledby em vez de repeti-lo num aria-label. Antes eram duas
frases idênticas em seguida na árvore de acessibilidade: o parágrafo escondido e
o nome do grupo, um atrás do outro. O <p> fica aria-hidden, porque quem
carrega a frase para quem ouve é o nome do grupo; tirá-lo da leitura não tira
nada de ninguém, e é o que faz a frase ser dita uma vez em vez de duas.
Guardar o <p> em vez de apagá-lo é o que preserva as duas intenções: a fatia
label existe para quem quer o texto na tela, e o nome do grupo continua saindo
do mesmo lugar que essa pessoa vê.
Um aria-label escrito por quem chama vence o label e cai no mesmo grupo.
Antes ele parava na div externa, sem papel, que o Chrome guarda como um nó
generic nomeado e nenhum leitor de tela expõe.
Sentido da escrita
Em dir="rtl" a faixa vira junto. O período mais recente passa a ser o da
esquerda, o ponteiro lê a partir da borda onde a leitura começa e as setas
andam para o lado que a pessoa vê: ← avança no tempo, → volta. Home e
End continuam lógicos: o primeiro e o último período, e não a esquerda e a
direita.
A direção vem do RivoProvider, e não de um dir escrito à mão num elemento
acima da faixa. É o mesmo dir que o resto do catálogo lê, e sem ele a faixa
espelharia o desenho sem espelhar a conta: o dedo na primeira coluna leria o
último período.
O balão anda um quadro atrás
Enquanto o dedo varre a faixa, a marca fina troca de período no mesmo quadro do
evento e o balão chega no quadro seguinte. A Base UI acompanha âncora que se
move por IntersectionObserver, que só avisa no fim do quadro. Não há como
fazê-lo chegar junto sem dar à dica um posicionador próprio.
O atraso é de exatamente um quadro, e não cresce: a distância entre a marca e o balão é a que o ponteiro percorre nesse quadro (a 800px/s, cerca de 13px em 60Hz) e no quadro em que o dedo para os dois voltam a coincidir. Como a dica só se lê com o ponteiro parado, isto está declarado como limite e não como defeito a corrigir.
Movimento
A faixa aparece da esquerda para a direita na montagem, por recorte (animate-reveal, --rc-duration-slow): é uma linha do tempo, e se revela no sentido dela. Com "reduzir movimento", aparece inteira.
Quando não usar
Quando a grandeza é contínua e a forma da curva importa, use Sparkline: o
tracker conta ocorrências discretas, uma por período, e não desenha tendência.
No React Native
Traduz, e os dois lados chegaram ao mesmo desenho: a faixa inteira é um alvo só. O nativo chegou primeiro por necessidade, e o web o seguiu. Lá cada ponto montava um Tooltip, e tooltip é portal: 365 dias eram 365 portais montados para que no máximo um aparecesse. Aqui nem essa saída existia, porque dica se abre ao pousar o ponteiro, e trocar cada quadrado por um Pressable também não resolveria: 90 períodos em 358px dão 4px por quadrado, seis vezes menos que o alvo de toque mínimo.
O que não atravessa é o balão. No web a leitura sai num Tooltip único que segue ponteiro e teclado; aqui ela mora numa linha fixa embaixo da faixa. O dedo pousa e arrasta, uma marca fina acompanha, e o período lido aparece nessa linha, que existe desde o primeiro quadro, mostrando o período mais recente: o espaço fica reservado, a tela não pula no primeiro toque, e o mais recente é o que a pergunta "piorou ontem?" quer ler primeiro.
A leitura de tela também muda de forma. A lista escondida com os 365 textos, que no web é barata, aqui seriam 365 paradas de VoiceOver dentro de um cartão; a faixa é uma parada só, do tipo ajustável (o mesmo contrato do Slider), e cada passo anuncia o texto de um período. Nenhum dado fica inalcançável e nenhum vira obstáculo. Por isso o label de cada ponto é string, e não ReactNode: ele vai inteiro para o valor acessível da faixa, e de um ReactNode não há como ler o texto de volta.
API
| Prop | Tipo |
|---|---|
dataobrigatória0.5.0 | TrackerPoint[] |
labelobrigatória0.5.0O que a faixa mede, dito por extenso para o leitor de tela. | string |
classNames0.5.0Classe por parte: `label`, `track`, `cell`. | Partial<Record<"cell""label""track", string>> |
Além destas, a peça aceita className, style, id e children, repassados ao elemento de baixo.