Novidades do Akira UI 3.2.0
Um seletor de hora e outro de data e hora para formulários, e gráficos e stat cards que mostram o valor exato, com as percentagens no formato da app.
Até à versão anterior, uma tabela com uma só linha mostrava “1 registos”. No Akira UI 3.2.0, que acabei de publicar, o total por baixo da tabela escolhe entre singular e plural com Intl.PluralRules:

Em português passa a dizer “1 registo”, e em francês “1 enregistrement”. O resto da release vai no mesmo sentido: formulários que pedem uma hora e dashboards com números escritos na língua de quem os lê.
Para quem não conhece, o Akira UI é uma biblioteca de componentes React construída sobre as primitivas do shadcn. Além de botões, diálogos e tabelas, inclui shells de aplicação, blocos prontos, textos traduzidos e um adaptador para Inertia. A 3.2.0 é uma versão minor, por isso quem está na 3.1.0 só precisa de subir a versão. As imagens abaixo são os exemplos de ui.akira-io.com, em inglês, renderizados com a 3.2.0. O da tabela foi reduzido a uma só linha.
Um total dividido em partes

O StatBreakdownCard mostra o total à esquerda e, à direita, uma barra com um segmento por parte e a legenda por baixo. Cada segmento pode receber o foco e mostra num tooltip o nome, a percentagem e o valor exato. O CompositionBar desenha só a barra e a legenda, para usar dentro de um card próprio.
As percentagens destes componentes, e a tendência do StatCard, seguem agora um locale definido no provider. Sem ele, ficam em en-US:
<UiLocaleProvider labels={ptLabels} dateLocale={pt} locale="pt-PT">
<App />
</UiLocaleProvider>
Com pt-PT, os 62.4% da imagem passam a 62,4%. Uma tag mal formada, como pt_PT, não rebenta com o componente: a formatação volta ao en-US.
Gráficos que mostram o valor exato

Um saldo que oscila entre positivo e negativo pede o zero ao centro, uma linha a marcá-lo e os meses negativos noutra cor:
<BarChart
data={balanceByMonth}
series={['balance']}
xKey="month"
yDomain="symmetric"
referenceLines={[{ y: 0 }]}
colorBy={(datum) =>
Number(datum.balance) < 0 ? 'var(--destructive)' : 'var(--chart-1)'
}
yFormat={{ style: 'currency', currency: 'EUR', notation: 'compact' }}
/>
O yDomain="symmetric" pega no maior valor absoluto, arredonda-o para cima e espelha-o. O pico de abril, 25 296, dá um eixo de -30 000 a 30 000. O vermelho vem do colorBy, que aceita uma função que recebe cada linha dos dados ou 'category', que dá a cada linha uma cor da paleta.
O eixo é compacto e conta de 10 mil em 10 mil, mas o tooltip mostra agora o valor exato por omissão, como mostra o tooltip de abril (€25,296). Para rankings existe a variant="lollipop", e o valueLabels escreve o valor em cada marca. Os gráficos de linhas aceitam yScale="log", e um gráfico de área pode desvanecer-se com fill="gradient".
Escolher a hora, ou a data e a hora

A biblioteca tinha um DatePicker, mas nada para a hora. O TimePicker resolve isso. No exemplo, um armazém aceita recolhas entre as 08:00 e as 18:00, de 15 em 15 minutos:
<TimePicker
value={pickup}
onChange={setPickup}
minuteStep={15}
minTime="08:00"
maxTime="18:00"
/>
A hora pode ser escrita no campo ou escolhida nas colunas, e o valor é devolvido como uma string simples, HH:mm. Sem hourCycle, o componente pergunta ao Intl.DateTimeFormat qual é o ciclo horário do locale de datas do UiLocaleProvider. Numa app em português, o relógio aparece em formato de 24 horas sem ser preciso configurar nada, e numa app americana aparece com AM e PM.

Para um momento concreto, o DateTimePicker junta o calendário às mesmas colunas e devolve um Date. Aqui, a janela de manutenção só pode começar num dia útil de setembro, de 30 em 30 minutos:
<DateTimePicker
value={start}
onChange={setStart}
minDate={opensAt}
maxDate={closesAt}
disabledDays={isWeekend}
minuteStep={30}
/>
O minDate e o maxDate limitam também a hora: no próprio dia do limite, as colunas param na hora desse limite. Os dois seletores trazem textos em português, espanhol e francês, como “Escolher hora” e “Limpar hora”.
Outras mudanças
- O
NotificationBellmostra um contador de não lidas e um popover, e oInertiaNotificationBellfaz polling enquanto a página está ativa. - O
useFortifyTwoFactorliga os blocos de autenticação de dois fatores ao Laravel Fortify. - Os grupos de navegação podem conter outros grupos, e o
AppSidebarrecupera o estado, recolhido ou aberto, que guardou da última vez. - O
Comboboxaceita uma função de filtro, e oCommandDialogpassa as props aoCommandinterno. - Um tour salta os passos cujo alvo não está na página, e o progresso só conta os passos que mostra.
Para terminar
Numa app em português, as percentagens passam a ter vírgula e a hora deixa de precisar de um input feito à mão. Cada componente pode ser experimentado em ui.akira-io.com. A lista completa de alterações está nas notas da release, e o pacote está no npm.