Alert
Status messages with typed intent, title, description, and icon slots.
- Source
app/components/nitro_kit/alert.rb- API
NitroKit::Alert.new(variant:, title:, description:) { |alert| alert.title; alert.description }
Variants
Every semantic intent stays visible in data. live: defaults to :off, so these static alerts render without a live region role.
Intent matrix
test/dummy/app/components/gallery/components/alert_page.rbGallery::Data.alert_variants.each do |alert|
sample(alert.variant.to_s.humanize, slug: alert.slug) do
render_alert(alert)
end
endContent modes
Title, description, icon, and nested content are optional independent slots.
Slot combinations
test/dummy/app/components/gallery/components/alert_page.rbsample("Title only", slug: "title-only") do
render NitroKit::Alert.new(id: "gallery-alert-title-only") do |alert|
alert.title("Scheduled maintenance")
end
end
sample("Description only", slug: "description-only") do
render NitroKit::Alert.new(id: "gallery-alert-description-only") do |alert|
alert.description("New sign-ins require a recovery code for the next 24 hours.")
end
end
sample("Icon and title", slug: "icon-title") do
render NitroKit::Alert.new(id: "gallery-alert-icon-title", variant: :success) do |alert|
alert.icon(NitroKit::Icon.new(:circle_check, id: "gallery-alert-icon-title-icon"))
alert.title("All systems operational")
end
end
sample("Constructor text", slug: "constructor-text") do
render NitroKit::Alert.new(
id: "gallery-alert-constructor-text",
variant: :info,
title: "Scheduled maintenance",
description: "Deploys pause Thursday between 02:00 and 02:10 UTC."
)
end
sample("Nested status", slug: "nested-status") do
render NitroKit::Alert.new(id: "gallery-alert-nested-status") do |alert|
alert.title("Production release")
alert.description do
render NitroKit::Badge.new(
"Deploying",
id: "gallery-alert-deploying-badge",
color: :info,
size: :sm
)
end
end
endLive announcement
live: :polite renders role=status and live: :assertive renders role=alert, so alerts inserted by Turbo are announced; the :off default stays silent.
Live modes
test/dummy/app/components/gallery/components/alert_page.rbsample("Polite", slug: "polite") do
render NitroKit::Alert.new(
id: "gallery-alert-live-polite",
variant: :info,
live: :polite,
title: "Export ready",
description: "The workspace export finished and is ready to download."
)
end
sample("Assertive", slug: "assertive") do
render NitroKit::Alert.new(
id: "gallery-alert-live-assertive",
variant: :destructive,
live: :assertive,
title: "Connection lost",
description: "Changes stopped saving; check the network before continuing."
)
endLong content
Operational messages remain readable when product copy is specific and multi-line.
Detailed incident
test/dummy/app/components/gallery/components/alert_page.rbrender NitroKit::Alert.new(id: "gallery-alert-long", variant: :destructive) do |alert|
alert.icon(NitroKit::Icon.new(:circle_x, id: "gallery-alert-long-icon"))
alert.title("Production deployment could not complete after the database migration timed out")
alert.description do
"Existing traffic is still served by release 2026.07.12. Review the migration log, resolve the " \
"lock contention, and retry the deploy when the primary database is healthy."
end
endNotification composition
Card, Alert, Icon, Badge, AvatarStack, and Avatar compose into a realistic release notice.
Release notification
test/dummy/app/components/gallery/components/alert_page.rbrender NitroKit::Card.new(id: "gallery-alert-notification-card") do |card|
card.title("Release 2026.07.13", level: 3)
card.body do
render NitroKit::Alert.new(
id: "gallery-alert-notification-success",
variant: :success
) do |alert|
alert.icon(
NitroKit::Icon.new(:circle_check, id: "gallery-alert-notification-success-icon")
)
alert.title("Production deployment completed")
alert.description("The release is serving all workspaces in Europe and North America.")
end
end
card.footer do
render NitroKit::Badge.new(
"Production",
id: "gallery-alert-notification-badge",
color: :success,
size: :sm
)
render NitroKit::AvatarStack.new(
id: "gallery-alert-notification-reviewers",
size: :sm,
label: "Release reviewers"
) do |stack|
stack.avatar(alt: "Ada Lovelace", fallback: "AL", id: "gallery-alert-reviewer-ada")
stack.avatar(alt: "Grace Hopper", fallback: "GH", id: "gallery-alert-reviewer-grace")
stack.overflow(2)
end
end
endComponent contract
Constructor options, rendered root, closed vocabularies, and compound boundary for this component, exactly as shipped.
docs/component_contracts.md · NitroKit::Alert
- Constructor-specific options
variant: :default,title: nil,description: nil,live: :off,id: nil
- Root and closed vocabulary
div[data-nk=alert]; variantsdefault info success warning destructive, the same families asToast::Item, which spells its failure varianterror; live modesoff polite assertive- Compound contract
- One semantic axis:
variant:emitsdata-variantand drives the tint through the shared semantic palette, which resolves every family to the public--nk-palette-*tokens. An Alert and aToast::Itemof the same family render identically; Alert'sdestructiveand Toast'serrorresolve to the same tint family. There is nocolor:option. Accepts at most oneNitroKit::Iconthroughicon, plustitleanddescriptionthrough constructor text or the matching compound method, never both. Nitro renders icon, title, then description regardless of declaration order; declaring outside the render block raises.live: :politeaddsrole=status;live: :assertiveaddsrole=alert; static alerts have no live role by default.
Relevant patterns
Application conventions this component belongs to. Each summary is the leading section of its pattern document.
docs/patterns/flash_and_toast.md
Flash and toast
- Rails flash is the server-side feedback contract; render
NitroKit::Toast::FlashMessagesonce in the application layout. - Use redirect flash for navigation and
flash.nowwhen rendering the current request. - Toast items are Turbo-temporary so cached pages do not replay them; the region keeps a stable address for stream updates.
- Do not add a client-side notification store for server outcomes. render NitroKit::Toast::FlashMessages.new(flash: flash) yield
System rules for coding agents
Instructions for coding agents, repeated on every component page so one fetched page has enough context. Humans can usually skip this section.
test/dummy/app/components/gallery/agent_rules.rb
View agent instructions
- Nitro Kit 2.0 is a gem-owned, Phlex-only UI system for Rails. Render components directly:
render NitroKit::Button.new("Save", variant: :primary). - Compose Nitro components inside application-owned Phlex classes. Public initializers and declared slots are the component API; private methods are not.
- Public options are explicit keywords, and enumerated options are closed vocabularies. Invalid names or values raise
ArgumentError; this component's accepted options are in the contract above. - Pass native attributes through their typed boundary:
html:for HTML,aria:for ARIA, anddata:for application data.classandstyleare forbidden, including insidehtml:. - Nitro owns
NitroKit::Component::RESERVED_DATA_ATTRIBUTES:data-nk,data-slot,data-variant,data-size,data-nk-escape,data-enhanced,data-state,data-disabled,data-required,data-orientation,data-presentation,data-placement,data-layout,data-side,data-field-type,data-dir,data-gap,data-align,data-justify,data-wrap,data-cols,data-mode,data-key. Do not pass them throughdata:.data-action,data-controllerare additive and compose with Nitro behavior. - If an integration truly requires a class, use
desperately_need_a_class:. It requires a non-blank String and marks the exception withdata-nk-escape="class". - Every root emits
data-nk; owned parts emit component-qualifieddata-slotvalues such asfield-controlorcard-title. Select on those attributes, never on classes. - Customize components with documented
--nk-*custom properties in an application stylesheet. Variables beginning with--_nk-*are private component mechanics. - Use
NitroKit::FlexandNitroKit::Gridfor layout. Parents own external placement and available width; components own their intrinsic geometry. - Preserve native elements and accessibility semantics. State is exposed through native semantics and ARIA first, and through
data-statewhen styling or behavior also needs it.