Skip to content

Commit

Permalink
Render on load
Browse files Browse the repository at this point in the history
  • Loading branch information
sfnelson committed Oct 16, 2023
1 parent 6141775 commit f5e5391
Show file tree
Hide file tree
Showing 10 changed files with 85 additions and 26 deletions.
16 changes: 12 additions & 4 deletions app/assets/javascripts/controllers/kpop/frame_controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,15 @@ export default class Kpop__FrameController extends Controller {
scrimOutletConnected(scrim) {
if (DEBUG) console.debug("frame:scrim-connected");

this.scrimConnected = true;

// return if already initialized
if (this.openValue) return;

// Capture the scrim and then show the content
// modal controller may not have loaded yet (lazy loading)
if (!this.modalConnected) return;

// Capture the scrim and then show the content, if present
if (this.hasModalOutlet) {
this.#openModal(scrim, this.modalOutlet);
}
Expand All @@ -24,13 +29,16 @@ export default class Kpop__FrameController extends Controller {
modalOutletConnected(modal) {
if (DEBUG) console.debug("frame:modal-connected");

this.modalConnected = true;

// When switching modals a target may connect while scrim is already open
if (this.openValue) return;

// scrim controller may not have loaded yet (lazy loading)
if (!this.scrimConnected) return;

// Capture the scrim and then show the content if the scrim is ready
if (this.hasScrimOutlet) {
this.#openModal(this.scrimOutlet, modal);
}
this.#openModal(this.scrimOutlet, modal);
}

modalOutletDisconnected(_) {
Expand Down
18 changes: 14 additions & 4 deletions app/assets/javascripts/controllers/kpop/modal_controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const DEBUG = true;

export default class Kpop__ModalController extends Controller {
static values = {
dismiss: String,
temporary: { type: Boolean, default: true },
};

Expand All @@ -29,7 +30,10 @@ export default class Kpop__ModalController extends Controller {
async open(scrim) {
// Push a new history entry. This will be popped or replaced when the modal is dismissed.
// Persistent modals push a history entry via Turbo.
if (this.temporaryValue) {
if (this.dismissValue) {
if (DEBUG) console.debug("modal:injected, load without history");
scrim.show(this.scrimConfig);
} else if (this.temporaryValue) {
if (DEBUG) console.debug("modal:push-state");
window.history.pushState(window.history.state, "", window.location);
scrim.show(this.scrimConfig);
Expand Down Expand Up @@ -66,9 +70,15 @@ export default class Kpop__ModalController extends Controller {
() => {
if (DEBUG) console.debug("modal:dismiss-end");

const event = this.temporaryValue ? "popstate" : "turbo:render";
window.addEventListener(event, () => resolve(), { once: true });
window.history.back();
if (this.dismissValue) {
this.element.remove();
Turbo.visit(this.dismissValue, { action: "replace" });
resolve();
} else {
const event = this.temporaryValue ? "popstate" : "turbo:render";
window.addEventListener(event, () => resolve(), { once: true });
window.history.back();
}
},
{
once: true,
Expand Down
3 changes: 2 additions & 1 deletion app/assets/stylesheets/katalyst/kpop/_side_panel.scss
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
max-width: unset;
min-width: unset;
width: 100%;
height: 100%;
height: calc(100% - 1.5rem);
align-self: flex-end;
}
}

Expand Down
9 changes: 9 additions & 0 deletions app/components/kpop/frame_component.html.erb
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
<%= turbo_frame_tag(id, **html_attributes) do %>
<%= content %>
<% if flash[:kpop] %>
<%= tag.div("", data: {
controller: "kpop--redirect",
kpop__redirect_kpop__frame_outlet: "##{id}",
kpop__redirect_path_value: flash[:kpop],
kpop__redirect_target_value: id,
turbo_temporary: "",
}) %>
<% end %>
<% end %>
4 changes: 3 additions & 1 deletion app/components/kpop/modal_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ class ModalComponent < ViewComponent::Base
renders_one :header
renders_one :footer

def initialize(title:, captive: false, temporary: true, **)
def initialize(title:, captive: false, temporary: true, dismiss: nil, **)
super

@dismiss = dismiss
@temporary = temporary

# Generate a title bar. This can be overridden by calling title_bar again.
Expand All @@ -36,6 +37,7 @@ def default_html_attributes
controller: "kpop--modal",
action: ACTIONS.join(" "),
"kpop--frame-target": "modal",
"kpop--modal-dismiss-value": @dismiss,
"kpop--modal-temporary-value": @temporary,
},
}
Expand Down
6 changes: 0 additions & 6 deletions app/helpers/kpop_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,6 @@
module KpopHelper
using HTMLAttributesUtils

# Render a modal dialog. Intended for use inside a kpop turbo frame tag.
# See builder for options.
def render_kpop(options = {}, &)
render(Kpop::ModalComponent.new(**options), &)
end

# Render a turbo stream action that will dismiss any open kpop modals.
def kpop_dismiss(id: "kpop")
turbo_stream.append(id) do
Expand Down
5 changes: 4 additions & 1 deletion spec/dummy/app/controllers/modals_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ def anonymous
end

def persistent
redirect_to root_path, status: :see_other unless request.headers["Turbo-Frame"] == "kpop"
unless request.headers["Turbo-Frame"] == "kpop"
@dismiss = root_path
render "home/index", layout: "application", locals: { kpop: "modals/persistent" }
end
end

def update
Expand Down
6 changes: 6 additions & 0 deletions spec/dummy/app/views/home/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,9 @@
<li><%= kpop_link_to "Anonymous Modal", anonymous_modal_path %></li>
<li><%= kpop_link_to "Persistent Modal", persistent_modal_path, data: { turbo_action: "advance" } %></li>
</ul>

<% if local_assigns[:kpop] %>
<% content_for(:kpop) do %>
<%= render template: kpop %>
<% end %>
<% end %>
2 changes: 1 addition & 1 deletion spec/dummy/app/views/modals/persistent.html.erb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<%= render Kpop::ModalComponent.new(title: "Persistent modal", class: "kpop-side-panel", temporary: false) do %>
<%= render Kpop::ModalComponent.new(title: "Persistent modal", class: "kpop-side-panel", temporary: false, dismiss: @dismiss) do %>
Modal content
<a href="/">Home</a>
<a href="/test">Test</a>
Expand Down
42 changes: 34 additions & 8 deletions spec/system/persistent_modal_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@
require "rails_helper"

RSpec.describe "Persistent modal" do
before do
visit root_path
context "when opening from URL" do
before do
visit root_path

# Open modal
click_link("Persistent")
# Open modal
click_link("Persistent")

# Wait for modal to render
find("[data-kpop--frame-open-value='true']")
end
# Wait for modal to render
find("[data-kpop--frame-open-value='true']")
end

context "when opening from URL" do
it "opens successfully" do
# Modal shows
within(".kpop-modal") do |kpop|
Expand Down Expand Up @@ -218,4 +218,30 @@
expect(page).to have_current_path(nil)
end
end

context "when navigating to modal URL" do
before do
visit persistent_modal_path

# Wait for modal to render
find("[data-kpop--frame-open-value='true']")
end

it "supports form errors on form submission" do
expect(page).to have_current_path(persistent_modal_path) # url is modal url
expect(page).to have_content("Hello world!") # root page is rendered in the background

# Clicking the close button closes the modal
find(".kpop-close").click

expect(page).to have_current_path(root_path)
expect(page).not_to have_css(".kpop-modal")

# Click the back button leaves the site
# Note: this is not ideal, but otherwise would need to know if modal is persistent or not
page.go_back

expect(page).to have_current_path(nil)
end
end
end

0 comments on commit f5e5391

Please sign in to comment.