feat: add GitHub help tooltip

This commit is contained in:
xmanrui 2026-08-17 17:09:59 +08:00
parent ba2e27217c
commit b0fee08852
5 changed files with 53 additions and 19 deletions

View file

@ -367,6 +367,7 @@ var EN = Object.freeze({
"IM\u673A\u5668\u4EBA\u8BBE\u7F6E": "IM bot settings",
"IM \u6E20\u9053": "IM channels",
"\u8BA9\u804A\u5929\u673A\u5668\u4EBA\u8F7B\u677E\u63A5\u5165 DeepSeek Harness": "Connect chatbots to DeepSeek Harness with ease",
"\u5E2E\u52A9\u4E0E\u53CD\u9988 \xB7 \u524D\u5F80 GitHub": "Help & feedback \xB7 Open GitHub",
"\u5FAE\u4FE1": "WeChat",
"\u98DE\u4E66": "Feishu",
"\u9489\u9489": "DingTalk",
@ -7234,10 +7235,13 @@ var CSS10 = String.raw`
.dim-page *, .dim-page *::before, .dim-page *::after { box-sizing: border-box; }
.dim-title { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin: 0 0 26px; }
.dim-title p { margin: 0; color: var(--dsw-alias-label-primary, #1f2329); font-size: 14px; line-height: 20px; font-weight: 700; white-space: nowrap; }
.dim-githubAction { position: relative; display: inline-flex; flex: none; }
.dim-githubLink { min-height: 30px; display: inline-flex; align-items: center; gap: 5px; flex: none; padding: 0 10px; border: 1px solid var(--dsw-alias-border-l2, #dfe1e5); border-radius: 8px; color: var(--dsw-alias-label-secondary, #646a73); background: var(--dsw-alias-bg-layer-1, #fff); font-size: 12px; line-height: normal; font-weight: 560; text-decoration: none; transition: border-color .15s ease, color .15s ease, background .15s ease; }
.dim-githubLink:hover { border-color: #aeb3bb; color: var(--dsw-alias-label-primary, #1f2329); background: var(--dsw-alias-interactive-bg-hover, #f7f8fa); }
.dim-githubLink:focus-visible { outline: 2px solid color-mix(in srgb, var(--dim-blue) 70%, white); outline-offset: 2px; }
.dim-githubArrow { font-size: 13px; line-height: 1; }
.dim-githubTooltip { position: absolute; right: 0; bottom: calc(100% + 8px); z-index: 20; width: max-content; max-width: min(220px, 80vw); padding: 6px 9px; border: 1px solid var(--dsw-alias-border-l2, #dfe1e5); border-radius: 7px; color: var(--dsw-alias-label-primary, #1f2329); background: var(--dsw-alias-bg-layer-3, #fff); box-shadow: 0 8px 24px rgb(31 35 41 / 14%); font-size: 11px; line-height: 16px; font-weight: 500; white-space: nowrap; opacity: 0; visibility: hidden; transform: translateY(3px); pointer-events: none; transition: opacity .15s ease, transform .15s ease, visibility .15s ease; }
.dim-githubAction:hover .dim-githubTooltip, .dim-githubAction:focus-within .dim-githubTooltip { opacity: 1; visibility: visible; transform: translateY(0); }
.dim-layout { display: grid; grid-template-columns: 174px 1px minmax(0, 1fr); gap: 24px; align-items: start; }
.dim-rail { max-height: 520px; display: grid; align-content: start; gap: 8px; overflow-y: auto; padding: 1px 4px 1px 1px; scrollbar-width: thin; scrollbar-color: var(--dsw-alias-border-l2, #dfe1e5) transparent; }
.dim-rail::-webkit-scrollbar { width: 4px; }
@ -7407,6 +7411,7 @@ var CSS10 = String.raw`
@media (max-width: 560px) {
.dim-title { flex-direction: column; gap: 10px; }
.dim-title p { white-space: normal; }
.dim-githubTooltip { right: auto; left: 0; }
.dim-rail { grid-template-columns: minmax(0, 1fr); }
}
@media (prefers-reduced-motion: reduce) {
@ -7519,6 +7524,7 @@ function IMSettingsTab({
whatsappRpcCall
}) {
const [selected, setSelected] = React13.useState("weixin");
const githubTooltipId = React13.useId();
const active = CHANNELS.find((channel4) => channel4.id === selected) ?? CHANNELS[0];
return h2(
"section",
@ -7528,16 +7534,26 @@ function IMSettingsTab({
{ className: "dim-title" },
h2("p", null, "\u8BA9\u804A\u5929\u673A\u5668\u4EBA\u8F7B\u677E\u63A5\u5165 DeepSeek Harness"),
h2(
"a",
{
className: "dim-githubLink",
href: "https://github.com/xmanrui/dsh-im",
target: "_blank",
rel: "noopener noreferrer",
"aria-label": "dsh-im GitHub"
},
h2("span", null, "GitHub"),
h2("span", { className: "dim-githubArrow", "aria-hidden": "true" }, "\u2197")
"span",
{ className: "dim-githubAction" },
h2(
"a",
{
className: "dim-githubLink",
href: "https://github.com/xmanrui/dsh-im",
target: "_blank",
rel: "noopener noreferrer",
"aria-label": "dsh-im GitHub",
"aria-describedby": githubTooltipId
},
h2("span", null, "GitHub"),
h2("span", { className: "dim-githubArrow", "aria-hidden": "true" }, "\u2197")
),
h2("span", {
id: githubTooltipId,
className: "dim-githubTooltip",
role: "tooltip"
}, "\u5E2E\u52A9\u4E0E\u53CD\u9988 \xB7 \u524D\u5F80 GitHub")
)
),
h2(

View file

@ -8,6 +8,7 @@ const EN = Object.freeze({
'IM机器人设置': 'IM bot settings',
'IM 渠道': 'IM channels',
'让聊天机器人轻松接入 DeepSeek Harness': 'Connect chatbots to DeepSeek Harness with ease',
'帮助与反馈 · 前往 GitHub': 'Help & feedback · Open GitHub',
'微信': 'WeChat',
'飞书': 'Feishu',
'钉钉': 'DingTalk',

View file

@ -122,19 +122,27 @@ export function IMSettingsTab({
whatsappRpcCall,
}) {
const [selected, setSelected] = React.useState('weixin');
const githubTooltipId = React.useId();
const active = CHANNELS.find((channel) => channel.id === selected) ?? CHANNELS[0];
return h('section', { className: 'dim-page', 'aria-label': 'IM机器人设置' },
h('header', { className: 'dim-title' },
h('p', null, '让聊天机器人轻松接入 DeepSeek Harness'),
h('a', {
className: 'dim-githubLink',
href: 'https://github.com/xmanrui/dsh-im',
target: '_blank',
rel: 'noopener noreferrer',
'aria-label': 'dsh-im GitHub',
},
h('span', null, 'GitHub'),
h('span', { className: 'dim-githubArrow', 'aria-hidden': 'true' }, '↗')),
h('span', { className: 'dim-githubAction' },
h('a', {
className: 'dim-githubLink',
href: 'https://github.com/xmanrui/dsh-im',
target: '_blank',
rel: 'noopener noreferrer',
'aria-label': 'dsh-im GitHub',
'aria-describedby': githubTooltipId,
},
h('span', null, 'GitHub'),
h('span', { className: 'dim-githubArrow', 'aria-hidden': 'true' }, '↗')),
h('span', {
id: githubTooltipId,
className: 'dim-githubTooltip',
role: 'tooltip',
}, '帮助与反馈 · 前往 GitHub')),
),
h('div', { className: 'dim-layout' },
h('nav', { className: 'dim-rail', role: 'tablist', 'aria-label': 'IM 渠道' },

View file

@ -13,10 +13,13 @@ const CSS = String.raw`
.dim-page *, .dim-page *::before, .dim-page *::after { box-sizing: border-box; }
.dim-title { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin: 0 0 26px; }
.dim-title p { margin: 0; color: var(--dsw-alias-label-primary, #1f2329); font-size: 14px; line-height: 20px; font-weight: 700; white-space: nowrap; }
.dim-githubAction { position: relative; display: inline-flex; flex: none; }
.dim-githubLink { min-height: 30px; display: inline-flex; align-items: center; gap: 5px; flex: none; padding: 0 10px; border: 1px solid var(--dsw-alias-border-l2, #dfe1e5); border-radius: 8px; color: var(--dsw-alias-label-secondary, #646a73); background: var(--dsw-alias-bg-layer-1, #fff); font-size: 12px; line-height: normal; font-weight: 560; text-decoration: none; transition: border-color .15s ease, color .15s ease, background .15s ease; }
.dim-githubLink:hover { border-color: #aeb3bb; color: var(--dsw-alias-label-primary, #1f2329); background: var(--dsw-alias-interactive-bg-hover, #f7f8fa); }
.dim-githubLink:focus-visible { outline: 2px solid color-mix(in srgb, var(--dim-blue) 70%, white); outline-offset: 2px; }
.dim-githubArrow { font-size: 13px; line-height: 1; }
.dim-githubTooltip { position: absolute; right: 0; bottom: calc(100% + 8px); z-index: 20; width: max-content; max-width: min(220px, 80vw); padding: 6px 9px; border: 1px solid var(--dsw-alias-border-l2, #dfe1e5); border-radius: 7px; color: var(--dsw-alias-label-primary, #1f2329); background: var(--dsw-alias-bg-layer-3, #fff); box-shadow: 0 8px 24px rgb(31 35 41 / 14%); font-size: 11px; line-height: 16px; font-weight: 500; white-space: nowrap; opacity: 0; visibility: hidden; transform: translateY(3px); pointer-events: none; transition: opacity .15s ease, transform .15s ease, visibility .15s ease; }
.dim-githubAction:hover .dim-githubTooltip, .dim-githubAction:focus-within .dim-githubTooltip { opacity: 1; visibility: visible; transform: translateY(0); }
.dim-layout { display: grid; grid-template-columns: 174px 1px minmax(0, 1fr); gap: 24px; align-items: start; }
.dim-rail { max-height: 520px; display: grid; align-content: start; gap: 8px; overflow-y: auto; padding: 1px 4px 1px 1px; scrollbar-width: thin; scrollbar-color: var(--dsw-alias-border-l2, #dfe1e5) transparent; }
.dim-rail::-webkit-scrollbar { width: 4px; }
@ -186,6 +189,7 @@ const CSS = String.raw`
@media (max-width: 560px) {
.dim-title { flex-direction: column; gap: 10px; }
.dim-title p { white-space: normal; }
.dim-githubTooltip { right: auto; left: 0; }
.dim-rail { grid-template-columns: minmax(0, 1fr); }
}
@media (prefers-reduced-motion: reduce) {

View file

@ -116,8 +116,12 @@ test('IM settings renders nine compact logo channel tabs without enable switches
assert.match(markup, /target="_blank"/);
assert.match(markup, /rel="noopener noreferrer"/);
assert.match(markup, /aria-label="dsh-im GitHub"/);
assert.match(markup, /aria-describedby="[^"]+"/);
assert.match(markup, /role="tooltip"[^>]*>帮助与反馈 · 前往 GitHub</);
assert.match(styles, /\.dim-title p \{[^}]*color: var\(--dsw-alias-label-primary, #1f2329\);[^}]*font-size: 14px;[^}]*font-weight: 700;/);
assert.match(styles, /\.dim-githubLink \{[^}]*border: 1px solid var\(--dsw-alias-border-l2, #dfe1e5\);[^}]*text-decoration: none;/);
assert.match(styles, /\.dim-githubTooltip \{[^}]*bottom: calc\(100% \+ 8px\);[^}]*transform: translateY\(3px\);/);
assert.match(styles, /\.dim-githubAction:hover \.dim-githubTooltip, \.dim-githubAction:focus-within \.dim-githubTooltip \{[^}]*opacity: 1;[^}]*visibility: visible;/);
assert.doesNotMatch(markup, /\d+ 个渠道|dim-channelCount/);
assert.match(markup, />微信</);
assert.match(markup, />飞书</);
@ -596,6 +600,7 @@ test('client registers a live bilingual locale seat for the IM settings tab', ()
registrations[0].options.inject(),
));
assert.match(markup, /Connect chatbots to DeepSeek Harness with ease/);
assert.match(markup, /Help &amp; feedback · Open GitHub/);
assert.match(markup, />WeChat<|>Feishu<|>DingTalk<|>WeCom</);
assert.match(markup, />QQ<[^]*>Slack<[^]*>Telegram<[^]*>Discord<[^]*>WhatsApp</);
assert.doesNotMatch(markup, /[\p{Script=Han}]/u);