O que milda faz?
Milda é um compilador com interface gráfica para sistemas de design. Um arquivo .milda é o sistema de design: fundamentos (tokens), componentes, regras de uso, documentação e assets. Pacotes React, bibliotecas Figma, sites de documentação e arquivos legíveis por agentes são gerados a partir dele. Você nunca edita uma saída; você altera o arquivo e regenera.
Esta habilidade tem como alvo a superfície de linguagem 0.10 com prelúdio 0.0.2. Cada arquivo que você escrever começa com esse cabeçalho.
O ciclo: escrever, verificar, corrigir
Nunca diga ao usuário que um arquivo .milda é válido até que o leitor confirme. Após cada edição, execute:
npx -y -p @mildastudio/milda-lsp milda-check --strict caminho/para/sistema/
Forneça o diretório, ou todos os arquivos do sistema juntos, porque tokens declarados em um arquivo resolvem referências em outro. Ele imprime caminho:linha:col severidade [código] mensagem, os mesmos diagnósticos que as extensões do editor mostram, e sai com código diferente de zero em caso de erro (ou, com --strict, qualquer aviso). Corrija o que ele reportar e execute novamente até que diga 0 erros, 0 avisos. Um aviso não é ruído: faceta desconhecida "background" ignorada significa que aquela linha não fez nada.
Para mostrar o resultado ao usuário, o playground em https://play.milda.dev renderiza um arquivo colado ao vivo, sem necessidade de conta.
Pensar em Milda: dez regras
A maioria dos erros vem de escrever CSS, uma árvore DOM ou um componente React na sintaxe de Milda. Estas regras são o que a sintaxe existe para expressar.
- O sistema é a fonte; o código é uma saída. Tudo que tem forma de plataforma é decidido no momento da geração, então um arquivo nunca contém uma propriedade CSS, uma tag, um nome de evento de um framework ou uma pseudo-classe.
- Diga o que uma coisa é, nunca do que ela é feita. Uma parte tem um tipo neutro (
container,text,input,icon,control, ...), nuncadivoubutton. Cada destino escolhe seu próprio elemento. - Um valor tem um nome, e o nome tem uma camada. Componentes nunca pintam com literais. Uma faceta aponta para um token; uma camada
Semanticcria um alias para uma camadaBasede literais. Uma reformulação é uma alteração nos fundamentos. - Contexto é uma dimensão, não uma cópia. Modo escuro, densidade, marca: cada um é um
context-group, e um token responde por contexto comalias by Group { ... }. Uma propriedade tipada por um grupo de contexto (umavariant) usa o mesmo mecanismo por instância. - Um estado vem de um comportamento.
hovered,pressed,focus-visible,disabled,open,selectedsão emitidos pelos comportamentos do arquétipo. Estilize-os comstate hovered { }, nunca com algo específico de ponteiro ou plataforma. A lista é fechada (reference/vocabulary.md), e o leitor avisa sobre qualquer outra palavra:state hoveré reportado com a grafia que ele pretendia. - O contrato é a identidade.
propseeventssão contra o que os consumidores programam e o que as diferenças de versionamento usam. Nomeie-os pelo significado (variant,checkedChange), não por uma plataforma. - Construa a partir do que existe. Comece um componente a partir de um
archetypeno prelúdio: ele traz a forma do contrato, as partes necessárias e os comportamentos (teclado, ARIA, foco). Componha componentes maiores a partir de menores com partesinstance. - Toda referência é por nome. Partes por caminho pontuado (
Header.Title), tokens por caminho (space.smparaspace/sm), componentes por identificador. Sem IDs. Comentários (#) são a única coisa que não sobrevive a uma ida e volta. - Estenda através de pontos de extensão, nunca remendando a saída. Quando o vocabulário não puder dizer algo, use um
slot, uma opção por destino ou, como último recurso, conteúdoforeignmarcado com seu destino. Nunca sugira editar código gerado. - Diga como deve ser usado. Coloque restrições de interface (
required,required when,one-of) emprops, e regras de composição (rule ... { never X within Y }) no nível superior, cada uma com sua justificativa.
Um arquivo, de cima a baixo
milda 0.10
prelude 0.0.2
meta { name "Acme" }
context-group ColorScheme { Light Dark }
foundations {
layer Base {
token violet/600 : color = hex(7c3aed)
token white : color = hex(ffffff)
token gray/900 : color = hex(0f172a)
}
layer Semantic {
token accent : color = alias by ColorScheme { default -> violet.600 }
token on-accent : color = alias by ColorScheme { default -> white; Dark -> gray.900 }
token space/sm : spacing = 8px
token radius/sm : radius = 6px
}
}
component Button "A ação primária." {
archetype Button
props {
label : string = "Get started"
}
events {
click
}
part Button: container {
emits { click on activate }
layout { stack row; gap space.sm; align center }
fill accent
ink on-accent
corner radius.sm
inset space.sm
state focus-visible {
ring accent
}
}
part label: text {
content bind label
}
}
Ordem: cabeçalho, meta, context-groups, groups (seções da biblioteca), foundations, types, components, rules, depois examples, assets, icons, docs. A parte raiz recebe o nome do componente; outras partes são nomeadas pela anatomia do arquétipo (label, icon, control, ...) ou por você, aninhadas com caminhos pontuados.
De CSS e React para Milda
| Você escreveria | Milda diz |
|---|---|
<div>, <span>, <button> | part X: container / text / a raiz do arquétipo |
background | fill |
color | ink |
padding, padding-inline-start | inset, inset.inline-start |
margin | nada: gap no pai, alinhamento, ou bleed |
border, border-radius | border <color> <width>, corner |
box-shadow, outline (foco) | elevation, ring |
font-size + line-height, font-weight | text <typography or font-size token>, weight |
display: flex; flex-direction: row | layout { stack row } |
justify-content, align-items, flex: 1 | distribute, align, size fill |
position: absolute | layout { stack layers } + position overlay no filho |
:hover, :focus-visible, :disabled | state hovered { }, state focus-visible { }, ... |
.btn--secondary, [data-variant] | when variant = Secondary { } |
.card:hover .icon | when ancestor Card hovered { } na parte do ícone |
@media (prefers-color-scheme: dark) | context-group ColorScheme + alias by ColorScheme |
--space-sm: 8px / var(--space-sm) | token space/sm : spacing = 8px / space.sm |
#7c3aed, oklch(...) | hex(7c3aed), oklch(...), apenas dentro de um token |
color-mix(), calc() | compute <token> in oklch { darken 10% } |
prop onClick | events { click } + emits { click on activate } |
{children} | slot of content default na parte que os contém |
{cond && <X/>} | present when <prop> na parte |
z-index, text-align, box-sizing | nada: ordem das partes, o contêiner, existe uma caixa |
Facetas, estados e condições em uma parte
part Panel: container {
layout { stack column; gap space.sm; size fill fit }
fill surface
ink text
border line hairline
corner radius.sm
inset space.sm space.md
when tone = danger {
border danger hairline
}
state hovered {
fill surface-raised
}
state hovered when tone = danger {
fill danger-subtle
}
}
O valor de uma faceta resolve como um token primeiro; um literal simples é aceito apenas onde nenhum token reivindica a palavra (opacity 50, inset 0). Prefira tokens. when chaveia em props, state em estados de comportamento, e os dois se combinam.
Props, eventos e restrições
archetype TextField
props {
label : string required "O que o campo pede. Também seu nome acessível."
value : string
invalid : boolean = false
error : string required when invalid "Mostrado abaixo do controle enquanto inválido."
size : enum(sm, md) = md
tone : context Tone = Neutral
}
events {
valueChange
}
Tipos: string, number, boolean, enum(a, b), context <Group>, array<T>, seus próprios types. Uma string ao final é a documentação da prop. one-of a, b / any-of / exclusive restringem grupos de props.
Onde consultar a seguir
- reference/syntax.md: cada declaração com um exemplo verificado (tokens e valores, layout, slots, instâncias, comportamentos, regras, documentação, assets, ícones).
- reference/vocabulary.md: gerado a partir do pacote da linguagem. Cada tipo de token, tipo de parte, faceta, estado, palavra de layout e função literal que o leitor aceita. Em caso de dúvida sobre uma palavra, consulte aqui em vez de adivinhar.
- reference/archetypes.md: gerado a partir do prelúdio. Cada arquétipo com seu contrato, anatomia (quais partes são necessárias) e comportamentos.
- examples/acme.milda: um sistema completo e limpo para copiar padrões.
- A especificação normativa: https://github.com/mildastudio/milda-lang/tree/main/spec (
FORMAT.mdpara o que um arquivo promete,GRAMMAR.ebnfpara a sintaxe,PRELUDE.mdpara os arquétipos). - Para um sistema de design já publicado, o servidor MCP Milda responde com seus componentes e tokens exatos; veja https://milda.dev/mcp.
Antes de finalizar
- O cabeçalho diz
milda 0.10eprelude 0.0.2. - Nenhum literal de cor, comprimento ou fonte em um componente; todo valor é uma referência a token.
- Nenhuma palavra de plataforma em lugar algum: sem tags, propriedades CSS, pseudo-classes ou nomes de eventos de framework.
- Todo componente começa a partir de um arquétipo, a menos que seja uma composição pura de instâncias.
milda-check --strictem todo o sistema imprime0 erros, 0 avisos.