Skip to content

Commit f90095b

Browse files
committed
docs(spec): add heartbeat record pagination design
1 parent 2cd1858 commit f90095b

28 files changed

Lines changed: 10349 additions & 0 deletions

File tree

DESIGN.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,17 @@ Workspaces
132132
- desktop split 的 resize state 必须以 ratio 持久化,而不是记像素宽度;这样窗口变化时 left/right intent 才能保持稳定。
133133
- 如果 route 内还需要第二个滚动区,例如 terminal stage、长列表 pane 或 detail inspection surface,必须显式声明那个次级 scroll owner;不要让 shared body scroll 和 route-local stage scroll 互相抢所有权。
134134

135+
### 5.1 Dense Record Surfaces
136+
137+
- 当页面承载大量可生成记录的 surface(例如 transcript、heartbeat、timeline、inspector rows)时,列表层只承担稳定摘要,不承担完整详情。
138+
- 列表主单元优先使用 `RecordCard` 语义:时间、状态、类型、过程摘要是第一序列;可选叙事、长文本和完整参数应进入 detail。
139+
- 同类型记录的卡片高度必须稳定;可选字段缺失时,应通过布局补位或收纳保持视觉平衡,而不是靠高度抖动表达差异。
140+
- 用户面对的主词优先是 `record` / `RecordCard``group` 这类词可以保留给数据投影层,不应成为主视觉词。
141+
- 详情层以 chips-line rail 作为主导航,时间信息分布在线上而不是塞进卡片正文。
142+
- 当空间宽裕时,导航 rail 可以完整展开为 chip + time + chip;当空间收紧时,优先压缩中段统计,而不是切换成另一套布局语言。
143+
- 详情层的时间线可以用双线表达:外线承载时间与渐变,内线连接 chip 节点;两条线的职责不要混写。
144+
- 如果一条信息已经被一层视觉元素清晰表达,就不要在同一行里重复渲染同一种事实。
145+
135146
## 6) 系统页装配法则
136147

137148
不同系统页面应共享同一套页面物理法则,只改变主体内容语义。
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
schema: vision-driven
2+
created: 2026-06-02
Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
:host {
2+
display: block;
3+
min-inline-size: 0;
4+
inline-size: 100%;
5+
max-inline-size: 100%;
6+
}
7+
8+
@keyframes record-breathe {
9+
0%,
10+
100% {
11+
filter: saturate(1);
12+
opacity: 0.74;
13+
transform: scale(1);
14+
}
15+
16+
50% {
17+
filter: saturate(1.16);
18+
opacity: 1;
19+
transform: scale(1.018);
20+
}
21+
}
22+
23+
@keyframes record-shiny-text {
24+
0% {
25+
background-position: 140% center;
26+
}
27+
28+
100% {
29+
background-position: -140% center;
30+
}
31+
}
32+
33+
.card {
34+
box-sizing: border-box;
35+
display: grid;
36+
grid-template-rows: auto minmax(44px, 1fr);
37+
gap: 10px;
38+
inline-size: 100%;
39+
max-inline-size: 100%;
40+
min-block-size: 126px;
41+
border: 1px solid var(--line);
42+
border-radius: 16px;
43+
background: var(--soft);
44+
padding: 10px;
45+
}
46+
47+
:host([has-support]) .card {
48+
grid-template-rows: auto minmax(44px, 1fr) auto;
49+
min-block-size: 150px;
50+
}
51+
52+
.head {
53+
display: grid;
54+
grid-template-columns: 54px minmax(0, 1fr) auto;
55+
gap: 10px;
56+
align-items: start;
57+
}
58+
59+
.stack {
60+
display: grid;
61+
gap: 2px;
62+
min-inline-size: 0;
63+
}
64+
65+
.status-wrap {
66+
display: flex;
67+
justify-content: flex-end;
68+
}
69+
70+
.body {
71+
display: grid;
72+
align-items: center;
73+
min-inline-size: 0;
74+
}
75+
76+
.support {
77+
display: none;
78+
min-inline-size: 0;
79+
}
80+
81+
:host([has-support]) .support {
82+
display: block;
83+
}
84+
85+
.card.has-support .support {
86+
display: block;
87+
}
88+
89+
::slotted([slot="time"]) {
90+
display: block;
91+
color: var(--ink);
92+
font-size: 12.5px;
93+
font-weight: 760;
94+
line-height: 1.15;
95+
}
96+
97+
::slotted([slot="time"][data-live]),
98+
::slotted([slot="duration"][data-live]) {
99+
animation: record-breathe 2.3s ease-in-out infinite;
100+
transform-origin: left center;
101+
}
102+
103+
::slotted([slot="duration"]),
104+
::slotted([slot="meta"]),
105+
::slotted([slot="support"]) {
106+
display: block;
107+
color: var(--muted);
108+
font-size: 10.5px;
109+
line-height: 1.35;
110+
}
111+
112+
::slotted([slot="title"]) {
113+
display: block;
114+
overflow: hidden;
115+
color: var(--ink);
116+
font-size: 12.5px;
117+
font-weight: 760;
118+
line-height: 1.15;
119+
text-overflow: ellipsis;
120+
white-space: nowrap;
121+
}
122+
123+
::slotted([slot="meta"]),
124+
::slotted([slot="support"]) {
125+
overflow: hidden;
126+
text-overflow: ellipsis;
127+
white-space: nowrap;
128+
}
129+
130+
::slotted([slot="status"]) {
131+
display: inline-flex;
132+
align-items: center;
133+
gap: 6px;
134+
border: 1px solid var(--line);
135+
border-radius: 999px;
136+
background: #fff;
137+
padding: 3px 7px;
138+
color: var(--muted);
139+
font-size: 10px;
140+
font-weight: 760;
141+
line-height: 1;
142+
white-space: nowrap;
143+
}
144+
145+
::slotted([slot="status"][data-status="running"]) {
146+
border-color: color-mix(in oklab, var(--kind-pending, #b45309), white 50%);
147+
background: color-mix(in oklab, var(--kind-pending, #b45309), white 91%);
148+
color: color-mix(in oklab, var(--kind-pending, #b45309), black 16%);
149+
animation: record-breathe 2.3s ease-in-out infinite;
150+
transform-origin: right center;
151+
}
152+
153+
::slotted([slot="status"][data-status="streaming"]) {
154+
border-color: color-mix(in oklab, var(--tone-accent, #2563eb), white 54%);
155+
background: color-mix(in oklab, var(--tone-accent, #2563eb), white 92%);
156+
color: color-mix(in oklab, var(--tone-accent, #2563eb), black 12%);
157+
animation: record-breathe 2.3s ease-in-out infinite;
158+
transform-origin: right center;
159+
}
160+
161+
::slotted([slot="status"][data-status="error"]) {
162+
border-color: color-mix(in oklab, var(--kind-error, #dc2626), white 58%);
163+
background: color-mix(in oklab, var(--kind-error, #dc2626), white 92%);
164+
color: color-mix(in oklab, var(--kind-error, #dc2626), black 10%);
165+
}
166+
167+
::slotted([slot="status"][data-shiny]) {
168+
--status-shine-base: color-mix(in oklab, var(--tone-accent, #2563eb), black 10%);
169+
background-image: linear-gradient(
170+
100deg,
171+
var(--status-shine-base) 18%,
172+
color-mix(in oklab, var(--status-shine-base), white 56%) 46%,
173+
var(--status-shine-base) 72%
174+
);
175+
background-position: 140% center;
176+
background-size: 220% 100%;
177+
-webkit-background-clip: text;
178+
background-clip: text;
179+
color: transparent;
180+
animation:
181+
record-shiny-text 2.2s linear infinite,
182+
record-breathe 2.3s ease-in-out infinite;
183+
}
184+
185+
::slotted([slot="body"]) {
186+
display: block;
187+
min-inline-size: 0;
188+
}

0 commit comments

Comments
 (0)