Mobile Phase 8i: bottom-tab SVG line-icons + ·Ten31· top-bar wordmark

Replace the four bottom-tab emoji glyphs with the dc tabIcon SVGs
(BottomTabIcon, currentColor so they flip with active/theme) and add the
·Ten31· mobile-wordmark to the top bar, making the page title desktop-only.
Closes S1/S2 — Phase 8 (8a–8i) complete; next is deploy + device-test.
This commit is contained in:
Keysat
2026-06-20 07:49:26 -05:00
parent 707a270922
commit 81ed6cbbab
3 changed files with 74 additions and 15 deletions
+4 -4
View File
File diff suppressed because one or more lines are too long
+6 -3
View File
@@ -194,9 +194,12 @@ The **per-surface mobile visual-conformance reference** is `design/phase8-confor
text pill, 4-stage chip, Contacts avatar ring (see the §4 mobile-card bullet). The **Contacts +
Pipeline detail surfaces are drag-dismiss bottom sheets (Phase 8b)** — email-copy pill + Log/Email
actions + Organization card (Contacts); stat tiles + inline move-stage list + notes timeline + Log
sheet (Pipeline); both log through `POST /api/communications`. Remaining 8c8i (quick-log pencil,
sort sheets, reminders/Pipeline-card polish, add-investor, shell icons) are pending; the Grid detail
stays full-screen (its dc default) with the G4/G5/G6 stage-card/reminder-card/timeline restructure to do.
sheet (Pipeline); both log through `POST /api/communications`. **Phase 8 is complete (8a8i)**
8c8h added the quick-log pencil, sort sheets, reminders/Pipeline-card polish, add-investor sheet,
and the Grid detail's G4/G5/G6 stage-card/reminder-card/timeline restructure; **8i** swapped the
bottom-tab emoji glyphs for the dc SVG line-icons (`BottomTabIcon`) and added the `·Ten31·` top-bar
wordmark (the page title is now desktop-only). The Grid detail stays full-screen (its dc default).
What remains is **deploy + real-phone device-test** (light/dark), not further build.
## 9. Agent prompt guide
+64 -8
View File
@@ -2084,7 +2084,7 @@
transition: color 0.15s ease;
}
.bottom-tab.active { color: var(--accent); }
.bottom-tab-icon { font-size: 20px; line-height: 1; }
.bottom-tab-icon { display: flex; align-items: center; justify-content: center; width: 20px; height: 20px; }
.bottom-tab-label {
font-family: 'IBM Plex Mono', monospace;
font-size: var(--mobile-font-tab-label);
@@ -2093,6 +2093,16 @@
text-transform: uppercase;
}
/* Mobile top-bar wordmark (Phase 8i) — the dc top bar's left mark (GridApp.dc.html:51).
Replaces the redundant page title on mobile (each surface renders its own heading). */
.mobile-wordmark {
font-family: 'IBM Plex Mono', monospace;
font-weight: 600;
font-size: 15px;
letter-spacing: 0.04em;
color: var(--text-primary);
}
/* Bottom-sheet primitive — replaces the centered modal + right slide-over on mobile.
Rendered by the <BottomSheet> component; `.open` is toggled to animate in. */
.sheet-scrim {
@@ -14089,6 +14099,51 @@
);
};
// Bottom-tab line-icons (Phase 8i) — the dc tabIcon SVGs (GridApp.dc.html:585),
// replacing the prior emoji glyphs. Strokes/fills are currentColor so each icon
// inherits its .bottom-tab color: --text-subtle inactive, --accent when active,
// and it flips automatically across the light/dark themes.
const BottomTabIcon = ({ name }) => {
const common = { width: 20, height: 20, viewBox: '0 0 20 20', fill: 'none', 'aria-hidden': 'true' };
if (name === 'grid') {
return (
<svg {...common} stroke="currentColor" strokeWidth="1.6">
<rect x="3" y="3" width="6" height="6" rx="1" />
<rect x="11" y="3" width="6" height="6" rx="1" />
<rect x="3" y="11" width="6" height="6" rx="1" />
<rect x="11" y="11" width="6" height="6" rx="1" />
</svg>
);
}
if (name === 'pipeline') {
return (
<svg {...common}>
<rect x="3" y="3" width="4.5" height="14" rx="1" stroke="currentColor" strokeWidth="1.6" />
<rect x="9.25" y="3" width="4.5" height="10" rx="1" stroke="currentColor" strokeWidth="1.6" />
<rect x="15.5" y="3" width="1.5" height="6" rx="0.7" fill="currentColor" />
</svg>
);
}
if (name === 'reminders') {
return (
<svg {...common} stroke="currentColor" strokeWidth="1.6" strokeLinecap="round">
<circle cx="10" cy="11" r="6.2" />
<line x1="10" y1="11" x2="10" y2="7.5" />
<line x1="10" y1="11" x2="12.4" y2="12" />
<line x1="7" y1="3.4" x2="4.4" y2="5.4" />
<line x1="13" y1="3.4" x2="15.6" y2="5.4" />
</svg>
);
}
// contacts — head + shoulders
return (
<svg {...common} stroke="currentColor" strokeWidth="1.6" strokeLinecap="round">
<circle cx="10" cy="7" r="3.2" />
<path d="M4 16.5c0-3 2.7-4.8 6-4.8s6 1.8 6 4.8" />
</svg>
);
};
// Quick-log — the dc top-bar pencil (GridApp:53-55): log a communication against any investor
// without first opening its detail. Two steps: pick an investor (search + recent-first pool) →
// inline log form. Writes via the one-row /api/fundraising/log-communication path (same write
@@ -14484,8 +14539,9 @@
<div className="main-content">
<div className="header">
<div style={{ display: 'flex', alignItems: 'center', gap: '10px' }}>
{sidebarHidden && <button className="sidebar-toggle" onClick={() => setSidebarHidden(false)}>Show Menu</button>}
<div className="header-title">
{sidebarHidden && <button className="sidebar-toggle desktop-only" onClick={() => setSidebarHidden(false)}>Show Menu</button>}
<span className="mobile-wordmark mobile-only">·Ten31·</span>
<div className="header-title desktop-only">
{page === 'fundraising-grid' && 'Fundraising Grid'}
{page === 'dashboard' && 'Dashboard'}
{page === 'contacts' && 'Contacts'}
@@ -14593,10 +14649,10 @@
desktop nav. Other destinations are intentionally absent on mobile. */}
<nav className="bottom-tab-bar" aria-label="Primary">
{[
{ id: 'fundraising-grid', icon: '', label: 'Grid' },
{ id: 'pipeline', icon: '', label: 'Pipeline' },
{ id: 'reminders', icon: '', label: 'Reminders' },
{ id: 'contacts', icon: '', label: 'Contacts' },
{ id: 'fundraising-grid', icon: 'grid', label: 'Grid' },
{ id: 'pipeline', icon: 'pipeline', label: 'Pipeline' },
{ id: 'reminders', icon: 'reminders', label: 'Reminders' },
{ id: 'contacts', icon: 'contacts', label: 'Contacts' },
].map((t) => (
<button
key={t.id}
@@ -14604,7 +14660,7 @@
onClick={() => setPage(t.id)}
aria-current={page === t.id ? 'page' : undefined}
>
<span className="bottom-tab-icon">{t.icon}</span>
<span className="bottom-tab-icon"><BottomTabIcon name={t.icon} /></span>
<span className="bottom-tab-label">{t.label}</span>
</button>
))}