Skip to content
Extensões

Guia de Uso - Loader

Status: Implementado (Design System 1.0 - 02/02/2026) - Componente de loading com spinner circular e icone central.

Indice

  1. Introducao
  2. Estrutura Base
  3. Tamanhos
  4. Variantes de Cor
  5. Modo Progress
  6. Dark Mode
  7. Uso com Modal
  8. JavaScript
  9. Exemplos Praticos

Introducao

O componente Loader e utilizado para indicar operacoes em andamento. Diferente do spinner simples, possui:

  • Circulo animado com arco de progresso
  • Icone central (customizavel)
  • Titulo e subtitulo descritivos
  • Suporte completo a dark/light mode

Quando Usar Loader

Use loader quando:

  • Uma operacao demora mais de 1-2 segundos
  • Deseja mostrar progresso visual com contexto
  • Precisa de feedback ao usuario com descricao
  • A operacao tem etapas que podem ser descritas

Evite usar loader quando:

  • A operacao e instantanea (use skeleton ou nada)
  • Nao ha contexto para mostrar (use spinner simples)
  • O espaco e muito pequeno (use spinner ou progress)

Estrutura Base

HTML Basico

html
<div class="loader">
    <!-- Spinner com Ring e Icone -->
    <div class="loader__spinner">
        <!-- Ring SVG -->
        <div class="loader__ring">
            <svg viewBox="0 0 96 96">
                <circle class="loader__ring-track" cx="48" cy="48" r="44"></circle>
                <circle class="loader__ring-arc" cx="48" cy="48" r="44"></circle>
            </svg>
        </div>

        <!-- Icone Central -->
        <div class="loader__icon">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
                 stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
                <polyline points="14 2 14 8 20 8"/>
                <line x1="16" y1="13" x2="8" y2="13"/>
                <line x1="16" y1="17" x2="8" y2="17"/>
                <polyline points="10 9 9 9 8 9"/>
            </svg>
        </div>
    </div>

    <!-- Conteudo de Texto -->
    <div class="loader__content">
        <h3 class="loader__title">Gerando documento...</h3>
        <p class="loader__subtitle">Validando e-mail</p>
    </div>
</div>

Classes Principais

ClasseDescricao
.loaderContainer principal
.loader__spinnerContainer do spinner (ring + icone)
.loader__ringSVG do anel animado
.loader__ring-trackCirculo de fundo (track)
.loader__ring-arcArco animado de progresso
.loader__iconContainer do icone central
.loader__contentContainer dos textos
.loader__titleTitulo principal
.loader__subtitleSubtitulo/descricao

Tamanhos

Small (64px)

html
<div class="loader loader--sm">
    ...
</div>

Medium - Padrao (96px)

html
<div class="loader">
    ...
</div>

Large (128px)

html
<div class="loader loader--lg">
    ...
</div>

Variantes de Cor

O arco de progresso usa --color-primary (vermelho) por padrao. Variantes disponiveis:

Primary (Padrao - Vermelho)

html
<div class="loader">
    <!-- Arco vermelho #970707 -->
</div>

Success (Verde)

html
<div class="loader loader--success">
    <!-- Arco verde #519000 -->
</div>

Info (Azul)

html
<div class="loader loader--info">
    <!-- Arco azul #3E68FB -->
</div>

Warning (Amarelo)

html
<div class="loader loader--warning">
    <!-- Arco amarelo #E9BD00 -->
</div>

Danger (Vermelho Alerta)

html
<div class="loader loader--danger">
    <!-- Arco vermelho #C90A0A -->
</div>

Modo Progress

Para mostrar progresso real (nao infinito), use a classe .loader--progress:

html
<div class="loader loader--progress">
    <div class="loader__spinner">
        <div class="loader__ring">
            <svg viewBox="0 0 96 96">
                <circle class="loader__ring-track" cx="48" cy="48" r="44"></circle>
                <circle class="loader__ring-arc" cx="48" cy="48" r="44"
                        style="stroke-dashoffset: 138.23"></circle>
            </svg>
        </div>
        <div class="loader__icon">...</div>
    </div>
    <div class="loader__content">
        <h3 class="loader__title">Processando...</h3>
        <p class="loader__subtitle">50% concluido</p>
    </div>
</div>

Calculo do Progresso

javascript
// Circunferencia = 2 * PI * raio (44)
const radius = 44;
const circumference = 2 * Math.PI * radius; // ~276.46

// Offset = (100 - percentual) / 100 * circunferencia
function calculateOffset(percent) {
    return ((100 - percent) / 100) * circumference;
}

// Exemplos:
// 0%   -> offset = 276.46 (circulo vazio)
// 25%  -> offset = 207.35
// 50%  -> offset = 138.23
// 75%  -> offset = 69.12
// 100% -> offset = 0 (circulo completo)

Dark Mode

O componente suporta dark mode automaticamente atraves das variaveis CSS. Nao e necessario fazer nada adicional.

Cores no Dark Mode

ElementoLight ModeDark Mode
Background (fullscreen)#F6F6F9#10141D
Ring Track#CED3E2#2A2F41
Ring Arc#970707#970707
Icon Background#ECEDF2#1D2333
Icon Color#394360#A2A8B9
Title#12151F#E0E2EB
Subtitle#394360#A2A8B9

Uso com Modal

Dentro de um Modal

html
<div class="modal modal--active">
    <div class="loader loader--modal">
        <!-- Estrutura do loader -->
    </div>
</div>

Fullscreen (Tela Inteira)

html
<div class="loader loader--fullscreen">
    <!-- Estrutura do loader -->
</div>

JavaScript

Funcao Helper para Exibir/Ocultar

javascript
/**
 * Mostra o loader com titulo e subtitulo personalizados
 * @param {Object} options - Opcoes do loader
 * @param {string} options.title - Titulo principal
 * @param {string} options.subtitle - Subtitulo/descricao
 * @param {string} options.icon - HTML do icone (opcional)
 * @param {string} options.variant - Variante de cor (opcional)
 */
function showLoader(options = {}) {
    const {
        title = 'Carregando...',
        subtitle = '',
        icon = null,
        variant = ''
    } = options;

    // Remove loader existente
    hideLoader();

    const loaderHTML = `
        <div class="loader loader--fullscreen loader--fade-in ${variant ? 'loader--' + variant : ''}" id="app-loader">
            <div class="loader__spinner">
                <div class="loader__ring">
                    <svg viewBox="0 0 96 96">
                        <circle class="loader__ring-track" cx="48" cy="48" r="44"></circle>
                        <circle class="loader__ring-arc" cx="48" cy="48" r="44"></circle>
                    </svg>
                </div>
                <div class="loader__icon">
                    ${icon || getDefaultIcon()}
                </div>
            </div>
            <div class="loader__content">
                <h3 class="loader__title">${title}</h3>
                ${subtitle ? `<p class="loader__subtitle">${subtitle}</p>` : ''}
            </div>
        </div>
    `;

    document.body.insertAdjacentHTML('beforeend', loaderHTML);
}

/**
 * Oculta o loader
 */
function hideLoader() {
    const loader = document.getElementById('app-loader');
    if (loader) {
        loader.classList.add('loader--fade-out');
        loader.addEventListener('animationend', () => loader.remove());
    }
}

/**
 * Atualiza o texto do loader
 * @param {string} title - Novo titulo
 * @param {string} subtitle - Novo subtitulo
 */
function updateLoader(title, subtitle) {
    const loader = document.getElementById('app-loader');
    if (loader) {
        const titleEl = loader.querySelector('.loader__title');
        const subtitleEl = loader.querySelector('.loader__subtitle');

        if (titleEl) titleEl.textContent = title;
        if (subtitleEl) subtitleEl.textContent = subtitle;
    }
}

/**
 * Icone padrao (documento)
 */
function getDefaultIcon() {
    return `
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
             stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
            <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
            <polyline points="14 2 14 8 20 8"/>
            <line x1="16" y1="13" x2="8" y2="13"/>
            <line x1="16" y1="17" x2="8" y2="17"/>
            <polyline points="10 9 9 9 8 9"/>
        </svg>
    `;
}

Exemplo de Uso

javascript
// Mostrar loader simples
showLoader({ title: 'Carregando...' });

// Mostrar loader com detalhes
showLoader({
    title: 'Gerando documento...',
    subtitle: 'Validando e-mail'
});

// Mostrar loader com variante
showLoader({
    title: 'Enviando dados...',
    subtitle: 'Aguarde',
    variant: 'primary'
});

// Atualizar texto durante operacao
updateLoader('Processando...', 'Etapa 2 de 3');

// Ocultar loader
hideLoader();

Exemplos Praticos

Exemplo 1: Geracao de Documento

html
<div class="loader">
    <div class="loader__spinner">
        <div class="loader__ring">
            <svg viewBox="0 0 96 96">
                <circle class="loader__ring-track" cx="48" cy="48" r="44"></circle>
                <circle class="loader__ring-arc" cx="48" cy="48" r="44"></circle>
            </svg>
        </div>
        <div class="loader__icon">
            <!-- Icone de documento -->
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
                 stroke="currentColor" stroke-width="2">
                <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
                <polyline points="14 2 14 8 20 8"/>
                <line x1="16" y1="13" x2="8" y2="13"/>
                <line x1="16" y1="17" x2="8" y2="17"/>
            </svg>
        </div>
    </div>
    <div class="loader__content">
        <h3 class="loader__title">Gerando documento...</h3>
        <p class="loader__subtitle">Validando e-mail</p>
    </div>
</div>

Exemplo 2: Upload de Arquivo

html
<div class="loader loader--info">
    <div class="loader__spinner">
        <div class="loader__ring">
            <svg viewBox="0 0 96 96">
                <circle class="loader__ring-track" cx="48" cy="48" r="44"></circle>
                <circle class="loader__ring-arc" cx="48" cy="48" r="44"></circle>
            </svg>
        </div>
        <div class="loader__icon">
            <!-- Icone de upload -->
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
                 stroke="currentColor" stroke-width="2">
                <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
                <polyline points="17 8 12 3 7 8"/>
                <line x1="12" y1="3" x2="12" y2="15"/>
            </svg>
        </div>
    </div>
    <div class="loader__content">
        <h3 class="loader__title">Enviando arquivo...</h3>
        <p class="loader__subtitle">relatorio-2026.pdf</p>
    </div>
</div>

Exemplo 3: Processamento com Progresso

html
<div class="loader loader--progress">
    <div class="loader__spinner">
        <div class="loader__ring">
            <svg viewBox="0 0 96 96">
                <circle class="loader__ring-track" cx="48" cy="48" r="44"></circle>
                <circle class="loader__ring-arc" cx="48" cy="48" r="44"
                        id="progress-arc" style="stroke-dashoffset: 138.23"></circle>
            </svg>
        </div>
        <div class="loader__icon">
            <!-- Icone de processamento -->
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
                 stroke="currentColor" stroke-width="2">
                <circle cx="12" cy="12" r="10"/>
                <polyline points="12 6 12 12 16 14"/>
            </svg>
        </div>
    </div>
    <div class="loader__content">
        <h3 class="loader__title">Processando dados...</h3>
        <p class="loader__subtitle" id="progress-text">50% concluido</p>
    </div>
</div>

<script>
function updateProgress(percent) {
    const arc = document.getElementById('progress-arc');
    const text = document.getElementById('progress-text');
    const circumference = 276.46;
    const offset = ((100 - percent) / 100) * circumference;

    arc.style.strokeDashoffset = offset;
    text.textContent = percent + '% concluido';
}
</script>

Icones Sugeridos

Documento

html
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
    <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
    <polyline points="14 2 14 8 20 8"/>
    <line x1="16" y1="13" x2="8" y2="13"/>
    <line x1="16" y1="17" x2="8" y2="17"/>
</svg>

Upload

html
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
    <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
    <polyline points="17 8 12 3 7 8"/>
    <line x1="12" y1="3" x2="12" y2="15"/>
</svg>

Download

html
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
    <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
    <polyline points="7 10 12 15 17 10"/>
    <line x1="12" y1="15" x2="12" y2="3"/>
</svg>

Relogio/Processamento

html
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
    <circle cx="12" cy="12" r="10"/>
    <polyline points="12 6 12 12 16 14"/>
</svg>

Email

html
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
    <path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"/>
    <polyline points="22,6 12,13 2,6"/>
</svg>

Boas Praticas

  1. Use titulos descritivos: Seja claro sobre o que esta acontecendo
  2. Atualize o subtitulo: Mostre progresso ou etapas quando possivel
  3. Escolha icones apropriados: O icone deve refletir a acao
  4. Use variantes de cor: Diferencie tipos de operacoes
  5. Considere o tempo: Loaders muito longos frustram usuarios

Versao: 1.0.0 Data: 02/02/2026 CSS: /public/css/design-system/components/loader.cssExemplo: /public/css/design-system/examples/loader.html

Design System interno do GALES