Skip to content

Commit e31250a

Browse files
Improve mobile expenses UI and add screenshots
- Redesign mobile expense rows to compact two-line layout - Add long-press to select functionality for bulk actions - Add visual feedback during long press (highlight + haptic) - Update README with app screenshots 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <[email protected]>
1 parent f45a119 commit e31250a

File tree

9 files changed

+173
-118
lines changed

9 files changed

+173
-118
lines changed

README.md

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
## What It Does
1111

12-
A privacy-focused, self-hosted web application for tracking healthcare expenses. Keep your sensitive financial and health data on your own server.
12+
A privacy-focused, self-hosted webapp for tracking HSA, FSA and DCFSA expenses with receipt support.
1313

1414
**Key Features:**
1515
- Track HSA, FSA, and DCFSA expenses with combined plan support
@@ -24,11 +24,22 @@ A privacy-focused, self-hosted web application for tracking healthcare expenses.
2424

2525
## Screenshots
2626

27-
| Dashboard | Expenses |
28-
|:---------:|:--------:|
29-
| ![Dashboard](docs/screenshots/dashboard.png) | ![Expenses](docs/screenshots/expenses.png) |
30-
| **New Expense** | **Settings** |
31-
| ![New Expense](docs/screenshots/new-expense.png) | ![Settings](docs/screenshots/settings.png) |
27+
### Dashboard
28+
![Dashboard Light](docs/screenshots/dashboard-light.png)
29+
30+
![Dashboard Dark](docs/screenshots/dashboard-dark.png)
31+
32+
### Expenses
33+
![Expenses](docs/screenshots/expense.png)
34+
35+
### New Expense
36+
![New Expense](docs/screenshots/new-expense.png)
37+
38+
### Settings
39+
![Settings](docs/screenshots/settings.png)
40+
41+
### Policy Management
42+
![Policy Management](docs/screenshots/policy-management.png)
3243

3344
---
3445

app/assets/css/pages/expenses.css

Lines changed: 93 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -173,9 +173,6 @@ html.dark-mode .expenses-table-container {
173173
font-weight: 500;
174174
}
175175

176-
.expenses-table tbody td:first-child {
177-
padding-left: 0.75rem;
178-
}
179176

180177
.expense-row {
181178
cursor: pointer;
@@ -291,7 +288,7 @@ html.dark-mode .expenses-table-container {
291288
position: absolute;
292289
left: 12px;
293290
top: 50%;
294-
transform: translateY(-50%) scale(0);
291+
transform: translate(-31%, -51%) scale(0);
295292
font-size: 14px;
296293
font-weight: bold;
297294
color: white;
@@ -306,7 +303,7 @@ html.dark-mode .expenses-table-container {
306303
}
307304

308305
.mobile-select-all-checkbox:checked + .mobile-select-all-label::after {
309-
transform: translateY(-50%) scale(1);
306+
transform: translate(-31%, -51%) scale(1);
310307
}
311308

312309
/* Hover state for select all */
@@ -343,13 +340,17 @@ html.dark-mode .expenses-table-container {
343340
accent-color: #3b82f6;
344341
}
345342

346-
/* Mobile Card Layout for Expenses - Revamped */
343+
/* Mobile Compact Row Layout for Expenses */
347344
.expenses-table-container {
348345
overflow: visible;
349-
background: transparent;
350-
box-shadow: none;
351-
border: none;
352-
border-radius: 0;
346+
background: var(--bg-primary);
347+
border-radius: 12px;
348+
border: 1px solid var(--border-color);
349+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
350+
}
351+
352+
html.dark-mode .expenses-table-container {
353+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
353354
}
354355

355356
.expenses-table thead {
@@ -359,32 +360,40 @@ html.dark-mode .expenses-table-container {
359360
.expenses-table tbody {
360361
display: flex;
361362
flex-direction: column;
362-
gap: 0.75rem;
363363
}
364364

365-
/* Card Structure: 4 rows x 2 columns grid */
365+
/* Compact Two-Line Row Structure */
366366
.expenses-table tbody tr {
367367
display: grid;
368-
grid-template-columns: auto 1fr;
369-
grid-template-rows: auto auto auto auto;
370-
gap: 0;
368+
grid-template-columns: auto 1fr auto;
369+
grid-template-rows: auto auto;
370+
column-gap: 0.6rem;
371+
row-gap: 0.25rem;
371372
background: var(--bg-primary);
372-
border-radius: 12px;
373-
border: 1px solid var(--border-color);
374-
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
375-
padding: 0;
376-
overflow: hidden;
373+
padding: 0.6rem 0.75rem 0.6rem 1rem;
377374
cursor: pointer;
378375
position: relative;
379-
transition: all 0.2s ease;
376+
transition: background-color 0.15s ease;
377+
border-bottom: 1px solid var(--border-color);
378+
align-items: center;
380379
}
381380

382-
html.dark-mode .expenses-table tbody tr {
383-
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.4);
381+
.expenses-table tbody tr:last-child {
382+
border-bottom: none;
384383
}
385384

386385
.expenses-table tbody tr:active {
387-
transform: scale(0.98);
386+
background-color: rgba(59, 130, 246, 0.08);
387+
}
388+
389+
/* Long press visual feedback */
390+
.expenses-table tbody tr.long-press-active {
391+
background-color: rgba(59, 130, 246, 0.06);
392+
transition: background-color 0.1s ease;
393+
}
394+
395+
.expenses-table tbody tr.long-press-selected {
396+
background-color: rgba(59, 130, 246, 0.15);
388397
}
389398

390399
/* Remove all default td styling and data-labels */
@@ -397,179 +406,151 @@ html.dark-mode .expenses-table-container {
397406
content: none !important;
398407
}
399408

400-
/* Row 1, Col 1: Checkbox */
409+
.expenses-table tbody td::after {
410+
content: none !important;
411+
}
412+
413+
/* Checkbox cell - spans both rows */
401414
.expenses-table tbody td:nth-child(1) {
402415
grid-column: 1;
403-
grid-row: 1;
404-
padding: 0.85rem 0 0 0.85rem;
416+
grid-row: 1 / 3;
405417
display: flex;
406-
align-items: flex-start;
407-
align-self: start;
418+
align-items: center;
408419
}
409420

410-
/* Row 1, Col 2: Date */
421+
/* Date cell - row 2, col 2 */
411422
.expenses-table tbody td:nth-child(2) {
412423
grid-column: 2;
413-
grid-row: 1;
414-
padding: 0.85rem 0.85rem 0 0.65rem;
415-
display: flex;
416-
justify-content: flex-start;
417-
align-items: flex-start;
418-
font-size: 0.85rem;
424+
grid-row: 2;
425+
font-size: 0.75rem;
419426
color: var(--text-secondary);
420-
font-weight: 500;
427+
font-weight: 400;
428+
display: flex;
429+
align-items: center;
430+
gap: 0.35rem;
421431
}
422432

423-
/* Row 2, Full Width: Provider Name */
433+
/* Provider cell - row 1, col 2 */
424434
.expenses-table tbody td:nth-child(3) {
425-
grid-column: 1 / -1;
426-
grid-row: 2;
427-
padding: 0.6rem 0.85rem 0.4rem 0.85rem;
428-
font-size: 1.05rem;
429-
font-weight: 600;
435+
grid-column: 2;
436+
grid-row: 1;
437+
font-size: 0.9rem;
438+
font-weight: 500;
430439
color: var(--text-primary);
431-
line-height: 1.3;
440+
white-space: nowrap;
441+
overflow: hidden;
442+
text-overflow: ellipsis;
432443
}
433444

434-
/* Row 3, Col 1: Account Badge */
445+
/* Account badge cell - hidden */
435446
.expenses-table tbody td:nth-child(4) {
436-
grid-column: 1;
437-
grid-row: 3;
438-
padding: 0.6rem 0 0.85rem 0.85rem;
439-
display: flex;
440-
align-items: flex-start;
441-
border-top: 1px solid var(--border-color);
442-
padding-top: 0.6rem;
447+
display: none;
443448
}
444449

445-
/* Row 3, Col 2: Amounts Column (right side) */
450+
/* Amount cell - row 1, col 3 */
446451
.expenses-table tbody td:nth-child(5) {
447-
grid-column: 2;
448-
grid-row: 3;
449-
padding: 0.6rem 0.85rem 0.85rem 0.5rem;
452+
grid-column: 3;
453+
grid-row: 1;
450454
display: flex;
451-
flex-direction: column;
452-
align-items: flex-end;
453-
gap: 0.35rem;
454-
border-top: 1px solid var(--border-color);
455-
padding-top: 0.6rem;
456-
font-size: 0.85rem;
457-
line-height: 1.4;
458-
}
459-
460-
.expenses-table tbody td:nth-child(5)::before {
461-
content: 'Paid amount: ' attr(data-paid);
462-
font-weight: 500;
463-
color: var(--text-secondary);
464-
white-space: nowrap;
465-
}
466-
467-
.expenses-table tbody td:nth-child(5)::after {
468-
content: 'Reimbursed amount: ' attr(data-reimbursed);
469-
font-weight: 500;
470-
color: var(--text-secondary);
471-
white-space: nowrap;
455+
align-items: center;
456+
justify-content: flex-end;
457+
font-weight: 600;
458+
font-size: 0.9rem;
459+
color: var(--text-primary);
460+
font-variant-numeric: tabular-nums;
472461
}
473462

474-
/* Hide the original reimbursed cell */
463+
/* Hide reimbursed cell */
475464
.expenses-table tbody td:nth-child(6) {
476465
display: none;
477466
}
478467

479-
/* Status Badge - Positioned in top-right corner */
468+
/* Status cell - row 2, col 3 */
480469
.expenses-table tbody td:nth-child(7) {
481-
position: absolute;
482-
top: 0;
483-
right: 0;
484-
padding: 0.5rem 0.5rem 0 0;
470+
grid-column: 3;
471+
grid-row: 2;
485472
display: flex;
473+
align-items: center;
474+
justify-content: flex-end;
486475
}
487476

488-
/* Gmail-style circular selection indicator */
477+
/* Checkbox styling */
489478
.checkbox-cell {
490479
z-index: 2;
491480
position: relative;
492481
}
493482

494-
/* Hide the default checkbox */
495483
.checkbox-cell .expense-checkbox {
496484
position: absolute;
497485
opacity: 0;
498486
width: 0;
499487
height: 0;
500488
}
501489

502-
/* Custom circular indicator */
503490
.checkbox-label {
504491
position: relative;
505492
display: flex;
506493
align-items: center;
507494
cursor: pointer;
508495
user-select: none;
496+
padding: 0.25rem 0.25rem 0.25rem 0;
509497
}
510498

511-
/* Circle background */
512499
.checkbox-label::before {
513500
content: '';
514501
display: inline-block;
515-
width: 24px;
516-
height: 24px;
502+
width: 22px;
503+
height: 22px;
517504
border: 2px solid var(--border-color);
518505
border-radius: 50%;
519506
background: transparent;
520-
transition: all 0.2s ease;
507+
transition: all 0.15s ease;
521508
}
522509

523-
/* Checkmark (hidden by default) */
524510
.checkbox-label::after {
525511
content: '✓';
526512
position: absolute;
527-
left: 50%;
513+
left: 11px;
528514
top: 50%;
529-
transform: translate(-50%, -50%) scale(0);
530-
font-size: 14px;
515+
transform: translate(-31%, -51%) scale(0);
516+
font-size: 12px;
531517
font-weight: bold;
532518
color: white;
533-
transition: transform 0.2s ease;
519+
transition: transform 0.15s ease;
534520
line-height: 1;
535521
}
536522

537-
/* When checkbox is checked */
538523
.expense-checkbox:checked + .checkbox-label::before {
539524
background: #3b82f6;
540525
border-color: #3b82f6;
541526
}
542527

543528
.expense-checkbox:checked + .checkbox-label::after {
544-
transform: translate(-50%, -50%) scale(1);
545-
}
546-
547-
/* Hover state */
548-
.checkbox-label:hover::before {
549-
border-color: #3b82f6;
550-
border-width: 2.5px;
529+
transform: translate(-31%, -51%) scale(1);
551530
}
552531

553532
.checkbox-text {
554533
display: none !important;
555534
}
556535

557-
/* Adjust status badges for mobile overlay */
536+
/* Compact status badges */
558537
.expenses-table tbody .status-badge {
559-
font-size: 0.65rem;
560-
padding: 0.25rem 0.5rem;
538+
font-size: 0.6rem;
539+
padding: 0.2rem 0.4rem;
561540
font-weight: 600;
562541
border-radius: 4px;
542+
white-space: nowrap;
563543
}
564544

565-
/* Account badges styling for mobile */
545+
/* Hide account badge in rows */
566546
.expenses-table tbody .account-badge {
567-
font-size: 0.75rem;
568-
padding: 0.3rem 0.65rem;
569-
font-weight: 600;
570-
border-radius: 6px;
547+
display: none;
548+
}
549+
550+
/* Receipt indicator in compact view - show inline */
551+
.expenses-table tbody .receipt-indicator {
552+
margin-left: 0.25rem;
571553
}
572-
}
573554
}
574555

575556
/* ===== No Data Messages ===== */

0 commit comments

Comments
 (0)