mirror of
https://github.com/System-End/hackatime.git
synced 2026-04-19 19:55:16 +00:00
Fix toasts
This commit is contained in:
parent
a897fcb7c0
commit
ed75919d75
8 changed files with 130 additions and 11 deletions
|
|
@ -87,6 +87,55 @@ select {
|
|||
border-color: var(--color-green);
|
||||
}
|
||||
|
||||
.flash-message {
|
||||
@apply rounded-md text-center text-sm border px-4 py-3;
|
||||
will-change: opacity, transform;
|
||||
}
|
||||
|
||||
.flash-message--success {
|
||||
color: var(--color-success);
|
||||
border-color: var(--color-success);
|
||||
background-color: rgba(51, 214, 166, 0.2);
|
||||
background-color: color-mix(in oklab, var(--color-success) 20%, transparent);
|
||||
}
|
||||
|
||||
.flash-message--error {
|
||||
color: var(--color-danger);
|
||||
border-color: var(--color-danger);
|
||||
background-color: rgba(200, 57, 79, 0.2);
|
||||
background-color: color-mix(in oklab, var(--color-danger) 20%, transparent);
|
||||
}
|
||||
|
||||
.flash-message--enter {
|
||||
animation: flash-enter 180ms ease-out;
|
||||
}
|
||||
|
||||
.flash-message--leaving {
|
||||
animation: flash-exit 240ms ease-in forwards;
|
||||
}
|
||||
|
||||
@keyframes flash-enter {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-4px) scale(0.98);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0) scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes flash-exit {
|
||||
from {
|
||||
opacity: 1;
|
||||
transform: translateY(0) scale(1);
|
||||
}
|
||||
to {
|
||||
opacity: 0;
|
||||
transform: translateY(-6px) scale(0.98);
|
||||
}
|
||||
}
|
||||
|
||||
.loading {
|
||||
@apply grayscale;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,11 +38,20 @@ class InertiaController < ApplicationController
|
|||
flash.to_hash.map do |type, message|
|
||||
{
|
||||
message: message.to_s,
|
||||
class_name: type.to_sym == :notice ? "border-green text-green" : "border-primary text-primary"
|
||||
class_name: flash_class_for(type)
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def flash_class_for(type)
|
||||
case type.to_sym
|
||||
when :notice, :success
|
||||
"flash-message--success"
|
||||
else
|
||||
"flash-message--error"
|
||||
end
|
||||
end
|
||||
|
||||
def inertia_primary_links
|
||||
links = []
|
||||
links << inertia_link("Home", root_path, active: helpers.current_page?(root_path))
|
||||
|
|
|
|||
26
app/javascript/controllers/flash_controller.js
Normal file
26
app/javascript/controllers/flash_controller.js
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
import { Controller } from "@hotwired/stimulus"
|
||||
|
||||
export default class extends Controller {
|
||||
static values = { timeout: Number, exitDuration: Number }
|
||||
|
||||
connect() {
|
||||
const timeout = this.hasTimeoutValue ? this.timeoutValue : 6000
|
||||
this.exitDuration = this.hasExitDurationValue ? this.exitDurationValue : 250
|
||||
this.element.classList.add("flash-message--enter")
|
||||
this.hideTimeoutId = setTimeout(() => this.dismiss(), timeout)
|
||||
}
|
||||
|
||||
disconnect() {
|
||||
if (this.hideTimeoutId) clearTimeout(this.hideTimeoutId)
|
||||
if (this.removeTimeoutId) clearTimeout(this.removeTimeoutId)
|
||||
}
|
||||
|
||||
dismiss() {
|
||||
if (this.leaving) return
|
||||
this.leaving = true
|
||||
this.element.classList.add("flash-message--leaving")
|
||||
this.removeTimeoutId = setTimeout(() => {
|
||||
this.element.remove()
|
||||
}, this.exitDuration)
|
||||
}
|
||||
}
|
||||
|
|
@ -72,6 +72,10 @@
|
|||
let navOpen = $state(false);
|
||||
let logoutOpen = $state(false);
|
||||
let currentlyExpanded = $state(false);
|
||||
let flashVisible = $state(layout.nav.flash.length > 0);
|
||||
let flashHiding = $state(false);
|
||||
const flashHideDelay = 6000;
|
||||
const flashExitDuration = 250;
|
||||
|
||||
const toggleNav = () => (navOpen = !navOpen);
|
||||
const closeNav = () => (navOpen = false);
|
||||
|
|
@ -116,6 +120,30 @@
|
|||
if (isBrowser) document.body.classList.toggle("overflow-hidden", navOpen);
|
||||
});
|
||||
|
||||
$effect(() => {
|
||||
if (!layout.nav.flash.length) {
|
||||
flashVisible = false;
|
||||
flashHiding = false;
|
||||
return;
|
||||
}
|
||||
|
||||
flashVisible = true;
|
||||
flashHiding = false;
|
||||
let removeTimeoutId: ReturnType<typeof setTimeout> | undefined;
|
||||
const hideTimeoutId = setTimeout(() => {
|
||||
flashHiding = true;
|
||||
removeTimeoutId = setTimeout(() => {
|
||||
flashVisible = false;
|
||||
flashHiding = false;
|
||||
}, flashExitDuration);
|
||||
}, flashHideDelay);
|
||||
|
||||
return () => {
|
||||
clearTimeout(hideTimeoutId);
|
||||
if (removeTimeoutId) clearTimeout(removeTimeoutId);
|
||||
};
|
||||
});
|
||||
|
||||
onMount(() => {
|
||||
if (!isBrowser) return;
|
||||
handleResize();
|
||||
|
|
@ -134,13 +162,13 @@
|
|||
`block px-3 py-2 rounded-md text-sm transition-colors ${active ? "bg-primary text-white" : "hover:bg-darkless"}`;
|
||||
</script>
|
||||
|
||||
{#if layout.nav.flash.length > 0}
|
||||
{#if flashVisible && layout.nav.flash.length > 0}
|
||||
<div
|
||||
class="fixed top-4 left-1/2 transform -translate-x-1/2 z-50 w-full max-w-md px-4 space-y-2"
|
||||
>
|
||||
{#each layout.nav.flash as item}
|
||||
<div
|
||||
class={`rounded-md text-center text-sm px-4 py-3 shadow-lg ${item.class_name}`}
|
||||
class={`flash-message shadow-lg flash-message--enter ${flashHiding ? "flash-message--leaving" : ""} ${item.class_name}`}
|
||||
>
|
||||
{item.message}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -25,13 +25,13 @@
|
|||
|
||||
<main class="flex-1 lg:ml-[250px] lg:max-w-[calc(100%-250px)] p-5 mb-[100px] pt-16 lg:pt-5 transition-all duration-300 ease-in-out">
|
||||
<%- if flash[:notice].present? %>
|
||||
<div class="mb-6 p-4 bg-green-500/10 border border-green-500/20 rounded-lg text-green-400">
|
||||
<div class="flash-message flash-message--enter flash-message--success mb-6" data-controller="flash">
|
||||
<%= flash[:notice] %>
|
||||
</div>
|
||||
<% end -%>
|
||||
|
||||
<%- if flash[:alert].present? %>
|
||||
<div class="mb-6 p-4 bg-red-500/10 border border-red-500/20 rounded-lg text-red-400">
|
||||
<div class="flash-message flash-message--enter flash-message--error mb-6" data-controller="flash">
|
||||
<%= flash[:alert] %>
|
||||
</div>
|
||||
<% end -%>
|
||||
|
|
|
|||
|
|
@ -8,15 +8,22 @@
|
|||
|
||||
<%= stylesheet_link_tag 'tailwind', 'data-turbo-track': 'reload' %>
|
||||
<%= csrf_meta_tags %>
|
||||
<%= javascript_importmap_tags %>
|
||||
</head>
|
||||
<body class="min-h-screen bg-darker text-white" style="margin: 0; padding: 0; display: flex; align-items: center; justify-content: center;">
|
||||
<main class="w-full max-w-md px-5 py-8">
|
||||
<%- if flash[:notice].present? %>
|
||||
<div class="mb-6 p-4 bg-green-500/10 border border-green-500/20 rounded-lg text-green-400">
|
||||
<div class="flash-message flash-message--enter flash-message--success mb-6" data-controller="flash">
|
||||
<%= flash[:notice] %>
|
||||
</div>
|
||||
<% end -%>
|
||||
|
||||
<%- if flash[:alert].present? %>
|
||||
<div class="flash-message flash-message--enter flash-message--error mb-6" data-controller="flash">
|
||||
<%= flash[:alert] %>
|
||||
</div>
|
||||
<% end -%>
|
||||
|
||||
<%= yield %>
|
||||
</main>
|
||||
</body>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
<p class="text-gray-400 mb-6">We try to autodetect your Git repository, but you can manually specify it if needed.</p>
|
||||
|
||||
<% if flash[:alert] %>
|
||||
<div class="bg-red-900/50 border border-red-500 text-red-300 px-4 py-3 rounded-lg mb-4">
|
||||
<div class="flash-message flash-message--enter flash-message--error mb-4" data-controller="flash">
|
||||
<%= flash[:alert] %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
|
|
|||
|
|
@ -4,13 +4,13 @@
|
|||
<%
|
||||
c =
|
||||
case name.to_sym
|
||||
when :notice
|
||||
'border-green text-green'
|
||||
when :notice, :success
|
||||
'flash-message--success'
|
||||
else
|
||||
'border-primary text-primary'
|
||||
'flash-message--error'
|
||||
end
|
||||
%>
|
||||
<div class="rounded-md text-center text-sm px-3 py-2 <%= c %>"><%= msg %></div>
|
||||
<div class="flash-message flash-message--enter <%= c %>" data-controller="flash"><%= msg %></div>
|
||||
<% end %>
|
||||
|
||||
<% if current_user %>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue