Dialog

A native dialog with Nitro-owned trigger, state, and accessible relationships.

Source
app/components/nitro_kit/dialog.rb
API
NitroKit::Dialog.new(id:) { |dialog| dialog.trigger; dialog.dialog }

Confirmation flow

The trigger opens a native dialog whose title and description are connected by ID.

Remove team member

Viewport640 px · sm
Rubytest/dummy/app/components/gallery/components/dialog_page.rb
render NitroKit::Dialog.new(id: "gallery-dialog-remove-member") do |dialog|
  dialog.trigger("Remove member", variant: :destructive)
  dialog.dialog(
    title: "Remove Katherine Johnson?",
    description: "Katherine will immediately lose access to this workspace."
  ) do
    dialog.close_button(label: "Keep team member")
  end
end

Panel states

Declarative commands open modal dialogs; nonmodal is explicit for server-rendered open panels.

Nonmodal and unavailable

Open nonmodal panel
Disabled trigger
Viewport640 px · sm
Rubytest/dummy/app/components/gallery/components/dialog_page.rb
sample("Open nonmodal panel", slug: "nonmodal") do
  render NitroKit::Dialog.new(id: "gallery-dialog-open") do |dialog|
    dialog.dialog(
      title: "Release notes",
      description: "This server-rendered panel is deliberately nonmodal.",
      nonmodal: true
    ) do
      dialog.close_button
    end
  end
end
sample("Disabled trigger", slug: "disabled-trigger") do
  render NitroKit::Dialog.new(id: "gallery-dialog-disabled") do |dialog|
    dialog.trigger("Unavailable action", disabled: true)
    dialog.dialog(title: "Unavailable action") do
      dialog.close_button
    end
  end
end

Form composition

Field, Input, and Button compose directly inside a dialog without a second template API.

Invite a teammate

Viewport640 px · sm
Rubytest/dummy/app/components/gallery/components/dialog_page.rb
render NitroKit::Dialog.new(id: "gallery-dialog-invite") do |dialog|
  dialog.trigger("Invite teammate", variant: :primary)
  dialog.dialog(
    title: "Invite a teammate",
    description: "Choose an address and the role this person should receive."
  ) do
    form(id: "gallery-dialog-invite-form", action: "#invite", method: "post") do
      render NitroKit::Field.new(
        nil,
        :email,
        as: :email,
        id: "gallery-dialog-invite-email",
        name: "invitation[email]",
        value: "[email protected]",
        label: "Email",
        autocomplete: "email",
        required: true,
        html: { id: "gallery-dialog-invite-email-field" }
      )
      render NitroKit::Field.new(
        nil,
        :role,
        as: :select,
        id: "gallery-dialog-invite-role",
        name: "invitation[role]",
        value: "member",
        label: "Role",
        options: Gallery::Forms::TeamInvitation::ROLES,
        html: { id: "gallery-dialog-invite-role-field" }
      )
      render NitroKit::Button.new(
        "Send invitation",
        id: "gallery-dialog-invite-submit",
        type: :submit,
        variant: :primary
      )
      dialog.close_button(label: "Cancel invitation")
    end
  end
end