larperCord Me pague um café no ko-fi.com English

Escrevendo temas

Um tema do larperCord é um arquivo KDL que descreve a interface inteira: cores, fontes, estilos e a árvore de layout. Dá pra mudar a posição de tudo sem escrever uma linha de código.

Coloque o arquivo em ~/.config/larpercord/themes/meu-tema.kdl (ou em themes/, ao rodar de dentro do repositório). Ao salvar, o app recarrega na hora. Se houver um erro, aparece um aviso com arquivo:linha:coluna e o tema anterior continua valendo.

Troque de tema com F2, pela paleta (Ctrl+K → "tema: …") ou em Configurações → Aparência.

Exemplo mínimo

kdl
theme "meu-tema" description="Servidores embaixo, chat em cima." preview=classic
palette "wal"                      // usa as cores do pywal (opcional)

colors {
    accent "wal:4"
    surface "mix(wal:0, black, 0.2)"
}

layout {
    column {
        row flex=1 {
            channel-list width=240 bg=sidebar
            column flex=1 {
                messages flex=1
                composer height=46 inset-x=16 inset-y=4
            }
        }
        guild-bar height=60 orientation=horizontal
    }
}

Nós de topo

NóO que faz
theme "nome" description=… author=… preview=…metadados. preview escolhe a miniatura nas configurações: classic, glass, terminal, bubbles, zen, mirror, office, desktop
palette "wal" ou palette "#hex" …as 16 cores base (wal:0 … wal:15). Sem isso, usa uma paleta padrão
colors { token "expressão" … }sobrescreve tokens de cor (lista abaixo)
roles "cor" …até 8 cores de cargo (nomes de usuário, ícones de servidor)
fonts ui="Inter" mono="JetBrains Mono" size=16famílias (resolvidas pelo fontconfig) e tamanho base
metrics radius=6arredondamento padrão de linhas e botões
window transparent=#truefundo da janela transparente: o compositor aplica blur
styles { style "nome" … }estilos nomeados para usar com style=nome
layout { … }a árvore da interface (um único filho na raiz)

Cores

Expressões aceitas em qualquer lugar que pede cor:

"#df68ad"   "#df68ad80"   "#fff"   "#fff8"
"wal:4"                    cor da paleta
"@surface"                 outro token (já definido)
"mix(a, b, 0.3)"           mistura
"alpha(a, 0.5)"            transparência
"lighten(a, 0.1)"  "darken(a, 0.2)"
white  black  transparent

Tokens: bg rail sidebar surface elevated overlay text muted faint accent accent-text border hover selected online idle dnd danger mention link code-bg bubble-self bubble-self-text bubble-other shadow.

Estilos

kdl
styles {
    style "card" bg="@surface" radius=18 border="@border" border-width=1.5 glow="@accent" shadow=16
}

glow é a cor da borda quando o mouse está em cima. shadow é o tamanho da sombra. Para um fundo simples, sem estilo nomeado, use direto no nó: bg=sidebar radius=12 (bg no nó também aceita expressão: bg="alpha(@accent, 0.4)").

Além disso, estilos e nós do layout podem ter as primitivas da seção Além do retângulo chapado: gradiente, padrão, grão, vinheta, sombra interna, borda por lado.

Layout

Contêineres: row (horizontal), column (vertical), stack (um sobre o outro).

PropriedadeEfeito
width= / height=tamanho fixo no eixo do pai
flex=peso no espaço que sobra (padrão 1)
gap= padding= padding-x= padding-y=espaçamentos (contêineres)
inset-x= inset-y=margem interna de um componente
max-width=limita a largura e centraliza
hide-below=esconde quando a janela é mais estreita que isso
show=#falseesconde
style= / bg= radius=fundo do nó
font=mono / font=ui / font="Liberation Serif"fonte do componente: a mono, a da interface ou qualquer família instalada
c-<token>=corsobrescreve um token de cor neste nó e nos filhos (ex.: c-text="#fff" numa barra lateral escura)

O filho de uma row que tem width= fixo e contém channel-list ou member-list é ajustável: o app desenha uma alça de arrastar do lado que dá para o vizinho flex da row, e a largura escolhida pela pessoa soma com a que você definiu. Sem vizinho flex, não tem alça.

Componentes

ComponentePropriedades
guild-barvariant=bar|dock|list icon-style=fill|soft|outline orientation=vertical|horizontal shape=circle|squircle|square|text size=48 labels=#true home=#false indicators=#false
channel-listvariant=discord|tree|pills header=#false
user-panelvariant=discord|tty
headervariant=discord|minimal|tty divider=#false
tabsvariant=pills|underline|tty
messagesvariant=cozy|irc|bubbles avatar=circle|squircle|square|none avatar-size=40 spacing=16 font-size=
composervariant=box|pill|prompt typing=#false
member-listvariant=discord|tty
status-barvariant=pills|tty|plain items="conn ping ram frame voice spacer theme keys clock"
labeltext= size= weight=regular|medium|semibold|bold color=token align=left|center|right, mais tipografia de display
shapecírculo, anel, arco, retângulo arredondado, linha (detalhes)
rulerégua lisa, tracejada, dupla, de jornal, com ornamento (detalhes)
starfield orbit aurora dunes topography radarfundos procedurais (primeiro filho de um stack)
window-controlsos três botões da janela, que funcionam de verdade: fechar, minimizar, maximizar. size=12 gap=8 color= color2= color3= align=
logovariant=ascii|wordmark size=
topbarbarra superior (abas, busca, ajuda)
crtspacing=3 strength=0.08
spacerespaço vazio

Um nome que não existe aparece com uma borda vermelha e a linha do arquivo, pra facilitar.

Além do retângulo chapado

Tudo aqui é opcional, vale num style "…" ou direto num nó do layout, e as cores são expressões ("alpha(@accent, 0.4)", ou só o nome do token). Elas são avaliadas com os tokens do momento, então acompanham o modo claro/escuro, a cor de destaque escolhida e os c-… do pedaço do layout.

kdl
styles {
    style "painel" radius=10 \
        gradient="alpha(@elevated, 0.9) alpha(@surface, 0.75)" gradient-angle=90 \
        pattern=dots pattern-color="alpha(@text, 0.05)" pattern-size=16 pattern-width=1 \
        grain="alpha(@text, 0.04)" vignette="alpha(black, 0.3)" vignette-size=0.55 \
        inner-shadow="alpha(black, 0.2)" inner-shadow-size=14 \
        border-gradient="@accent transparent @border" border-gradient-angle=70 border-width=1 \
        border-bottom="@border" border-bottom-width=2 \
        hover-bg="alpha(@accent, 0.05)"
}
layout { column gradient="@bg @rail" grain="alpha(@text, 0.05)" { … } }
PropriedadeO que faz
gradient="a b" ou "a b c"gradiente de 2 ou 3 cores (separadas por espaço)
gradient-angle=90graus: 0 da esquerda para a direita, 90 de cima para baixo (padrão)
pattern=dots|lines|grid|diagonalpadrão repetido; pede pattern-color
pattern-size=16 pattern-width=1distância entre repetições e espessura do traço (ou raio do ponto)
grain=corgrão: ruído fino, tingido por essa cor
vignette=cor vignette-size=0.55escurece (ou tinge) as bordas; size é onde começa, de 0 (centro) a 1 (cantos)
inner-shadow=cor inner-shadow-size=14sombra para dentro
border-gradient="a b c" border-gradient-angle= border-width=borda em gradiente
border-top=cor border-right= border-bottom= border-left=borda só naquele lado
border-top-width=2 (idem para os outros lados)espessura daquele lado (padrão: border-width, ou 1)
hover-bg=corfundo por cima quando o mouse está em cima, com transição
drop-shadow=cor drop-shadow-size=32 drop-shadow-y=10sombra macia e oca: não escurece o que está embaixo de um painel translúcido (o shadow= antigo escurece)
corners=left|right|top|bottomquais cantos o preenchimento arredonda: uma janela de dois painéis lado a lado
border=corborda inteira, para usar direto num nó (nos estilos, ela já existe)

Custo: gradiente de 2 cores são só vértices. Grão, padrão, vinheta e gradiente de 3 cores são texturas minúsculas geradas uma vez e repetidas: um quad por quadro, nada de ruído recalculado. Tema que não usa nada disso não passa por esse código.

Grão muito forte no escuro atrapalha mais do que no claro. Quando o valor precisa mudar com o modo, use estilos separados: styles mode=light { style "pagina" grain="alpha(@text, 0.07)" } e styles mode=dark { style "pagina" grain="alpha(@text, 0.025)" }. Um nó também pode aparecer só num modo: when=modo-claro, when=modo-escuro.

Tipografia de display no label

kdl
// Tracking de verdade: nada de "O R B I T A L" com espaços.
label text="ORBITAL" tracking=8 size=15 weight=bold font=mono

// Runs: cor, peso, tamanho e fonte diferentes na mesma linha, na mesma linha de base.
label height=38 size=9 color=muted font=mono span-gap=9 {
    span "01" size=18 color=accent
    span "CANAIS" en="CHANNELS" tracking=3
}

// Efeitos.
label text="larperCord" size=40 shadow="alpha(black, 0.5)" shadow-x=2 shadow-y=2
label text="larperCord" size=40 shadow="alpha(@accent, 0.4)" shadow-blur=3   // brilho
label text="larperCord" size=40 color=bg outline=accent outline-width=2
label text="larperCord" size=40 text-gradient="@text @accent" text-gradient-angle=0
PropriedadeO que faz
tracking=espaço extra entre as letras, em pixels (pode ser negativo)
color=também aceita expressão: color="alpha(@text, 0.7)"
text-en= (en= no span)versão em inglês do texto
span "texto"um pedaço da linha; size weight color font tracking herdam do label
span-gap=espaço entre os spans
shadow=cor shadow-x= shadow-y= shadow-blur=sombra; com blur vira um halo macio
outline=cor outline-width=contorno
text-gradient="a b" text-gradient-angle=gradiente no texto (padrão: horizontal)

O label sem nada disso continua igual e no mesmo caminho de sempre. Efeitos desenham o texto mais vezes: guarde para títulos e wordmarks.

shape e rule

Formas e réguas desenhadas de verdade, em vez de caracteres Unicode. Empilhe num stack para compor.

kdl
stack width=28 {
    shape kind=ring size=22 thickness=1 color="alpha(@accent, 0.35)"
    shape kind=arc size=22 thickness=1.6 start=-150 sweep=250 color=accent dot="@text" dot-size=2.4
    shape kind=circle size=6 color=accent
}
shape kind=rounded radius=6 color=accent fill="alpha(@accent, 0.1)" thickness=1
shape kind=line angle=30 thickness=2 color=border

rule height=1 color=border
rule height=1 kind=dashed dash=3 gap=3 color="alpha(@accent, 0.45)"
rule height=7 kind=oxford color=text                                 // fio grosso sobre fio fino
rule height=11 kind=double color=text ornament=star ornament-color=accent ornament-size=11
rule height=20 ornament-text="§" ornament-size=16 font="Liberation Serif"
rule width=1 vertical=#true color=border
rule height=1 fade=#true color=accent                                // some nas pontas
shape
kind=circle ring arc rounded line
color= thickness=cor e espessura do traço
size=diâmetro (padrão: o menor lado do nó); em line, o comprimento
fill=preenchimento de ring e rounded
start= sweep=início e abertura do arc, em graus
dot=cor dot-size=um ponto na ponta do arc
radius=cantos do rounded
angle=inclinação da line, em graus
align=left|center|right offset-x= offset-y=posição dentro do nó
rule
kind=solid dashed dotted double oxford
color= thickness=cor e espessura
dash= gap=tamanho do traço e do vão em dashed
vertical=#truede cima para baixo (dê um width= ao nó)
fade=#truesome nas duas pontas
ornament=diamond dot ring star, no meio da régua
ornament-text=um caractere no meio, em vez da forma (usa o font= do nó)
ornament-color= ornament-size= ornament-gap=cor, tamanho e o vão da régua em volta

Fundos procedurais

Vão como primeiro filho de um stack, atrás de todo o resto. São parados por padrão: gerados uma vez, ficam numa textura, e um tema parado não acorda o app.

kdl
layout {
    stack {
        starfield color="alpha(@muted, 0.75)" color2="alpha(@accent, 0.8)" density=1.1
        orbit center-x=0.73 center-y=0.4 rings=7 color="alpha(@accent, 0.4)" color2=accent
        column { … painéis … }
    }
}
ComponenteCoresPropriedades
starfieldcolor estrelas de longe, color2 as de pertodensity=1
orbitcolor as órbitas, color2 as luascenter-x=0.7 center-y=0.35 rings=6
auroracolor e color2, uma para cada cortina
dunescolor, color2, color3: colinas de trás para a frente (o céu é o gradient do nó em volta)
topographycolorlevels=14 (quantas curvas de nível)
radarcolor anéis, color2 a varreduracenter-x=0.5 center-y=0.5 rings=5

Todos aceitam seed= (outro desenho), e todos menos topography aceitam movimento: motion=#true, ou melhor motion="$opcao", para o usuário escolher, e motion-fps=10 (no máximo 15). O movimento só desloca a textura ou redesenha uma peça pequena, e para sozinho com "Reduzir movimento" e com a janela minimizada ou fora de foco.

A máscara é só forma: a cor vem na hora de desenhar. Trocar de modo ou de cor de destaque não gera nada de novo. Só orbit e radar dependem do tamanho, e são refeitos uma vez quando a janela para de mudar.

Contraste primeiro. Texto nunca fica direto sobre um fundo forte: ponha um painel translúcido no meio (gradient="alpha(@surface, 0.9) alpha(@surface, 0.76)") e confira nos dois modos. Use cores derivadas de tokens: @muted no escuro são estrelas claras, e no claro viram tinta sobre papel.

Claro e escuro

Todo tema tem as duas versões. Blocos com mode= só valem num dos modos:

kdl
colors mode=dark  { bg "#0b0906"; text "#ffcf73" }
colors mode=light { bg "#f4efe2"; text "#2e2412" }
roles mode=light "#7a4a00" "#9c3f10"

Sem mode=, o bloco vale nos dois. Se o tema não definir o claro, ele é derivado da paleta (papel quase branco, tinta escura e destaque escurecido). No layout, cl-<token> e cd-<token> sobrescrevem uma cor só no claro ou só no escuro. O usuário escolhe em Configurações → Aparência (Escuro / Claro / Seguir o sistema), ou pela linha de comando: --mode claro.

Opções do tema

Um tema pode oferecer chaves de liga/desliga, que aparecem em Configurações → Aparência:

kdl
options {
    option "crt" label="Efeito CRT" description="Linhas de varredura…" default=#true
    option "verde" label="Fósforo verde" default=#false
}

Formas de usar as opções:

OndeComo
esconder/mostrar um nócrt when=crt, tabs unless=compacto
propriedade booleanabanner="$banner", typing="$!digitando" (o ! inverte)
bloco de cores, cargos, estiloscolors mode=dark when=verde { … }
estilostyle "card" sheen="$brilho"

As escolhas ficam salvas por tema em ~/.config/larpercord/settings.kdl.

Cores personalizadas (sem editar o .kdl)

Em Configurações → Aparência → Cores do tema você pode trocar qualquer token de cor (bg, sidebar, text, accent, link, bubble-self…) e as oito cores de cargo por um hex livre. Vale só para o tema atual e o modo atual (escuro ou claro), e tem prioridade sobre a “Cor de destaque” global.

Em inglês

A interface tem português e inglês. Para o seu tema aparecer bem nos dois, ponha a versão em inglês ao lado: label-en= e description-en= nas opções, e description-en= no nó theme. Sem elas, aparece o texto em português.

kdl
theme "meu-tema" description="Servidores embaixo." description-en="Servers at the bottom."
options {
    option "crt" label="Efeito CRT" label-en="CRT effect" description="Linhas de varredura" description-en="Scanlines"
}

Recursos exclusivos

Componente / propriedadeO que fazUsado em
channel-list banner=#truebanner colorido com o nome do servidorclassico
style … sheen=#truereflexo de vidro no topo do cartãovidro
crtlinhas de varredura + vinheta, por cima de tudo (use num stack)terminal, subsolo
logo variant=ascii|wordmarklogo do app em ASCII ou em textoterminal, subsolo, escritorio
messages ruled=#true margin-line=#truefolha pautada e margem vermelhapapel
messages ticks=#true typing-bubble=#true"Entregue ✓✓" e balão de digitandobolhas
autohide=#true (qualquer nó)o componente some até o mouse chegar pertozen
guild-bar variant=bar orientation=horizontalfaixa horizontal de servidores no rodapé, sem zoom nos íconesorbital
topbarvoltar/avançar entre abas, busca e ajudaescritorio, editorial (opcional no orbital)
starfield orbit, wordmark com tracking, painéis translúcidosconsole no meio das estrelas; no claro, carta celesteorbital
grain, rule kind=oxford, label com spanpapel com grão, masthead, fios de jornaleditorial
aurora, border-gradient, grainluz por trás do vidro foscovidro
pattern=grid, radar, topographyretícula de osciloscópio; radar e mapa opcionaisterminal
dunes, window-controls, corners, drop-shadow, guild-bar variant=dockmesa de trabalho com janela flutuante, barra lateral translúcida e Dockcupertino
topography, pattern=diagonal, shadow-xmapa de túneis, fita de perigo, letreiro com aberração cromáticasubsolo
shape kind=arc, topography, grainenso e areia rasteladazen
shape kind=ring, pattern=dots, rule kind=oxford, ornament-textfuros de fichário, página pontilhada, índicepapel
aurora, pattern=dots, drop-shadowcartões flutuando sobre um fundo coloridobolhas

Os temas que vêm junto

Os testes (zig build test) carregam todos os temas embutidos e montam o layout de cada um. Se você mandar um tema novo num pull request, ele é verificado automaticamente.

Dicas de design

O que separa um tema bonito de um tema estranho quase nunca é a cor de destaque. Normalmente é:

Fonte desta página no GitHub