Como personalizar o visual de mensagens Flash no Rails

Tutoriais - 22/Abr/2021 - por Rafael Aquino

Introdução

O Rails possui uma forma de enviar mensagens, flash messages, que são exibidas na view e você pode personalizar com qualquer texto que quiser, por exemplo, com o status do resultado da requisição. Para armazenar essa mensagem é utilizado o objeto flash e este possui, por padrão, as seguintes chaves: :notice, :info, :warning, : error. Levando em conta que na maioria dos projetos temos requisições que retornam sucesso, falha ou queremos apenas passar uma informação para alertá-lo caso precise tomar alguma ação, podemos utilizar as chaves padrão ou criar nossas próprias. As flash messages são exibidas no HTML e podem ser estilizadas por meio do CSS, assim como qualquer outro elemento HTML. Vamos ver um exemplo de como isso pode ser feito?

Exemplificando

A fim de deixar a implementação dinâmica, primeiro colocaremos o código a seguir no application_helper.rb:

module ApplicationHelper
 def flash_message
   messages = ""
   [:notice, :info, :warning, :error].each {|type|
     if flash[type]
       messages += "<div class=\"base-alert #{type}\" role='alert'>#{flash[type]}</div>"
     end
   }
   messages.html_safe
 end
end

No código acima temos o método flash_message que percorre as possíveis chaves do objeto flash e, caso exista uma mensagem em determinada chave, ele cria um elemento HTML com o conteúdo da mensagem, além de adicionar uma classe CSS com o mesmo nome da chave encontrada.

No controller passamos a mensagem que desejamos para o objeto flash, já na view chamamos esse helper que criamos da seguinte forma: <%= flash_message %>. Quando chamado, o código verifica o objeto flash e se houver algum valor para uma das chaves, o HTML referente a essa chave é renderizado com a mensagem passada no flash. Ou seja, caso tenhamos o flash[:notice] = "Login efetuado com sucesso!", será renderizado: <div class="base-alert notice" role="alert">Login efetuado com sucesso!</div>

Como temos 4 possíveis chaves, irei passar diferentes textos para cada chave para vermos o resultado. Então ficaria assim:

flash[:notice] = "Login efetuado com sucesso!"
flash[:info] = "Você tem mensagens não visualizadas"
flash[:warning] = "País deve ser selecionado"
flash[:error] = "Não foi possível encontrar o imóvel"

Na nossa view, para cada tipo de flash passado, o resultado seria:

Como podemos ver, os textos ainda não estão estilizados, pois não criamos nenhuma classe CSS no nosso arquivo de CSS.

Criando as classes

No nosso helper adicionamos uma classe CSS em <div class=\"base-alert #{type}\" role='alert'>, onde estará contida a nossa mensagem, com o mesmo nome das possíveis chaves do objeto flash. Será a partir dessas classes que iremos estilizar o HTML com nosso CSS para ficar como desejamos. Como são 4 possíveis valores de chaves, teremos 4 classes CSS diferentes, uma para cada chave.

Criaremos as classes CSS no arquivo app/assets/stylesheets/application.scss. Além das 4 classes para cada valor de chave do flash message, teremos mais uma classe que será usada independente de qual for a mensagem. Chamaremos essa classe de .base-alert

.base-alert {
 position: relative;
 padding: 0.75rem 1.25rem;
 margin-bottom: 1rem;
 border: 1px solid transparent;
 border-radius: 0.25rem;
}

.notice {
 color: #18603a;
 background-color: #d5f1de;
 border-color: #c4ebd1;
}

.info {
 color: #1b508f;
 background-color: #d6ebff;
 border-color: #c6e2ff;
}

.error {
 color: #772b35;
 background-color: #fadddd;
 border-color: #f8cfcf;
}

.warning {
 color: #815c15;
 background-color: #feefd0;
 border-color: #fde9bd;
}

Após adicionar essas classes, a sua flash message já estará com um visual mais personalizado, como podemos ver abaixo:

Poderíamos deixar ainda melhor esse visual adicionando um ícone ao lado de cada texto

Adicionando ícones

Para adicionar um ícone ao lado da mensagem, primeiro é necessário fazer o download dos ícones desejados. Utilizei o Free Icons para essa finalidade e escolhi quatro ícones, um para cada mensagem.

Após escolher os ícones, adicione eles na pasta app/assets/images e altere o CSS da seguinte maneira:



.notice {
 color: #18603a;
 background: #d5f1de image_url('notice.png') no-repeat 5px center;
 border-color: #c4ebd1;
}

.info {
 color: #1b508f;
 background: #d6ebff image_url('info.png') no-repeat 5px center;
 border-color: #c6e2ff;
}

.error {
 color: #772b35;
 background: #fadddd image_url('error.png') no-repeat 5px center;
 border-color: #f8cfcf;
}

.warning {
 color: #815c15;
 background: #feefd0 image_url('warning.png') no-repeat 5px center;
 border-color: #fde9bd;
}

Agora você terá ícones ao lado das mensagens:

Para finalizar, que tal adicionarmos um pouco de movimento quando essa mensagem aparecer na tela?

Adicionando movimento

Para adicionar um efeito de slide (deslize) da direita pra esquerda, só é preciso alterar seu CSS para que fique assim:



body {
 overflow: hidden;
}

.base-alert {
 position: relative;
 padding: 0.75rem 2.3rem;
 margin-bottom: 1rem;
 border: 1px solid transparent;
 border-radius: 0.25rem;
 width: 20%;
 top: 15%;
 right: 0;
 transform: translateX(0%);
 position: absolute;
 animation: alert-box 5s forwards .5;
}

@keyframes alert-box {
 0% {
   transform: translateX(100%);
    opacity: 0;
 }
 25% {
   transform: translateX(-10%);
   opacity: 1;
 }

 50% {
   transform: translateX(0%);
 }
}

Neste código primeiramente posicionamos nossa div que contém o flash_message no canto direito utilizando o position:absolute e o right: 0. Então, criamos uma animação chamada alert-box e configuramos para inicialmente nossa div ficar fora da tela utilizando o transform: translateX(100%);. Ao longo da animação de 5 segundos, movemos a div da direita para a esquerda enquanto aumentamos a opacidade do estado inicial zero até o final 1. Vale lembrar que só é possível esconder a div dessa forma sem aparecer a barra de rolagem, porque colocamos no body a propriedade overflow: hidden

Então o resultado final será algo assim:

Utilizei como exemplo a flash message de sucesso, mas em todos o efeito será o mesmo.

Pronto! Passamos desde a criação dinâmica dessas mensagens, adicionamos estilo e ícones para ficar mais personalizado e, por fim, uma animaçãozinha para dar movimento ao visual.

Referências

Foto de perfil do autor
Rafael Aquino

Dev na Rebase