teste / docs /theme_system.md
torxyton's picture
feat: Implementar botão de alternância de tema e tema escuro padrão
349675c

A newer version of the Gradio SDK is available: 6.6.0

Upgrade

Sistema de Temas

Este documento descreve o sistema de temas dinâmico implementado na aplicação de análise financeira.

Visão Geral

O sistema de temas permite alternar entre modo claro e escuro, proporcionando uma experiência visual otimizada para diferentes condições de iluminação e preferências do usuário.

Componentes Principais

1. ThemeManager (src/ui/theme_manager.py)

Gerenciador centralizado responsável por:

  • Controle do tema atual (claro/escuro)
  • Definição de paletas de cores
  • Geração de CSS customizado
  • Alternância entre temas

Funcionalidades:

# Obter tema atual
current_theme = theme_manager.get_current_theme()

# Definir tema
theme_manager.set_theme(ThemeType.DARK)

# Alternar tema
theme_manager.toggle_theme()

# Obter CSS customizado
css = theme_manager.get_custom_css()

2. DarkThemeUIComponents (src/ui/dark_theme_components.py)

Componentes de interface com suporte a tema escuro:

  • Cabeçalho adaptável
  • Formatação de padrões harmônicos
  • Alertas de Fibonacci
  • Análise de sentimento
  • Recomendações de trading
  • Rodapé responsivo

Paletas de Cores

Tema Claro

  • Fundo Principal: #ffffff (--bg-primary, --bg)
  • Fundo Secundário: #f8f9fa (--bg-secondary, --surface)
  • Texto Principal: #495057
  • Texto Secundário: #6c757d
  • Bordas: #dee2e6
  • Accent: #007bff

Tema Escuro

  • Fundo Principal: #0f172a (--bg-primary, --bg)
  • Fundo Secundário: #1e293b (--bg-secondary, --surface)
  • Texto Principal: #f1f5f9
  • Texto Secundário: #cbd5e1
  • Bordas: #475569
  • Accent: #60a5fa

Implementação

CSS Dinâmico

O sistema utiliza variáveis CSS para permitir alternância dinâmica:

:root {
  --bg-primary: #ffffff;
  --bg-secondary: #f8f9fa;
  --bg: #ffffff;
  --surface: #f8f9fa;
  --text-primary: #495057;
  --text-secondary: #6c757d;
  --border-color: #dee2e6;
  --accent-color: #007bff;
}

[data-theme="dark"] {
  --bg-primary: #0f172a;
  --bg-secondary: #1e293b;
  --bg: #0f172a;
  --surface: #1e293b;
  --text-primary: #f1f5f9;
  --text-secondary: #cbd5e1;
  --border-color: #475569;
  --accent-color: #60a5fa;
}

Componentes Adaptáveis

Todos os componentes HTML utilizam as variáveis CSS:

def create_component():
    return f"""
    <div style="
        background: var(--bg-primary);
        color: var(--text-primary);
        border: 1px solid var(--border-color);
    ">
        Conteúdo do componente
    </div>
    """

Benefícios

1. Experiência do Usuário

  • Redução da Fadiga Visual: Modo escuro reduz o cansaço em ambientes com pouca luz
  • Personalização: Usuários podem escolher o tema de sua preferência
  • Acessibilidade: Melhor contraste para diferentes necessidades visuais

2. Técnicos

  • Manutenibilidade: Sistema centralizado facilita atualizações
  • Consistência: Paleta de cores padronizada em toda a aplicação
  • Performance: CSS otimizado com variáveis nativas
  • Escalabilidade: Fácil adição de novos temas

Uso na Interface

Botão de Alternância de Tema

A aplicação agora inclui um botão de alternância de tema integrado ao cabeçalho:

  • Localização: Canto superior direito da interface
  • Ícones: 🌙 para tema escuro, ☀️ para tema claro
  • Funcionalidade: Alternância instantânea entre temas
  • Atualização Dinâmica: CSS aplicado via JavaScript sem recarregar a página

Implementação do Botão

# No GradioInterface.create_interface()
with gr.Row():
    with gr.Column(scale=4):
        header_html = gr.HTML(self.ui_components.create_header())
    with gr.Column(scale=1, min_width=120):
        theme_toggle_btn = gr.Button(
            "🌙 Tema Escuro", 
            elem_id="theme-toggle",
            size="sm"
        )

# Evento de alternância
theme_toggle_btn.click(
    fn=self._toggle_theme,
    outputs=[theme_toggle_btn, theme_update_html]
)

Função de Alternância

def _toggle_theme(self):
    """Alterna entre tema claro e escuro"""
    theme_manager.toggle_theme()
    current_theme = theme_manager.get_current_theme()
    
    if current_theme == ThemeType.DARK:
        button_text = "🌙 Tema Escuro"
        theme_name = "dark"
    else:
        button_text = "☀️ Tema Claro"
        theme_name = "light"
    
    # JavaScript para atualização dinâmica do CSS
    js_code = f"""
    <script>
    // Remove CSS anterior
    const oldStyle = document.getElementById('dynamic-theme-css');
    if (oldStyle) oldStyle.remove();
    
    // Adiciona novo CSS
    const style = document.createElement('style');
    style.id = 'dynamic-theme-css';
    style.textContent = `{theme_manager.get_custom_css()}`;
    document.head.appendChild(style);
    
    // Aplica tema ao body
    document.body.setAttribute('data-theme', '{theme_name}');
    </script>
    """
    
    return button_text, js_code

Integração com Gradio

A interface Gradio utiliza o sistema de temas através do GradioInterface:

class GradioInterface:
    def _get_custom_css(self) -> str:
        return theme_manager.get_custom_css()
    
    def create_header(self) -> str:
        return DarkThemeUIComponents.create_header()
    
    def _apply_initial_theme(self):
        """Aplica o tema padrão na inicialização"""
        current_theme = theme_manager.get_current_theme()
        theme_name = "dark" if current_theme == ThemeType.DARK else "light"
        
        return f"""
        <script>
        document.body.setAttribute('data-theme', '{theme_name}');
        const style = document.createElement('style');
        style.id = 'dynamic-theme-css';
        style.textContent = `{theme_manager.get_custom_css()}`;
        document.head.appendChild(style);
        </script>
        """

Componentes Suportados

  • ✅ Cabeçalho da aplicação
  • ✅ Botão de alternância de tema
  • ✅ Padrões harmônicos
  • ✅ Alertas de Fibonacci
  • ✅ Análise de sentimento
  • ✅ Recomendações de trading
  • ✅ Respostas do bot
  • ✅ Rodapé da aplicação
  • ✅ Aplicação automática do tema na inicialização

Configuração

Tema Padrão

A aplicação agora inicia com o tema escuro como padrão:

# No theme_manager.py - Inicialização global
theme_manager = ThemeManager(ThemeType.DARK)

# CSS para aplicação automática do tema
body[data-theme="dark"] {
    background: var(--bg-primary);
    color: var(--text-primary);
}

Aplicação Automática na Inicialização

O tema é aplicado automaticamente quando a interface carrega:

# No create_interface()
theme_update_html.load(
    fn=self._apply_initial_theme,
    outputs=theme_update_html
)

Personalização

Para adicionar novos temas:

  1. Estender o enum ThemeType
  2. Adicionar paleta de cores no ThemeManager
  3. Atualizar o CSS customizado
  4. Implementar componentes específicos se necessário

Funcionalidades Implementadas

  • Botão de Alternância: Interface intuitiva para trocar temas
  • Tema Escuro Padrão: Aplicação inicia com tema escuro
  • Atualização Dinâmica: CSS aplicado via JavaScript sem reload
  • Aplicação Automática: Tema aplicado na inicialização da interface
  • Integração Completa: Todos os componentes suportam alternância

Futuras Melhorias

  • Detecção automática do tema do sistema
  • Persistência da preferência do usuário
  • Temas adicionais (alto contraste, sepia)
  • Animações de transição entre temas
  • API para temas personalizados
  • Atalhos de teclado para alternância

Conclusão

O sistema de temas proporciona uma experiência visual moderna e adaptável, melhorando significativamente a usabilidade da aplicação em diferentes contextos de uso.