diff --git a/client/src/dom.ts b/client/src/dom.ts index 609c38a..e380c80 100644 --- a/client/src/dom.ts +++ b/client/src/dom.ts @@ -374,11 +374,24 @@ export function createChatWindow(config: ResolvedConfig): { const inputEl = document.createElement('t-chat-sender'); inputEl.id = 'csk-input'; inputEl.setAttribute('placeholder', t('placeholder')); + // 压缩输入框:autosize 为 Object 复杂类型,走 property 赋值(同 dom.ts createChatItemMsg 的 content 处理) + (inputEl as unknown as { autosize: { minRows: number } }).autosize = { minRows: 1 }; inputArea.appendChild(inputEl); - // === 保密声明脚注 === + // === 保密声明脚注(默认折叠为单行,点击展开完整条文) === const disclaimer = document.createElement('div'); disclaimer.className = 'csk-disclaimer'; + disclaimer.setAttribute('role', 'button'); + disclaimer.setAttribute('tabindex', '0'); + disclaimer.setAttribute('aria-expanded', 'false'); + const toggleDisclaimer = () => { + const expanded = disclaimer.classList.toggle('csk-disclaimer--expanded'); + disclaimer.setAttribute('aria-expanded', String(expanded)); + }; + disclaimer.addEventListener('click', toggleDisclaimer); + disclaimer.addEventListener('keydown', (e) => { + if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); toggleDisclaimer(); } + }); if (config.disclaimer !== undefined) { // 用户自定义或传空串隐藏。 // 注意:disclaimer 语义为「受信 HTML」(由宿主开发者或后端管理员配置), diff --git a/client/src/styles.ts b/client/src/styles.ts index 7100a44..1f37456 100644 --- a/client/src/styles.ts +++ b/client/src/styles.ts @@ -51,6 +51,9 @@ function cssVars(config: ResolvedConfig): string { --td-brand-color-light-hover: ${lighter}; /* 覆盖 TDesign chat-item 默认 800px 限制,使 AI 回复内容自适应 SDK 弹窗宽度 */ --td-chat-item-content-max-width: 100%; + /* 压缩输入组件:缩小内容区上下 padding 与字号(变量穿透 shadow DOM 生效于 t-chat-sender) */ + --td-chat-input-padding: 8px 12px; + --td-chat-input-font-size: 14px; `; } @@ -354,21 +357,14 @@ function getStyles(config: ResolvedConfig): string { } /* 消息气泡 */ +/* 注意:.csk-msg 为块级纵向容器。头像 + 气泡的横向对齐由 t-chat-item 内部(placement 属性)完成, + sources / suggestions 直接 append 到 wrapper 末尾,须纵向堆叠在气泡下方,不能用 flex row 排布 */ .csk-msg { - display: flex; margin-bottom: 16px; max-width: 100%; word-break: break-word; animation: csk-msg-in 0.28s cubic-bezier(0.22, 1, 0.36, 1); } -.csk-msg--user { - flex-direction: row-reverse; - align-items: flex-end; -} -.csk-msg--ai { - flex-direction: row; - align-items: flex-start; -} @keyframes csk-msg-in { from { opacity: 0; transform: translateY(8px); } @@ -381,7 +377,7 @@ function getStyles(config: ResolvedConfig): string { /* ========== 输入区 ========== */ .csk-input-area { - padding: 10px 12px 14px; + padding: 8px 12px 10px; background: #fff; border-top: 1px solid var(--csk-border); flex-shrink: 0; @@ -389,18 +385,24 @@ function getStyles(config: ResolvedConfig): string { /* ========== 保密声明脚注 ========== */ .csk-disclaimer { - margin-top: 8px; - padding: 6px 8px 4px; + margin-top: 4px; + padding: 4px 8px 2px; font-size: 10px; color: #9CA3AF; - line-height: 1.5; + line-height: 1.4; user-select: none; + cursor: pointer; } .csk-disclaimer__title { font-weight: 600; margin-bottom: 2px; color: #9CA3AF; } +/* 折叠态:默认只显示首行(标题),其余条文隐藏;标题末尾加 ▾ 提示可展开 */ +.csk-disclaimer > :not(:first-child) { display: none; } +.csk-disclaimer > :first-child::after { content: ' ▾'; } +.csk-disclaimer--expanded > :not(:first-child) { display: block; } +.csk-disclaimer--expanded > :first-child::after { content: ' ▴'; } .csk-dark .csk-disclaimer { color: #6B7280; } .csk-dark .csk-disclaimer__title { color: #6B7280; }