303 lines
7.5 KiB
Markdown
303 lines
7.5 KiB
Markdown
# Contract: Web Visual Baseline
|
|
|
|
Version: 1.0
|
|
|
|
## Scope
|
|
|
|
Defines the default visual baseline for future web applications in this ecosystem.
|
|
|
|
The canonical reference is the UI style from:
|
|
|
|
- `/Users/mchusavitin/Documents/git/chart/web/static/view.css`
|
|
- `/Users/mchusavitin/Documents/git/chart/web/templates/view.html`
|
|
- `/Users/mchusavitin/Documents/git/chart/web/templates/upload.html`
|
|
|
|
When a project does not already have an established design system, use this baseline by default.
|
|
|
|
## Core Direction
|
|
|
|
- Prefer a clean, data-first interface over decorative marketing UI.
|
|
- Default to server-rendered HTML with simple CSS.
|
|
- Optimize for scanability, density, and operational clarity.
|
|
- Use restrained visual hierarchy, not novelty effects.
|
|
- Reuse the baseline directly when possible; copying the canonical CSS and adapting tokens is allowed.
|
|
|
|
## Canonical Visual Language
|
|
|
|
- Dark application header on top.
|
|
- White page background and white content surfaces.
|
|
- Light secondary surfaces for headers and table heads.
|
|
- Thin gray borders with a subtle shadow.
|
|
- Small radii (`4px`).
|
|
- Dense but readable typography (`14px/1.5` baseline).
|
|
- Blue accent in the `#2185d0` family for primary actions and active accents.
|
|
- Tables and key-value layouts as the primary presentation pattern.
|
|
- Status communicated with both text and color.
|
|
|
|
## Typography
|
|
|
|
- Use `Lato, "Helvetica Neue", Arial, Helvetica, sans-serif` unless a project has an approved alternative.
|
|
- Page titles are compact and strong, not oversized hero typography.
|
|
- Section titles should be clear and structural.
|
|
- Avoid display fonts, novelty fonts, and oversized marketing headings in application UI.
|
|
|
|
## Layout Primitives
|
|
|
|
- `page-header`: dark global header with page title and compact actions.
|
|
- `page-main`: centered content area with generous outer margin and bounded max width.
|
|
- `panel`: white surface with border, light shadow, and simple heading strip.
|
|
- `section-card`: heading followed by table/content block.
|
|
- `table-wrap`: horizontal overflow container for dense data tables.
|
|
|
|
## Preferred Components
|
|
|
|
- Key-value tables for singleton object/detail views.
|
|
- Dense data tables for repeated records.
|
|
- Compact upload/open panels when local file input is needed.
|
|
- Quiet header actions for secondary navigation.
|
|
- Clear primary buttons for the main action on a screen.
|
|
- Simple alert/error boxes with border + tinted background.
|
|
|
|
## Status Rules
|
|
|
|
- `OK`: green
|
|
- `Warning`: amber
|
|
- `Critical`: red
|
|
- `Unknown`: gray
|
|
- `Empty`: light gray
|
|
|
|
Status must not rely on color alone.
|
|
Show text or another explicit indicator together with the color treatment.
|
|
|
|
## Responsive Rules
|
|
|
|
- Keep desktop density high.
|
|
- Collapse grids to one column on small screens.
|
|
- Preserve table readability with horizontal scrolling instead of destructive cardification by default.
|
|
- Header actions may wrap or stack on mobile, but should remain compact.
|
|
|
|
## Forbidden Drift
|
|
|
|
- Do not default to glassmorphism, blurred shells, floating neon gradients, or soft-dribbble styling.
|
|
- Do not replace dense tables with oversized card grids when the data is inherently tabular.
|
|
- Do not introduce arbitrary color coding for non-status fields.
|
|
- Do not use oversized border radii, heavy shadows, or large empty spacing as the default application style.
|
|
- Do not import a SPA/dashboard aesthetic unless the product explicitly requires it.
|
|
|
|
## Relationship To Other UI Contracts
|
|
|
|
- Use this contract as the visual baseline.
|
|
- Use `table-management` for shared table geometry and interaction seams.
|
|
- Use `controls-selection` for button hierarchy, filters, and bulk selection semantics.
|
|
- Pattern-specific contracts may override details only when they document the reason.
|
|
|
|
## Copyable Starter CSS
|
|
|
|
Use this as the default starting point for new web apps:
|
|
|
|
```css
|
|
:root {
|
|
--bg: #ffffff;
|
|
--surface: #ffffff;
|
|
--surface-2: #f9fafb;
|
|
--border: rgba(34, 36, 38, 0.15);
|
|
--border-lite: rgba(34, 36, 38, 0.1);
|
|
--ink: rgba(0, 0, 0, 0.87);
|
|
--muted: rgba(0, 0, 0, 0.6);
|
|
--accent: #2185d0;
|
|
--accent-dark: #1678c2;
|
|
--accent-bg: #dff0ff;
|
|
--ok: #16ab39;
|
|
--warn: #f2711c;
|
|
--crit: #db2828;
|
|
--header-bg: #1b1c1d;
|
|
--radius: 4px;
|
|
--shadow: 0 1px 2px 0 rgba(34, 36, 38, 0.15);
|
|
--content-width: 1500px;
|
|
}
|
|
|
|
* {
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
body {
|
|
margin: 0;
|
|
background: var(--bg);
|
|
color: var(--ink);
|
|
font: 14px/1.5 Lato, "Helvetica Neue", Arial, Helvetica, sans-serif;
|
|
}
|
|
|
|
.page-header {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: 16px;
|
|
padding: 14px 24px;
|
|
background: var(--header-bg);
|
|
}
|
|
|
|
.page-header h1 {
|
|
margin: 0;
|
|
font-size: 18px;
|
|
font-weight: 700;
|
|
color: rgba(255, 255, 255, 0.9);
|
|
}
|
|
|
|
.page-main {
|
|
width: min(var(--content-width), calc(100vw - 48px));
|
|
margin: 28px auto 56px;
|
|
}
|
|
|
|
.panel {
|
|
margin-bottom: 28px;
|
|
overflow: hidden;
|
|
background: var(--surface);
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--radius);
|
|
box-shadow: var(--shadow);
|
|
}
|
|
|
|
.panel > h2 {
|
|
margin: 0;
|
|
padding: 13px 16px;
|
|
background: var(--surface-2);
|
|
border-bottom: 1px solid var(--border);
|
|
font-size: 13px;
|
|
font-weight: 700;
|
|
}
|
|
|
|
.table-wrap {
|
|
overflow-x: auto;
|
|
}
|
|
|
|
.kv-table,
|
|
.data-table {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
background: var(--surface);
|
|
}
|
|
|
|
.kv-table th,
|
|
.kv-table td,
|
|
.data-table th,
|
|
.data-table td {
|
|
padding: 11px 14px;
|
|
text-align: left;
|
|
vertical-align: top;
|
|
border-top: 1px solid var(--border-lite);
|
|
}
|
|
|
|
.kv-table th,
|
|
.data-table th {
|
|
background: var(--surface-2);
|
|
border-top: 0;
|
|
border-bottom: 1px solid var(--border-lite);
|
|
font-weight: 700;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.data-table tbody tr:hover {
|
|
background: rgba(0, 0, 0, 0.04);
|
|
}
|
|
|
|
.button-primary {
|
|
display: inline-block;
|
|
padding: 8px 18px;
|
|
border: none;
|
|
border-radius: var(--radius);
|
|
background: var(--accent);
|
|
color: #fff;
|
|
font: inherit;
|
|
font-weight: 700;
|
|
text-decoration: none;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.button-primary:hover {
|
|
background: var(--accent-dark);
|
|
}
|
|
|
|
.header-action {
|
|
display: inline-block;
|
|
padding: 6px 14px;
|
|
border-radius: var(--radius);
|
|
background: rgba(255, 255, 255, 0.12);
|
|
color: rgba(255, 255, 255, 0.85);
|
|
text-decoration: none;
|
|
font-size: 13px;
|
|
font-weight: 700;
|
|
}
|
|
|
|
.header-action:hover {
|
|
background: rgba(255, 255, 255, 0.2);
|
|
}
|
|
|
|
.status-ok { color: var(--ok); }
|
|
.status-warning { color: var(--warn); }
|
|
.status-critical { color: var(--crit); }
|
|
.status-unknown { color: rgba(0, 0, 0, 0.45); }
|
|
|
|
@media (max-width: 720px) {
|
|
.page-header {
|
|
flex-direction: column;
|
|
padding: 12px 16px;
|
|
}
|
|
|
|
.page-main {
|
|
width: calc(100vw - 24px);
|
|
margin-top: 20px;
|
|
}
|
|
}
|
|
```
|
|
|
|
## Copyable Starter HTML
|
|
|
|
```html
|
|
<header class="page-header">
|
|
<h1>Application Title</h1>
|
|
<a class="header-action" href="/back">Back</a>
|
|
</header>
|
|
|
|
<main class="page-main">
|
|
<section class="panel">
|
|
<h2>Overview</h2>
|
|
<div class="table-wrap">
|
|
<table class="kv-table">
|
|
<tbody>
|
|
<tr>
|
|
<th>Host</th>
|
|
<td>server-01</td>
|
|
</tr>
|
|
<tr>
|
|
<th>Status</th>
|
|
<td><span class="status-ok">OK</span></td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="panel">
|
|
<h2>Devices</h2>
|
|
<div class="table-wrap">
|
|
<table class="data-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Name</th>
|
|
<th>Vendor</th>
|
|
<th>Status</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td>NIC 1</td>
|
|
<td>Intel</td>
|
|
<td><span class="status-warning">Warning</span></td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</section>
|
|
</main>
|
|
```
|