diff --git a/docs/plans/2026-06-27-001-fix-ssr-modal-regressions-plan.md b/docs/plans/2026-06-27-001-fix-ssr-modal-regressions-plan.md index e4449f92..00e51dbc 100644 --- a/docs/plans/2026-06-27-001-fix-ssr-modal-regressions-plan.md +++ b/docs/plans/2026-06-27-001-fix-ssr-modal-regressions-plan.md @@ -93,21 +93,28 @@ animate: - By contrast, `dialog/success-modal-` and the Invoice Pay card (`last-modal-step transition duration-150`) keep transitions, so the intended pattern still exists to copy from. -**FIX — DONE (subtle fade) & verified:** added the codebase's existing `fade-in transition-opacity -duration-300` to all three wizard step cards (new-invoice basic-details + accounts, vendor -step-card, client step-card). `fade-in` is defined in `resources/input.css` -(`.htmx-added .fade-in { opacity:0 }` → transitions to 1 after htmx settle), so each card fades in -on open *and* on every step swap. Verified live: cards always settle to **opacity 1** (never stuck -invisible) on both open and step navigation — no functional risk. - -Notes / intentionally deferred (needs design intent + visual sign-off, so not done autonomously): -- The transaction-edit "reference" card's `last-modal-step` class is **undefined** (a no-op); its - only real transition is `transition duration-150`. So there was no clean reference slide to copy. -- The richer **forward/backward slide** transitions (the old `mm/*` modal-stack system using - `group/transition` + `forward`/`backward` + `htmx-*:translate-x-2/3`) were deliberately deleted in - Phase 11 and purged from the CSS. Re-introducing directional slides is a larger design decision - (which element carries `htmx-swapping`/`htmx-added` — the form vs the card — plus settle timing) - and is left for a human-in-the-loop pass if the subtle fade isn't enough. +**FIX — DONE (forward/back slide restored) in the shared `wizard2` engine.** The user confirmed the +old wizard had a directional **slide forward/back** between steps; the engine migration dropped it. +Restored the original mechanism (read out of the deleted `mm/multi_modal.clj`) in one shared place: +- `wizard2/step-slide-classes` — the `group-[.forward]/transition:htmx-*` + `group-[.backward]/…` + variants, now applied to the swapped wizard `
`. +- `wizard2/transitioner` — the `#transitioner` wrapper with the `@htmx:after-request` hook that reads + the `x-transition-type` response header and toggles `group/transition` + `forward|backward` on + itself (so the variants fire on the next swap). All 5 wizard configs' `:open-response` now wrap the + form in `wizard2/transitioner` instead of a plain `#transitioner` div. +- `wizard2/handle-step-submit` now sets `x-transition-type` (forward on advance, backward on Back, + `none` on a same-step validation re-render) + `HX-reswap: outerHTML swap:0.16s` (the swap delay + that lets the slide-out play). Direction is computed from the step order (`transition-type`). +- The earlier per-card `fade-in` (interim) was removed in favor of this. +- CSS rebuilt so the `group-[.forward]/transition:htmx-*` variants (16 fwd + 16 back) are compiled. +- Applies to ALL wizards (new-invoice, vendor, client, pay, transaction-rule) since it lives in the + engine. REPL-verified: `open-wizard` emits the transitioner, the form carries the slide classes, + and submit responses carry `x-transition-type` + the `HX-reswap` swap delay. +- **Live-verify caveat:** the long-lived dev server froze its route table at startup + (`auto-ap.handler/match->handler-lookup` is a `def` that merged the per-ns `key->handler` maps), so + an nREPL reload of leaf namespaces does NOT reach the running router — a server refresh + (`stop jetty → tools.namespace refresh → user/start-http`) or a fresh `lein run` is needed to see + it live. (Documented hazard; see the QA memory.) ## 4. Bug list + fixes (prioritized task list) diff --git a/resources/public/output.css b/resources/public/output.css index f7ece718..de06df74 100644 --- a/resources/public/output.css +++ b/resources/public/output.css @@ -1609,10 +1609,6 @@ input:checked + .toggle-bg { width: 5em; } -.w-\[600px\] { - width: 600px; -} - .w-\[700px\] { width: 700px; } @@ -3996,6 +3992,44 @@ input:checked + .toggle-bg { opacity: 0; } +.group\/transition.backward .group-\[\.backward\]\/transition\:htmx-swapping\:translate-x-1\/4.htmx-swapping { + --tw-translate-x: 25%; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.group\/transition.forward .group-\[\.forward\]\/transition\:htmx-swapping\:-translate-x-1\/4.htmx-swapping { + --tw-translate-x: -25%; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.group\/transition.backward .group-\[\.backward\]\/transition\:htmx-swapping\:scale-75.htmx-swapping { + --tw-scale-x: .75; + --tw-scale-y: .75; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.group\/transition.forward .group-\[\.forward\]\/transition\:htmx-swapping\:scale-75.htmx-swapping { + --tw-scale-x: .75; + --tw-scale-y: .75; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.group\/transition.backward .group-\[\.backward\]\/transition\:htmx-swapping\:opacity-0.htmx-swapping { + opacity: 0; +} + +.group\/transition.forward .group-\[\.forward\]\/transition\:htmx-swapping\:opacity-0.htmx-swapping { + opacity: 0; +} + +.group\/transition.backward .group-\[\.backward\]\/transition\:htmx-swapping\:ease-in.htmx-swapping { + transition-timing-function: cubic-bezier(0.4, 0, 1, 1); +} + +.group\/transition.forward .group-\[\.forward\]\/transition\:htmx-swapping\:ease-in.htmx-swapping { + transition-timing-function: cubic-bezier(0.4, 0, 1, 1); +} + .htmx-swapping .htmx-swapping\:-translate-x-2\/3 { --tw-translate-x: -66.666667%; transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); @@ -4011,6 +4045,44 @@ input:checked + .toggle-bg { opacity: 0; } +.group\/transition.backward .htmx-swapping .group-\[\.backward\]\/transition\:htmx-swapping\:translate-x-1\/4 { + --tw-translate-x: 25%; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.group\/transition.forward .htmx-swapping .group-\[\.forward\]\/transition\:htmx-swapping\:-translate-x-1\/4 { + --tw-translate-x: -25%; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.group\/transition.backward .htmx-swapping .group-\[\.backward\]\/transition\:htmx-swapping\:scale-75 { + --tw-scale-x: .75; + --tw-scale-y: .75; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.group\/transition.forward .htmx-swapping .group-\[\.forward\]\/transition\:htmx-swapping\:scale-75 { + --tw-scale-x: .75; + --tw-scale-y: .75; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.group\/transition.backward .htmx-swapping .group-\[\.backward\]\/transition\:htmx-swapping\:opacity-0 { + opacity: 0; +} + +.group\/transition.forward .htmx-swapping .group-\[\.forward\]\/transition\:htmx-swapping\:opacity-0 { + opacity: 0; +} + +.group\/transition.backward .htmx-swapping .group-\[\.backward\]\/transition\:htmx-swapping\:ease-in { + transition-timing-function: cubic-bezier(0.4, 0, 1, 1); +} + +.group\/transition.forward .htmx-swapping .group-\[\.forward\]\/transition\:htmx-swapping\:ease-in { + transition-timing-function: cubic-bezier(0.4, 0, 1, 1); +} + .htmx-added\:translate-x-2\/3.htmx-added { --tw-translate-x: 66.666667%; transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); @@ -4026,6 +4098,44 @@ input:checked + .toggle-bg { opacity: 0; } +.group\/transition.backward .group-\[\.backward\]\/transition\:htmx-added\:-translate-x-1\/4.htmx-added { + --tw-translate-x: -25%; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.group\/transition.forward .group-\[\.forward\]\/transition\:htmx-added\:translate-x-1\/4.htmx-added { + --tw-translate-x: 25%; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.group\/transition.backward .group-\[\.backward\]\/transition\:htmx-added\:scale-75.htmx-added { + --tw-scale-x: .75; + --tw-scale-y: .75; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.group\/transition.forward .group-\[\.forward\]\/transition\:htmx-added\:scale-75.htmx-added { + --tw-scale-x: .75; + --tw-scale-y: .75; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.group\/transition.backward .group-\[\.backward\]\/transition\:htmx-added\:opacity-0.htmx-added { + opacity: 0; +} + +.group\/transition.forward .group-\[\.forward\]\/transition\:htmx-added\:opacity-0.htmx-added { + opacity: 0; +} + +.group\/transition.backward .group-\[\.backward\]\/transition\:htmx-added\:ease-out.htmx-added { + transition-timing-function: cubic-bezier(0, 0, 0.2, 1); +} + +.group\/transition.forward .group-\[\.forward\]\/transition\:htmx-added\:ease-out.htmx-added { + transition-timing-function: cubic-bezier(0, 0, 0.2, 1); +} + .htmx-added .htmx-added\:translate-x-2\/3 { --tw-translate-x: 66.666667%; transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); @@ -4041,6 +4151,44 @@ input:checked + .toggle-bg { opacity: 0; } +.group\/transition.backward .htmx-added .group-\[\.backward\]\/transition\:htmx-added\:-translate-x-1\/4 { + --tw-translate-x: -25%; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.group\/transition.forward .htmx-added .group-\[\.forward\]\/transition\:htmx-added\:translate-x-1\/4 { + --tw-translate-x: 25%; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.group\/transition.backward .htmx-added .group-\[\.backward\]\/transition\:htmx-added\:scale-75 { + --tw-scale-x: .75; + --tw-scale-y: .75; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.group\/transition.forward .htmx-added .group-\[\.forward\]\/transition\:htmx-added\:scale-75 { + --tw-scale-x: .75; + --tw-scale-y: .75; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.group\/transition.backward .htmx-added .group-\[\.backward\]\/transition\:htmx-added\:opacity-0 { + opacity: 0; +} + +.group\/transition.forward .htmx-added .group-\[\.forward\]\/transition\:htmx-added\:opacity-0 { + opacity: 0; +} + +.group\/transition.backward .htmx-added .group-\[\.backward\]\/transition\:htmx-added\:ease-out { + transition-timing-function: cubic-bezier(0, 0, 0.2, 1); +} + +.group\/transition.forward .htmx-added .group-\[\.forward\]\/transition\:htmx-added\:ease-out { + transition-timing-function: cubic-bezier(0, 0, 0.2, 1); +} + :is(.dark .dark\:border-blue-500) { --tw-border-opacity: 1; border-color: rgb(0 156 234 / var(--tw-border-opacity)); diff --git a/src/clj/auto_ap/ssr/admin/clients.clj b/src/clj/auto_ap/ssr/admin/clients.clj index c7296953..a7791eb3 100644 --- a/src/clj/auto_ap/ssr/admin/clients.clj +++ b/src/clj/auto_ap/ssr/admin/clients.clj @@ -517,7 +517,7 @@ [{:keys [title active all-data nav body]}] (com/modal-card-advanced {"@keydown.enter.prevent.stop" "if ($refs.next) {$refs.next.click()}" - :class " md:w-[820px] md:h-[560px] w-full h-full fade-in transition-opacity duration-300" + :class " md:w-[820px] md:h-[560px] w-full h-full" :x-data (hx/json {"clientName" (:client/name all-data)})} (com/modal-header {} [:div.flex [:div.p-2 title] [:p.ml-2.rounded.bg-gray-50.p-2.dark:bg-gray-600 [:span {:x-text "clientName"}]]]) @@ -1216,7 +1216,7 @@ :form-id "wizard-form" :submit-route (bidi/path-for ssr-routes/only-routes ::route/save) :form-attrs {:hx-ext "response-targets" :hx-target-400 "#form-errors"} - :open-response (fn [form] (modal-response [:div#transitioner.flex-1 form])) + :open-response (fn [form] (modal-response (wizard2/transitioner form))) :init-fn client-init-fn :steps [{:key :info :decode decode-info :validate (partial validate-with info-schema) :render render-info :next (fn [_] :matches)} {:key :matches :decode (partial decode-with matches-schema) :validate (partial validate-with matches-schema) :render render-matches :next (fn [_] :contact)} diff --git a/src/clj/auto_ap/ssr/admin/transaction_rules.clj b/src/clj/auto_ap/ssr/admin/transaction_rules.clj index 70b245a7..b4801bd9 100644 --- a/src/clj/auto_ap/ssr/admin/transaction_rules.clj +++ b/src/clj/auto_ap/ssr/admin/transaction_rules.clj @@ -827,7 +827,7 @@ ;; new/edit routes are just (partial wizard2/open-wizard config) -- no hand-rolled ;; create!/render/wrap/thread boilerplate. :open-response (fn [form] - (modal-response [:div#transitioner.flex-1 form])) + (modal-response (wizard2/transitioner form))) :steps [{:key :edit :decode decode-rule-form :validate rule-form-errors diff --git a/src/clj/auto_ap/ssr/admin/vendors.clj b/src/clj/auto_ap/ssr/admin/vendors.clj index 85ef0557..5e416527 100644 --- a/src/clj/auto_ap/ssr/admin/vendors.clj +++ b/src/clj/auto_ap/ssr/admin/vendors.clj @@ -373,7 +373,7 @@ [{:keys [title active all-data nav body]}] (com/modal-card-advanced {"@keydown.enter.prevent.stop" "if ($refs.next) {$refs.next.click()}" - :class " md:w-[760px] md:h-[520px] w-full h-full fade-in transition-opacity duration-300" + :class " md:w-[760px] md:h-[520px] w-full h-full" :x-data (hx/json {"vendorName" (:vendor/name all-data) "showPrintAs" (boolean (not-empty (:vendor/print-as all-data))) "printAs" (:vendor/print-as all-data)})} @@ -672,7 +672,7 @@ :form-id "wizard-form" :submit-route (bidi/path-for ssr-routes/only-routes ::route/save) :form-attrs {:hx-ext "response-targets" :hx-target-400 "#form-errors"} - :open-response (fn [form] (modal-response [:div#transitioner.flex-1 form])) + :open-response (fn [form] (modal-response (wizard2/transitioner form))) :init-fn vendor-init-fn :steps [{:key :info :decode (partial decode-with info-schema) :validate (partial validate-with info-schema) :render render-info :next (fn [_] :terms)} {:key :terms :decode (partial decode-with terms-schema) :validate (partial validate-with terms-schema) :render render-terms :next (fn [_] :account)} diff --git a/src/clj/auto_ap/ssr/components/wizard2.clj b/src/clj/auto_ap/ssr/components/wizard2.clj index 9d8b5f72..52e99169 100644 --- a/src/clj/auto_ap/ssr/components/wizard2.clj +++ b/src/clj/auto_ap/ssr/components/wizard2.clj @@ -33,11 +33,15 @@ (:require [auto-ap.ssr.components :as com] [auto-ap.ssr.components.wizard-state :as ws] + [auto-ap.ssr.hx :as hx] [auto-ap.ssr.utils :refer [html-response]])) (defn- step-by-key [config k] (first (filter #(= (:key %) k) (:steps config)))) +(defn- step-index [config k] + (.indexOf (mapv :key (:steps config)) k)) + (defn- prev-step "The step key before `k` in the linear step order (or `k` itself if first)." [config k] @@ -45,13 +49,68 @@ i (.indexOf keys k)] (if (pos? i) (nth keys (dec i)) k))) +(defn- transition-type + "forward when advancing to a later step, backward when returning to an earlier one, nil + when staying on the same step (a validation re-render) — used to drive the slide." + [config from-key to-key] + (let [fi (step-index config from-key) + ti (step-index config to-key)] + (cond + (or (neg? fi) (neg? ti) (= fi ti)) nil + (> fi ti) "backward" + :else "forward"))) + +(def step-slide-classes + "Forward/back slide variants applied to the swapped wizard . The #transitioner + ancestor (see `transitioner`) carries `group/transition` + `forward`|`backward`; during a + step swap the outgoing form gets `htmx-swapping` and the incoming one `htmx-added`, so + these variants animate the card sliding/​fading in the matching direction." + (str "group-[.forward]/transition:htmx-swapping:opacity-0 " + "group-[.forward]/transition:htmx-swapping:-translate-x-1/4 " + "group-[.forward]/transition:htmx-swapping:scale-75 " + "group-[.forward]/transition:htmx-swapping:ease-in " + "group-[.forward]/transition:htmx-added:opacity-0 " + "group-[.forward]/transition:htmx-added:scale-75 " + "group-[.forward]/transition:htmx-added:translate-x-1/4 " + "group-[.forward]/transition:htmx-added:ease-out " + "group-[.backward]/transition:htmx-swapping:opacity-0 " + "group-[.backward]/transition:htmx-swapping:translate-x-1/4 " + "group-[.backward]/transition:htmx-swapping:scale-75 " + "group-[.backward]/transition:htmx-swapping:ease-in " + "group-[.backward]/transition:htmx-added:opacity-0 " + "group-[.backward]/transition:htmx-added:scale-75 " + "group-[.backward]/transition:htmx-added:-translate-x-1/4 " + "group-[.backward]/transition:htmx-added:ease-out " + "opacity-100 translate-x-0 scale-100 transition duration-150")) + +(defn transitioner + "Wrap the opened wizard form in the #transitioner the slide animation hooks onto. After + each step swap it reads the `x-transition-type` response header and toggles + `group/transition` + `forward`|`backward` on itself, which drives `step-slide-classes` on + the swapped form. Rendered once on open; the form swaps itself inside it, so this node + (and its Alpine state) persists across steps." + [form] + [:div#transitioner.flex-1 + {:x-data (hx/json {"transitionType" "none"}) + :x-ref "transitioner" + "@htmx:after-request" (str "if (event.detail.xhr.getResponseHeader('x-transition-type') && " + "event.detail.xhr.getResponseHeader('x-transition-type') !== 'none') {" + " $refs.transitioner.classList.remove('forward');" + " $refs.transitioner.classList.remove('backward');" + " $refs.transitioner.classList.add('group/transition');" + " $refs.transitioner.classList.add(event.detail.xhr.getResponseHeader('x-transition-type'));" + "} else { $refs.transitioner.classList.remove('group/transition'); }")} + form]) + (defn wizard-form "Wrap a step body in the wizard : the form posts to the submit route, and only the wizard-id + current-step ride along (no accumulated data — that lives in the session). Enter is guarded so it triggers the step's primary nav button (the one marked - `data-primary`) rather than whichever submit button the browser picks first." + `data-primary`) rather than whichever submit button the browser picks first. The form + carries `step-slide-classes` so the whole-form swap animates as a directional slide." [config wizard-id current-step body] [:form (merge {:id (:form-id config "wizard-form") + :class step-slide-classes :hx-post (:submit-route config) :hx-target "this" :hx-swap "outerHTML" @@ -115,6 +174,17 @@ extra))) (assoc :session session))) +(defn- with-transition + "Attach the slide headers the #transitioner reads: `x-transition-type` (forward/backward) + plus an `HX-reswap` swap delay so the outgoing form's slide-out is visible before the + swap. nil tt -> `none` (a same-step validation re-render does not animate)." + [resp tt] + (if tt + (-> resp + (assoc-in [:headers "x-transition-type"] tt) + (assoc-in [:headers "HX-reswap"] "outerHTML swap:0.16s")) + (assoc-in resp [:headers "x-transition-type"] "none"))) + (defn open-wizard "Create a wizard instance in the session, render its first step, and return a Ring response with the updated session threaded. `:init-fn` returns {:context ..., :init-data @@ -158,9 +228,11 @@ (expired-response config request) (= direction "back") - (render-response config wizard-id - (ws/set-step session wizard-id (prev-step config current-step)) - request) + (let [prev (prev-step config current-step)] + (-> (render-response config wizard-id + (ws/set-step session wizard-id prev) + request) + (with-transition (transition-type config current-step prev)))) :else (let [step (step-by-key config current-step) @@ -171,13 +243,16 @@ posted ((:decode step) clean) errors (when-let [v (:validate step)] (v posted request))] (if (seq errors) - (render-response config wizard-id session request - {:step-errors errors :step-posted posted}) + ;; same step -> no slide (with-transition nil => "none") + (-> (render-response config wizard-id session request + {:step-errors errors :step-posted posted}) + (with-transition nil)) (let [session' (ws/put-step session wizard-id current-step posted) nxt ((:next step) posted)] (if (= nxt :done) (-> ((:done-fn config) (ws/get-all session' wizard-id) request) (assoc :session (ws/forget session' wizard-id))) - (render-response config wizard-id - (ws/set-step session' wizard-id nxt) - request)))))))) + (-> (render-response config wizard-id + (ws/set-step session' wizard-id nxt) + request) + (with-transition (transition-type config current-step nxt)))))))))) diff --git a/src/clj/auto_ap/ssr/invoice/new_invoice_wizard.clj b/src/clj/auto_ap/ssr/invoice/new_invoice_wizard.clj index f75d6952..d7b586f4 100644 --- a/src/clj/auto_ap/ssr/invoice/new_invoice_wizard.clj +++ b/src/clj/auto_ap/ssr/invoice/new_invoice_wizard.clj @@ -333,7 +333,7 @@ client-val (or (:invoice/client data) client-from-req)] (com/modal-card-advanced {"@keydown.enter.prevent.stop" "if ($refs.next) {$refs.next.click()}" - :class " md:w-[750px] md:h-[600px] w-full h-full fade-in transition-opacity duration-300" + :class " md:w-[750px] md:h-[600px] w-full h-full" "x-data" ""} (com/modal-header {} [:div.p-2 (if extant? "Edit invoice" "New invoice")]) (com/modal-body @@ -526,7 +526,7 @@ total (expense-accounts-total* rows)] (com/modal-card-advanced {"@keydown.enter.prevent.stop" "if ($refs.next) {$refs.next.click()}" - :class " md:w-[750px] md:h-[600px] w-full h-full fade-in transition-opacity duration-300" + :class " md:w-[750px] md:h-[600px] w-full h-full" "x-data" ""} (com/modal-header {} [:div.p-2 "Invoice accounts "]) (com/modal-body @@ -778,7 +778,7 @@ :submit-route (bidi/path-for ssr-routes/only-routes ::route/new-invoice-submit) :form-attrs {:hx-ext "response-targets" :hx-target-400 "#form-errors"} - :open-response (fn [form] (modal-response [:div#transitioner.flex-1 form])) + :open-response (fn [form] (modal-response (wizard2/transitioner form))) :init-fn new-init-fn :steps [{:key :basic-details :decode decode-basic-details diff --git a/src/clj/auto_ap/ssr/invoices.clj b/src/clj/auto_ap/ssr/invoices.clj index d9d789cf..07c67389 100644 --- a/src/clj/auto_ap/ssr/invoices.clj +++ b/src/clj/auto_ap/ssr/invoices.clj @@ -1366,7 +1366,7 @@ :submit-route (bidi/path-for ssr-routes/only-routes ::route/pay-submit) :form-attrs {:hx-ext "response-targets" :hx-target-400 "#form-errors"} - :open-response (fn [form] (modal-response [:div#transitioner.flex-1 form])) + :open-response (fn [form] (modal-response (wizard2/transitioner form))) :init-fn pay-init-fn :steps [{:key :choose-method :decode decode-choose-method