Created
July 27, 2021 04:11
-
-
Save cvkmohan/33056905768ec7834e772b72c738aa80 to your computer and use it in GitHub Desktop.
Rails Flash Messages using Tailwind, Stimulus and ViewComponents
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<% flash.each do |type, title| %> | |
<%= render FlashComponent.new(type: type, title: title) %> | |
<% end %> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@keyframes flash-countdown { | |
from { | |
width: 100%; | |
} | |
to { | |
width: 0; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class FlashComponent < ViewComponent::Base | |
def initialize(type:, title:) | |
super | |
@type = type | |
@title = title | |
@icon = icon.html_safe | |
@icon_color_class = icon_color_class | |
@icon_bg_class = icon_bg_class | |
@timeout ||= timeout | |
end | |
def icon | |
case @type | |
when 'notice' | |
'<path d="M20 3.33331C10.8 3.33331 3.33337 10.8 3.33337 20C3.33337 29.2 10.8 36.6666 20 36.6666C29.2 36.6666 | |
36.6667 29.2 36.6667 20C36.6667 10.8 29.2 3.33331 20 3.33331ZM16.6667 28.3333L8.33337 20L10.6834 17.65L16.6667 | |
23.6166L29.3167 10.9666L31.6667 13.3333L16.6667 28.3333Z"/>' | |
when 'error' | |
'<path d="M20 3.36667C10.8167 3.36667 3.3667 10.8167 3.3667 20C3.3667 29.1833 10.8167 36.6333 20 36.6333C29.1834 | |
36.6333 36.6334 29.1833 36.6334 20C36.6334 10.8167 29.1834 3.36667 20 3.36667ZM19.1334 | |
33.3333V22.9H13.3334L21.6667 6.66667V17.1H27.25L19.1334 33.3333Z"/>' | |
else | |
'<path d="M20 3.33331C10.8 3.33331 3.33337 10.8 3.33337 20C3.33337 29.2 10.8 36.6666 20 36.6666C29.2 36.6666 | |
36.6667 29.2 36.6667 20C36.6667 10.8 29.2 3.33331 20 3.33331ZM21.6667 28.3333H18.3334V25H21.6667V28.3333ZM21.6667 | |
21.6666H18.3334V11.6666H21.6667V21.6666Z"/>' | |
end | |
end | |
def timeout | |
case @type | |
when 'notice' | |
8 | |
else | |
15 | |
end | |
end | |
def icon_color_class | |
case @type | |
when 'notice' | |
'text-green-500 dark:text-green-400' | |
when 'error' | |
'text-red-500 dark:text-red-400' | |
else | |
'text-yellow-400 dark:text-yellow-300' | |
end | |
end | |
def icon_bg_class | |
case @type | |
when ('notice' || 'success') | |
'bg-green-500' | |
when 'error' | |
'bg-red-500' | |
else | |
'bg-yellow-400' | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div class="flex w-full max-w-sm mx-auto overflow-hidden bg-white rounded-lg shadow-md dark:bg-gray-800 pointer-events-auto hidden fixed top-10 lg:right-10 z-50 border mt-2" data-flash-timeout="<%= @timeout %>" data-controller="flash"> | |
<div class="flex items-center justify-center w-12 <%= @icon_bg_class %>"> | |
<svg class="w-6 h-6 text-white fill-current" viewBox="0 0 40 40" xmlns="http://www.w3.org/2000/svg"> | |
<%= @icon %> | |
</svg> | |
</div> | |
<div class="px-4 py-2 -mx-3"> | |
<div class="mx-3"> | |
<span class="font-semibold capitalize <%= @icon_color_class %>"> <%= @type %> </span> | |
<p class="text-sm text-gray-600 dark:text-gray-200"> <%= @title %> </p> | |
</div> | |
<div class="<%= @icon_bg_class %> rounded-lg h-1 w-0" data-flash-target="countdown"></div> | |
</div> | |
<div class="ml-auto flex-shrink-0 flex"> | |
<button class="inline-flex text-gray-400 focus:outline-none focus:text-gray-500 transition ease-in-out duration-150" data-action="flash#close" type="button"> | |
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | |
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" /> | |
</svg> | |
</button> | |
</div> | |
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Controller } from 'stimulus' | |
export default class extends Controller { | |
static targets = ['countdown']; | |
connect () { | |
const timeoutSeconds = parseInt(this.data.get('timeout')) | |
if (!this.isPreview) { | |
setTimeout(() => { | |
this.element.classList.remove('hidden') | |
this.element.classList.add( | |
'transform', | |
'ease-out', | |
'duration-300', | |
'transition', | |
'translate-y-2', | |
'opacity-0', | |
'sm:translate-y-0', | |
'sm:translate-x-2' | |
) | |
setTimeout(() => { | |
this.element.classList.add( | |
'translate-y-0', | |
'opacity-100', | |
'sm:translate-x-0' | |
) | |
}, 100) | |
if (this.hasCountdownTarget) { | |
this.countdownTarget.style.animation = | |
'flash-countdown linear ' + timeoutSeconds + 's' | |
} | |
}, 500) | |
this.timeoutId = setTimeout(() => { | |
this.close() | |
}, timeoutSeconds * 1000 + 500) | |
} | |
} | |
stop () { | |
clearTimeout(this.timeoutId) | |
this.timeoutId = null | |
} | |
close () { | |
this.element.classList.remove( | |
'transform', | |
'ease-out', | |
'duration-300', | |
'translate-y-2', | |
'opacity-0', | |
'sm:translate-y-0', | |
'sm:translate-x-2', | |
'translate-y-0', | |
'sm:translate-x-0' | |
) | |
this.element.classList.add('ease-in', 'duration-100') | |
setTimeout(() => { | |
this.element.classList.add('opacity-0') | |
}, 100) | |
setTimeout(() => { | |
this.element.remove() | |
}, 300) | |
} | |
get isPreview () { | |
return document.documentElement.hasAttribute('data-turbolinks-preview') | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment