diff --git a/lib/client.js b/lib/client.js index 4d9e9c1..b02ee8a 100644 --- a/lib/client.js +++ b/lib/client.js @@ -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( diff --git a/plugin-src/client/i18n.js b/plugin-src/client/i18n.js index 8df5f02..29136b4 100644 --- a/plugin-src/client/i18n.js +++ b/plugin-src/client/i18n.js @@ -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', diff --git a/plugin-src/client/index.js b/plugin-src/client/index.js index 62602f4..d110994 100644 --- a/plugin-src/client/index.js +++ b/plugin-src/client/index.js @@ -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 渠道' }, diff --git a/plugin-src/client/styles.js b/plugin-src/client/styles.js index 7a2db4f..9271b1a 100644 --- a/plugin-src/client/styles.js +++ b/plugin-src/client/styles.js @@ -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) { diff --git a/test/client-ui.test.mjs b/test/client-ui.test.mjs index 614218d..cb8d0ec 100644 --- a/test/client-ui.test.mjs +++ b/test/client-ui.test.mjs @@ -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微信飞书WeChat<|>Feishu<|>DingTalk<|>WeComQQ<[^]*>Slack<[^]*>Telegram<[^]*>Discord<[^]*>WhatsApp