Merge pull request #17 from GoncaloRodri/feature/fixes-mobile-nav

fix: portfolio values, Yahoo UA header, mobile hamburger nav
This commit is contained in:
Gonçalo Rodrigues 2026-06-13 19:37:39 +01:00 committed by GitHub
commit 1b9284801c
2 changed files with 100 additions and 4 deletions

View File

@ -413,17 +413,67 @@
.animate-on-scroll:nth-child(4) { transition-delay: 0.21s; } .animate-on-scroll:nth-child(4) { transition-delay: 0.21s; }
.animate-on-scroll:nth-child(5) { transition-delay: 0.28s; } .animate-on-scroll:nth-child(5) { transition-delay: 0.28s; }
/* ── Hamburger / mobile drawer ────────────────────────────────────── */
.nav-hamburger {
display: none;
width: 36px; height: 36px;
border: none; background: none; cursor: pointer;
color: var(--text2);
flex-direction: column; justify-content: center; align-items: center; gap: 5px;
border-radius: var(--radius-sm);
transition: background 0.18s;
}
.nav-hamburger:hover { background: var(--surface2); }
.nav-hamburger span {
display: block; width: 20px; height: 2px;
background: currentColor; border-radius: 2px;
transition: transform 0.25s ease, opacity 0.25s ease;
}
.nav-hamburger.open span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav-hamburger.open span:nth-child(2) { opacity: 0; }
.nav-hamburger.open span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }
.nav-drawer {
display: none;
position: fixed; inset: var(--nav-h) 0 0 0;
background: var(--bg);
z-index: 199;
overflow-y: auto;
padding: 12px 16px 32px;
flex-direction: column; gap: 4px;
animation: slideIn 0.2s ease-out both;
}
.nav-drawer.open { display: flex; }
.nav-drawer a, .nav-drawer-section-label {
display: block;
padding: 11px 14px;
border-radius: var(--radius-sm);
font-size: 15px; font-weight: 500;
color: var(--text2); text-decoration: none;
transition: all 0.15s;
}
.nav-drawer a:hover { color: var(--text); background: var(--surface2); }
.nav-drawer a.active { color: var(--accent2); background: var(--accent-glow); }
.nav-drawer-section-label {
font-size: 11px; font-weight: 600; letter-spacing: 0.08em;
text-transform: uppercase; color: var(--text3);
padding-top: 16px; padding-bottom: 4px;
}
.nav-drawer hr { border: none; border-top: 1px solid var(--border); margin: 8px 0; }
/* ── Responsive ──────────────────────────────────────────────────── */ /* ── Responsive ──────────────────────────────────────────────────── */
@media (max-width: 900px) { @media (max-width: 900px) {
.grid-2 { grid-template-columns: 1fr; } .grid-2 { grid-template-columns: 1fr; }
} }
@media (max-width: 600px) { @media (max-width: 720px) {
.nav { padding: 0 12px; gap: 2px; overflow-x: auto; } .nav-hamburger { display: flex; }
.nav a:not(.nav-brand) { padding: 6px 7px; font-size: 12px; } .nav > a:not(.nav-brand),
.nav > .nav-group,
.nav > .nav-spacer,
.nav-email { display: none; }
.container { padding: 16px 12px 32px; } .container { padding: 16px 12px 32px; }
.grid { grid-template-columns: 1fr 1fr; } .grid { grid-template-columns: 1fr 1fr; }
.card { padding: 16px; } .card { padding: 16px; }
.nav-email { display: none; }
} }
</style> </style>
</head> </head>
@ -469,8 +519,32 @@
<div class="nav-spacer"></div> <div class="nav-spacer"></div>
<span class="nav-email">{{.Email}}</span> <span class="nav-email">{{.Email}}</span>
<button class="theme-btn" id="theme-toggle" title="Toggle dark/light mode">🌙</button> <button class="theme-btn" id="theme-toggle" title="Toggle dark/light mode">🌙</button>
<button class="nav-hamburger" id="nav-hamburger" aria-label="Menu">
<span></span><span></span><span></span>
</button>
</nav> </nav>
<!-- Mobile drawer -->
<div class="nav-drawer" id="nav-drawer">
<a href="/" class="{{if eq .Route "dashboard"}}active{{end}}">Dashboard</a>
<a href="/transactions" class="{{if eq .Route "transactions"}}active{{end}}">Transactions</a>
<a href="/portfolio" class="{{if eq .Route "portfolio"}}active{{end}}">Portfolio</a>
<a href="/goals" class="{{if eq .Route "goals"}}active{{end}}">Goals</a>
<a href="/people" class="{{if eq .Route "people"}}active{{end}}">People</a>
<hr>
<span class="nav-drawer-section-label">Analysis</span>
<a href="/reports" class="{{if eq .Route "reports"}}active{{end}}">Reports</a>
<a href="/projections" class="{{if eq .Route "projections"}}active{{end}}">Projections</a>
<a href="/tax" class="{{if eq .Route "tax"}}active{{end}}">Tax</a>
<a href="/networth" class="{{if eq .Route "networth"}}active{{end}}">Net Worth</a>
<a href="/simulator" class="{{if eq .Route "simulator"}}active{{end}}">What If</a>
<hr>
<span class="nav-drawer-section-label">Settings</span>
<a href="/settings?tab=accounts" class="{{if eq .Route "settings"}}active{{end}}">Accounts &amp; Categories</a>
<a href="/import" class="{{if eq .Route "import"}}active{{end}}">Import CSV</a>
<a href="/auto-import" class="{{if eq .Route "auto-import"}}active{{end}}">Import Guide</a>
</div>
<div class="container"> <div class="container">
{{block "content" .}}{{end}} {{block "content" .}}{{end}}
</div> </div>
@ -493,6 +567,22 @@
btn.addEventListener('click', () => btn.addEventListener('click', () =>
applyTheme(html.getAttribute('data-theme') === 'dark' ? 'light' : 'dark')); applyTheme(html.getAttribute('data-theme') === 'dark' ? 'light' : 'dark'));
/* ── Mobile hamburger ─────────────────────────────────────────── */
const hamburger = document.getElementById('nav-hamburger');
const drawer = document.getElementById('nav-drawer');
hamburger.addEventListener('click', () => {
const open = drawer.classList.toggle('open');
hamburger.classList.toggle('open', open);
document.body.style.overflow = open ? 'hidden' : '';
});
drawer.querySelectorAll('a').forEach(a =>
a.addEventListener('click', () => {
drawer.classList.remove('open');
hamburger.classList.remove('open');
document.body.style.overflow = '';
})
);
/* ── Animated counter ─────────────────────────────────────────── */ /* ── Animated counter ─────────────────────────────────────────── */
function animateCounter(el) { function animateCounter(el) {
const target = parseFloat(el.getAttribute('data-target')); const target = parseFloat(el.getAttribute('data-target'));

View File

@ -0,0 +1,6 @@
date,name,isin,type,quantity,price,total,currency
2024-01-10,iShares S&P 500 IT Sector,IE00B3WJKG14,buy,0.5,60.00,30.00,EUR
2024-01-15,Vanguard FTSE All-World,IE00B3RBWM25,buy,1.0,100.00,100.00,EUR
2024-01-20,iShares Core S&P 500,IE00B5BMR087,buy,2.0,50.00,100.00,EUR
2024-02-05,iShares S&P 500 IT Sector,IE00B3WJKG14,buy,1.0,62.00,62.00,EUR
2024-02-10,Vanguard FTSE All-World,IE00B3RBWM25,buy,0.5,105.00,52.50,EUR
1 date name isin type quantity price total currency
2 2024-01-10 iShares S&P 500 IT Sector IE00B3WJKG14 buy 0.5 60.00 30.00 EUR
3 2024-01-15 Vanguard FTSE All-World IE00B3RBWM25 buy 1.0 100.00 100.00 EUR
4 2024-01-20 iShares Core S&P 500 IE00B5BMR087 buy 2.0 50.00 100.00 EUR
5 2024-02-05 iShares S&P 500 IT Sector IE00B3WJKG14 buy 1.0 62.00 62.00 EUR
6 2024-02-10 Vanguard FTSE All-World IE00B3RBWM25 buy 0.5 105.00 52.50 EUR