9.6 KiB
FightRate Design System — Corner Instrument
Status: oficial para a reconstrução em React Native
Direção escolhida: 01 — Corner Instrument
Substitui: qualquer direção antiga baseada em Combat Lab, cards genéricos ou dashboard visualmente pesado.
1. Essência da marca
FightRate é uma ferramenta de treino para luta.
A interface deve parecer:
- equipamento de córner;
- instrumento físico de captura;
- confiável sob pressão;
- legível em um celular largado perto do treino;
- forte, mas não decorativa.
A interface não deve parecer:
- dashboard SaaS;
- app fitness genérico;
- coleção de cards;
- UI médica fria;
- layout de template;
- tela cheia de controles que o atleta precisa operar no meio da luta.
Frase-guia:
Treino ligado. Celular esquecido. Dados confiáveis depois.
2. Modelo de produto
O fluxo principal é captura contínua do treino inteiro.
- Atleta coloca a cinta.
- Abre o app.
- Toca em Iniciar treino.
- Larga o celular.
- Treina.
- Volta e toca em Parar treino.
- Analisa histórico, relatório, sensor e insights.
Rounds são secundários. Se existirem, devem ser pré-configurados ou detectados/segmentados depois. Não devem dominar a tela principal.
3. Paleta 60 / 30 / 10
60% — Preto lona
#070605
Uso:
- fundo da captura ativa;
- superfícies profundas;
- atmosfera de treino real.
30% — Couro queimado
#1D170F
#12100C
#19130C
Uso:
- painéis;
- blocos de métrica;
- trilhos de gráfico;
- superfícies secundárias.
10% — Vermelho golpe
#E23B2E
Uso:
- ação primária;
- pico;
- risco;
- estado intenso;
- pontos de atenção.
Não usar vermelho como decoração espalhada. Se tudo é vermelho, nada é urgente.
Auxiliares
#FFB43D âmbar / leitura auxiliar
#34C77B verde / sucesso ou estabilidade
#FFF0DC creme / ação crítica clara, como Parar treino
#B9A98E texto secundário
#392D1E borda técnica quente
4. Tipografia
Regra
Número vem primeiro.
Durante captura, o usuário precisa entender o estado em menos de 1 segundo.
Hierarquia
Display numérico
Uso:
- BPM atual;
- duração;
- pico;
- TRIMP/carga;
- recuperação.
Estilo:
font-weight: 900–1000
letter-spacing: -0.08em a -0.10em
line-height: 0.82–0.90
Tamanhos de referência mobile:
BPM principal: 72–88px
Métrica secundária grande: 42–56px
Tile numérico: 22–28px
Labels técnicos
Uso:
- CAPTURA ATIVA;
- SENSOR OK;
- MÉDIA;
- PICO;
- Z4/Z5;
- RSSI.
Estilo:
uppercase
font-weight: 850–950
letter-spacing: 0.12em–0.18em
font-size: 10–12px
Texto explicativo
Uso só quando ajuda decisão:
- pré-treino;
- pós-treino;
- insights;
- diagnóstico sensor.
Evitar parágrafos longos durante captura ativa.
5. Forma, borda e raio
Raios
r1: 10px elementos pequenos técnicos
r2: 16px inputs e linhas técnicas
r3: 24px tiles e módulos
r4: 36px painéis principais
r5: 48px carcaça / phone shell / hero surfaces
Bordas
Cor base:
#392D1E
Bordas são parte da metáfora de instrumento físico. Devem parecer metal/couro queimado, nunca cinza genérico.
Sombra
Usar sombra profunda apenas em:
- carcaça de tela;
- painéis principais;
- overlays críticos.
Evitar sombra em cada tile.
6. Componentes base
6.1 Capture Shell
Função: conter a experiência de treino ativo.
Características:
- fundo escuro;
- BPM dominante;
- status no topo;
- gráfico compacto;
- métricas essenciais;
- ação de parar muito clara.
Conteúdo máximo:
CAPTURA ATIVA 42:18
154 bpm
[linha temporal]
MÉDIA 146 | PICO 183 | Z4/Z5 41%
[Evento] [Parar treino]
6.2 Primary Action
Uso:
- Iniciar treino;
- abrir relatório;
- ação principal do estado atual.
Estilo:
- pill;
- vermelho golpe;
- texto curto;
- opcional com ícone circular interno.
6.3 Stop Action
Uso:
- Parar treino.
Estilo:
background: #FFF0DC
text: #120B07
border: none
Motivo: precisa ser imediatamente reconhecível, sem parecer alerta destrutivo escondido.
6.4 Metric Tile
Uso:
- média;
- pico;
- zona;
- carga;
- recuperação;
- RSSI;
- bateria.
Estrutura:
valor grande
label técnico pequeno
Não transformar cada métrica em card pesado.
6.5 Sensor Row
Uso:
- UUID;
- propriedade BLE;
- estado;
- leitura.
Exemplo:
2A37 · notify
2A19 · read
RSSI · -61 dBm
Usar monospace pontual apenas para UUIDs, logs e identificadores BLE.
6.6 Insight Note
Estrutura:
Conclusão
Por que importa
O que fazer agora
Base/confiança dos dados
Insight bom é curto, explicável e acionável.
7. Gráficos
Princípios
- Nunca mostrar gráfico fake.
- Nunca mostrar eixo vazio decorativo.
- Só renderizar linha com dados reais suficientes.
- O viewport inicial deve mostrar a janela selecionada inteira.
- Zoom é ação do usuário, não estado inicial.
Visual
- fundo escuro técnico;
- grade sutil;
- linha vermelha principal;
- labels mínimos;
- destaque de pico e média fora do gráfico, não poluindo a linha.
Densidade temporal
Labels devem se adaptar:
10 min: HH:mm
1h: HH:mm limpo
Hoje: horas principais
Zoom profundo: granularidade progressiva
8. Telas
Captura pronta
Objetivo: começar rápido.
Deve mostrar:
- status do sensor;
- bateria;
- RSSI;
- ação Iniciar treino;
- check-in opcional.
Não deve mostrar:
- gráfico vazio;
- round timer dominante;
- histórico;
- insights longos.
Captura ativa
Objetivo: monitorar sem interação.
Deve mostrar:
- BPM grande;
- duração;
- média;
- pico;
- tempo em zona/carga;
- sensor OK;
- parar treino.
Pós-treino
Objetivo: transformar captura em interpretação.
Deve mostrar:
- duração;
- carga;
- pico;
- blocos do treino;
- recuperação;
- exportação;
- relatório completo.
Histórico
Objetivo: análise densa, organizada e útil.
Deve mostrar:
- semanas;
- sessões;
- tendência;
- melhores trechos;
- comparação;
- carga total;
- consistência.
Sensor
Objetivo: confiança técnica.
Deve mostrar:
- dispositivo conectado;
- RSSI;
- bateria;
- serviços BLE;
- características;
- propriedades;
- quedas de sinal;
- última amostra;
- taxa aproximada de amostragem.
9. Motion
Motion deve ser funcional.
Permitido:
- transição suave de BPM;
- pulso discreto em status ativo;
- entrada curta de linhas no histórico;
- expansão de detalhes do sensor.
Evitar:
- animações decorativas grandes;
- blur pesado;
- gradiente animado;
- movimento durante treino que distraia.
10. React Native tokens sugeridos
export const colors = {
canvas: '#070605',
surface: '#12100C',
surfaceRaised: '#1D170F',
text: '#F8EAD8',
textMuted: '#B9A98E',
line: '#392D1E',
action: '#E23B2E',
warning: '#FFB43D',
success: '#34C77B',
stopSurface: '#FFF0DC',
stopText: '#120B07',
}
export const radius = {
xs: 10,
sm: 16,
md: 24,
lg: 36,
xl: 48,
}
export const spacing = {
xxs: 4,
xs: 8,
sm: 12,
md: 16,
lg: 24,
xl: 32,
xxl: 48,
}
11. Proibição explícita
Não usar mais a direção visual antiga do app nativo.
Não usar como base:
- Combat Lab antigo;
- cards genéricos;
- Material dashboard padrão;
- tela cheia de tiles sem hierarquia;
- round timer manual como produto principal.
12. Artefato visual de referência
HTML aprovado como base de exploração:
docs/design-directions/react-native-redesign-2026-06-10/v2/01-corner-instrument-v2.html
Tipografia numérica tabular (v2)
Para todos os valores numéricos do app (BPM, métricas, zone, timestamps, IDs, UUIDs), o app usa JetBrains Mono com fontVariant: ['tabular-nums'] para alinhamento perfeito de dígitos. Esta fonte está bundled em assets/fonts/JetBrainsMono-{Regular,Medium,Bold,ExtraBold}.ttf e linkada via react-native.config.js + react-native-asset.
Tokens em src/theme/typography.ts:
displayNumeric: 110px JetBrains Mono ExtraBold, lineHeight 100, letterSpacing -7displaySmallNumeric: 56px JetBrains Mono ExtraBold, lineHeight 54, letterSpacing -3metricNumeric: 28px JetBrains Mono Bold, lineHeight 30, letterSpacing -1.2detailNumeric: 18px JetBrains Mono Bold, lineHeight 22, letterSpacing -0.8
display, displaySmall, body, label, button permanecem em Inter (fallback do sistema). Apenas os tokens numéricos exigem JetBrains Mono.
Motion presets (v2)
src/theme/motion.ts define easing e durações canônicas:
easeOutQuart: 'cubic-bezier(0.25, 1, 0.5, 1)'(entradas)easeOutExpo: 'cubic-bezier(0.16, 1, 0.3, 1)'(transições longas)easeOutBack: 'cubic-bezier(0.34, 1.56, 0.64, 1)'(pin, overshoot sutil)easeInOutQuart: 'cubic-bezier(0.76, 0, 0.24, 1)'(pulse loops)
Durations: instant: 80, fast: 160, normal: 240, slow: 380, pulse: 800, pulseSlow: 1600 ms.
Staggers: row: 50, item: 80 ms.
Animações registradas:
bpmPulse(loop, 800ms) — BPM quandoreceivingliveDotPulse(loop, 1600ms) — LiveDot quandolive = truestopAlertRing(loop, 1600ms) — anel de aviso em volta do botão Parar quandoisCapturingtabFade(200ms cross-fade) — entre tabsrowEnter(240ms fade+translateY 8→0, stagger 50ms) — listas de Histórico e InsightspinEnter(500ms easeOutBack 1.4→1) — pin do TrainingChartpressDown/Up(80/160ms scale 1→0.96→1, opacity 1→0.82→1) — feedback físico de todos os botões
Todas respeitam AccessibilityInfo.isReduceMotionEnabled() (instantâneas quando true).