Kobalte fornece componentes sem interface visual para Solid, incluindo campos numéricos com valores brutos e formatados separados, a anatomia composta de caixas de seleção e botões com estado pressionado. Este guia conecta esses primitivos aos sinais do Solid por meio de um ajustador de receitas com quantidades derivadas e caixas de seleção de ingredientes que podem ser redefinidas.
Kobalte 0.13.14 com Solid 1.9.15; primitivas headless nativas e CSS original completo. · Referência de implementação
02
Referência de design do sistema de design Kobalte
Kobalte 0.13.14 oferece primitivas headless do Solid, mas não uma escala visual canônica. Cada cor e dimensão recipe-* abaixo faz parte da configuração completa original do aplicativo. Os nomes API e os atributos de estado foram verificados no pacote instalado e na documentação oficial dos componentes.
Conecte componentes do sistema de design Kobalte a sinais do Solid Kobalte
Conecte os componentes Kobalte aos Signals do Solid
O componente usa sinais Solid para as porções, os ingredientes separados e a fixação. createMemo deriva a validade do sinal numérico, e For renderiza uma coleção estável de ingredientes. As propriedades controladas de Kobalte leem esses sinais diretamente; as atualizações não exigem um provedor de formulário separado nem um adaptador de estado no estilo de React.
NumberField, Checkbox e ToggleButton são importados dos respectivos pontos de entrada dos componentes. Cada um tem uma função diferente: o campo numérico recebe entradas numéricas editáveis, cada caixa de seleção representa um ingrediente separado, e o botão de alternância controla a fixação da receita. As regras de cálculo e invalidação ficam em funções da aplicação, em vez de serem incorporadas a seletores visuais.
Sistema de design Kobalte: mantenha o estado numérico separado do texto formatado
Mantenha o estado numérico separado do texto formatado
NumberField recebe rawValue={portions()} e onRawValueChange={update}. O sinal numérico direciona a multiplicação, enquanto o campo lida com a formatação e a edição pelo usuário. Usar texto de exibição formatado nos cálculos introduziria suposições sobre separadores ou localidade que a primitiva nativa já resolve.
O exemplo permite de uma a oito porções inteiras, com incremento de uma unidade e maximumFractionDigits definido como zero. Um predicado calculado à parte ainda verifica se o valor é finito, inteiro e está dentro dos limites, pois um campo editável pode conter temporariamente um valor incompleto ou inválido. Enquanto o valor for inválido, os totais exibem um travessão e as caixas de seleção dos ingredientes ficam desativadas. A interface não apresenta uma quantidade plausível, mas incorreta, como se o usuário tivesse informado um valor válido.
Sistema de design Kobalte: componha o campo com seu rótulo e suas mensagens nativos
Componha o campo com seu rótulo e suas mensagens nativos
O campo numérico contém Label, DecrementTrigger, Input, IncrementTrigger, Description e ErrorMessage. A descrição visível explica tanto o intervalo permitido quanto o efeito da alteração das porções. Os disparadores têm rótulos claros — Menos porções e Mais porções —, para que os sinais de menos e mais não precisem, sozinhos, transmitir todo o nome acessível.
validationState alterna entre válido e inválido conforme o predicado da aplicação. ErrorMessage pertence a esse campo nativo, e não a um parágrafo sem relação inserido em outro lugar da página. Em um formulário enviado, Kobalte também oferece um HiddenInput para serializar o valor bruto; este exemplo local não o inclui porque não tem um endpoint de envio nem um payload de formulário.
Sistema de design Kobalte: mantenha a seleção de ingredientes em um Set imutável
Mantenha a seleção de ingredientes em um conjunto imutável
Cada ingrediente usa a estrutura completa de Checkbox: Input, Control, Indicator e Label. O input real preserva a semântica e a interação pelo teclado, enquanto o controle visível recebe a marca de seleção e os estilos originais dos estados. O rótulo inclui tanto o nome do ingrediente quanto a quantidade, tornando-a parte do item que a pessoa está reunindo.
mark cria um novo Set a partir da seleção anterior antes de adicionar ou remover um ID. Alterar apenas o Set existente não produziria uma atualização do sinal igualmente confiável. A contagem exibida lê o tamanho do Set, e cada Checkbox verifica a seleção por ID estável do ingrediente. Uma alteração na quantidade limpa toda a seleção, pois reunir 320 gramas não comprova que o novo requisito de 400 gramas foi atendido.
Associe cada nome de ingrediente visível a Checkbox.Label.
Mantenha Checkbox.Input mesmo quando o quadrado visível tiver um estilo personalizado.
Use IDs estáveis para a seleção e crie um novo Set a cada atualização.
Sistema de design Kobalte: use um botão de alternância para uma escolha local persistente
Use um botão de alternância para uma escolha local persistente
A fixação é controlada por um ToggleButton com pressed e onChange, não por um botão comum que apenas altera a legenda. O estado pressed é refletido na semântica nativa e no seletor data-pressed. O rótulo muda para Fixada com uma marca de seleção, e o status próximo explica que isso afeta apenas a prévia local.
Fixar a receita não altera as quantidades nem a seleção dos ingredientes. Alterar as porções limpa as seleções de ingredientes, mas mantém a fixação, pois a identidade da receita não mudou. Restaurar a receita padrão redefine juntos os três aspectos do modelo: quatro porções, um Set de ingredientes vazio e a fixação desativada. Esses limites diferentes de redefinição refletem o significado de cada estado, em vez de limpar tudo a cada interação.
Sistema de design Kobalte: defina uma configuração visual reproduzível para controles sem estilo
Defina uma configuração visual reproduzível para controles headless
A folha de estilos da receita separa a superfície de edição do campo numérico, os disparadores de incremento e decremento e a função de seleção das caixas de seleção. O texto atenuado dos ingredientes só é aplicado depois da seleção; as quantidades permanecem legíveis para que a pessoa ainda possa comparar o que reuniu com a quantidade atual de porções.
O espaçamento usa quatro, oito, doze, dezesseis, vinte e quatro e trinta e dois pixels. A hierarquia tipográfica original combina uma fonte sem serifa do sistema para os controles com Georgia no título da receita. Uma caixa de seleção visual de vinte e um pixels aparece ao lado de um rótulo associado completo; o rótulo continua sendo a área de ativação mais prática. Esses valores exatos estão incluídos no CSS completo para que seja possível reproduzir o exemplo sem precisar deduzi-los de uma captura de tela.
Sistema de design Kobalte: permita que a composição se ajuste sem ocultar informações
Permita que a composição se ajuste sem ocultar informações
O layout amplo combina um cartão de receita flexível com um painel de porções de 280 pixels. Em 760 pixels, os elementos passam para uma única coluna. O título do cartão pode ocupar mais de uma linha, os rótulos dos ingredientes podem quebrar linha e a quantidade permanece compacta, sem quebra. No menor ponto de interrupção, o espaçamento interno do painel e o tamanho da fonte dos rótulos diminuem ligeiramente, em vez de ocultar as quantidades.
A ilustração da salada é original CSS e está marcada como decorativa. O nome da receita, a quantidade de porções e as quantidades dos ingredientes transmitem o significado independentemente da imagem. Ao alterar a ilustração ou estreitar o cartão, mantenha os rótulos completos dos ingredientes e suas quantidades; são eles que orientam a tarefa de reunir os itens.
Sistema de design Kobalte: trate alterações nas quantidades como atualizações de estado dependente
Trate as alterações de quantidade como uma atualização de estado dependente
Cada porção corresponde a 250 gramas distribuídas entre os cinco ingredientes. Ao passar de quatro para cinco porções, o total exibido muda de 1,000 para 1,250 gramas, e a quantidade de laranja necessária passa de 320 para 400 gramas. As seleções já feitas são limpas porque se referiam às quantidades anteriores, enquanto a fixação da receita permanece inalterada, pois a identidade da receita é a mesma.
A função de atualização primeiro compara o valor recebido com o sinal atual usando Object.is. Uma chamada sem alteração não deve limpar a lista de ingredientes nem anunciar uma mudança na quantidade. Valores inválidos ocultam as quantidades e desativam a seleção dos ingredientes; a mensagem de erro explica então o intervalo aceito. Essas regras permitem observar edições intermediárias sem deixar que um número inválido produza um total enganoso.
Selecione Gomos de laranja com quatro porções.
Aumente para cinco e confirme 400 g de laranja, 1,250 g no total e zero itens reunidos.
Fixe a receita, restaure os padrões e confirme que todos os estados locais foram redefinidos.
Sistema de design Kobalte: use uma compilação Solid e inclua a folha de estilos completa
Use uma compilação do Solid e inclua a folha de estilos completa
A configuração usa o template Vite para Solid, fixa as versões verificadas do Solid e de Kobalte e monta a aplicação em uma raiz explícita. O componente e a folha de estilos apresentados acima são arquivos completos. Este exemplo não exige provedor de tema, pacote de ícones, fonte externa nem backend.
Ao integrar a outro aplicativo, mantenha alinhados o compilador do framework e a geração de componentes. Uma transformação de React não converterá JSX do Solid em um aplicativo Kobalte correto. Da mesma forma, antes de substituir a dependência fixada por uma futura versão principal de Kobalte API, consulte a documentação correspondente. As quantidades da receita e a paleta são dados de exemplo da aplicação; adaptá-los não exige alterar o contrato das primitivas nativas.
Exemplos de componentes do sistema de design Kobalte
Componente de receita reativo completo
Campo numérico nativo, estrutura de Checkbox e botão de alternância com comportamentos explícitos para valores inválidos e redefinição.
jsx
import {createSignal,createMemo,For} from 'solid-js';
import {NumberField} from '@kobalte/core/number-field';
import {Checkbox} from '@kobalte/core/checkbox';
import {ToggleButton} from '@kobalte/core/toggle-button';
export default function App(){
const[portions,setPortions]=createSignal(4),[checked,setChecked]=createSignal(new Set()),[pinned,setPinned]=createSignal(false),[notice,setNotice]=createSignal('');
const ingredients=[{id:'orange',name:'Orange segments',grams:80},{id:'beans',name:'Cooked white beans',grams:90},{id:'leaves',name:'Salad leaves',grams:25},{id:'fennel',name:'Thinly sliced fennel',grams:40},{id:'dressing',name:'Citrus dressing',grams:15}];
const valid=createMemo(()=>Number.isFinite(portions())&&Number.isInteger(portions())&&portions()>=1&&portions()<=8);
function update(value){if(Object.is(value,portions()))return;setPortions(value);setChecked(new Set());setNotice('Portions changed. Ingredient checks were cleared for the new quantities.')}
function mark(id,value){setChecked(previous=>{const next=new Set(previous);value?next.add(id):next.delete(id);return next})}
function reset(){setPortions(4);setChecked(new Set());setPinned(false);setNotice('Restored four portions and an unchecked ingredient list.')}
return <main class="recipe-shell"><header><p class="eyebrow">KITCHEN NOTEBOOK · REACTIVE RECIPE CARD</p><h1>A brighter bowl, sized for your table.</h1><p>Change the portions, check the scaled ingredients and pin the recipe locally. The quantities are original sample data for this interface.</p></header><div class="recipe-layout"><section class="recipe-card"><div class="salad-art" aria-hidden="true"><div class="plate"><i/><b/><em/><span/><strong/></div></div><div class="recipe-heading"><div><p class="eyebrow">CITRUS & WHITE BEAN SALAD</p><h2>Fresh, crisp, generous.</h2></div><ToggleButton class="pin" pressed={pinned()} onChange={value=>{setPinned(value);setNotice(value?'Recipe pinned in this local preview.':'Recipe unpinned in this local preview.')}} aria-label="Pin recipe">{pinned()?'Pinned ✓':'Pin recipe'}</ToggleButton></div><p class="recipe-description">Sweet citrus, tender beans and crisp fennel. Use the checklist to gather the amounts for your chosen portion count.</p><div class="ingredient-title"><h3>Ingredients</h3><span>{checked().size} / 5 gathered</span></div><div class="ingredients"><For each={ingredients}>{ingredient=><Checkbox class="ingredient" checked={checked().has(ingredient.id)} onChange={value=>mark(ingredient.id,value)} disabled={!valid()}><Checkbox.Input/><Checkbox.Control class="check-control"><Checkbox.Indicator>✓</Checkbox.Indicator></Checkbox.Control><Checkbox.Label class="ingredient-label"><span>{ingredient.name}</span><strong>{valid()?ingredient.grams*portions()+' g':'—'}</strong></Checkbox.Label></Checkbox>}</For></div></section><aside class="portion-panel"><h2>Make it yours</h2><NumberField rawValue={portions()} onRawValueChange={update} minValue={1} maxValue={8} step={1} formatOptions={{maximumFractionDigits:0}} validationState={valid()?'valid':'invalid'} class="portion-field"><NumberField.Label class="field-label">Portions</NumberField.Label><div class="stepper"><NumberField.DecrementTrigger aria-label="Fewer portions">−</NumberField.DecrementTrigger><NumberField.Input/><NumberField.IncrementTrigger aria-label="More portions">+</NumberField.IncrementTrigger></div><NumberField.Description class="field-description">Choose 1–8 whole portions. Changing the quantity clears ingredient checks.</NumberField.Description><NumberField.ErrorMessage class="field-error">Enter a whole number from 1 to 8.</NumberField.ErrorMessage></NumberField><div class="portion-total"><span>Total ingredients</span><strong>{valid()?ingredients.reduce((s,x)=>s+x.grams,0)*portions()+' g':'—'}</strong></div><h3>A simple preparation order</h3><ol><li>Gather the scaled amounts and drain the cooked beans.</li><li>Combine the orange, fennel and leaves in a bowl.</li><li>Add the beans and dressing, then toss gently.</li></ol><button class="reset" onClick={reset}>Restore default recipe</button><p role="status" class="notice">{notice()||(pinned()?'Recipe pinned in this local preview.':'No shopping order or account update is created.')}</p></aside></div></main>
}
Esses valores recipe-* são escolhas originais da aplicação, não tokens oficiais de Kobalte.
A folha de estilos completa inclui uma composição responsiva e foco visível.
04
Configuração de agente do sistema de design Kobalte
Ponto de partida para implementação
O template Vite para Solid fornece o compilador JSX necessário para Solid. Os exemplos completos de App.jsx e style.css acima contêm todo o código e os estilos da aplicação; não é necessário nenhum provedor nem serviço externo.
javascript
// npm create vite@latest kobalte-recipe -- --template solid
// cd kobalte-recipe && npm install
// npm install [email protected] @kobalte/[email protected]
// Save the complete examples as src/App.jsx and src/style.css.
// src/index.jsx:
import {render} from 'solid-js/web';
import App from './App.jsx';
import './style.css';
render(() => <App />, document.getElementById('app'));
// index.html: <div id="app"></div><script type="module" src="/src/index.jsx"></script>
// npm run dev
Um prompt para seu projeto
Prompt para agente de IA
Use Kobalte 0.13.14 com Solid 1.9.15 para reproduzir o cartão de receita reativo. Mantenha NumberField rawValue/onRawValueChange, limites de um a oito, validação de porções inteiras e toda a estrutura de Label/Description/ErrorMessage. Calcule os gramas dos ingredientes e os totais com base no sinal de porções; uma alteração real na quantidade limpa o Set imutável de IDs marcados, mas preserva a fixação da receita. Mantenha as partes nativas de Checkbox e ToggleButton pressed/onChange, desative a coleta quando a quantidade for inválida e restaure quatro porções, nenhuma marcação e nenhuma fixação ao redefinir. Inclua a receita original completa CSS; todo o estado permanece local.
05
Fontes e escopo do sistema de design Kobalte
Verificado com Kobalte 0.13.14 e Solid 1.9.15. Todos os tokens recipe-*, a ilustração CSS e as quantidades dos ingredientes são dados originais do exemplo. A fixação e a coleta permanecem no estado local; não há conexão com conta, serviço de compras ou armazenamento persistente de receitas.