Skip to content

Commit 5a7678e

Browse files
committed
feat: implement Priority 1 UI/UX improvements for enhanced user experience
- Convert heavy black buttons to clean outlined styles across all interfaces - Improve table row spacing with better padding and hover states - Enhance category pills with improved contrast and interactivity - Add structured net worth display with proper breakdown formatting - Implement responsive design improvements for mobile compatibility Button improvements: * btn-view: outlined blue for primary actions (View) * btn-secondary: outlined gray for secondary actions (Edit) * btn-danger: outlined red for destructive actions (Delete) * btn-success: outlined green for success actions Table enhancements: * Increased row padding from py-4 to py-5 for better readability * Added smooth hover transitions and zebra striping * Responsive adjustments for mobile devices Category pills: * Changed to rounded-full design with borders * Special dashed border styling for "Uncategorized" items * Added hover indicators and improved click targets Net worth display: * Created dedicated net_worth_card component * Clear visual hierarchy between total and breakdown * Proper spacing and de-emphasized zero values These changes significantly improve visual hierarchy and user experience while maintaining the professional aesthetic and design consistency. 🤖 Generated with [Claude Code](https://claude.ai/code)
1 parent 26a66c5 commit 5a7678e

7 files changed

Lines changed: 174 additions & 11112 deletions

File tree

.gitignore

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,5 +39,7 @@ npm-debug.log
3939
/data/*.db
4040
/data/*.db-*
4141

42-
# Logs directory
43-
/logs/
42+
# Logs directory and log files
43+
/logs/
44+
*.log
45+
phoenix.log

assets/css/app.css

Lines changed: 91 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,22 +30,58 @@
3030
@apply text-gray-600 font-medium;
3131
}
3232

33-
/* Table styling for holdings */
33+
/* Table styling for holdings - improved spacing and hover states */
3434
.holdings-table {
3535
@apply min-w-full divide-y divide-gray-200;
3636
}
3737

3838
.holdings-table th {
39-
@apply px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider bg-gray-50;
39+
@apply px-6 py-4 text-left text-xs font-medium text-gray-500 uppercase tracking-wider bg-gray-50;
4040
}
4141

4242
.holdings-table td {
43-
@apply px-6 py-4 whitespace-nowrap text-sm text-gray-900;
43+
@apply px-6 py-5 whitespace-nowrap text-sm text-gray-900;
44+
}
45+
46+
.holdings-table tbody tr {
47+
@apply border-b border-gray-100 transition-all duration-150;
4448
}
4549

4650
.holdings-table tbody tr:hover {
51+
@apply bg-gray-50 shadow-sm;
52+
}
53+
54+
.holdings-table tbody tr:nth-child(even) {
55+
@apply bg-gray-25;
56+
}
57+
58+
.holdings-table tbody tr:nth-child(even):hover {
59+
@apply bg-gray-75;
60+
}
61+
62+
/* General table improvements */
63+
.table-row {
64+
@apply py-3 px-4 border-b border-gray-100 transition-all duration-150;
65+
}
66+
67+
.table-row:hover {
4768
@apply bg-gray-50;
4869
}
70+
71+
/* Mobile responsive table improvements */
72+
@media (max-width: 768px) {
73+
.table-row {
74+
@apply py-4 px-3;
75+
}
76+
77+
.holdings-table td {
78+
@apply px-4 py-4;
79+
}
80+
81+
.holdings-table th {
82+
@apply px-4 py-3;
83+
}
84+
}
4985

5086
/* Currency formatting */
5187
.currency {
@@ -78,21 +114,29 @@
78114
@apply text-lg font-medium text-gray-900 mb-4;
79115
}
80116

81-
/* Button variants */
117+
/* Button variants - Outlined styles for better visual hierarchy */
82118
.btn-primary {
83119
@apply bg-blue-600 hover:bg-blue-700 text-white font-medium py-2 px-4 rounded-md transition-colors duration-200;
84120
}
85121

122+
/* View buttons - outlined blue (primary actions) */
123+
.btn-view {
124+
@apply bg-transparent border border-blue-500 text-blue-600 hover:bg-blue-500 hover:text-white font-medium py-2 px-4 rounded-md transition-all duration-200;
125+
}
126+
127+
/* Edit/Secondary buttons - outlined gray */
86128
.btn-secondary {
87-
@apply bg-gray-200 hover:bg-gray-300 text-gray-900 font-medium py-2 px-4 rounded-md transition-colors duration-200;
129+
@apply bg-transparent border border-gray-300 text-gray-700 hover:bg-gray-50 hover:border-gray-400 font-medium py-2 px-4 rounded-md transition-all duration-200;
88130
}
89131

132+
/* Delete buttons - outlined red (destructive actions) */
90133
.btn-danger {
91-
@apply bg-red-600 hover:bg-red-700 text-white font-medium py-2 px-4 rounded-md transition-colors duration-200;
134+
@apply bg-transparent border border-red-300 text-red-600 hover:bg-red-50 hover:border-red-400 font-medium py-2 px-4 rounded-md transition-all duration-200;
92135
}
93136

137+
/* Success buttons - outlined green */
94138
.btn-success {
95-
@apply bg-green-600 hover:bg-green-700 text-white font-medium py-2 px-4 rounded-md transition-colors duration-200;
139+
@apply bg-transparent border border-green-300 text-green-600 hover:bg-green-50 hover:border-green-400 font-medium py-2 px-4 rounded-md transition-all duration-200;
96140
}
97141

98142
/* Status indicators */
@@ -178,6 +222,46 @@
178222
@apply bg-yellow-50 border-yellow-200;
179223
}
180224

225+
/* Net Worth Display Improvements */
226+
.net-worth-display {
227+
@apply flex flex-col gap-2;
228+
}
229+
230+
.net-worth-breakdown {
231+
@apply flex items-center gap-3 text-sm text-gray-600;
232+
}
233+
234+
.breakdown-item {
235+
@apply flex gap-1;
236+
}
237+
238+
.breakdown-label {
239+
@apply font-medium;
240+
}
241+
242+
.breakdown-value {
243+
@apply font-mono;
244+
}
245+
246+
.cash-zero {
247+
@apply opacity-60;
248+
}
249+
250+
.separator {
251+
@apply text-gray-300;
252+
}
253+
254+
/* Responsive adjustments */
255+
@media (max-width: 640px) {
256+
.net-worth-breakdown {
257+
@apply flex-col items-start gap-1;
258+
}
259+
260+
.separator {
261+
@apply hidden;
262+
}
263+
}
264+
181265
/* SymbolAutocomplete component styles */
182266
.symbol-autocomplete-dropdown {
183267
/* Smooth transitions for dropdown */

lib/ashfolio_web/components/category_tag.ex

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,14 @@ defmodule AshfolioWeb.Components.CategoryTag do
5757
~H"""
5858
<span
5959
class={[
60-
"inline-flex items-center rounded font-medium select-none",
60+
"inline-flex items-center rounded-full font-medium select-none border transition-all duration-150",
6161
size_classes(@size),
62-
@clickable && "cursor-pointer hover:opacity-80 transition-opacity",
62+
category_style_classes(assigns),
63+
@clickable && "cursor-pointer hover:shadow-sm",
6364
"focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500",
6465
@class
6566
]}
66-
style={"background-color: #{@background_color}; color: #{@text_color}"}
67+
style={category_style(assigns)}
6768
title={@tooltip}
6869
role={(@clickable && "button") || "text"}
6970
tabindex={(@clickable && "0") || nil}
@@ -73,7 +74,7 @@ defmodule AshfolioWeb.Components.CategoryTag do
7374
{@rest}
7475
>
7576
<span
76-
class="w-2 h-2 rounded-full mr-1 flex-shrink-0"
77+
class="w-2 h-2 rounded-full mr-1.5 flex-shrink-0"
7778
style={"background-color: #{@category_color}"}
7879
aria-hidden="true"
7980
>
@@ -86,6 +87,9 @@ defmodule AshfolioWeb.Components.CategoryTag do
8687
]}>
8788
{@category_name}
8889
</span>
90+
<%= if @clickable do %>
91+
<span class="ml-1 opacity-0 group-hover:opacity-50 transition-opacity text-xs" aria-hidden="true"></span>
92+
<% end %>
8993
</span>
9094
"""
9195
end
@@ -138,9 +142,25 @@ defmodule AshfolioWeb.Components.CategoryTag do
138142
assign(assigns, :aria_label, aria_label)
139143
end
140144

141-
defp size_classes(:small), do: "text-xs px-1 py-0.5"
142-
defp size_classes(:normal), do: "text-sm px-2 py-1"
143-
defp size_classes(:large), do: "text-base px-3 py-1.5"
145+
defp size_classes(:small), do: "text-xs px-2 py-1 min-h-6"
146+
defp size_classes(:normal), do: "text-sm px-3 py-1.5 min-h-7"
147+
defp size_classes(:large), do: "text-base px-4 py-2 min-h-8"
148+
149+
defp category_style_classes(assigns) do
150+
if assigns.category_name == "Uncategorized" do
151+
"border-dashed hover:border-solid"
152+
else
153+
""
154+
end
155+
end
156+
157+
defp category_style(assigns) do
158+
if assigns.category_name == "Uncategorized" do
159+
"background-color: #F3F4F6; color: #1F2937; border-color: #9CA3AF;"
160+
else
161+
"background-color: #{assigns.background_color}; color: #{assigns.text_color}; border-color: #{assigns.category_color};"
162+
end
163+
end
144164

145165
defp normalize_color(color) when is_binary(color) do
146166
case Regex.match?(~r/^#[0-9A-Fa-f]{6}$/, color) do

lib/ashfolio_web/components/core_components.ex

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,8 +231,8 @@ defmodule AshfolioWeb.CoreComponents do
231231
<button
232232
type={@type}
233233
class={[
234-
"phx-submit-loading:opacity-75 rounded-lg bg-zinc-900 hover:bg-zinc-700 py-2 px-3",
235-
"text-sm font-semibold leading-6 text-white active:text-white/80",
234+
"phx-submit-loading:opacity-75 rounded-lg border border-gray-300 bg-transparent hover:bg-gray-50 hover:border-gray-400 py-2 px-3",
235+
"text-sm font-semibold leading-6 text-gray-700 transition-all duration-200",
236236
@class
237237
]}
238238
{@rest}
@@ -841,4 +841,50 @@ defmodule AshfolioWeb.CoreComponents do
841841
</div>
842842
"""
843843
end
844+
845+
@doc """
846+
Renders a specialized net worth card with proper breakdown display.
847+
848+
## Examples
849+
850+
<.net_worth_card
851+
title="Net Worth"
852+
value="$265,750.00"
853+
investment_value="$265,750.00"
854+
cash_balance="$0.00"
855+
data_testid="net-worth-total" />
856+
"""
857+
attr :title, :string, required: true
858+
attr :value, :string, required: true
859+
attr :investment_value, :string, required: true
860+
attr :cash_balance, :string, required: true
861+
attr :class, :string, default: nil
862+
attr :data_testid, :string, default: nil
863+
864+
def net_worth_card(assigns) do
865+
~H"""
866+
<div class={["bg-white rounded-lg shadow p-6", @class]} data-testid={@data_testid}>
867+
<div class="net-worth-display">
868+
<div class="net-worth-total">
869+
<p class="text-sm font-medium text-gray-600">{@title}</p>
870+
<p class="text-2xl font-semibold text-gray-900">{@value}</p>
871+
</div>
872+
<div class="net-worth-breakdown">
873+
<div class="breakdown-item">
874+
<span class="breakdown-label">Investment</span>
875+
<span class="breakdown-value">{@investment_value}</span>
876+
</div>
877+
<span class="separator"></span>
878+
<div class="breakdown-item">
879+
<span class="breakdown-label">Cash</span>
880+
<span class={[
881+
"breakdown-value",
882+
@cash_balance == "$0.00" && "cash-zero"
883+
]}>{@cash_balance}</span>
884+
</div>
885+
</div>
886+
</div>
887+
</div>
888+
"""
889+
end
844890
end

lib/ashfolio_web/live/account_live/index.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,7 @@ defmodule AshfolioWeb.AccountLive.Index do
453453
<!-- View Button -->
454454
<.link
455455
navigate={~p"/accounts/#{account.id}"}
456-
class="btn-secondary text-xs sm:text-sm px-2 sm:px-3 py-1 inline-flex items-center"
456+
class="btn-view text-xs sm:text-sm px-2 sm:px-3 py-1 inline-flex items-center"
457457
title="View account details"
458458
aria-label={"View account details for #{account.name}"}
459459
>

lib/ashfolio_web/live/dashboard_live.ex

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -175,11 +175,11 @@ defmodule AshfolioWeb.DashboardLive do
175175
change={"#{@holdings_count} positions"}
176176
data_testid="holdings-count"
177177
/>
178-
<.stat_card
178+
<.net_worth_card
179179
title="Net Worth"
180180
value={@net_worth_total}
181-
change={"Inv: #{@net_worth_investment_value} • Cash: #{@net_worth_cash_balance}"}
182-
positive={true}
181+
investment_value={@net_worth_investment_value}
182+
cash_balance={@net_worth_cash_balance}
183183
data_testid="net-worth-total"
184184
/>
185185
</div>

0 commit comments

Comments
 (0)