Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion Components/App.razor
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@

<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
<meta name="theme-color" content="#dbeeff" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="default" />
<base href="/" />
<link rel="stylesheet" href="@Assets["lib/bootstrap/dist/css/bootstrap.min.css"]" />
<link rel="stylesheet" href="@Assets["theme.css"]" />
Expand Down
2 changes: 1 addition & 1 deletion Components/Layout/MainLayout.razor
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
</div>

<main>
<article class="content px-4">
<article class="content">
@Body
</article>
</main>
Expand Down
144 changes: 62 additions & 82 deletions Components/Layout/MainLayout.razor.css
Original file line number Diff line number Diff line change
@@ -1,111 +1,91 @@
/*
* App shell.
*
* Phone: one column. The brand bar is sticky at the top, content scrolls
* under it, and the tab bar is pinned to the bottom. To let those two be
* placed independently, `.sidebar` is dissolved with `display: contents`
* so the elements NavMenu renders become direct children of `.page`.
* NavMenu.razor.css owns how they look in both layouts.
*
* Desktop (>= 48rem): `.sidebar` becomes a real box again and the page
* turns into a two-column row with a sticky glass rail on the left.
*/

.page {
position: relative;
display: flex;
flex-direction: column;
min-height: 100dvh;
}

.sidebar {
display: contents;
}

main {
flex: 1;
/* Without this, a page whose content has a wide intrinsic minimum
width (e.g. Financials' summary grid/tables) refuses to shrink
below that width by default, forcing .page wider than the
viewport and squeezing .sidebar - "crushing" the nav text (#196). */
below that width by default, forcing .page wider than the viewport
and squeezing the nav - "crushing" it (#196). */
min-width: 0;
padding-top: 0.75rem;
padding-right: calc(1rem + var(--safe-right));
padding-left: calc(1rem + var(--safe-left));
/* Clear the fixed tab bar, and the home indicator underneath it. */
padding-bottom: calc(var(--tab-bar-height) + var(--safe-bottom) + 1.5rem);
}

.sidebar {
background-image: linear-gradient(180deg, var(--sidebar-from) 0%, var(--sidebar-to) 70%);
/* Keep the sidebar at its intended width regardless of how wide any
page's content gets - main should scroll internally, not compress
the nav (#196). */
flex-shrink: 0;
}

.top-row {
background-color: var(--topbar-bg);
border-bottom: 1px solid var(--topbar-border);
justify-content: flex-end;
height: 3.5rem;
display: flex;
align-items: center;
}

.top-row ::deep a,
.top-row ::deep .btn-link {
white-space: nowrap;
margin-left: 1.5rem;
text-decoration: none;
}

.top-row ::deep a:hover,
.top-row ::deep .btn-link:hover {
text-decoration: underline;
}

.top-row ::deep a:first-child {
overflow: hidden;
text-overflow: ellipsis;
/*
* Blazor's unhandled-error toast is fixed to the bottom of the viewport,
* which is exactly where the tab bar now lives. Lift it clear.
*/
#blazor-error-ui {
color-scheme: light only;
position: fixed;
bottom: calc(var(--tab-bar-height) + var(--safe-bottom));
left: 0;
z-index: 1000;
display: none;
box-sizing: border-box;
width: 100%;
padding: 0.6rem 1.25rem 0.7rem;
background: var(--error-toast-bg);
box-shadow: var(--shadow-toast);
}

@media (max-width: 640.98px) {
.top-row {
justify-content: space-between;
}

.top-row ::deep a,
.top-row ::deep .btn-link {
margin-left: 0;
}
#blazor-error-ui .dismiss {
position: absolute;
top: 0.5rem;
right: 0.75rem;
cursor: pointer;
}

@media (min-width: 641px) {
@media (min-width: 48rem) {
.page {
flex-direction: row;
}

.sidebar {
width: 250px;
height: 100vh;
position: sticky;
top: 0;
}

.top-row {
display: block;
position: sticky;
top: 0;
z-index: 1;
/* Hold the rail at its intended width however wide the page's
content gets: main should scroll internally, not compress the
nav (#196). */
flex-shrink: 0;
width: var(--nav-rail-width);
height: 100dvh;
border-right: 1px solid var(--glass-hairline);
background: var(--glass-bg);
backdrop-filter: var(--glass-blur-strong);
-webkit-backdrop-filter: var(--glass-blur-strong);
}

.top-row.auth ::deep a:first-child {
flex: 1;
text-align: right;
width: 0;
main {
padding: 2rem 2.5rem 3rem;
}

.top-row,
article {
padding-left: 2rem !important;
padding-right: 1.5rem !important;
#blazor-error-ui {
bottom: 0;
}
}

#blazor-error-ui {
color-scheme: light only;
background: var(--error-toast-bg);
bottom: 0;
box-shadow: var(--shadow-toast);
box-sizing: border-box;
display: none;
left: 0;
padding: 0.6rem 1.25rem 0.7rem 1.25rem;
position: fixed;
width: 100%;
z-index: 1000;
}

#blazor-error-ui .dismiss {
cursor: pointer;
position: absolute;
right: 0.75rem;
top: 0.5rem;
}
104 changes: 52 additions & 52 deletions Components/Layout/NavMenu.razor
Original file line number Diff line number Diff line change
@@ -1,56 +1,56 @@
<div class="top-row ps-3 navbar navbar-dark">
<div class="container-fluid">
<a class="navbar-brand" href="">
<span class="brand-logo" aria-hidden="true"></span>Money Mirror
</a>
</div>
@*
Primary navigation.

One set of links, two presentations: a bottom tab bar on a phone, a
side rail on a desktop. Which one you get is decided entirely in
NavMenu.razor.css at the 48rem breakpoint - this markup is identical
either way, so there is no second copy of the links to keep in step.

Each link is an icon plus a label. The icon spans are written here
rather than inside NavLink so they pick up this component's scope
attribute; the <a> that NavLink renders does not, which is why the
stylesheet reaches it through ::deep.
*@

<div class="top-row">
<a class="navbar-brand" href="">
<span class="brand-logo" aria-hidden="true"></span>
<span class="brand-name">Money Mirror</span>
</a>
</div>

<input type="checkbox" title="Navigation menu" class="navbar-toggler" />

<div class="nav-scrollable" onclick="document.querySelector('.navbar-toggler').click()">
<nav class="nav flex-column">

<!-- Dashboard -->
<div class="nav-item px-3">
<NavLink class="nav-link" href="" Match="NavLinkMatch.All">
<span class="bi bi-house-door-fill-nav-menu" aria-hidden="true"></span> Dashboard
</NavLink>
</div>

<!-- Financial -->
<div class="nav-item px-3">
<NavLink class="nav-link" href="financials">
<span class="bi bi-coin-fill-nav-menu" aria-hidden="true"></span> Financial
</NavLink>
</div>

<!-- Physical Assets -->
<div class="nav-item px-3">
<NavLink class="nav-link" href="physical-assets">
<span class="bi bi-plus-square-fill-nav-menu" aria-hidden="true"></span> Physical Assets
</NavLink>
</div>

<!-- Inventory -->
<div class="nav-item px-3">
<NavLink class="nav-link" href="inventory">
<span class="bi bi-backpack-fill-nav-menu" aria-hidden="true"></span> Inventory
</NavLink>
</div>

<!-- Human Capital -->
<div class="nav-item px-3">
<NavLink class="nav-link" href="human-capital">
<span class="bi bi-mortarboard-fill-nav-menu" aria-hidden="true"></span> Human Capital
</NavLink>
</div>

<!-- Market Potential -->
<div class="nav-item px-3">
<NavLink class="nav-link" href="/market-potential" Match="NavLinkMatch.All">
<span class="bi bi-bar-chart-line-fill-nav-menu" aria-hidden="true"></span> Market Potential
</NavLink>
</div>
<div class="nav-scrollable">
<nav class="nav-list" aria-label="Primary">

<NavLink class="nav-link" href="" Match="NavLinkMatch.All">
<span class="nav-icon bi-house-door-fill-nav-menu" aria-hidden="true"></span>
<span class="nav-label">Dashboard</span>
</NavLink>

<NavLink class="nav-link" href="financials">
<span class="nav-icon bi-coin-fill-nav-menu" aria-hidden="true"></span>
<span class="nav-label">Financial</span>
</NavLink>

<NavLink class="nav-link" href="physical-assets">
<span class="nav-icon bi-plus-square-fill-nav-menu" aria-hidden="true"></span>
<span class="nav-label">Physical Assets</span>
</NavLink>

<NavLink class="nav-link" href="inventory">
<span class="nav-icon bi-backpack-fill-nav-menu" aria-hidden="true"></span>
<span class="nav-label">Inventory</span>
</NavLink>

<NavLink class="nav-link" href="human-capital">
<span class="nav-icon bi-mortarboard-fill-nav-menu" aria-hidden="true"></span>
<span class="nav-label">Human Capital</span>
</NavLink>

<NavLink class="nav-link" href="/market-potential" Match="NavLinkMatch.All">
<span class="nav-icon bi-bar-chart-line-fill-nav-menu" aria-hidden="true"></span>
<span class="nav-label">Market Potential</span>
</NavLink>

</nav>
</div>
Loading
Loading