Commit Graph

13 Commits

Author SHA1 Message Date
Guillem Arias Fauste
e07d641ead fix(design-system): DS::Button a11y audit — focus ring, touch target, type default, icon-only label (#1840)
* fix(design-system): DS::Button a11y audit

Closes #1738. Four concrete fixes surfaced by the savings-goals
audit + #1737 universal checklist:

1. Focus ring (WCAG 2.4.7). `base.css` had
   `focus-visible:outline-gray-900` which is **1.07:1** against the
   primary button's gray-900 background — invisible. Widen to
   `outline-2 outline-offset-2`, place outline outside the button
   via offset, and add a dark-mode `outline-white` so the ring is
   always visible against the page chrome regardless of the button
   surface.

2. Touch target (WCAG 2.5.5). Icon-only buttons at the default
   `:md` size were `w-9 h-9` = 36×36, below the 44×44 enhanced
   target. Bump `md.icon_container_classes` to `w-11 h-11` and
   `lg.icon_container_classes` to `w-12 h-12` to keep the size
   scale intact. `sm` stays at 32×32 (already passes WCAG 2.5.8
   AA's 24×24 minimum; intentional compact-density variant).

3. Default button type. `content_tag(:button, ...)` inherits the
   HTML default `type="submit"`, so a DS::Button rendered inside a
   form steals Enter-key submission from the first text input
   (reproducible in the form stepper). Default to `type="button"`
   in the non-`href` branch; existing form submitters pass
   `type: "submit"` explicitly and continue to work. The `button_to`
   (href) branch keeps the submit default because button_to wraps
   its own form.

4. Icon-only accessible name. Icon-only buttons render no text
   node, so AT users hear "button" with no name. Derive a
   humanized aria-label from the icon key (e.g. `icon: "more-horizontal"`
   → `aria-label="More horizontal"`); explicit
   `aria: { label: }` on the caller still wins. Soft fallback —
   callers should still pass meaningful labels for richer copy.

Plus: replace the stale `fg-white` icon class on the destructive
variant with `text-inverse` (the `fg-*` namespace was deprecated
in #1626 so `fg-white` resolved to nothing; the icon was using its
helper-default color rather than the white the design intended).

Out of scope:
- Menu avatar trigger (custom 36×36 button bypassing DS::Button) —
  belongs to #1743 DS::Menu audit.
- DS::FilledIcon `lg` size container (decorative, not interactive)
  — belongs to #1742.

* fix(design-system): force type=submit on StyledFormBuilder#submit

The DS::Button default-type-button change in the previous commit
broke every `form.submit "Log in"` callsite because
`StyledFormBuilder#submit` (app/helpers/styled_form_builder.rb)
renders a DS::Button under the hood with no explicit `type:`.

After the default flip, those submit buttons rendered as
`type="button"`, so submitting forms (login, password reset, every
form using `form.submit`) silently no-ops. CI surfaced this via
~30 system tests failing in the `sign_in` helper, which couldn't
get past the login page.

Pin `type: "submit"` on the DS::Button rendered by
`StyledFormBuilder#submit`. The 22 view-level `f.submit` /
`render DS::Button.new(type: :submit, ...)` callers already pass
type explicitly and are unaffected.

* fix(review): href-branch type-button bug + focus-ring tokens + profile Save submit

CodeRabbit P1+P2 review on #1840:

1. button.rb: `merged_opts.delete(:href)` always returned nil because
   Buttonish#initialize strips :href from opts into @href, so the
   `if href.blank?` guard was ALWAYS true. Every DS::Button rendered via
   button_to (the href branch) got `type="button"` on the inner button,
   breaking submission of those button_to-generated forms (e.g.
   imports/_ready.html.erb publish button, imports/_failure.html.erb
   try-again button). Drop the local `href = merged_opts.delete(:href)`
   so the guard now reads the @href reader, leaving the href branch's
   HTML default intact.

2. settings/profiles/show.html.erb: the Save button is rendered with
   `render DS::Button.new(...)` inside `styled_form_with` (not via
   form.submit), so the StyledFormBuilder#submit type-pin from
   624e9794 doesn't cover it. Pass `type: :submit` explicitly so the
   profile form submits again under the default-type-button policy.

3. base.css: replace raw `outline-gray-900` / `outline-white` with the
   established alpha-ring focus pattern
   (focus-visible:ring-alpha-black-300 + theme-dark:ring-alpha-white-300)
   already used by app/components/settings/provider_card.html.erb and
   sure-design-system/components.css. Keeps a11y focus ring while using
   DS tokens.

* fix(review): add type: :submit to DS::Button submitters inside forms

CI test_system on #1840 surfaced 6 failures (confirm-dialog close,
property create/edit, transaction filter apply) caused by the same
gap that db563f3d started addressing: the default-type-button policy
on DS::Button means every \`render DS::Button.new(...)\` inside a
\`<form>\` (or \`styled_form_with\`) that relies on the HTML default to
submit is now an inert \`type="button"\`.

Audited every \`render DS::Button.new(\` callsite repo-wide for the
combination (no \`type:\`, no \`href:\`, inside a form context) and
pinned \`type: :submit\` explicitly on the 12 forms that need it:

- layouts/shared/_confirm_dialog.html.erb: Confirm button inside the
  global \`<form method=\"dialog\">\` — fixes
  test_should_allow_revoking_API_key_with_confirmation.
- properties/{new,edit,balances}.html.erb: Save/Next submitter inside
  \`styled_form_with\` — fixes test_can_create_property_account,
  test_can_persist_property_subtype.
- transactions/searches/_menu.html.erb: Apply inside the filter form —
  fixes test_can_filter_uncategorized_transactions,
  test_all_filters_work_and_empty_state_shows_if_no_match,
  test_can_open_filters_and_apply_one_or_more.
- transactions/bulk_updates/new.html.erb: Save in bulk-edit drawer.
- account_sharings/show.html.erb: Save in account-sharing form.
- category/deletions/new.html.erb, tag/deletions/new.html.erb:
  destructive + safe submit buttons in deletion dialog forms.
- family_merchants/merge.html.erb: Submit in merge form.
- subscriptions/upgrade.html.erb: contribute_and_support_sure submit.
- rules/_category_rule_cta.html.erb: Dismiss inside the
  rule_prompts_disabled form.

Cancel/close DS::Button instances inside these same forms intentionally
keep the \`type=button\` default since they drive JS-only actions
(\`DS--dialog#close\`, \`DS--menu#close\`).

* fix(review): add type: :submit to 4 remaining form-context DS::Button callers

Second sweep for the same default-type-button regression that 24c517eb
fixed for 12 callsites. The latest CI run on this branch narrowed the
failures from 6 to 2 (the property wizard's Address step still failed
because that view was not in the first sweep). Audited via a wider
4000-char form-context window:

- app/views/properties/address.html.erb: Save inside
  styled_form_with — fixes the remaining
  test_can_create_property_account + test_can_persist_property_subtype
  by letting Step 3 of the property wizard complete.
- app/views/onboardings/goals.html.erb: Submit inside form_with so
  the onboarding goals step submits.
- app/views/account_sharings/show.html.erb (owner-side form): Save
  button for the family-share permissions form (the non-owner Save
  was already fixed in 24c517eb).
- app/views/transactions/_attachments.html.erb: Upload inside
  styled_form_with — kept the JS-driven hook (attachment_upload_target)
  but explicit type:submit covers the no-JS fallback.

* fix(review): pin type=submit on the Save currencies button

Codex P1 (third pass) caught one more in-form DS::Button I missed in
the earlier sweeps: \`app/views/settings/preferences/show.html.erb:185\`
renders the Save currencies submit deep inside a long
\`styled_form_with\` block. The form-context scan I used had a finite
look-back window which missed it because the matching
\`styled_form_with\` opener sits ~80 lines / 4k+ characters above the
button. Switched to a whole-file scan to confirm no further callsite
remains.
2026-05-20 18:12:36 +02:00
Brendon Scheiber
7411db5689 feat(i18n): add Hungarian translations for strings extracted in #1806 (#1817)
* add missing Hungarian translations for newly extracted strings

Replace hard-coded UI strings with I18n lookups across controllers, models and views (breadcrumbs, dashboard, reports, settings, transactions, balance sheet, MFA status). Update models to use translations for category defaults, account/display names, classification group and period labels; remove a few hardcoded display_name methods. Add and update numerous locale files (English and extensive Hungarian translations, plus model/view/doorkeeper entries) to provide the required keys. These changes centralize copy for localization and prepare the app for Hungarian/English UI text.

* Pluralize account type labels; tidy Crypto model

Update English locale account type labels to use plural forms for consistency (Investment(s), Properties, Vehicles, Other Assets, Credit Cards, Loans, Other Liabilities). Also remove an extra blank line in app/models/crypto.rb to tidy up formatting.

* Back to singular

* fix(i18n): separate singular and group account labels

* Update _accountable_group.html.erb

* Use I18n plural names for account types

Change Accountable#display_name to look up pluralized account type names via I18n (accounts.types_plural.<underscored_class>) with a fallback to the legacy display logic. Add legacy_display_name helper to preserve previous behavior (singular for Depository and Crypto, pluralized otherwise). Add corresponding types_plural entries in English and Hungarian locale files for various account types.

---------

Co-authored-by: Juan José Mata <jjmata@jjmata.com>
Co-authored-by: sure-admin <sure-admin@splashblot.com>
2026-05-18 20:49:28 +02:00
maverick
ee352dada4 Added ability to bulk-edit transaction names for multiple selected transactions (#1553)
* Added ability to bulk-edit transaction names for multiple selected transactions.

* Added ability to bulk-edit transaction names for multiple selected transactions.

* Added ability to bulk-edit transaction names for multiple selected transactions.

* Lint, minimize changes

---------

Co-authored-by: Juan José Mata <jjmata@jjmata.com>
2026-04-29 18:35:00 +02:00
soky srm
9410e5b38d Providers sharing (#1273)
* third party provider scoping

* Simplify logic and allow only admins to mange providers

* Broadcast fixes

* FIX tests and build

* Fixes

* Reviews

* Scope merchants

* DRY fixes
2026-03-25 17:47:04 +01:00
Ang Wei Feng (Ted)
c77971ea0d fix: Preserve tags on bulk edits (take 3) (#889)
* fix: handle tags separately from entryable_attributes in bulk updates

Tags use a join table (taggings) rather than a direct column, which means
empty tag_ids clears all tags rather than meaning "no change". This caused
bulk category-only edits to accidentally clear existing tags.

This fix:
- Removes tag_ids from entryable_attributes in Entry.bulk_update!
- Adds update_tags parameter to explicitly control tag updates
- Uses params.key?(:tag_ids) in controller to detect explicit tag changes
- Preserves existing tags when tag_ids is not provided in the request

This is a cleaner architectural solution compared to tracking "touched"
state in the frontend, as it properly acknowledges the semantic difference
between column attributes and join table associations.

https://claude.ai/code/session_014CsmTwjteP4qJs6YZqCKnY

* fix: handle tags separately in API transaction updates

Apply the same pattern to the API endpoint: tags are now handled
separately from entryable_attributes to distinguish between "not
provided" (preserve existing tags) and "explicitly set to empty"
(clear all tags).

This allows API consumers to:
- Update other fields without affecting tags (omit tag_ids)
- Clear all tags (send tag_ids: [])
- Set specific tags (send tag_ids: [id1, id2])

https://claude.ai/code/session_014CsmTwjteP4qJs6YZqCKnY

* Proposed fix

* fix: improve tag handling in bulk updates for transactions

* fix: allow bulk edit to clear/preserve tags by omitting hidden multi-select field

* PR comments

* Dumb copy/paste error

* Linter

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Juan José Mata <juanjo.mata@gmail.com>
Co-authored-by: Juan José Mata <jjmata@jjmata.com>
2026-02-06 14:11:46 +01:00
Number Eight
408bdd6788 fix: transaction UI padding and mobile selection bar position (#847)
* style: adjust the bottom position of the transaction selection bar and remove unnecessary padding from transaction forms

* fix: prevent overlap with the navbar in PWA mode

* fix: prevent selection bar overlap with navbar in PWA mode

* Update _selection_bar.html.erb

Signed-off-by: Number Eight <55629655+CylonN8@users.noreply.github.com>

* Update _selection_bar.html.erb

Signed-off-by: Number Eight <55629655+CylonN8@users.noreply.github.com>

---------

Signed-off-by: Number Eight <55629655+CylonN8@users.noreply.github.com>
2026-02-01 23:50:39 +01:00
Alessio Cappa
27fdfca595 fix: remove fixed height on tags field in bulk update (#778) 2026-01-25 18:31:57 +01:00
soky srm
76dc91377c Merchants improvements (#594)
* FIX logos

* Implement merchant mods

* FIX confirm issue

* FIX linter

* Add recently seen merchants to re-add if needed

* Update merge.html.erb

* FIX do security check

* Add error handling for update failures.
2026-01-09 19:38:04 +01:00
ByteBard
b7d9c89471 Correct Dialog Close Button (#85)
* correct dialog#close -> DS--dialog#close

* additional ds-- add

* stop reload on close

* Added option for reload_on_close var

* Fix test to allow query param in redirect URL
2025-08-08 02:05:03 +03:00
Zach Gollwitzer
ab6fdbbb68 Component namespacing (#2463)
* [claudesquad] update from 'component-namespacing' on 18 Jul 25 07:23 EDT

* [claudesquad] update from 'component-namespacing' on 18 Jul 25 07:30 EDT

* Update stimulus controller references to use namespace

* Fix remaining tests
2025-07-18 08:30:00 -04:00
Zach Gollwitzer
0fdeebceb1 Fix bulk edit dialog form structure 2025-05-06 11:53:12 -04:00
Zach Gollwitzer
90a9546f32 Pre-launch design sync with Figma spec (#2154)
* Add lookbook + viewcomponent, organize design system file

* Build menu component

* Button updates

* More button fixes

* Replace all menus with new ViewComponent

* Checkpoint: fix tests, all buttons and menus converted

* Split into Link and Button components for clarity

* Button cleanup

* Simplify custom confirmation configuration in views

* Finalize button, link component API

* Add toggle field to custom form builder + Component

* Basic tabs component

* Custom tabs, convert all menu / tab instances in app

* Gem updates

* Centralized icon helper

* Update all icon usage to central helper

* Lint fixes

* Centralize all disclosure instances

* Dialog replacements

* Consolidation of all dialog styles

* Test fixes

* Fix app layout issues, move to component with slots

* Layout simplification

* Flakey test fix

* Fix dashboard mobile issues

* Finalize homepage

* Lint fixes

* Fix shadows and borders in dark mode

* Fix tests

* Remove stale class

* Fix filled icon logic

* Move transparent? to public interface
2025-04-30 18:14:22 -04:00
Zach Gollwitzer
e657c40d19 Account:: namespace simplifications and cleanup (#2110)
* Flatten Holding model

* Flatten balance model

* Entries domain renames

* Fix valuations reference

* Fix trades stream

* Fix brakeman warnings

* Fix tests

* Replace existing entryable type references in DB
2025-04-14 11:40:34 -04:00