feat: implement UI redesign for Comparador de Notas
- Introduced a new theme for the application based on dark navy aesthetics. - Created design tokens for colors, spacings, and border radii. - Developed a theme module in Rust to manage styles for various UI components. - Updated multiple screens and components to align with the new design, including cards, buttons, badges, and progress bars. - Enhanced user experience with improved layouts and visual elements across the application.
This commit is contained in:
+291
@@ -0,0 +1,291 @@
|
||||
# UI Redesign — Comparador de Notas
|
||||
|
||||
**Data:** 04/03/2026
|
||||
**Branch:** `change-ui`
|
||||
**Base:** iced 0.13.1 (Elm architecture)
|
||||
**Referência visual:** `ui-ideia/mockup.html` + `ui-ideia/design_tokens.json`
|
||||
|
||||
---
|
||||
|
||||
## 1. Objetivo
|
||||
|
||||
Aplicar o visual do mockup (tema dark navy, cards, badges coloridos, progress bars) a todas as telas da aplicação, mantendo a lógica de negócio e a arquitetura Elm intocadas.
|
||||
|
||||
---
|
||||
|
||||
## 2. Design Tokens (mapeados para Rust)
|
||||
|
||||
### Paleta de cores
|
||||
|
||||
| Token | Hex | Uso |
|
||||
|------------------------|-----------|---------------------------------------|
|
||||
| `BG` | `#0F172A` | Fundo geral da janela |
|
||||
| `SURFACE` | `#1E293B` | Cards / containers primários |
|
||||
| `SURFACE_2` | `#334155` | Cards secundários, cabeçalho de tabela|
|
||||
| `BORDER` | `#334155` | Bordas de inputs e cards |
|
||||
| `TEXT` | `#F1F5F9` | Texto principal |
|
||||
| `TEXT_SECONDARY` | `#94A3B8` | Labels, placeholders, texto muted |
|
||||
| `TEXT_MUTED` | `#64748B` | Texto desabilitado |
|
||||
| `PRIMARY` | `#3B82F6` | Botões primários, links, step ativo |
|
||||
| `PRIMARY_HOVER` | `#2563EB` | Hover em botões primários |
|
||||
| `SUCCESS` | `#22C55E` | Badge OK, progress bar ≥ 90% |
|
||||
| `WARNING` | `#F59E0B` | Badge Faltante, progress bar 60–89% |
|
||||
| `ERROR` | `#EF4444` | Badge Duplicada, progress bar < 60% |
|
||||
| `OVERLAY` | rgba(0,0,0,0.6) | Fundo do modal |
|
||||
|
||||
### Espaçamentos
|
||||
|
||||
| Token | px |
|
||||
|-------|----|
|
||||
| `XS` | 4 |
|
||||
| `SM` | 8 |
|
||||
| `MD` | 12 |
|
||||
| `LG` | 16 |
|
||||
| `XL` | 24 |
|
||||
| `XXL` | 32 |
|
||||
|
||||
### Border radius
|
||||
|
||||
| Token | px |
|
||||
|--------|----|
|
||||
| `SM` | 4 |
|
||||
| `MD` | 6 |
|
||||
| `LG` | 8 |
|
||||
|
||||
---
|
||||
|
||||
## 3. Arquivo de tema: `src/ui/theme.rs`
|
||||
|
||||
Módulo responsável por expor:
|
||||
|
||||
- `PALETA`: constantes `Color` para todas as cores acima
|
||||
- Funções de estilo para `container::Style`, `button::Style`, `text_input::Style`, `progress_bar::Style`
|
||||
- Nenhuma lógica de negócio — apenas aparência
|
||||
|
||||
### Estratégia de tema iced
|
||||
|
||||
```rust
|
||||
// main.rs — encadear .theme()
|
||||
iced::application(...)
|
||||
.theme(|_app, _| tema_dark())
|
||||
.run_with(App::new)
|
||||
|
||||
// theme.rs
|
||||
pub fn tema_dark() -> iced::Theme {
|
||||
iced::Theme::custom("dark".to_string(), iced::theme::Palette {
|
||||
background: hex("#0F172A"),
|
||||
text: hex("#F1F5F9"),
|
||||
primary: hex("#3B82F6"),
|
||||
success: hex("#22C55E"),
|
||||
danger: hex("#EF4444"),
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
Widgets que precisam de aparência customizada além da paleta (cards, badges) recebem closure `.style(|theme| ...)` inline ou via função helper em `theme.rs`.
|
||||
|
||||
---
|
||||
|
||||
## 4. Componentes visuais novos / modificados
|
||||
|
||||
### 4.1 Card container
|
||||
|
||||
Container com background `SURFACE`, borda `BORDER` 1px, radius `LG` (8px), padding `LG` (16px).
|
||||
|
||||
```rust
|
||||
// theme.rs
|
||||
pub fn card(theme: &iced::Theme) -> container::Style { ... }
|
||||
pub fn card_secondary(theme: &iced::Theme) -> container::Style { ... }
|
||||
```
|
||||
|
||||
### 4.2 Botão primary
|
||||
|
||||
Background `PRIMARY`, texto `TEXT`, radius `MD` (6px), sem borda.
|
||||
Hover: background `PRIMARY_HOVER`.
|
||||
|
||||
### 4.3 Botão secondary / ghost
|
||||
|
||||
Background `SURFACE_2`, texto `TEXT`, radius `MD`.
|
||||
|
||||
### 4.4 Botão danger
|
||||
|
||||
Background semi-transparente `ERROR` (20% alpha), texto `ERROR`, radius `MD`.
|
||||
|
||||
### 4.5 Badge de status (inline)
|
||||
|
||||
Container com padding `[2, 8]`, radius `SM` (4px), background 20% alpha da cor semântica.
|
||||
Implementado como `container(text(...).size(12))` com style closure.
|
||||
|
||||
| Status | Cor texto | Background alpha |
|
||||
|------------|------------|-----------------|
|
||||
| OK | `SUCCESS` | 20% |
|
||||
| Faltante | `WARNING` | 20% |
|
||||
| Duplicada | `ERROR` | 20% |
|
||||
|
||||
### 4.6 Progress bar por série
|
||||
|
||||
Componente `progress_bar` nativo do iced com style closure que escolhe cor baseada no percentual:
|
||||
- ≥ 90% → `SUCCESS`
|
||||
- 60–89% → `WARNING`
|
||||
- < 60% → `ERROR`
|
||||
|
||||
Background da trilha: `#111827` (mais escuro que SURFACE).
|
||||
|
||||
### 4.7 Stat cards (tela de resultado)
|
||||
|
||||
Row de 3 cards com número grande colorido + label. Componente reutilizável `stat_card(valor, label, cor)`.
|
||||
|
||||
### 4.8 Breadcrumb
|
||||
|
||||
Row no topo da janela (exceto Layouts e Analisando). Steps separados por `›`. Background `SURFACE`, padding `[8, 16]`, borda inferior 1px `BORDER`.
|
||||
|
||||
| Estado do step | Cor | Tamanho |
|
||||
|---------------|-------------|---------|
|
||||
| Ativo | `PRIMARY` | 14px |
|
||||
| Concluído | `TEXT_SECONDARY` | 13px |
|
||||
| Futuro | `TEXT_MUTED` | 13px |
|
||||
|
||||
---
|
||||
|
||||
## 5. Telas — mudanças por arquivo
|
||||
|
||||
### 5.1 `screens/import.rs`
|
||||
|
||||
**Atual:** Coluna plana com título, row de arquivo e row de layout.
|
||||
|
||||
**Novo:**
|
||||
- Card central (max-width 600px) centrado na tela
|
||||
- Área de drop zone estilizada com borda tracejada `BORDER`, radius `LG`, padding `XL`
|
||||
- Ícone `📂` grande + texto instrucional
|
||||
- Nome do arquivo selecionado com truncamento
|
||||
- Seção de layout com separador visual
|
||||
- Botão primary "▶ Configurar Colunas" ocupando largura do card
|
||||
|
||||
### 5.2 `screens/selecionar_aba.rs`
|
||||
|
||||
**Atual:** Lista de botões idênticos (bug de highlight).
|
||||
|
||||
**Novo:**
|
||||
- Card com lista de abas scrollável
|
||||
- Aba selecionada: background `PRIMARY` (20% alpha), texto `PRIMARY`, borda `PRIMARY`
|
||||
- Aba não selecionada: background `SURFACE_2`, texto `TEXT`
|
||||
- Preview abaixo da lista em card separado
|
||||
|
||||
### 5.3 `screens/configuracao_colunas.rs`
|
||||
|
||||
**Atual:** Coluna plana de inputs.
|
||||
|
||||
**Novo:**
|
||||
- Seção de configuração em card `SURFACE`
|
||||
- Labels com `TEXT_SECONDARY`, inputs com fundo `BG`, borda `BORDER`
|
||||
- Campos opcionais: checkbox com estilo consistente + input inline
|
||||
- Erros em card com borda `ERROR` (20% alpha)
|
||||
- Botões na barra inferior fixada: "Voltar" (ghost), "Analisar" (primary), "Reanalisar" (secondary), "Salvar" (ghost)
|
||||
|
||||
### 5.4 `screens/resultado.rs`
|
||||
|
||||
**Atual:** Coluna de texto puro.
|
||||
|
||||
**Novo (alinhado ao mockup):**
|
||||
|
||||
1. **Header row:** título + botões de ação à direita
|
||||
2. **Stat cards row:** 3 cards — "Notas Faltantes" (azul), "Duplicadas" (vermelho), "Total R$" (texto branco)
|
||||
3. **Card de completude por série:** para cada série, label + progress bar colorida por threshold
|
||||
4. **Controle de itens/página:** botões com highlight no ativo
|
||||
5. **Seções faltantes/duplicatas:** cabeçalho de série em row com badge de contagem + botão Copiar; itens em lista
|
||||
|
||||
### 5.5 `screens/layouts.rs`
|
||||
|
||||
**Atual:** Coluna plana.
|
||||
|
||||
**Novo:**
|
||||
- Seções CSV e XLSX em cards separados
|
||||
- Cada layout numa row com hover highlight
|
||||
- Botões de ação menores (ícone + texto compacto)
|
||||
- Linha de importar JSON no rodapé do card
|
||||
|
||||
### 5.6 `components/modal.rs`
|
||||
|
||||
**Atual:** Box com estilo do tema padrão.
|
||||
|
||||
**Novo:**
|
||||
- Background `SURFACE`, borda `BORDER`, radius `LG`
|
||||
- Título `TEXT` 18px, mensagem `TEXT_SECONDARY` 14px
|
||||
- Separador entre conteúdo e botões
|
||||
- Botão "Fechar" ghost, "Confirmar" primary
|
||||
- Tipos Erro/Aviso com ícone + cor no título
|
||||
|
||||
### 5.7 `components/tabela_preview.rs`
|
||||
|
||||
**Atual:** Monospace puro.
|
||||
|
||||
**Novo:**
|
||||
- Cabeçalho com background `SURFACE_2`, texto `TEXT_SECONDARY`
|
||||
- Células com background `SURFACE`, texto `TEXT`, fonte monospace
|
||||
- Borda inferior `BORDER` nas células
|
||||
|
||||
### 5.8 `components/paginacao.rs`
|
||||
|
||||
**Atual:** Row simples de botões.
|
||||
|
||||
**Novo:**
|
||||
- Botões ◀/▶ com estilo ghost
|
||||
- "Página X / Y" em `TEXT_SECONDARY`
|
||||
|
||||
---
|
||||
|
||||
## 6. Arquivos a criar/modificar
|
||||
|
||||
| Arquivo | Ação |
|
||||
|---------|------|
|
||||
| `src/main.rs` | Adicionar `.theme(...)` |
|
||||
| `src/ui/mod.rs` | Adicionar `pub mod theme;` |
|
||||
| `src/ui/theme.rs` | **Criar** — paleta + helpers de estilo |
|
||||
| `src/ui/app.rs` | Breadcrumb novo estilo + tela Analisando centralizada |
|
||||
| `src/ui/screens/import.rs` | Reescrever |
|
||||
| `src/ui/screens/selecionar_aba.rs` | Reescrever (corrigir bug highlight) |
|
||||
| `src/ui/screens/configuracao_colunas.rs` | Reescrever |
|
||||
| `src/ui/screens/resultado.rs` | Reescrever |
|
||||
| `src/ui/screens/layouts.rs` | Reescrever |
|
||||
| `src/ui/components/modal.rs` | Reescrever |
|
||||
| `src/ui/components/tabela_preview.rs` | Reescrever |
|
||||
| `src/ui/components/paginacao.rs` | Reescrever |
|
||||
|
||||
---
|
||||
|
||||
## 7. Limitações do iced 0.13 e workarounds
|
||||
|
||||
| Limitação CSS | Workaround iced |
|
||||
|---------------|----------------|
|
||||
| `box-shadow` | Cor de borda ou sem sombra (aceitar diferença) |
|
||||
| `rgba(r,g,b,0.2)` | `Color { r, g, b, a: 0.2 }` com valores 0.0–1.0 |
|
||||
| Font Inter | Usa fonte do sistema (system-ui) — sem mudança necessária |
|
||||
| `display: flex; gap` | `row![...].spacing(N)` |
|
||||
| `border-bottom` nas células | `container` com border bottom via `border.width` fracional não suportado — usar separador visual alternativo |
|
||||
|
||||
---
|
||||
|
||||
## 8. Ordem de implementação
|
||||
|
||||
1. `theme.rs` — paleta e helpers (base para tudo)
|
||||
2. `main.rs` — ativar tema
|
||||
3. `modal.rs` — usado por todas as telas
|
||||
4. `resultado.rs` — tela principal do mockup
|
||||
5. `import.rs`
|
||||
6. `selecionar_aba.rs`
|
||||
7. `configuracao_colunas.rs`
|
||||
8. `layouts.rs`
|
||||
9. `app.rs` — breadcrumb + Analisando
|
||||
10. `tabela_preview.rs` + `paginacao.rs`
|
||||
11. Compilar e corrigir
|
||||
|
||||
---
|
||||
|
||||
## 9. Notas de compatibilidade iced 0.13
|
||||
|
||||
- `button::Style` inclui `background`, `text_color`, `border: Border { color, width, radius }`, `shadow`
|
||||
- `container::Style` inclui `background`, `text_color`, `border`, `shadow`
|
||||
- `progress_bar::Style` inclui `background` e `bar`
|
||||
- `text_input::Style` inclui `background`, `border`, `icon`, `placeholder`, `value`, `selection`
|
||||
- Closures de estilo recebem `&Theme` e retornam o `Style` concreto do widget
|
||||
- `iced::Border` aceita `radius: iced::border::Radius` — usar `N.into()` para uniform radius
|
||||
Reference in New Issue
Block a user