feat(savings_goals/new): checkbox styling, visible stepper, DS::Disclosure for notes, drop redundant cancel

Use Sure's .checkbox checkbox--light classes on the funding-account
check_box_tag — matches transactions / entries / settings pages.

Stepper line: 2px tall bg-secondary in resting state (was 1px bg-subdued
which disappeared in dark mode). Step 2 inactive circle: border-secondary
outline instead of bg-container-inset fill — visible in both themes.

Notes collapse switches from raw <details> to DS::Disclosure for
consistency with the rest of Sure's DS.

Drop the footer Cancel button — the close X in the modal header already
handles that, and double cancel was redundant. The footer-left slot now
only renders Back (with arrow-left icon) and only on step 2.
This commit is contained in:
Guillem Arias
2026-05-11 15:13:04 +02:00
parent c3bf6a157f
commit 27863882fe
2 changed files with 19 additions and 28 deletions

View File

@@ -51,12 +51,7 @@ export default class extends Controller {
footerLeft(event) {
event.preventDefault();
if (this.currentStep === 1) {
const dialog = this.element.closest("dialog");
if (dialog) dialog.close();
} else {
this.back();
}
this.back();
}
footerRight(event) {
@@ -194,11 +189,13 @@ export default class extends Controller {
if (this.hasStep2CircleTarget) {
this.step2CircleTarget.classList.toggle("bg-inverse", this.currentStep === 2);
this.step2CircleTarget.classList.toggle("text-inverse", this.currentStep === 2);
this.step2CircleTarget.classList.toggle("bg-container-inset", this.currentStep < 2);
this.step2CircleTarget.classList.toggle("border", this.currentStep < 2);
this.step2CircleTarget.classList.toggle("border-secondary", this.currentStep < 2);
this.step2CircleTarget.classList.toggle("text-secondary", this.currentStep < 2);
}
if (this.hasStepperLineTarget) {
this.stepperLineTarget.classList.toggle("bg-inverse", this.currentStep > 1);
this.stepperLineTarget.classList.toggle("bg-secondary", this.currentStep === 1);
}
// Modal subtitle lives in the dialog header, outside this controller's
// DOM scope. Locate it by attribute and update directly.
@@ -211,11 +208,7 @@ export default class extends Controller {
updateFooter() {
if (this.hasFooterLeftButtonTarget) {
const labelSpan = this.footerLeftButtonTarget.querySelector("span");
if (labelSpan) {
labelSpan.textContent =
this.currentStep === 1 ? this.cancelLabelValue : this.backLabelValue;
}
this.footerLeftButtonTarget.classList.toggle("hidden", this.currentStep === 1);
}
if (this.hasFooterRightButtonTarget) {
const labelSpan = this.footerRightButtonTarget.querySelector("span");

View File

@@ -11,9 +11,9 @@
<span data-savings-goal-stepper-target="step1Circle" class="w-7 h-7 rounded-full inline-flex items-center justify-center bg-inverse text-inverse text-xs font-medium">1</span>
<span class="text-sm font-medium text-primary"><%= t("savings_goals.form_stepper.step1.label") %></span>
</div>
<div class="flex-1 h-px bg-subdued" data-savings-goal-stepper-target="stepperLine"></div>
<div class="flex-1 h-0.5 bg-secondary rounded-full" data-savings-goal-stepper-target="stepperLine"></div>
<div class="flex items-center gap-2" data-savings-goal-stepper-target="step2Indicator">
<span data-savings-goal-stepper-target="step2Circle" class="w-7 h-7 rounded-full inline-flex items-center justify-center bg-container-inset text-secondary text-xs font-medium">2</span>
<span data-savings-goal-stepper-target="step2Circle" class="w-7 h-7 rounded-full inline-flex items-center justify-center border border-secondary text-secondary text-xs font-medium">2</span>
<span class="text-sm font-medium text-secondary"><%= t("savings_goals.form_stepper.step2.label") %></span>
</div>
</div>
@@ -65,7 +65,7 @@
<%= check_box_tag "savings_goal[account_ids][]",
account.id,
false,
class: "shrink-0",
class: "checkbox checkbox--light shrink-0",
data: {
savings_goal_stepper_target: "linkedAccountCheckbox",
action: "change->savings-goal-stepper#linkedAccountChanged",
@@ -87,18 +87,12 @@
<p class="hidden mt-1.5 text-xs text-destructive" data-savings-goal-stepper-target="accountsError"><%= t("savings_goals.form_stepper.errors.accounts_required") %></p>
</div>
<details class="border border-subdued rounded-lg group">
<summary class="flex items-center justify-between gap-3 px-4 py-3 cursor-pointer list-none text-sm font-medium text-primary">
<span><%= t("savings_goals.form_stepper.step1.fields.notes_summary") %></span>
<%= icon("chevron-down", size: "sm", class: "group-open:rotate-180 transition-transform") %>
</summary>
<div class="px-4 pb-4">
<%= f.text_area :notes,
label: "",
rows: 2,
placeholder: t("savings_goals.form_stepper.step1.fields.notes_placeholder") %>
</div>
</details>
<%= render DS::Disclosure.new(title: t("savings_goals.form_stepper.step1.fields.notes_summary"), align: "right") do %>
<%= f.text_area :notes,
label: false,
rows: 2,
placeholder: t("savings_goals.form_stepper.step1.fields.notes_placeholder") %>
<% end %>
<%= f.hidden_field :color %>
</section>
@@ -167,12 +161,16 @@
<div class="flex items-center justify-between pt-2">
<%= render DS::Button.new(
variant: "ghost",
text: t("savings_goals.form_stepper.cancel"),
text: t("savings_goals.form_stepper.back"),
icon: "arrow-left",
icon_position: :left,
class: "hidden",
data: {
savings_goal_stepper_target: "footerLeftButton",
action: "click->savings-goal-stepper#footerLeft"
}
) %>
<span data-savings-goal-stepper-target="footerLeftPlaceholder"></span>
<%= render DS::Button.new(
text: t("savings_goals.form_stepper.continue"),
variant: "primary",