Skip to content
Nitro Kitv2.0.0.alpha.4

Search gallery…

IntroductionGalleryAgent guideGalleryHuman guideGalleryColorsFoundations · ThemeTypographyFoundations · ThemeSpacing & sizingFoundations · ThemeEffectsFoundations · ThemeButtonComponents · ActionsButton groupComponents · ActionsButton toComponents · ActionsAppearance pickerComponents · FormsCheckboxComponents · FormsCheckbox groupComponents · FormsComboboxComponents · FormsControl groupComponents · FormsDropzoneComponents · FormsFieldComponents · FormsField groupComponents · FormsFieldsetComponents · FormsInputComponents · FormsLabelComponents · FormsRadio buttonComponents · FormsRadio button groupComponents · FormsRich text areaComponents · FormsSelectComponents · FormsSwitchComponents · FormsTextareaComponents · FormsCommand paletteComponents · OverlaysDialogComponents · OverlaysDropdownComponents · OverlaysSheetComponents · OverlaysTooltipComponents · OverlaysAlertComponents · FeedbackEmpty stateComponents · FeedbackToastComponents · FeedbackAccordionComponents · Data displayAvatarComponents · Data displayAvatar stackComponents · Data displayBadgeComponents · Data displayDetails tableComponents · Data displayIconComponents · Data displayProgressive imageComponents · Data displayStat gridComponents · Data displayTableComponents · Data displayTypesetComponents · Data displayPaginationComponents · NavigationPagination barComponents · NavigationTabsComponents · NavigationToolbarComponents · NavigationCardComponents · LayoutContainerComponents · LayoutFlexComponents · LayoutGridComponents · LayoutApplication navigationComponents · ApplicationApplication shellComponents · ApplicationAuthentication shellComponents · ApplicationDanger zoneComponents · ApplicationData sectionComponents · ApplicationForm sectionComponents · ApplicationPage headerComponents · ApplicationSettings layoutComponents · ApplicationSign inCompositions · Access & onboardingPassword resetCompositions · Access & onboardingEmail verificationCompositions · Access & onboardingInvitation acceptanceCompositions · Access & onboardingAccount creationCompositions · Access & onboardingAccount securityCompositions · Access & onboardingWorkspace onboardingCompositions · Access & onboardingBranched onboardingCompositions · Access & onboardingWorkspace dashboardCompositions · Workspace & organizationWorkspace settingsCompositions · Workspace & organizationWorkspace usersCompositions · Workspace & organizationTeam managementCompositions · Workspace & organizationAPI credentialsCompositions · Workspace & organizationOrganization overviewCompositions · Workspace & organizationOrganization settingsCompositions · Workspace & organizationTeam activityCompositions · Workspace & organizationTeam memberCompositions · Workspace & organizationSubscription billingCompositions · Billing & commerceCheckout and paymentCompositions · Billing & commerceCheckout resultsCompositions · Billing & commerceData resource overviewCompositions · Data & operationsData resource activityCompositions · Data & operationsData resource settingsCompositions · Data & operationsProduct resource lifecycleCompositions · Data & operationsAPI webhooksCompositions · Data & operationsIntegration managementCompositions · Data & operationsFile uploadsCompositions · Data & operationsActivity and audit logCompositions · Data & operationsChangelogCompositions · Product & supportHelp centerCompositions · Product & supportSystem status and errorsCompositions · Product & supportProduct landingCompositions · MarketingPublic pricingCompositions · MarketingProduct featuresCompositions · MarketingPublic contactCompositions · MarketingSidebar operations applicationCompositions · Complete applicationsTopbar media applicationCompositions · Complete applicationsHybrid account applicationCompositions · Complete applications

No destinations found.

  • Introduction
  • Agent guide
  • Human guide
  • Foundations
    • Colors
    • Typography
    • Spacing & sizing
    • Effects
  • Actions
    • Button
    • Button group
    • Button to
  • Forms
    • Appearance picker
    • Checkbox
    • Checkbox group
    • Combobox
    • Control group
    • Dropzone
    • Field
    • Field group
    • Fieldset
    • Input
    • Label
    • Radio button
    • Radio button group
    • Rich text area
    • Select
    • Switch
    • Textarea
  • Overlays
    • Command palette
    • Dialog
    • Dropdown
    • Sheet
    • Tooltip
  • Feedback
    • Alert
    • Empty state
    • Toast
  • Data display
    • Accordion
    • Avatar
    • Avatar stack
    • Badge
    • Details table
    • Icon
    • Progressive image
    • Stat grid
    • Table
    • Typeset
  • Navigation
    • Pagination
    • Pagination bar
    • Tabs
    • Toolbar
  • Layout
    • Card
    • Container
    • Flex
    • Grid
  • Application
    • Application navigation
    • Application shell
    • Authentication shell
    • Danger zone
    • Data section
    • Form section
    • Page header
    • Settings layout
  • Access & onboarding
    • Sign in
    • Password reset
    • Email verification
    • Invitation acceptance
    • Account creation
    • Account security
    • Workspace onboarding
    • Branched onboarding
  • Workspace & organization
    • Workspace dashboard
    • Workspace settings
    • Workspace users
    • Team management
    • API credentials
    • Organization overview
    • Organization settings
    • Team activity
    • Team member
  • Billing & commerce
    • Subscription billing
    • Checkout and payment
    • Checkout results
  • Data & operations
    • Data resource overview
    • Data resource activity
    • Data resource settings
    • Product resource lifecycle
    • API webhooks
    • Integration management
    • File uploads
    • Activity and audit log
  • Product & support
    • Changelog
    • Help center
    • System status and errors
  • Marketing
    • Product landing
    • Public pricing
    • Product features
    • Public contact
  • Complete applications
    • Sidebar operations application
    • Topbar media application
    • Hybrid account application

Toast

Explicit notification markup, Rails flash mapping, and pauseable dismissal behavior.

Source
app/components/nitro_kit/toast.rb
API
NitroKit::Toast.new(id:, duration:) { |toast| toast.item(id:) }

Variants

Every notification intent renders as explicit server-owned markup. The list is addressable as <toast id>-list so Turbo Streams can append items.

Intent stack

Replay dismissed notifications
  1. Default

    Workspace preferences were updated.
  2. Info

    A new release is ready for verification.
  3. Success

    The production deployment completed.
  4. Warning

    The payment method expires next month.
  5. Error

    The deployment stopped during migration.
ViewportFull width
Rubytest/dummy/app/components/gallery/components/toast_page.rb
turbo_frame_tag("gallery-toast-variants-frame") do
  render NitroKit::Button.new(
    "Replay dismissed notifications",
    id: "gallery-toast-variants-replay",
    href: "/gallery/components/toast",
    size: :sm
  )
  render NitroKit::Toast.new(
    duration: 600_000,
    label: "Variant examples",
    id: "gallery-toast-variants"
  ) do |toast|
    NitroKit::Toast::Item::VARIANTS.each do |variant|
      toast.item(
        title: variant.to_s.humanize,
        description: toast_description(variant),
        variant:
      )
    end
  end
end

Content and dismissal

Title, description, block content, permanent notices, and long messages are independent.

Content combinations

Title only
  1. Workspace saved

Permanent
  1. A workspace owner must acknowledge this billing change.
Timed pause
Replay
  1. Focus keeps this notification visible

Block content
  1. Deployment details

    Release 2026.07.13 is healthy in fra1 and iad1.

    Production
Long error
  1. The production deployment could not be promoted

    The release remains healthy in staging, but the primary database rejected the migration lock. Review the deployment log before retrying.
Viewport640 px · sm
Rubytest/dummy/app/components/gallery/components/toast_page.rb
sample("Title only", slug: "title-only") do
  render NitroKit::Toast.new(
    duration: 600_000,
    label: "Title only notification",
    id: "gallery-toast-title-only"
  ) do |toast|
    toast.item(title: "Workspace saved", id: "gallery-toast-workspace-saved")
  end
end
sample("Permanent", slug: "permanent") do
  render NitroKit::Toast.new(
    label: "Permanent notification",
    id: "gallery-toast-permanent"
  ) do |toast|
    toast.item(
      description: "A workspace owner must acknowledge this billing change.",
      variant: :warning,
      dismissible: false
    )
  end
end
sample("Timed pause", slug: "timed-pause") do
  turbo_frame_tag("gallery-toast-timed-frame") do
    render NitroKit::Button.new(
      "Replay",
      id: "gallery-toast-timed-replay",
      href: "/gallery/components/toast",
      size: :sm
    )
    render NitroKit::Toast.new(
      duration: 1_200,
      label: "Timed notification",
      id: "gallery-toast-timed"
    ) do |toast|
      toast.item(title: "Focus keeps this notification visible")
    end
  end
end
sample("Block content", slug: "block") do
  render NitroKit::Toast.new(
    duration: 600_000,
    label: "Block notification",
    id: "gallery-toast-block"
  ) do |toast|
    toast.item(title: "Deployment details", variant: :info) do
      p { "Release 2026.07.13 is healthy in fra1 and iad1." }
      render NitroKit::Badge.new(
        "Production",
        id: "gallery-toast-environment",
        color: :success,
        size: :sm
      )
    end
  end
end
sample("Long error", slug: "long-error") do
  render NitroKit::Toast.new(
    duration: 600_000,
    label: "Long error notification",
    id: "gallery-toast-long"
  ) do |toast|
    toast.item(
      title: "The production deployment could not be promoted",
      description: "The release remains healthy in staging, but the primary database rejected the migration lock. Review the deployment log before retrying.",
      variant: :error
    )
  end
end

Rails flash

Flash rendering receives explicit data and never reaches through a template context.

Flash severity mapping

  1. Welcome back, Ada.
  2. Production settings were saved.
  3. The payment method expires next month.
  4. Your session expired; sign in again.
Viewport640 px · sm
Rubytest/dummy/app/components/gallery/components/toast_page.rb
render NitroKit::Toast::FlashMessages.new(
  flash: {
    notice: "Welcome back, Ada.",
    success: "Production settings were saved.",
    warning: "The payment method expires next month.",
    alert: "Your session expired; sign in again."
  },
  duration: 600_000,
  label: "Rails flash messages",
  id: "gallery-toast-flash"
)

Controller to screen

Rails flash is the whole feedback contract. Render NitroKit::Toast::FlashMessages once in the application layout, set ordinary flash in the controller, and never add a client-side notification store for a server outcome.

Flash lifecycle

A successful action redirects with status: :see_other (303) and flash[:success], which Turbo follows so the message renders on the next page. A failed action never redirects: it sets flash.now and re-renders with status: :unprocessable_entity (422), which Turbo renders in place. Severity keys map notice to the default presentation, alert and error to error, and success, warning, and info to their matching variants; an unknown key falls back to the default presentation.

  1. Project created

    Rendered from flash[:success] after a 303 redirect.
  2. Payment method was declined

    Rendered from flash.now[:alert] with the 422 re-render of the form.
Viewport640 px · sm
Rubytest/dummy/app/components/gallery/components/toast_page.rb
render NitroKit::Toast::FlashMessages.new(flash: flash, duration: 5_000)

# app/controllers/projects_controller.rb#create, when the record saves.
# 303 so Turbo follows the redirect after a non-GET request; the flash
# survives it and renders on the next page.
redirect_to(@project, status: :see_other, flash: { success: "Project created" })

# The same action, when validation fails. No redirect, so flash.now, and
# 422 so Turbo renders the response in place instead of ignoring it.
flash.now[:alert] = "Project could not be created"
render(UI::Projects::New.new(@project), status: :unprocessable_entity)

# A Turbo Stream that neither redirects nor re-renders appends to the
# region's list, addressable as the toast id plus "-list".
turbo_stream.append("nk-toast-list") do
  render NitroKit::Toast::Item.new(title: "Import finished", variant: :success)
end

Region and announcement

The region is section[data-nk=toast] with role=region and the label passed as label:. Each notification is li[data-nk=toast-item] with aria-atomic=true and role=status, except the error variant, which uses role=alert so assistive technology interrupts. Every item is data-turbo-temporary so a cached page never replays old feedback, while the region survives and its ol stays addressable as the toast id plus "-list" for a Turbo Stream append. duration: is the auto-dismiss timer in milliseconds; it pauses on hover and focus, and dismissible: false keeps a notice on screen until the person dismisses the page.

  1. Polite status

    role=status waits for a pause in speech.
  2. Assertive alert

    role=alert interrupts, so it is reserved for the error variant.
Viewport640 px · sm
Rubytest/dummy/app/components/gallery/components/toast_page.rb
render NitroKit::Toast.new(
  duration: 600_000,
  label: "Announcement examples",
  id: "gallery-toast-announcement"
) do |toast|
  toast.item(
    title: "Polite status",
    description: "role=status waits for a pause in speech.",
    variant: :success
  )
  toast.item(
    title: "Assertive alert",
    description: "role=alert interrupts, so it is reserved for the error variant.",
    variant: :error
  )
end

Action result composition

A realistic settings result keeps source data, action controls, and notifications explicit.

Saved integration

Slack integration

Connected

Deployment notifications post to #operations.

Configure
  1. Slack settings saved

    New deployment notifications will use #operations.
Viewport640 px · sm
Rubytest/dummy/app/components/gallery/components/toast_page.rb
render NitroKit::Card.new(id: "gallery-toast-integration-card") do |card|
  card.title("Slack integration", level: 3)
  card.body do
    render NitroKit::Badge.new(
      "Connected",
      id: "gallery-toast-integration-status",
      color: :success
    )
    p { "Deployment notifications post to #operations." }
  end
  card.footer do
    render NitroKit::Button.new(
      "Configure",
      id: "gallery-toast-configure",
      href: "#configure",
      variant: :default
    )
  end
end
render NitroKit::Toast.new(
  duration: 600_000,
  label: "Integration result",
  id: "gallery-toast-integration-result"
) do |toast|
  toast.item(
    title: "Slack settings saved",
    description: "New deployment notifications will use #operations.",
    variant: :success
  )
end

Component contract

Constructor options, rendered root, closed vocabularies, and compound boundary for this component, exactly as shipped.

docs/component_contracts.md · NitroKit::Toast

Constructor-specific options
  • duration: 5000, label: defaulting to I18n.t("nitro_kit.toast.label"), id: "nk-toast"
Root and closed vocabulary
section[data-nk=toast][role=region] wrapping ol[data-slot=toast-list]; item variants default info success warning error
Compound contract
Accepts zero or more item(title:, description:, variant:, dismissible:, id:) declarations inside its render block. Each item requires a title, description, or block. Items carry role="status", or role="alert" for the error variant, plus aria-atomic, so server-rendered flash items are announced without waiting for a DOM mutation; caller aria: colliding with the owned region label or item atomic raises. Every item is data-turbo-temporary, so a cached page never replays stale feedback; the region and list survive. The list id is the toast id plus -list, so a Turbo Stream can append to it: turbo_stream.append("nk-toast-list") { render NitroKit::Toast::Item.new(title: "Saved", variant: :success) }. Items with dismissible: false render no dismiss button and are never auto-dismissed; the application owns their removal. Toast::FlashMessages maps an enumerable Rails flash into items through explicit keywords. The dismiss control is named from nitro_kit.toast.dismiss.

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::FlashMessages once in the application layout.
  • Use redirect flash for navigation and flash.now when 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, and data: for application data. class and style are forbidden, including inside html:.
  • 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 through data:. data-action, data-controller are 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 with data-nk-escape="class".
  • Every root emits data-nk; owned parts emit component-qualified data-slot values such as field-control or card-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::Flex and NitroKit::Grid for 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-state when styling or behavior also needs it.