Skip to content

Commit

Permalink
Add modal component
Browse files Browse the repository at this point in the history
This component uses the Slots from ViewComponent.
Those slots allow the developer to pass a block to the component,
this enables an in-depth customization of the component,
especially for the modal, in which the body should be dynamic.
Since modals also carry action confirmations,
I've added the possibility to change the action button as well.
  • Loading branch information
the-krg committed Sep 6, 2023
1 parent 9aae2b0 commit e42aacf
Show file tree
Hide file tree
Showing 6 changed files with 172 additions and 0 deletions.
33 changes: 33 additions & 0 deletions admin/app/components/solidus_admin/ui/modal/component.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<div data-controller=<%= stimulus_id %> id=<%= @id %> class="relative z-10 hidden" aria-labelledby="modal-title" role="dialog" aria-modal="true">
<div class="fixed inset-0 bg-gray-500 bg-opacity-75"></div>

<div class="fixed inset-0 z-10 overflow-y-auto">
<div class="flex min-h-full items-end justify-center p-4 text-center sm:items-center sm:p-0">
<div class="relative transform overflow-hidden rounded-lg bg-white text-left shadow-xl sm:my-8 sm:w-full sm:max-w-lg divide-y">
<div class="flex justify-between pb-4 pt-5 sm:p-6 sm:pb-4">
<div class="mt-3 text-center sm:mt-0 sm:text-left">
<h3 class="text-xl font-semibold leading-6 text-gray-900" id="modal-title">
<%= @title %>
</h3>
</div>
<button type="button" class="close" data-action=<%= "#{stimulus_id}#toggleModal" %> data-modal-id=<%= @id %> aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="px-3 pb-4 pt-5 sm:p-6 sm:pb-4">
<%= body %>
</div>
<div class="px-3 py-3 sm:flex sm:flex-row-reverse sm:px-6">
<% if actions? %>
<div class="ml-2 sm:mt-0 sm:w-auto">
<%= actions %>
</div>
<% end %>
<div>
<%= render_cancel_button %>
</div>
</div>
</div>
</div>
</div>
</div>
9 changes: 9 additions & 0 deletions admin/app/components/solidus_admin/ui/modal/component.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
static values = { modal: String }

toggleModal(e) {
document.getElementById(e.currentTarget.dataset.modalId).classList.toggle('hidden');
}
}
22 changes: 22 additions & 0 deletions admin/app/components/solidus_admin/ui/modal/component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# frozen_string_literal: true

class SolidusAdmin::UI::Modal::Component < SolidusAdmin::BaseComponent
renders_one :body
renders_one :actions

def initialize(
title:,
id: SecureRandom.hex,
close_message: "Close",
button_component: component("ui/button")
)
@id = id
@title = title
@close_message = close_message
@button_component = button_component
end

def render_cancel_button
render @button_component.new(text: @close_message, scheme: :secondary, class: 'sm:mt-0 sm:w-auto', 'data-action': "#{stimulus_id}#toggleModal", 'data-modal-id': @id)
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# frozen_string_literal: true

# @component "ui/modal"
class SolidusAdmin::UI::Modal::ComponentPreview < ViewComponent::Preview
include SolidusAdmin::Preview

def overview
render_with_template
end

# @param title text
# @param body textarea
# @param close_message text
# @param actions textarea
def playground(title: 'Modal', body: 'Body', close_message: nil, actions: nil)
render_with_template(
locals: {
title: title,
body: body,
actions: actions,
close_message: close_message
}
)
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<div class="flex justify-center items-center h-screen">
<table>
<tr>
<td class="px-3 py-1 text-center">
<%= render component('ui/button').new(
scheme: :primary,
text: 'Modal',
'data-action': 'click->ui--modal#toggleModal',
'data-controller': 'ui--modal',
'data-modal-id': 'testModal') %>
<%= render current_component.new(id: 'testModal', title: 'Modal Title') do |component| %>
<% component.with_body do %>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
<% end %>
<% end %>
</td>

<td class="px-3 py-1 text-center">
<%= render component('ui/button').new(
scheme: :primary,
text: 'Modal with form',
'data-action': 'click->ui--modal#toggleModal',
'data-controller': 'ui--modal',
'data-modal-id': 'formModal') %>
<%= render current_component.new(id: 'formModal', title: 'Create user') do |component| %>
<%= form_with(url: "#", scope: :overview, method: :get) do |form| %>
<% component.with_body do %>
<%=
render SolidusAdmin::UI::Forms::TextField::Component.new(
builder: form,
field: "Test Form",
placeholder: "Placeholder",
errors: { "empty_with_error" => ["can't be blank"] }
)
%>
<% end %>
<% component.with_actions do %>
<%= render component('ui/button').new(
scheme: :primary,
form: form.id,
type: :submit,
text: 'Create'
) %>
<% end %>
<% end %>
<% end %>
</td>
<td class="px-3 py-1 text-center">
<%= render component('ui/button').new(
scheme: :primary,
text: 'Modal with custom action',
'data-action': 'click->ui--modal#toggleModal',
'data-controller': 'ui--modal',
'data-modal-id': 'customModal') %>
<%= render current_component.new(id: 'customModal', title: 'Delete view?') do |component| %>
<% component.with_body do %>
<b>This can't be undone. T-shirt SM view will no longer be available in your admin!</b>
<% end %>
<% component.with_actions do %>
<%= render component('ui/button').new(scheme: :primary, text: 'Delete', 'data-action': 'click->ui--modal#toggleModal', 'data-controller': 'ui--modal', 'data-modal-id': 'customModal') %>
<% end %>
<% end %>
</td>
</tr>
</table>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<%= render component('ui/button').new(scheme: :primary, text: 'Open Modal', 'data-action': 'click->ui--modal#toggleModal', 'data-controller': 'ui--modal', 'data-modal-id': 'customModal') %>
<%= render component("ui/modal").new(id: 'customModal', title: title, close_message: close_message) do |modal| %>
<% modal.with_body do %>
<%= body.html_safe %>
<% end %>
<% if actions%>
<% modal.with_actions do %>
<%= actions.html_safe %>
<% end %>
<% end %>
<% end %>

0 comments on commit e42aacf

Please sign in to comment.