2 pontos por GN⁺ 14 시간 전 | 1 comentários | Compartilhar no WhatsApp
  • Jelly UI v1.1 é uma biblioteca de Web Components sem dependências que combina controles de formulário reais com efeitos de física de corpo macio e gelatinoso, oferecendo 40 elementos personalizados
  • A instalação é feita com um único script de módulo e há suporte a modo escuro, acompanhamento automático do tema do sistema operacional, alteração da cor de destaque e layout RTL, da direita para a esquerda
  • Os botões usam um <button> nativo, e os sliders usam uma entrada range oculta para manter a semântica nativa para operação por teclado, leitores de tela e participação em formulários
  • De checkboxes e campos de entrada a toasts, abas e diálogos, vários elementos recebem animações táteis como pressionar, esticar, ondular e quicar
  • Com tokens de cor WCAG AA e padrões ARIA integrados, permite criar interfaces de produto acessíveis mantendo efeitos visuais suaves

Instalação e tema

  • O Jelly UI pode ser usado sem dependências, com 40 elementos personalizados e apenas uma tag <script type="module">
    <script type="module" src="https://jelly-ui.com/package.js"></script>;
    
    <jelly-theme mode="auto">
      <jelly-button variant="mint">Publish</jelly-button>
    </jelly-theme>
    
  • <jelly-theme> é um provedor de tema que aplica tokens de design de forma limitada à subárvore
    • mode aceita auto, light e dark, permitindo seguir as configurações do sistema operacional ou forçar um tema específico
    • accent permite redefinir a cor de destaque
  • As variações de cor comuns são azure, rose, amber, mint, graphite, platinum e white; os tamanhos são principalmente small, medium e large

Botões e elementos de ação

  • <jelly-button> é um botão em formato de cápsula que inclui internamente um <button> nativo real para dar suporte a teclado e leitores de tela
    • Permite configurar cor, tamanho, formatos pill e square, desativação e layout em bloco
  • <jelly-icon-button> é um botão quadrado ou circular ajustado para um único ícone
    • O atributo label define o nome reconhecido por leitores de tela

Controles de entrada de formulário

  • <jelly-checkbox> participa de formulários, aceita checked e estado indeterminado (indeterminate), e o quadrado gelatinoso salta quando o estado muda
  • <jelly-input> é um campo de entrada de uma linha para text, email e password
    • Ao receber foco, a superfície se eleva e a borda aparece; a cada entrada, uma onda se espalha a partir da posição do cursor
    • Aceita disabled e readonly
  • <jelly-label> se associa ao controle via for
    • Ao clicar, leva o foco ao destino, o texto do rótulo se torna o nome acessível, e é possível definir obrigatoriedade e tamanho
  • <jelly-otp> é uma entrada de código de uso único que oferece uma caixa para cada dígito
    • Trata digitação, Backspace, teclas de seta e colagem, além de permitir configurar comprimento, cor, tamanho e desativação
  • <jelly-radio> forma um grupo entre itens que compartilham o mesmo name na mesma raiz
    • Aceita navegação por teclas de seta com tabindex móvel e considerando a direção do documento
  • <jelly-radio-group> é um contêiner radiogroup com rótulo para jelly-radio
    • Oferece legenda, layout de fluxo horizontal ou vertical e propagação de tamanho para os elementos filhos
  • <jelly-range> é um slider de dois handles para escolher um intervalo entre valor mínimo e máximo
    • Aplica role="slider", foco e ARIA aos dois controles; ao arrastar, os handles gelatinosos são pressionados
  • <jelly-segmented> é uma trilha em formato de cápsula com opções mutuamente exclusivas
    • O indicador de seleção se comporta como uma pílula gelatinosa que se inclina e se estica ao se mover entre os segmentos
  • <jelly-select> é um dropdown integrado a formulários que usa os padrões ARIA combobox e listbox
    • Tanto o gatilho quanto o painel de opções são compostos por superfícies de corpo macio
    • O painel se expande a partir do campo e, se não houver espaço suficiente abaixo, muda para cima
  • <jelly-slider> é um slider para escolher um único valor
    • Uma entrada range nativa oculta cuida da semântica e da participação no formulário, enquanto na tela aparece um handle gelatinoso pressionável
  • <jelly-switch> é um switch arrastável: o handle se estica como uma gota líquida, e as cores de desligado/ligado alternam entre si
  • <jelly-textarea> cresce automaticamente entre alturas mínima e máxima conforme a entrada de várias linhas
    • A superfície também se estica de acordo com a altura; ao digitar, uma onda surge na posição do cursor, e há suporte a disabled e readonly

Estado e feedback

  • <jelly-alert> é um banner com quatro tons — info, success, warning e danger — e um botão de fechar opcional
  • <jelly-badge> é um pequeno elemento usado para badges, tags e indicadores de status, que salta quando o texto muda
    • Permite configurar preenchimento ou contorno, formatos de pílula ou quadrado, e comportamentos live e instant
  • <jelly-progress> é uma barra de progresso cuja parte frontal do preenchimento oscila conforme o avanço
    • No modo indeterminado, o bloco quica entre as duas paredes
  • <jelly-skeleton> é um placeholder de carregamento que balança suavemente como se respirasse, em vez de brilhar
    • Aceita os formatos line, rect e circle
  • <jelly-spinner> oferece um indicador dots, em forma de massa viscosa que se move entre três pontos, e um blob, que gira enquanto muda de forma
  • <jelly-toaster> gerencia notificações toast que aparecem e desaparecem a partir da extremidade inline
    • Normalmente é chamado pelo helper jellyToast('Saved!', { tone: 'success' })
    • Ao definir position="bottom" no elemento posicionado, a pilha de notificações cresce para cima

Superfícies de conteúdo

  • <jelly-accordion> agrupa vários itens <jelly-collapsible>
    • No modo single, quando um item é aberto, os demais se fecham com efeito de quique
  • <jelly-card> é um contêiner de superfície gelatinosa colocado abaixo do conteúdo
    • Ao adicionar squish, ele é pressionado como uma almofada macia e atua como botão
  • <jelly-chip> pode ser usado como rótulo estático, filtro alternável ou tag removível
    • Permite configurar se é selecionável, selecionado, removível ou desativado
  • <jelly-collapsible> é uma área expansível/recolhível que abre e fecha um painel com efeito de quique por meio de um botão de cabeçalho
    • É configurado para que a superfície se mova, não o texto
  • <jelly-divider> é uma linha divisória fina horizontal, vertical ou com rótulo
  • <jelly-kbd> é uma keycap gelatinosa que pode ser pressionada
    • Ao vinculá-la a uma tecla real com key, a keycap também desce enquanto essa tecla estiver sendo pressionada em qualquer lugar da página

Navegação e layout

  • <jelly-resizable> é uma grade de painéis cujo tamanho pode ser ajustado arrastando divisórias gelatinosas ou pelo teclado
    • Aceita as direções row, vertical e both
  • <jelly-tabs> é uma visualização em abas que usa semântica real de tablist
    • O indicador de seleção em forma de pílula gelatinosa se move, e os painéis de abas aparecem com efeito de quique

Overlays

  • <jelly-dialog> é uma caixa de diálogo modal que aparece saltando como gelatina
    • Bloqueia a página e, depois de fechada, devolve o foco à posição anterior
    • Pode ser fechada pela tecla Escape, pelo botão de fechar ou por clique no plano de fundo
  • <jelly-drawer> é uma folha flutuante que aparece com efeito de mola, passando levemente do limite e voltando
    • Pode abrir a partir do início ou fim inline, ou pela parte inferior
  • <jelly-popover> é um painel não modal aberto por clique
    • Fica ancorado ao gatilho e fecha com a tecla Escape ou clique externo
    • Aceita posicionamentos top, bottom, start e end
  • <jelly-tooltip> mostra um balão com tema acima do gatilho ao passar o mouse ou receber foco pelo teclado
    • Aceita posicionamento nas quatro direções e três tamanhos

1 comentários

 
Comentários no Hacker News
  • A janela estava meio engasgando, então fui investigar a causa, e esta biblioteca executa um loop de animação com requestAnimationFrame (RAF) a cada 8 ms em todos os componentes da página, fazendo o documento inteiro ser redesenhado
    O comentário acima, de que “processa os componentes ativos juntos em um quadro e para quando está ocioso”, também parece ter sido gerado por IA. O JellyEngine não calcula a animação gelatinosa apenas quando ocorrem eventos de ponteiro; ele recalcula, a cada quadro, todos os componentes ativos da página. É uma implementação que uma pessoa comum olharia e diria: “não faça isso, é exagerado demais”

    • Fiz profiling de desempenho no Chrome e isso não sustentou essa explicação. O loop parece gerenciar os componentes a atualizar com um Set() ativo e removê-los quando o movimento para
      Concordo que o comentário parece um tanto gerado às pressas por IA, mas não encontrei nenhum problema evidente na abordagem em si, e, quando nada está acontecendo, o loop principal termina em poucos microssegundos
    • Não é uma abordagem exagerada. 99,99% dos videogames funcionam literalmente assim, redesenhando a tela inteira continuamente enquanto a taxa de atualização com sincronização vertical ou o desempenho do hardware permitir
  • Gostei, mas parece não estar alinhado com as práticas padrão de UX
    Acho que, se você mantiver pressionado e mover o mouse para fora do elemento, isso não deveria ser tratado como clique. Atualmente, o botão trata como clique, mas a caixa de seleção não, então falta consistência

    • Era um problema que eu sempre enfrentava ao trabalhar com desenvolvedores Flash. O princípio “não reimplemente uma barra de rolagem se você não consegue implementar todos os recursos dela” era comum, mas no fim acabávamos corrigindo mais de cinco vezes e gastando dias nisso
    • Boa descoberta; ajustei a lógica do botão, e agora o clique não acontece se o cursor estiver fora dos limites do botão
  • É sinceramente fofo, e também gosto do fato de reduzir o recurso de forma natural em @media (prefers-reduced-motion: reduce)
    Ainda assim, no site de demonstração seria bom permitir que o usuário sobrescrevesse isso sem alterar a configuração do sistema, ou pelo menos exibir um aviso de que a animação não está sendo mostrada

    • Não percebi que a redução de movimento era intencional e achei que estava quebrado. Eu também tinha esquecido que havia ativado essa configuração antes
    • Menu Apple > Ajustes do Sistema > Acessibilidade > Movimento, onde é possível configurar Reduzir Movimento
      Sempre que aparece uma demo bacana dessas, demoro um pouco para lembrar da configuração e, enquanto isso, fico clicando decepcionado, pensando “o que isso tem de especial?”
    • Agora ele mostra uma notificação e também permite tocar no ícone fofo de coelho para sobrescrever a configuração do sistema
  • Quando eu era mais jovem, teria adorado isso, mas hoje passo mais tempo removendo esse tipo de efeito com folhas de estilo locais ou usando modo escuro e modo de leitura. Os tempos mudaram muito

    • Gosto da animação porque ela serve como feedback que destaca o que está acontecendo ou mudando no momento. Componentes nativos nem sempre expressam isso bem, e animações bem usadas não são só decoração; têm valor real de UX
    • Mais ou menos uma vez por ano eu volto a querer mais diversão no software, para depois voltar a querer apenas que ele não atrapalhe
  • Seria bom se o efeito aparecesse com baixa intensidade também ao passar o mouse. Alguns controles, como barras de progresso e toasts, parecem não ter o efeito gelatinoso
    O desempenho da página de demonstração também não é lá essas coisas e dá a impressão de sequestrar a rolagem, mas, no geral, é fofo e parece combinar bem com UIs de jogos

  • O elemento Chip deveria permanecer no lugar durante a transição, mas, ao clicar, ele sai para fora dos limites, o que não me agrada

  • É fofo, mas a velocidade de resposta de alguns controles é ruim demais. Ao arrastar o slider para frente e para trás, ele fica muito atrás do cursor do mouse; deveria seguir o cursor como se estivesse colado a ele
    Por outro lado, outros controles, como jelly-resizable, se movem bem grudados ao cursor. O controle "Placeholder" parece não remover o placeholder quando clicado

  • Fico me perguntando se alguém se lembra de que, por volta de 2007–2010, havia um efeito gelatinoso parecido nas bordas das páginas do site, blog e showcase do Paul Neave. Na época, era implementado em Flash
    Naqueles tempos, Paul Neave era um herói pessoal para mim; se ele estiver lendo isto, espero que esteja bem

  • É difícil encontrar algo neste sistema de design de UI que possa ser chamado de efeito físico

    • Esta biblioteca respeita a configuração de reduzir movimento do cliente e desativa todos os efeitos de animação
  • Pode ser por causa do meu tipo de daltonismo ou da configuração do meu monitor, mas o vermelho e o âmbar são tão parecidos que eu nem conseguia distinguir se o botão havia sido pressionado