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