Sistema de componentes sem estilos · Novo recurso

Sistema de Design Bits UI.

Bits UI oferece componentes Svelte sem interface visual, compostos com partes nativas e o estado do Svelte 5. O exemplo combina uma caixa de seleção com estado misto derivado, seções de acordeão expansíveis de forma independente e uma caixa de diálogo de revisão baseada em portal, incluindo a configuração completa de estilos.

Guia OpenDesign9 capítulos28 entradas de referênciaGuia de aplicação original
01

Prévia da interface do sistema de design Bits UI

Marque uma verificação individual, examine o estado misto do controle em lote, confira o progresso incompleto e, em seguida, conclua e salve a lista de verificação local.

Revisão manual da interfaceAbrir exemplo completo
Bits UI 2.19.5 Checkbox, Accordion e Dialog com Svelte 5.57.1. Toda a estilização visual é original. · Referência de implementação
02

Referência de design do sistema de design Bits UI

Bits UI 2.19.5 com Svelte 5.57.1. Bits UI é headless: todas as cores --app-*, os valores tipográficos e de espaçamento são configurações originais explícitas fornecidas com este exemplo, não tokens de design oficiais de Bits UI. Os atributos de dados nativos e as propriedades dos componentes são identificados separadamente.

Configuração semântica original de CSS

Fonte
Nome / RegraValor / ConfiguraçãoUso
--app-canvas#f4f3f8 Plano de fundo da página.
--app-surface#ffffff Superfície do painel e do diálogo.
--app-ink#2d2938 Texto principal.
--app-muted#746d80 Texto de apoio.
--app-line#e3dfeb Divisórias e bordas.
--app-action#604c88 Controles marcados e ações principais.
--app-on-action#fffTexto sobre ações.
--app-focus#9a80ce Foco visível do teclado.
--app-soft#eee8f7 Função opcional de superfície suave.

Espaçamento e geometria originais

Fonte
Nome / RegraValor / ConfiguraçãoUso
--app-space-14pxMenor unidade de espaçamento nomeada.
--app-space-28pxEspaçamento compacto.
--app-space-312pxEspaço entre controle e rótulo.
--app-space-416pxRecuo estreito do painel.
--app-space-624pxRecuo do painel e espaço entre colunas em telas de desktop.
--app-space-832pxRecuo da página em telas de desktop.
Checkbox geometry22×22px; 5px radius; 1px borderEstilização original explícita dos controles.
Focus ring3px solid #9a80ce; 3px offsetAplicado ao foco do botão visível pelo teclado.
Dialog widthmin(440px, 100% − 28px)Geometria explícita e responsiva da sobreposição.
Dialog maximum height100vh − 28px with overflow:autoRestrição da área visível exclusiva da sobreposição; sem ajuste com base na altura da página.
Type hierarchy34px title / 29px mobile; 16px accordion; 13px checks; 12px guidanceHierarquia tipográfica original com fontes do sistema.

Contratos dos componentes nativos

Fonte
Nome / RegraValor / ConfiguraçãoUso
Checkbox.Root checkedbooleanEstado concluído ou incompleto.
Checkbox.Root indeterminatebooleanO controle em lote expõe o estado misto quando algumas verificações estão marcadas.
Checkbox data-statechecked / unchecked / indeterminateUsado diretamente pela folha de estilos.
Accordion.Root typemultipleVárias seções da revisão podem permanecer abertas.
Accordion valuestring[]Lista vinculada ao Svelte com os IDs dos grupos expandidos.
Dialog.Root openboolean, two-way boundControla a visibilidade da revisão.
Dialog.Title / DescriptionNative title and description relationshipsNão são necessários IDs ARIA duplicados criados manualmente.
Dialog.PortalOverlay and content rendered outside the normal panelEvita cortes usando o fluxo do documento do painel.
03

Guia completo do sistema de design Bits UI

Um guia prático para escolher, aplicar e avaliar este sistema em uma interface real.

DESIGN-bits-ui.md

Orientações completas, um ponto de partida para a implementação e links para o código-fonte.

Baixar o guia

Sistema de Design Bits UI: componha partes nativas com o estado do Svelte 5

Componha partes nativas com o estado do Svelte 5

A lista de verificação usa $state para as respostas individuais, os IDs das seções expandidas e a visibilidade do diálogo. Uma contagem derivada com $derived alimenta tanto o progresso exibido quanto a caixa de seleção em lote. Assim, a fonte da verdade fica em um único modelo Svelte, enquanto Bits UI fornece a interação nativa de cada componente.

Com base neste guia de OpenDesign

Checkbox, Accordion e Dialog são compostos a partir de suas próprias partes. O diálogo de revisão não precisa controlar as respostas da lista de verificação, e o accordion não precisa descartar essas respostas ao ser fechado. Essa separação é um ponto de partida útil para um formulário com várias seções: o modelo permanece intacto mesmo quando as partes visíveis da interface mudam.

Consulte a especificação de apoio

Sistema de Design Bits UI: use em conjunto as fontes de componentes e estilos do Svelte 5

Use em conjunto as fontes de componentes e estilos do Svelte 5

O exemplo usa runes do Svelte 5: $state para grupos, seções expandidas, visibilidade do diálogo e estado salvo; e $derived para a contagem de itens concluídos. Bits UI 2.19.5 é importado diretamente. Não são necessários plugin do Tailwind, provedor de tema ou biblioteca de ícones para este tratamento visual original.

Os arquivos completos App.svelte e style.css funcionam em um projeto Svelte padrão do Vite. A entrada usa mount do Svelte, em vez do construtor antigo new App. Ao transferir o exemplo, mantenha a sintaxe de runes do componente junto com a dependência Bits UI 2.19.5; os bindings e callbacks apresentados aqui não são de um componente API antigo do Svelte.

Consulte a especificação de apoio

Sistema de Design Bits UI: derive um verdadeiro estado misto das verificações individuais

Derive um verdadeiro estado misto das verificações individuais

Seis verificações booleanas estão distribuídas em três grupos. O controle em lote fica marcado somente quando as seis são verdadeiras e assume o estado indeterminado quando a contagem fica entre uma e cinco. Seu callback onCheckedChange atualiza todas as verificações, fazendo do estado misto um resultado calculado, em vez de uma variável armazenada separadamente que pode ficar dessincronizada.

Os controles individuais chamam uma pequena função de alteração que atualiza o modelo e invalida a mensagem salva. Depois que uma verificação é selecionada, a caixa de seleção nativa do controle em lote renderizada expõe aria-checked=mixed. A folha de estilos reage a data-state=checked e data-state=indeterminate, vinculando o comportamento e a apresentação ao mesmo estado nativo.

  1. Selecione a primeira verificação do indicador de foco e confira o traço no controle em lote.
  2. Abra a lista de verificação da revisão e confirme que a opção Salvar revisão concluída está desativada.
  3. Volte, marque todas as verificações e salve o registro local completo.

Consulte a especificação de apoio

Sistema de design Bits UI: permita seções independentes sem perder as respostas

Permita seções independentes sem perder as respostas

Accordion.Root usa type=multiple e um array vinculado de IDs dos grupos expandidos. A navegação pelo teclado começa com uma seção expandida, enquanto Correção do formulário e Feedback do resultado podem ser abertos de forma independente. Recolher uma seção não apaga as respostas, pois elas ficam no estado do componente pai.

Cada acionador repete sua própria contagem de itens concluídos, mantendo o progresso visível quando o conteúdo está recolhido. As partes nativas Header, Trigger e Content preservam a relação esperada e o comportamento do teclado. O marcador de mais gira conforme o data-state do acionador e respeita as preferências de movimento reduzido, em vez de controlar a expansão por meio de um manipulador de clique separado.

Consulte a especificação de apoio

Bits UI: sistema de design — componha a estrutura completa do diálogo e mantenha o foco nele

Componha toda a estrutura do diálogo e deixe que ele controle o foco

A revisão usa Dialog.Root, Trigger, Portal, Overlay, Content, Title, Description e Close. Title e Description são partes nativas de fato, permitindo que Bits UI estabeleça as relações de acessibilidade entre elas. O portal posiciona a sobreposição fora do fluxo normal do painel da lista de verificação.

O conteúdo tem uma largura responsiva limitada e uma altura máxima aplicada somente à sobreposição, com rolagem para revisões mais longas. A tecla Escape fecha o diálogo sem apagar a lista de verificação. Mantenha o acionador disponível como destino para o retorno do foco, em vez de removê-lo quando a sobreposição abrir.

Consulte a especificação de apoio

Bits UI: sistema de design — torne explícitas e reutilizáveis as regras visuais da aplicação

Torne explícitas e reutilizáveis as regras visuais da aplicação

CSS mapeia os estados nativo, marcado e indeterminado para a mesma função de ação, mas usa glifos diferentes para cada um. Uma função de foco separada corresponde à posição do teclado, permitindo que um controle permaneça visivelmente selecionado e também indique onde ocorrerá a próxima ação do teclado.

A escala de espaçamento nomeada é composta por quatro, oito, doze, dezesseis, vinte e quatro e trinta e dois pixels. Em telas de desktop, os painéis usam o valor de vinte e quatro pixels; em telas estreitas, usam dezesseis. A tabela de especificações documenta essas escolhas concretas como configuração original, para que os leitores possam reproduzi-las ou substituí-las sem confundir o estilo da demonstração com uma garantia do pacote.

Consulte a especificação de apoio

Bits UI: sistema de design — separe uma marcação manual do resultado de um teste automatizado

Separe uma marcação manual do resultado de um teste automatizado

A lista de verificação registra o que o leitor marcou. Ela não inspeciona outra página, executa testes de teclado nem atesta conformidade com os requisitos de acessibilidade. Tanto o texto introdutório quanto a descrição da revisão deixam esse escopo explícito, o que é necessário porque os seis itens dizem respeito a comportamentos reais de acessibilidade.

O botão Salvar fica desativado até que os seis itens sejam marcados. A mensagem de confirmação informa que todos os seis foram marcados pelo leitor e que o resultado é local. Ainda é possível abrir uma revisão parcial para verificar o que falta, mas ela não pode gerar uma mensagem de revisão concluída. Essa distinção mantém significativas as mudanças de estado do exemplo.

Consulte a especificação de apoio

Bits UI: sistema de design — atualize as mensagens de conclusão sempre que as evidências mudarem

Limpe as mensagens de conclusão sempre que as evidências mudarem

Qualquer alteração individual ou em massa limpa o estado salvo. Assim, uma confirmação de conclusão não permanece depois que um item é desmarcado. A ação Limpar tudo também restaura a seção expandida inicialmente e fecha o diálogo de revisão, retornando todos os estados relacionados a um ponto de partida conhecido.

A região de status fica fora da sobreposição, então a mensagem salva permanece no documento depois que o diálogo fecha. Ela descreve o estado local da página e não sugere que um relatório foi enviado. Ao recarregar a página, a lista de verificação é descartada, o que é adequado para esta demonstração independente.

Consulte a especificação de apoio

Bits UI: sistema de design — conecte as partes dos componentes aos rótulos visíveis

Conecte as partes dos componentes aos rótulos visíveis

Cada caixa de seleção tem um ID estável e um rótulo visível associado. O estado marcado ou indeterminado é representado pelo controle nativo; o tique e o traço são decorativos. Mantenha tanto o valor booleano checked quanto o valor indeterminado derivado conectados ao controle em massa, para que uma seleção parcial não seja anunciada como um item comum desmarcado.

Dialog.Title e Dialog.Description fornecem o nome e a explicação da revisão por meio da estrutura nativa. O portal separa a sobreposição do layout do acordeão, enquanto Dialog.Close permanece como a ação explícita para fechá-la. A região de status externa mantém o resultado salvo depois que a sobreposição fecha, para que ele não se perca com o conteúdo do diálogo.

  • Mantenha o rótulo visível associado ao controle.
  • Mantenha um anel de foco visível bem definido após aplicar estilos personalizados.
  • Não remova as partes de título ou descrição ao reformular o estilo de um diálogo.

Consulte a especificação de apoio

Exemplos de componentes do sistema de design Bits UI

Lista de verificação completa em Svelte 5

Composição nativa de Bits UI com modelos $state/$derived, caixas de seleção controladas e diálogo de revisão baseado em portal.

svelte
<script>
import {Accordion,Checkbox,Dialog} from 'bits-ui';
let groups=$state([{id:'keyboard',name:'Keyboard flow',description:'Move through the interface without a pointer.',checks:[{id:'focus',label:'Every action has a visible focus indicator.',done:false},{id:'order',label:'Focus follows the visual reading order.',done:false}]},{id:'forms',name:'Form correction',description:'Make a mistake and recover from it.',checks:[{id:'labels',label:'Each input has a persistent visible label.',done:false},{id:'errors',label:'Errors identify the field and explain the correction.',done:false}]},{id:'feedback',name:'Result feedback',description:'Confirm that the outcome is understandable.',checks:[{id:'status',label:'A status message describes the completed action.',done:false},{id:'color',label:'Meaning remains clear without color alone.',done:false}]}]);
let expanded=$state(['keyboard']),open=$state(false),saved=$state(false);
const complete=$derived(groups.reduce((sum,g)=>sum+g.checks.filter(c=>c.done).length,0));
function change(check,value){check.done=value;saved=false}
function all(value){groups.forEach(g=>g.checks.forEach(c=>c.done=value));saved=false}
function reset(){all(false);expanded=['keyboard'];open=false}
</script>
<main class="check-shell"><header><p class="eyebrow">INTERFACE REVIEW · MANUAL CHECKLIST</p><h1>Check the experience between the screens.</h1><p>Work through six practical checks, then review what you have marked. This is a personal checklist, not an automated accessibility test.</p></header><div class="check-layout"><section class="check-panel"><div class="bulk"><Checkbox.Root id="all-checks" checked={complete===6} indeterminate={complete>0&&complete<6} onCheckedChange={all} class="checkbox"><span aria-hidden="true">{complete===6?'✓':complete>0?'−':''}</span></Checkbox.Root><label for="all-checks">Mark all checks</label><span class="count">{complete}/6</span></div><Accordion.Root type="multiple" bind:value={expanded} class="accordion">{#each groups as group}<Accordion.Item value={group.id} class="accordion-item"><Accordion.Header class="accordion-heading"><Accordion.Trigger class="accordion-trigger"><span>{group.name}<small>{group.checks.filter(c=>c.done).length} of 2 checked</small></span><span class="plus" aria-hidden="true">+</span></Accordion.Trigger></Accordion.Header><Accordion.Content class="accordion-content"><p class="group-description">{group.description}</p>{#each group.checks as check}<div class="check-row"><Checkbox.Root id={check.id} checked={check.done} onCheckedChange={value=>change(check,value)} class="checkbox"><span aria-hidden="true">{check.done?'✓':''}</span></Checkbox.Root><label for={check.id}>{check.label}</label></div>{/each}</Accordion.Content></Accordion.Item>{/each}</Accordion.Root><Dialog.Root bind:open><Dialog.Trigger class="primary">Review checklist</Dialog.Trigger><Dialog.Portal><Dialog.Overlay class="overlay"/><Dialog.Content class="dialog"><Dialog.Title class="dialog-title">Your review snapshot</Dialog.Title><Dialog.Description class="dialog-description">{complete} of 6 checks are marked. Saving records your own review state; it does not certify the interface.</Dialog.Description><ul class="review-summary">{#each groups as group}<li><strong>{group.name}</strong><span>{group.checks.filter(c=>c.done).length} / 2</span></li>{/each}</ul>{#if complete<6}<p class="remaining">Return to the checklist to finish the remaining {6-complete} checks.</p>{/if}<div class="dialog-actions"><Dialog.Close class="secondary">Back to checks</Dialog.Close><button class="primary" disabled={complete<6} onclick={()=>{saved=true;open=false}}>Save completed review</button></div></Dialog.Content></Dialog.Portal></Dialog.Root><button class="reset" onclick={reset}>Clear all checks</button><p class="result" role="status">{saved?'Completed review saved locally. All six checks were marked by you.':'Progress stays in this preview until you reload.'}</p></section><aside class="check-notes"><div class="focus-art" aria-hidden="true"><span></span><i></i><b></b></div><p class="eyebrow">WHAT TO LOOK FOR</p><h2>Make the next action clear.</h2><p>A good check leaves evidence: where focus moved, what an error said, or how a result was announced.</p><dl><div><dt>Keyboard</dt><dd>Tab, Shift+Tab, Enter and Escape should support the relevant task.</dd></div><div><dt>Correction</dt><dd>Keep the user’s input and point to a specific next step.</dd></div><div><dt>Feedback</dt><dd>Describe the outcome in words as well as visual styling.</dd></div></dl></aside></div></main>

Referência de código

  • O controle principal deriva os estados marcado e indeterminado das seis verificações individuais.
  • O salvamento depende da conclusão, não de o diálogo estar aberto.
  • Esta lista manual não executa uma auditoria de acessibilidade.

Configuração visual original completa

Cores semânticas nomeadas, escala de espaçamento, seletores nativos data-state e estilos responsivos para a sobreposição.

css
:root{--app-canvas:#f4f3f8;--app-surface:#ffffff;--app-ink:#2d2938;--app-muted:#746d80;--app-line:#e3dfeb;--app-action:#604c88;--app-on-action:#fff;--app-focus:#9a80ce;--app-soft:#eee8f7;--app-radius:12px;--app-space-1:4px;--app-space-2:8px;--app-space-3:12px;--app-space-4:16px;--app-space-6:24px;--app-space-8:32px}html,body,#app{height:auto;min-height:0;margin:0}*{box-sizing:border-box}body{font-family:system-ui,sans-serif;background:var(--app-canvas);color:var(--app-ink)}button{font:inherit;cursor:pointer}button:disabled{opacity:.45;cursor:default}button:focus-visible{outline:3px solid var(--app-focus);outline-offset:3px}.check-shell{max-width:1080px;margin:auto;padding:var(--app-space-8)}.eyebrow{font-size:10px;letter-spacing:.14em;font-weight:700;color:var(--app-muted)}h1{font-size:34px;line-height:1.15;max-width:710px;margin:12px 0}header>p:last-child{font-size:14px;line-height:1.7;max-width:640px;color:var(--app-muted)}.check-layout{display:grid;grid-template-columns:minmax(0,1fr) 270px;gap:var(--app-space-6);margin-top:28px}.check-panel{background:var(--app-surface);border:1px solid var(--app-line);border-radius:16px;padding:var(--app-space-6);min-width:0}.bulk{display:flex;align-items:center;gap:12px;font-size:14px;font-weight:600;padding-bottom:24px}.count{margin-left:auto;color:var(--app-muted);font-size:12px}.checkbox{width:22px;height:22px;flex-shrink:0;border:1px solid #aaa1ba;background:white;border-radius:5px;display:inline-flex;align-items:center;justify-content:center;padding:0;line-height:1}.checkbox[data-state=checked],.checkbox[data-state=indeterminate]{background:var(--app-action);border-color:var(--app-action);color:var(--app-on-action)}.accordion{margin-bottom:24px}.accordion-item{border-top:1px solid var(--app-line)}.accordion-item:last-child{border-bottom:1px solid var(--app-line)}.accordion-heading{margin:0;font-size:16px}.accordion-trigger{width:100%;border:0;background:transparent;display:flex;align-items:center;justify-content:space-between;text-align:left;padding:20px 0;color:var(--app-ink);font-weight:600}.accordion-trigger small{display:block;font-weight:400;font-size:11px;color:var(--app-muted);margin-top:6px}.plus{font-size:23px;font-weight:400;transition:transform .15s}.accordion-trigger[data-state=open] .plus{transform:rotate(45deg)}.accordion-content{padding:0 0 20px}.group-description{font-size:12px;line-height:1.6;color:var(--app-muted);margin:0 0 16px}.check-row{display:flex;align-items:flex-start;gap:12px;margin-top:14px}.check-row label{font-size:13px;line-height:1.6;cursor:pointer}.primary,.secondary{border:1px solid transparent;border-radius:8px;padding:12px 16px;font-size:13px;font-weight:600}.primary{background:var(--app-action);color:var(--app-on-action)}.secondary{background:white;color:var(--app-ink);border-color:var(--app-line)}.reset{border:0;background:transparent;color:var(--app-muted);font-size:12px;padding:12px}.result{font-size:12px;line-height:1.6;color:var(--app-muted);margin:18px 0 0}.check-notes{min-width:0;padding:0 4px}.check-notes h2{font:400 29px/1.2 Georgia,serif}.check-notes>p:not(.eyebrow){font-size:13px;line-height:1.7;color:var(--app-muted)}.check-notes dl>div{padding:14px 0;border-top:1px solid var(--app-line)}.check-notes dt{font-size:13px;font-weight:600}.check-notes dd{font-size:12px;line-height:1.7;color:var(--app-muted);margin:5px 0 0}.focus-art{height:165px;background:#e6e0ef;border-radius:12px;position:relative;overflow:hidden;margin-bottom:24px}.focus-art span{position:absolute;width:140px;height:85px;left:35px;top:44px;background:white;border-radius:8px;transform:rotate(-9deg);box-shadow:0 0 0 6px #b3a3cd}.focus-art i{position:absolute;width:75px;height:13px;background:#b7adc6;left:60px;top:61px;transform:rotate(-9deg)}.focus-art b{position:absolute;width:72px;height:28px;background:#695587;left:87px;top:91px;border-radius:5px;transform:rotate(-9deg)}.overlay{position:fixed;inset:0;background:#21193180;z-index:20}.dialog{position:fixed;z-index:21;left:50%;top:50%;transform:translate(-50%,-50%);width:min(440px,calc(100% - 28px));max-height:calc(100vh - 28px);overflow:auto;background:white;padding:24px;border-radius:14px;box-shadow:0 20px 80px #23193640}.dialog-title{font-size:23px;margin:0 0 12px}.dialog-description,.remaining{font-size:13px;line-height:1.7;color:var(--app-muted)}.review-summary{padding:0;list-style:none}.review-summary li{display:flex;justify-content:space-between;gap:12px;padding:12px 0;border-bottom:1px solid var(--app-line);font-size:13px}.dialog-actions{display:flex;gap:10px;flex-wrap:wrap;margin-top:22px}@media(max-width:740px){.check-layout{grid-template-columns:minmax(0,1fr)}.check-shell{padding:20px}h1{font-size:29px}}@media(max-width:360px){.check-shell{padding:14px}.check-panel,.dialog{padding:16px}.check-panel>.primary,.dialog-actions>*{width:100%}}@media(prefers-reduced-motion:reduce){.plus{transition:none}}

Referência de código

  • Estas são variáveis --app-* originais, não uma paleta oficial do Bits.
  • Inclui estilos de foco e de movimento reduzido.
  • Somente a sobreposição usa uma altura máxima relativa à área de visualização.
04

Configuração de agente do sistema de design Bits UI

Ponto de partida para implementação

Verificado com Bits UI 2.19.5 e Svelte 5.57.1. A folha de estilos original completa é necessária; Bits UI não fornece cores padrão nem layout de página.

javascript
// npm create vite@latest bits-review -- --template svelte
// cd bits-review && npm install
// npm install [email protected] [email protected]
// Save the complete examples as src/App.svelte and src/style.css.
// src/main.js:
import {mount} from 'svelte';
import App from './App.svelte';
import './style.css';
mount(App, {target:document.querySelector('#app')});
// index.html: <div id="app"></div><script type="module" src="/src/main.js"></script>
// npm run dev

Um prompt para seu projeto

Prompt para agente de IA
Use Bits UI 2.19.5 e Svelte 5 para criar a revisão manual da interface fornecida. Mantenha seis verificações distribuídas em três seções de Accordion, derive os estados marcado/indeterminado do controle em massa a partir das respostas individuais e preserve as respostas quando as seções forem recolhidas. Componha todas as partes de Dialog para a revisão, permitindo consultar os itens incompletos e mantendo Salvar desativado até que os seis sejam marcados. Qualquer alteração nas respostas invalida o feedback salvo; Limpar tudo restaura a expansão inicial e fecha a revisão. Inclua o CSS completo e descreva os resultados como verificações locais marcadas pelo leitor, não como certificação automatizada de acessibilidade.
05

Fontes e escopo do sistema de design Bits UI

Bits UI 2.19.5 com Svelte 5.57.1. Tokens e ilustrações originais da aplicação. Esta é uma lista de verificação manual com estado local, não uma auditoria ou certificação automatizada de acessibilidade.