SWCore
SWCore / Componentes / Panel (drawer)

Panel (drawer) Componentes

Painel que desliza da borda da tela — carrinho, filtros, menu no celular, detalhes de um item — pela direita, esquerda, topo ou de baixo.

O que é

Sabe o carrinho que entra pela direita quando você clica em "Ver carrinho", ou os filtros que abrem pela esquerda na loja pelo celular? Isso é o painel (também chamado de "drawer"). Ele aparece por cima da página, escurece o fundo e fecha com o × , com a tecla Esc ou clicando fora. Você escreve o painel uma vez com sw-panel e um id, e coloca sw-panel-open="#id" no botão que abre. Para escolher de onde ele vem e o tamanho, escreva palavras no atributo: sw-panel="lft", sw-panel="bot sm"…

Precisa do CSS e do JavaScript do SWCore (os dois arquivos principais). Ao abrir, o painel trava a rolagem da página de trás, põe o foco dentro dele (quem usa teclado já cai no primeiro botão) e, ao fechar, devolve o foco para o botão que abriu. Em telas com menos de 640 px (celular), ele ocupa sempre a tela toda. Uma página pode ter vários painéis; cada um com seu id.

Quando usar

  • Carrinho de compras que abre pela direita sem sair da página — sw-panel.
  • Filtros de uma lista (preço, tamanho, cor) no celular — sw-panel="lft".
  • Menu do site no celular — sw-panel="lft sm".
  • Detalhes de uma linha da tabela no painel admin, sem perder a lista — sw-panel="lg".
  • Opções rápidas que sobem de baixo, como "Compartilhar" no celular — sw-panel="bot".
  • Para uma pergunta curta que pede resposta ("Excluir mesmo?"), use o Modal, que aparece no centro.

Comece aqui

  1. 1

    Coloque o SWCore na página: o CSS no <head> e o JavaScript antes de fechar o </body>. O painel precisa dos dois.

    <link rel="stylesheet" href="https://swcore.sanweb.com.br/dist/2.1.0/swcore.min.css">
    <!-- … sua página … -->
    <script src="https://swcore.sanweb.com.br/dist/2.1.0/swcore.min.js"></script>
  2. 2

    Escreva o botão com sw-panel-open="#id-do-painel" e o painel com o mesmo id. O × precisa de sw-panel-close para fechar.

    Seu carrinho

    2 itens — R$ 348,00

    <button sw-btn="pri" sw-panel-open="#carrinho">Ver carrinho</button>
    
    <div sw-panel id="carrinho">
      <div sw-panel-hdr>
        <h3>Seu carrinho</h3>
        <button sw-panel-cls sw-panel-close aria-label="Fechar"></button>
      </div>
      <div sw-panel-bdy>
        <p>2 itens — R$ 348,00</p>
      </div>
    </div>
  3. 3

    Quer mudar de onde ele vem ou o tamanho? Acrescente palavras: aqui, pela esquerda e estreito.

    Menu

    Início · Serviços · Contato

    <div sw-panel="lft sm" id="menu">…</div>

Todas as variações

Cada quadro abaixo é o componente de verdade, rodando. O código embaixo é exatamente o que está no quadro: copie e cole.

1. De onde ele vem

Sem palavra de posição ele entra pela direita. Clique para ver cada um.

Direita

Entrou pela direita — o padrão. Bom para carrinho e detalhes.
Padrão — direita <button sw-btn="out" sw-panel-open="#pnl-pos-r">Direita</button> <div sw-panel id="pnl-pos-r">…</div>

Esquerda

Entrou pela esquerda. Bom para menu e filtros.
lft — esquerda <button sw-btn="out" sw-panel-open="#pnl-pos-l">Esquerda</button> <div sw-panel="lft" id="pnl-pos-l">…</div>

Topo

Desceu do topo, na largura toda. Bom para busca.
top — desce do topo <button sw-btn="out" sw-panel-open="#pnl-pos-t">Topo</button> <div sw-panel="top" id="pnl-pos-t">…</div>

Baixo

Subiu de baixo, na largura toda. Bom para opções no celular.
bot — sobe de baixo <button sw-btn="out" sw-panel-open="#pnl-pos-b">Baixo</button> <div sw-panel="bot" id="pnl-pos-b">…</div>

2. Tamanhos

O tamanho é a largura (nos painéis da direita/esquerda) ou a altura (topo/baixo). Sem palavra: 450 px. No celular (menos de 640 px) ele ocupa a tela toda, qualquer que seja o tamanho.

sm

240 px. Cabe um menu ou uma lista curta.
sm — estreito (240 px) <button sw-btn="out" sw-panel-open="#pnl-tam-sm">sm</button> <div sw-panel="sm" id="pnl-tam-sm">…</div>

Padrão

450 px. O tamanho do meio.
Padrão (450 px) <button sw-btn="out" sw-panel-open="#pnl-tam-md">Padrão</button> <div sw-panel id="pnl-tam-md">…</div>

lg

640 px.
lg — largo (640 px) <button sw-btn="out" sw-panel-open="#pnl-tam-lg">lg</button> <div sw-panel="lg" id="pnl-tam-lg">…</div>

fl

Ocupa a largura toda da tela.
fl — tela toda (100%) <button sw-btn="out" sw-panel-open="#pnl-tam-fl">fl</button> <div sw-panel="fl" id="pnl-tam-fl">…</div>

3. Combinando posição e tamanho

Uma palavra de posição + uma de tamanho, na ordem que quiser.

Menu

Início
Serviços
Contato
lft sm — menu lateral estreito <button sw-btn="out" sw-panel-open="#pnl-cmb-1">lft sm</button> <div sw-panel="lft sm" id="pnl-cmb-1">…</div>

Tela cheia

Subiu de baixo até o limite de 85% da altura.
bot fl — sobe e cobre a tela <button sw-btn="out" sw-panel-open="#pnl-cmb-2">bot fl</button> <div sw-panel="bot fl" id="pnl-cmb-2">…</div>

4. Partes do painel

Todas opcionais. Com cabeçalho e rodapé, só o corpo rola quando o conteúdo é alto — o título e os botões ficam sempre à vista.

Seu carrinho

Camiseta básica — R$ 59,90

Boné — R$ 39,90

Este corpo rola por dentro quando tem muita coisa.

Cabeçalho + corpo + rodapé
<button sw-btn="pri" sw-panel-open="#carrinho">Abrir painel completo</button>

<div sw-panel id="carrinho">
  <div sw-panel-hdr>                     <!-- cabeçalho: fica fixo em cima -->
    <h3>Seu carrinho</h3>
    <button sw-panel-cls sw-panel-close aria-label="Fechar"></button>
  </div>
  <div sw-panel-bdy>                     <!-- corpo: rola por dentro -->
    <p>Camiseta básica — R$ 59,90</p>
    <p>Boné — R$ 39,90</p>
  </div>
  <div sw-panel-ftr>                     <!-- rodapé: fica fixo embaixo -->
    <button sw-btn="pri" sw-panel-close>Finalizar compra</button>
    <button sw-btn="ghost sec" sw-panel-close>Continuar comprando</button>
  </div>
</div>

Tabela de opções

PalavraO que fazExemplo
Posição (valor de sw-panel)
(nenhuma)Entra pela direita.<div sw-panel id="x">
lftEntra pela esquerda.<div sw-panel="lft" id="x">
topDesce do topo, na largura toda. Altura máxima: 85% da tela.<div sw-panel="top" id="x">
botSobe de baixo, na largura toda. Altura máxima: 85% da tela.<div sw-panel="bot" id="x">
Tamanho (valor de sw-panel)
sm240 px.<div sw-panel="sm" id="x">
(nenhum)450 px.
lg640 px.<div sw-panel="lg" id="x">
fl100% (tela toda naquela direção).<div sw-panel="fl" id="x">
Abrir e fechar
sw-panel-open="#id"No botão ou link de fora: abre o painel daquele id (tem que começar com #).<button sw-panel-open="#carrinho">
sw-panel-closeEm qualquer coisa dentro do painel: clicar fecha.<button sw-panel-close>Fechar</button>
Tecla EscFecha o painel aberto.
Clique foraClicar no fundo escuro (ou fora do painel) fecha.
Partes (atributos dentro do painel)
sw-panel-hdrCabeçalho: título à esquerda, × à direita. Fica fixo em cima.<div sw-panel-hdr>
sw-panel-bdyCorpo: ocupa o espaço que sobra e rola por dentro.<div sw-panel-bdy>
sw-panel-ftrRodapé: botões de ação lado a lado. Fica fixo embaixo.<div sw-panel-ftr>
sw-panel-clsDesenha o × (botão redondo). Junte com sw-panel-close para ele fechar.<button sw-panel-cls sw-panel-close aria-label="Fechar"></button>
Ajuste fino (no CSS da sua página)
--sw-panel-szLargura (ou altura, em topo/baixo) exata, em px, rem ou %..pnl-filtros { --sw-panel-sz: 360px; }
--sw-panel-spdDuração da animação de abrir/fechar. Padrão: 0.35s..pnl-filtros { --sw-panel-spd: .6s; }

Receitas prontas — usos reais

Situações que aparecem em quase todo site. Copie a que servir.

Carrinho da loja (direita) Ao vivo

Carrinho

Camiseta básica (M)R$ 59,90

Boné pretoR$ 39,90

TotalR$ 99,80
Finalizar compra
<button sw-btn="suc" sw-panel-open="#carrinho"><i class="swi-cart"></i> Carrinho (2)</button>

<div sw-panel id="carrinho">
  <div sw-panel-hdr>
    <h3>Carrinho</h3>
    <button sw-panel-cls sw-panel-close aria-label="Fechar"></button>
  </div>
  <div sw-panel-bdy>
    <div class="flx j-sb"><span>Camiseta básica (M)</span><span>R$ 59,90</span></div>
    <hr sw-div="dsh">
    <div class="flx j-sb"><span>Boné preto</span><span>R$ 39,90</span></div>
    <hr sw-div>
    <div class="flx j-sb"><strong>Total</strong><strong>R$ 99,80</strong></div>
  </div>
  <div sw-panel-ftr>
    <a href="/checkout" sw-btn="suc">Finalizar compra</a>
    <button sw-btn="ghost sec" sw-panel-close>Continuar comprando</button>
  </div>
</div>
Filtros da loja pela esquerda Ao vivo

Filtrar produtos

<button sw-btn="out" sw-panel-open="#filtros"><i class="swi-filter"></i> Filtrar</button>

<div sw-panel="lft" id="filtros">
  <div sw-panel-hdr>
    <h3>Filtrar produtos</h3>
    <button sw-panel-cls sw-panel-close aria-label="Fechar"></button>
  </div>
  <div sw-panel-bdy>
    <div sw-fld>
      <label for="cat">Categoria</label>
      <select sw-inp id="cat"><option>Todas</option><option>Camisetas</option></select>
    </div>
    <div class="sw-chk-grp">
      <label sw-chk><input type="checkbox" checked> Só com frete grátis</label>
      <label sw-chk><input type="checkbox"> Só em promoção</label>
    </div>
  </div>
  <div sw-panel-ftr>
    <button sw-btn="pri" sw-panel-close>Ver resultados</button>
  </div>
</div>
Painel admin: abrir os detalhes de uma linha pelo JavaScript Ao vivo

Pedido

Cliente: Maria Souza

Status: pago

<div sw-panel="lg" id="detalhe">
  <div sw-panel-hdr>
    <h3 id="detalhe-titulo">Pedido</h3>
    <button sw-panel-cls sw-panel-close aria-label="Fechar"></button>
  </div>
  <div sw-panel-bdy id="detalhe-corpo"></div>
</div>

<script>
  // chamado ao clicar numa linha da tabela
  function abrirPedido(numero) {
    document.getElementById('detalhe-titulo').textContent = 'Pedido #' + numero;
    SW.Panel.show('#detalhe');
  }

  // avisa quando fechou (ex.: atualizar a tabela)
  document.getElementById('detalhe').addEventListener('sw:panel:close', () => {
    console.log('painel fechado');
  });
</script>
Opções que sobem de baixo (celular) Ao vivo

Compartilhar

WhatsApp E-mail
<button sw-btn="out" sw-panel-open="#compartilhar">Compartilhar</button>

<div sw-panel="bot" id="compartilhar">
  <div sw-panel-hdr>
    <h3>Compartilhar</h3>
    <button sw-panel-cls sw-panel-close aria-label="Fechar"></button>
  </div>
  <div sw-panel-bdy>
    <a href="https://wa.me/?text=…" sw-btn="suc"><i class="swi-chat"></i> WhatsApp</a>
    <a href="mailto:?body=…" sw-btn="inf"><i class="swi-envelope"></i> E-mail</a>
  </div>
</div>

Eventos

sw:panel:open
O painel abriu. Dispara no próprio painel (<div sw-panel>) e sobe para a página.
sw:panel:close
O painel fechou — pelo ×, Esc, clique fora, SW.Panel.hide() ou porque ele saiu da página.

API (JavaScript)

SW.Panel.show('#id')
Abre o painel. Aceita o texto '#id' ou o próprio elemento. Devolve true se abriu (false se já estava aberto ou não existe).
SW.Panel.hide('#id')
Fecha o painel. Devolve true se fechou.

Precisa de quê

  • swcore.min.css e swcore.min.js — o painel precisa dos dois.
  • swcore.compl.min.css — só se usar ícone swi-* dentro dele.

Cuidados — erros comuns

  • O valor de sw-panel-open tem que começar com #: sw-panel-open="#carrinho". Sem o #, o botão não faz nada.
  • O × (sw-panel-cls) é só o desenho. Sem sw-panel-close junto, ele não fecha.
  • Dois painéis com o mesmo id: o botão sempre abre o primeiro.
  • Não coloque o painel dentro de uma caixa com animação de movimento (transform) ou filtro: ele passa a se prender a essa caixa em vez da tela. O lugar mais seguro é direto no <body>.
  • Dê um aria-label="Fechar" ao botão do ×, que não tem texto.

O que ele não faz

  • Um de cada vez: um botão que abre outro painel de dentro de um painel aberto deixa os dois abertos. Feche o primeiro com SW.Panel.hide() antes de abrir o segundo.
  • Enquanto está aberto, a página de trás não rola.
  • Em topo/baixo, a altura para em 85% da tela (no celular, na tela toda).
  • Para uma pergunta curta e centralizada, o componente certo é o Modal.