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

@orkestra-ai/contraste

v0.1.0

Published

A régua de contraste da suíte Orkestra: mede todas as superfícies x papéis x temas de um globals.css contra os mínimos da WCAG 2.1. Zero dependências.

Readme

@orkestra-ai/contraste

Mede o contraste de um globals.css contra os mínimos da WCAG 2.1 §1.4.3 — todas as superfícies × todos os papéis de texto × os dois temas.

Zero dependências. Node ≥ 18.

npx @orkestra-ai/contraste app/globals.css
=== app/globals.css
    temas lidos: escuro=":root"  claro=":root[data-theme="light"]"
    32 pares medidos
    todos dentro do mínimo da WCAG

Sai com 1 se algum par reprovar, se um bloco de tema não for encontrado, se um token faltar ou se um valor não for hexadecimal. Serve como portão de CI.

Por que mede tudo, e não uma superfície

Porque foi assim que um defeito real passou. Uma correção anterior mediu o texto apagado contra um fundo, passou com 4,67:1 e declarou vitória. O mesmo token dava 4,46:1 sobre o fundo elevado e 4,16:1 sobre o painel — e é dentro de cartão que os rótulos vivem. Um portão só mede a pergunta que ele faz.

Dois mínimos, e o segundo é o esquecido

| | mínimo | | ------------------------------------------------------------------ | ------ | | texto normal | 4,5:1 | | texto grande e elemento gráfico — borda de 1px, traço de ícone | 3,0:1 |

Texto desabilitado é medido contra o piso gráfico: ele precisa de ser perceptível, não confortável. Exigir-lhe 4,5:1 obrigaria a uma cor que já não se lê como desabilitada.

O que ele lê

Tokens --color-* declarados em blocos de tema:

  • escuro: :root, html, e dentro de @media (prefers-color-scheme: dark);
  • claro: :root[data-theme="light"], html[data-theme="light"], .light, :root.light.

Superfícies: --color-bg-base, --color-bg-raised, --color-bg-sunken, --color-bg-panel. Papéis: --color-text-primary, --color-text-secondary, --color-text-muted, --color-text-disabled.

At-rules que não são tema são ignoradas — inclusive o @theme do Tailwind v4, cujos valores são pontes var() e não cores.

--color-text-inverted fica fora de propósito: é usado sobre preenchimento de acento, não sobre superfície, e medi-lo contra as superfícies daria números plausíveis e sem sentido.

Nunca sai verde sem medir

É a propriedade que o pacote existe para garantir. Uma régua que lê CSS e não encontra os tokens reportaria zero reprovações e passaria — por isso toda lacuna lança, com o motivo e o ficheiro nomeados: bloco ausente, token ausente, valor não hexadecimal.

API

import { medirCss, tokensDoCss, razao, MINIMO_TEXTO } from '@orkestra-ai/contraste';

const v = medirCss(css, 'app/globals.css');
v.reprovadas; // Medicao[]
razao('#757f9c', '#10162a'); // 4.51

Aviso

Ferramenta interna da suíte Orkestra, publicada para os nossos repositórios a poderem instalá-la. Funciona para qualquer projeto com a mesma convenção de tokens, mas a lista de superfícies e papéis não é configurável nesta versão.

MIT.