trdr-ui
v0.9.0
Published
Biblioteca de componentes da TRDR. Baseada em shadcn/ui, com a identidade TRDR embutida.
Maintainers
Readme
trdr-ui
A biblioteca de componentes da TRDR. Baseada em shadcn/ui (Tailwind v4, Radix, CVA), com a identidade TRDR embutida: dark-first, marca cyan, e os componentes de trading que um terminal de operações precisa e uma biblioteca genérica não tem.
Uma correção publicada aqui chega em todos os projetos TRDR pelo próximo update de versão. Esse é o ponto: antes, os componentes eram distribuídos como texto que cada projeto reimplementava, e corrigir um bug não consertava ninguém.
Instalação
Três modos, dependendo do que o projeto já usa.
Projeto com Tailwind v4 (o padrão)
npm i trdr-ui trdr-tokens@import "tailwindcss";
@import "trdr-ui/styles";Projeto sem Tailwind (CSS puro, CSS Modules, MUI)
npm i trdr-ui@import "trdr-ui/standalone.css";O bundle vem pré-compilado e sem preflight, então não zera a baseline de estilo que o projeto já tem. É o que permite conviver com MUI ou Bootstrap.
Só os tokens
npm i trdr-tokens@import "trdr-tokens/tokens.css";Em todos os casos
Marque o tema no documento e carregue as fontes:
<html lang="pt-BR" data-theme="dark">Atenção a uma diferença de convenção. Instalando pelo pacote, o tema é data-theme, e o
padrão sem atributo nenhum já é o escuro (o produto é dark-first). Instalando o tema pelo
registry (npx shadcn add .../r/trdr-theme.json), o CLI do shadcn escreve na convenção dele:
claro em :root e escuro em .dark. As duas funcionam, mas não misture: escolha um caminho
por projeto.
Ícone de produto é o componente Icon do pacote trdr-icons (SVG inline, sem webfont, sem
requisição de rede): não existe recurso externo para carregar.
npm i trdr-iconsimport { Icon } from "trdr-icons"
<Icon name="candlestick_chart" size={20} />Os componentes usam três famílias de fonte de texto: DM Sans nos títulos e no texto principal
(--font-primary), Inter na interface (--font-secondary) e JetBrains Mono nos números e no
código (--font-mono). Os tokens já trazem fallback, então funciona sem configuração, mas
carregue as três para o resultado certo.
A troca de família aconteceu em 2026-08-22: antes a display era JetBrains Mono e a mono era
Roboto Mono. A --font-roboto-mono não é mais referenciada por token nenhum, então declará-la
hoje não tem efeito.
Declare as três variáveis via next/font no arquivo que monta a <html> (app/layout.tsx
num app Next). Um módulo único de fontes, importado por toda a árvore que monta <html>, evita
duplicar a declaração projeto afora:
// app/_shared/fonts.ts (ou src/lib/fonts.ts)
import { DM_Sans, Inter, JetBrains_Mono } from "next/font/google"
export const fontDisplay = DM_Sans({
subsets: ["latin"],
variable: "--font-dm-sans",
display: "swap",
})
export const fontSans = Inter({
subsets: ["latin"],
variable: "--font-inter",
display: "swap",
})
export const fontMono = JetBrains_Mono({
subsets: ["latin"],
variable: "--font-jetbrains-mono",
display: "swap",
})
/** Concatenado, para aplicar de uma vez na tag que monta o documento. */
export const fontVariables = `${fontDisplay.variable} ${fontSans.variable} ${fontMono.variable}`// app/layout.tsx
import { fontVariables } from "./_shared/fonts"
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="pt-BR" data-theme="dark" className={fontVariables}>
<body>{children}</body>
</html>
)
}Se o projeto carrega só duas das três famílias, resolva a variável que falta com uma custom property apontando para uma das que já foram carregadas, em vez de baixar uma fonte a mais só para satisfazer o nome:
:root {
--font-jetbrains-mono: var(--font-dm-sans);
}O que acontece se uma das três faltar por completo. --font-primary (e as outras duas) são
var(--font-dm-sans), 'DM Sans', sans-serif: um var() aninhado dentro da lista de
família, não um fallback do próprio var(). Se --font-dm-sans nunca for declarada, a
variável fica "guaranteed-invalid" pela spec de custom properties, e isso invalida a declaração
inteira em computed-value time (IACVT): não cai no 'DM Sans', sans-serif textual que vem
depois da vírgula. O resultado é o site inteiro trocando de fonte para o padrão do navegador, sem
erro de build, sem warning de lint, sem teste vermelho. A partir da versão que inclui a guarda
@property em dist/tokens.css, essa ausência já resolve para o fallback textual em vez de
invalidar tudo, mas carregar as três continua sendo o caminho certo, porque só ele traz a fonte
de verdade em vez do genérico.
Uso
import { Button } from "trdr-ui/button"
export function Exemplo() {
return <Button variant="primary">Confirmar</Button>
}Importe pelo subpath. O barrel raiz (trdr-ui) existe para conveniência, mas puxa a fronteira
"use client" inteira num app Next.
Quando você precisa mudar um componente
Aí você ejeta: o código é copiado para dentro do seu projeto e passa a ser seu.
npx shadcn@latest add https://trdr.mrocontent.com.br/r/button.jsonO custo é que ele para de receber correção automática. Para isso existe o
trdr-cli:
npx trdr-cli doctorEle compara o que você ejetou com a versão atual da biblioteca e separa em três: idêntico (dá para atualizar sem medo), customizado (mostra o diff para merge manual) e token quebrado.
Convenções
Todo componente segue as mesmas regras, e elas são verificadas mecanicamente no CI:
data-slotem toda parte renderizada. É o gancho para estilizar partes internas sem depender de classe da biblioteca:[data-slot="card-header"] { ... }.classNamesempre sobrescreve. A composição usacn()com oclassNamedo consumidor por último, e otailwind-mergeconhece as escalas nomeadas da TRDR, entãogap-xsde fato vencegap-lg.refsempre encaminha, com peerreact: ^18.3 || ^19."use client"só quando necessário. Componentes de apresentação (card,badge,table,separator,breadcrumb,empty) são server-safe, para não empurrar a fronteira client do seu app sem motivo.
Identidade
Se você for customizar, saiba o que não muda:
- Dark-first. O produto é um terminal de operações às três da manhã.
- O cyan
#00D4FFé a cor de ação da marca, e é o quebg-primaryresolve, com texto escuro por cima. - Verde e vermelho são de trading, alta e baixa de preço (
context-trading-upedown). Sucesso e erro de interface usamcontent-successecontent-error. Trocar os dois confunde quem opera. - Número é
font-mono. Em fonte proporcional, o número muda de largura a cada atualização de cotação e a tabela inteira treme.
Documentação
trdr.mrocontent.com.br, gerada do código real desta biblioteca: variantes, props, slots e tokens saem do arquivo fonte, não de uma lista mantida à mão.
Endpoints públicos, com CORS aberto:
| Endpoint | O que é |
|---|---|
| /v2/components.json | catálogo completo |
| /tokens.json | tokens com valor, referência e descrição |
| /theme.css | tema Tailwind v4 |
| /r/<nome>.json | item do registry, para npx shadcn add |
Licença
MIT
