mirror of
https://github.com/maybe-finance/maybe.git
synced 2025-07-19 13:19:39 +02:00
Add notification UI (#449)
* Add notification UI * Make animation an aribtrary value It didn't make much sense in the theme as it feels very specific, this change also means the timing information is clearer within the html itself. * Update to use tailwind theme * Refactor structure of icon * Add support for multiple notifications at once * Adjust notification animation timing * Make notification more accessible Applies role to the notification which will apply the appropriate aria-live status to ensure notifications are read out when they are rendered into the screen for screenreader users. Wraps the svg with a button tag that keyboard users can focus and engage with to close the notification. * Fix notification progress indicator placement * Map flash types to notification types automatically * Refine notification animations * Set success as default icon for notifications
This commit is contained in:
parent
bbe7323ca4
commit
101a5ee0c5
5 changed files with 51 additions and 0 deletions
|
@ -11,6 +11,13 @@ module ApplicationHelper
|
|||
name.underscore
|
||||
end
|
||||
|
||||
def notification(text, **options, &block)
|
||||
content = tag.p(text)
|
||||
content = capture &block if block_given?
|
||||
|
||||
render partial: "shared/notification", locals: { type: options[:type], content: content }
|
||||
end
|
||||
|
||||
# Wrap view with <%= modal do %> ... <% end %> to have it open in a modal
|
||||
# Make sure to add data-turbo-frame="modal" to the link/button that opens the modal
|
||||
def modal(&block)
|
||||
|
|
9
app/javascript/controllers/element_removal_controller.js
Normal file
9
app/javascript/controllers/element_removal_controller.js
Normal file
|
@ -0,0 +1,9 @@
|
|||
import { Controller } from '@hotwired/stimulus'
|
||||
|
||||
// Connects to data-controller="element-removal"
|
||||
export default class extends Controller {
|
||||
remove() {
|
||||
this.element.remove()
|
||||
}
|
||||
}
|
||||
|
|
@ -24,6 +24,9 @@
|
|||
</head>
|
||||
|
||||
<body class="h-full">
|
||||
<div id="notification-tray" class="fixed top-6 right-6 space-y-1 z-50"></div>
|
||||
<%= safe_join(flash.map { |type, message| notification(message, type: type) }) %>
|
||||
|
||||
<div class="flex">
|
||||
<div class="flex-col p-5 min-w-80">
|
||||
<div class="flex items-center justify-between">
|
||||
|
|
23
app/views/shared/_notification.html.erb
Normal file
23
app/views/shared/_notification.html.erb
Normal file
|
@ -0,0 +1,23 @@
|
|||
<%# locals: (type: "success", content:) -%>
|
||||
|
||||
<turbo-stream action="append" target="notification-tray">
|
||||
<template>
|
||||
<div
|
||||
class="max-w-80 bg-white shadow-xs border border-alpha-black-50 border-solid py-3 px-4 rounded-[10px] text-sm font-medium flex gap-3 animate-[appear-then-fade_5s_300ms_both]"
|
||||
role="<%= type == "error" ? "alert" : "status" %>"
|
||||
data-controller="element-removal"
|
||||
data-action="click->element-removal#remove animationend->element-removal#remove">
|
||||
<% base_class = "w-5 h-5 p-1 text-white flex shrink-0 items-center justify-center rounded-full" %>
|
||||
<%= type.in?(["error", "alert"]) ? lucide_icon("x", class: "#{base_class} bg-error") : lucide_icon("check", class: "#{base_class} bg-success") %>
|
||||
|
||||
<%= content %>
|
||||
|
||||
<button aria-label="Close notification" data-action="click->element-removal#remove" class="shrink-0 h-5">
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg" class="shrink-0">
|
||||
<path d="M18 10C18 14.4183 14.4183 18 10 18C5.58172 18 2 14.4183 2 10C2 5.58172 5.58172 2 10 2C14.4183 2 18 5.58172 18 10ZM3.6 10C3.6 13.5346 6.46538 16.4 10 16.4C13.5346 16.4 16.4 13.5346 16.4 10C16.4 6.46538 13.5346 3.6 10 3.6C6.46538 3.6 3.6 6.46538 3.6 10Z" fill="#E5E5E5" />
|
||||
<circle class="origin-center -rotate-90 animate-[stroke-fill_5s_300ms_forwards]" stroke="#141414" stroke-opacity="0.4" r="7.2" cx="10" cy="10" stroke-dasharray="43.9822971503" stroke-dashoffset="43.9822971503" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
</turbo-stream>
|
|
@ -204,6 +204,15 @@ module.exports = {
|
|||
fontSize: {
|
||||
"2xs": ".625rem",
|
||||
},
|
||||
keyframes: {
|
||||
'appear-then-fade': {
|
||||
'0%,100%': { opacity: 0 },
|
||||
'5%,90%': { opacity: 1 },
|
||||
},
|
||||
'stroke-fill': {
|
||||
to: { 'stroke-dashoffset': 0 },
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue