Skip to content

Commit fa70659

Browse files
committed
fix(sender): normalize action tooltip gap and rendering
1 parent 6a8bf29 commit fa70659

7 files changed

Lines changed: 115 additions & 22 deletions

File tree

docs/demos/sender/actions-config-basic.vue

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,3 @@ const handleSubmit = (text: string) => {
4949
color: #606266;
5050
}
5151
</style>
52-
53-
<style>
54-
.tr-submit-button-tooltip-popper,
55-
.tr-action-button-tooltip-popper {
56-
top: -10px !important;
57-
}
58-
</style>

docs/src/components/sender.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -724,11 +724,16 @@ Sender 组件提供了丰富的 CSS 变量用于自定义样式。
724724
| -------------------------------- | ------------ |
725725
| `--tr-sender-button-size` | 按钮尺寸 |
726726
| `--tr-sender-button-size-submit` | 提交按钮尺寸 |
727+
| `--tr-sender-tooltip-gap` | 按钮 Tooltip 与触发按钮的间距 |
727728

728729
:::tip 尺寸变体
729730
所有变量都支持通过 `size` 属性自动切换。当 `size="small"` 时,组件会使用对应的 `-small` 变体(如 `--tr-sender-font-size-small`)。
730731
:::
731732

733+
:::tip Tooltip 间距
734+
Sender 按钮的 Tooltip 间距可通过 `--tr-sender-tooltip-gap` 全局自定义,默认值为 `8px`。由于 Tooltip 弹层通常挂载在全局层级,建议在 `:root` 或全局主题作用域下设置该变量。
735+
:::
736+
732737
:::tip 使用示例
733738
```css
734739
/* 自定义背景色 */
@@ -742,6 +747,11 @@ Sender 组件提供了丰富的 CSS 变量用于自定义样式。
742747
--tr-sender-button-size: 40px;
743748
--tr-sender-button-size-submit: 44px;
744749
}
750+
751+
/* 全局调整 Sender 按钮 Tooltip 间距 */
752+
:root {
753+
--tr-sender-tooltip-gap: 10px;
754+
}
745755
```
746756
:::
747757

@@ -789,4 +799,4 @@ Sender 组件提供了丰富的 CSS 变量用于自定义样式。
789799
|-------|----------|
790800
| startSpeech | 使用 `VoiceButton.start()` |
791801
| stopSpeech | 使用 `VoiceButton.stop()` |
792-
| activateTemplateFirstField | 自动处理,无需调用 |
802+
| activateTemplateFirstField | 自动处理,无需调用 |

packages/components/src/sender-actions/action-button/index.vue

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,3 +86,11 @@ const sizeStyle = computed(() => {
8686
}
8787
}
8888
</style>
89+
90+
<style lang="less">
91+
@import '../styles/tooltip.less';
92+
93+
.tiny-tooltip.tiny-tooltip__popper.tr-action-button-tooltip-popper {
94+
.tr-sender-tooltip-light-popper-mixin();
95+
}
96+
</style>

packages/components/src/sender-actions/clear-button/index.vue

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { computed } from 'vue'
33
import { useSenderContext } from '../../sender/context'
44
import { IconClear } from '@opentiny/tiny-robot-svgs'
55
import ActionButton from '../action-button/index.vue'
6-
import { normalizeTooltipContent } from '../utils/tooltip'
76
87
// 从 Context 读取状态和配置
98
const { hasContent, clearable, clear, loading, defaultActions } = useSenderContext()
@@ -18,7 +17,7 @@ const isDisabled = computed(() => {
1817
return false
1918
})
2019
21-
const tooltipRenderFn = computed(() => normalizeTooltipContent(defaultActions.value?.clear?.tooltip))
20+
const tooltip = computed(() => defaultActions.value?.clear?.tooltip)
2221
2322
const tooltipPlacement = computed(() => defaultActions.value?.clear?.tooltipPlacement ?? 'top')
2423
@@ -46,7 +45,7 @@ const handleClick = () => {
4645
v-if="show"
4746
:icon="IconClear"
4847
:disabled="isDisabled"
49-
:tooltip="tooltipRenderFn"
48+
:tooltip="tooltip"
5049
:tooltip-placement="tooltipPlacement"
5150
@click="handleClick"
5251
/>
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
.tr-sender-tooltip-gap-mixin() {
2+
&[data-popper-placement^='top'],
3+
&[x-placement^='top'],
4+
&[data-placement^='top'] {
5+
padding-bottom: var(--tr-sender-tooltip-gap, 8px);
6+
}
7+
8+
&[data-popper-placement^='bottom'],
9+
&[x-placement^='bottom'],
10+
&[data-placement^='bottom'] {
11+
padding-top: var(--tr-sender-tooltip-gap, 8px);
12+
}
13+
14+
&[data-popper-placement^='left'],
15+
&[x-placement^='left'],
16+
&[data-placement^='left'] {
17+
padding-right: var(--tr-sender-tooltip-gap, 8px);
18+
}
19+
20+
&[data-popper-placement^='right'],
21+
&[x-placement^='right'],
22+
&[data-placement^='right'] {
23+
padding-left: var(--tr-sender-tooltip-gap, 8px);
24+
}
25+
}
26+
27+
.tr-sender-tooltip-shell-mixin() {
28+
padding: 0;
29+
background: transparent;
30+
border-radius: 0;
31+
box-shadow: none;
32+
}
33+
34+
.tr-sender-tooltip-inner-base-mixin() {
35+
display: block;
36+
min-width: 10px;
37+
max-width: 450px;
38+
word-wrap: break-word;
39+
white-space: pre-wrap;
40+
}
41+
42+
.tr-sender-tooltip-light-inner-mixin() {
43+
.tr-sender-tooltip-inner {
44+
.tr-sender-tooltip-inner-base-mixin();
45+
padding: var(--tv-Tooltip-padding-y) var(--tv-Tooltip-padding-x);
46+
color: var(--tv-Tooltip-popper-light-text-color);
47+
font-size: var(--tv-Tooltip-popper-font-size);
48+
line-height: var(--tv-Tooltip-popper-font-line-height);
49+
background: var(--tv-Tooltip-popper-light-bg-color);
50+
border-radius: var(--tv-Tooltip-popper-border-radius);
51+
box-shadow: var(--tv-Tooltip-box-shadow);
52+
}
53+
}
54+
55+
.tr-sender-tooltip-light-popper-mixin() {
56+
.tr-sender-tooltip-shell-mixin();
57+
.tr-sender-tooltip-gap-mixin();
58+
.tr-sender-tooltip-light-inner-mixin();
59+
}

packages/components/src/sender-actions/submit-button/index.vue

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -148,15 +148,10 @@ const handleClick = () => {
148148
</style>
149149

150150
<style lang="less">
151+
@import '../styles/tooltip.less';
152+
151153
/* 全局样式:自定义 TinyTooltip 样式 */
152-
.tr-submit-button-tooltip-popper {
153-
.tiny-tooltip__popper {
154-
padding: 6px 12px;
155-
background-color: rgba(0, 0, 0, 0.85);
156-
color: white;
157-
border-radius: 4px;
158-
font-size: 12px;
159-
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
160-
}
154+
.tiny-tooltip.tiny-tooltip__popper.tr-submit-button-tooltip-popper {
155+
.tr-sender-tooltip-light-popper-mixin();
161156
}
162157
</style>
Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,43 @@
1+
import { h, isVNode, type VNode } from 'vue'
12
import type { TooltipContent } from '../types/tooltip'
23

4+
const TOOLTIP_INNER_CLASS = 'tr-sender-tooltip-inner'
5+
6+
function hasTooltipInnerClass(value: unknown): boolean {
7+
if (!value) return false
8+
9+
if (typeof value === 'string') {
10+
return value.split(/\s+/).includes(TOOLTIP_INNER_CLASS)
11+
}
12+
13+
if (Array.isArray(value)) {
14+
return value.some(hasTooltipInnerClass)
15+
}
16+
17+
if (typeof value === 'object') {
18+
return Boolean((value as Record<string, unknown>)[TOOLTIP_INNER_CLASS])
19+
}
20+
21+
return false
22+
}
23+
24+
function renderTooltipInner(content: string | VNode) {
25+
if (isVNode(content) && hasTooltipInnerClass(content.props?.class)) {
26+
return content
27+
}
28+
29+
return h('div', { class: TOOLTIP_INNER_CLASS }, content)
30+
}
31+
332
/**
433
* 将 TooltipContent 转换为 TinyTooltip 的 render-content 函数
534
*/
635
export function normalizeTooltipContent(tooltip: TooltipContent | undefined) {
736
if (!tooltip) return undefined
837

938
if (typeof tooltip === 'string') {
10-
return () => tooltip
39+
return () => renderTooltipInner(tooltip)
1140
}
1241

13-
return tooltip
42+
return () => renderTooltipInner(tooltip())
1443
}

0 commit comments

Comments
 (0)