Primeiros passos
O Lyra vem em dois pacotes. O @lyra-ds/styles carrega toda a aparência — tokens e classes
.lyra-*, sem build. O @lyra-ds/react é um wrapper fino sobre essas classes. Você pode
usar só o CSS; o pacote React é conveniência, não requisito.
Instalação
Escolha a stack em que você está construindo. As três instalam @lyra-ds/styles, porque é lá que a
aparência vive — e em nenhum outro lugar.
npm i @lyra-ds/react @lyra-ds/stylesnpm i @lyra-ds/styles alpinejs @lyra-ds/alpineRegistre o plugin antes de iniciar o Alpine, uma vez só, no entry da aplicação:
import Alpine from 'alpinejs';
import lyra from '@lyra-ds/alpine';
Alpine.plugin(lyra);
Alpine.start();composer require lyra-ds/blade
npm i @lyra-ds/styles alpinejs @lyra-ds/alpineO Laravel descobre o service provider sozinho, então os componentes já funcionam nas duas sintaxes:
<lyra:button variant="primary">Salvar</lyra:button>Os 29 componentes interativos emitem x-data, então registre o plugin do Alpine exatamente como na
aba HTML + Alpine. Ponha o @lyraThemeScript no <head> do documento, antes das folhas de estilo.
As fontes são peer dependencies em qualquer stack, então você as instala e controla como elas carregam:
npm i @fontsource/plus-jakarta-sans @fontsource/jetbrains-monoImporte o CSS uma única vez
Um import, na raiz do app. Todo o resto é classe.
// entrada do app (main.tsx / layout.tsx)
import '@lyra-ds/styles/styles.css';Importe uma vez e só uma. É uma folha de estilos comum, então importar em vários módulos só entrega as mesmas regras repetidas.
Seu primeiro componente
import { Button } from '@lyra-ds/react';
export function App() {
return <Button>Olá, Lyra</Button>;
}Tema escuro
Defina data-theme="dark" no elemento <html>. Todos os tokens semânticos respondem — não
há trabalho por componente nem provider de tema para ligar.
<html data-theme="dark"></html>Para seguir a preferência do sistema sem piscar o tema errado, defina o atributo antes da primeira pintura, num script inline e bloqueante:
<script>
const stored = localStorage.getItem('theme');
const dark = stored ? stored === 'dark' : matchMedia('(prefers-color-scheme: dark)').matches;
document.documentElement.dataset.theme = dark ? 'dark' : 'light';
</script>Ele precisa ser inline e bloqueante. Qualquer coisa adiada roda depois da primeira pintura, que é exatamente o piscar que você quer evitar.
Por onde seguir
Cada componente tem página própria, com exemplos vivos, tabela de props gerada e o HTML puro por trás. Comece pelo índice de componentes, ou leia Button para ver o formato que todas as páginas seguem.