Skip to content

Instantly share code, notes, and snippets.

@secretpray
Last active December 18, 2022 08:29
Show Gist options
  • Save secretpray/0996ba7298286a05b6f1ba49b3644e7d to your computer and use it in GitHub Desktop.
Save secretpray/0996ba7298286a05b6f1ba49b3644e7d to your computer and use it in GitHub Desktop.
Flash like tailwind with Stimulus (Rails 7)
app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
  <head>
    <title>Turboapp</title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>
    <link rel="stylesheet" href="https://cdn.simplecss.org/simple.min.css">
    <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
    <%= javascript_importmap_tags %>
  </head>

  <body>
    <div id='notifications'>
      <%= render 'shared/flash' %>
    </div>

    <%= yield %>
  </body>
</html>

app/views/shared/_flash.html.erb
<div id="flash">
  <% flash.each do |type, message| %>
    <div class="flash-overlay fixed inset-x-0 top-0 flex items-end justify-right px-4 py-5 sm:p-5 justify-end z-30 pointer-events-none">
      <div
          data-controller="alert"
          data-alert-show-class="translate-x-0 opacity-100 bg-lemonchiffon"
          data-alert-hide-class="translate-x-full opacity-0 bg-transparent"
          class="flash-section max-w-sm w-full shadow-lg px-4 py-2 rounded relative bg-transparent border-l-8 border-sky-400 border-opacity-90 text-gray-600 pointer-events-auto transition translate-x-full transform ease-in-out duration-1000 opacity-0">
        <div class="flash-section-one p-2">
          <div class="flash-section-two flex items-start">
            <div class="flash-section-three ml-3 w-0 flex-1 pt-0.5">
              <p class="flash-section-four text-sm leading-5 font-medium">
                <%= content_tag :div, message %>
              </p>
            </div>
            <div class="flash-button-section ml-4 flex-shrink-0 flex">
              <button data-action="alert#close" class="close-flash inline-flex text-gray-600 focus:outline-none focus:text-gray-300">
                <svg class="svg-close h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
                  <path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"/>
                </svg>
              </button>
            </div>
          </div>
        </div>
      </div>
    </div>
  <% end %>
</div>

app/assets/stylesheets/application.css
.flash-overlay {
  position: fixed;
  display: flex;
  align-items: flex-end;
  justify-content: flex-end;
  left: 0px;
  right: 0px;
  top: 0px;
  padding-left: 1rem;
  padding-right: 1rem;
  z-index: 30;
}

.flash-section {
  position: relative;
  border-left-width: 8px;
  border-color: rgb(245, 158, 11);
  color: rgb(75, 85, 99);
  max-width: 24rem;
  width: 100%;
  padding-left: 1rem;
  padding-right: 1rem;
  padding-top: 0.5rem;
  padding-bottom: 0.5rem;
  border-radius: 8px;
  box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px,
              rgba(0, 0, 0, 0) 0px 0px 0px 0px,
              rgba(0, 0, 0, 0.1) 0px 10px 15px -3px,
              rgba(0, 0, 0, 0.1) 0px 4px 6px -4px;
}

.flash-section-one {
  padding: 0.5rem;
}

.flash-section-two {
  display: flex;
  align-items: flex-start;
}

.flash-section-three {
  flex: 1 1 0%;
  margin-left: 0.75rem;
  width: 0px;
  padding-top: 0.125rem;

}

.flash-section-four {
  font-size: 0.875rem;
  line-height: 1.25rem;
  font-weight: 500;
}

.flash-button-section {
  display: flex;
  flex-shrink: 0;
  margin-left: 1rem;
}

.close-flash {
  display: inline-flex;
  color: rgb(75, 85, 99);
  background-color: transparent;
}

.close-flash:focus {
  color: rgb(209, 213, 219)
  outline: 2px solid transparent;
  outline-offset: 2px;
}

.svg-close {
  height: 1.25rem;
  width: 1.25rem;
}


.translate-x-full {
  -webkit-transform: translateX(100%);
          transform: translateX(100%);
}

.-translate-x-full {
  -webkit-transform: translateX(-100%);
          transform: translateX(-100%);
}

.translate-x-0 {
  -webkit-transform: translateX(0);
          transform: translateX(0);
}

.opacity-100 {
  opacity: 1;
}
.opacity-0 {
  opacity: 0;
}

.bg-white {
  background-color: white;
}

.bg-transparent {
  background-color: transparent;
}

.duration-1000 {
  transition-duration: 1000ms;
}

.ease-in-out {
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}

.pointer-events-none {
  pointer-events: none;
}

.pointer-events-auto {
  pointer-events: auto;
}

.bg-lemonchiffon {
  background-color: lemonchiffon;
}
  1. [./bin/rails g stimulus alert] app/javascript/controllers/alert_controller.js =============================================
import { Controller } from '@hotwired/stimulus'

export default class extends Controller {
  static values = {
    dismissAfter: Number,
    showDelay: Number,
    removeDelay: Number

  }
  static classes = ["show", "hide"]

  initialize() {
    this.hide()
  }

  connect() {
    setTimeout(() => {
      this.show()
    }, this.showAfter)

    // Auto dimiss if defined
    if (this.hasDismissAfterValue || true) {
      setTimeout(() => {
        this.close()
      // }, this.dismissAfterValue)
      }, 7000)
    }
  }

  close() {
    this.hide()

    setTimeout(() => {
      this.element.remove()
    }, this.removeAfter)
  }

  show() {
    this.element.classList.add(...this.showClasses)
    this.element.classList.remove(...this.hideClasses)
  }

  hide() {
    this.element.classList.add(...this.hideClasses)
    this.element.classList.remove(...this.showClasses)
  }

  get removeAfter() {
    if (this.hasRemoveDelayValue) {
      return this.removeDelayValue
    } else {
      return 5000
    }
  }

  get showAfter() {
    if (this.hasShowDelayValue) {
      return this.showDelayValue
    } else {
      return 200
    }
  }
}
@secretpray
Copy link
Author

flash = ActionDispatch::Flash::FlashHash.new
turbo_stream.update 'service-frame', partial: "shared/flash", locals: { flash: flash }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment