Vitral 0.2
Personalização

Direção do texto

Da esquerda para a direita, a menos que você diga o contrário: um atributo vira de uma vez o layout, o teclado e os ícones que querem dizer “próximo”.

Árabe, hebraico, persa e urdu se leem da direita para a esquerda, e o mesmo vale para tudo o que é diagramado para eles: a barra lateral começa à direita, um chevron que quer dizer “próximo” aponta para a esquerda e a seta para a direita anda para trás. O Vitral é da esquerda para a direita por padrão e se vira com um atributo, porque o navegador já sabe fazer quase tudo isso.

Defina dir

index.html
<html lang="ar" dir="rtl">

Isso é todo o layout. Todas as folhas de estilos da biblioteca são escritas em propriedades lógicas — padding-inline-start, inset-inline-end, border-inline-start — então as caixas, os paddings, as bordas e os cantos seguem o dir sem uma segunda folha de estilos para distribuir nem uma etapa de build para rodar. Não existe vitral.rtl.css, e não há nada para manter em sincronia.

Defina-o no elemento em que a aplicação é montada, e não apenas a propriedade CSS direction: o dir é o que os componentes medem para descobrir qual seta anda para a frente, e é por ele que os ícones se orientam.

Informe a configuração também

main.ts
import { Vitral } from '@vitral/vue';

createApp(App).use(Vitral, { direction: 'rtl' });

Um popup é teleportado para o <body>, fora de qualquer dir que a sua aplicação tenha, então abriria do lado errado. A biblioteca dá a cada um a direção daquilo a que ele pertence, e recorre a esta configuração para os que pertencem à página e não a uma âncora — um diálogo, um toast. É também o que o servidor assume, onde não há layout para medir.

nuxt.config.ts
export default defineNuxtConfig({
    modules: ['@vitral/nuxt'],
    vitral: { direction: 'rtl', locale: 'ar' }
});

No Nuxt, o módulo coloca o dir no <html> durante a renderização, então a página já chega do lado certo em vez de se virar na hidratação.

Parte de uma página

Uma direção não é uma decisão da aplicação inteira; é uma propriedade de um trecho de texto. Aninhe-a onde ela pertence:

template
<!-- One panel the other way round, inside a left-to-right page. -->
<div dir="rtl">
    <Menubar :model="items" />
    <DataGrid :value="rows" />
</div>

Os componentes leem a direção em que de fato estão diagramados, então um painel da direita para a esquerda dentro de uma página da esquerda para a direita se comporta bem, teclado incluído.

O teclado

Lendo da direita para a esquerda, a esquerda é para a frente. Todo componente que se move com as setas já sabe disso: as abas, os menus, a menubar, a toolbar, o stepper, o rating, o splitter, o carrossel, o quadro de tarefas, a agenda e os gráficos trocam Esquerda por Direita, e um deslizar de dedo inverte junto. Os overlays também se invertem — um menu que abre para o fim do seu gatilho abre para a esquerda.

Ícones

Um ícone que indica uma direção tem de se virar; um ícone que indica um lado não pode. chevronRight num botão “próximo” indica o sentido em que o leitor avança, então é espelhado; alignLeft indica a esquerda do parágrafo em qualquer idioma, então não é. O conjunto responde por si, e você pode discordar dele:

template
<!-- Ours know: a chevron that means "next" turns round, alignLeft does not. -->
<Button icon="chevronRight" label="Next" />

<!-- An icon from somewhere else cannot be asked, so tell it. -->
<Icon :icon="ArrowRightIcon" mirrored />

<!-- Or disagree about one of ours. -->
<Icon icon="undo" :mirrored="false" />

Os controles de mídia (play, rewind, fastForward) ficam de fora de propósito, porque uma linha do tempo corre da esquerda para a direita em todo lugar, e o mesmo vale para a rotação, que ou é no sentido horário ou não é. Um ícone seu diz qual é o caso:

icons.ts
import { registerIcons } from '@vitral/icons';

registerIcons([{ name: 'nextStage', body: '<path d="M4 12h16M14 6l6 6-6 6"/>', mirrored: true }]);

A inversão é CSS guiado pelo dir, não script: não custa nada, é igual no servidor e acompanha um dir alterado em tempo de execução sem que nada renderize de novo. renderSvg(def, {}, { direction: 'rtl' }) faz o mesmo para um ícone desenhado fora de um componente.

Em tempo de execução

ts
const { direction, isRtl, setDirection } = useDirection();

setDirection('rtl');
document.documentElement.dir = 'rtl';   // the layout follows this one

useDirection() é o handle reativo: a direção configurada, se ela é da direita para a esquerda, e um setter que todo componente segue — o mesmo formato do useLocale(), que você normalmente vai mudar no mesmo momento. Mover o layout continua sendo trabalho do atributo dir.