ui(dev SPA): 主页轻量美化 — header brand logo + 左 pane 子行轻分隔 + 顶栏语义按钮 hover-only 上色 + 圆角微调

- header: 加 24×24 红渐变 "Z" logo + 标题 14→15px + 1px 极淡 box-shadow
- 左 pane: --border-soft #ececec + `#pane-left .pane-head + .pane-head` 把 filter/sort 子行换白底淡分隔,inline border-top 顺手去掉(避免与新 border-bottom 双线)
- 顶栏 4 按钮 + 选入弹框 copy/move: 常态中性 + hover 一次性上语义色(color/border/bg),沿用 button.danger 的 hover-only 范式,button 基础类加 0.15s transition
- 圆角: button/input/.msg/floating-menu 4→6; 三个 modal 卡片 6→8 + 阴影 0 8px 24px → 0 12px 32px

纯 CSS / HTML, 不动 JS / 后端 / DESIGN / RUN; dd-item 菜单语义色保留(菜单内动作类型区分,不在"顶栏中性"范畴)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
caoqianming 2026-05-20 10:36:22 +08:00
parent 7fc9570ffe
commit 515684e60b
1 changed files with 40 additions and 27 deletions

View File

@ -16,6 +16,7 @@
--bg: #f7f7f7; --bg: #f7f7f7;
--panel: #ffffff; --panel: #ffffff;
--border: #e3e3e3; --border: #e3e3e3;
--border-soft: #ececec;
--text: #222; --text: #222;
--muted: #888; --muted: #888;
--accent: #c0392b; --accent: #c0392b;
@ -37,7 +38,8 @@
} }
button { button {
background: #fff; border: 1px solid var(--border); background: #fff; border: 1px solid var(--border);
padding: 4px 10px; border-radius: 4px; cursor: pointer; padding: 4px 10px; border-radius: 6px; cursor: pointer;
transition: color .15s, border-color .15s, background .15s, box-shadow .15s;
} }
button:hover { background: var(--hover); } button:hover { background: var(--hover); }
button.primary { background: var(--accent); color: #fff; border-color: var(--accent); } button.primary { background: var(--accent); color: #fff; border-color: var(--accent); }
@ -46,7 +48,7 @@
input:not([type="checkbox"]):not([type="radio"]):not([type="file"]), input:not([type="checkbox"]):not([type="radio"]):not([type="file"]),
textarea, select { textarea, select {
background: #fff; border: 1px solid var(--border); background: #fff; border: 1px solid var(--border);
padding: 5px 8px; border-radius: 4px; width: 100%; padding: 5px 8px; border-radius: 6px; width: 100%;
} }
input[type="checkbox"], input[type="radio"] { cursor: pointer; } input[type="checkbox"], input[type="radio"] { cursor: pointer; }
textarea { resize: vertical; min-height: 60px; } textarea { resize: vertical; min-height: 60px; }
@ -143,8 +145,17 @@
header { header {
grid-area: head; background: #fff; border-bottom: 1px solid var(--border); grid-area: head; background: #fff; border-bottom: 1px solid var(--border);
padding: 8px 14px; display: flex; align-items: center; gap: 12px; padding: 8px 14px; display: flex; align-items: center; gap: 12px;
box-shadow: 0 1px 2px rgba(0,0,0,.03);
} }
header .title { font-weight: 600; } header .brand { display: flex; align-items: center; gap: 8px; }
header .brand .logo {
width: 24px; height: 24px; border-radius: 6px;
background: linear-gradient(135deg, var(--accent), #8e2a20);
color: #fff; font-weight: 700; font-size: 13px;
display: flex; align-items: center; justify-content: center;
box-shadow: 0 2px 6px rgba(192,57,43,.28);
}
header .title { font-weight: 600; font-size: 15px; letter-spacing: .2px; }
header .who { color: var(--muted); font-size: 12px; font-family: monospace; } header .who { color: var(--muted); font-size: 12px; font-family: monospace; }
header .spacer { flex: 1; } header .spacer { flex: 1; }
@ -161,15 +172,16 @@
} }
.pane-head .label { font-weight: 600; font-size: 13px; white-space: nowrap; flex-shrink: 0; } .pane-head .label { font-weight: 600; font-size: 13px; white-space: nowrap; flex-shrink: 0; }
.pane-head .spacer { flex: 1; } .pane-head .spacer { flex: 1; }
/* 对话顶栏按钮:语义化常态上色 — 完成 绿/导出 蓝/废弃 橙/删除 红 */ /* 左 pane:title 行(#fafafa)下面的 filter / sort 子行换成白底 + 极淡分隔,弱化层级 */
#btn-done { color: #27ae60; border-color: #a9dfbf; } #pane-left .pane-head + .pane-head {
#btn-export { color: #2980b9; border-color: #aed6f1; } background: #fff;
#btn-abandon { color: #e67e22; border-color: #f5cba7; } border-bottom: 1px solid var(--border-soft);
#btn-delete-task { color: #c0392b; border-color: #f5b7b1; } }
#btn-done:hover:not(:disabled) { background: #e9f7ef; } /* 对话顶栏按钮:常态中性 + hover 上语义色 — 完成 绿/导出 蓝/废弃 橙/删除 红 */
#btn-export:hover:not(:disabled) { background: #ebf5fb; } #btn-done:hover:not(:disabled) { color: #27ae60; border-color: #a9dfbf; background: #e9f7ef; }
#btn-abandon:hover:not(:disabled) { background: #fef5e7; } #btn-export:hover:not(:disabled) { color: #2980b9; border-color: #aed6f1; background: #ebf5fb; }
#btn-delete-task:hover:not(:disabled) { background: #fdedec; } #btn-abandon:hover:not(:disabled) { color: #e67e22; border-color: #f5cba7; background: #fef5e7; }
#btn-delete-task:hover:not(:disabled) { color: #c0392b; border-color: #f5b7b1; background: #fdedec; }
#pane-mid > .pane-head > button.small:disabled { opacity: 0.4; cursor: not-allowed; } #pane-mid > .pane-head > button.small:disabled { opacity: 0.4; cursor: not-allowed; }
/* ───── floating dropdown menu ───── */ /* ───── floating dropdown menu ───── */
@ -183,7 +195,7 @@
#floating-menu { #floating-menu {
display: none; position: fixed; display: none; position: fixed;
min-width: 132px; background: #fff; min-width: 132px; background: #fff;
border: 1px solid var(--border); border-radius: 4px; border: 1px solid var(--border); border-radius: 6px;
box-shadow: 0 4px 14px rgba(0,0,0,0.12); box-shadow: 0 4px 14px rgba(0,0,0,0.12);
z-index: 60; padding: 4px 0; z-index: 60; padding: 4px 0;
} }
@ -233,7 +245,7 @@
min-height: 0; /* 同上,允许在 flex 容器里收缩 + 触发自身滚动 */ min-height: 0; /* 同上,允许在 flex 容器里收缩 + 触发自身滚动 */
} }
.msg { .msg {
border: 1px solid var(--border); border-radius: 4px; padding: 8px 12px; border: 1px solid var(--border); border-radius: 6px; padding: 8px 12px;
max-width: 92%; max-width: 92%;
} }
.msg.user { background: var(--user-bg); align-self: flex-end; } .msg.user { background: var(--user-bg); align-self: flex-end; }
@ -338,10 +350,10 @@
} }
#src-picker-modal.show { display: flex; } #src-picker-modal.show { display: flex; }
#src-picker-modal .card { #src-picker-modal .card {
background: var(--panel); border-radius: 6px; background: var(--panel); border-radius: 8px;
width: 560px; max-height: 82vh; width: 560px; max-height: 82vh;
display: flex; flex-direction: column; display: flex; flex-direction: column;
box-shadow: 0 8px 24px rgba(0,0,0,.15); box-shadow: 0 12px 32px rgba(0,0,0,.18);
} }
#src-picker-modal h3 { #src-picker-modal h3 {
margin: 0; padding: 14px 18px; font-size: 16px; margin: 0; padding: 14px 18px; font-size: 16px;
@ -386,10 +398,8 @@
#src-picker-modal .actions .count { #src-picker-modal .actions .count {
flex: 1; font-size: 12px; color: var(--muted); flex: 1; font-size: 12px; color: var(--muted);
} }
#sp-copy { color: #1565c0; border-color: #aed6f1; } #sp-copy:hover:not(:disabled) { color: #1565c0; border-color: #aed6f1; background: #ebf5fb; }
#sp-copy:hover:not(:disabled) { background: #ebf5fb; } #sp-move:hover:not(:disabled) { color: #c77800; border-color: #f5cba7; background: #fef5e7; }
#sp-move { color: #c77800; border-color: #f5cba7; }
#sp-move:hover:not(:disabled) { background: #fef5e7; }
#sp-copy:disabled, #sp-move:disabled { opacity: 0.4; cursor: not-allowed; } #sp-copy:disabled, #sp-move:disabled { opacity: 0.4; cursor: not-allowed; }
/* ───── new task modal ───── */ /* ───── new task modal ───── */
@ -399,8 +409,8 @@
} }
#new-task-modal.show { display: flex; } #new-task-modal.show { display: flex; }
#new-task-modal .card { #new-task-modal .card {
background: var(--panel); padding: 20px; border-radius: 6px; background: var(--panel); padding: 20px; border-radius: 8px;
width: 420px; box-shadow: 0 8px 24px rgba(0,0,0,.15); width: 420px; box-shadow: 0 12px 32px rgba(0,0,0,.18);
} }
#new-task-modal h3 { margin: 0 0 12px; font-size: 16px; } #new-task-modal h3 { margin: 0 0 12px; font-size: 16px; }
#new-task-modal label { display: block; margin-top: 8px; font-size: 12px; color: var(--muted); } #new-task-modal label { display: block; margin-top: 8px; font-size: 12px; color: var(--muted); }
@ -414,10 +424,10 @@
} }
#file-preview-modal.show { display: flex; } #file-preview-modal.show { display: flex; }
#file-preview-modal .card { #file-preview-modal .card {
background: var(--panel); border-radius: 6px; background: var(--panel); border-radius: 8px;
width: 90vw; height: 90vh; max-width: 1200px; width: 90vw; height: 90vh; max-width: 1200px;
display: flex; flex-direction: column; display: flex; flex-direction: column;
box-shadow: 0 8px 24px rgba(0,0,0,.2); box-shadow: 0 12px 32px rgba(0,0,0,.22);
} }
#file-preview-modal .hdr { #file-preview-modal .hdr {
display: flex; align-items: center; gap: 8px; display: flex; align-items: center; gap: 8px;
@ -526,7 +536,10 @@
<!-- ───── main 3-pane ───── --> <!-- ───── main 3-pane ───── -->
<div id="app"> <div id="app">
<header> <header>
<div class="brand">
<div class="logo">Z</div>
<div class="title">zcbot</div> <div class="title">zcbot</div>
</div>
<div class="who" id="hd-who"></div> <div class="who" id="hd-who"></div>
<div class="spacer"></div> <div class="spacer"></div>
<button id="hd-new" class="primary">+ 新建任务</button> <button id="hd-new" class="primary">+ 新建任务</button>
@ -546,11 +559,11 @@
</select> </select>
<button id="btn-refresh-tasks" class="small" title="刷新"></button> <button id="btn-refresh-tasks" class="small" title="刷新"></button>
</div> </div>
<div class="pane-head" style="border-top: 1px solid var(--border); gap: 6px;"> <div class="pane-head" style="gap: 6px;">
<input id="filter-q" class="small" placeholder="搜索名称/描述..." style="flex:1; padding: 3px 6px;" /> <input id="filter-q" class="small" placeholder="搜索名称/描述..." style="flex:1; padding: 3px 6px;" />
<input id="filter-wd" list="folders-datalist" class="small" placeholder="工作目录" style="flex:1; padding: 3px 6px;" /> <input id="filter-wd" list="folders-datalist" class="small" placeholder="工作目录" style="flex:1; padding: 3px 6px;" />
</div> </div>
<div class="pane-head" style="border-top: 1px solid var(--border); gap: 6px;"> <div class="pane-head" style="gap: 6px;">
<span class="small muted" style="white-space:nowrap;">排序</span> <span class="small muted" style="white-space:nowrap;">排序</span>
<select id="filter-order" class="small" style="flex:1; width:auto;"> <select id="filter-order" class="small" style="flex:1; width:auto;">
<option value="-created_at">创建时间 ↓(新→旧)</option> <option value="-created_at">创建时间 ↓(新→旧)</option>