Construir Protótipo HTML
Construa cada protótipo em assets/template.html (no diretório desta skill): um único arquivo HTML independente. O modelo já possui toda a estrutura: cabeçalho, moldura do navegador, alternador de estados, painel de notas, mapa de tela, comentários de revisores, tokens Koobiq com componentes k-* e o runtime. A interface do modelo está em inglês ou russo, selecionada com base no idioma do SO/navegador; o texto do próprio protótipo é o que você escrever. Você escreve apenas o bloco PROTOTYPE (JS) e a seção 5. PROTOTYPE STYLES (CSS). Não quebre o modelo: nunca reconstrua, reestilize ou descreva a estrutura.
Projete antes de codificar
Um protótipo é uma ferramenta para uma única decisão, não uma galeria de telas. Siga estas etapas antes de escrever prototype.js.
-
Reúna o contexto. Quem é o usuário (função, experiência), qual tarefa ele está realizando, o que a desencadeia e como é o "pronto" para ele. Se o produto existir (repositório, capturas de tela, Figma, documentos, um protótipo anterior), use sua navegação, termos, entidades e dados de lá e projete apenas a mudança. Não invente um produto em torno do recurso.
-
Nomeie a pergunta. Uma frase, ou várias apenas para um protótipo grande: o que os revisores devem decidir, ou o que é mais duvidoso na UI (os usuários encontrarão X, entenderão Y, Z se mantém com dados reais). Para cada pergunta, anote o que um revisor precisa ver para respondê-la e qual estado ou dado poderia quebrar o design. Se a solicitação não nomear nenhuma pergunta, considere a decisão mais arriscada como uma e apresente-a ao autor na etapa 4.
-
Escreva o cenário nas palavras do usuário, do gatilho ao resultado: "analista vê um pico → abre a regra → diminui o limite → vê quantos incidentes haverá". Em seguida, adicione apenas as ramificações que a pergunta precisa: cancelar, erro de validação, vazio ou primeiro uso, e os casos difíceis onde requisitos que ninguém viu antes surgem: sem permissão, um conflito com outro objeto, um limite, muitos dados, uma ação que o estado atual do objeto proíbe. As etapas se tornam
STEPS, as ramificações se tornam estados, e as condições transversais (função, flag de recurso, volume de dados) se tornamSWITCHES. -
Combine com o autor antes de construir. Em uma mensagem curta, envie:
- a pergunta;
- o cenário com as ramificações e casos difíceis que você planeja mostrar;
- tudo o que você supôs em vez de tirar da solicitação ou do produto, como uma lista numerada com uma afirmação por item, para que o autor possa responder por número: "2 — não, é necessária a aprovação de um gerente".
Aguarde a resposta. Pule esta etapa para pequenas edições em um protótipo existente. Se o autor pediu para não ser questionado, construa com base em suas suposições e liste-as na resposta.
-
Defina a profundidade de cada célula de etapa × estado:
- completo = no caminho da pergunta: clicável, todos os estados, dados de estresse;
- plausível = contexto: estático, mas realista;
- fora = nomeado na resposta como não coberto.
Use apenas os estados que a pergunta precisa: ideal, vazio ou primeiro uso, parcial, erro, sem permissão, no máximo cerca de 6 por etapa. Adicione carregamento apenas quando mostrar algo específico (uma operação longa, progresso, resultados parciais). Um carregamento com falha raramente vale um estado, mas "não permitido no estado deste objeto" geralmente vale. Nunca finja um resultado que não foi projetado.
-
Projete cada tela primeiro em palavras: seu propósito em uma frase, a única ação primária e o que o usuário precisa ver para decidir aqui, ordenado por importância. Em seguida, construa-a a partir de padrões Koobiq padrão (tabela, formulário, painel lateral, modal, estado vazio). Coloque novidade apenas onde está a pergunta; todo o resto se parece com as telas comuns do produto.
- Toda ação tem um resultado visível: o que aconteceu e onde o objeto está agora.
- Uma ação destrutiva nomeia o objeto e a consequência. Botões geralmente dizem o verbo.
- Um erro diz como corrigi-lo e mantém a entrada.
- Um nome para cada coisa em todas as telas, breadcrumbs, toasts e a URL. O texto da UI está no idioma do usuário e segue
ux-writese estiver instalado.
-
Escreva os dados antes das visualizações. Use dados de domínio realistas que estressem o layout: um nome longo, uma contagem 0 / 1 / muitos, um status raro. Use datas e valores fixos (sem
Date.now()/Math.random()) e sem lorem ipsum.
Variantes, apenas quando a pergunta é "qual solução". Construa 2–3 (máx. 5) em VARIANTS em vez de escolher para os revisores.
- Elas diferem em estrutura (layout, hierarquia, ação primária), não em cor ou texto. Se dois rascunhos parecem iguais, refaça um com uma proibição explícita ("nenhuma grade de cartões").
- As variantes podem compartilhar dados, nunca o layout.
- Dê a cada uma um
titlee uma ideia de uma linha emtext. - O melhor feedback é "cabeçalho de B, lista de C".
Pronto quando
Verifique o protótipo em cada item antes de responder:
- Todo caminho mostrado é executado do início ao fim. Começa onde o usuário encontra o gatilho, não em um login ou painel. Toda ramificação mostrada termina, de volta ao caminho ou em um resultado. Uma transferência para outro produto ou sistema é um stub com um resultado visível (um toast, ou um estado como "Tarefa criada no Jira"), nunca uma cópia da outra UI. Um controle secundário pode não fazer nada (um item de menu pode apenas
close) desde que nenhum cenário comece a partir dele. - O que é discutível está marcado. Cada elemento alterado ou discutível tem uma nota. Quando a pergunta é qual solução adotar, existem 2–3 variantes que diferem em estrutura.
- Nada extra. Cada estado, switch e nota ou ajuda a responder à pergunta ou testa uma suposição sobre um requisito. Remova o resto.
Construir
-
Obtenha as partes editáveis. Com
SKILL_DIR= diretório desta skill,A=$SKILL_DIR/scripts/assemble.mjs(execute comnode, sem dependências), diretório de trabalho, por exemplo,/tmp/proto-<nome>/:- novo protótipo:
node $A --split $SKILL_DIR/assets/template.html /tmp/proto-<nome>; - alterar um existente:
node $A --split <arquivo>.html /tmp/proto-<nome>. A remontagem também atualiza sua estrutura.
Isso fornece
prototype.js(bloco PROTOTYPE de demonstração) eprototype.css(seção 5). - novo protótipo:
-
Reescreva
prototype.js, substituindo todo o conteúdo de demonstração:PROTO,STEPS,SWITCHES,S,NOTES,LINKS(geralmente[]), dados,VIEWS,ACTIONS. CSS personalizado vai paraprototype.css. Trabalhe em passes:- o caminho principal, clicável do início ao fim, em seu estado ideal;
- os outros estados e ramificações;
- notas;
- Verifique e Pronto quando.
Não polia uma tela antes que o caminho através dela funcione.
-
Monte:
node $A <alvo>.html /tmp/proto-<nome>/prototype.js /tmp/proto-<nome>/prototype.css. Isso verifica a sintaxe e as declarações necessárias. Entregue apenas o HTML. -
Visualizações: um
VIEWS[step](S)por etapa que retorna uma string HTML e ramifica emS.state/S.sw. Construa a partir de classesk-*; consultereferences/koobiq-cheatsheet.md.- Cada estado renderiza completamente quando aberto diretamente. Uma abertura direta (popover, link de hash, miniatura do mapa, nota, ←/→,
protoCheck) começa a partir doSinicial mais oseeddo estado, por exemplo{ id: 'confirm', title: 'Confirmation', seed: { name: 'Brute force: RDP' } }. Umgoto()em fluxo mantém o que o usuário digitou. As VIEWS leem apenasSe dados constantes. - Sobreposições. Um modal ou painel lateral é desenhado sobre a tela que cobre, dentro da mesma visualização. Uma sobreposição única (uma confirmação) é um estado dessa etapa (
form/confirm). Uma sobreposição com seu próprio subfluxo (formulário → erro → confirmar) pode ser sua própria etapa que desenha a tela coberta por baixo. Para um modal sobre um painel, renderize o modal após o painel: o último.k-overlayé o superior, e apenas seus marcadores aparecem. - Rolagem. Uma tela mais alta que a moldura do navegador rola dentro dela, como uma página. Uma nova etapa começa no topo; um novo estado ou variante na mesma etapa mantém a rolagem, para que os revisores comparem no mesmo ponto. Um shell de aplicativo (
.app-body+.app-content) rola dentro de.app-content, como antes. - Conecte cliques com
data-act→ACTIONS. Altere telas apenas viagoto(step, state)/data-goto, para que o botão de estado, barra de URL e hash permaneçam sincronizados.
- Cada estado renderiza completamente quando aberto diretamente. Uma abertura direta (popover, link de hash, miniatura do mapa, nota, ←/→,
-
Notas (3–7) vão apenas nos elementos sobre os quais a pergunta é: alterados ou discutíveis.
- Coloque
class="changed" data-anchor="note-N"no elemento e${marker(N)}dentro dele. Envolva elementos vazios ou desabilitados em<span class="k-anchor changed" data-anchor="note-N">. - O
textda nota diz o que mudou e por que em 1–2 frases. Para uma hipótese, termine com "Verifique: …". trydiz no que clicar para vê-la.
- Coloque
-
Mapa de tela é construído automaticamente a partir dos estados e transições. As transições vêm da marcação de cada estado:
data-goto, e chamadas literaisgoto()/openState()nosACTIONSque seus controles habilitados, itens de menu e sobreposição superior chamam (controles desabilitados não dão seta). Um estado computado na mesma ação funciona se seus ids possíveis aparecerem lá como strings:goto('list', S.q ? 'empty' : 'data'). Uma transição por trás de uma função auxiliar, um temporizador ou um evento que o usuário não clica vai paraLINKS:{ from: 'report/building', to: 'report/ready', label: 'Relatório pronto' }. -
Verifique (consulte Verificação). Corrija e remonte até que
protoCheck()esteja limpo, depois verifique o protótipo em relação a Pronto quando. -
Responda com o caminho do arquivo, a tabela de etapa × estado, o que está deliberadamente não coberto e qualquer suposição feita após o acordo. Não descreva a estrutura.
Comentários do revisor
O usuário pode colar o Markdown de "Copiar tudo". Ele nomeia o arquivo na linha File:. Cada ## é uma tela com seu hash (#step/state?switches); com variantes, começa com Variant B · Cards → e o hash tem variant=<id>. A estrutura o escreve no idioma da UI do revisor, então pode estar em russo: Файл:, Вариант B. Cada ### é um elemento com seu seletor dentro de #view, seus atributos data-* e o número da nota vinculada, seguido pelo comentário como uma citação.
Para aplicá-lo, encontre o elemento em VIEWS[step] / ACTIONS desse arquivo (dessa variante), então edite via --split e remonte no mesmo arquivo: os comentários vivem no localStorage do navegador sob o caminho do arquivo.
Regras da estrutura
- Cabeçalho = apenas título curto. Sem subtítulo, legenda, lenda ou "protótipo do fluxo…" texto em qualquer lugar acima da moldura.
- Um controle de estado: o popover "Etapa · Estado". Sem steppers anterior/próximo, controles segmentados por tela, guias sobre a moldura ou teclas de atalho personalizadas (←/→, Esc e o seletor de variantes com 1–9 são integrados).
- Notas vivem apenas em
aside#notes, fora de.browser. Dentro de.appexistem apenas marcadores numerados. Nunca coloque texto de nota em tooltips::after, sobreposições ou uma coluna de "modo de revisão" dentro do aplicativo. - Não edite RUNTIME, e não mova ou reestilize o deck, stage, browser, notas, comentários ou mapa de tela. O comportamento vai em
ACTIONS. - Koobiq por padrão: classes
k-*e tokens--kbq-*. Sem cores hex/rgb, sem paleta inventada (--bg, acentos roxos) e sem estilo apenas claro, porque o alternador de tema deve funcionar. Para outro sistema de design, mantenha a estrutura e reestilize apenas o aplicativo. - Um arquivo, sem JS externo.
API PROTOTYPE
| O quê | Como |
|---|---|
| Título / barra de URL | PROTO.title, PROTO.url(S) |
| Grade de popover | STEPS[{id,title,states[{id,title,seed?}]}], SWITCHES[{id,title,options}] |
| Estado | S.step, S.state, S.sw[id], S.menu (id do menu aberto), mais seus próprios campos |
| Navegar | goto(step, state, patch?) dentro do fluxo (mantém S); marcação data-act="goto" data-goto="form/errors". openState(step, state) = abertura direta (S inicial + seed) |
| Ações | data-act="name" → ACTIONS.name(el, e); re-renderiza a menos que retorne false |
| Ações integradas | goto; close (S.menu = null); menu + data-menu="id" (alternar); set + data-field + data-value (escrever em S, fechar menu). Um menu também fecha em Esc, clique fora e qualquer outra ação |
| Entradas | data-model="field" escreve S.field; data-live re-renderiza na entrada (o foco e o cursor são mantidos); data-live="act" primeiro chama ACTIONS.act; data-scroll="key" mantém a rolagem |
| Foco | goto('form', 'errors', { focus: 'name' }) foca [data-model="name"] uma vez |
| Auxiliares | icon('search'), marker(n, '--x:100%;--y:50%'), tip(html, text, 'k-float--right'), matches(S.q, ...fields), toast(title, {kind, text}), esc(str) |
| Notas | NOTES[{id, step, state, title, text(html), try}]: step/state dizem onde a âncora vive |
| Mapa de tela | Construído automaticamente; LINKS[{from: 'step/state', to: 'step/state', label}] adiciona transições que a varredura não pode ver |
| Variantes | VARIANTS[{id, title, text, STEPS?, NOTES?, VIEWS?, ACTIONS?, LINKS?, S?, url?}]. As declarações globais são a variante A; uma variante substitui apenas o que difere (S é mesclado sobre o S global). Cada uma tem seu próprio mapa de tela, notas e comentários; SWITCHES e voltar/avançar são compartilhados. Seletor no cabeçalho, teclas 1–9 |
Verificação
Sirva a pasta em segundo plano (file:// geralmente é bloqueado) e abra a URL impressa mais <arquivo>.html na ferramenta do navegador. Recarregue após cada remontagem, porque uma alteração apenas no hash não recarrega o arquivo.
cd <dir> && node -e "const fs=require('fs'),T={'.html':'text/html; charset=utf-8','.js':'text/javascript','.css':'text/css','.svg':'image/svg+xml'};require('http').createServer((q,r)=>{const p='.'+decodeURIComponent(new URL(q.url,'http://x').pathname);fs.readFile(p,(e,d)=>{r.writeHead(e?404:200,{'Content-Type':T[require('path').extname(p)]||'application/octet-stream'});r.end(e?'Not found':d)})}).listen(0,'127.0.0.1',function(){console.log('http://127.0.0.1:'+this.address().port+'/')})"
- Execute
protoCheck()na página (console ou evaluate da ferramenta do navegador) com uma largura de janela de 1440 ou mais. Deve retornarok: true. Ele abre cada combinação de etapa × estado × switch em ambos os temas e relata erros de renderização, telas vazias, overflow, marcadores ou notas quebrados, destinosdata-act/data-goto/goto()/LINKSdesconhecidos, cores codificadas e sobras do modelo. Corrija cada aviso (estados idênticos, switches sem efeito, dados não determinísticos, notas fora de 3–7, uma etapa não conectada a outras) ou explique-o na resposta. - Olhe para isso em l