Browse Source

Gui and UI rules and updates

main
Daniel Covington 1 day ago
parent
commit
6062b68617
4 changed files with 695 additions and 0 deletions
  1. +91
    -0
      AGENTS.md
  2. +53
    -0
      docker-publish.ps1
  3. +99
    -0
      docs/ux-color-themes.html
  4. +452
    -0
      docs/ux-design-directions.html

+ 91
- 0
AGENTS.md View File

@@ -908,3 +908,94 @@ Browser → public/index.php → Request → Dispatcher → Router → Route →

## Creating Table
When you create tables and code for a table you will need a corrisponding _audit table with audit_id , id that refrences the object id , an action R I U D , the fields in json , username and created at

### Color System

Visual direction: calm operational clarity with high-signal status semantics.

Core palette:
- Primary: `#1F4E79` (municipal navy; trust and structure)
- Secondary: `#0F766E` (teal support/action)
- Accent: `#2563EB` (interactive focus/action emphasis)

Semantic status palette:
- Success / On Track: `#2E7D32`
- Warning / At Risk: `#B45309`
- Error / Blocked: `#B91C1C`
- Info / Neutral Progress: `#2563EB`
- Overdue / Critical Flag: `#7F1D1D`

Neutral foundation:
- Background: `#F7F9FC`
- Surface: `#FFFFFF`
- Border: `#D0D7E2`
- Primary Text: `#111827`
- Secondary Text: `#4B5563`

Ant Design token strategy:
- Configure global tokens first (`colorPrimary`, `colorSuccess`, `colorWarning`, `colorError`, `colorInfo`, `colorBgBase`, `colorText`, `borderRadius`, density-related sizing).
- Keep status meaning consistent across tables, tags, timelines, and alerts.

### Typography System

Tone: professional, clear, non-decorative, optimized for dense operational reading.

Type stack:
- Primary UI text: `Public Sans`, `Segoe UI`, `Arial`, sans-serif
- Data-heavy/labels fallback: `IBM Plex Sans`, `Segoe UI`, sans-serif
- Monospace for IDs/reference codes: `IBM Plex Mono`, `Consolas`, monospace

Type hierarchy (desktop-first):
- H1: 28px / 36px / 600
- H2: 22px / 30px / 600
- H3: 18px / 26px / 600
- Body default: 14px / 22px / 400
- Dense table/body compact: 13px / 20px / 400
- Caption/meta: 12px / 18px / 400

Typography principles:
- Prioritize legibility over brand flourish.
- Keep numeric/date fields highly scannable.
- Use consistent casing and label patterns for form-heavy workflows.

### Spacing & Layout Foundation

Layout direction: compact, structured, desktop-optimized operational workspace.

Spacing system:
- Base unit: 8px
- Micro spacing for dense table controls: 4px
- Section spacing rhythm: 16px / 24px / 32px

Grid and containers:
- Desktop-first 12-column grid
- Content max-width bands for readability in wide monitors
- Persistent side regions for risk queue/filter panels when useful

Component density rules:
- Default to compact controls for grid and forms
- Keep touch-target inflation out of scope (PC-only product)
- Reserve larger spacing only for high-risk confirmations/modals

Visual rhythm:
- Clear row grouping and section boundaries
- Strong alignment around key operational identifiers (municipality, cycle, status, due date)

### Accessibility Considerations

- WCAG 2.2 AA minimum contrast targets:
- 4.5:1 for normal text
- 3:1 for large text and UI components
- Keyboard-first operation:
- Visible 2px focus indicators on interactive elements
- Logical tab order in grids, forms, drawers, and modals
- Do not rely on color alone:
- Pair status colors with labels/icons/patterns
- Motion and feedback:
- Subtle motion only for orientation, not decoration
- Respect reduced-motion preferences
- Dense-data readability:
- Preserve minimum font sizes and row heights that remain readable during long operational sessions

# UI desgin
- Refer to template info in the files docs\ux-color-themes.html and docs\ux-design-directions.html

+ 53
- 0
docker-publish.ps1 View File

@@ -0,0 +1,53 @@
#Requires -Version 5.1
<#
.SYNOPSIS
Builds the Campaign Tracker Docker image and pushes it to the private registry.
.EXAMPLE
.\docker-publish.ps1
.\docker-publish.ps1 -SkipBuild # push a previously built image
#>

param(
[switch]$SkipBuild
)

Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"

# ---------------------------------------------------------------------------
# Configuration
# ---------------------------------------------------------------------------
$REGISTRY_HOST = "192.168.1.200" # change port if needed, e.g. "192.168.1.200:5000"
$IMAGE_NAME = "campaign-tracker"
$FULL_TAG = "$REGISTRY_HOST/$IMAGE_NAME`:latest"

# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------
function Write-Step([string]$msg) {
Write-Host "`n==> $msg" -ForegroundColor Cyan
}

function Assert-DockerRunning {
docker info > $null 2>&1
if ($LASTEXITCODE -ne 0) {
Write-Error "Docker is not running or not reachable. Start Docker Desktop and retry."
}
}

# ---------------------------------------------------------------------------
# Main
# ---------------------------------------------------------------------------
Assert-DockerRunning

if (-not $SkipBuild) {
Write-Step "Building image: $FULL_TAG"
docker build --tag $FULL_TAG .
if ($LASTEXITCODE -ne 0) { Write-Error "docker build failed (exit $LASTEXITCODE)." }
}

Write-Step "Pushing image: $FULL_TAG"
docker push $FULL_TAG
if ($LASTEXITCODE -ne 0) { Write-Error "docker push failed (exit $LASTEXITCODE)." }

Write-Host "`nDone. Image available at $FULL_TAG" -ForegroundColor Green

+ 99
- 0
docs/ux-color-themes.html View File

@@ -0,0 +1,99 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>UX Color Themes - Campaign_Tracker App</title>
<style>
body {
margin: 0;
font-family: "Public Sans", "Segoe UI", Arial, sans-serif;
background: #f3f6fb;
color: #111827;
}
.wrap {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
h1 { margin: 0 0 8px; font-size: 22px; }
p { margin: 0 0 18px; color: #4b5563; }
.grid {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 14px;
}
.card {
background: #fff;
border: 1px solid #d1d5db;
border-radius: 10px;
overflow: hidden;
}
.head {
padding: 10px 12px;
border-bottom: 1px solid #e5e7eb;
font-weight: 600;
font-size: 14px;
}
.swatches {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 8px;
padding: 10px;
}
.sw {
border: 1px solid #e5e7eb;
border-radius: 8px;
overflow: hidden;
font-size: 11px;
}
.color {
height: 38px;
}
.label {
padding: 5px 6px;
background: #fff;
color: #374151;
}
@media (max-width: 980px) {
.grid { grid-template-columns: 1fr; }
}
</style>
</head>
<body>
<div class="wrap">
<h1>Color Theme Visualizer</h1>
<p>Primary candidate is Theme A (Municipal Calm). Status semantics remain consistent across all options.</p>
<div class="grid">
<section class="card">
<div class="head">Theme A - Municipal Calm (Selected)</div>
<div class="swatches">
<div class="sw"><div class="color" style="background:#1F4E79"></div><div class="label">Primary #1F4E79</div></div>
<div class="sw"><div class="color" style="background:#0F766E"></div><div class="label">Secondary #0F766E</div></div>
<div class="sw"><div class="color" style="background:#2E7D32"></div><div class="label">Success #2E7D32</div></div>
<div class="sw"><div class="color" style="background:#B45309"></div><div class="label">Warning #B45309</div></div>
</div>
</section>
<section class="card">
<div class="head">Theme B - Slate Ops</div>
<div class="swatches">
<div class="sw"><div class="color" style="background:#334155"></div><div class="label">Primary #334155</div></div>
<div class="sw"><div class="color" style="background:#0369A1"></div><div class="label">Secondary #0369A1</div></div>
<div class="sw"><div class="color" style="background:#15803D"></div><div class="label">Success #15803D</div></div>
<div class="sw"><div class="color" style="background:#D97706"></div><div class="label">Warning #D97706</div></div>
</div>
</section>
<section class="card">
<div class="head">Theme C - Civic Teal</div>
<div class="swatches">
<div class="sw"><div class="color" style="background:#0F766E"></div><div class="label">Primary #0F766E</div></div>
<div class="sw"><div class="color" style="background:#1D4ED8"></div><div class="label">Secondary #1D4ED8</div></div>
<div class="sw"><div class="color" style="background:#2E7D32"></div><div class="label">Success #2E7D32</div></div>
<div class="sw"><div class="color" style="background:#B45309"></div><div class="label">Warning #B45309</div></div>
</div>
</section>
</div>
</div>
</body>
</html>


+ 452
- 0
docs/ux-design-directions.html View File

@@ -0,0 +1,452 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>UX Design Directions - Campaign_Tracker App</title>
<style>
:root {
--bg: #f7f9fc;
--surface: #ffffff;
--text: #111827;
--muted: #4b5563;
--border: #d0d7e2;
--primary: #1f4e79;
--accent: #2563eb;
--ok: #2e7d32;
--warn: #b45309;
--err: #b91c1c;
--radius: 10px;
}

* { box-sizing: border-box; }
body {
margin: 0;
background: var(--bg);
color: var(--text);
font: 14px/1.5 "Public Sans", "Segoe UI", Arial, sans-serif;
}

.topbar {
position: sticky;
top: 0;
z-index: 10;
background: #0f172a;
color: #e5e7eb;
border-bottom: 1px solid #1f2937;
padding: 12px 18px;
display: flex;
flex-wrap: wrap;
gap: 12px;
align-items: center;
justify-content: space-between;
}

.topbar h1 {
margin: 0;
font-size: 16px;
letter-spacing: 0.01em;
font-weight: 600;
}

.legend {
display: flex;
gap: 8px;
flex-wrap: wrap;
}

.pill {
border: 1px solid #334155;
border-radius: 999px;
padding: 2px 10px;
font-size: 12px;
background: #111827;
color: #cbd5e1;
}

.wrap {
max-width: 1480px;
margin: 0 auto;
padding: 20px;
display: grid;
gap: 16px;
grid-template-columns: repeat(12, minmax(0, 1fr));
}

.summary {
grid-column: span 12;
background: var(--surface);
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 14px 16px;
}

.summary h2 {
margin: 0 0 6px;
font-size: 16px;
}

.grid {
grid-column: span 12;
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 16px;
}

.card {
background: var(--surface);
border: 1px solid var(--border);
border-radius: var(--radius);
overflow: hidden;
box-shadow: 0 1px 0 rgba(15, 23, 42, 0.06);
}

.card:hover {
border-color: #9fb6d6;
box-shadow: 0 8px 28px rgba(31, 78, 121, 0.15);
transform: translateY(-1px);
transition: all 0.2s ease;
}

.card-head {
padding: 12px 14px;
border-bottom: 1px solid var(--border);
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
}

.card-head h3 {
margin: 0;
font-size: 14px;
font-weight: 600;
}

.tag {
font-size: 11px;
border-radius: 999px;
border: 1px solid #c7d2fe;
background: #eef2ff;
color: #3730a3;
padding: 2px 8px;
white-space: nowrap;
}

.preview {
background: #f8fafc;
min-height: 320px;
padding: 10px;
}

.mock {
height: 100%;
border: 1px solid #cbd5e1;
border-radius: 8px;
background: white;
overflow: hidden;
display: grid;
}

.mock-top {
border-bottom: 1px solid #e2e8f0;
background: #f8fafc;
height: 34px;
display: flex;
align-items: center;
padding: 0 10px;
gap: 8px;
color: #334155;
font-size: 12px;
}

.dot {
width: 8px;
height: 8px;
border-radius: 999px;
background: #94a3b8;
}

.body-a { grid-template-columns: 220px 1fr 280px; }
.body-b { grid-template-columns: 1fr 340px; }
.body-c { grid-template-columns: 220px 1fr; grid-template-rows: 1fr 130px; }
.body-d { grid-template-columns: 1fr; grid-template-rows: 72px 1fr; }
.body-e { grid-template-columns: 260px 1fr; }
.body-f { grid-template-columns: 1fr; }

.pane {
border-right: 1px solid #e2e8f0;
padding: 8px;
background: #fff;
}
.pane:last-child { border-right: 0; }
.pane.soft { background: #f8fafc; }
.pane.dark {
background: #0f172a;
color: #cbd5e1;
border-right: 1px solid #1e293b;
}

.lane {
margin-bottom: 8px;
border: 1px solid #e2e8f0;
border-radius: 6px;
padding: 6px 8px;
font-size: 12px;
background: #ffffff;
}

.lane.ok { border-left: 4px solid var(--ok); }
.lane.warn { border-left: 4px solid var(--warn); }
.lane.err { border-left: 4px solid var(--err); }

.data-table {
width: 100%;
border-collapse: collapse;
font-size: 12px;
}
.data-table th,
.data-table td {
border: 1px solid #e2e8f0;
padding: 4px 6px;
text-align: left;
}
.data-table th {
background: #eff6ff;
color: #1e3a8a;
font-weight: 600;
}

.chip {
font-size: 11px;
padding: 1px 6px;
border-radius: 999px;
border: 1px solid #dbeafe;
background: #eff6ff;
color: #1d4ed8;
}
.chip.ok { background: #ecfdf5; border-color: #bbf7d0; color: #166534; }
.chip.warn { background: #fffbeb; border-color: #fde68a; color: #92400e; }
.chip.err { background: #fef2f2; border-color: #fecaca; color: #991b1b; }

.notes {
padding: 10px 14px 14px;
border-top: 1px solid var(--border);
color: #334155;
font-size: 12px;
background: #fcfdff;
}
.notes strong { color: #0f172a; }

.footer {
grid-column: span 12;
background: var(--surface);
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 12px 14px;
color: #334155;
font-size: 13px;
}

@media (max-width: 1180px) {
.grid { grid-template-columns: 1fr; }
}
</style>
</head>
<body>
<header class="topbar">
<h1>Design Direction Showcase • Campaign_Tracker App</h1>
<div class="legend">
<span class="pill">PC-first</span>
<span class="pill">Ant Design Foundation</span>
<span class="pill">Dense Operations UX</span>
<span class="pill">Status + Provenance Visible</span>
</div>
</header>

<main class="wrap">
<section class="summary">
<h2>How to Evaluate</h2>
Compare directions by layout intuitiveness, risk visibility, editing clarity, and workflow speed under deadline pressure.
</section>

<section class="grid">
<article class="card">
<div class="card-head">
<h3>Direction 1: Operations Command Desk</h3>
<span class="tag">Tri-pane control</span>
</div>
<div class="preview">
<div class="mock" style="grid-template-rows:34px 1fr;">
<div class="mock-top"><span class="dot"></span><span class="dot"></span><span class="dot"></span> Command Desk / Election Cycle Workspace</div>
<div class="mock body-a">
<aside class="pane dark">
<div class="lane">Municipalities</div>
<div class="lane">Election Cycles</div>
<div class="lane">Saved Filters</div>
</aside>
<section class="pane">
<table class="data-table">
<thead><tr><th>Town</th><th>Cycle</th><th>Milestone</th><th>Status</th></tr></thead>
<tbody>
<tr><td>Northfield</td><td>2026-Q3</td><td>Addressing</td><td><span class="chip warn">At Risk</span></td></tr>
<tr><td>Oak Hills</td><td>2026-Q3</td><td>Sort Complete</td><td><span class="chip ok">On Track</span></td></tr>
<tr><td>Lakeview</td><td>2026-Q3</td><td>Dispatch</td><td><span class="chip err">Blocked</span></td></tr>
</tbody>
</table>
</section>
<aside class="pane soft">
<div class="lane err">Cutoff Risk Queue</div>
<div class="lane warn">Dependency Alerts</div>
<div class="lane">Provenance Details</div>
</aside>
</div>
</div>
</div>
<div class="notes"><strong>Best for:</strong> Maximum situational awareness and real-time risk triage.</div>
</article>

<article class="card">
<div class="card-head">
<h3>Direction 2: Queue + Inspector</h3>
<span class="tag">Speed edits</span>
</div>
<div class="preview">
<div class="mock" style="grid-template-rows:34px 1fr;">
<div class="mock-top"><span class="dot"></span><span class="dot"></span><span class="dot"></span> Priority Queue / Detail Inspector</div>
<div class="mock body-b">
<section class="pane">
<div class="lane warn">At-Risk: Millbrook sorting due in 18h</div>
<div class="lane err">Blocked: Easton transport window conflict</div>
<div class="lane ok">On Track: Pinecrest office copies</div>
<div class="lane">Ready: Blue envelope print</div>
</section>
<aside class="pane soft">
<div class="lane">Inline Edit Fields</div>
<div class="lane">Safe Commit Checks</div>
<div class="lane">Reason Code + Save</div>
<div class="lane">Audit Trail</div>
</aside>
</div>
</div>
</div>
<div class="notes"><strong>Best for:</strong> Fast operator throughput with minimal navigation friction.</div>
</article>

<article class="card">
<div class="card-head">
<h3>Direction 3: Spreadsheet Plus</h3>
<span class="tag">Excel-inspired</span>
</div>
<div class="preview">
<div class="mock" style="grid-template-rows:34px 1fr;">
<div class="mock-top"><span class="dot"></span><span class="dot"></span><span class="dot"></span> Grid Operations / Trusted Commit</div>
<div class="mock body-c">
<aside class="pane soft">
<div class="lane">Column Presets</div>
<div class="lane">Saved Views</div>
<div class="lane">Bulk Actions</div>
</aside>
<section class="pane">
<table class="data-table">
<thead><tr><th>Municipality</th><th>Cycle</th><th>Envelope</th><th>Dispatch</th><th>Owner</th></tr></thead>
<tbody>
<tr><td>Riverside</td><td>Primary</td><td>Purple</td><td>04/07</td><td>D. Hall</td></tr>
<tr><td>Brighton</td><td>General</td><td>Blue</td><td>04/09</td><td>M. Cole</td></tr>
<tr><td>Auburn</td><td>General</td><td>Purple</td><td>04/08</td><td>J. Lee</td></tr>
</tbody>
</table>
</section>
<section class="pane" style="grid-column:2; grid-row:2;">
<div class="lane">Validation Console</div>
<div class="lane ok">Ready to commit 6 updates</div>
</section>
</div>
</div>
</div>
<div class="notes"><strong>Best for:</strong> Teams migrating from Access/Excel habits with low retraining cost.</div>
</article>

<article class="card">
<div class="card-head">
<h3>Direction 4: Timeline Operations</h3>
<span class="tag">Deadline-first</span>
</div>
<div class="preview">
<div class="mock body-d">
<div class="pane soft" style="border-bottom:1px solid #e2e8f0;">
<div class="lane">Election Timeline Ribbon • D-10 to D+2</div>
</div>
<section class="pane">
<div class="lane warn">D-3: Address finalization (2 blockers)</div>
<div class="lane err">D-2: Transportation route unresolved</div>
<div class="lane ok">D-1: Office copies complete</div>
<div class="lane">D-Day: Dispatch verification checklist</div>
</section>
</div>
</div>
<div class="notes"><strong>Best for:</strong> Production-led teams where timing risk is the primary management lens.</div>
</article>

<article class="card">
<div class="card-head">
<h3>Direction 5: Workbench + Modal Deep Work</h3>
<span class="tag">Focus workflows</span>
</div>
<div class="preview">
<div class="mock" style="grid-template-rows:34px 1fr;">
<div class="mock-top"><span class="dot"></span><span class="dot"></span><span class="dot"></span> Operations Workbench / Task Focus</div>
<div class="mock body-e">
<aside class="pane soft">
<div class="lane">Task Stack</div>
<div class="lane warn">Urgent (4)</div>
<div class="lane">Due Today (11)</div>
</aside>
<section class="pane">
<div class="lane">Primary Work Area</div>
<div class="lane">Contextual Drawer Opens on Select</div>
<div class="lane">Commit + Reason Code Modal</div>
<div class="lane ok">Success Feedback With Next Action</div>
</section>
</div>
</div>
</div>
<div class="notes"><strong>Best for:</strong> Reduced cognitive load when users process one high-impact task at a time.</div>
</article>

<article class="card">
<div class="card-head">
<h3>Direction 6: Executive Snapshot + Drilldown</h3>
<span class="tag">Overview to action</span>
</div>
<div class="preview">
<div class="mock body-f">
<section class="pane">
<div style="display:grid; grid-template-columns:repeat(4,1fr); gap:8px; margin-bottom:8px;">
<div class="lane ok">On Track: 124</div>
<div class="lane warn">At Risk: 19</div>
<div class="lane err">Blocked: 7</div>
<div class="lane">Needs Review: 11</div>
</div>
<table class="data-table">
<thead><tr><th>Region</th><th>Upcoming Cutoff</th><th>Primary Risk</th><th>Action</th></tr></thead>
<tbody>
<tr><td>North</td><td>04/07</td><td>Addressing Lag</td><td>Open Queue</td></tr>
<tr><td>South</td><td>04/08</td><td>Route Capacity</td><td>Open Queue</td></tr>
<tr><td>West</td><td>04/08</td><td>No blockers</td><td>Review</td></tr>
</tbody>
</table>
</section>
</div>
</div>
<div class="notes"><strong>Best for:</strong> Leadership and admins who need rapid oversight before acting at detail level.</div>
</article>
</section>

<section class="footer">
Recommended base candidate: <strong>Direction 1 (Operations Command Desk)</strong>, with selective adoption of Direction 3 grid affordances and Direction 2 quick inspector behavior.
</section>
</main>
</body>
</html>


Loading…
Cancel
Save

Powered by TurnKey Linux.