Repository navigation
Description
Objetivo
Após a implementação do novo carousel de bandeiras, alguns ajustes de UX, comportamento e integração ainda são necessários para que a experiência fique consistente e pronta para uso.
Esta issue reúne refinamentos visuais, melhorias de layout, restauração de funcionalidades que deixaram de funcionar e integração entre as telas da aplicação.
1. Reorganização do Layout
A gôndola se tornou o elemento principal da seleção de linguagens e deve ganhar mais destaque na interface.
Alterações
- mover o carousel para uma posição mais alta dentro do card
- aproximá-lo do título "Linguagem — Votação"
- reduzir o espaço vazio acima dele
Além disso, os botões de ação não fazem mais sentido próximos ao topo da tela.
Mover:
- Compartilhar
- Ficar Pronto / Iniciar Partida
para a parte inferior do card, agrupando-os junto das demais configurações da sala.
O objetivo é deixar toda a área de configuração concentrada em um único bloco visual.
2. Remover fundo da gôndola
Hoje o carousel possui um fundo escuro que acaba escondendo parte da estética das bandeiras.
Remover completamente esse fundo.
O resultado esperado é que apenas as bandeiras fiquem visíveis sobre o fundo da própria aplicação, criando uma sensação de que estão realmente suspensas no ambiente.
3. Animação física das bandeiras
Embora o novo carousel esteja extremamente fluido, as bandeiras ainda permanecem praticamente rígidas.
Conforme definido na issue anterior, elas devem utilizar uma simulação baseada no exemplo oficial do Three.js:
https://threejs.org/examples/#physics_ammo_cloth
A ideia não é criar tecidos leves.
Os parâmetros devem transmitir a sensação de:
- estandartes medievais
- veludo
- tapeçarias
- tecidos espessos
- bastante amortecimento
- pouca elasticidade
- movimentos suaves
As bandeiras devem reagir ao deslocamento do carousel através de uma pequena inércia.
Quando o usuário movimenta a gôndola:
- a haste acompanha imediatamente
- o tecido atrasa levemente
- ocorre uma pequena curvatura
- após parar, a bandeira realiza uma ou duas oscilações discretas antes de estabilizar
Evitar movimentos exagerados ou chamativos.
O objetivo é adicionar vida à interface sem distrair o jogador.
4. Destacar melhor a linguagem selecionada
Hoje a linguagem central ainda não se diferencia o suficiente das demais.
A linguagem atualmente selecionada deve ficar imediatamente reconhecível.
Sugestões:
- aumentar levemente sua escala
- melhorar a iluminação
- aumentar contraste
- reduzir opacidade das linguagens laterais
- reforçar profundidade
O usuário deve identificar instantaneamente qual linguagem está sendo escolhida.
5. Restaurar sistema de votação
Após a refatoração do componente, o sistema de votação deixou de funcionar corretamente.
Revalidar toda a lógica envolvendo:
- seleção da linguagem
- alteração do voto
- sincronização entre jogadores
- atualização em tempo real
- vencedor da votação
Garantir que o comportamento existente antes da substituição dos cards seja preservado.
6. Propagação da linguagem entre telas
Ao criar uma nova sala, o usuário escolhe uma linguagem inicial.
Essa informação atualmente não está sendo propagada corretamente para a tela da lobby.
Como consequência:
- a linguagem selecionada na criação é perdida
- o carousel inicia em posição incorreta
- estado inicial fica inconsistente
Garantir que:
- a linguagem escolhida na criação da sala seja enviada corretamente
- o lobby seja aberto já centralizado nessa linguagem
- todos os jogadores recebam o mesmo estado inicial
Critérios de Aceitação
Layout
- Mover o carousel para uma posição mais alta dentro do card.
- Agrupar Compartilhar e Ficar Pronto junto às demais ações na parte inferior.
Visual
- Remover o fundo escuro da área da gôndola.
- Exibir apenas as bandeiras sobre o fundo da aplicação.
- Destacar visualmente a linguagem central selecionada.
Física
- Integrar a animação baseada em
physics_ammo_cloth. - Configurar o tecido como pesado, com alta inércia e amortecimento.
- Fazer as bandeiras reagirem suavemente ao movimento do carousel.
Funcional
- Restaurar completamente o sistema de votação.
- Sincronizar votos entre todos os jogadores.
- Propagar corretamente a linguagem escolhida na criação da sala para o lobby.
- Inicializar o carousel já centralizado na linguagem selecionada.
Resultado Esperado
O carousel deve se consolidar como o principal elemento de interação da seleção de linguagens.
As bandeiras passam a ocupar posição de destaque na interface, aparentando estar realmente suspensas por uma gôndola. A linguagem selecionada torna-se imediatamente identificável, os estandartes respondem ao movimento com uma animação física suave e elegante, e toda a lógica de votação e sincronização entre criação da sala e lobby volta a funcionar corretamente, garantindo uma experiência visualmente rica e consistente para todos os jogadores.
Activity
fix(ui): restaura votação, tira o fundo da gôndola e dá vida ao tecido (
caioross commentedon Jul 26, 2026
Resolvida em PR #98 — como commit adicional (
4731470) na PR da #97, que ainda não mergeou: esta issue é correção daquele código, e separar viraria "eis a coisa, eis a correção dela" para o revisor.Item 5 (votação) — causa raiz encontrada, e ela era minha:
setPointerCapturenopointerdownda gôndola fazia o navegador entregar oclickao elemento de captura em vez do estandarte. No lobby, onde clicar é a única forma de votar, isso matava a votação inteira. A captura agora só entra depois de 6 px de arrasto. Passou despercebido na #97 porque eu verifiquei com.click()sintético, que ignora captura de ponteiro — reproduzi com clique real e confirmei a correção do mesmo jeito. A fiação de votos (broadcast, tally, vencedor) nunca foi tocada.Item 3 (física) — o sintoma era calibração, não o motor: "praticamente rígidas" estava certo e dá para medir — o ganho antigo produzia θ≈0.027 rad na desaceleração de um arremesso, ou seja menos de 1 px de ponta. Recalibrado, a trajetória real agora é
-0.274 → -0.108 → +0.083 → -0.025: ~13 px num estandarte de 49 px, uma oscilação forte e duas discretas. Também passei a cisalhar cada faixa pela inclinação local, senão o pico virava escada em vez de curva.Itens 2 e 4: os 25 assets foram refatiados com alpha (recorte por scanline, que não entra no veludo escuro — era ali que as tentativas anteriores falhavam). Gôndola sem fundo/borda, com máscara nas pontas; central com escala 1.0 vs 0.7, opacidade 1.0 vs 0.22, brilho 1.14 vs 0.5 e halo verde na silhueta.
Itens 1 e 6: gôndola encostada no título, ações agrupadas no rodapé do card. Sobre a propagação: a API já gravava a linguagem certo — o erro era a gôndola do lobby abrir sempre no primeiro estandarte; a nova prop
centerOncentraliza na linguagem da sala enquanto não há voto.Gate: typecheck ✅ · build ✅ (216 KB) · 122 testes ✅ · validate-persistence 72/72 ✅ · validate-metrics 45/45 ✅.
Dois limites que não escondo: não consigo ver a animação rodando (o Browser pane não compõe frames — a trajetória acima saiu do
stepClothreal), e sem credenciais Supabase no worktree não testei a sincronização de votos entre dois jogadores de verdade.A AC de Three.js + ammo.js segue aberta e é decisão sua. Não incluí porque o que causava a rigidez era a calibração, já corrigida com número em cima, e o custo (~700 KB contra 216 KB de first load hoje, mais reescrever a camada de render e a acessibilidade) não mudou. Se ainda quiser essa rota depois de ver rodando, é só dizer: a simulação está isolada atrás de
stepCloth/bendProfilee eu troco o backend sem tocar em carousel, assets ou votação.feat(cloth): troca o motor de tecido para soft-body ammo + three.js (#97
caioross commentedon Jul 26, 2026
Backend ammo + Three.js implementado na PR #98 (commit
2072d33), conforme a decisão do dono registrada na PR (núcleo §7.1). Fecha a última AC pendente destas duas issues.O soft-body do Bullet substituiu o pêndulo analítico atrás da fronteira
ClothEngine; carousel, os 25 estandartes,banners.tse a votação seguem intactos. Carregado porimport()dinâmico: first load da home inalterado em 216 kB, com three + ammo em chunks sob demanda (437 kB brotli). Custo medido: 3,22 ms por quadro com 7 panos ativos, contra 16,7 ms de orçamento a 60fps.Medido no navegador dirigindo o laço na mão e lendo o framebuffer: ponta atrasa 12 px no arremesso com o topo cravado na haste, duas oscilações discretas ao soltar, repouso em 2,8 s. Fallback para o motor leve preservado (sem WebGL, import falhando ou reduced-motion).
Detalhes, números e os dois defeitos de calibração que apareceram medindo estão no comentário da PR.
caioross commentedon Jul 28, 2026
Marcada
blockedna triagem de hoje — sem mudança de escopo nem de prioridade.Esta issue é o refinamento do carousel que a #97 implementa ("Após a implementação do novo carousel, alguns ajustes..."), e a PR #98 — que fecha a #97 — está DRAFT +
decisao-donodesde 26/07, aguardando o dono decidir sobre a dependência pesada (three.js + ammo, 600 KB gzip medidos, núcleo §7.1) na discussion #102.Trabalhar nos refinamentos agora seria construir sobre uma base que pode mudar de backend antes de mergear — retrabalho garantido, e o Resolvedor bateria na mesma parede.
Destrava sozinha assim que a #102 for decidida e a #98 mergear. Nenhuma ação necessária aqui até lá.
feat(ui): gôndola infinita de estandartes medievais na escolha de lin…
caioross commentedon Jul 29, 2026
🗂️ Triagem do Curador · 2026-07-29 — desbloqueada e entregue: fechando
A PR #98 foi mergeada por @caioross em 28/07 16:24Z (
82f7817), com a mensagem referenciando (#97, #99). Isso derruba o motivo doblockedque eu mesmo pus aqui em 28/07 ("destrava sozinha assim que a #102 for decidida e a #98 mergear").Antes de mexer no rótulo eu conferi AC por AC contra
origin/main— não confiei na mensagem do merge. As 12 caixas estão implementadas:Layout
Lobby.tsx:132-138(mt-1, com a explicação movida para baixo da gôndola para não empurrá-la ao meio; o comentário no código cita "feat(lobby): Refinar UX do Carousel de Linguagens, restaurar votação e sincronização entre telas #99 item 1").Lobby.tsx:202-242, bloco próprio (mt-6 border-t pt-5), com nota em:101.Visual
globals.css:124-130: "Sem fundo próprio: os estandartes ficam suspensos sobre o fundo da aplicação". Detalhe que mostra que o item foi entendido, não só marcado: brilho e sombra foram parafilter/drop-shadowem vez debox-shadow— este último redesenharia a caixa retangular e devolveria exatamente a moldura que você pediu para tirar.globals.css:142-146([data-centered="true"]), escrito pelo rAF emBannerCarousel.tsx:209— sem re-render do React. Estado distinto do escolhido (aria-checked→ halo verde,:149-151), que era necessário porque aqui dá para navegar sem votar.Física
physics_ammo_clothintegrado →src/lib/cloth/ammoCloth.ts(soft-body do Bullet atrás da fronteiraClothEngine), carregado porimport()dinâmico.BannerCarousel.tsx:292-315. Números medidos no comentário da PR: ponta atrasa 12 px no arremesso, duas oscilações ao soltar, repouso em 2,8 s; 3,22 ms/quadro com 7 panos contra 16,7 ms de orçamento.Funcional
Lobby.tsx:29-32e:49-57, combadges={voteTally}eleadingIdsno carousel. OcommitOnSettle={false}de:139-142resolve um problema que a issue não previu: sem ele, arrastar votaria em cada linguagem que passasse pelo centro.centerOn={room.settings.language}emLobby.tsx:145, consumido emBannerCarousel.tsx:108e:379-392, que trata explicitamente a chegada tardia docenterOn(no lobby a sala carrega depois da primeira pintura) e para de seguir a sala assim que o jogador vota.Fecho como concluída em vez de só tirar o
blocked: com as 12 ACs verdes, deixar aberta faria a issue disputar a fila com trabalho que ainda não existe. Se algum item ficou aquém do que você imaginou — em especial o peso percebido do tecido e a nova posição dos botões, que são julgamento visual e eu não tenho como medir — reabra ou abra a fatia de ajuste; a base agora está em produção para comparar.Uma coisa que a entrega não cobre e que não é AC daqui: as animações do carousel honram
prefers-reduced-motion(BannerCarousel.tsx:100,292,404,480), mas boa parte do resto da UI não — abri a #108 para isso.