Shadwire
Componentes

Dialog

Uma janela sobreposta à página principal, construída sobre o elemento <dialog> nativo.

Instalação

O Shadwire segue o modelo open-code do shadcn/ui: o código-fonte do componente é copiado para a sua aplicação e passa a ser seu. Instale com a CLI:

shadwire add dialog --yes

O item dialog do registry instala estes arquivos:

  • app/components/ui_component.rb
  • app/components/ui/dialog_component.rb
  • app/components/ui/dialog/trigger_component.rb
  • app/components/ui/dialog/content_component.rb
  • app/components/ui/dialog/header_component.rb
  • app/components/ui/dialog/footer_component.rb
  • app/components/ui/dialog/title_component.rb
  • app/components/ui/dialog/description_component.rb
  • app/components/ui/dialog/close_component.rb
  • app/components/ui/button_component.rb
  • app/components/ui/icon_component.rb
  • app/helpers/ui/dialog_helper.rb
  • app/helpers/ui/button_helper.rb
  • app/helpers/ui/icon_helper.rb
  • app/javascript/controllers/ui_dialog_controller.js
  • vendor/shadwire/shadwire.css

Este componente usa Stimulus: a aplicação precisa de importmap-rails e stimulus-rails com carregamento automático de controllers.

Ainda não instalou a CLI? gem install shadwire e depois shadwire init.

Uso

showModal() entrega focus trap, top layer, Esc e restauração de foco nativamente; o controller adiciona animações, fechamento pelo backdrop e o wiring de aria-labelledby/aria-describedby.

<%= ui_dialog do %>
  <%= ui_dialog_trigger(variant: :outline) { "Abrir" } %>
  <%= ui_dialog_content do %>
    <%= ui_dialog_header do %>
      <%= ui_dialog_title { "Título" } %>
      <%= ui_dialog_description { "Descrição do diálogo." } %>
    <% end %>
    <%= ui_dialog_footer do %>

Ou renderize os componentes diretamente:

<%= render Ui::DialogComponent.new do %>
  <%= render Ui::Dialog::TriggerComponent.new do %>
    Abrir
  <% end %>
  <%= render Ui::Dialog::ContentComponent.new do %>
    <%= render Ui::Dialog::TitleComponent.new do %>
      Título
    <% end %>

Composição

Dialog (data-controller="ui-dialog")
|-- Dialog::Trigger (Button que chama showModal)
`-- Dialog::Content (<dialog> nativo)
    |-- Dialog::Header > Dialog::Title + Dialog::Description
    `-- Dialog::Footer > Dialog::Close (Button)

Exemplos

Padrão

Formulário de perfil em um <dialog> nativo: focus trap, Esc e restauração de foco vêm do navegador.

Editar perfil

Faça alterações no seu perfil e salve quando terminar.

<%= ui_dialog do %>
  <%= ui_dialog_trigger(variant: :outline) { "Editar perfil" } %>
  <%= ui_dialog_content(class: "sm:max-w-md") do %>
    <%= ui_dialog_header do %>
      <%= ui_dialog_title { "Editar perfil" } %>
      <%= ui_dialog_description { "Faça alterações no seu perfil e salve quando terminar." } %>
    <% end %>
    <div class="grid gap-4">

Sem fechar pelo backdrop

close_on_backdrop: false ignora cliques fora do painel.

Atenção

Clicar fora não fecha este diálogo — use o X, Esc ou o botão abaixo.

<%= ui_dialog(close_on_backdrop: false) do %>
  <%= ui_dialog_trigger(variant: :outline) { "Sem fechar pelo backdrop" } %>
  <%= ui_dialog_content do %>
    <%= ui_dialog_header do %>
      <%= ui_dialog_title { "Atenção" } %>
      <%= ui_dialog_description { "Clicar fora não fecha este diálogo — use o X, Esc ou o botão abaixo." } %>
    <% end %>
    <%= ui_dialog_footer do %>

Footer custom

show_close_button: false remove o X; componha seus próprios botões com ui_dialog_close.

Compartilhar

Qualquer pessoa com este link poderá visualizar.

<%= ui_dialog do %>
  <%= ui_dialog_trigger(variant: :outline) { "Compartilhar link" } %>
  <%= ui_dialog_content(show_close_button: false, class: "sm:max-w-md") do %>
    <%= ui_dialog_header do %>
      <%= ui_dialog_title { "Compartilhar" } %>
      <%= ui_dialog_description { "Qualquer pessoa com este link poderá visualizar." } %>
    <% end %>
    <div class="flex items-center gap-2">

Referência da API

Todas as partes aceitam class / class_name e **attrs.

Componente Argumento Padrão Descrição
Dialog close_on_backdrop true Fecha ao clicar fora do painel (no ::backdrop).
Dialog::Trigger / Dialog::Close variant, size :default / :outline Encapsulam Ui::ButtonComponent com as ações de abrir/fechar.
Dialog::Content show_close_button true Renderiza o botão X no canto superior direito.
Dialog::Title / Dialog::Description Ligados ao diálogo via aria-labelledby/aria-describedby na abertura.