Compare commits
1 commit
main
...
lavender/p
| Author | SHA1 | Date | |
|---|---|---|---|
| bf75ef344c |
2 changed files with 279 additions and 9 deletions
|
|
@ -20,6 +20,7 @@
|
||||||
--blue-soft: oklch(0.72 0.13 247 / 0.11);
|
--blue-soft: oklch(0.72 0.13 247 / 0.11);
|
||||||
--rail-width: 236px;
|
--rail-width: 236px;
|
||||||
--topbar-height: 64px;
|
--topbar-height: 64px;
|
||||||
|
--ease-out-terminal: cubic-bezier(0.22, 1, 0.36, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
* {
|
* {
|
||||||
|
|
@ -32,6 +33,29 @@ body {
|
||||||
min-height: 100%;
|
min-height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
* {
|
||||||
|
scrollbar-color: oklch(0.78 0.12 74 / 0.24) oklch(0.12 0.01 250 / 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
*::-webkit-scrollbar {
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
*::-webkit-scrollbar-track {
|
||||||
|
background: oklch(0.12 0.01 250 / 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
*::-webkit-scrollbar-thumb {
|
||||||
|
border: 2px solid oklch(0.12 0.01 250 / 0.72);
|
||||||
|
border-radius: 999px;
|
||||||
|
background: oklch(0.78 0.12 74 / 0.24);
|
||||||
|
}
|
||||||
|
|
||||||
|
*::-webkit-scrollbar-thumb:hover {
|
||||||
|
background: oklch(0.78 0.12 74 / 0.36);
|
||||||
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
font-family: var(--font-sans), sans-serif;
|
font-family: var(--font-sans), sans-serif;
|
||||||
|
|
@ -140,7 +164,10 @@ input {
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
letter-spacing: 0.14em;
|
letter-spacing: 0.14em;
|
||||||
font-size: 0.76rem;
|
font-size: 0.76rem;
|
||||||
transition: border-color 0.15s ease, background-color 0.15s ease, color 0.15s ease;
|
transition:
|
||||||
|
border-color 160ms var(--ease-out-terminal),
|
||||||
|
background-color 160ms var(--ease-out-terminal),
|
||||||
|
color 160ms var(--ease-out-terminal);
|
||||||
}
|
}
|
||||||
|
|
||||||
.terminal-nav-link:hover {
|
.terminal-nav-link:hover {
|
||||||
|
|
@ -160,6 +187,7 @@ input {
|
||||||
border-color: var(--border-strong);
|
border-color: var(--border-strong);
|
||||||
color: var(--text);
|
color: var(--text);
|
||||||
background: var(--accent-soft);
|
background: var(--accent-soft);
|
||||||
|
box-shadow: inset 0 0 0 1px oklch(0.78 0.12 74 / 0.08);
|
||||||
}
|
}
|
||||||
|
|
||||||
.shell-metrics {
|
.shell-metrics {
|
||||||
|
|
@ -172,7 +200,7 @@ input {
|
||||||
padding: 11px 13px;
|
padding: 11px 13px;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
border: 1px solid var(--border);
|
border: 1px solid var(--border);
|
||||||
background: var(--bg-soft);
|
background: linear-gradient(180deg, oklch(0.97 0.008 250 / 0.05), oklch(0.97 0.008 250 / 0.025));
|
||||||
}
|
}
|
||||||
|
|
||||||
.shell-metric-label,
|
.shell-metric-label,
|
||||||
|
|
@ -383,6 +411,36 @@ input {
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
letter-spacing: 0.12em;
|
letter-spacing: 0.12em;
|
||||||
font-size: 0.72rem;
|
font-size: 0.72rem;
|
||||||
|
transition:
|
||||||
|
border-color 160ms var(--ease-out-terminal),
|
||||||
|
background-color 160ms var(--ease-out-terminal),
|
||||||
|
color 160ms var(--ease-out-terminal),
|
||||||
|
opacity 160ms var(--ease-out-terminal);
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-button:hover:not(:disabled),
|
||||||
|
.mode-button:hover:not(:disabled),
|
||||||
|
.filter-clear:hover:not(:disabled),
|
||||||
|
.jump-button:hover:not(:disabled),
|
||||||
|
.pause-button:hover:not(:disabled),
|
||||||
|
.interval-button:hover:not(:disabled),
|
||||||
|
.overlay-toggle:hover:not(:disabled),
|
||||||
|
.drawer-close:hover:not(:disabled) {
|
||||||
|
border-color: oklch(0.78 0.09 74 / 0.36);
|
||||||
|
background: oklch(0.78 0.12 74 / 0.075);
|
||||||
|
color: var(--text);
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-button:active:not(:disabled),
|
||||||
|
.mode-button:active:not(:disabled),
|
||||||
|
.filter-clear:active:not(:disabled),
|
||||||
|
.jump-button:active:not(:disabled),
|
||||||
|
.pause-button:active:not(:disabled),
|
||||||
|
.interval-button:active:not(:disabled),
|
||||||
|
.overlay-toggle:active:not(:disabled),
|
||||||
|
.drawer-close:active:not(:disabled) {
|
||||||
|
border-color: oklch(0.78 0.1 74 / 0.5);
|
||||||
|
background: oklch(0.78 0.12 74 / 0.12);
|
||||||
}
|
}
|
||||||
|
|
||||||
.terminal-button:disabled,
|
.terminal-button:disabled,
|
||||||
|
|
@ -411,7 +469,7 @@ input {
|
||||||
padding: 5px 8px 5px 10px;
|
padding: 5px 8px 5px 10px;
|
||||||
border: 1px solid var(--border-strong);
|
border: 1px solid var(--border-strong);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
background: oklch(0.78 0.12 74 / 0.07);
|
background: linear-gradient(180deg, oklch(0.78 0.12 74 / 0.09), oklch(0.78 0.12 74 / 0.045));
|
||||||
color: var(--text);
|
color: var(--text);
|
||||||
font-family: var(--font-mono), monospace;
|
font-family: var(--font-mono), monospace;
|
||||||
font-size: 0.72rem;
|
font-size: 0.72rem;
|
||||||
|
|
@ -456,6 +514,12 @@ input {
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.instrument-cell-button:focus-visible {
|
||||||
|
outline: 1px solid oklch(0.83 0.08 74 / 0.82);
|
||||||
|
outline-offset: 3px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
.pause-button {
|
.pause-button {
|
||||||
padding: 7px 10px;
|
padding: 7px 10px;
|
||||||
font-size: 0.66rem;
|
font-size: 0.66rem;
|
||||||
|
|
@ -721,7 +785,9 @@ h3 {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
border: 1px solid var(--border);
|
border: 1px solid var(--border);
|
||||||
border-radius: 14px;
|
border-radius: 14px;
|
||||||
background: var(--bg-pane);
|
background:
|
||||||
|
linear-gradient(180deg, oklch(0.21 0.013 250 / 0.42), transparent 140px),
|
||||||
|
var(--bg-pane);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -732,7 +798,7 @@ h3 {
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
padding: 15px 18px;
|
padding: 15px 18px;
|
||||||
border-bottom: 1px solid var(--border);
|
border-bottom: 1px solid var(--border);
|
||||||
background: oklch(0.2 0.012 250 / 0.38);
|
background: oklch(0.2 0.012 250 / 0.48);
|
||||||
}
|
}
|
||||||
|
|
||||||
.terminal-pane-title-row {
|
.terminal-pane-title-row {
|
||||||
|
|
@ -1022,6 +1088,7 @@ h3 {
|
||||||
overflow-y: hidden;
|
overflow-y: hidden;
|
||||||
border-top: 1px solid var(--border);
|
border-top: 1px solid var(--border);
|
||||||
border-bottom: 1px solid var(--border);
|
border-bottom: 1px solid var(--border);
|
||||||
|
border-radius: 10px;
|
||||||
background: oklch(0.14 0.01 250 / 0.72);
|
background: oklch(0.14 0.01 250 / 0.72);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1105,6 +1172,10 @@ h3 {
|
||||||
letter-spacing: 0.08em;
|
letter-spacing: 0.08em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.data-table-head .data-table-cell {
|
||||||
|
font-size: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
.data-table-row {
|
.data-table-row {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
|
|
@ -1115,6 +1186,9 @@ h3 {
|
||||||
color: inherit;
|
color: inherit;
|
||||||
font: inherit;
|
font: inherit;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
|
transition:
|
||||||
|
background-color 140ms var(--ease-out-terminal),
|
||||||
|
box-shadow 140ms var(--ease-out-terminal);
|
||||||
}
|
}
|
||||||
|
|
||||||
.data-table-row.is-even {
|
.data-table-row.is-even {
|
||||||
|
|
@ -1130,7 +1204,8 @@ h3 {
|
||||||
|
|
||||||
.data-table-row:hover,
|
.data-table-row:hover,
|
||||||
.data-table-row:focus-visible {
|
.data-table-row:focus-visible {
|
||||||
outline: none;
|
outline: 1px solid oklch(0.78 0.12 74 / 0.36);
|
||||||
|
outline-offset: -1px;
|
||||||
background: oklch(0.78 0.12 74 / 0.05);
|
background: oklch(0.78 0.12 74 / 0.05);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1230,6 +1305,7 @@ h3 {
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
font-size: 0.72rem;
|
font-size: 0.72rem;
|
||||||
|
line-height: 1.25;
|
||||||
}
|
}
|
||||||
|
|
||||||
.data-table-cell-number {
|
.data-table-cell-number {
|
||||||
|
|
@ -1568,8 +1644,11 @@ h3 {
|
||||||
padding: 18px;
|
padding: 18px;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
border: 1px dashed var(--border);
|
border: 1px dashed var(--border);
|
||||||
background: var(--bg-soft);
|
background:
|
||||||
|
linear-gradient(135deg, oklch(0.78 0.12 74 / 0.045), transparent 42%),
|
||||||
|
var(--bg-soft);
|
||||||
color: var(--text-dim);
|
color: var(--text-dim);
|
||||||
|
line-height: 1.45;
|
||||||
}
|
}
|
||||||
|
|
||||||
.drawer {
|
.drawer {
|
||||||
|
|
@ -2012,12 +2091,13 @@ h3 {
|
||||||
}
|
}
|
||||||
|
|
||||||
.shell-metrics {
|
.shell-metrics {
|
||||||
display: flex;
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.shell-metric {
|
.shell-metric {
|
||||||
flex: 0 0 156px;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.terminal-content {
|
.terminal-content {
|
||||||
|
|
@ -2042,6 +2122,12 @@ h3 {
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.page-actions {
|
||||||
|
width: 100%;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
.terminal-pane-title-row {
|
.terminal-pane-title-row {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
|
|
@ -2083,9 +2169,11 @@ h3 {
|
||||||
|
|
||||||
.terminal-topbar-mode .terminal-button,
|
.terminal-topbar-mode .terminal-button,
|
||||||
.terminal-topbar-controls > .terminal-button,
|
.terminal-topbar-controls > .terminal-button,
|
||||||
|
.page-actions > .contract-filter-button,
|
||||||
.page-actions > .terminal-button,
|
.page-actions > .terminal-button,
|
||||||
.page-actions > .flow-filter-popover {
|
.page-actions > .flow-filter-popover {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
max-width: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.instrument-focus-chip {
|
.instrument-focus-chip {
|
||||||
|
|
|
||||||
182
docs/turns/2026-05-17-1123-polish-terminal-view.html
Normal file
182
docs/turns/2026-05-17-1123-polish-terminal-view.html
Normal file
|
|
@ -0,0 +1,182 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>2026-05-17 11:23, Polish Terminal View</title>
|
||||||
|
<style>
|
||||||
|
:root {
|
||||||
|
color-scheme: dark;
|
||||||
|
--bg: oklch(0.13 0.012 250);
|
||||||
|
--panel: oklch(0.18 0.014 250);
|
||||||
|
--panel-soft: oklch(0.22 0.014 250);
|
||||||
|
--border: oklch(0.72 0.012 250 / 0.18);
|
||||||
|
--text: oklch(0.93 0.014 250);
|
||||||
|
--muted: oklch(0.73 0.018 250);
|
||||||
|
--faint: oklch(0.58 0.016 250);
|
||||||
|
--accent: oklch(0.78 0.12 74);
|
||||||
|
}
|
||||||
|
|
||||||
|
* {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
background:
|
||||||
|
radial-gradient(circle at 12% 0%, oklch(0.78 0.12 74 / 0.09), transparent 30rem),
|
||||||
|
linear-gradient(180deg, oklch(0.15 0.012 250), var(--bg));
|
||||||
|
color: var(--text);
|
||||||
|
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
||||||
|
line-height: 1.55;
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
width: min(920px, calc(100vw - 32px));
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 48px 0 64px;
|
||||||
|
}
|
||||||
|
|
||||||
|
header {
|
||||||
|
margin-bottom: 28px;
|
||||||
|
padding-bottom: 20px;
|
||||||
|
border-bottom: 1px solid var(--border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.kicker,
|
||||||
|
h2 {
|
||||||
|
color: var(--accent);
|
||||||
|
font-size: 0.74rem;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: 0.14em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
max-width: 760px;
|
||||||
|
margin: 8px 0 12px;
|
||||||
|
font-size: 2rem;
|
||||||
|
line-height: 1.1;
|
||||||
|
letter-spacing: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
margin: 0 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
max-width: 74ch;
|
||||||
|
margin: 0 0 12px;
|
||||||
|
color: var(--muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
section {
|
||||||
|
margin-top: 18px;
|
||||||
|
padding: 18px;
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: 12px;
|
||||||
|
background: linear-gradient(180deg, var(--panel-soft), var(--panel));
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
margin: 0;
|
||||||
|
padding-left: 1.1rem;
|
||||||
|
color: var(--muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
li + li {
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
color: var(--text);
|
||||||
|
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
||||||
|
font-size: 0.92em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary {
|
||||||
|
color: var(--text);
|
||||||
|
font-size: 1.04rem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<main>
|
||||||
|
<header>
|
||||||
|
<div class="kicker">Turn Document, 2026-05-17 11:23 ET</div>
|
||||||
|
<h1>Polish Terminal View</h1>
|
||||||
|
<p class="summary">
|
||||||
|
Refined the Islandflow web terminal shell so the Tape view feels more deliberate, more keyboard-readable, and more stable across desktop and mobile.
|
||||||
|
</p>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h2>Summary</h2>
|
||||||
|
<p>
|
||||||
|
This was a focused product polish pass on <code>apps/web/app/globals.css</code>. The work stayed inside the established Islandflow terminal design language: dark operational surfaces, scarce amber emphasis, compact controls, and clear evidence-console states.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h2>Changes Made</h2>
|
||||||
|
<ul>
|
||||||
|
<li>Added a shared terminal easing token for consistent, restrained interaction transitions.</li>
|
||||||
|
<li>Styled scrollbars to match the terminal surface instead of falling back to browser defaults.</li>
|
||||||
|
<li>Improved nav, button, and active-control hover and pressed states using the existing OKLCH palette.</li>
|
||||||
|
<li>Refined shell metrics, pane headers, table shells, row focus states, and empty states for clearer hierarchy.</li>
|
||||||
|
<li>Adjusted mobile metric cards and Tape action controls so they align cleanly without horizontal page overflow.</li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h2>Context</h2>
|
||||||
|
<p>
|
||||||
|
Islandflow is a serious market-data terminal for traders and researchers. The polish target was product UI, not brand theater, so the changes prioritize trust, legibility, predictable controls, and stable responsive structure.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h2>Important Implementation Details</h2>
|
||||||
|
<ul>
|
||||||
|
<li>All new color work uses existing OKLCH roles and keeps amber as a scarce signal rather than a decorative wash.</li>
|
||||||
|
<li>Keyboard focus on table rows and instrument buttons is now visible without introducing layout shift.</li>
|
||||||
|
<li>Mobile shell metrics now use a two-column grid, and page actions stretch to the viewport width.</li>
|
||||||
|
<li>The polish is CSS-only, so no data contracts, route behavior, or live-stream logic changed.</li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h2>Expected Impact for End-Users</h2>
|
||||||
|
<p>
|
||||||
|
Users should experience a terminal that reads as more finished under pressure: clearer controls, cleaner empty states, better keyboard affordances, and less visual friction on narrow screens.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h2>Validation</h2>
|
||||||
|
<ul>
|
||||||
|
<li><code>bun install</code> completed to restore missing workspace dependencies.</li>
|
||||||
|
<li><code>bun test apps/web/app/terminal.test.ts apps/web/app/routes.test.ts</code> passed with 69 tests.</li>
|
||||||
|
<li><code>bun --cwd=apps/web run build</code> passed.</li>
|
||||||
|
<li>Playwright visual QA checked <code>http://localhost:3000/tape</code> at 1440x1000 and 390x900.</li>
|
||||||
|
<li>Visual QA confirmed no document-level horizontal overflow after the responsive polish.</li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h2>Issues, Limitations, and Mitigations</h2>
|
||||||
|
<ul>
|
||||||
|
<li>The local backend WebSocket at <code>localhost:4000</code> was offline during visual QA, so the screen showed disconnected empty states. This was useful for validating the empty-state polish but did not exercise live data density.</li>
|
||||||
|
<li>Playwright needed a locally cached Chromium executable. The visual check used an existing browser cache path after the default runtime binary was unavailable.</li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h2>Follow-up Work</h2>
|
||||||
|
<p>
|
||||||
|
No new Beads follow-up issue was filed. Live-data density should be rechecked naturally when the full local stack is running, but this polish did not reveal a separate actionable defect.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue