Tema
BaseThemeSwitch
A escolha do tema da tela: claro, escuro ou o mesmo do sistema operacional. A escolha vale para a página inteira e fica guardada no navegador. "Seguir sistema" apaga a escolha guardada, e a tela volta a acompanhar o computador ou o celular, inclusive quando ele troca de tema com a página aberta.
Nesta documentação, o seletor troca o tema do site inteiro. A chave de tema no alto da página, do próprio site, guarda a mesma escolha: mudar uma muda a outra.
Uso
- Ponha um
BaseThemeSwitchno menu da pessoa, no slotuser-menudoBaseAppShell, antes do "Sair". É uma preferência da pessoa e vale em todas as telas. - A tela de login fica sem seletor. Ela tem uma ação só, entrar com a conta do Tribunal, e já abre no tema guardado ou no do sistema, porque o
initTheme()roda antes de qualquer tela. Depois de entrar, a pessoa troca o tema no menu dela. - Chame
initTheme()nomain.ts, antes de montar o app. É ela que aplica a escolha guardada antes da primeira pintura e acompanha o sistema operacional quando não há escolha. O seletor só mostra e muda a escolha. - Um seletor por tela basta. Se houver mais de um, todos mostram a mesma escolha.
- O seletor não cria um tema de alto contraste. Quem usa o alto contraste do Windows continua com as cores do sistema operacional, que valem por cima de qualquer tema.
- Para trocar o tema sem o seletor, use
setTheme('light'),setTheme('dark')ousetTheme('system'), da página Tokens e temas.
Anatomia
- Nome: o texto de
label, "Tema" por padrão, acima das opções. - Opções: "Claro", "Escuro" e "Seguir sistema", num
BaseSegmented. A escolhida fica elevada e em negrito.
Tamanhos
O trilho das três opções tem 204 px de largura no sm, 240 px no md e 276 px no lg. Num espaço mais estreito, as opções rolam para o lado, como em qualquer BaseSegmented.
No menu da pessoa, use sm: as opções ficam mais baixas que os itens do menu e não parecem ações. Com 26 px de altura e pelo menos 44 px de largura, elas passam do alvo mínimo de 24 × 24 px do WCAG 2.2 (critério 2.5.8, nível AA). Os links da faixa do menu no celular têm 44 × 44 px porque a pessoa passa por eles a cada troca de tela; o tema se escolhe uma vez e fica guardado.
No menu da pessoa
Escolher um tema não fecha o menu: a pessoa vê o resultado e pode trocar de novo. "Sair" e os outros itens continuam fechando o menu.
Faça e não faça
| Faça | Não faça |
|---|---|
| Pôr o seletor no menu da pessoa, antes do "Sair". | Pôr o seletor no meio da tela ou em cada página. |
| Deixar "Seguir sistema" como está quando a pessoa nunca escolheu. | Gravar o tema do sistema como se fosse uma escolha. |
Chamar initTheme() no main.ts. | Ler ou gravar o tema no localStorage direto. |
| Contar com o alto contraste do Windows para quem precisa dele. | Apresentar o tema escuro como alto contraste. |
Estilo
| Propriedade | Token |
|---|---|
| Nome | --tj-text-sm, --tj-leading-sm, --tj-weight-medium e --tj-text-secondary |
| Espaço entre o nome e as opções | --tj-space-2 |
| Opções | as do BaseSegmented |
| No menu da pessoa | espaço interno de --tj-space-2 e --tj-space-3, alinhado ao texto dos itens; o painel se alarga para caber as três opções |
Código
ts
// main.ts
import { initTheme } from '@lab-inovacao-tjes/design-system'
initTheme()vue
<script setup lang="ts">
import { BaseAppShell, BaseThemeSwitch, BaseUserMenuItem } from '@lab-inovacao-tjes/design-system'
</script>
<template>
<BaseAppShell product="Gestão de Obras" user-name="Marta Coelho" user-role="Fiscal de contrato">
<template #user-menu>
<BaseThemeSwitch size="sm" />
<hr>
<BaseUserMenuItem icon="box-arrow-right" @click="signOut">Sair</BaseUserMenuItem>
</template>
</BaseAppShell>
</template>Propriedades
| Propriedade | Tipo | Padrão | Descrição |
|---|---|---|---|
label | string | 'Tema' | Nome mostrado acima das opções; também é o nome do grupo para o leitor de tela |
size | 'sm' | 'md' | 'lg' | 'md' | Altura das opções |
Não há eventos nem slots. A escolha chega ao resto do app pelo evento ds-themechange do document (THEME_CHANGE_EVENT), com o tema aplicado e a escolha.
Acessibilidade
- Segue o padrão Radio Group do WAI-ARIA APG, pelo
BaseSegmented: umrole="radiogroup"com o nome delabele trêsrole="radio"comaria-checked. - O nome visível fica escondido do leitor de tela, porque o grupo já tem o mesmo texto como nome. Assim "Tema" não é lido duas vezes.
- A opção escolhida não depende só da cor: fica elevada, com contorno e em negrito.
- No alto contraste do Windows (
forced-colors), a escolhida ganha bordaHighlighte o foco, contornoCanvasText. Isso foi conferido só na emulação do alto contraste do Chromium. Falta o teste num Windows com o alto contraste ligado. - O nível seguido é o WCAG 2.2, nível AA. O eMAG 3.1 (consultado em 05/11/2026), na seção 4, dos elementos padronizados do Governo Federal, pede uma opção de alto contraste com pelo menos 7:1 entre o fundo e o primeiro plano (item 4.2). Falta confirmar com a STIC se isso vale para os sistemas do TJES.
- Teclado:
| Tecla | O que faz |
|---|---|
| Tab | Entra no grupo pela opção escolhida e sai dele na próxima vez |
| → ↓ | Vai à próxima opção e troca o tema; da última, volta à primeira |
| ← ↑ | Vai à opção anterior e troca o tema; da primeira, vai à última |
| Home End | Vai à primeira ou à última opção e troca o tema |
| Espaço Enter | Escolhe a opção em foco |
- Testes no navegador, em 05/11/2026, na página gerada desta documentação, no Chromium e no WebKit como iPhone e iPad (
e2e/theme-switch.spec.ts): o teclado troca o tema; com "Seguir sistema", a página acompanha o sistema operacional quando ele troca de claro para escuro com a página aberta; com "Escuro", ela não acompanha quando o sistema troca para escuro e volta para claro; a escolha continua depois de recarregar a página. Só no Chromium, porque a chave de tema do site fica no alto da página a partir de 1280 px: a chave guarda a escolha e o seletor passa a mostrá-la. - Os testes em jsdom passam o axe com cada opção escolhida e dentro do menu da pessoa. O axe roda sem layout, então o contraste das cores é medido no
tests/contrast.test.ts, nos dois temas, pelos pares doBaseSegmented.