From 628e1f89bb90871de7f776a4a9466fc689c8d1c9 Mon Sep 17 00:00:00 2001 From: Guillem Arias Date: Mon, 11 May 2026 20:43:41 +0200 Subject: [PATCH] feat(goals/new): standalone page render when not in a Turbo frame MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Direct nav to /goals/new used to render the index page with an empty modal frame because the entire template was wrapped in DS::Dialog. The URL was effectively un-shareable. Branch on turbo_frame_request? — Turbo Frame requests still render the DS::Dialog wrapper (the existing in-modal flow on the index page keeps working). Non-frame requests render a standalone page-level header (h1 + subtitle + icon) followed by the form_stepper partial. Same Stimulus controller, same data-goal-stepper-modal-subtitle selector, so the stepper's subtitle update path works identically. Controller sets @breadcrumbs so the standalone variant gets the Home > Goals > New goal trail. Verified both paths via Playwright: direct GET renders standalone form with h1 "New goal" + no dialog; click-from-index opens the DS::Dialog with the stepper inside. --- app/controllers/goals_controller.rb | 5 ++++ app/views/goals/new.html.erb | 43 +++++++++++++++++++---------- 2 files changed, 34 insertions(+), 14 deletions(-) diff --git a/app/controllers/goals_controller.rb b/app/controllers/goals_controller.rb index 70ae70c34..3105a4c9a 100644 --- a/app/controllers/goals_controller.rb +++ b/app/controllers/goals_controller.rb @@ -45,6 +45,11 @@ class GoalsController < ApplicationController currency: Current.family.primary_currency_code ) @linkable_accounts = linkable_accounts_for_new + @breadcrumbs = [ + [ t("breadcrumbs.home"), root_path ], + [ t("goals.index.title"), goals_path ], + [ t("goals.new.heading"), nil ] + ] end def create diff --git a/app/views/goals/new.html.erb b/app/views/goals/new.html.erb index 45f5cb71a..0f673e668 100644 --- a/app/views/goals/new.html.erb +++ b/app/views/goals/new.html.erb @@ -1,19 +1,34 @@ -<%= render DS::Dialog.new(width: "lg") do |dialog| %> - <% dialog.with_header(custom_header: true) do %> -
-
- <%= render DS::FilledIcon.new(variant: :container, icon: "target", size: "md", rounded: true) %> -
-

<%= t(".heading") %>

-

- <%= t(".step1_subtitle") %> -

+<% if turbo_frame_request? %> + <%= render DS::Dialog.new(width: "lg") do |dialog| %> + <% dialog.with_header(custom_header: true) do %> +
+
+ <%= render DS::FilledIcon.new(variant: :container, icon: "target", size: "md", rounded: true) %> +
+

<%= t(".heading") %>

+

+ <%= t(".step1_subtitle") %> +

+
+ <%= render DS::Button.new(variant: "icon", icon: "x", title: t("common.close"), aria_label: t("common.close"), data: { action: "DS--dialog#close" }) %>
- <%= render DS::Button.new(variant: "icon", icon: "x", title: t("common.close"), aria_label: t("common.close"), data: { action: "DS--dialog#close" }) %> -
+ <% end %> + <% dialog.with_body do %> + <%= render "form_stepper", goal: @goal, linkable_accounts: @linkable_accounts %> + <% end %> <% end %> - <% dialog.with_body do %> +<% else %> +
+
+ <%= render DS::FilledIcon.new(variant: :container, icon: "target", size: "md", rounded: true) %> +
+

<%= t(".heading") %>

+

+ <%= t(".step1_subtitle") %> +

+
+
<%= render "form_stepper", goal: @goal, linkable_accounts: @linkable_accounts %> - <% end %> +
<% end %>