PWA: Update manifest, meta tags, and fix UI layout issues (#801)

* pwa(cleanup): enforce LF, head meta + icons, manifest orientation, remove static webmanifest

* pwa(cleanup): add gitattributes, head meta/icons, manifest orientation; remove static manifest; small nav & dashboard fixes

* pwa(cleanup): improve transaction drawer header layout with inline close button

* fix: address PR review feedback

- Add dom_id to transaction header for Turbo Stream updates (Codex)
- Add pending badge next to date when transaction is pending (CodeRabbit)
- Make close button keyboard-focusable by removing tabindex=-1 (CodeRabbit)
- Fix settings nav horizontal scroll with flex-nowrap space-x-1 (CodeRabbit)

* fix: localize 'Linked with Plaid' tooltip string (CodeRabbit)

* Update .gitattributes

Better comment smh

* fix: align transaction/transfer dialog icons and update transfer drawer pattern

- Fix icon alignment in transaction header (items-center instead of items-start)
- Make transfer/linked icons consistent size and color
- Update transfers/show.html.erb to use frame: drawer with hide_close_icon pattern
- Match transfer dialog header layout with transaction details

* fix: enhance header layout

This in the transaction and transfer views, with consistent icon placement

* fix: remove fixed height from HTML document class

basically a regression issue pretty sure

* fix: update dialog rendering to use 'frame' and hide close icon in headers

* fix: update transaction type tabs layout for improved responsiveness

* fix: conditionally render transaction type tabs based on account type
This commit is contained in:
StalkerSea
2026-01-29 08:16:49 -06:00
committed by GitHub
parent bdfb0e64bc
commit a86329d632
16 changed files with 106 additions and 76 deletions

5
.gitattributes vendored
View File

@@ -7,3 +7,8 @@ db/schema.rb linguist-generated
vendor/* linguist-vendored
config/credentials/*.yml.enc diff=rails_credentials
config/credentials.yml.enc diff=rails_credentials
# Ensure consistent line endings for scripts and Ruby files to avoid shebang issues on Windows
bin/* text eol=lf
*.sh text eol=lf
*.rb text eol=lf

View File

@@ -1,5 +1,5 @@
<%= render DS::Dialog.new(variant: "drawer") do |dialog| %>
<% dialog.with_header do %>
<%= render DS::Dialog.new(frame: "drawer") do |dialog| %>
<% dialog.with_header(hide_close_icon: true) do %>
<div class="flex items-center justify-between">
<div>
<%= tag.h3 @holding.name, class: "text-2xl font-medium text-primary" %>

View File

@@ -19,13 +19,19 @@
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="apple-mobile-web-app-title" content="<%= product_name %>">
<meta name="color-scheme" content="dark light">
<meta name="msapplication-TileColor" content="#F9F9F9">
<meta name="theme-color" content="#F9F9F9">
<%# Use theme colors that match both light and dark modes %>
<meta name="msapplication-TileColor" content="#0B0B0B">
<meta name="theme-color" content="#F9F9F9" media="(prefers-color-scheme: light)">
<meta name="theme-color" content="#0B0B0B" media="(prefers-color-scheme: dark)">
<link rel="manifest" href="<%= pwa_manifest_path %>">
<link rel="apple-touch-icon" href="/logo-pwa.png">
<%# Provide multiple iOS icons (standard 180x180 and larger) %>
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
<link rel="apple-touch-icon" sizes="512x512" href="/logo-pwa.png">
<link rel="icon" sizes="192x192" type="image/png" href="/android-chrome-192x192.png">
<% if Rails.env.production? && (posthog_config = Rails.configuration.x.posthog).try(:api_key).present? %>
<%= render "shared/posthog", posthog_api_key: posthog_config.api_key, posthog_host: posthog_config.host %>

View File

@@ -7,7 +7,7 @@
data-theme="<%= theme %>"
data-controller="theme"
data-theme-user-preference-value="<%= Current.user&.theme || "system" %>"
class="h-[100vh] text-primary bg-surface overflow-hidden overscroll-none font-sans <%= @os %>">
class="text-primary bg-surface overflow-hidden overscroll-none font-sans <%= @os %>">
<head>
<%= render "layouts/shared/head" %>
<%= yield :head %>

View File

@@ -83,9 +83,9 @@
<%= t(".period_activity", period: period.label) %>
</div>
<div class="shadow-border-xs rounded-lg bg-container font-medium text-sm">
<div class="p-4 flex items-center justify-between gap-4">
<div class="p-4 grid grid-cols-1 sm:grid-cols-3 gap-4">
<div class="flex items-center gap-2">
<div class="w-8 h-8 rounded-full bg-green-500/10 flex items-center justify-center">
<div class="w-8 h-8 p-1.5 rounded-full bg-green-500/10 flex items-center justify-center">
<%= icon "trending-up", size: "sm", color: "green" %>
</div>
<div>
@@ -94,7 +94,7 @@
</div>
</div>
<div class="flex items-center gap-2">
<div class="w-8 h-8 rounded-full bg-orange-500/10 flex items-center justify-center">
<div class="w-8 h-8 p-1.5 rounded-full bg-orange-500/10 flex items-center justify-center">
<%= icon "trending-down", size: "sm", color: "orange" %>
</div>
<div>
@@ -103,7 +103,7 @@
</div>
</div>
<div class="flex items-center gap-2">
<div class="w-8 h-8 rounded-full bg-blue-500/10 flex items-center justify-center">
<div class="w-8 h-8 p-1.5 rounded-full bg-blue-500/10 flex items-center justify-center">
<%= icon "arrow-left-right", size: "sm", color: "blue" %>
</div>
<div>

View File

@@ -16,8 +16,9 @@
],
"start_url": "/",
"display": "standalone",
"display_override": ["fullscreen", "minimal-ui"],
"display_override": ["window-controls-overlay", "minimal-ui"],
"scope": "/",
"orientation": "any",
"description": "<%= j product_name %> is your personal finance assistant.",
"theme_color": "#F9F9F9",
"background_color": "#F9F9F9"

View File

@@ -84,8 +84,8 @@ nav_sections = [
<% end %>
</section>
</nav>
<nav class="space-y-4 overflow-y-auto md:hidden no-scrollbar" id="mobile-settings-nav" data-controller="preserve-scroll scroll-on-connect">
<ul class="flex space-y-1">
<nav class="space-y-4 overflow-x-auto md:hidden no-scrollbar overscroll-none" id="mobile-settings-nav" data-controller="preserve-scroll scroll-on-connect">
<ul class="flex flex-nowrap space-x-1">
<li>
<%= render DS::Link.new(
text: t("settings.settings_nav_link_large.previous"),
@@ -102,10 +102,12 @@ nav_sections = [
</li>
<% end %>
<% end %>
<%= button_to session_path(Current.session), method: :delete, class: "flex items-center gap-2 px-3 py-2 rounded-lg text-sm text-destructive hover:bg-surface-hover w-full" do %>
<%= icon("log-out", color: "current") %>
<span><%= t(".logout") %></span>
<% end %>
<li>
<%= button_to session_path(Current.session), method: :delete, class: "flex items-center gap-2 px-3 py-2 rounded-lg text-sm text-destructive hover:bg-surface-hover w-full" do %>
<%= icon("log-out", color: "current") %>
<span><%= t(".logout") %></span>
<% end %>
</li>
</ul>
</nav>
</div>

View File

@@ -1,24 +1,30 @@
<%# locals: (active_tab:, account_id: nil) %>
<fieldset class="bg-surface-inset rounded-lg p-1 grid grid-flow-col justify-stretch gap-x-2">
<fieldset class="bg-surface-inset rounded-lg p-1 flex flex-wrap gap-2">
<%= link_to new_transaction_path(nature: "outflow", account_id: account_id),
data: { turbo_frame: :modal },
class: "flex px-4 py-1 rounded-lg items-center space-x-2 justify-center text-sm #{active_tab == 'expense' ? 'bg-container text-primary shadow-sm' : 'hover:bg-container text-subdued hover:text-primary hover:shadow-sm'}" do %>
class: "flex-1 min-w-0 flex px-4 py-1 rounded-lg items-center space-x-2 justify-center text-sm #{active_tab == 'expense' ? 'bg-container text-primary shadow-sm' : 'hover:bg-container text-subdued hover:text-primary hover:shadow-sm'}" do %>
<%= icon "minus-circle" %>
<%= tag.span t("shared.transaction_tabs.expense") %>
<%= tag.span class: "truncate" do %>
<%= t("shared.transaction_tabs.expense") %>
<% end %>
<% end %>
<%= link_to new_transaction_path(nature: "inflow", account_id: account_id),
data: { turbo_frame: :modal },
class: "flex px-4 py-1 rounded-lg items-center space-x-2 justify-center text-sm #{active_tab == 'income' ? 'bg-container text-primary shadow-sm' : 'hover:bg-container text-subdued hover:text-primary hover:shadow-sm'}" do %>
class: "flex-1 min-w-0 flex px-4 py-1 rounded-lg items-center space-x-2 justify-center text-sm #{active_tab == 'income' ? 'bg-container text-primary shadow-sm' : 'hover:bg-container text-subdued hover:text-primary hover:shadow-sm'}" do %>
<%= icon "plus-circle" %>
<%= tag.span t("shared.transaction_tabs.income") %>
<%= tag.span class: "truncate" do %>
<%= t("shared.transaction_tabs.income") %>
<% end %>
<% end %>
<%= 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-sm #{active_tab == 'transfer' ? 'bg-container text-primary shadow-sm' : 'hover:bg-container text-subdued hover:text-primary hover:shadow-sm'}" do %>
class: "flex-1 min-w-0 flex px-4 py-1 rounded-lg items-center space-x-2 justify-center text-sm #{active_tab == 'transfer' ? 'bg-container text-primary shadow-sm' : 'hover:bg-container text-subdued hover:text-primary hover:shadow-sm'}" do %>
<%= icon "arrow-right-left" %>
<%= tag.span t("shared.transaction_tabs.transfer") %>
<%= tag.span class: "truncate" do %>
<%= t("shared.transaction_tabs.transfer") %>
<% end %>
<% end %>
</fieldset>

View File

@@ -1,5 +1,5 @@
<%= render DS::Dialog.new(variant: "drawer") do |dialog| %>
<% dialog.with_header do %>
<%= render DS::Dialog.new(frame: "drawer") do |dialog| %>
<% dialog.with_header(hide_close_icon: true) do %>
<%= render "trades/header", entry: @entry %>
<% end %>

View File

@@ -1,8 +1,8 @@
<%# locals: (entry:) %>
<%= tag.header class: "mb-4 space-y-1", id: dom_id(entry, :header) do %>
<div class="flex items-center gap-4">
<h3 class="font-medium">
<div class="flex items-start justify-between gap-4" id="<%= dom_id(entry, :header) %>">
<div>
<h3 class="font-medium flex items-center gap-2">
<span class="text-2xl text-primary">
<%= format_money -entry.amount_money %>
</span>
@@ -10,20 +10,31 @@
<span class="text-lg text-secondary">
<%= entry.currency %>
</span>
<% if entry.transaction.transfer? %>
<%= icon "arrow-left-right", size: "sm", class: "text-secondary" %>
<% end %>
<% if entry.linked? %>
<span title="<%= t('transactions.transaction.linked_with_plaid') %>" class="text-secondary">
<%= icon("refresh-ccw", size: "sm") %>
</span>
<% end %>
</h3>
<% if entry.transaction.transfer? %>
<%= icon "arrow-left-right", class: "mt-1" %>
<% end %>
<% if entry.linked? %>
<span title="Linked with Plaid">
<%= icon("refresh-ccw", size: "sm") %>
<div class="flex items-center gap-2">
<span class="text-sm text-secondary">
<%= I18n.l(entry.date, format: :long) %>
</span>
<% end %>
<% if entry.transaction.pending? %>
<span class="inline-flex items-center gap-1 text-xs font-medium rounded-full px-1.5 py-0.5 border border-secondary text-secondary" title="<%= t("transactions.transaction.pending_tooltip") %>">
<%= icon "clock", size: "sm", color: "current" %>
<%= t("transactions.transaction.pending") %>
</span>
<% end %>
</div>
</div>
<span class="text-sm text-secondary">
<%= I18n.l(entry.date, format: :long) %>
</span>
<% end %>
<%= render DS::Button.new(variant: "icon", icon: "x", data: { action: "DS--dialog#close" }) %>
</div>

View File

@@ -1,5 +1,5 @@
<%= render DS::Dialog.new(variant: "drawer") do |dialog| %>
<% dialog.with_header do %>
<%= render DS::Dialog.new(frame: "drawer") do |dialog| %>
<% dialog.with_header(hide_close_icon: true) do %>
<%= render "transactions/header", entry: @entry %>
<% end %>

View File

@@ -6,9 +6,24 @@
</div>
<% end %>
<section>
<%= render "shared/transaction_type_tabs", active_tab: "transfer" %>
</section>
<%# Hide expense/income tabs when creating a transfer involving an investment or crypto account. %>
<% show_type_tabs = true %>
<% account_ids = [] %>
<% account_ids << @from_account_id if defined?(@from_account_id) && @from_account_id.present? %>
<% account_ids << params[:from_account_id] if params[:from_account_id].present? %>
<% account_ids << params[:to_account_id] if params[:to_account_id].present? %>
<% account_ids << transfer.from_account_id if transfer.respond_to?(:from_account_id) && transfer.from_account_id.present? %>
<% account_ids << transfer.to_account_id if transfer.respond_to?(:to_account_id) && transfer.to_account_id.present? %>
<% if account_ids.any? && Current.family.accounts.where(id: account_ids).any? { |a| a.investment? || a.crypto? } %>
<% show_type_tabs = false %>
<% end %>
<% if show_type_tabs %>
<section>
<%= render "shared/transaction_type_tabs", active_tab: "transfer" %>
</section>
<% end %>
<section class="space-y-2">
<%= f.collection_select :from_account_id, Current.family.accounts.alphabetically, :id, :name, { prompt: t(".select_account"), label: t(".from"), selected: @from_account_id }, required: true %>

View File

@@ -1,8 +1,8 @@
<%= render DS::Dialog.new(variant: "drawer") do |dialog| %>
<% dialog.with_header do %>
<div class="space-y-1">
<div class="flex items-center gap-4">
<h3 class="font-medium">
<%= render DS::Dialog.new(frame: "drawer") do |dialog| %>
<% dialog.with_header(hide_close_icon: true) do %>
<div class="flex items-start justify-between gap-4">
<div>
<h3 class="font-medium flex items-center gap-2">
<span class="text-2xl text-primary">
<%= format_money @transfer.amount_abs %>
</span>
@@ -10,14 +10,16 @@
<span class="text-lg text-secondary">
<%= @transfer.amount_abs.currency.iso_code %>
</span>
<%= icon "arrow-left-right", size: "sm", class: "text-secondary" %>
</h3>
<%= icon "arrow-left-right", size: "sm" %>
<span class="text-sm text-secondary">
<%= @transfer.name %>
</span>
</div>
<span class="text-sm text-secondary">
<%= @transfer.name %>
</span>
<%= render DS::Button.new(variant: "icon", icon: "x", data: { action: "DS--dialog#close" }) %>
</div>
<% end %>

View File

@@ -1,7 +1,7 @@
<% entry, account = @entry, @entry.account %>
<%= render DS::Dialog.new(variant: "drawer") do |dialog| %>
<% dialog.with_header do %>
<%= render DS::Dialog.new(frame: "drawer") do |dialog| %>
<% dialog.with_header(hide_close_icon: true) do %>
<%= render "valuations/header", entry: @entry %>
<% end %>

View File

@@ -76,6 +76,7 @@ en:
transaction:
pending: Pending
pending_tooltip: Pending transaction — may change when posted
linked_with_plaid: Linked with Plaid
activity_type_tooltip: Investment activity type
possible_duplicate: Duplicate?
potential_duplicate_tooltip: This may be a duplicate of another transaction

View File

@@ -1,19 +0,0 @@
{
"name": "",
"short_name": "",
"icons": [
{
"src": "/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"theme_color": "#ffffff",
"background_color": "#ffffff",
"display": "fullscreen"
}