Acessibilidade e idioma
O que a Vitrine já faz por quem usa teclado e leitor de tela, e como traduzir a aplicação.
O que vem pronto#
Nada disto precisa ser ligado. É como os componentes são desenhados.
| O quê | Como |
|---|---|
| HTML semântico | <main>, <aside>, <fieldset>/<legend>, <table> com <thead> |
| Link para pular a navegação | o primeiro elemento da página, visível só ao receber foco |
| Foco sempre visível | :focus-visible com contorno de 2 px, em todo elemento interativo |
| Rótulo ligado ao campo | <label for> em todos os campos com rótulo |
| Erro anunciado | role="alert" na mensagem, aria-invalid e aria-describedby no campo |
| Abas pelo teclado | role="tablist", setas ← →, Home e End, e só a ativa no caminho do Tab |
| Alerta com a urgência certa | role="alert" para erro e aviso, role="status" para o resto |
| Progresso legível | role="progressbar" com aria-valuenow e aria-label |
| Movimento respeitado | prefers-reduced-motion desliga as animações |
| Tema do sistema | prefers-color-scheme escolhe claro ou escuro sozinho |
A paleta clara usa #B28600 como primária, e não o amarelo #FED403 da marca: amarelo sobre branco dá contraste 1,3:1, e a WCAG pede 4,5:1 para texto. O amarelo continua sendo a marca no tema escuro, onde ele funciona.
O que fica com você#
| O quê | Como fazer |
|---|---|
| Texto alternativo de imagem | V.imagem(origem, legenda := "…") — a legenda vira o alt |
| Ordem de leitura | é a ordem do programa; escreva na ordem em que se lê |
| Rótulo que descreve | V.botao("Excluir pedido 42") diz mais que V.botao("Excluir") |
| Contraste do seu tema | se trocar as cores, confira 4,5:1 para texto e 3:1 para borda |
V.html | o que você puser ali passa cru, sem nenhuma dessas garantias |
Idioma#
Carregue as chaves e peça o texto. O idioma é por sessão: dois visitantes podem estar lendo a mesma página em línguas diferentes, e guardar isso num lugar só faria um trocar o idioma do outro.
dataforge
V.i18n.carregar("pt-BR", {
"painel.titulo": "Painel de Vendas",
"ola": "Olá, {nome}",
"vazio": "Nenhum resultado."
})
V.i18n.carregar("en-US", {
"painel.titulo": "Sales Dashboard",
"ola": "Hello, {nome}",
"vazio": "No results."
})
action painel():
V.titulo(V.t("painel.titulo"))
V.texto(V.t("ola", nome := V.usuario()["nome"]))| Chamada | Faz |
|---|---|
V.i18n.carregar(idioma, vault) | acrescenta chaves a um idioma |
V.i18n.idioma() | o idioma desta sessão |
V.i18n.idioma("en-US") | troca, e reexecuta a página |
V.i18n.idiomas() | os carregados |
V.i18n.seletor("Idioma") | desenha a troca, pronta |
V.t(chave, …) | o texto, com {nome} substituído |
O seletor troca o idioma e reexecuta a página: mudá-lo no meio deixaria a metade de cima na língua anterior.
dataforge
V.lateral().espaco(8)
V.i18n.seletor("Idioma", {"pt-BR": "Português", "en-US": "English"})