npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

germinastack-ui-components

v1.0.6

Published

Componentes HTML, CSS e JavaScript vanilla para interfaces GerminaStack.

Downloads

688

Readme

GerminaStack UI Components

Kit de componentes em HTML, CSS e JavaScript vanilla. Sem framework; o Rollup gera os arquivos públicos em dist/.

Começando agora? Leia o guia para iniciantes. Antes de produção, leia o guia de segurança.

Instalação

npm install germinastack-ui-components

Bundler

import "germinastack-ui-components/styles.css";
import { Button, Card, ui } from "germinastack-ui-components";

document.body.append(Card("Conteúdo"), Button({ label: "Continuar" }));
ui.showToast({ title: "Pronto", message: "Kit carregado." });

O runtime é exposto como window.GerminaStackUI. Para markup inserido depois do carregamento, inicialize apenas o novo escopo:

window.GerminaStackUI.init(document.querySelector("#nova-area"));

HTML sem bundler

Depois de copiar os arquivos para uma pasta pública, use os caminhos públicos — nunca node_modules diretamente:

<link rel="stylesheet" href="/static/vendor/germinastack/css/germinastack.css" />
<script src="/static/vendor/germinastack/js/germinastack.js" defer></script>

O runtime fica em window.GerminaStackUI; os exemplos Button e Card ficam em window.GerminaStack.

Projeto estático com postinstall

Instale o pacote e coloque este script no package.json do projeto consumidor:

{
  "scripts": {
    "postinstall": "node ./node_modules/germinastack-ui-components/scripts/copy-to-static.mjs ./static/vendor/germinastack"
  }
}

Depois de npm install ou npm update, os arquivos vão para static/vendor/germinastack. O CSS já encontra a fonte em fonts/ nessa mesma pasta.

Uso mínimo

<main class="gs-page">
  <section class="gs-card">
    <h1>Título</h1>
    <button class="gs-btn gs-btn-primary" type="button">Continuar</button>
  </section>
</main>

O único stylesheet, germinastack.css, inclui contratos e aparência padrão. Para personalizar, sobrescreva os tokens --gs-* após o import.

Leitura confortável

O modo opt-in gs-readable usa a fonte local OpenDyslexic e espaçamento maior para conteúdos longos:

<article class="gs-readable" data-gs-letter-spacing="wide">
  <h2>Conteúdo para leitura</h2>
  <p>O espaçamento pode ser normal ou wide.</p>
</article>

A fonte e sua licença acompanham o pacote; não há requisição a CDN.

Temas de produto opcionais

Importe o tema depois do stylesheet base e escolha os atributos no elemento <html>:

import "germinastack-ui-components/styles.css";
import "germinastack-ui-components/themes.css";

document.documentElement.dataset.tema = "dark";
document.documentElement.dataset.fonte = "open_dyslexic";
document.documentElement.dataset.espacamento = "grande";
document.documentElement.dataset.tamanho = "grande";

Temas disponíveis: normal, dark, high_contrast, black_yellow e yellow_black. Fontes: normal, arial, verdana, lexend, atkinson_hyperlegible e open_dyslexic. Espaçamento (data-espacamento): normal, pequeno e grande — ajusta letter-spacing/word-spacing do texto corrido. Tamanho (data-tamanho): normal, pequeno e grande — escala a página inteira via zoom (ver comentário em src/themes/product-themes.css sobre por que não é baseado em rem).

Em HTML estático, inclua themes.css depois de germinastack.css:

<html data-tema="dark" data-fonte="open_dyslexic" data-espacamento="grande" data-tamanho="grande">
  <head>
    <link rel="stylesheet" href="/static/vendor/germinastack/css/germinastack.css" />
    <link rel="stylesheet" href="/static/vendor/germinastack/themes.css" />
  </head>

Popover de notificações (opcional)

Mesmo princípio de themes.css: um extra específico do produto GerminaStack, fora do kit, importado só por quem usa o popover de notificações do cabeçalho (classes .gs-notif-*). Reaproveita o menu contextual do kit (.gs-menu / .gs-menu-panel) só para dar mais largura e rolagem ao painel — sem isso, o popover funciona com o tamanho padrão do kit (240px, sem teto de altura).

import "germinastack-ui-components/styles.css";
import "germinastack-ui-components/notifications.css";

Em HTML estático:

<link rel="stylesheet" href="/static/vendor/germinastack/css/germinastack.css" />
<link rel="stylesheet" href="/static/vendor/germinastack/notifications.css" />

Publicação

npm login
npm run check
npm publish

O nome germinastack-ui-components estava disponível no registry no momento da preparação. O prepublishOnly executa as validações antes do publish.

Publicação automática pelo GitHub Actions

O workflow publish.yml roda após merge na main. Ele valida o pacote e publica somente quando a versão de package.json ainda não existe no npm.

Antes do primeiro merge, configure o Trusted Publisher no npm para o pacote:

  1. npmjs.com → pacote → SettingsTrusted Publisher → GitHub Actions.
  2. Owner: Nicolas25vlad; Repository: germinastack-ui-components; Workflow: publish.yml.
  3. Autorize a ação npm publish.

Isso usa OIDC e não exige salvar token npm no GitHub. Para lançar uma versão, altere version em uma PR e faça o merge depois do CI e da aprovação.

Estrutura do projeto

src/                    # onde o time edita
  css/
    01-foundations.css  # tokens, reset e acessibilidade global
    02-layout.css       # grid, página e navegação
    03-actions-and-surfaces.css
    04-content-and-forms.css
    05-feedback-and-docs.css
    06-advanced-components.css
    07-theme.css        # aparência final e overrides
  js/
    germinastack.js     # runtime do kit
    docs.js             # apenas para a página de documentação
  components/
    Button.js
    Card.js
  themes/               # extras opcionais do produto, fora do kit
    product-themes.css        # -> dist/themes.css
    product-notifications.css # -> dist/notifications.css
  fonts/
    OpenDyslexic-Regular.woff2
  index.js              # entrada ESM
dist/                   # gerado; é o que aplicações e npm consomem
rollup.config.mjs       # gera UMD, ESM, CSS e fontes
scripts/copy-to-static.mjs
index.html              # documentação viva
playground.html         # validação visual

Edite somente src/, rode npm run build e nunca altere dist/ manualmente.

O que o kit cobre hoje

  • hero, topbar, cards, sidebar e blocos de conteúdo
  • botões, chips, badges e segmentado
  • composer, inputs, textarea, select e comentário inline
  • post, comentários, reply e menu contextual
  • métricas, progresso, timeline, tabela, callout e empty state
  • accordion, modal, toast, banner e alert
  • pricing cards e blocos de showcase
  • select/combobox com busca, grupos e navegação por teclado
  • date picker / date range picker com calendário acessível
  • data table com ordenação, filtro, paginação e seleção de linhas
  • tooltip / popover com posicionamento automático e conteúdo rico

Bootstrap mínimo

<link rel="stylesheet" href="./dist/css/germinastack.css" />
<script src="./dist/js/germinastack.js" defer></script>

<main class="gs-page">
  <section class="gs-card">Conteúdo</section>
</main>

Fluxo recomendado para o time

  1. Validar visualmente o componente ou layout em playground.html.
  2. Consultar index.html para pegar markup, classes e contratos de comportamento.
  3. Copiar o bloco necessário para a tela real.
  4. Ajustar conteúdo, dados e tokens.
  5. Criar JS específico do produto fora do kit quando a interação deixar de ser genérica.

Convenções

  • prefixo CSS: gs-
  • prefixo de comportamento: data-gs-*
  • customização preferencial: sobrescrever tokens, não duplicar componente
  • regra de negócio: fora do kit
  • responsividade: reduzir colunas antes de mexer em tipografia e spacing

Contratos JS disponíveis

  • window.GerminaStackUI.init(root) Inicializa um escopo novo quando markup é inserido dinamicamente (tabs, menus, toasts, dismiss, accordion, selects, datepickers, datatables, tooltips).
  • window.GerminaStackUI.validateAccessibility(root) Marca e informa imagens sem alt, campos sem label/nome e botões ou links sem nome acessível.
  • window.GerminaStackUI.showToast({ title, message, tone, duration }) Dispara toast programaticamente.
  • window.GerminaStackUI.request(url, options) Consome uma API JSON com serialização de body e erros HTTP normalizados.
  • window.GerminaStackUI.closeMenus() Fecha todos os menus contextuais abertos.
  • window.GerminaStackUI.openModal(modalEl) Abre modal com armadilha de foco e anúncio.
  • window.GerminaStackUI.closeModal(modalEl) Fecha modal com restauração de foco.
  • window.GerminaStackUI.activateTab(tabBtn) Ativa uma tab programaticamente.
  • window.GerminaStackUI.toggleAccordion(triggerBtn) Alterna accordion com anúncio para leitor de tela.
  • window.GerminaStackUI.announceToScreenReader(message, priority) Anuncia mensagem via região ao vivo ("polite" | "assertive").
  • window.GerminaStackUI.trapFocus(element) Ativa armadilha de foco em um elemento (usado internamente por modais).
  • window.GerminaStackUI.initSelects(root) Inicializa selects/combobox com busca, grupos e navegação por teclado.
  • window.GerminaStackUI.initDatePickers(root) Inicializa date pickers e range pickers com calendário acessível.
  • window.GerminaStackUI.initDataTables(root) Inicializa data tables com ordenação, filtro, paginação e seleção.
  • window.GerminaStackUI.initTooltips(root) Inicializa tooltips e popovers com posicionamento automático.

Receitas práticas

Tela nova

  1. Comece por gs-page.
  2. Estruture com gs-stack, gs-grid-2, gs-grid-3 ou gs-grid-4.
  3. Use gs-card, gs-side-card, gs-showcase-card e gs-post como blocos principais.

Dashboard

  1. Abra com gs-metric-grid.
  2. Adicione gs-progress, gs-kpi-strip e gs-table.
  3. Se houver sequência temporal, encaixe gs-timeline.

Interações

  • tabs: data-gs-tabs, data-gs-tab, data-gs-panel
  • menu: data-gs-menu, data-gs-menu-trigger, data-gs-menu-panel
  • modal: data-gs-modal-open, data-gs-modal, data-gs-modal-close
  • accordion: data-gs-accordion-item, data-gs-accordion-trigger, data-gs-accordion-panel
  • feedback rápido: data-gs-toast ou GerminaStackUI.showToast(...)
  • select/combobox: data-gs-select, data-gs-select-search, data-gs-select-placeholder, data-gs-select-multiple
  • date picker: data-gs-datepicker, data-gs-datepicker-range, data-gs-datepicker-placeholder
  • data table: data-gs-datatable, data-gs-datatable-sort, data-gs-datatable-filter, data-gs-datatable-paginate, data-gs-datatable-page-size
  • tooltip: data-gs-tooltip, data-gs-tooltip-content, data-gs-tooltip-placement
  • popover: data-gs-popover, data-gs-popover-trigger, data-gs-popover-title, data-gs-popover-content

Novos componentes (v1.2)

Select / Combobox

<div class="gs-select" data-gs-select data-gs-select-search data-gs-select-placeholder="Selecione...">
  <button class="gs-select-trigger" type="button" aria-haspopup="listbox" aria-expanded="false">
    <span class="gs-select-value">Selecione...</span>
    <span class="gs-select-icon" aria-hidden="true">▼</span>
  </button>
  <div class="gs-select-panel" role="listbox" hidden>
    <div class="gs-select-search"><input type="text" placeholder="Buscar..." aria-label="Filtrar opções" /></div>
    <div class="gs-select-group">
      <span class="gs-select-group-label">Grupo</span>
      <div class="gs-select-option" role="option" data-value="1" aria-selected="false">Opção 1</div>
      <div class="gs-select-option" role="option" data-value="2" aria-selected="false">Opção 2</div>
    </div>
  </div>
</div>

Atributos: data-gs-select (raiz), data-gs-select-search (habilita busca), data-gs-select-placeholder, data-gs-select-multiple (seleção múltipla)

Teclado: Enter/Space abre, ↑↓ navega, Esc fecha, digita para filtrar, Home/End primeiro/último

Acessibilidade: role="listbox", role="option", aria-selected, aria-controls, aria-expanded, busca anuncia resultados via aria-live


Date Picker / Date Range Picker

<div class="gs-datepicker" data-gs-datepicker data-gs-datepicker-placeholder="Selecione uma data">
  <button class="gs-datepicker-trigger" type="button" aria-haspopup="dialog" aria-expanded="false">
    <span class="gs-datepicker-value">Selecione uma data</span>
    <span class="gs-datepicker-icon" aria-hidden="true">📅</span>
  </button>
  <div class="gs-datepicker-panel" role="dialog" aria-modal="true" aria-label="Selecionar data" hidden>
    <div class="gs-datepicker-header">
      <button class="gs-datepicker-nav" type="button" aria-label="Mês anterior">‹</button>
      <span class="gs-datepicker-title">Janeiro 2025</span>
      <button class="gs-datepicker-nav" type="button" aria-label="Próximo mês">›</button>
    </div>
    <div class="gs-datepicker-grid" role="grid" aria-label="Dias do mês">
      <div class="gs-datepicker-weekday" role="columnheader">Dom</div>
      <!-- ... dias da semana ... -->
      <div class="gs-datepicker-day" role="gridcell" aria-selected="false" tabindex="-1">1</div>
      <!-- ... dias do mês ... -->
    </div>
  </div>
</div>

Atributos: data-gs-datepicker (raiz), data-gs-datepicker-range (seleção de intervalo), data-gs-datepicker-placeholder

Teclado: Enter abre, setas navegam dias, PgUp/PgDn muda mês, Home/End primeira/última semana, Esc fecha

Acessibilidade: role="dialog", aria-modal="true", role="grid", role="gridcell", aria-selected, navegação por grade 2D


Data Table

<div class="gs-datatable" data-gs-datatable data-gs-datatable-sort data-gs-datatable-filter data-gs-datatable-paginate data-gs-datatable-page-size="10">
  <div class="gs-datatable-toolbar">
    <input type="text" class="gs-datatable-filter-input" placeholder="Filtrar..." aria-label="Filtrar linhas" />
    <div class="gs-datatable-info" aria-live="polite"></div>
  </div>
  <div class="gs-datatable-wrap">
    <table class="gs-table">
      <thead>
        <tr>
          <th scope="col" data-gs-sort="string">Nome</th>
          <th scope="col" data-gs-sort="number">Valor</th>
          <th scope="col" data-gs-sort="date">Data</th>
          <th scope="col"><input type="checkbox" class="gs-datatable-select-all" aria-label="Selecionar todas" /></th>
        </tr>
      </thead>
      <tbody>
        <tr data-gs-row>
          <td>Item 1</td>
          <td>100</td>
          <td>2025-01-15</td>
          <td><input type="checkbox" class="gs-datatable-row-select" /></td>
        </tr>
      </tbody>
    </table>
  </div>
  <div class="gs-datatable-pagination" aria-label="Paginação">
    <button class="gs-datatable-page-btn" type="button" aria-label="Primeira página" disabled>««</button>
    <button class="gs-datatable-page-btn" type="button" aria-label="Página anterior" disabled>«</button>
    <span class="gs-datatable-page-info">Página 1 de 5</span>
    <button class="gs-datatable-page-btn" type="button" aria-label="Próxima página">»</button>
    <button class="gs-datatable-page-btn" type="button" aria-label="Última página">»»</button>
  </div>
</div>

Atributos: data-gs-datatable (raiz), data-gs-datatable-sort, data-gs-datatable-filter, data-gs-datatable-paginate, data-gs-datatable-page-size

Colunas: data-gs-sort="string|number|date" no <th>

Teclado: Tab navega células, Enter/Space ordena (cabeçalho), Space seleciona linha (checkbox)

Acessibilidade: scope="col", aria-sort no cabeçalho ativo, aria-live no contador, checkboxes com aria-label


Tooltip / Popover

<!-- Tooltip -->
<button class="gs-btn gs-btn-secondary" type="button" 
        data-gs-tooltip 
        data-gs-tooltip-content="Dica contextual" 
        data-gs-tooltip-placement="top">
  Passe o mouse
</button>

<!-- Popover -->
<button class="gs-btn gs-btn-primary" type="button" 
        data-gs-popover 
        data-gs-popover-trigger="click" 
        data-gs-popover-title="Ações" 
        data-gs-popover-content="Ações disponíveis para este item.">
  Clique para ver
</button>

Tooltip atributos: data-gs-tooltip, data-gs-tooltip-content, data-gs-tooltip-placement (top|right|bottom|left)

Popover atributos: data-gs-popover, data-gs-popover-trigger (hover|click), data-gs-popover-title, data-gs-popover-content (texto simples)

Teclado: Esc fecha, foco move para popover ao abrir (trigger=click)

Acessibilidade: role="tooltip" para tooltip, role="dialog" para popover, aria-describedby no trigger, posicionamento com Floating UI logic (viewport clamping, flip, shift)


Checklist antes de entregar uma tela

  • os tokens foram reaproveitados sem cor solta?
  • existe um único CTA primário por área?
  • o layout colapsa bem em mobile?
  • estados de foco e hover continuam visíveis?
  • a interação poderia ser resolvida por data-gs-* antes de criar JS novo?

Acessibilidade (WCAG 2.1 AA)

O kit implementa recursos de acessibilidade nativos. Antes de entregar, valide:

O runtime completa o estado de tabs (role="tab", role="tabpanel", aria-selected, aria-hidden), mantém o painel ativo focável, fecha modais com Escape restaurando o foco e atualiza aria-expanded nos comentários. Para novos componentes, prefira HTML nativo e só adicione ARIA quando o comportamento não puder ser expresso pelo elemento nativo.

Checklist de acessibilidade

  • [ ] Navegação por teclado: Toda funcionalidade acessível via Tab, Shift+Tab, setas, Enter, Space e Esc
  • [ ] Foco visível: Anel de foco (--gs-focus-ring-width, --gs-focus-ring-color) visível em todos os elementos interativos
  • [ ] Armadilha de foco em modais: Tab/Shift+Tab cicla dentro do modal; foco restaura ao fechar
  • [ ] Regiões ao vivo: Toasts, accordion e modal anunciam mudanças via aria-live
  • [ ] ARIA automático: Tabs (role="tablist/tab/tabpanel"), Accordion (aria-expanded, aria-controls), Menu (aria-expanded, aria-haspopup)
  • [ ] Contraste: Tokens principais atendem AA (4.5:1) — veja tabela abaixo
  • [ ] Alto contraste: prefers-contrast: high mantém bordas, foco e estados visíveis
  • [ ] Cores forçadas: forced-colors: active usa cores do sistema sem quebrar UI
  • [ ] Redução de movimento: prefers-reduced-motion: reduce elimina animações/transições
  • [ ] Zoom 200%: Layout funcional sem scroll horizontal
  • [ ] Labels: Todo input tem <label> explícita; ícones decorativos têm aria-hidden="true"

Tabela de contraste dos tokens principais

| Token | Cor | Fundo | Contraste | WCAG | |-------|-----|-------|-----------|------| | --gs-color-navy-900 | #0a1929 | #fff | 18.2:1 | ✅ AAA | | --gs-color-navy-700 | #1a3a5c | #fff | 10.4:1 | ✅ AAA | | --gs-color-text | #0a1929 | #f0f2f5 | 17.1:1 | ✅ AAA | | --gs-color-text-secondary | #546e7a | #f0f2f5 | 5.2:1 | ✅ AA | | --gs-color-primary | #ff8c00 | #fff | 3.0:1 | ⚠️ Apenas texto grande (≥18pt/14pt bold) |

Testes manuais recomendados

  1. Teclado: Navegue toda a interface sem mouse
  2. Leitor de tela: NVDA (Windows) ou VoiceOver (macOS) — verifique anúncios de tabs, accordion, modal, toasts
  3. Alto contraste: DevTools → Rendering → Emule prefers-contrast: high e forced-colors: active
  4. Redução de movimento: DevTools → Rendering → Emule prefers-reduced-motion: reduce
  5. Zoom: Amplie a 200% — sem scroll horizontal

Diretrizes de contribuição para acessibilidade

  • Novos componentes: Devem incluir role apropriado, aria-* necessários e navegação por teclado
  • Novos tokens de cor: Validar contraste AA (4.5:1 texto normal, 3:1 texto grande) antes de merge
  • Animações: Respeitar prefers-reduced-motion — use transition: none !important no media query
  • Foco: Nunca remova outline sem substituir por :focus-visible com anel visível
  • Testes: Rode checklist acima em PRs que tocam componentes interativos

Histórico git desta entrega

  • 967038f feat: scaffold GerminaStack UI kit foundation
  • f99c400 docs: add living documentation and playground
  • 590213f docs: add repository handoff guides
  • 39f85ff refactor: move UI kit to repository root
  • a11y feat: WCAG 2.1 AA accessibility enhancements (focus trap, live regions, keyboard nav, high contrast, reduced motion)
  • v1.2 feat: add Select/Combobox, DatePicker/RangePicker, DataTable, Tooltip/Popover components with full accessibility