From 88a6373e849838ecca8fa15fb0683e0fd1038216 Mon Sep 17 00:00:00 2001 From: Josh Pigford Date: Fri, 11 Apr 2025 09:28:00 -0500 Subject: [PATCH] Implement dark mode (#2078) * User theme settings * Initial rough pass on colors * More progress on dark mode --- .cursor/rules/ui-ux-design-guidelines.mdc | 2 +- app/assets/tailwind/maybe-design-system.css | 333 +++++++++++++++++- app/controllers/users_controller.rb | 2 +- app/helpers/forms_helper.rb | 4 +- app/helpers/menus_helper.rb | 2 +- .../controllers/theme_controller.js | 73 ++++ .../account/entries/_entry_group.html.erb | 4 +- app/views/account/entries/_loading.html.erb | 2 +- app/views/account/holdings/index.html.erb | 6 +- app/views/account/transactions/_form.html.erb | 2 +- .../account/transactions/bulk_edit.html.erb | 2 +- app/views/account/valuations/index.html.erb | 6 +- .../accounts/_account_sidebar_tabs.html.erb | 2 +- .../accounts/_accountable_group.html.erb | 6 +- app/views/accounts/_summary_card.html.erb | 2 +- app/views/accounts/index/_account_groups.erb | 4 +- .../accounts/index/_manual_accounts.html.erb | 2 +- app/views/accounts/show/_activity.html.erb | 10 +- app/views/accounts/show/_chart.html.erb | 2 +- app/views/accounts/show/_menu.html.erb | 2 +- app/views/accounts/show/_tab.html.erb | 2 +- .../_budget_category.html.erb | 2 +- app/views/budget_categories/index.html.erb | 2 +- app/views/budgets/_budget_categories.html.erb | 2 +- app/views/budgets/_budget_nav.html.erb | 4 +- app/views/budgets/_picker.html.erb | 2 +- app/views/budgets/show.html.erb | 14 +- app/views/categories/_category.html.erb | 4 +- .../categories/_category_list_group.html.erb | 4 +- app/views/categories/_form.html.erb | 2 +- app/views/categories/_menu.html.erb | 2 +- app/views/categories/_ruler.html.erb | 2 +- app/views/categories/index.html.erb | 2 +- app/views/category/deletions/new.html.erb | 4 +- app/views/category/dropdowns/_row.html.erb | 2 +- app/views/category/dropdowns/show.html.erb | 2 +- app/views/chats/_ai_consent.html.erb | 8 +- app/views/chats/_ai_greeting.html.erb | 2 +- app/views/chats/edit.html.erb | 2 +- app/views/chats/index.html.erb | 6 +- app/views/import/cleans/show.html.erb | 14 +- app/views/import/confirms/_mappings.html.erb | 4 +- app/views/import/uploads/show.html.erb | 6 +- app/views/imports/_import.html.erb | 2 +- app/views/imports/_nav.html.erb | 4 +- app/views/imports/_ready.html.erb | 6 +- app/views/imports/_table.html.erb | 6 +- app/views/imports/index.html.erb | 6 +- app/views/imports/new.html.erb | 4 +- app/views/invite_codes/index.html.erb | 2 +- app/views/layouts/application.html.erb | 6 +- app/views/layouts/auth.html.erb | 2 +- app/views/layouts/imports.html.erb | 2 +- app/views/layouts/settings.html.erb | 2 +- .../layouts/shared/_breadcrumbs.html.erb | 6 +- app/views/layouts/shared/_htmldoc.html.erb | 2 +- .../layouts/shared/_page_header.html.erb | 2 +- app/views/layouts/sidebar/_nav_item.html.erb | 4 +- app/views/merchants/_merchant.html.erb | 4 +- app/views/merchants/_ruler.html.erb | 2 +- app/views/merchants/index.html.erb | 6 +- app/views/messages/_chat_form.html.erb | 4 +- app/views/onboardings/preferences.html.erb | 2 +- app/views/onboardings/profile.html.erb | 4 +- app/views/pages/changelog.html.erb | 2 +- app/views/pages/dashboard.html.erb | 4 +- .../pages/dashboard/_balance_sheet.html.erb | 6 +- app/views/pages/early_access.html.erb | 4 +- app/views/pages/feedback.html.erb | 2 +- app/views/plaid_items/_plaid_item.html.erb | 4 +- app/views/settings/_section.html.erb | 2 +- .../settings/_settings_nav_item.html.erb | 2 +- .../_settings_nav_link_large.html.erb | 2 +- app/views/settings/billings/show.html.erb | 2 +- app/views/settings/preferences/show.html.erb | 8 +- app/views/settings/profiles/show.html.erb | 8 +- app/views/settings/securities/show.html.erb | 2 +- app/views/shared/_app_version.html.erb | 2 +- app/views/shared/_drawer.html.erb | 2 +- app/views/shared/_modal.html.erb | 2 +- app/views/shared/_notification.html.erb | 4 +- app/views/shared/_pagination.html.erb | 20 +- app/views/shared/_subscribe_modal.html.erb | 4 +- app/views/shared/_syncing_notice.html.erb | 2 +- app/views/tag/deletions/new.html.erb | 4 +- app/views/tags/_ruler.html.erb | 2 +- app/views/tags/_tag.html.erb | 4 +- app/views/tags/index.html.erb | 6 +- app/views/transactions/_summary.html.erb | 2 +- app/views/transactions/index.html.erb | 4 +- .../transactions/searches/_form.html.erb | 2 +- .../transactions/searches/_menu.html.erb | 10 +- app/views/transfers/_form.html.erb | 2 +- .../user_messages/_user_message.html.erb | 2 +- app/views/users/_user_menu.html.erb | 2 +- config/locales/views/settings/en.yml | 2 +- .../20250410144939_add_theme_to_users.rb | 5 + db/schema.rb | 5 +- 98 files changed, 580 insertions(+), 196 deletions(-) create mode 100644 app/javascript/controllers/theme_controller.js create mode 100644 db/migrate/20250410144939_add_theme_to_users.rb diff --git a/.cursor/rules/ui-ux-design-guidelines.mdc b/.cursor/rules/ui-ux-design-guidelines.mdc index 430959d6..49bf9faf 100644 --- a/.cursor/rules/ui-ux-design-guidelines.mdc +++ b/.cursor/rules/ui-ux-design-guidelines.mdc @@ -15,7 +15,7 @@ The codebase uses TailwindCSS v4.x (the newest version) with a custom design sys - Always start by referencing [maybe-design-system.css](mdc:app/assets/tailwind/maybe-design-system.css) to see the base primitives, functional tokens, and component tokens we use in the codebase - Always prefer using the functional "tokens" defined in @maybe-design-system.css when possible. - - Example 1: use `text-primary` rather than `text-gray-900` + - Example 1: use `text-primary` rather than `text-primary` - Example 2: use `bg-container` rather than `bg-white` - Example 3: use `border border-primary` rather than `border border-gray-200` - Never create new styles in [maybe-design-system.css](mdc:app/assets/tailwind/maybe-design-system.css) or [application.css](mdc:app/assets/tailwind/application.css) without explicitly receiving permission to do so diff --git a/app/assets/tailwind/maybe-design-system.css b/app/assets/tailwind/maybe-design-system.css index ca4f1bbe..61a3de14 100644 --- a/app/assets/tailwind/maybe-design-system.css +++ b/app/assets/tailwind/maybe-design-system.css @@ -5,6 +5,8 @@ One-off styling (3rd party overrides, etc.) should be done in the application.css file. */ +@custom-variant theme-dark (&:where([data-theme=dark], [data-theme=dark] *)); + @theme { /* Font families */ --font-sans: 'Geist', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; @@ -241,78 +243,235 @@ /* Design system color utilities */ @utility text-primary { @apply text-gray-900; + + @variant theme-dark { + @apply text-white; + } } @utility text-secondary { @apply text-gray-500; + + @variant theme-dark { + @apply text-gray-400; + } } @utility text-subdued { @apply text-gray-400; + + @variant theme-dark { + @apply text-gray-600; + } } @utility text-link { @apply text-blue-600; + + @variant theme-dark { + @apply text-blue-500; + } } @utility bg-surface { @apply bg-gray-50; + + @variant theme-dark { + @apply bg-black; + } } @utility bg-surface-hover { @apply bg-gray-100; + + @variant theme-dark { + @apply bg-gray-800; + } } @utility bg-surface-inset { @apply bg-gray-100; + + @variant theme-dark { + @apply bg-gray-900; + } } @utility bg-surface-inset-hover { @apply bg-gray-200; + + @variant theme-dark { + @apply bg-gray-800; + } } @utility bg-container { @apply bg-white; + + @variant theme-dark { + @apply bg-gray-900; + } } @utility bg-container-hover { @apply bg-gray-50; + + @variant theme-dark { + @apply bg-gray-800; + } } @utility bg-container-inset { @apply bg-gray-50; + + @variant theme-dark { + @apply bg-gray-800; + } } @utility bg-container-inset-hover { @apply bg-gray-100; + + @variant theme-dark { + @apply bg-gray-700; + } } @utility bg-inverse { @apply bg-gray-800; + + @variant theme-dark { + @apply bg-white; + } } @utility bg-inverse-hover { @apply bg-gray-700; + + @variant theme-dark { + @apply bg-gray-100; + } } @utility bg-overlay { - @apply bg-alpha-black-200; + background-color: rgba(var(--color-gray-100), 0.5); + + @variant theme-dark { + background-color: var(--color-alpha-black-900); + } } @utility border-primary { @apply border-alpha-black-300; + + @variant theme-dark { + @apply border-alpha-white-400; + } } @utility border-secondary { @apply border-alpha-black-200; + + @variant theme-dark { + @apply border-alpha-white-300; + } } @utility border-tertiary { @apply border-alpha-black-100; + + @variant theme-dark { + @apply border-alpha-white-200; + } } @utility border-subdued { @apply border-alpha-black-50; + + @variant theme-dark { + @apply border-alpha-white-100; + } +} + +@utility border-solid { + @apply border-black; + + @variant theme-dark { + @apply border-white; + } +} + +@utility border-destructive { + @apply border-red-500; + + @variant theme-dark { + @apply border-red-400; + } +} + +/* Foreground Colors */ +@utility fg-gray { + @apply text-gray-500; + + @variant theme-dark { + @apply text-gray-400; + } +} + +@utility fg-contrast { + @apply text-gray-400; + + @variant theme-dark { + @apply text-gray-500; + } +} + +@utility fg-inverse { + @apply text-white; + + @variant theme-dark { + @apply text-gray-900; + } +} + +@utility fg-primary { + @apply text-gray-900; + + @variant theme-dark { + @apply text-white; + } +} + +@utility fg-primary-variant { + @apply text-gray-800; + + @variant theme-dark { + @apply text-gray-50; + } +} + +@utility fg-secondary { + @apply text-gray-50; + + @variant theme-dark { + @apply text-gray-700; + } +} + +@utility fg-secondary-variant { + @apply text-gray-100; + + @variant theme-dark { + @apply text-gray-600; + } +} + +@utility fg-subdued { + @apply text-gray-400; + + @variant theme-dark { + @apply text-gray-500; + } } @layer base { @@ -331,6 +490,15 @@ details>summary { @apply list-none; } + + input[type='radio'] { + @apply border-gray-300 text-indigo-600 focus:ring-indigo-600; /* Default light mode */ + + @variant theme-dark { + /* Dark mode radio button base and checked styles */ + @apply border-gray-600 bg-gray-700 checked:bg-blue-500 focus:ring-blue-500 focus:ring-offset-gray-800; + } + } } @layer components { @@ -341,31 +509,63 @@ } .btn--primary { - @apply bg-gray-900 text-white hover:bg-gray-700 disabled:bg-gray-50 disabled:hover:bg-gray-50 disabled:text-gray-400; + @apply button-bg-primary text-white disabled:text-gray-400; + @apply hover:button-bg-primary-hover; + @apply disabled:button-bg-disabled disabled:hover:button-bg-disabled; + + @variant theme-dark { + @apply button-bg-primary fg-primary; + @apply hover:button-bg-primary-hover; + @apply disabled:button-bg-disabled disabled:hover:button-bg-disabled; + } } .btn--secondary { - @apply bg-gray-50 hover:bg-gray-100 text-gray-900; + @apply button-bg-secondary text-primary; + @apply hover:button-bg-secondary-hover; + + @variant theme-dark { + @apply button-bg-secondary text-white; + @apply hover:button-bg-secondary-hover; + } } .btn--outline { - @apply border border-alpha-black-200 text-gray-900 hover:bg-gray-50 disabled:bg-gray-50 disabled:hover:bg-gray-50 disabled:text-gray-400; + @apply border border-alpha-black-200 text-primary disabled:button-bg-disabled disabled:hover:button-bg-disabled disabled:text-gray-400; + @apply hover:button-bg-outline-hover; + + @variant theme-dark { + @apply border-alpha-white-300 text-white disabled:button-bg-disabled disabled:hover:button-bg-disabled disabled:text-gray-600; + @apply hover:button-bg-outline-hover; + } } .btn--ghost { - @apply border border-transparent text-gray-900 hover:bg-gray-100; + @apply border border-transparent text-primary hover:button-bg-ghost-hover; + + @variant theme-dark { + @apply fg-primary hover:button-bg-ghost-hover; + } } .btn--destructive { - @apply bg-red-500 text-white hover:bg-red-600 disabled:bg-red-50 disabled:hover:bg-red-50 disabled:text-red-400; + @apply button-bg-destructive text-white hover:button-bg-destructive-hover disabled:button-bg-disabled disabled:hover:button-bg-disabled disabled:text-red-400; + + @variant theme-dark { + @apply button-bg-destructive text-white hover:button-bg-destructive-hover disabled:button-bg-disabled disabled:hover:button-bg-disabled; + } } /* Forms */ .form-field { - @apply flex flex-col gap-1 relative px-3 py-2 rounded-md border bg-white border-alpha-black-100 shadow-xs w-full; - @apply focus-within:border-gray-900 focus-within:shadow-none focus-within:ring-4 focus-within:ring-gray-100; + @apply flex flex-col gap-1 relative px-3 py-2 rounded-md border bg-container border-secondary shadow-xs w-full; + @apply focus-within:border-secondary focus-within:shadow-none focus-within:ring-4 focus-within:ring-alpha-black-200; @apply transition-all duration-300; + @variant theme-dark { + @apply focus-within:ring-alpha-white-300; + } + /* Add styles for multiple select within form fields */ select[multiple] { @apply py-2 pr-2 space-y-0.5 overflow-y-auto; @@ -375,25 +575,25 @@ } option:checked { - @apply after:content-['\2713'] bg-white after:text-gray-500 after:ml-2; + @apply after:content-['\2713'] bg-container-inset after:text-gray-500 after:ml-2; } option:active, option:focus { - @apply bg-white; + @apply bg-container-inset; } } } .form-field__label { - @apply block text-xs text-gray-500 peer-disabled:text-gray-400; + @apply block text-xs text-secondary peer-disabled:text-subdued; } .form-field__input { @apply border-none bg-transparent text-sm opacity-100 w-full p-0; @apply focus:opacity-100 focus:outline-hidden focus:ring-0; @apply placeholder-shown:opacity-50; - @apply disabled:text-gray-400; + @apply disabled:text-subdued; @apply text-ellipsis overflow-hidden whitespace-nowrap; @apply transition-opacity duration-300; @@ -403,11 +603,11 @@ } .form-field__radio { - @apply text-gray-900; + @apply text-primary; } .form-field__submit { - @apply cursor-pointer rounded-lg bg-black p-3 text-center text-white hover:bg-gray-700; + @apply cursor-pointer rounded-lg bg-surface p-3 text-center text-white hover:bg-surface-hover; } /* Checkboxes */ @@ -455,4 +655,109 @@ .tooltip { @apply hidden absolute; } +} + +@layer utilities { + /* Specific override for strong tags in prose under dark mode */ + .prose:where([data-theme=dark], [data-theme=dark] *) strong { + color: theme(colors.white) !important; + } +} + +/* Button Backgrounds */ +@utility button-bg-primary { + @apply bg-gray-900; /* Maps to fg-primary light */ + + @variant theme-dark { + @apply bg-white; /* Maps to fg-primary dark */ + } +} + +@utility button-bg-primary-hover { + @apply bg-gray-800; /* Maps to fg-primary-variant light */ + + @variant theme-dark { + @apply bg-gray-50; /* Maps to fg-primary-variant dark */ + } +} + +@utility button-bg-secondary { + @apply bg-gray-50; /* Maps to fg-secondary light */ + + @variant theme-dark { + @apply bg-gray-700; /* Maps to fg-secondary dark */ + } +} + +@utility button-bg-secondary-hover { + @apply bg-gray-100; /* Maps to fg-secondary-variant light */ + + @variant theme-dark { + @apply bg-gray-600; /* Maps to fg-secondary-variant dark */ + } +} + +@utility button-bg-disabled { + @apply bg-gray-50; + + @variant theme-dark { + @apply bg-gray-700; + } +} + +@utility button-bg-destructive { + @apply bg-red-500; + + @variant theme-dark { + @apply bg-red-400; + } +} + +@utility button-bg-destructive-hover { + @apply bg-red-600; + + @variant theme-dark { + @apply bg-red-500; + } +} + +@utility button-bg-ghost-hover { + @apply bg-gray-50; + + @variant theme-dark { + @apply bg-gray-800; + } +} + +@utility button-bg-outline-hover { + @apply bg-gray-100; + + @variant theme-dark { + @apply bg-gray-700; + } +} + +/* Tab Styles */ +@utility tab-item-active { + @apply bg-white; + + @variant theme-dark { + @apply bg-gray-700; + } +} + +@utility tab-item-hover { + @apply bg-gray-200; + + @variant theme-dark { + @apply bg-gray-800; + } +} + +@utility tab-bg-group { + @apply bg-gray-50; + + @variant theme-dark { + @apply bg-alpha-black-700; + } } \ No newline at end of file diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 2b146864..6cfefaec 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -74,7 +74,7 @@ class UsersController < ApplicationController def user_params params.require(:user).permit( - :first_name, :last_name, :email, :profile_image, :redirect_to, :delete_profile_image, :onboarded_at, :show_sidebar, :default_period, :show_ai_sidebar, :ai_enabled, + :first_name, :last_name, :email, :profile_image, :redirect_to, :delete_profile_image, :onboarded_at, :show_sidebar, :default_period, :show_ai_sidebar, :ai_enabled, :theme, family_attributes: [ :name, :currency, :country, :locale, :date_format, :timezone, :id, :data_enrichment_enabled ] ) end diff --git a/app/helpers/forms_helper.rb b/app/helpers/forms_helper.rb index 55c8c74c..d2f6cb04 100644 --- a/app/helpers/forms_helper.rb +++ b/app/helpers/forms_helper.rb @@ -17,7 +17,7 @@ module FormsHelper end end - def period_select(form:, selected:, classes: "border border-secondary rounded-lg text-sm pr-7 cursor-pointer text-primary focus:outline-hidden focus:ring-0") + def period_select(form:, selected:, classes: "border border-secondary bg-container-inset rounded-lg text-sm pr-7 cursor-pointer text-primary focus:outline-hidden focus:ring-0") periods_for_select = Period.all.map { |period| [ period.label_short, period.key ] } form.select(:period, periods_for_select, { selected: selected.key }, class: classes, data: { "auto-submit-form-target": "auto" }) @@ -30,7 +30,7 @@ end private def radio_tab_contents(label:, icon:) - tag.div(class: "flex px-4 py-1 rounded-lg items-center space-x-2 justify-center text-subdued group-has-checked:bg-white group-has-checked:text-gray-800 group-has-checked:shadow-sm") do + tag.div(class: "flex px-4 py-1 rounded-lg items-center space-x-2 justify-center text-subdued group-has-checked:bg-container group-has-checked:text-gray-800 group-has-checked:shadow-sm") do concat lucide_icon(icon, class: "w-5 h-5") concat tag.span(label, class: "group-has-checked:font-semibold") end diff --git a/app/helpers/menus_helper.rb b/app/helpers/menus_helper.rb index f903d8ec..34134888 100644 --- a/app/helpers/menus_helper.rb +++ b/app/helpers/menus_helper.rb @@ -38,7 +38,7 @@ module MenusHelper end def contextual_menu_content(&block) - tag.div class: "min-w-[200px] p-1 z-50 shadow-border-xs bg-white rounded-lg hidden", + tag.div class: "min-w-[200px] p-1 z-50 shadow-border-xs bg-container rounded-lg hidden", data: { menu_target: "content" } do capture(&block) end diff --git a/app/javascript/controllers/theme_controller.js b/app/javascript/controllers/theme_controller.js new file mode 100644 index 00000000..d01edf7f --- /dev/null +++ b/app/javascript/controllers/theme_controller.js @@ -0,0 +1,73 @@ +import { Controller } from "@hotwired/stimulus" + +export default class extends Controller { + static values = { userPreference: String } + + connect() { + this.applyTheme() + this.startSystemThemeListener() + } + + disconnect() { + this.stopSystemThemeListener() + } + + // Called automatically by Stimulus when the userPreferenceValue changes (e.g., after form submit/page reload) + userPreferenceValueChanged() { + this.applyTheme() + } + + // Called when a theme radio button is clicked + updateTheme(event) { + const selectedTheme = event.currentTarget.value + if (selectedTheme === "system") { + this.setTheme(this.systemPrefersDark()) + } else if (selectedTheme === "dark") { + this.setTheme(true) + } else { + this.setTheme(false) + } + } + + // Applies theme based on the userPreferenceValue (from server) + applyTheme() { + if (this.userPreferenceValue === "system") { + this.setTheme(this.systemPrefersDark()) + } else if (this.userPreferenceValue === "dark") { + this.setTheme(true) + } else { + this.setTheme(false) + } + } + + // Sets or removes the data-theme attribute + setTheme(isDark) { + if (isDark) { + document.documentElement.setAttribute("data-theme", "dark") + } else { + document.documentElement.removeAttribute("data-theme") + } + } + + systemPrefersDark() { + return window.matchMedia("(prefers-color-scheme: dark)").matches + } + + handleSystemThemeChange = (event) => { + // Only apply system theme changes if the user preference is currently 'system' + if (this.userPreferenceValue === "system") { + this.setTheme(event.matches) + } + } + + startSystemThemeListener() { + this.darkMediaQuery = window.matchMedia("(prefers-color-scheme: dark)") + this.darkMediaQuery.addEventListener("change", this.handleSystemThemeChange) + } + + stopSystemThemeListener() { + if (this.darkMediaQuery) { + this.darkMediaQuery.removeEventListener("change", this.handleSystemThemeChange) + } + } +} \ No newline at end of file diff --git a/app/views/account/entries/_entry_group.html.erb b/app/views/account/entries/_entry_group.html.erb index 7a08bcf7..36aeb27a 100644 --- a/app/views/account/entries/_entry_group.html.erb +++ b/app/views/account/entries/_entry_group.html.erb @@ -1,6 +1,6 @@ <%# locals: (date:, entries:, content:, totals: false) %> -
+
<%= check_box_tag "#{date}_entries_selection", @@ -21,7 +21,7 @@
<% end %>
-
+
<%= content %>
diff --git a/app/views/account/entries/_loading.html.erb b/app/views/account/entries/_loading.html.erb index e5496bb7..cb9276b5 100644 --- a/app/views/account/entries/_loading.html.erb +++ b/app/views/account/entries/_loading.html.erb @@ -1,4 +1,4 @@ -
+
<%= tag.p t(".loading"), class: "text-secondary animate-pulse text-sm" %>
diff --git a/app/views/account/holdings/index.html.erb b/app/views/account/holdings/index.html.erb index 6b80ab59..5afacc32 100644 --- a/app/views/account/holdings/index.html.erb +++ b/app/views/account/holdings/index.html.erb @@ -1,5 +1,5 @@ <%= turbo_frame_tag dom_id(@account, "holdings") do %> -
+
<%= tag.h2 t(".holdings"), class: "font-medium text-lg" %> <%= link_to new_account_trade_path(account_id: @account.id), @@ -11,7 +11,7 @@ <% end %>
-
+
<%= tag.p t(".name"), class: "col-span-4" %> <%= tag.p t(".weight"), class: "col-span-2 justify-self-end" %> @@ -20,7 +20,7 @@ <%= tag.p t(".return"), class: "col-span-2 justify-self-end" %>
-
+
<%= render "account/holdings/cash", account: @account %> <%= render "account/holdings/ruler" %> diff --git a/app/views/account/transactions/_form.html.erb b/app/views/account/transactions/_form.html.erb index 8ca19c39..fd8d404c 100644 --- a/app/views/account/transactions/_form.html.erb +++ b/app/views/account/transactions/_form.html.erb @@ -8,7 +8,7 @@
<%= radio_tab_tag form: f, name: :nature, value: :outflow, label: t(".expense"), icon: "minus-circle", checked: params[:nature] == "outflow" || params[:nature].nil? %> <%= radio_tab_tag form: f, name: :nature, value: :inflow, label: t(".income"), icon: "plus-circle", checked: params[:nature] == "inflow" %> - <%= link_to new_transfer_path, data: { turbo_frame: :modal }, class: "flex px-4 py-1 rounded-lg items-center space-x-2 justify-center text-subdued group-has-checked:bg-white group-has-checked:text-gray-800 group-has-checked:shadow-sm" do %> + <%= link_to new_transfer_path, data: { turbo_frame: :modal }, class: "flex px-4 py-1 rounded-lg items-center space-x-2 justify-center text-subdued group-has-checked:bg-container group-has-checked:text-gray-800 group-has-checked:shadow-sm" do %> <%= lucide_icon "arrow-right-left", class: "w-5 h-5" %> <%= tag.span t(".transfer") %> <% end %> diff --git a/app/views/account/transactions/bulk_edit.html.erb b/app/views/account/transactions/bulk_edit.html.erb index ed9a6194..c42faf50 100644 --- a/app/views/account/transactions/bulk_edit.html.erb +++ b/app/views/account/transactions/bulk_edit.html.erb @@ -1,7 +1,7 @@ <%= turbo_frame_tag "bulk_transaction_edit_drawer" do %> + class="bg-container shadow-border-xs rounded-2xl max-h-[calc(100vh-32px)] h-full max-w-[480px] w-full mt-4 mr-4 ml-auto"> <%= styled_form_with url: bulk_update_account_transactions_path, scope: "bulk_update", class: "h-full", data: { turbo_frame: "_top" } do |form| %>
diff --git a/app/views/account/valuations/index.html.erb b/app/views/account/valuations/index.html.erb index 0d859559..1100431c 100644 --- a/app/views/account/valuations/index.html.erb +++ b/app/views/account/valuations/index.html.erb @@ -1,5 +1,5 @@ <%= turbo_frame_tag dom_id(@account, "valuations") do %> -
+
<%= tag.h2 t(".valuations"), class: "font-medium text-lg" %> <%= link_to new_account_valuation_path(@account), @@ -10,7 +10,7 @@ <% end %>
-
+
<%= tag.p t(".date"), class: "col-span-5" %> <%= tag.p t(".value"), class: "col-span-2 justify-self-end" %> @@ -18,7 +18,7 @@ <%= tag.div class: "col-span-1" %>
-
+
<%= turbo_frame_tag dom_id(@account.entries.account_valuations.new) %> <% if @entries.any? %> diff --git a/app/views/accounts/_account_sidebar_tabs.html.erb b/app/views/accounts/_account_sidebar_tabs.html.erb index 764ca6af..49d6ebaf 100644 --- a/app/views/accounts/_account_sidebar_tabs.html.erb +++ b/app/views/accounts/_account_sidebar_tabs.html.erb @@ -24,7 +24,7 @@ class="space-y-3" data-controller="tabs" data-tabs-local-storage-key-value="account-sidebar-tabs" - data-tabs-active-class="bg-white shadow-sm text-primary" + data-tabs-active-class="bg-surface shadow-sm text-primary" data-tabs-inactive-class="text-secondary" data-tabs-default-tab-value="assets-tab">
diff --git a/app/views/accounts/_accountable_group.html.erb b/app/views/accounts/_accountable_group.html.erb index b240a557..b9676a9a 100644 --- a/app/views/accounts/_accountable_group.html.erb +++ b/app/views/accounts/_accountable_group.html.erb @@ -11,7 +11,7 @@ <%= turbo_frame_tag "#{account_group.key}_sparkline", src: accountable_sparkline_path(account_group.key), loading: "lazy" do %>
-
+
<% end %>
@@ -23,7 +23,7 @@ <%= render "accounts/logo", account: account, size: "sm", color: account_group.color %>
- <%= tag.p account.name, class: "text-sm font-medium mb-0.5 truncate" %> + <%= tag.p account.name, class: "text-sm text-primary font-medium mb-0.5 truncate" %> <%= tag.p account.subtype&.humanize.presence || account_group.name, class: "text-sm text-secondary truncate" %>
@@ -32,7 +32,7 @@ <%= turbo_frame_tag dom_id(account, :sparkline), src: sparkline_account_path(account), loading: "lazy" do %>
-
+
<% end %>
diff --git a/app/views/accounts/_summary_card.html.erb b/app/views/accounts/_summary_card.html.erb index 384c1c8e..fe327728 100644 --- a/app/views/accounts/_summary_card.html.erb +++ b/app/views/accounts/_summary_card.html.erb @@ -1,6 +1,6 @@ <%# locals: (title:, content:) %> -
+

<%= title %>

<%= content %> diff --git a/app/views/accounts/index/_account_groups.erb b/app/views/accounts/index/_account_groups.erb index a5665690..6347339c 100644 --- a/app/views/accounts/index/_account_groups.erb +++ b/app/views/accounts/index/_account_groups.erb @@ -1,14 +1,14 @@ <%# locals: (accounts:) %> <% accounts.group_by(&:accountable_type).sort_by { |group, _| group }.each do |group, accounts| %> -

+

<%= Accountable.from_type(group).display_name %>

·

<%= accounts.count %>

<%= totals_by_currency(collection: accounts, money_method: :balance_money) %>

-
+
<% accounts.each do |account| %> <%= render account %> <% end %> diff --git a/app/views/accounts/index/_manual_accounts.html.erb b/app/views/accounts/index/_manual_accounts.html.erb index 9f3d34ed..b20c400e 100644 --- a/app/views/accounts/index/_manual_accounts.html.erb +++ b/app/views/accounts/index/_manual_accounts.html.erb @@ -1,6 +1,6 @@ <%# locals: (accounts:) %> -
+
<%= lucide_icon "chevron-right", class: "group-open:transform group-open:rotate-90 text-secondary w-5" %> diff --git a/app/views/accounts/show/_activity.html.erb b/app/views/accounts/show/_activity.html.erb index e882e4c6..88d9f78c 100644 --- a/app/views/accounts/show/_activity.html.erb +++ b/app/views/accounts/show/_activity.html.erb @@ -1,7 +1,7 @@ <%# locals: (account:) %> <%= turbo_frame_tag dom_id(account, "entries") do %> -
+
<%= tag.h2 t(".title"), class: "font-medium text-lg" %> <% unless @account.plaid_account_id.present? %> @@ -10,7 +10,7 @@ <%= lucide_icon("plus", class: "w-4 h-4") %> <%= tag.span t(".new") %> -
-
+
">

Color

diff --git a/app/views/categories/_menu.html.erb b/app/views/categories/_menu.html.erb index ff098cb0..83532011 100644 --- a/app/views/categories/_menu.html.erb +++ b/app/views/categories/_menu.html.erb @@ -5,7 +5,7 @@ <%= render partial: "categories/badge", locals: { category: transaction.category } %>