@blade-hq/agent-react 2610.0.0-beta.8 → 2610.0.0-beta.80
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +313 -8
- package/dist/chunk-G3PMV62Z.js +36 -0
- package/dist/components/AgentChat.d.ts +3 -0
- package/dist/components/AgentLoopBlock.d.ts +3 -5
- package/dist/components/AgentTaskCard.d.ts +12 -0
- package/dist/components/AskUserQuestionBlock.d.ts +12 -1
- package/dist/components/AssistantTurnBlock.d.ts +26 -8
- package/dist/components/ChatInput.d.ts +21 -1
- package/dist/components/ChatSurface.d.ts +133 -2
- package/dist/components/ChatView.d.ts +1 -1
- package/dist/components/ConnectorPanel.d.ts +41 -0
- package/dist/components/ContextCard.d.ts +20 -0
- package/dist/components/MarkdownContent.d.ts +17 -0
- package/dist/components/McpAppCard.d.ts +14 -0
- package/dist/components/MessageList.d.ts +38 -4
- package/dist/components/PlanUpdateBlock.d.ts +32 -0
- package/dist/components/PluginConnectorList.d.ts +47 -0
- package/dist/components/PluginTriggerStack.d.ts +22 -0
- package/dist/components/PostChatFollowupBlock.d.ts +5 -1
- package/dist/components/SessionMemoryToggle.d.ts +19 -0
- package/dist/components/SessionPluginConfigDialog.d.ts +10 -0
- package/dist/components/SessionPluginConfigForm.d.ts +14 -0
- package/dist/components/SessionPluginIcon.d.ts +30 -0
- package/dist/components/SessionPluginSelector.d.ts +10 -0
- package/dist/components/SessionQueuePanel.d.ts +74 -0
- package/dist/components/ToolCallBlock.d.ts +9 -3
- package/dist/components/ToolUiCardView.d.ts +9 -0
- package/dist/components/TurnNavRail.d.ts +23 -0
- package/dist/components/UserMessageBubble.d.ts +7 -3
- package/dist/components/WhatIfUserBubble.d.ts +7 -0
- package/dist/components/connector-panel-types.d.ts +37 -0
- package/dist/components/display-utils.d.ts +10 -0
- package/dist/components/markdown/heal-incomplete.d.ts +7 -0
- package/dist/components/markdown/incremental.d.ts +73 -0
- package/dist/components/markdown/index.d.ts +18 -0
- package/dist/components/markdown/parse.d.ts +19 -0
- package/dist/components/markdown/render.d.ts +79 -0
- package/dist/components/markdown/sanitize.d.ts +50 -0
- package/dist/components/markdown/types.d.ts +53 -0
- package/dist/components/plugin-config-draft.d.ts +13 -0
- package/dist/components/plugin-config-schema.d.ts +6 -0
- package/dist/components/plugin-connector.d.ts +40 -0
- package/dist/components/queue-panel-adjacency.d.ts +1 -0
- package/dist/components/use-session-plugin-activation.d.ts +40 -0
- package/dist/context.d.ts +1 -0
- package/dist/embed/blade-chat-element.d.ts +4 -3
- package/dist/embed/entry.d.ts +49 -0
- package/dist/hooks/use-agent-session.d.ts +5 -0
- package/dist/hooks/use-message-pin.d.ts +28 -0
- package/dist/hooks/use-turn-navigation.d.ts +117 -0
- package/dist/hooks/use-typewriter-reveal.d.ts +32 -0
- package/dist/index.d.ts +53 -1
- package/dist/index.js +58278 -2242
- package/dist/index.js.map +1 -1
- package/dist/lib/agent-computer-command.d.ts +34 -0
- package/dist/lib/random-id.d.ts +10 -0
- package/dist/lib/utils.d.ts +17 -2
- package/dist/lib/whatif-prompt.d.ts +18 -0
- package/dist/style.css +506 -401
- package/dist/style.full.css +517 -405
- package/dist/webapi-W3IB5DO4.js +2481 -0
- package/dist/webapi-W3IB5DO4.js.map +1 -0
- package/package.json +2 -2
- package/public-api.md +1749 -65
- package/dist/chunk-ZXXLY4RM.js +0 -28255
- package/dist/chunk-ZXXLY4RM.js.map +0 -1
- package/dist/highlighted-body-B3W2YXNL-YD7FAP6V.js +0 -27
- package/dist/highlighted-body-B3W2YXNL-YD7FAP6V.js.map +0 -1
- package/dist/mermaid-3ZIDBTTL-N7YKJ3SM.js +0 -8
- /package/dist/{mermaid-3ZIDBTTL-N7YKJ3SM.js.map → chunk-G3PMV62Z.js.map} +0 -0
package/dist/style.css
CHANGED
|
@@ -1,11 +1,108 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* @blade-hq/agent-react 自包含样式。
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* 这份文件只放 Tailwind 工具类表达不了的东西,其余视觉一律由组件上的 Tailwind
|
|
5
|
+
* class 定义一次(R1:一个视觉效果只在一处定义):
|
|
6
|
+
*
|
|
7
|
+
* - CSS 变量(主题、圆角、gutter)与 `:host` 尺寸默认值;
|
|
8
|
+
* - 容器查询(`@container`):按「容器宽度」而不是视口伸缩的内边距与断点;
|
|
9
|
+
* - Markdown 排版:正文是 streamdown 生成的 HTML,没有类名可挂,只能在这里写;
|
|
10
|
+
* - 无 Tailwind 预检时组件仍需要的少量 rest(按钮游标、textarea 去边框);
|
|
11
|
+
* - 跨元素的形状约束,如 `.blade-chat-messages-content > div` 的轮次间距。
|
|
12
|
+
*
|
|
13
|
+
* 组件上的 Tailwind class 不再需要在这里重复一份。视觉规则的层序见下面
|
|
14
|
+
* `@layer` 声明:兜底在 components 层,Tailwind 工具类在 utilities 层,
|
|
15
|
+
* 接入方无层的普通 CSS 天然最高优先——所以 `.blade-chat-user-bubble { background: red }`
|
|
16
|
+
* 一定生效,不需要 `!important`。
|
|
7
17
|
*/
|
|
8
18
|
|
|
19
|
+
/* ------------------------------------------------------------ 语义锚点清单
|
|
20
|
+
*
|
|
21
|
+
* 公开契约:每个可见区块的根元素固定带一个 blade-chat-* 类,接入方用普通 CSS
|
|
22
|
+
* 选它即可覆盖 SDK 默认样式(README「样式定制」第 4 层),不需要 !important,
|
|
23
|
+
* 也不需要跟着 SDK 的构建顺序走。
|
|
24
|
+
*
|
|
25
|
+
* 锚点只承担「可被选中」职责,不承载视觉规则。下面的兜底样式里出现的锚点,
|
|
26
|
+
* 只是恰好需要兜底的那几个;清单本身才是契约的一部分。
|
|
27
|
+
*
|
|
28
|
+
* scripts/gen-embed-styles.mjs 会校验这份清单的两件事:源码里出现的每个锚点都
|
|
29
|
+
* 必须在这里登记;清单里的每个锚点都必须出现在三份 CSS 产物中。新增可见区块时
|
|
30
|
+
* 先在这里登记锚点,再让元素带上它。
|
|
31
|
+
*
|
|
32
|
+
* @blade-chat-anchors
|
|
33
|
+
* blade-chat
|
|
34
|
+
* blade-chat-advanced
|
|
35
|
+
* blade-chat-agent-loop
|
|
36
|
+
* blade-chat-ask-card
|
|
37
|
+
* blade-chat-ask-option
|
|
38
|
+
* blade-chat-assistant-text
|
|
39
|
+
* blade-chat-assistant-turn
|
|
40
|
+
* blade-chat-banner
|
|
41
|
+
* blade-chat-codeblock
|
|
42
|
+
* blade-chat-codeblock-body
|
|
43
|
+
* blade-chat-codeblock-header
|
|
44
|
+
* blade-chat-context-card
|
|
45
|
+
* blade-chat-context-chevron
|
|
46
|
+
* blade-chat-context-copy
|
|
47
|
+
* blade-chat-context-detail
|
|
48
|
+
* blade-chat-context-group-items
|
|
49
|
+
* blade-chat-context-icon
|
|
50
|
+
* blade-chat-context-status
|
|
51
|
+
* blade-chat-context-summary
|
|
52
|
+
* blade-chat-context-title
|
|
53
|
+
* blade-chat-empty
|
|
54
|
+
* blade-chat-error-bar
|
|
55
|
+
* blade-chat-error-block
|
|
56
|
+
* blade-chat-error-row
|
|
57
|
+
* blade-chat-file-card
|
|
58
|
+
* blade-chat-file-card-icon
|
|
59
|
+
* blade-chat-file-card-name
|
|
60
|
+
* blade-chat-followup
|
|
61
|
+
* blade-chat-followup-action
|
|
62
|
+
* blade-chat-host
|
|
63
|
+
* blade-chat-input
|
|
64
|
+
* blade-chat-input-inner
|
|
65
|
+
* blade-chat-input-toolbar
|
|
66
|
+
* blade-chat-login
|
|
67
|
+
* blade-chat-markdown
|
|
68
|
+
* blade-chat-mcp-app
|
|
69
|
+
* blade-chat-memory-refs
|
|
70
|
+
* blade-chat-messages
|
|
71
|
+
* blade-chat-messages-content
|
|
72
|
+
* blade-chat-messages-scroll
|
|
73
|
+
* blade-chat-plan
|
|
74
|
+
* blade-chat-plan-block
|
|
75
|
+
* blade-chat-prose
|
|
76
|
+
* blade-chat-queue
|
|
77
|
+
* blade-chat-queue-item
|
|
78
|
+
* blade-chat-queue-notice
|
|
79
|
+
* blade-chat-render-error
|
|
80
|
+
* blade-chat-replay-bar
|
|
81
|
+
* blade-chat-scroll-bottom
|
|
82
|
+
* blade-chat-scroll-bottom-label
|
|
83
|
+
* blade-chat-table-wrapper
|
|
84
|
+
* blade-chat-textarea
|
|
85
|
+
* blade-chat-thinking
|
|
86
|
+
* blade-chat-tool-row
|
|
87
|
+
* blade-chat-user-bubble
|
|
88
|
+
* blade-chat-user-col
|
|
89
|
+
* blade-chat-user-row
|
|
90
|
+
*/
|
|
91
|
+
|
|
92
|
+
/* 层序先定死:兜底排在 Tailwind 工具类之前,换肤和覆盖才有稳定的先后。
|
|
93
|
+
* 三份产物都从这一行开始,Tailwind 自己那份声明用的是同一个顺序。
|
|
94
|
+
*
|
|
95
|
+
* properties 是 Tailwind 自己的 --tw-* 初始值层,必须排在最前:它的 `* { --tw-*: … }`
|
|
96
|
+
* 一旦排在 utilities 之后,就会把工具类设的 translate / ring / shadow 变量初始化掉。
|
|
97
|
+
*
|
|
98
|
+
* 最后一层 blade-chat-overrides 是给「必须压过组件自己 Tailwind 类」的规则用的:窄容器里
|
|
99
|
+
* 放宽用户消息宽度、iOS 聚焦不缩放、代码块与 Markdown 的排版——这些规则一旦
|
|
100
|
+
* 掉进 components 层就会被同元素的 utilities 盖掉,等于没写。接入方的普通
|
|
101
|
+
* CSS 不分层,仍然赢过这里所有层。 */
|
|
102
|
+
@layer properties, theme, base, components, utilities, blade-chat-overrides;
|
|
103
|
+
|
|
104
|
+
/* 变量不分层:它是主题契约,接入方在页面或祖先元素上重设同名变量即可换肤,
|
|
105
|
+
* 分层反而让"谁覆盖谁"取决于产物拼接顺序。 */
|
|
9
106
|
:root,
|
|
10
107
|
:host {
|
|
11
108
|
--background: 0 0% 100%;
|
|
@@ -54,496 +151,504 @@
|
|
|
54
151
|
--user-msg-border: 38 30% 19%;
|
|
55
152
|
}
|
|
56
153
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
/* <blade-chat> 宿主默认块级 + 默认高度;页面对元素写的任何尺寸规则都会覆盖
|
|
60
|
-
* :host 默认值。host 容器把高度传导给内部 flex 链,消息区撑满、输入框钉底。 */
|
|
61
|
-
:host {
|
|
62
|
-
display: block;
|
|
63
|
-
height: 560px;
|
|
64
|
-
}
|
|
154
|
+
@layer components {
|
|
155
|
+
/* -------------------------------------------------------------- 布局骨架 */
|
|
65
156
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
157
|
+
/* <blade-chat> 宿主默认块级 + 默认高度;页面对元素写的任何尺寸规则都会覆盖
|
|
158
|
+
* :host 默认值。host 容器把高度传导给内部 flex 链,消息区撑满、输入框钉底。 */
|
|
159
|
+
:host {
|
|
160
|
+
display: block;
|
|
161
|
+
height: 560px;
|
|
162
|
+
}
|
|
71
163
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
.blade-chat {
|
|
78
|
-
/* 具名容器:宿主或以后的子组件万一在中间又建了个匿名 query container,
|
|
79
|
-
* 下面的 @container 查询不会悄悄改成以那个为基准。 */
|
|
80
|
-
container: blade-chat / inline-size;
|
|
81
|
-
display: flex;
|
|
82
|
-
flex-direction: column;
|
|
83
|
-
flex: 1 1 0%;
|
|
84
|
-
min-height: 0;
|
|
85
|
-
min-width: 0;
|
|
86
|
-
overflow: hidden;
|
|
87
|
-
--blade-chat-gutter: 1rem;
|
|
88
|
-
--blade-chat-turn-gap: 1.5rem;
|
|
89
|
-
background: hsl(var(--background));
|
|
90
|
-
color: hsl(var(--foreground));
|
|
91
|
-
font-family:
|
|
92
|
-
system-ui,
|
|
93
|
-
-apple-system,
|
|
94
|
-
"Segoe UI",
|
|
95
|
-
Roboto,
|
|
96
|
-
"PingFang SC",
|
|
97
|
-
"Microsoft YaHei",
|
|
98
|
-
sans-serif;
|
|
99
|
-
}
|
|
164
|
+
.blade-chat-host {
|
|
165
|
+
height: 100%;
|
|
166
|
+
display: flex;
|
|
167
|
+
flex-direction: column;
|
|
168
|
+
}
|
|
100
169
|
|
|
101
|
-
/*
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
170
|
+
/* 聊天根容器。SDK 常被嵌进只有 300-400px 宽的侧栏,而宿主页面视口是全宽的,
|
|
171
|
+
* 所以内边距一律按「容器宽度」伸缩,不能用视口断点——那会在窄容器里反向命中最大值。
|
|
172
|
+
* container-type 建在这里(而不是消息区),是为了让消息区和输入区共享同一个 cqi
|
|
173
|
+
* 基准,两者左右边缘才对得齐。代价是内部内容不再向外传递固有宽度,所以宿主需要给
|
|
174
|
+
* 容器一个确定宽度(flex/grid 拉伸或显式宽度都可以)。
|
|
175
|
+
* 底色与文字色也从这里给:根节点上没有对应的 Tailwind class。 */
|
|
106
176
|
.blade-chat {
|
|
107
|
-
|
|
108
|
-
|
|
177
|
+
/* 具名容器:宿主或以后的子组件万一在中间又建了个匿名 query container,
|
|
178
|
+
* 下面的 @container 查询不会悄悄改成以那个为基准。 */
|
|
179
|
+
container: blade-chat / inline-size;
|
|
180
|
+
min-width: 0;
|
|
181
|
+
--blade-chat-gutter: 1rem;
|
|
182
|
+
--blade-chat-turn-gap: 1.5rem;
|
|
183
|
+
background: hsl(var(--background));
|
|
184
|
+
color: hsl(var(--foreground));
|
|
185
|
+
font-family:
|
|
186
|
+
system-ui,
|
|
187
|
+
-apple-system,
|
|
188
|
+
"Segoe UI",
|
|
189
|
+
Roboto,
|
|
190
|
+
"PingFang SC",
|
|
191
|
+
"Microsoft YaHei",
|
|
192
|
+
sans-serif;
|
|
109
193
|
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
.blade-chat-messages {
|
|
113
|
-
position: relative;
|
|
114
|
-
flex: 1 1 0%;
|
|
115
|
-
min-height: 0;
|
|
116
|
-
}
|
|
117
194
|
|
|
118
|
-
/*
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
195
|
+
/* 上面两个变量的兜底值必须留在 @supports 外面。不能靠「同一个变量写两遍、让浏览器
|
|
196
|
+
* 丢掉无效的那条」降级:自定义属性在声明处不做类型校验,带 cqi 的值在旧浏览器里同样是
|
|
197
|
+
* 合法 token、照样覆盖兜底值,失效发生在 padding: var(...) 的使用处——结果是整条 padding
|
|
198
|
+
* 作废变成 0,而不是回落到兜底值。 */
|
|
199
|
+
@supports (container-type: inline-size) and (width: 1cqi) {
|
|
200
|
+
.blade-chat {
|
|
201
|
+
--blade-chat-gutter: clamp(0.875rem, 4cqi, 2.5rem);
|
|
202
|
+
--blade-chat-turn-gap: clamp(1.25rem, 3cqi, 2.25rem);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
123
205
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
206
|
+
/* 滚动内容的内边距。左右按上面的 gutter 变量走,宿主没装 Tailwind 时消息也不会贴边;
|
|
207
|
+
* 底部那份补白是消息顶置功能的 spacer(--blade-chat-pin-spacer 由组件写行内变量)。 */
|
|
208
|
+
.blade-chat-messages-scroll {
|
|
209
|
+
padding: calc(var(--blade-chat-gutter) * 1.4) var(--blade-chat-gutter)
|
|
210
|
+
calc(var(--blade-chat-gutter) * 1.1 + var(--blade-chat-pin-spacer, 0px));
|
|
211
|
+
}
|
|
128
212
|
|
|
129
|
-
.blade-chat
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
min-width: 0;
|
|
134
|
-
}
|
|
213
|
+
/* 轮次之间的间距用容器宽度算(见 .blade-chat 的说明),挂在内层容器上。 */
|
|
214
|
+
.blade-chat-messages-content > div {
|
|
215
|
+
gap: var(--blade-chat-turn-gap);
|
|
216
|
+
}
|
|
135
217
|
|
|
136
|
-
.blade-chat-empty {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
}
|
|
218
|
+
.blade-chat-empty {
|
|
219
|
+
display: flex;
|
|
220
|
+
flex-direction: column;
|
|
221
|
+
align-items: center;
|
|
222
|
+
justify-content: center;
|
|
223
|
+
gap: 0.75rem;
|
|
224
|
+
/* 这里的双写是有效降级:cqi 出现在属性值里,旧浏览器会丢掉整条声明并回落到上一条。 */
|
|
225
|
+
padding: 4rem 0;
|
|
226
|
+
padding: clamp(2.5rem, 12cqi, 6rem) 0;
|
|
227
|
+
color: hsl(var(--muted-foreground));
|
|
228
|
+
}
|
|
147
229
|
|
|
148
|
-
|
|
149
|
-
.blade-chat-version-mismatch {
|
|
150
|
-
display: flex;
|
|
151
|
-
flex: 1 1 0%;
|
|
152
|
-
align-items: center;
|
|
153
|
-
justify-content: center;
|
|
154
|
-
padding: 1.5rem;
|
|
155
|
-
}
|
|
230
|
+
/* -------------------------------------------------------------- 输入区 */
|
|
156
231
|
|
|
157
|
-
/*
|
|
232
|
+
/* 左右内边距和消息区共用同一个 gutter,否则输入框与消息文字左边缘对不齐。
|
|
233
|
+
* 上下留白由组件上的 py-3 / pt-0 给。 */
|
|
234
|
+
.blade-chat-input {
|
|
235
|
+
/* 队列面板占位时组件会加上 border-t-0 收起这条线,所以这里不能写死:写死会
|
|
236
|
+
盖过那个切换。用变量保留默认值,外层仍按原样渲染一条分隔线。 */
|
|
237
|
+
border-top: var(--blade-chat-input-top-border, 1px solid hsl(var(--border)));
|
|
238
|
+
padding-left: var(--blade-chat-gutter);
|
|
239
|
+
padding-right: var(--blade-chat-gutter);
|
|
240
|
+
}
|
|
158
241
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
242
|
+
/* 队列面板的外层左右留白:必须跟下面输入框一致,两边各自居中才不会错位。
|
|
243
|
+
* 默认跟随本包输入框用的同一个 gutter 变量;宿主输入框用别的留白时(内置 Web
|
|
244
|
+
* 的输入框外层是 px-5),在自己的样式里覆盖 --blade-chat-queue-gutter 即可。 */
|
|
245
|
+
.blade-chat-queue {
|
|
246
|
+
--blade-chat-queue-gutter: var(--blade-chat-gutter, 1rem);
|
|
247
|
+
padding-left: var(--blade-chat-queue-gutter);
|
|
248
|
+
padding-right: var(--blade-chat-queue-gutter);
|
|
249
|
+
}
|
|
163
250
|
|
|
164
|
-
|
|
165
|
-
display: flex;
|
|
166
|
-
flex-direction: column;
|
|
167
|
-
align-items: flex-end;
|
|
168
|
-
gap: 0.75rem;
|
|
169
|
-
max-width: 72%;
|
|
170
|
-
}
|
|
251
|
+
/* ------------------------------------------------- 无 preflight 时的控件复位 */
|
|
171
252
|
|
|
172
|
-
/*
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
253
|
+
/* 组件上的工具类不负责这些:宿主只用 style.css 且自己的 Tailwind 关了 preflight 时,
|
|
254
|
+
输入框和按钮会退回浏览器默认外观(原生边框、原生按钮底色)。 */
|
|
255
|
+
.blade-chat-textarea {
|
|
256
|
+
border: 0;
|
|
257
|
+
font: inherit;
|
|
177
258
|
}
|
|
178
259
|
|
|
179
|
-
.blade-chat-
|
|
180
|
-
|
|
260
|
+
.blade-chat-input-inner button,
|
|
261
|
+
.blade-chat-codeblock-header button,
|
|
262
|
+
.blade-chat-ask-card button {
|
|
263
|
+
cursor: pointer;
|
|
264
|
+
border: 0;
|
|
265
|
+
background-color: transparent;
|
|
181
266
|
}
|
|
182
|
-
}
|
|
183
267
|
|
|
184
|
-
|
|
185
|
-
max-width: 100%;
|
|
186
|
-
border: 1px solid hsl(var(--user-msg-border));
|
|
187
|
-
background: hsl(var(--user-msg-bg));
|
|
188
|
-
color: hsl(var(--user-msg-fg));
|
|
189
|
-
border-radius: 20px;
|
|
190
|
-
border-bottom-right-radius: 6px;
|
|
191
|
-
padding: 13px 18px;
|
|
192
|
-
font-size: 0.875rem;
|
|
193
|
-
line-height: 1.65;
|
|
194
|
-
}
|
|
268
|
+
/* ------------------------------------------------------------ 出错条配色 */
|
|
195
269
|
|
|
196
|
-
.blade-chat-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
270
|
+
/* 配色由 .blade-chat-error-bar 的 --destructive 变量给,别写死 red-*:
|
|
271
|
+
* Tailwind 的 dark: 变体跟的是系统偏好,会和 data-theme 主题打架。 */
|
|
272
|
+
.blade-chat-error-bar {
|
|
273
|
+
border-bottom-color: hsl(var(--destructive) / 0.3);
|
|
274
|
+
background: hsl(var(--destructive) / 0.08);
|
|
275
|
+
color: hsl(var(--destructive));
|
|
276
|
+
}
|
|
200
277
|
}
|
|
201
278
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
279
|
+
@layer blade-chat-overrides {
|
|
280
|
+
/* ------------------------------------------------- 窄容器与移动端的手感 */
|
|
281
|
+
/* 需要跳变而非连续伸缩的值才用 @container:窄容器里 72% 只剩 250px 左右,
|
|
282
|
+
* 一句话就折三行。这条必须压过组件上的 max-w-[72%],所以归 blade-chat-overrides。 */
|
|
283
|
+
@container blade-chat (max-width: 480px) {
|
|
284
|
+
.blade-chat-user-col {
|
|
285
|
+
max-width: 88%;
|
|
286
|
+
}
|
|
207
287
|
|
|
208
|
-
.blade-chat-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
}
|
|
288
|
+
.blade-chat-scroll-bottom-label {
|
|
289
|
+
display: none;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
212
292
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
293
|
+
/* Keep embedded ChatView usable on iOS without forcing every host app to know
|
|
294
|
+
Safari's 16px focus-zoom threshold. Desktop sizing remains unchanged.
|
|
295
|
+
text-sm / text-xs 会让输入控件低于 16px,所以这条也归 blade-chat-overrides。 */
|
|
296
|
+
@media (hover: none) and (pointer: coarse) {
|
|
297
|
+
.blade-chat-textarea,
|
|
298
|
+
.blade-chat-ask-card input,
|
|
299
|
+
.blade-chat-ask-card textarea {
|
|
300
|
+
font-size: 1rem;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
.blade-chat-input-inner button {
|
|
304
|
+
min-width: 44px;
|
|
305
|
+
min-height: 44px;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
221
308
|
|
|
222
|
-
|
|
223
|
-
display: flex;
|
|
224
|
-
align-items: flex-start;
|
|
225
|
-
gap: 0.5rem;
|
|
226
|
-
border-bottom: 1px solid hsl(var(--destructive) / 0.3);
|
|
227
|
-
background: hsl(var(--destructive) / 0.08);
|
|
228
|
-
padding: 0.75rem 1rem;
|
|
229
|
-
font-size: 0.875rem;
|
|
230
|
-
color: hsl(var(--destructive));
|
|
231
|
-
}
|
|
309
|
+
/* ------------------------------------------------------------- Markdown */
|
|
232
310
|
|
|
233
|
-
/*
|
|
311
|
+
/* 正文是 streamdown 生成的 HTML,元素上没有类名可挂,排版只能写在这里。
|
|
312
|
+
* 反过来,带 Tailwind class 的那几个外壳(codeblock、prose 容器)不在这里重复。 */
|
|
313
|
+
.blade-chat-markdown {
|
|
314
|
+
min-width: 0;
|
|
315
|
+
}
|
|
234
316
|
|
|
235
|
-
/*
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
317
|
+
/* 任务列表项自己已经有 checkbox,不需要再叠一个项目符号——`.contains-task-list`
|
|
318
|
+
* 命名沿用 streamdown/GitHub 的惯例,宿主如果用了 @tailwindcss/typography 的
|
|
319
|
+
* `.prose` 会自带同名规则,这里给没有 typography 插件的宿主兜底。 */
|
|
320
|
+
.blade-chat-markdown .contains-task-list .task-list-item {
|
|
321
|
+
list-style: none;
|
|
322
|
+
}
|
|
240
323
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
border: 1px solid hsl(var(--border));
|
|
248
|
-
background: hsl(var(--card));
|
|
249
|
-
border-radius: 1rem;
|
|
250
|
-
padding: 0.5rem 0.75rem;
|
|
251
|
-
}
|
|
324
|
+
/* 勾选框和文字之间原来没有间隔——scoped-preflight 把子树内所有元素的
|
|
325
|
+
* margin 重置成 0,勾选框和它后面紧跟的文字节点之间没有任何空白/margin
|
|
326
|
+
* 节点,两者会贴在一起;旧的 streamdown DOM 里有一个显式空格。 */
|
|
327
|
+
.blade-chat-markdown .contains-task-list .task-list-item input[type="checkbox"] {
|
|
328
|
+
margin-right: 0.4em;
|
|
329
|
+
}
|
|
252
330
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
min-height: 28px;
|
|
264
|
-
max-height: 12rem;
|
|
265
|
-
outline: none;
|
|
266
|
-
}
|
|
331
|
+
/* 窄容器里真正把版面撑破的是内容而不是内边距:宽表格、大图、超长 URL 都会把整个
|
|
332
|
+
* 消息区顶宽,然后出现一条横向滚动条。表格自己滚,图片自己缩,长 token 强制断行。
|
|
333
|
+
* 新渲染器不再产出 streamdown 的 `data-streamdown="table-wrapper"` 属性,改用
|
|
334
|
+
* 渲染器自己声明的 `.blade-chat-table-wrapper`——原来的 selector 换渲染器之后
|
|
335
|
+
* 一直没匹配上,宽表格会直接撑破窄容器而不是自己滚,这里补回来。 */
|
|
336
|
+
.blade-chat-markdown .blade-chat-table-wrapper {
|
|
337
|
+
max-width: 100%;
|
|
338
|
+
min-width: 0;
|
|
339
|
+
overflow-x: auto;
|
|
340
|
+
}
|
|
267
341
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
.blade-chat-ask-card input {
|
|
273
|
-
font-size: 1rem;
|
|
342
|
+
.blade-chat-markdown img,
|
|
343
|
+
.blade-chat-markdown video {
|
|
344
|
+
max-width: 100%;
|
|
345
|
+
height: auto;
|
|
274
346
|
}
|
|
275
347
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
348
|
+
/* 长 URL 和长内联代码是撑宽的另外两个常见肇事者。用 anywhere 而不是 break-word:
|
|
349
|
+
* 只有 anywhere 参与 min-content 计算,break-word 挡不住 flex item 被顶宽。 */
|
|
350
|
+
.blade-chat-markdown :not(pre) > code,
|
|
351
|
+
.blade-chat-markdown a {
|
|
352
|
+
overflow-wrap: anywhere;
|
|
279
353
|
}
|
|
280
|
-
}
|
|
281
354
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
355
|
+
/* 未闭合的加粗/斜体/删除线/行内代码,在闭合符真正到达前先按最终标签
|
|
356
|
+
* 渲染、只用透明度标出"待确认"——内容和标签结构全程不变,闭合符到达后
|
|
357
|
+
* 这条规则自然不再匹配,恢复完全不透明,DOM 节点没有被替换过。 */
|
|
358
|
+
.blade-chat-markdown [data-markdown-pending="true"] {
|
|
359
|
+
opacity: 0.6;
|
|
360
|
+
}
|
|
286
361
|
|
|
287
|
-
|
|
362
|
+
.blade-chat-prose p {
|
|
363
|
+
margin: 0.5em 0;
|
|
364
|
+
}
|
|
288
365
|
|
|
289
|
-
.blade-chat-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
gap: 0.5rem;
|
|
295
|
-
vertical-align: middle;
|
|
296
|
-
}
|
|
366
|
+
.blade-chat-prose > p:first-child,
|
|
367
|
+
.blade-chat-prose > ul:first-child,
|
|
368
|
+
.blade-chat-prose > ol:first-child {
|
|
369
|
+
margin-top: 0;
|
|
370
|
+
}
|
|
297
371
|
|
|
298
|
-
.blade-chat-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
cursor: pointer;
|
|
304
|
-
border: 1px solid hsl(var(--border));
|
|
305
|
-
border-radius: 0.375rem;
|
|
306
|
-
background: hsl(var(--card));
|
|
307
|
-
color: hsl(var(--card-foreground));
|
|
308
|
-
padding: 0.375rem 0.625rem;
|
|
309
|
-
font-size: 0.75rem;
|
|
310
|
-
font-weight: 500;
|
|
311
|
-
line-height: 1.25rem;
|
|
312
|
-
text-align: left;
|
|
313
|
-
}
|
|
372
|
+
.blade-chat-prose > p:last-child,
|
|
373
|
+
.blade-chat-prose > ul:last-child,
|
|
374
|
+
.blade-chat-prose > ol:last-child {
|
|
375
|
+
margin-bottom: 0;
|
|
376
|
+
}
|
|
314
377
|
|
|
315
|
-
.blade-chat-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
378
|
+
.blade-chat-prose ul,
|
|
379
|
+
.blade-chat-prose ol {
|
|
380
|
+
margin: 0.5em 0;
|
|
381
|
+
padding-left: 1.4em;
|
|
382
|
+
}
|
|
319
383
|
|
|
320
|
-
.blade-chat-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
}
|
|
384
|
+
.blade-chat-prose li {
|
|
385
|
+
margin: 0.25em 0;
|
|
386
|
+
}
|
|
324
387
|
|
|
325
|
-
.blade-chat-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
}
|
|
388
|
+
.blade-chat-prose h1 {
|
|
389
|
+
font-size: 1.25em;
|
|
390
|
+
font-weight: 600;
|
|
391
|
+
margin: 1em 0 0.5em;
|
|
392
|
+
}
|
|
330
393
|
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
max-width: 15rem;
|
|
337
|
-
max-width: min(15rem, 60cqi);
|
|
338
|
-
}
|
|
394
|
+
.blade-chat-prose h2 {
|
|
395
|
+
font-size: 1.15em;
|
|
396
|
+
font-weight: 600;
|
|
397
|
+
margin: 1em 0 0.5em;
|
|
398
|
+
}
|
|
339
399
|
|
|
340
|
-
.blade-chat-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
400
|
+
.blade-chat-prose h3,
|
|
401
|
+
.blade-chat-prose h4 {
|
|
402
|
+
font-size: 1.05em;
|
|
403
|
+
font-weight: 600;
|
|
404
|
+
margin: 0.9em 0 0.4em;
|
|
405
|
+
}
|
|
344
406
|
|
|
345
|
-
.blade-chat-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
407
|
+
.blade-chat-prose blockquote {
|
|
408
|
+
border-left: 3px solid hsl(var(--border));
|
|
409
|
+
margin: 0.5em 0;
|
|
410
|
+
padding-left: 0.9em;
|
|
411
|
+
color: hsl(var(--muted-foreground));
|
|
412
|
+
}
|
|
349
413
|
|
|
350
|
-
|
|
414
|
+
.blade-chat-prose a {
|
|
415
|
+
color: hsl(var(--primary));
|
|
416
|
+
text-decoration: underline;
|
|
417
|
+
}
|
|
351
418
|
|
|
352
|
-
.blade-chat-
|
|
353
|
-
.
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
419
|
+
.blade-chat-prose code {
|
|
420
|
+
background: hsl(var(--muted) / 0.6);
|
|
421
|
+
border-radius: 0.25rem;
|
|
422
|
+
padding: 0.1em 0.35em;
|
|
423
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
424
|
+
font-size: 0.9em;
|
|
425
|
+
}
|
|
358
426
|
|
|
359
|
-
.blade-chat-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
padding: 0.5rem;
|
|
365
|
-
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
366
|
-
font-size: 11px;
|
|
367
|
-
color: hsl(var(--foreground));
|
|
368
|
-
}
|
|
427
|
+
.blade-chat-prose table {
|
|
428
|
+
border-collapse: collapse;
|
|
429
|
+
margin: 0.75em 0;
|
|
430
|
+
width: 100%;
|
|
431
|
+
}
|
|
369
432
|
|
|
370
|
-
|
|
433
|
+
.blade-chat-prose th,
|
|
434
|
+
.blade-chat-prose td {
|
|
435
|
+
border: 1px solid hsl(var(--border));
|
|
436
|
+
padding: 0.4em 0.7em;
|
|
437
|
+
text-align: left;
|
|
438
|
+
}
|
|
371
439
|
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
440
|
+
/* 代码块正文(<pre>)的排版:外层 codeblock 外壳与滚动由组件上的类给,
|
|
441
|
+
* 这里只补等宽字体和底色。 */
|
|
442
|
+
.blade-chat-codeblock-body {
|
|
443
|
+
background: hsl(var(--muted) / 0.25);
|
|
444
|
+
padding: 0.875rem 1rem;
|
|
445
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
446
|
+
font-size: 13.5px;
|
|
447
|
+
line-height: 1.7;
|
|
448
|
+
}
|
|
376
449
|
|
|
377
|
-
/*
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
}
|
|
450
|
+
/* 代码块里的内联 code 不再套一层底色和留白。 */
|
|
451
|
+
.blade-chat-codeblock-body code {
|
|
452
|
+
background: transparent;
|
|
453
|
+
padding: 0;
|
|
454
|
+
}
|
|
383
455
|
|
|
384
|
-
/*
|
|
385
|
-
|
|
386
|
-
.blade-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
456
|
+
/* ---------------------------------------------------------------- 动效 */
|
|
457
|
+
|
|
458
|
+
.blade-shimmer-text {
|
|
459
|
+
background: linear-gradient(
|
|
460
|
+
90deg,
|
|
461
|
+
hsl(var(--muted-foreground)) 0%,
|
|
462
|
+
hsl(var(--foreground)) 50%,
|
|
463
|
+
hsl(var(--muted-foreground)) 100%
|
|
464
|
+
);
|
|
465
|
+
background-size: 200% 100%;
|
|
466
|
+
-webkit-background-clip: text;
|
|
467
|
+
background-clip: text;
|
|
468
|
+
-webkit-text-fill-color: transparent;
|
|
469
|
+
color: transparent;
|
|
470
|
+
animation: blade-shimmer 2s linear infinite;
|
|
471
|
+
}
|
|
390
472
|
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
473
|
+
@keyframes blade-shimmer {
|
|
474
|
+
from {
|
|
475
|
+
background-position: 200% 0;
|
|
476
|
+
}
|
|
477
|
+
to {
|
|
478
|
+
background-position: -200% 0;
|
|
479
|
+
}
|
|
480
|
+
}
|
|
395
481
|
}
|
|
396
482
|
|
|
397
|
-
/*
|
|
398
|
-
* 只有 anywhere 参与 min-content 计算,break-word 挡不住 flex item 被顶宽。 */
|
|
399
|
-
.blade-chat-markdown :not(pre) > code,
|
|
400
|
-
.blade-chat-markdown a {
|
|
401
|
-
overflow-wrap: anywhere;
|
|
402
|
-
}
|
|
483
|
+
/* ------------------------------------------------------------ 消息导航轨 */
|
|
403
484
|
|
|
404
|
-
|
|
405
|
-
|
|
485
|
+
/* 右侧的发言刻度轨。定位绝对:悬停才展开的目录不能占布局宽度,否则同一行的
|
|
486
|
+
* 内容会被挤窄,而不悬停时那块空间永远是空的。 */
|
|
487
|
+
.blade-turn-nav {
|
|
488
|
+
position: absolute;
|
|
489
|
+
right: 0.5rem;
|
|
490
|
+
top: 50%;
|
|
491
|
+
transform: translateY(-50%);
|
|
492
|
+
z-index: 30;
|
|
406
493
|
}
|
|
407
494
|
|
|
408
|
-
.blade-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
495
|
+
.blade-turn-nav-markers {
|
|
496
|
+
display: flex;
|
|
497
|
+
flex-direction: column;
|
|
498
|
+
align-items: flex-end;
|
|
499
|
+
max-height: 20rem;
|
|
500
|
+
/* 条数超过可视高度时要能滚:固定 hidden 会让后面的刻度永远点不到。
|
|
501
|
+
滚动条本身藏掉,它只是给长会话兜底。 */
|
|
502
|
+
overflow-y: auto;
|
|
503
|
+
scrollbar-width: none;
|
|
504
|
+
padding: 0.375rem 0.375rem 0.375rem 0;
|
|
505
|
+
-webkit-mask-image: linear-gradient(
|
|
506
|
+
to bottom,
|
|
507
|
+
transparent,
|
|
508
|
+
black 10%,
|
|
509
|
+
black 90%,
|
|
510
|
+
transparent
|
|
511
|
+
);
|
|
512
|
+
mask-image: linear-gradient(to bottom, transparent, black 10%, black 90%, transparent);
|
|
412
513
|
}
|
|
413
514
|
|
|
414
|
-
.blade-
|
|
415
|
-
|
|
416
|
-
.blade-chat-prose > ol:last-child {
|
|
417
|
-
margin-bottom: 0;
|
|
515
|
+
.blade-turn-nav-markers::-webkit-scrollbar {
|
|
516
|
+
display: none;
|
|
418
517
|
}
|
|
419
518
|
|
|
420
|
-
.blade-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
519
|
+
.blade-turn-nav-spacer-top {
|
|
520
|
+
margin-top: auto;
|
|
521
|
+
}
|
|
522
|
+
.blade-turn-nav-spacer-bottom {
|
|
523
|
+
margin-bottom: auto;
|
|
424
524
|
}
|
|
425
525
|
|
|
426
|
-
.blade-
|
|
427
|
-
|
|
526
|
+
.blade-turn-nav-tick {
|
|
527
|
+
display: flex;
|
|
528
|
+
align-items: center;
|
|
529
|
+
height: 0.875rem;
|
|
530
|
+
flex-shrink: 0;
|
|
531
|
+
padding: 0;
|
|
532
|
+
border: 0;
|
|
533
|
+
background: none;
|
|
534
|
+
cursor: pointer;
|
|
428
535
|
}
|
|
429
536
|
|
|
430
|
-
.blade-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
537
|
+
.blade-turn-nav-tick > span {
|
|
538
|
+
display: block;
|
|
539
|
+
width: 0.75rem;
|
|
540
|
+
height: 0.125rem;
|
|
541
|
+
border-radius: 9999px;
|
|
542
|
+
background: hsl(var(--muted-foreground) / 0.35);
|
|
543
|
+
transition: width 0.15s ease, height 0.15s ease, background-color 0.15s ease;
|
|
434
544
|
}
|
|
435
545
|
|
|
436
|
-
.blade-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
546
|
+
.blade-turn-nav-tick[data-hovered="true"] > span {
|
|
547
|
+
width: 1.25rem;
|
|
548
|
+
height: 0.25rem;
|
|
549
|
+
background: hsl(var(--muted-foreground) / 0.7);
|
|
440
550
|
}
|
|
441
551
|
|
|
442
|
-
.blade-
|
|
443
|
-
.
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
margin: 0.9em 0 0.4em;
|
|
552
|
+
.blade-turn-nav-tick[data-active="true"] > span {
|
|
553
|
+
width: 1.25rem;
|
|
554
|
+
height: 0.25rem;
|
|
555
|
+
background: hsl(var(--foreground));
|
|
447
556
|
}
|
|
448
557
|
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
558
|
+
/* 定位的进度与失败提示:贴在刻度轨左侧,不随面板开合。 */
|
|
559
|
+
.blade-turn-nav-status {
|
|
560
|
+
position: absolute;
|
|
561
|
+
right: 100%;
|
|
562
|
+
top: 50%;
|
|
563
|
+
transform: translateY(-50%);
|
|
564
|
+
display: flex;
|
|
565
|
+
align-items: center;
|
|
566
|
+
gap: 0.5rem;
|
|
567
|
+
margin-right: 0.5rem;
|
|
568
|
+
padding: 0.25rem 0.625rem;
|
|
569
|
+
border: 1px solid hsl(var(--border));
|
|
570
|
+
border-radius: 9999px;
|
|
571
|
+
background: hsl(var(--popover));
|
|
572
|
+
color: hsl(var(--popover-foreground));
|
|
573
|
+
font-size: 0.75rem;
|
|
574
|
+
white-space: nowrap;
|
|
575
|
+
box-shadow: 0 4px 14px hsl(var(--foreground) / 0.12);
|
|
454
576
|
}
|
|
455
577
|
|
|
456
|
-
.blade-
|
|
578
|
+
.blade-turn-nav-status button {
|
|
579
|
+
border: 0;
|
|
580
|
+
background: none;
|
|
581
|
+
padding: 0;
|
|
457
582
|
color: hsl(var(--primary));
|
|
583
|
+
font-size: 0.75rem;
|
|
584
|
+
cursor: pointer;
|
|
458
585
|
text-decoration: underline;
|
|
459
586
|
}
|
|
460
587
|
|
|
461
|
-
.blade-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
.blade-chat-prose table {
|
|
470
|
-
border-collapse: collapse;
|
|
471
|
-
margin: 0.75em 0;
|
|
472
|
-
width: 100%;
|
|
588
|
+
.blade-turn-nav-panel {
|
|
589
|
+
position: absolute;
|
|
590
|
+
right: 100%;
|
|
591
|
+
/* 与刻度轨同心:顶对齐会让一个接近上限高度的面板整条往下长,聊天区是 overflow: hidden,
|
|
592
|
+
视口矮一点下面的条目就被裁掉、连滚都滚不到(滚动容器以为自己有完整高度)。 */
|
|
593
|
+
top: 50%;
|
|
594
|
+
transform: translateY(-50%);
|
|
595
|
+
padding-right: 0.5rem;
|
|
473
596
|
}
|
|
474
597
|
|
|
475
|
-
.blade-
|
|
476
|
-
|
|
598
|
+
.blade-turn-nav-list {
|
|
599
|
+
display: flex;
|
|
600
|
+
flex-direction: column;
|
|
601
|
+
width: 20rem;
|
|
602
|
+
/* 高度上限同时受视口约束,短视口里面板整体缩进去而不是被裁掉。 */
|
|
603
|
+
max-height: min(28rem, 60vh);
|
|
604
|
+
overflow-y: auto;
|
|
605
|
+
padding: 0.25rem 0;
|
|
477
606
|
border: 1px solid hsl(var(--border));
|
|
478
|
-
|
|
479
|
-
|
|
607
|
+
border-radius: 0.5rem;
|
|
608
|
+
background: hsl(var(--popover));
|
|
609
|
+
box-shadow: 0 10px 30px hsl(var(--foreground) / 0.18);
|
|
480
610
|
}
|
|
481
611
|
|
|
482
|
-
.blade-
|
|
483
|
-
|
|
612
|
+
.blade-turn-nav-item {
|
|
613
|
+
flex-shrink: 0;
|
|
614
|
+
padding: 0.375rem 0.75rem;
|
|
615
|
+
border: 0;
|
|
616
|
+
background: none;
|
|
617
|
+
text-align: left;
|
|
618
|
+
font-size: 0.75rem;
|
|
619
|
+
line-height: 1.25rem;
|
|
620
|
+
color: hsl(var(--popover-foreground));
|
|
621
|
+
white-space: nowrap;
|
|
484
622
|
overflow: hidden;
|
|
485
|
-
|
|
486
|
-
border-radius: 0.75rem;
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
.blade-chat-codeblock-header {
|
|
490
|
-
display: flex;
|
|
491
|
-
align-items: center;
|
|
492
|
-
justify-content: space-between;
|
|
493
|
-
height: 34px;
|
|
494
|
-
border-bottom: 1px solid hsl(var(--border));
|
|
495
|
-
background: hsl(var(--muted) / 0.5);
|
|
496
|
-
padding: 0 0.375rem 0 0.875rem;
|
|
497
|
-
color: hsl(var(--muted-foreground));
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
.blade-chat-codeblock-header button {
|
|
623
|
+
text-overflow: ellipsis;
|
|
501
624
|
cursor: pointer;
|
|
502
|
-
border: 0;
|
|
503
|
-
background: transparent;
|
|
504
|
-
display: inline-flex;
|
|
505
|
-
align-items: center;
|
|
506
|
-
gap: 0.25rem;
|
|
507
|
-
color: inherit;
|
|
508
625
|
}
|
|
509
626
|
|
|
510
|
-
.blade-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
background: hsl(var(--muted) / 0.25);
|
|
514
|
-
padding: 0.875rem 1rem;
|
|
515
|
-
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
516
|
-
font-size: 13.5px;
|
|
517
|
-
line-height: 1.7;
|
|
627
|
+
.blade-turn-nav-item[data-hovered="true"],
|
|
628
|
+
.blade-turn-nav-item[data-active="true"] {
|
|
629
|
+
background: hsl(var(--accent));
|
|
518
630
|
}
|
|
519
631
|
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
632
|
+
/* 定位到某条发言后的短暂高亮。加到消息行本身(data-entry-id 那一层),
|
|
633
|
+
* 到点由 hook 摘掉类名,不改变滚动位置。内置 Web 的 app.css 有同名镜像。 */
|
|
634
|
+
.blade-turn-nav-flash {
|
|
635
|
+
animation: blade-turn-nav-flash 1.6s ease-out both;
|
|
636
|
+
border-radius: 0.5rem;
|
|
523
637
|
}
|
|
524
638
|
|
|
525
|
-
/*
|
|
526
|
-
|
|
527
|
-
.blade-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
hsl(var(--foreground)) 50%,
|
|
532
|
-
hsl(var(--muted-foreground)) 100%
|
|
533
|
-
);
|
|
534
|
-
background-size: 200% 100%;
|
|
535
|
-
-webkit-background-clip: text;
|
|
536
|
-
background-clip: text;
|
|
537
|
-
-webkit-text-fill-color: transparent;
|
|
538
|
-
color: transparent;
|
|
539
|
-
animation: blade-shimmer 2s linear infinite;
|
|
639
|
+
/* 减少动效:保留高亮但不动画,用户仍然看得见"定位到哪一条"。 */
|
|
640
|
+
@media (prefers-reduced-motion: reduce) {
|
|
641
|
+
.blade-turn-nav-flash {
|
|
642
|
+
animation: none;
|
|
643
|
+
background-color: hsl(var(--accent) / 0.75);
|
|
644
|
+
}
|
|
540
645
|
}
|
|
541
646
|
|
|
542
|
-
@keyframes blade-
|
|
647
|
+
@keyframes blade-turn-nav-flash {
|
|
543
648
|
from {
|
|
544
|
-
background-
|
|
649
|
+
background-color: hsl(var(--accent) / 0.75);
|
|
545
650
|
}
|
|
546
651
|
to {
|
|
547
|
-
background-
|
|
652
|
+
background-color: transparent;
|
|
548
653
|
}
|
|
549
654
|
}
|