From 35fe97a1661f60f2b7a149de30fabeae485f158c Mon Sep 17 00:00:00 2001 From: Tyler Koenig Date: Sat, 16 May 2026 19:00:25 -0400 Subject: [PATCH 1/2] feat(ui): add tinycard theme MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - New [data-theme="tinycard"] token block with purple accent palette - Theme toggle cycles dark → paper → tinycard - Load Inter font for tinycard sans stack --- web/app.js | 10 +++++++--- web/index.html | 2 +- web/style.css | 24 ++++++++++++++++++++++++ 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/web/app.js b/web/app.js index a20149c..9df72c1 100644 --- a/web/app.js +++ b/web/app.js @@ -1590,16 +1590,20 @@ // ========== Theme ========== + const THEMES = ['dark', 'paper', 'tinycard']; + const THEME_ICONS = { dark: '◑', paper: '◐', tinycard: '◈' }; + const themeToggle = $('#theme-toggle'); let nibTheme = localStorage.getItem('nib:theme') || 'dark'; + if (!THEMES.includes(nibTheme)) nibTheme = 'dark'; document.documentElement.setAttribute('data-theme', nibTheme); - themeToggle.textContent = nibTheme === 'paper' ? '◐' : '◑'; + themeToggle.textContent = THEME_ICONS[nibTheme]; themeToggle.addEventListener('click', () => { - nibTheme = nibTheme === 'dark' ? 'paper' : 'dark'; + nibTheme = THEMES[(THEMES.indexOf(nibTheme) + 1) % THEMES.length]; document.documentElement.setAttribute('data-theme', nibTheme); localStorage.setItem('nib:theme', nibTheme); - themeToggle.textContent = nibTheme === 'paper' ? '◐' : '◑'; + themeToggle.textContent = THEME_ICONS[nibTheme]; }); // ========== Init ========== diff --git a/web/index.html b/web/index.html index 42aed17..2c29c7b 100644 --- a/web/index.html +++ b/web/index.html @@ -6,7 +6,7 @@ nib - + diff --git a/web/style.css b/web/style.css index 43cf33d..d5f9966 100644 --- a/web/style.css +++ b/web/style.css @@ -50,6 +50,30 @@ --lineage: #5830a0; } +[data-theme="tinycard"] { + color-scheme: dark; + --bg: #0f1117; + --surf: #161922; + --raised: #1e2130; + --border: #2a2e3d; + --soft: #222639; + --text: #e1e4ed; + --muted: #8b90a0; + --dim: #555a6a; + --accent: #ad8ee6; + --a-bg: rgba(173,142,230,.09); + --a-str: rgba(173,142,230,.22); + --todo: #fbbf24; + --note: #22d3ee; + --event: #22d3ee; + --remind: #e8845a; + --ok: #4ade80; + --danger: #ef4444; + --lineage: #a78bfa; + --sans: 'Inter', system-ui, sans-serif; + --mono: 'JetBrains Mono', ui-monospace, monospace; +} + /* ── RESET ──────────────────────────────────────────── */ *, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; } html, body { height: 100%; overflow: hidden; } From ef647aea7a4d094c0670b47542fc79dc166a9ddd Mon Sep 17 00:00:00 2001 From: Tyler Koenig Date: Sat, 16 May 2026 19:01:44 -0400 Subject: [PATCH 2/2] feat(ui): sort dropdown for cards, capture bar prominence MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Cards sort dropdown: newest, oldest, most used — wired to reload - Capture bar: larger font, more padding, accent glow on focus - Prompt glyph scales up for visibility --- web/app.js | 21 ++++++++++++++++++--- web/style.css | 17 +++++++++++------ 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/web/app.js b/web/app.js index 9df72c1..f2119f0 100644 --- a/web/app.js +++ b/web/app.js @@ -33,6 +33,7 @@ fillValues: {}, fillActive: 0, searchQuery: '', + cardsSort: 'newest', }; const $ = (sel) => document.querySelector(sel); @@ -611,11 +612,17 @@ panel.insertBefore(hdr, list); } const scope = state.activeTag ? `${state.intent} · #${state.activeTag}` : state.intent; + const sorts = ['newest', 'oldest', 'most used']; + const options = sorts.map(s => `${s}`).join(''); hdr.innerHTML = ` ${scope} ${state.entities.length} cards - + `; + hdr.querySelector('.cards-sort').addEventListener('change', (ev) => { + state.cardsSort = ev.target.value; + loadEntities(); + }); } function renderCardRow(e, idx) { @@ -1103,8 +1110,16 @@ if (state.activeTag) params.tag = state.activeTag; if (state.view === 'cards') { params.cards_only = true; - params.sort = 'use_count'; - params.order = 'desc'; + if (state.cardsSort === 'oldest') { + params.sort = 'created'; + params.order = 'asc'; + } else if (state.cardsSort === 'most used') { + params.sort = 'use_count'; + params.order = 'desc'; + } else { + params.sort = 'created'; + params.order = 'desc'; + } } else { params.sort = 'created'; params.order = 'desc'; diff --git a/web/style.css b/web/style.css index d5f9966..4c07f85 100644 --- a/web/style.css +++ b/web/style.css @@ -665,7 +665,12 @@ main { border-top: 1px solid var(--border); background: var(--surf); flex-shrink: 0; - transition: border-top-color var(--t-base); + padding: 4px 0; + transition: border-top-color var(--t-base), box-shadow var(--t-base); +} + +#capture-bar:focus-within { + box-shadow: 0 -2px 12px rgba(200,148,42,.08); } /* ── Capture preview ── */ @@ -697,7 +702,7 @@ main { .cap-pill-card { color: var(--accent); border-color: rgba(200,148,42,.25); } .cap-pill-query { color: var(--event); border-color: rgba(104,152,200,.3); } -#capture-bar:focus-within { border-top-color: rgba(200,148,42,.35); } +#capture-bar:focus-within { border-top-color: var(--accent); } .cap-row { display: flex; @@ -707,10 +712,10 @@ main { .cap-prompt { font-family: var(--mono); - font-size: 14px; + font-size: 16px; color: var(--accent); opacity: .4; - padding-bottom: 8px; + padding-bottom: 10px; flex-shrink: 0; transition: opacity var(--t-base); } @@ -722,9 +727,9 @@ main { background: transparent; border: none; outline: none; - padding: 8px 10px; + padding: 10px 10px; font-family: var(--mono); - font-size: 12px; + font-size: 13px; color: var(--text); line-height: 1.5; resize: none;