Componentes

Gráficos


O gráfico é uma representação visual utilizada para apresentar dados. Podem ser usados, por exemplo, para mostrar padrões ou comparar informações.

Hoje usamos o framework Chart.js para a renderização de gráficos.

Anatomia

Imagem que representa anatomia de um gráfico
Imagem que representa anatomia de um gráfico

1. Título

O título é obrigatório em todos os gráficos. Ele serve para fornecer contexto ao usuário.

2. Descrição curta (opcional)

Use a descrição quando for necessário um texto complementar ao título para a contextualização ou quando precisar explicar um indicador. A descrição deve ser sucinta e caber na área destinada a ela em cada componente.

3. Legenda (opcional)

A legenda deve ser usada somente quando necessária. Se, por exemplo, o gráfico possuir apenas uma cor, não use legenda.

4. Gráfico

Completando o componente, temos de fato o gráfico. Este deve ser escolhido de acordo com o objetivo e os dados a serem apresentados. Falamos mais sobre isso no subtítulo Tipos de Gráficos.

As cores utilizadas nos gráficos não são as cores padrão do Purple, são cores específicas para uso nesse contexto e serão apresentadas na próxima seção.

5. Tooltip

As tooltips servem como texto de apoio e jamais devem conter informações essenciais para o entendimento do gráfico. Podem ser usadas para mostrar percentagens ou totais por categoria dos gráficos e complementar informações. Por exemplo, se a descrição curta for maior que o espaço destinado a ela, irredutível e ainda assim necessária, você pode iniciar o texto no campo descrição curta, colocar reticencias no final e o texto completo na tooltip. Isso pode funcionar apenas em gráficos do menor tamanho.

A largura máxima de uma tooltip é 228px (equivalente a 3 colunas do grid com menu lateral). Você pode encontrar mais diretrizes relacionadas a esse componente na página Tooltip.

Eixos

Os gráficos possuem 2 eixos: X e Y. Para que possamos fazer um combinado, é importante que você saiba qual é qual.

Imagem que representa os eixos X e Y de um gráfico
Imagem que representa os eixos X e Y de um gráfico

Vamos ao combinado: Quando um dos eixos for relativo a tempo, ele deve ser sempre o eixo X. Isso é porque o tempo nos gráficos parte da esquerda para a direita.

Tipos de Gráficos

Inicialmente trabalharemos com 4 tipos de gráficos (barras, linha, circular e numeral) e tabelas para compor dashboards.

Barras

Um gráfico de barras, também conhecido como gráfico de colunas, representa os dados através de retângulos com alturas ou comprimentos proporcionais aos valores declarados.

Serve para comparações de dados.

Sent messages

Default bar chart.

Sent messages

Alternative bar chart: horizontalBar

<div class="columns is-centered is-multiline">
  <div class="column is-12 is-8-desktop is-6-widescreen">
    <div class="chart">
      <h3 class="chart-title">Sent messages</h3>
      <p>Default bar chart.</p>
      <div class="chart-data">
        <canvas id="chart-01"></canvas>
      </div>
    </div>
  </div>

  <div class="column is-12 is-8-desktop is-6-widescreen">
    <div class="chart">
      <h3 class="chart-title">Sent messages</h3>
      <p>Alternative bar chart: <code>horizontalBar</code></p>
      <div class="chart-data">
        <canvas id="chart-02"></canvas>
      </div>
    </div>
  </div>
</div>

Para gráficos com rótulos longos, use o gráfico de barras horizontais.

O número recomendado de barras é 7 ou menos.

Organização de dados

Ao usar um gráfico de barras ou colunas, caso a organização dos dados não seja por data, considere mostrá-los de ordem crescente ou decrescente. Busque sempre uma forma lógica de apresentação dos dados.

O eixo Value (geralmente o Y) sempre deve começar do 0. Isso evita que os cérebros das pessoas sejam enganados por distorções visuais.

Caso uma das dimensões seja tempo, deve ficar sempre que possível no eixo X.

Linhas

O gráfico de linhas exibe dados como pontos (chamados “marcadores”) conectados por linhas.

Serve para comparar dados através do tempo.

Não use esse tipo de gráfico se não for comparar dados em função do tempo.

API Calls

Multiple series.

<div class="columns is-centered is-multiline">
  <div class="column is-12 is-8-desktop is-6-widescreen">
    <div class="chart">
      <h3 class="chart-title">API Calls</h3>
      <p>Multiple series.</p>
      <div class="chart-data">
        <canvas id="chart-03"></canvas>
      </div>
    </div>
  </div>
</div>

Dependendo da largura do gráfico e dos números que serão apresentados, os gráficos de linhas podem ser afetados. Se a inclinação for muito drástica irá influenciar na percepção da informação. Na próxima seção falaremos sobre os tamanhos de gráficos, isso pode ajudar. A recomendação é que os ângulos fiquem em até 45°, então caso os ângulos fiquem muito estreitos com o tamanho que está usando (ex. small), recomendamos utilizar o próximo (ex. medium).

O número recomendado de linhas é 5 a 7 nos tamanhos medium e large e no máximo 4 no tamanho small.

Legenda

A legenda deve seguir a leitura de cima para baixo, sendo o primeiro label o que tem a primeira marcação mais acima.

A única variação deste gráfico que dispensa legenda é quando temos apenas uma linha.

Circular

O gráfico circular representa os dados como fatias proporcionais. Eles mostram partes de um todo.

Serve para apresentação de dados.

Users

Total users by channel.

<div class="columns is-centered">
  <div class="column is-12 is-8-desktop is-6-widescreen">
    <div class="chart">
      <h3 class="chart-title">Users</h3>
      <p>Total users by channel.</p>
      <div class="chart-data">
        <canvas id="chart-04"></canvas>
      </div>
    </div>
  </div>
</div>

Não use gráfico circular se o valor total não soma 100% ou se os valores forem muito semelhantes. Devido a se tratar de ângulos e áreas, é muito difícil de ler nesse caso. Para essa situação, considere usar o gráfico de barras.

Esse gráfico infelizmente possui uma má reputação, por conta de aplicações que não comunicam de forma clara. Por isso, é essencial que esteja atento as diretrizes de uso que serão apresentadas a seguir.

Organização de dados

Ordene as categorias em ordem decrescente, iniciando no ponto 12h. Organize a legenda da maior fatia para a menor.

Use cores diferentes para cada fatia.

Adicione no máximo 5 fatias ao gráfico. Caso seja necessário mais fatias, é melhor optar pelo uso de outro tipo de gráfico. O uso de mais fatias exige outras formas de apresentação de rótulos que podem não ser efetivas.

Numeral

Esse gráfico contem um número ou porcentagem e é usado para dar visibilidade a dados.

Atendimentos

Total de atendimentos pelo Zenvia Chat.

158 -2%

Comparado ao mês anterior

Mensagens enviadas

Total de mensagens recebidas.

95.108 +34%

Comparado ao mês anterior

<div class="columns is-centered is-multiline">

  <div class="column is-12 is-8-desktop is-6-widescreen">
    <div class="chart">
      <h3 class="chart-title">Atendimentos</h3>
      <p>Total de atendimentos pelo Zenvia Chat.</p>
      <div class="chart-data">
        <span class="chart-data-number">158</span>
        <span class="chart-data-delta" data-value="-2">-2%</span>
        <p>Comparado ao mês anterior</p>
      </div>
    </div>
  </div>

  <div class="column is-12 is-8-desktop is-6-widescreen">
    <div class="chart is-success">
      <h3 class="chart-title">Mensagens enviadas</h3>
      <p>Total de mensagens recebidas.</p>
      <div class="chart-data">
        <span class="chart-data-number">95.108</span>
        <span class="chart-data-delta" data-value="34">+34%</span>
        <p>Comparado ao mês anterior</p>
      </div>
    </div>
  </div>
</div>

Em caso de comparação com período anterior (ex.: crescimento percentual de vendas), é recomendado que o aumento ou a queda seja indicado também através de cores (verde e vermelho) e símbolos (seta para cima e para baixo). Nesse caso, sempre informe o usuário com qual período estamos comparando os dados.

Atenção: dependendo do indicador, uma queda pode ser positiva e um aumento negativo. Um exemplo disso é o indicador “Contatos não confirmados” do Zenvia Flow (o aumento é negativo).

Tamanhos

Temos 3 tamanhos de gráficos: Small (4 colunas da grid), Medium (6 colunas) e Large (8 colunas). Sendo o medium o tamanho padrão, mais recomendado por se adequar melhor a mais situações.

A altura de todos eles é padrão, possui 376px.

Exemplo dos tamanhos possíveis de gráficos
Exemplo dos tamanhos possíveis de gráficos

Ainda não existem definições de quando cada tamanho deve ser utilizado. Esse tamanho deve ser definido pelo Designer, PM ou outro responsável de acordo com os dados a serem apresentados.

Os gráficos de tamanhos medium e large são iguais em todos os gráficos, com exceção do numeral que não possui tamanho large, apenas small e medium. Já os gráficos small possuem algumas particularidades.

Small

Os gráficos desse tamanho possuem as legendas sempre na parte superior e sua descrição pode não estar completa no campo Descrição curta, deixando reticências e o texto completo em uma tooltip.

Além disso, os gráficos de barras e linhas possuem um grid reduzido no eixo que contém Value.

Aplicação

Os gráficos sempre devem ser postos dentro de cards, isso te dará mais flexibilidade e ajudará a torná-lo responsivo, além de manter a estrutura consistente. As margens internas do card devem ser de no mínimo 24px.

Ausência de dados

Quando houver ausência de dados, mostre isso visualmente. Opte, por exemplo, por fazer uma pausa no gráfico de linha ou não mostrar uma coluna no gráfico de barras.

Exemplo de gráficos com intervalores de dados faltando
Exemplo de gráficos com intervalores de dados faltando

Última atualização

Os gráficos não são atualizados em tempo real. Por esse motivo, é necessário que sempre informemos o usuário que podem haver novos dados. Para isso, temos duas abordagens:

Caso o gráfico esteja em um Dashboard

Deve ser apresentada a data e hora de atualização da página em geral. Conheça as diretrizes para esse caso na página Dashboard.

Caso o gráfico não esteja em um Dashboard

A data e hora de atualização devem ser apresentadas fora do card de gráfico, com o estilo Caption. A posição deve ser decidida de acordo com a necessidade de cada página. Veja abaixo as possibilidades:

Imagem que mostra a data e hora da última atualização dos dados
Imagem que mostra a data e hora da última atualização dos dados

Para a última atualização, utilizamos o Human Readable timestamp format.

Boas Práticas

  • Opte pelo grid horizontal ou vertical. Evite o uso de ambos ao mesmo tempo.
  • Não dependa de tooltips. Elas devem ser usadas apenas como apoio.
  • Use legenda apenas quando for necessário.
  • Evite misturar tipos de gráficos (ex. barras e linhas).

Scripts de inicialização de gráficos

Para começar a usar gráficos em sua página, o script abaixo deve ser carregado como dependência:

<!-- Chart.js library -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/Chart.min.js"></script>

Como o Chart.js possui suas próprias guidelines e comportamentos, precisamos mudar algumas configurações para se adequar ao estilo de uso da Zenvia. Adicione as configurações abaixo no script de sua aplicação.

// General behavior
Chart.defaults.global.responsive = true;

// Font
Chart.defaults.global.defaultFontColor = '#2f3039';
Chart.defaults.global.defaultFontFamily = 'Nunito Sans';
Chart.defaults.global.defaultFontSize = 14;
Chart.defaults.global.maintainAspectRatio = false;

// Legend
Chart.defaults.global.legend.align = 'start';
Chart.defaults.global.legend.fontColor = '#2f3039';
Chart.defaults.global.legend.fontFamily = 'Nunito Sans';
Chart.defaults.global.legend.labels.boxWidth = 8;
Chart.defaults.global.legend.labels.usePointStyle = true;

// Elements
Chart.defaults.global.elements.arc.borderWidth = 0;
Chart.defaults.global.elements.line.fill = false;
Chart.defaults.global.elements.line.borderWidth = 2;

<!-- See below how to start chart rendering -->

<button class="button" onclick="renderCharts()">Render charts</button>

<script>
  function renderCharts() {

    // Chart 01
    new Chart(document.getElementById('chart-01'), {
      type: 'bar',
      data: {
        labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul'],
        datasets: [{
          label: 'SMS',
          data: [112, 193, 37, 59, 22, 30, 118],
          backgroundColor: '#0096dc'
        },{
          label: 'WhatsApp',
          data: [98, 116, 47, 105, 83, 131, 96],
          backgroundColor: '#ec407a'
        }]
      },
      options: {
        scales: { // for stacked bar charts
          xAxes: [{
            stacked: true,
            gridLines: {
              display: false
            }
          }],
          yAxes: [{
            stacked: true,
            gridLines: {
              drawBorder: false
            }
          }]
        }
      }
    });

    // Chart 02
    new Chart(document.getElementById('chart-02'), {
      type: 'horizontalBar',
      data: {
        labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul'],
        datasets: [{
          label: 'SMS',
          data: [112, 193, 37, 59, 22, 30, 118],
          backgroundColor: '#0096dc'
        },{
          label: 'WhatsApp',
          data: [98, 116, 47, 105, 83, 131, 96],
          backgroundColor: '#ec407a'
        }]
      },
      options: {
        scales: { // for stacked bar charts
          xAxes: [{
            stacked: true,
            gridLines: {
              drawBorder: false
            }
          }],
          yAxes: [{
            stacked: true,
            gridLines: {
              display: false
            }
          }]
        }
      }
    });

    // Chart 03
    new Chart(document.getElementById('chart-03'), {
      type: 'line',
      data: {
        labels: ['0h', '3h', '6h', '9h', '12h', '15h', '18h', '21h'],
        datasets: [{
          label: 'SMS',
          data: [112, 143, 37, 59, 22, 30, 118, 80],
          backgroundColor: '#0096dc',
          borderColor: '#0096dc'
        },{
          label: 'WhatsApp',
          data: [71, 17, 47, 15, 30, 78, 6, 54],
          backgroundColor: '#ec407a',
          borderColor: '#ec407a'
        },{
          label: 'RCS',
          data: [98, 116, 47, 105, 83, 131, 96, 18],
          backgroundColor: '#00cbee',
          borderColor: '#00cbee'
        },{
          label: 'Voice',
          data: [4, 2, 12, 9, 27, 31, 6, 33],
          backgroundColor: '#f48fb1',
          borderColor: '#f48fb1'
        }]
      },
      options: {
        scales: {
          xAxes: [{
            gridLines: {
              display: false
            }
          }],
          yAxes: [{
            gridLines: {
              drawBorder: false
            }
          }]
        }
      }
    });

    // Chart 04
    new Chart(document.getElementById('chart-04'), {
      type: 'doughnut',
      data: {
        labels: ['WhatsApp', 'SMS', 'Facebook', 'RCS'],
        datasets: [{
          data: [1450, 780, 640, 400],
          backgroundColor: [
            '#ec407a',
            '#f48fb1',
            '#ad1457',
            '#f06292'
          ]
        }]
      },
      options: {
        legend: {
          align: 'middle',
          position: 'right'
        }
      }
    });
  }

  window.onload = function() {
    renderCharts();
  };
</script>

Para mais informações de como usar e configurar os gráficos, acesse documentação do Chart.js