feat: replace Pico CSS with mockup custom CSS in both templates
This commit is contained in:
+69
-74
@@ -4,81 +4,76 @@
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="color-scheme" content="light dark" />
|
||||
<title>Spine — Add Book</title>
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@2.1.1/css/pico.min.css" />
|
||||
<title>Spine — add book</title>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/tabler-icons/3.31.0/iconfont/tabler-icons.min.css" />
|
||||
<style>
|
||||
:root {
|
||||
--bg-page: #efeee9; --bg-primary: #ffffff; --bg-secondary: #f5f4ef;
|
||||
--text-primary: #1d1d1b; --text-secondary: #5f5e5a; --text-tertiary: #8a8980;
|
||||
--bg-info: #e6f1fb; --text-info: #0c447c; --border-info: #378add;
|
||||
--bg-warning: #faeeda; --text-warning: #854f0b;
|
||||
--bg-success: #e1f5ee; --text-success: #085041;
|
||||
--border-tertiary: rgba(0,0,0,0.12); --border-secondary: rgba(0,0,0,0.22);
|
||||
--radius-md: 8px; --radius-lg: 12px;
|
||||
--mono: ui-monospace, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
|
||||
--sans: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
|
||||
}
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--bg-page: #161615; --bg-primary: #232321; --bg-secondary: #1c1c1a;
|
||||
--text-primary: #ededeb; --text-secondary: #a8a79f; --text-tertiary: #76756d;
|
||||
--bg-info: #14304a; --text-info: #b5d4f4; --border-info: #378add;
|
||||
--bg-warning: #3a2c12; --text-warning: #fac775;
|
||||
--bg-success: #103a30; --text-success: #9fe1cb;
|
||||
--border-tertiary: rgba(255,255,255,0.14); --border-secondary: rgba(255,255,255,0.24);
|
||||
}
|
||||
}
|
||||
* { box-sizing: border-box; }
|
||||
body { margin: 0; background: var(--bg-page); color: var(--text-primary);
|
||||
font-family: var(--sans); padding: 28px 16px; }
|
||||
.wrap { max-width: 560px; margin: 0 auto; }
|
||||
.frame { font-family: var(--mono); border: 0.5px solid var(--border-secondary);
|
||||
border-radius: var(--radius-lg); overflow: hidden; background: var(--bg-primary); }
|
||||
.titlebar { display:flex; align-items:center; justify-content:space-between;
|
||||
padding:10px 14px; border-bottom:0.5px solid var(--border-tertiary);
|
||||
background: var(--bg-secondary); font-size:13px; }
|
||||
.form-body { padding:14px; font-size:13px; }
|
||||
.form-body label { display:block; margin-bottom:6px; }
|
||||
.form-body input, .form-body select, .form-body textarea {
|
||||
font-family: var(--mono); font-size:13px; width:100%; padding:6px 8px;
|
||||
border:0.5px solid var(--border-secondary); border-radius:var(--radius-md);
|
||||
background:var(--bg-page); color:var(--text-primary); margin-bottom:12px;
|
||||
}
|
||||
.form-body button { font-family: var(--mono); font-size:13px; padding:6px 14px;
|
||||
border:0.5px solid var(--border-info); border-radius:var(--radius-md);
|
||||
background:var(--bg-info); color:var(--text-info); cursor:pointer; }
|
||||
.form-body button:hover { background:var(--border-info); color:white; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<main class="container">
|
||||
<article style="max-width: 560px; margin-inline: auto;">
|
||||
<header>
|
||||
<strong>{{app_title}} · add book</strong>
|
||||
</header>
|
||||
|
||||
<form method="post" action="/add">
|
||||
<label>
|
||||
Date added
|
||||
<input type="date" name="date_added" />
|
||||
</label>
|
||||
|
||||
<label>
|
||||
Title *
|
||||
<input type="text" name="title" required autofocus />
|
||||
</label>
|
||||
|
||||
<label>
|
||||
Author
|
||||
<input type="text" name="author" list="authors-list" />
|
||||
<datalist id="authors-list">
|
||||
{{#existing_authors}}<option value="{{.}}">{{/existing_authors}}
|
||||
</datalist>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
Category
|
||||
<input type="text" name="category" list="categories-list" />
|
||||
<datalist id="categories-list">
|
||||
{{#existing_categories}}<option value="{{.}}">{{/existing_categories}}
|
||||
</datalist>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
Format
|
||||
<select name="format">
|
||||
<option value="">—</option>
|
||||
<option value="hardcover">Hardcover</option>
|
||||
<option value="ebook">eBook</option>
|
||||
<option value="audiobook">Audiobook</option>
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
ISBN
|
||||
<input type="text" name="isbn" />
|
||||
</label>
|
||||
|
||||
<label>
|
||||
Cover (path)
|
||||
<input type="text" name="cover" placeholder="covers/filename.jpg" />
|
||||
</label>
|
||||
|
||||
<label>
|
||||
Recommended by
|
||||
<input type="text" name="rec_by" />
|
||||
</label>
|
||||
|
||||
<label>
|
||||
Why it's on your radar
|
||||
<input type="text" name="rec_note" />
|
||||
</label>
|
||||
|
||||
<label>
|
||||
Initial note
|
||||
<textarea name="initial_note" rows="3" placeholder="First impressions…"></textarea>
|
||||
</label>
|
||||
|
||||
<button type="submit">Add book</button>
|
||||
</form>
|
||||
</article>
|
||||
</main>
|
||||
<div class="wrap">
|
||||
<div class="frame">
|
||||
<div class="titlebar">
|
||||
<span style="font-weight:500;">spine · add book</span>
|
||||
</div>
|
||||
<div class="form-body">
|
||||
<form method="post" action="/add">
|
||||
<label>Date added <input type="date" name="date_added" /></label>
|
||||
<label>Title * <input type="text" name="title" required autofocus /></label>
|
||||
<label>Author <input type="text" name="author" list="authors-list" /></label>
|
||||
<datalist id="authors-list">{{#existing_authors}}<option value="{{.}}">{{/existing_authors}}</datalist>
|
||||
<label>Category <input type="text" name="category" list="categories-list" /></label>
|
||||
<datalist id="categories-list">{{#existing_categories}}<option value="{{.}}">{{/existing_categories}}</datalist>
|
||||
<label>Format <select name="format"><option value="">—</option><option value="hardcover">Hardcover</option><option value="ebook">eBook</option><option value="audiobook">Audiobook</option></select></label>
|
||||
<label>ISBN <input type="text" name="isbn" /></label>
|
||||
<label>Cover (path) <input type="text" name="cover" placeholder="covers/filename.jpg" /></label>
|
||||
<label>Recommended by <input type="text" name="rec_by" /></label>
|
||||
<label>Why it's on your radar <input type="text" name="rec_note" /></label>
|
||||
<label>Initial note <textarea name="initial_note" rows="3" placeholder="First impressions…"></textarea></label>
|
||||
<button type="submit">Add book</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
+76
-95
@@ -4,103 +4,84 @@
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="color-scheme" content="light dark" />
|
||||
<title>Spine — Direction A (agenda)</title>
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@2.1.1/css/pico.min.css" />
|
||||
<title>Spine — agenda</title>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/tabler-icons/3.31.0/iconfont/tabler-icons.min.css" />
|
||||
<style>
|
||||
.agenda { font-family: var(--pico-font-family-monospace); padding: 0; overflow: hidden; }
|
||||
.agenda > header, .agenda > footer { margin: 0; padding: .6rem .9rem; font-size: .85rem; }
|
||||
.agenda > header { display: flex; justify-content: space-between; align-items: center; }
|
||||
.group { padding: .65rem .9rem .2rem; font-size: .7rem; letter-spacing: .04em; color: var(--pico-muted-color); }
|
||||
.row { display: flex; align-items: center; gap: .6rem; padding: .3rem .9rem; font-size: .85rem; }
|
||||
.row.selected { background: var(--pico-card-sectioning-background-color); border-left: 2px solid var(--pico-primary); }
|
||||
.row.selected .title { font-weight: 500; }
|
||||
.row.selected .glyph { color: var(--pico-color); }
|
||||
.glyph { width: 1rem; color: var(--pico-muted-color); flex-shrink: 0; }
|
||||
.title { flex: 1; min-width: 0; }
|
||||
.muted { color: var(--pico-muted-color); }
|
||||
.tags { color: var(--pico-primary); font-size: .8rem; }
|
||||
.trail { color: var(--pico-muted-color); font-size: .8rem; }
|
||||
.pill { padding: .05rem .45rem; border-radius: var(--pico-border-radius); font-size: .7rem; font-weight: 500; }
|
||||
.pill.want { background: #e6f1fb; color: #0c447c; }
|
||||
.pill.reading { background: #faeeda; color: #854f0b; }
|
||||
.pill.read { background: #e1f5ee; color: #085041; }
|
||||
.detail { padding: .5rem .9rem .7rem 2rem; background: var(--pico-card-sectioning-background-color);
|
||||
border-left: 2px solid var(--pico-primary); font-size: .8rem; }
|
||||
.logline { display: flex; gap: .5rem; margin-bottom: .3rem; }
|
||||
.logline:last-child { margin-bottom: 0; }
|
||||
.logdate { color: var(--pico-muted-color); white-space: nowrap; }
|
||||
.endpad { height: .4rem; }
|
||||
.minibuffer { display: flex; gap: .5rem; align-items: center; }
|
||||
.minibuffer .text { border-left: 2px solid var(--pico-primary); padding-left: .4rem; }
|
||||
.caret { opacity: .5; }
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.pill.want { background: #14304a; color: #b5d4f4; }
|
||||
.pill.reading { background: #3a2c12; color: #fac775; }
|
||||
.pill.read { background: #103a30; color: #9fe1cb; }
|
||||
:root {
|
||||
--bg-page: #efeee9; --bg-primary: #ffffff; --bg-secondary: #f5f4ef;
|
||||
--text-primary: #1d1d1b; --text-secondary: #5f5e5a; --text-tertiary: #8a8980;
|
||||
--bg-info: #e6f1fb; --text-info: #0c447c; --border-info: #378add;
|
||||
--bg-warning: #faeeda; --text-warning: #854f0b;
|
||||
--bg-success: #e1f5ee; --text-success: #085041;
|
||||
--border-tertiary: rgba(0,0,0,0.12); --border-secondary: rgba(0,0,0,0.22);
|
||||
--radius-md: 8px; --radius-lg: 12px;
|
||||
--mono: ui-monospace, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
|
||||
--sans: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
|
||||
}
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--bg-page: #161615; --bg-primary: #232321; --bg-secondary: #1c1c1a;
|
||||
--text-primary: #ededeb; --text-secondary: #a8a79f; --text-tertiary: #76756d;
|
||||
--bg-info: #14304a; --text-info: #b5d4f4; --border-info: #378add;
|
||||
--bg-warning: #3a2c12; --text-warning: #fac775;
|
||||
--bg-success: #103a30; --text-success: #9fe1cb;
|
||||
--border-tertiary: rgba(255,255,255,0.14); --border-secondary: rgba(255,255,255,0.24);
|
||||
}
|
||||
}
|
||||
* { box-sizing: border-box; }
|
||||
body { margin: 0; background: var(--bg-page); color: var(--text-primary);
|
||||
font-family: var(--sans); padding: 28px 16px; }
|
||||
.wrap { max-width: 720px; margin: 0 auto; }
|
||||
.frame { font-family: var(--mono); border: 0.5px solid var(--border-secondary);
|
||||
border-radius: var(--radius-lg); overflow: hidden; background: var(--bg-primary); }
|
||||
.titlebar { display:flex; align-items:center; justify-content:space-between;
|
||||
padding:10px 14px; border-bottom:0.5px solid var(--border-tertiary);
|
||||
background: var(--bg-secondary); font-size:13px; }
|
||||
.group { padding:10px 14px 4px; font-size:11px; letter-spacing:0.04em; color: var(--text-tertiary); }
|
||||
.row { display:flex; align-items:center; gap:10px; padding:5px 14px; font-size:13px; }
|
||||
.glyph { font-size:15px; color:var(--text-tertiary); width:16px; }
|
||||
.pill { padding:1px 7px; border-radius:var(--radius-md); font-size:11px; }
|
||||
.pill.want { background:var(--bg-info); color:var(--text-info); }
|
||||
.pill.reading { background:var(--bg-warning); color:var(--text-warning); }
|
||||
.pill.read { background:var(--bg-success); color:var(--text-success); }
|
||||
.title { flex:1; min-width:0; }
|
||||
.muted { color:var(--text-tertiary); }
|
||||
.tags { color:var(--text-info); font-size:12px; }
|
||||
.trail { color:var(--text-secondary); font-size:12px; }
|
||||
.selected { background:var(--bg-secondary); border-left:2px solid var(--border-info); }
|
||||
.detail { padding:8px 14px 12px 32px; background:var(--bg-secondary);
|
||||
border-left:2px solid var(--border-info); font-size:12.5px; }
|
||||
.logline { display:flex; gap:8px; margin-bottom:5px; }
|
||||
.logdate { color:var(--text-tertiary); white-space:nowrap; }
|
||||
.minibuffer { border-top:0.5px solid var(--border-tertiary); padding:9px 14px;
|
||||
background:var(--bg-secondary); font-size:13px; display:flex; gap:8px; align-items:center; }
|
||||
.caret { opacity:0.5; }
|
||||
.filter-bar { padding:8px 14px; font-size:11px; border-bottom:0.5px solid var(--border-tertiary); }
|
||||
.filter-bar a { color:var(--text-info); text-decoration:none; }
|
||||
.filter-bar a:hover { text-decoration:underline; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
{{!
|
||||
View model for this template:
|
||||
{
|
||||
app_title: string,
|
||||
total_books: number,
|
||||
reading_count: number,
|
||||
groups: [
|
||||
{
|
||||
label: string, e.g. "on deck"
|
||||
count: number,
|
||||
books: [
|
||||
{
|
||||
format_icon: string, Tabler class, e.g. "ti-headphones" (data layer maps FORMAT -> icon)
|
||||
status_class: string, "want" | "reading" | "read" (maps Org TODO state -> pill style)
|
||||
status_label: string, text shown in the pill
|
||||
title: string,
|
||||
author: string,
|
||||
tags_inline: string?, optional, e.g. ":scifi:literary:"
|
||||
rec_via: string?, optional, REC_BY -> rendered as "via {name}"
|
||||
rating_display: string?, optional, e.g. "★★★★☆"
|
||||
selected: boolean?, marks the in-focus row (expands detail)
|
||||
detail: { optional; render when a row is expanded
|
||||
meta: string, e.g. "started [2026-02-20] · hardcover · 62% · rating —"
|
||||
notes: [ { date: string, text: string } ] reading log
|
||||
}?
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
minibuffer: { command: string, text: string }? optional capture line
|
||||
}
|
||||
}}
|
||||
<main class="container">
|
||||
<article class="agenda" style="max-width: 720px; margin-inline: auto;">
|
||||
<header>
|
||||
<nav>
|
||||
<ul><li><strong>{{app_title}}</strong></li></ul>
|
||||
<ul>
|
||||
<li><span class="muted">{{total_books}} books · {{reading_count}} reading</span></li>
|
||||
<li><a role="button" href="/add" class="secondary">Add book</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
<div class="wrap">
|
||||
<div class="frame">
|
||||
<div class="titlebar">
|
||||
<span style="font-weight:500;">spine</span>
|
||||
<span class="muted">{{total_books}} books · {{reading_count}} reading</span>
|
||||
</div>
|
||||
|
||||
{{#current_filter}}
|
||||
<nav class="filter-bar" style="padding: .4rem .9rem; font-size: .8rem;">
|
||||
<div class="filter-bar">
|
||||
<a href="/index">Concise view</a>
|
||||
</nav>
|
||||
</div>
|
||||
{{/current_filter}}
|
||||
{{^current_filter}}
|
||||
<nav class="filter-bar" style="padding: .4rem .9rem; font-size: .8rem;">
|
||||
<span>
|
||||
<a href="/index?filter=all">All books ({{total_books}})</a>
|
||||
·
|
||||
<a href="/index?filter=want">Want list</a>
|
||||
·
|
||||
<a href="/index?filter=read">Read ({{reading_count}})</a>
|
||||
</span>
|
||||
</nav>
|
||||
<div class="filter-bar">
|
||||
<a href="/index?filter=all">All books ({{total_books}})</a>
|
||||
·
|
||||
<a href="/index?filter=want">Want list</a>
|
||||
·
|
||||
<a href="/index?filter=read">Read ({{reading_count}})</a>
|
||||
</div>
|
||||
{{/current_filter}}
|
||||
|
||||
{{#groups}}
|
||||
@@ -116,7 +97,7 @@
|
||||
</div>
|
||||
{{#detail}}
|
||||
<div class="detail">
|
||||
<div class="muted" style="margin-bottom: .5rem;">{{meta}}</div>
|
||||
<div class="muted" style="margin-bottom:8px;">{{meta}}</div>
|
||||
{{#notes}}
|
||||
<div class="logline"><span class="logdate">{{date}}</span><span>{{text}}</span></div>
|
||||
{{/notes}}
|
||||
@@ -124,22 +105,22 @@
|
||||
{{/detail}}
|
||||
{{/books}}
|
||||
{{/groups}}
|
||||
|
||||
{{#summary_groups}}
|
||||
<div class="row"><a href="{{href}}">{{label}} · {{count}}</a></div>
|
||||
<div class="group"><a href="{{href}}" style="color:var(--text-info);text-decoration:none">{{label}} · {{count}}</a></div>
|
||||
{{/summary_groups}}
|
||||
<div class="endpad"></div>
|
||||
|
||||
{{#minibuffer}}
|
||||
<footer class="minibuffer">
|
||||
<div class="minibuffer">
|
||||
<span class="muted">M-x</span>
|
||||
<span style="display:flex;gap:.5rem;flex-wrap:wrap">
|
||||
<span style="display:flex;gap:8px;flex-wrap:wrap">
|
||||
{{#actions}}
|
||||
<a href="{{href}}" class="pill" style="text-decoration:none">{{label}}</a>
|
||||
<a href="{{href}}" class="pill" style="text-decoration:none;cursor:pointer">{{label}}</a>
|
||||
{{/actions}}
|
||||
</span>
|
||||
</footer>
|
||||
</div>
|
||||
{{/minibuffer}}
|
||||
</article>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user