@commenteme/react
v0.7.0
Published
Componentes React de commente.me (kit de marca e interface v3.3.1): os do admin da Especificaciones — campos, combobox, datas, filtros, tabela, gráficos, KPI, permissões, busca global ⌘K, status de pedido, modal, drawer, toast — e o layout com submenu e s
Downloads
622
Maintainers
Readme
@commenteme/react
Componentes React do admin de commente.me (app.commente.me), do kit de marca e
interface v3.3.1: botões, campos, controles de escolha, badges, avisos, abas, tabela, modal,
toast, stepper, configuração e o layout do admin (sidebar com submenu, drawer no celular,
topbar, cabeçalho de página). Medidas, cores e estados saem do kit; nenhum hex solto.
npm install @commenteme/reactTraz junto @commenteme/tokens e @commenteme/icons. React 18 ou 19.
Estilos
Com Tailwind 4:
@import "tailwindcss";
@import "@commenteme/tokens/tailwind.css";
@import "@commenteme/react/styles.css";Sem Tailwind, os tokens antes dos componentes:
import '@commenteme/tokens/tokens.css';
import '@commenteme/react/styles.css';O layout raiz do app leva .ctx-admin: fonte do sistema, base 14px, fundo papel gris.
Os estilos ficam na camada components, na mesma ordem de camadas do Tailwind. Uma classe
utilitária no className vence o componente: <Button className="w-full">.
Componentes
import { Button, Field, Input, Select, Badge, Alert } from '@commenteme/react';
<Button variant="primario" icon="sincronizar">Sincronizar</Button>
<Field label="RUT empresa" hint="Con guion." error={erro}>
<Input name="rut" />
</Field>| componente | o que é |
|---|---|
| Button | variant: primario (um por vista), secundario (padrão), acento (só ação comercial), fantasma, destructivo (só dentro da confirmação), peligro (contorno vermelho, o da zona de perigo). size: sm 32 · md 40 · lg 48, raio 6/8/10. icon de 16px. loading mostra o spinner e bloqueia o clique; loadingText="Guardando…" troca o texto. type="button" por padrão. |
| IconButton | Só ícone, quadrado. label é obrigatório e vira aria-label e title. |
| buttonClass() | As classes do botão para outro elemento: <Link className={buttonClass({ variant: 'primario' })}>. |
| Field | Rótulo em cima, controle, ajuda ou erro embaixo, já ligados (for, aria-describedby, aria-invalid). error troca a ajuda e marca o controle. disabled e required passam para o controle. |
| Input | 40px, raio 8. prefix e suffix (CLP $, https://, .myvtex.com), icon (buscar), shortcut (⌘K), mono (account name, SKU). |
| Select | O <select> nativo com o chevron-abajo. |
| Combobox | Para clientes, SKU, marketplaces: options (filtra sozinho pelo rótulo e pelo meta) ou onSearch (servidor, debounce de 250 ms, «Buscando…»). Coincidência em negrito sem acento nem caixa, até 8 visíveis, «Sin coincidencias para “zz”.». role="combobox" com aria-activedescendant; setas, Enter, Esc. Dentro de Field. |
| DateRangePicker | O período da topbar e dos filtros: «28-09 — 04-10» (ano só se não for o atual) e, com comparação, «vs. 21 — 27-09». Atalhos, dois meses com a semana na segunda, o futuro bloqueado, «Comparar con» (período anterior ou ano passado); nada muda até «Aplicar». size filtro 36 ou md 40. |
| DateInput | Data solta dd-mm-aaaa com os hífens entrando sozinhos e a validação ao sair (onValidityChange): o erro vai no Field. Funções formatFecha, parseFecha, formatRango, periodoComparado também para o servidor. |
| Textarea | maxLength + showCount mostra 12/280; dentro do Field, na linha do rótulo. |
| Checkbox | 18px, raio 5, check de 12 com traço 3,2; size="sm" é o da tabela, 16px, raio 4, check de 10 com traço 3,6. label, description, indeterminate. |
| RadioGroup + Radio | Fieldset com título; name e valor marcado (value ou defaultValue, onValueChange) vão para os radios. error põe a mensagem do grupo embaixo, ligada por aria-describedby. |
| RadioCard | Radio em cartão (o rol, o marketplace, o objetivo): padding 14, raio 10; selecionado com borda azul de 1,5 e --seleccion-fondo. Dentro de <RadioGroup cards>, a grade de 200px. |
| Switch | 36×20, role="switch". Com label, ocupa a linha: texto à esquerda, switch à direita. |
| Fieldset | Título + grupo de checkboxes ou switches. disabled desliga todos. |
| Badge | status: conectado, atencion, error, pausado, borrador. Ponto + texto; o texto padrão é o nome do estado. |
| OrderStatus, orderStatus(), OrderTimeline | O status de pedido do OMS: o código VTEX vira o nome em espanhol no badge certo (o mapa completo do kit; invoiced com tracking é «Despachado»); late soma o «Atrasado». A linha do tempo do detalhe: feito, atual e pendente. |
| Tag | kind: nuevo (amarelo) ou proximamente (contorno). |
| Counter | 20px, 11/700, vermelho. max mostra 99+. |
| Chip | Filtro aplicado: «Canal: Falabella» ou «Canal: 2». 36 de altura, fundo info, borda azul, × de 12. onRemove tira (pelo × ou Backspace com foco); onEdit reabre o filtro. |
| FilterButton, FilterBar | «+ Canal» com borda pontilhada, 36 de altura; a barra junta chips e botões e põe o «Limpiar» (onClear) no fim. |
| Alert | tone: info, atencion (fundo --atencion-fondo, ícone --atencion-icono), error, exito. Raio 10, ícone 18. title em negrito + texto; um link dentro sai sublinhado. |
| ErrorPage | 404, 500, sem permissão e sem conexão com VTEX (kind), com o texto do kit: código de 44 ou ícone na caixa de 52, título, texto e um botão secundário. |
| ConnectionBanner, SuperAdminBar | As faixas de atenção: «Sin conexión con VTEX desde las 09:12…» com «Reintentar», embaixo da topbar; e «Estás en la cuenta X como super admin…» com «Salir de la cuenta». |
| EmptyState | Ícone de 24, sem círculo, na caixa de 52px; title, texto até 40ch e no máximo uma action (primária no estado inicial, «Limpiar filtros» secundária sem resultados, nenhuma quando está ao dia). |
| Lockup, Ladrillo | O logo em curvas — não precisa da Barlow. onBlue para fundo azul: ladrillo e logotipo brancos, ponto amarelo. |
| Spinner, Icon | O spinner do botão e o <Icon> de @commenteme/icons. |
| Tabs + TabPanel | Abas com painéis: altura 40, 24 entre elas, a ativa 600 em azul com --activo-tab. Setas, Home e End trocam de aba. count põe o contador cinza. Mudam o conteúdo; para ver os mesmos dados de outro jeito, o segmentado. |
| NavTabs | Abas que são links (cada uma uma URL); a atual com current. |
| SegmentedControl | O segmentado único (Día · Semana · Mes, 2 a 4 opções): fundo papel gris, ativo em branco com --sombra-1. Radios nativos: entra no FormData. |
| Breadcrumb | Migalhas com «/» em --borde-campo, só a partir do nível 2; até 4 níveis (com mais, os do meio viram «…»); o último é a página atual, sem link. |
| Pagination | «Mostrando 26–50 de 1.284», as páginas com reticências (até 7 posições) e, com onPageSizeChange, o seletor «Filas» 25 · 50 · 100. onPageChange (botão) ou hrefFor (link, ?pagina=2&filas=50). Abaixo de 960, só «‹ 2 de 52 ›». |
| Table e partes | Table, TableHead, TableBody, TableRow (selected), TableHeaderCell, TableCell (variant: id, meta, num; align), TableSelectCell, TableEmpty. Uma <table> de verdade. |
| Cabeçalho ordenável + useTableSort | TableHeaderCell com sort e onSort: o texto vira botão, o <th> ganha aria-sort e o ícone de 12 (ordenar, chevron-arriba, chevron-abajo) vai à direita; ordenada em azul. useTableSort() guarda uma coluna por vez e dá sortProps('total'); o clique alterna ascendente → descendente → sem ordem (nextSort). |
| ActionMenu | O menu do botão «más»: items com label, icon, onSelect ou href, disabled e destructive — o destrutivo vai sempre por último, depois de um separador. 200 a 280px, itens de 36. Setas, Home, End, Enter e Esc; o foco volta ao botão. No top layer (popover), a rolagem da tabela não o corta. |
| Tooltip | Envolve um elemento: <Tooltip content="Sincronizar"><IconButton … /></Tooltip>. Tinta, 12px, até 240 numa linha; 400 ms no hover, na hora com foco de teclado, some com Esc. Nunca leva ação. Num IconButton com o mesmo texto, não repete a descrição e tira o title nativo. |
| SummaryList | Chave e valor do passo «Revisión» e das fichas, num <dl>: valor 14/600 à direita, missing em vermelho com o ícone («Falta API key»), «Cambiar» por onChange ou changeHref. |
| LineChart | Tempo: principal em --dato-principal de 2px, comparação em --dato-comparacion pontilhada, meta em --dato-meta; grade de no máximo 5 linhas; legenda em cima; tooltip pelo ponteiro ou pelas setas, com a variação contra o comparado; «Ver datos» troca pela tabela. Entra uma vez em --t-grafico. |
| BarList | Ranking em barras horizontais do maior para o menor, no máximo 10 + «Ver todo», valor à direita. |
| DonutChart | Partes de um total: no máximo 5 (as 4 maiores + «Otros» em --dato-6), total no centro, legenda com o percentual. |
| KpiCard | label, source (mono 11), value 28/700 e delta (value, direction, good): ▲/▼ com sinal, azul se melhora e vermelho se piora — passe good: false no CPA que sobe. Sem delta, «Sin período anterior». fullValue vira tooltip do valor abreviado; loading dá o esqueleto; error mostra «No disponible»; href torna o cartão clicável. |
| FileUpload, FileUploadItem | A zona de soltar de verdade (<input type="file">): accept, maxSize, hint e onFiles(aceitos, recusados) com o motivo (tipo, tamanho). A linha do arquivo mostra o percentual e a barra, o sucesso ou o erro em vermelho. validarArquivos() para a mesma regra no servidor. |
| Skeleton, SkeletonText, SkeletonGroup | Esqueletos de carga: papel gris, raio 4, pulso de 1,2 s, invisíveis nos primeiros 300 ms. SkeletonGroup dá aria-busy e o «Cargando…» para leitor de tela. Sem spinner em tabela nem cartão. |
| SelectionBar + useSelection | Barra azul de 48px «3 seleccionados», que substitui a barra de filtros, com as ações à direita (no máximo 3 + «más», uma só em amarelo, fantasmas em branco); com total e onSelectAll, o link «Seleccionar los 1.284». O hook guarda os marcados e diz o estado do «selecionar todos». |
| PermissionsMatrix | Módulo × Ver / Editar / Exportar / Administrar: ação liga Ver, tirar Ver limpa a linha (alternarPermissao); limit dá o teto do super admin (cadeado com «Lo habilita commente.me»); contracted: false desliga a linha; roles no segmentado, que passa a «Personalizado» ao mexer; a barra tinta conta as mudanças contra savedValue e oferece «Descartar» e «Guardar permisos». |
| Modal | Até 480px (--modal-max), --sombra-modal, título + frase, footer à direita; entra com escala e opacidade e abre no primeiro campo. Para confirmar ou uma tarefa de 1 a 3 campos. dismissible={false} em passo com dados não salvos. |
| ConfirmDialog | Confirmação destrutiva; abre com o foco no Cancelar; com confirmWord, só libera o botão com a palavra escrita. |
| Drawer | Editar um registro sem perder a tabela: pela direita, 460px, altura toda, header de 60 com o fechar, footer fixo; abaixo de 960, a tela toda. Mesma API do Modal (open, onClose, title, description, footer, dismissible). Mais de 8 campos pedem página própria. |
| ToastProvider + useToast | toast('Cambios guardados.'), com action: { label: 'Deshacer', onClick }; some em 4 s (duration: 8000 para o deshacer de ação em massa). tone: 'error': ícone vermelho, «Reintentar», não some sozinho, tem o fechar e é anunciado na hora. Um por vez; os seguintes esperam. |
| Stepper | Passos do formulário longo: feito, atual, pendente, marca de 22px. |
| Card | Cartão branco, raio 12, título e ações opcionais; flush para tabela de borda a borda. |
| SettingsSection, DangerZone | Configuração em duas colunas e a zona de perigo com o botão peligro. |
| AppShell, Sidebar, SidebarSection, SidebarItem, SidebarGroup | A moldura do admin: sidebar de 248px, fixa, com rolagem própria; itens de 38px com ícone 20 (ativo em --info-fondo, azul 700 e a barra amarela; contador vermelho só para alerta; «Pronto»); SidebarGroup é o item com submenu (subitens de 32px sobre a guia, chevron que gira, pai em azul quando um filho está ativo, soma dos alertas quando fechado). Conteúdo até 1360px. Abaixo de 960, a sidebar vira drawer de 280px com o véu. |
| CommandPalette, CommandPaletteTrigger, useCommandPaletteShortcut | A busca global ⌘K: o painel de 560 a 15% do topo, campo de 52, grupos (Pedidos, Productos, Clientes, Ir a) com no máximo 5, coincidência em negrito, «Preguntar a Dante» na última linha (⌘↵). Sem texto, emptyGroups (recentes, frequentes). Quem usa faz a busca — e respeita a loja ativa. |
| OnboardingChecklist | O cartão «Primeros pasos» do Inicio: «2 de 5», a barra, os passos que levam à sua tela, feitos riscados, e «Ocultar». |
| StoreSwitcher | O seletor de conta e loja da topbar: botão de 44 com as iniciais da conta, popover de 300 com busca a partir de 6 opções, grupos por conta (e «Otras cuentas» para o super admin), a loja em uso com o check, a que tem erro com o badge. Digitar filtra; ↑↓, Enter, Esc. |
| Topbar, StoreBadge, Avatar | Barra do topo de 60px (no celular, com o botão de menu 44×44), a loja em uso com o host do VTEX, as iniciais. |
| PageHeader | Migalhas (só do nível 2) → título 24/700 com badge de estado → meta 13px → ações à direita (1 primária + 1 secundária) → abas. |
| LinkProvider, AppLink | O link do app para os componentes que navegam. |
Todos aceitam className e as props do elemento HTML; os controles aceitam ref.
Layout e links
import { forwardRef } from 'react';
import { Link, Outlet } from 'react-router';
import {
AppShell, Avatar, LinkProvider, Lockup, Sidebar, SidebarGroup, SidebarItem, SidebarSection, ToastProvider, Topbar,
type LinkComponentProps,
} from '@commenteme/react';
const RouterLink = forwardRef<HTMLAnchorElement, LinkComponentProps>(({ href, ...props }, ref) => (
<Link ref={ref} to={href} {...props} />
));
export default function LayoutAdmin() {
return (
<LinkProvider component={RouterLink}>
<ToastProvider>
<AppShell
sidebar={
<Sidebar
logo={<Link to="/" aria-label="commente.me, Inicio"><Lockup size={24} /></Link>}
footer={
<SidebarSection aria-label="Cuenta">
<SidebarItem href="/configuracion" icon="configuracion">Configuración</SidebarItem>
<SidebarItem href="https://help.commente.me" icon="soporte">Soporte</SidebarItem>
<SidebarItem href="/salir" icon="salir" muted>Salir</SidebarItem>
</SidebarSection>
}
>
<SidebarSection aria-label="Menú principal">
<SidebarItem href="/" icon="inicio">Inicio</SidebarItem>
<SidebarGroup icon="oms" label="OMS" active>
<SidebarItem href="/oms/pedidos" active count={4}>Pedidos</SidebarItem>
<SidebarItem href="/oms/envios">Envíos</SidebarItem>
</SidebarGroup>
<SidebarGroup icon="catalogo" label="Catálogo">
<SidebarItem href="/catalogo/productos">Productos</SidebarItem>
</SidebarGroup>
</SidebarSection>
</Sidebar>
}
topbar={<Topbar end={<Avatar name="María Contreras" />} />}
>
<Outlet />
</AppShell>
</ToastProvider>
</LinkProvider>
);
}O AppShell já põe o .ctx-admin e liga o botão de menu da Topbar à sidebar: abaixo de
960px ela vira drawer, Esc e o véu fecham e o foco volta ao botão. O Modal e o
ConfirmDialog são o <dialog> nativo: prendem o foco, fecham com Esc e devolvem o foco a
quem abriu, sem biblioteca.
Os nomes do menu são os do kit: palavra comum ou sigla do ofício, só a primeira maiúscula
(Inicio, OMS, Catálogo, Comparador de precios, Reportes, Conversaciones). Conexiones e
Integraciones moram só em Configuración. Rotas e submenus completos na skill, em
referencias/menu.md.
Por que elementos nativos
Botão é <button>, campo é <input>, select é <select>, checkbox, radio e switch são
<input> com a caixa desenhada por baixo. Teclado, leitor de tela, celular e autofill
funcionam sem código, e os valores entram no FormData — o <Form> do React Router e as
server actions recebem tudo sem fiação extra.
Ver todos
npm run build -w @commenteme/react && npm run demo -w @commenteme/react
# abre packages/react/.demo/index.htmlUm admin de mentira, montado com os próprios componentes, num HTML só que abre do disco:
menu com submenus, abas, tabela com seleção, ordenação, menu de ações e drawer de edição,
filtros, paginação com filas, tooltip, esqueletos, cartões de KPI, assistente por passos com
radio em cartão e revisão, upload de preços,
configuração com modal, confirmação destrutiva e toast de sucesso e de erro — tudo
funcionando. Para comparar com a Biblioteca e a Especificaciones do kit v3.3.1
(referencias/kit-v3/reference/ na skill).
Ainda não
Os componentes do sitio (commente.me, help e support) ainda se constroem com as medidas
da skill (referencias/sitio.md). Do admin, a Especificaciones inteira já está no pacote.
Versão e licença
Versionamento semântico próprio; mudanças em CHANGELOG.md. MIT para o código. A marca commente.me — nome, logotipo, ladrillo e lockup — não entra nessa licença: ver MARCA.md.
