From b47e3478b7f1ff2f1076ede0ae5fea0b281749cc Mon Sep 17 00:00:00 2001 From: Guillem Arias Date: Mon, 11 May 2026 21:00:47 +0200 Subject: [PATCH] ux(goals): catch-up rework, dark-mode pill contrast, color disclosure, stepper continue-right MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - catch_up alert: title now leads with the new info (delta) and body states the required rate. Was "Save $1,000/mo to catch up" + "Currently $750/mo behind" — confusingly double-stated. Now "Behind by $750/mo" + "Save $1,000/mo to stay on track for {date}." Locale keys swap the %{amount}/%{delta} placement. - Goals::StatusPillComponent: each variant carries a theme-dark: text override so the dark-700 text doesn't disappear against the dark-mode tinted surface. Verified in dark mode: Paused pill text is now rgb(231,231,231) (gray-200) instead of rgb(54,54,54) (gray-700). Pre-existing token contrast fix tracked at we-promise/sure#1736 stays the long-term path; this is the local workaround that doesn't drop 4.5:1 in either theme. - New goals/_color_picker.html.erb partial:
disclosure with current-color preview in the summary + swatch grid in the popover. Mirrors the categories form's pen-icon-overlay pattern in spirit (collapsed by default; user clicks to expand). Both _form_edit and _form_stepper render the partial; the stepper's hidden color field is replaced by the visible disclosure. - Stepper footer: change `justify-between` to `flex items-center` plus `ml-auto` on the Continue wrapper. Continue now sits right-aligned in step 1 (where Back is hidden) and stays right in step 2 with Back taking the left edge. --- app/components/goals/status_pill_component.rb | 24 +++++++++-------- app/views/goals/_color_picker.html.erb | 16 ++++++++++++ app/views/goals/_form_edit.html.erb | 13 +--------- app/views/goals/_form_stepper.html.erb | 26 ++++++++++--------- app/views/goals/show.html.erb | 6 ++--- config/locales/views/goals/en.yml | 6 ++--- 6 files changed, 50 insertions(+), 41 deletions(-) create mode 100644 app/views/goals/_color_picker.html.erb diff --git a/app/components/goals/status_pill_component.rb b/app/components/goals/status_pill_component.rb index a1e9e3490..3c764e97e 100644 --- a/app/components/goals/status_pill_component.rb +++ b/app/components/goals/status_pill_component.rb @@ -1,16 +1,18 @@ class Goals::StatusPillComponent < ApplicationComponent - # Text colors here intentionally use palette steps (green-700 / yellow-700 / - # gray-700) rather than `text-success` / `text-warning` / `text-secondary` - # tokens because the functional tokens drop below WCAG 1.4.3 4.5:1 on tinted - # surfaces in light mode (~2.88:1 / 3.0:1 / 4.16:1). Local override only; - # revert once we-promise/sure#1736 lands token-level fixes. + # Text colors here intentionally use palette steps (green/yellow/gray-700) + # instead of the `text-success` / `text-warning` / `text-secondary` tokens + # because the functional tokens drop below WCAG 1.4.3 4.5:1 on tinted + # surfaces in light mode (~2.88:1 / 3.0:1 / 4.16:1). Each variant carries + # a theme-dark: override so the dark-700 text doesn't disappear against + # the dark-mode tinted surface. Local override only; revert once + # we-promise/sure#1736 lands token-level fixes. VARIANTS = { - on_track: { classes: "bg-green-500/10 text-green-700", icon: "circle-check" }, - behind: { classes: "bg-yellow-500/10 text-yellow-700", icon: "triangle-alert" }, - reached: { classes: "bg-green-500/10 text-green-700", icon: "star" }, - no_target_date: { classes: "bg-surface-inset text-gray-700", icon: "infinity" }, - paused: { classes: "bg-surface-inset text-gray-700", icon: "pause" }, - archived: { classes: "bg-surface-inset text-gray-700", icon: "archive" } + on_track: { classes: "bg-green-500/10 text-green-700 theme-dark:text-green-300", icon: "circle-check" }, + behind: { classes: "bg-yellow-500/10 text-yellow-700 theme-dark:text-yellow-300", icon: "triangle-alert" }, + reached: { classes: "bg-green-500/10 text-green-700 theme-dark:text-green-300", icon: "star" }, + no_target_date: { classes: "bg-surface-inset text-gray-700 theme-dark:text-gray-200", icon: "infinity" }, + paused: { classes: "bg-surface-inset text-gray-700 theme-dark:text-gray-200", icon: "pause" }, + archived: { classes: "bg-surface-inset text-gray-700 theme-dark:text-gray-200", icon: "archive" } }.freeze def initialize(goal:) diff --git a/app/views/goals/_color_picker.html.erb b/app/views/goals/_color_picker.html.erb new file mode 100644 index 000000000..1d8fdb684 --- /dev/null +++ b/app/views/goals/_color_picker.html.erb @@ -0,0 +1,16 @@ +<%# locals: (form:, colors:) %> +
+ + + <%= t("goals.form_stepper.step1.fields.color") %> + <%= icon("chevron-down", size: "sm") %> + +
+ <% colors.each do |c| %> + + <% end %> +
+
diff --git a/app/views/goals/_form_edit.html.erb b/app/views/goals/_form_edit.html.erb index b0cf4fa26..47bc918e5 100644 --- a/app/views/goals/_form_edit.html.erb +++ b/app/views/goals/_form_edit.html.erb @@ -50,18 +50,7 @@ -
- <%= t("goals.form_stepper.step1.fields.color") %> -
- <% Goal::COLORS.each do |c| %> - - <% end %> -
-
+ <%= render "color_picker", form: f, colors: Goal::COLORS %> <%= f.text_area :notes, label: t("goals.form_stepper.step1.fields.notes"), diff --git a/app/views/goals/_form_stepper.html.erb b/app/views/goals/_form_stepper.html.erb index f1df2e6c6..7f87a5873 100644 --- a/app/views/goals/_form_stepper.html.erb +++ b/app/views/goals/_form_stepper.html.erb @@ -104,7 +104,7 @@ placeholder: t("goals.form_stepper.step1.fields.notes_placeholder") %> <% end %> - <%= f.hidden_field :color %> + <%= render "color_picker", form: f, colors: Goal::COLORS %>
-
+
- <%= render DS::Button.new( - text: t("goals.form_stepper.continue"), - variant: "primary", - icon: "arrow-right", - icon_position: :right, - data: { - goal_stepper_target: "footerRightButton", - action: "click->goal-stepper#footerRight" - } - ) %> +
+ <%= render DS::Button.new( + text: t("goals.form_stepper.continue"), + variant: "primary", + icon: "arrow-right", + icon_position: :right, + data: { + goal_stepper_target: "footerRightButton", + action: "click->goal-stepper#footerRight" + } + ) %> +