Hinweismeldung
Eine Benachrichtigungskomponente zur Anzeige wichtiger Meldungen für Benutzer. Unterstützt Erfolgs-, Fehler-, Warn- und Infovarianten mit optionalen Icons und Schließen-Funktion.
Vorschau & Code
_alert.html.erb
<%#
Alert Component (Classic)
Usage:
<%= render "components/alert", message: "Success!" %>
<%= render "components/alert", message: "Something went wrong", variant: :error %>
<%= render "components/alert", message: "Please note...", variant: :info, dismissible: true %>
%>
<%
variant ||= :success
dismissible ||= false
icon ||= nil
additional_class ||= defined?(binding.local_variable_get(:class)) ? binding.local_variable_get(:class) : ""
base_classes = "flex items-start gap-3 p-4 rounded-lg text-sm shadow-sm"
variant_config = case variant.to_sym
when :success
{
classes: "bg-emerald-50 text-emerald-800 border border-emerald-200 dark:bg-emerald-900/30 dark:text-emerald-300 dark:border-emerald-800",
icon_color: "text-emerald-500 dark:text-emerald-400",
default_icon: '<svg class="w-5 h-5 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>'
}
when :error
{
classes: "bg-red-50 text-red-800 border border-red-200 dark:bg-red-900/30 dark:text-red-300 dark:border-red-800",
icon_color: "text-red-500 dark:text-red-400",
default_icon: '<svg class="w-5 h-5 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>'
}
when :warning
{
classes: "bg-amber-50 text-amber-800 border border-amber-200 dark:bg-amber-900/30 dark:text-amber-300 dark:border-amber-800",
icon_color: "text-amber-500 dark:text-amber-400",
default_icon: '<svg class="w-5 h-5 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" /></svg>'
}
when :info
{
classes: "bg-blue-50 text-blue-800 border border-blue-200 dark:bg-blue-900/30 dark:text-blue-300 dark:border-blue-800",
icon_color: "text-blue-500 dark:text-blue-400",
default_icon: '<svg class="w-5 h-5 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>'
}
else
{
classes: "bg-emerald-50 text-emerald-800 border border-emerald-200 dark:bg-emerald-900/30 dark:text-emerald-300 dark:border-emerald-800",
icon_color: "text-emerald-500 dark:text-emerald-400",
default_icon: '<svg class="w-5 h-5 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>'
}
end
all_classes = [base_classes, variant_config[:classes], additional_class].join(" ")
display_icon = icon || variant_config[:default_icon]
%>
<div class="<%= all_classes %>" <% if dismissible %>data-controller="alert"<% end %> role="alert">
<span class="<%= variant_config[:icon_color] %>">
<%= display_icon.html_safe %>
</span>
<div class="flex-1">
<%= message %>
</div>
<% if dismissible %>
<button type="button" data-action="alert#dismiss" class="shrink-0 p-1 rounded hover:bg-black/5 transition-colors cursor-pointer">
<svg class="w-4 h-4 opacity-50" 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>
<% end %>
</div>
alert_controller.js
import { Controller } from "@hotwired/stimulus"
// Handles dismissible alert functionality
export default class extends Controller {
dismiss() {
this.element.classList.add("opacity-0", "transition-opacity", "duration-300")
setTimeout(() => {
this.element.remove()
}, 300)
}
}
alert_component.rb
# frozen_string_literal: true
class AlertComponent < ViewComponent::Base
VARIANTS = %i[success error warning info].freeze
attr_reader :message, :variant, :dismissible, :icon
def initialize(message:, variant: :success, dismissible: false, icon: nil, **extra_classes)
@message = message
@variant = variant.to_sym
@dismissible = dismissible
@icon = icon
@extra_classes = extra_classes[:class] || ""
end
def alert_classes
[ base_classes, variant_classes, @extra_classes ].compact.join(" ")
end
def icon_classes
variant_config[:icon_color]
end
def display_icon
@icon || variant_config[:default_icon]
end
private
def base_classes
"flex items-start gap-3 p-4 rounded-lg text-sm shadow-sm"
end
def variant_classes
variant_config[:classes]
end
def variant_config
@variant_config ||= case @variant
when :success
{
classes: "bg-emerald-50 text-emerald-800 border border-emerald-200 dark:bg-emerald-900/30 dark:text-emerald-300 dark:border-emerald-800",
icon_color: "text-emerald-500 dark:text-emerald-400",
default_icon: '<svg class="w-5 h-5 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>'
}
when :error
{
classes: "bg-red-50 text-red-800 border border-red-200 dark:bg-red-900/30 dark:text-red-300 dark:border-red-800",
icon_color: "text-red-500 dark:text-red-400",
default_icon: '<svg class="w-5 h-5 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>'
}
when :warning
{
classes: "bg-amber-50 text-amber-800 border border-amber-200 dark:bg-amber-900/30 dark:text-amber-300 dark:border-amber-800",
icon_color: "text-amber-500 dark:text-amber-400",
default_icon: '<svg class="w-5 h-5 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" /></svg>'
}
when :info
{
classes: "bg-blue-50 text-blue-800 border border-blue-200 dark:bg-blue-900/30 dark:text-blue-300 dark:border-blue-800",
icon_color: "text-blue-500 dark:text-blue-400",
default_icon: '<svg class="w-5 h-5 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>'
}
else
{
classes: "bg-emerald-50 text-emerald-800 border border-emerald-200 dark:bg-emerald-900/30 dark:text-emerald-300 dark:border-emerald-800",
icon_color: "text-emerald-500 dark:text-emerald-400",
default_icon: '<svg class="w-5 h-5 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>'
}
end
end
end
alert_component.html.erb
<div class="<%= alert_classes %>" <% if @dismissible %>data-controller="alert"<% end %> role="alert">
<span class="<%= icon_classes %>">
<%= display_icon.html_safe %>
</span>
<div class="flex-1">
<%= @message %>
</div>
<% if @dismissible %>
<button type="button" data-action="alert#dismiss" class="shrink-0 p-1 rounded hover:bg-black/5 transition-colors cursor-pointer">
<svg class="w-4 h-4 opacity-50" 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>
<% end %>
</div>
alert_controller.js
import { Controller } from "@hotwired/stimulus"
// Handles dismissible alert functionality
export default class extends Controller {
dismiss() {
this.element.classList.add("opacity-0", "transition-opacity", "duration-300")
setTimeout(() => {
this.element.remove()
}, 300)
}
}
Änderungsprotokoll
- Initial release with success, error, warning, and info variants
- Optional dismiss button with Stimulus controller
- Icon support with default icons per variant
Gefällt dir diese kostenlose Komponente? Erhalte alle 78 Komponenten mit einer einmaligen Zahlung.
Alle Komponenten erhalten