1
0
Fork 0
mirror of https://github.com/maybe-finance/maybe.git synced 2025-07-24 15:49:39 +02:00

Dashboard design fixes (#1898)
Some checks are pending
Publish Docker image / ci (push) Waiting to run
Publish Docker image / Build docker image (push) Blocked by required conditions

* Dashboard design fixes

* Update dashboard greeting

* Remove sidebar toggle from settings breadcrumbs

* Autofocus and outlines for category dropdowns

* Lint fixes
This commit is contained in:
Zach Gollwitzer 2025-02-25 17:28:40 -05:00 committed by GitHub
parent a4874815a6
commit c610b0ba4b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
25 changed files with 95 additions and 74 deletions

View file

@ -17,7 +17,7 @@ module FormsHelper
end
end
def period_select(form:, selected:, classes: "border border-tertiary shadow-xs 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 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" })

View file

@ -4,6 +4,10 @@ import { Controller } from "@hotwired/stimulus";
export default class extends Controller {
static targets = ["input", "list", "emptyMessage"];
connect() {
this.inputTarget.focus();
}
filter() {
const filterValue = this.inputTarget.value.toLowerCase();
const items = this.listTarget.querySelectorAll(".filterable-item");

View file

@ -8,7 +8,7 @@ export default class extends Controller {
toggle() {
this.panelTarget.classList.toggle("w-0");
this.panelTarget.classList.toggle("opacity-0");
this.panelTarget.classList.toggle("w-[260px]");
this.panelTarget.classList.toggle("w-80");
this.panelTarget.classList.toggle("opacity-100");
this.contentTarget.classList.toggle("max-w-4xl");
this.contentTarget.classList.toggle("max-w-5xl");

View file

@ -446,7 +446,7 @@ export default class extends Controller {
get _margin() {
if (this.useLabelsValue) {
return { top: 20, right: 0, bottom: 30, left: 0 };
return { top: 20, right: 0, bottom: 10, left: 0 };
}
return { top: 0, right: 0, bottom: 0, left: 0 };
}

View file

@ -6,6 +6,6 @@
<%= tag.p @series.trend.percent_formatted,
style: "color: #{@series.trend.color}",
class: "text-right text-xs font-medium text-primary" %>
class: "font-mono text-right text-xs font-medium text-primary" %>
</div>
<% end %>

View file

@ -8,21 +8,21 @@
data-tabs-inactive-class="text-secondary"
data-tabs-default-tab-value="assets-tab">
<div class="bg-surface-inset rounded-lg p-1 flex">
<button type="button" data-id="assets-tab" class="w-1/3 px-2 py-1 rounded-md text-sm text-secondary" data-tabs-target="btn" data-action="click->tabs#select">
<button type="button" data-id="assets-tab" class="w-1/3 px-2 py-1 rounded-md text-sm text-secondary font-medium" data-tabs-target="btn" data-action="click->tabs#select">
Assets
</button>
<button type="button" data-id="debts-tab" class="w-1/3 px-2 py-1 rounded-md text-secondary text-sm" data-tabs-target="btn" data-action="click->tabs#select">
<button type="button" data-id="debts-tab" class="w-1/3 px-2 py-1 rounded-md text-secondary text-sm font-medium" data-tabs-target="btn" data-action="click->tabs#select">
Debts
</button>
<button type="button" data-id="all-tab" class="w-1/3 px-2 py-1 rounded-md text-secondary text-sm" data-tabs-target="btn" data-action="click->tabs#select">
<button type="button" data-id="all-tab" class="w-1/3 px-2 py-1 rounded-md text-secondary text-sm font-medium" data-tabs-target="btn" data-action="click->tabs#select">
All
</button>
</div>
<div data-tabs-target="tab" id="assets-tab">
<%= link_to new_account_path(step: "method_select"),
<%= link_to new_account_path(step: "method_select", classification: "asset"),
class: "flex items-center gap-3 btn btn--ghost text-secondary mb-1",
data: { turbo_frame: "modal" } do %>
<%= icon("plus") %>
@ -37,7 +37,7 @@
</div>
<div data-tabs-target="tab" id="debts-tab" class="hidden">
<%= link_to new_account_path(step: "method_select"),
<%= link_to new_account_path(step: "method_select", classification: "liability"),
class: "flex items-center gap-3 btn btn--ghost text-secondary mb-1",
data: { turbo_frame: "modal" } do %>
<%= icon("plus") %>

View file

@ -19,12 +19,12 @@
<div class="space-y-1">
<% account_group.accounts.each do |account| %>
<%= link_to account_path(account), class: "block flex items-center gap-2 btn btn--ghost" do %>
<%= link_to account_path(account), class: "block flex items-center gap-2 btn btn--ghost", title: account.name do %>
<%= render "accounts/logo", account: account, size: "sm", color: account_group.color %>
<div>
<%= tag.p account.name, class: "text-sm font-medium mb-0.5" %>
<%= tag.p account.subtype&.humanize.presence || account_group.name, class: "text-sm text-secondary" %>
<div class="min-w-0 grow">
<%= tag.p account.name, class: "text-sm font-medium mb-0.5 truncate" %>
<%= tag.p account.subtype&.humanize.presence || account_group.name, class: "text-sm text-secondary truncate" %>
</div>
<div class="ml-auto text-right grow h-10">

View file

@ -8,9 +8,9 @@
} %>
<% if account.plaid_account_id? && account.institution_domain.present? %>
<%= image_tag "https://logo.synthfinance.com/#{account.institution_domain}", class: "rounded-full #{size_classes[size]}" %>
<%= image_tag "https://logo.synthfinance.com/#{account.institution_domain}", class: "shrink-0 rounded-full #{size_classes[size]}" %>
<% elsif account.logo.attached? %>
<%= image_tag account.logo, class: "rounded-full #{size_classes[size]}" %>
<%= image_tag account.logo, class: "shrink-0 rounded-full #{size_classes[size]}" %>
<% else %>
<%= circle_logo(account.name, hex: color || account.accountable.color, size: size) %>
<% end %>

View file

@ -16,7 +16,7 @@
<%= tag.span period.comparison_label, class: "text-secondary" %>
</div>
<div class="h-64">
<div class="h-64 pb-4">
<% if series.any? %>
<div
id="lineChart"

View file

@ -1,14 +1,25 @@
<%= render layout: "accounts/new/container", locals: { title: t(".title") } do %>
<div class="text-sm">
<%= render "account_type", accountable: Depository.new %>
<%= render "account_type", accountable: Investment.new %>
<%= render "account_type", accountable: Crypto.new %>
<%= render "account_type", accountable: Property.new %>
<%= render "account_type", accountable: Vehicle.new %>
<%= render "account_type", accountable: CreditCard.new %>
<%= render "account_type", accountable: Loan.new %>
<%= render "account_type", accountable: OtherAsset.new %>
<%= render "account_type", accountable: OtherLiability.new %>
<% unless params[:classification] == "liability" %>
<%= render "account_type", accountable: Depository.new %>
<%= render "account_type", accountable: Investment.new %>
<%= render "account_type", accountable: Crypto.new %>
<%= render "account_type", accountable: Property.new %>
<%= render "account_type", accountable: Vehicle.new %>
<% end %>
<% unless params[:classification] == "asset" %>
<%= render "account_type", accountable: CreditCard.new %>
<%= render "account_type", accountable: Loan.new %>
<% end %>
<% unless params[:classification] == "liability" %>
<%= render "account_type", accountable: OtherAsset.new %>
<% end %>
<% unless params[:classification] == "asset" %>
<%= render "account_type", accountable: OtherLiability.new %>
<% end %>
<% unless params[:return_to].present? %>
<%= button_to imports_path(import: { type: "AccountImport" }),

View file

@ -6,6 +6,6 @@
<%= tag.p @account.sparkline_series.trend.percent_formatted,
style: "color: #{@account.sparkline_series.trend.color}",
class: "text-right text-xs font-medium text-primary" %>
class: "font-mono text-right text-xs font-medium text-primary" %>
</div>
<% end %>

View file

@ -1,6 +1,6 @@
<%# locals: (category:) %>
<span
<span
data-category-target="avatar"
class="w-14 h-14 flex items-center justify-center rounded-full"
style="background-color: color-mix(in oklab, <%= category.color %> 10%, transparent); color: <%= category.color %>">

View file

@ -24,7 +24,7 @@
<% end %>
<label class="relative">
<%= f.radio_button :color, "custom-color", class: "sr-only peer", data: { category_target: "colorPickerRadioBtn"} %>
<div class="w-6 h-6 rounded-full cursor-pointer peer-checked:ring-2 peer-checked:ring-offset-2 peer-checked:ring-blue-500" data-category-target="pickerBtn" style="background: conic-gradient(red,orange,yellow,lime,green,teal,cyan,blue,indigo,purple,magenta,pink,red)" ></div>
<div class="w-6 h-6 rounded-full cursor-pointer peer-checked:ring-2 peer-checked:ring-offset-2 peer-checked:ring-blue-500" data-category-target="pickerBtn" style="background: conic-gradient(red,orange,yellow,lime,green,teal,cyan,blue,indigo,purple,magenta,pink,red)"></div>
</label>
</div>
<div class="flex gap-2 items-center hidden flex-col" data-category-target="paletteSection">
@ -46,7 +46,7 @@
<% Category.icon_codes.each do |icon| %>
<label class="relative">
<%= f.radio_button :lucide_icon, icon, class: "sr-only peer", data: { action: "change->category#handleIconChange change->category#handleIconColorChange", category_target:"icon" } %>
<div class="w-7 h-7 flex m-0.5 items-center justify-center rounded-full cursor-pointer hover:bg-gray-100 peer-checked:bg-gray-100 border-1 border-transparent" >
<div class="w-7 h-7 flex m-0.5 items-center justify-center rounded-full cursor-pointer hover:bg-gray-100 peer-checked:bg-gray-100 border-1 border-transparent">
<%= lucide_icon icon, class: "w-6 h-6 p-1" %>
</div>
</label>

View file

@ -1,7 +1,10 @@
<%# locals: (category:) %>
<% is_selected = category.id === @selected_category&.id %>
<%= content_tag :div, class: ["filterable-item flex justify-between items-center border-none rounded-lg px-2 py-1 group w-full", { "bg-gray-25": is_selected }], data: { filter_name: category.name } do %>
<%= content_tag :div,
class: ["filterable-item flex justify-between items-center border-none rounded-lg px-2 py-1 group w-full hover:bg-gray-25 focus-within:bg-gray-25",
{ "bg-gray-25": is_selected }],
data: { filter_name: category.name } do %>
<%= button_to account_transaction_category_path(
@transaction.entry,
account_entry: {
@ -10,7 +13,7 @@
}
),
method: :patch,
class: "flex w-full items-center gap-1.5 cursor-pointer" do %>
class: "flex w-full items-center gap-1.5 cursor-pointer focus:outline-none" do %>
<span class="w-5 h-5">
<%= lucide_icon("check", class: "w-5 h-5 text-secondary") if is_selected %>

View file

@ -17,7 +17,7 @@
</li>
<li>
<%= render "layouts/sidebar/nav_item", name: "Budgets", path: budgets_path, icon_key: "layout-grid" %>
<%= render "layouts/sidebar/nav_item", name: "Budgets", path: budgets_path, icon_key: "map" %>
</li>
</ul>
@ -26,7 +26,7 @@
</div>
</nav>
<%= tag.div class: class_names("py-4 shrink-0 h-full overflow-y-auto transition-all duration-300", Current.user.show_sidebar? ? "w-[260px]" : "w-0"), data: { sidebar_target: "panel" } do %>
<%= tag.div class: class_names("py-4 shrink-0 h-full overflow-y-auto transition-all duration-300", Current.user.show_sidebar? ? "w-80" : "w-0"), data: { sidebar_target: "panel" } do %>
<% if content_for?(:sidebar) %>
<%= yield :sidebar %>
<% else %>
@ -44,17 +44,16 @@
<% end %>
<%= tag.div class: class_names("mx-auto w-full h-full", Current.user.show_sidebar? ? "max-w-4xl" : "max-w-5xl"), data: { sidebar_target: "content" } do %>
<% unless controller_path.start_with?('settings/') %>
<% if content_for?(:breadcrumbs) %>
<%= yield :breadcrumbs %>
<% else %>
<%= render "layouts/shared/breadcrumbs", breadcrumbs: @breadcrumbs %>
<% end %>
<% if content_for?(:page_header) %>
<%= yield :page_header %>
<% end %>
<% if content_for?(:breadcrumbs) %>
<%= yield :breadcrumbs %>
<% else %>
<%= render "layouts/shared/breadcrumbs", breadcrumbs: @breadcrumbs %>
<% end %>
<% if content_for?(:page_header) %>
<%= yield :page_header %>
<% end %>
<%= yield %>
<% end %>
<% end %>

View file

@ -1,6 +1,6 @@
<%= render "layouts/shared/htmldoc" do %>
<div class="flex h-full bg-gray-25">
<div class="p-4 w-[260px] shrink-0 h-full overflow-y-auto">
<div class="p-4 w-96 shrink-0 h-full overflow-y-auto">
<%= render "settings/settings_nav" %>
</div>
@ -10,9 +10,9 @@
<% if content_for?(:breadcrumbs) %>
<%= yield :breadcrumbs %>
<% else %>
<%= render "layouts/shared/breadcrumbs", breadcrumbs: @breadcrumbs %>
<%= render "layouts/shared/breadcrumbs", breadcrumbs: @breadcrumbs, sidebar_toggle_enabled: false %>
<% end %>
<% if content_for?(:page_title) %>
<h1 class="text-primary text-xl font-medium">
<%= content_for :page_title %>

View file

@ -1,21 +1,25 @@
<%# locals: (breadcrumbs:) %>
<%# locals: (breadcrumbs:, sidebar_toggle_enabled: true) %>
<nav class="flex items-center gap-2 mb-6">
<button data-action="sidebar#toggle" class="w-9 h-9 inline-flex rounded-lg items-center justify-center hover:bg-gray-100 cursor-pointer">
<%= icon("panel-left", color: "gray") %>
</button>
<% breadcrumbs.each_with_index do |(name, path), index| %>
<% if index > 0 %>
<%= icon("chevron-right", color: "gray", size: "sm") %>
<% end %>
<% if path.present? && index < breadcrumbs.size - 1 %>
<%= link_to name, path, class: "text-sm text-gray-500 font-medium" %>
<% elsif index == breadcrumbs.size - 1 %>
<span class="text-gray-900 font-medium text-sm"><%= name %></span>
<% else %>
<span class="text-sm text-gray-500 font-medium"><%= name %></span>
<% end %>
<% if sidebar_toggle_enabled %>
<button data-action="sidebar#toggle" class="p-2 inline-flex rounded-lg items-center justify-center hover:bg-gray-100 cursor-pointer">
<%= icon("panel-left", color: "gray") %>
</button>
<% end %>
</nav>
<div class="py-2 flex items-center gap-2">
<% breadcrumbs.each_with_index do |(name, path), index| %>
<% if index > 0 %>
<%= icon("chevron-right", color: "gray", size: "sm") %>
<% end %>
<% if path.present? && index < breadcrumbs.size - 1 %>
<%= link_to name, path, class: "text-sm text-gray-500 font-medium" %>
<% elsif index == breadcrumbs.size - 1 %>
<span class="text-gray-900 font-medium text-sm"><%= name %></span>
<% else %>
<span class="text-sm text-gray-500 font-medium"><%= name %></span>
<% end %>
<% end %>
</div>
</nav>

View file

@ -8,4 +8,4 @@
<% end %>
</div>
<% end %>
</header>
</header>

View file

@ -1,7 +1,7 @@
<% content_for :page_header do %>
<div class="space-y-1 mb-6">
<h1 class="text-3xl font-medium text-gray-900">Welcome back, <%= Current.user.first_name %></h1>
<p class="text-gray-500">Here's what's happening with your money this week</p>
<p class="text-gray-500">Here's what's happening with your finances</p>
</div>
<% end %>

View file

@ -17,7 +17,7 @@
<div class="flex items-center gap-2 text-sm">
<div class="h-2.5 w-2.5 rounded-full" style="background-color: <%= account_group.color %>;"></div>
<p class="text-secondary"><%= account_group.name %></p>
<p class="text-black"><%= number_to_percentage(account_group.weight, precision: 0) %></p>
<p class="text-black font-mono"><%= number_to_percentage(account_group.weight, precision: 0) %></p>
</div>
<% end %>
</div>

View file

@ -1,10 +1,10 @@
<%# locals: (series:, period:) %>
<div class="flex justify-between p-4">
<div class="flex justify-between gap-4 px-4">
<div class="space-y-2">
<div class="space-y-2">
<p class="text-sm text-secondary font-medium">Net Worth</p>
<p class="text-primary -space-x-0.5 text-xl font-medium">
<p class="text-primary -space-x-0.5 text-3xl font-medium">
<%= series.current.format %>
</p>
<% if series.trend.nil? %>

View file

@ -1,5 +1,5 @@
<div class="space-y-4">
<div class="flex items-center gap-2 p-2">
<div class="flex items-center gap-2 p-1.5">
<%= link_to previous_path, class: "flex items-center gap-1 text-primary font-medium text-sm" do %>
<%= lucide_icon "chevron-left", class: "w-5 h-5 text-secondary" %>
<span>Back</span>

View file

@ -8,4 +8,4 @@
class="w-8 h-8 flex items-center justify-center rounded-full"
style="background-color: <%= background_color %>; border-color: <%= border_color %>; color: <%= color %>">
<%= letter.upcase %>
</span>
</span>

View file

@ -5,4 +5,4 @@
<%= content %>
</div>
</dialog>
<% end %>
<% end %>

View file

@ -4,11 +4,11 @@
<% if trend.direction.flat? %>
<span>No change</span>
<% else %>
<span>
<span class="font-mono">
<%= trend.value.is_a?(Money) ? format_money(trend.value) : trend.value.round(2) %>
</span>
<% unless trend.percent.infinite? %>
<span>(<%= lucide_icon(trend.icon, class: "w-4 h-4 align-text-bottom inline") %><%= trend.percent_formatted %>)</span>
<span class="font-mono">(<%= lucide_icon(trend.icon, class: "w-4 h-4 align-text-bottom inline") %><%= trend.percent_formatted %>)</span>
<% end %>
<% end %>
</p>