mirror of
https://github.com/hansjone/dsh-im-ops.git
synced 2026-10-09 00:33:20 +08:00
fix(ui): move agent preset guidance to tooltip
This commit is contained in:
parent
eadfc7372f
commit
ae49413871
7 changed files with 138 additions and 87 deletions
|
|
@ -326,6 +326,7 @@ var EN = Object.freeze({
|
|||
"\u5DE5\u4F5C\u533A\u8DEF\u5F84\u5FC5\u987B\u6307\u5411\u4E00\u4E2A\u76EE\u5F55\u3002": "The workspace path must point to a directory.",
|
||||
"\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002": "The bot could not be found.",
|
||||
"Agent Preset": "Agent Preset",
|
||||
"\u67E5\u770B Agent Preset \u8BF4\u660E": "View Agent Preset help",
|
||||
"\u8DDF\u968F Host \u9ED8\u8BA4": "Follow the Host default",
|
||||
"\uFF08\u5DF2\u4E0D\u53EF\u7528\uFF09": " (unavailable)",
|
||||
"\u53EA\u5F71\u54CD\u65B0\u5EFA\u4F1A\u8BDD\uFF1B\u82E5\u5F53\u524D\u804A\u5929\u5DF2\u6709\u4F1A\u8BDD\uFF0C\u5148\u53D1\u9001 /new\uFF0C\u518D\u53D1\u9001\u666E\u901A\u6D88\u606F\u751F\u6548\u3002": "This affects only new sessions. If the current chat already has a session, send /new, then send a regular message to apply it.",
|
||||
|
|
@ -904,6 +905,7 @@ function normalizeAgentPresetCatalog(value) {
|
|||
}
|
||||
function AgentPresetEditor({ agentPreset = "", disabled = false, onSave }) {
|
||||
const catalog = React3.useContext(AgentPresetCatalogContext) ?? EMPTY_AGENT_PRESET_CATALOG;
|
||||
const helpId = React3.useId();
|
||||
const current = normalizeAgentPresetId(agentPreset);
|
||||
const [saving, setSaving] = React3.useState(false);
|
||||
const [error, setError] = React3.useState(null);
|
||||
|
|
@ -936,7 +938,26 @@ function AgentPresetEditor({ agentPreset = "", disabled = false, onSave }) {
|
|||
h2(
|
||||
"div",
|
||||
{ className: "dim-presetHeader" },
|
||||
h2("span", null, "Agent Preset"),
|
||||
h2(
|
||||
"span",
|
||||
{ className: "dim-presetTitle" },
|
||||
h2("span", null, "Agent Preset"),
|
||||
h2(
|
||||
"span",
|
||||
{ className: "dim-presetHelp" },
|
||||
h2("button", {
|
||||
type: "button",
|
||||
className: "dim-presetHelpButton",
|
||||
"aria-label": "\u67E5\u770B Agent Preset \u8BF4\u660E",
|
||||
"aria-describedby": helpId
|
||||
}, h2("span", { "aria-hidden": "true" }, "?")),
|
||||
h2("span", {
|
||||
id: helpId,
|
||||
className: "dim-presetTooltip",
|
||||
role: "tooltip"
|
||||
}, "\u53EA\u5F71\u54CD\u65B0\u5EFA\u4F1A\u8BDD\uFF1B\u82E5\u5F53\u524D\u804A\u5929\u5DF2\u6709\u4F1A\u8BDD\uFF0C\u5148\u53D1\u9001 /new\uFF0C\u518D\u53D1\u9001\u666E\u901A\u6D88\u606F\u751F\u6548\u3002")
|
||||
)
|
||||
),
|
||||
saving ? h2("span", { className: "dim-presetStatus" }, "\u4FDD\u5B58\u4E2D\u2026") : null
|
||||
),
|
||||
React3.createElement(
|
||||
|
|
@ -957,11 +978,6 @@ function AgentPresetEditor({ agentPreset = "", disabled = false, onSave }) {
|
|||
item.unavailable ? [item.id, "\uFF08\u5DF2\u4E0D\u53EF\u7528\uFF09"] : item.label && item.label !== item.id ? `${item.label}\uFF08${item.id}\uFF09` : item.id
|
||||
))
|
||||
),
|
||||
h2(
|
||||
"small",
|
||||
{ className: "dim-presetHelp" },
|
||||
"\u53EA\u5F71\u54CD\u65B0\u5EFA\u4F1A\u8BDD\uFF1B\u82E5\u5F53\u524D\u804A\u5929\u5DF2\u6709\u4F1A\u8BDD\uFF0C\u5148\u53D1\u9001 /new\uFF0C\u518D\u53D1\u9001\u666E\u901A\u6D88\u606F\u751F\u6548\u3002"
|
||||
),
|
||||
error || currentUnavailable ? h2(
|
||||
"p",
|
||||
{ className: "dim-presetError", role: error ? "alert" : "status" },
|
||||
|
|
@ -9950,13 +9966,18 @@ var CSS11 = String.raw`
|
|||
.dim-panel .dim-workspaceEdit:disabled { cursor: not-allowed; opacity: .55; }
|
||||
.dim-panel .dim-workspacePath { min-width: 0; max-width: 100%; grid-column: 1 / -1; grid-row: 2; display: block; overflow-x: auto; overflow-y: hidden; color: var(--dsw-alias-label-primary, #1f2329); font: 12px/1.4 ui-monospace, SFMono-Regular, Menlo, monospace; white-space: nowrap; }
|
||||
.dim-panel .dim-preset { min-width: 0; display: grid; grid-template-columns: minmax(0, 1fr) max-content; align-items: center; column-gap: 10px; row-gap: 4px; margin-top: 6px; padding: 6px 10px; border: 1px solid var(--dsw-alias-border-l1, #eef0f3); border-radius: 9px; background: var(--dsw-alias-bg-module-platform, #f7f8fa); }
|
||||
.dim-panel .dim-presetHeader { display: contents; color: var(--dsw-alias-label-secondary, #646a73); font-size: 12px; line-height: normal; }
|
||||
.dim-panel .dim-presetHeader > span { grid-column: 1; grid-row: 1; white-space: nowrap; }
|
||||
.dim-panel .dim-presetHeader { position: relative; min-width: 0; grid-column: 1 / -1; grid-row: 1; display: flex; align-items: center; justify-content: space-between; gap: 10px; color: var(--dsw-alias-label-secondary, #646a73); font-size: 12px; line-height: normal; }
|
||||
.dim-panel .dim-presetTitle { min-width: 0; display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; }
|
||||
.dim-panel .dim-presetHelp { display: inline-flex; align-items: center; flex: none; }
|
||||
.dim-panel .dim-presetHelpButton { width: 17px; height: 17px; display: grid; place-items: center; padding: 0; border: 1px solid color-mix(in srgb, #1677ff 28%, var(--dsw-alias-border-l2, #dfe1e5)); border-radius: 50%; color: #1677ff; background: var(--dsw-alias-bg-layer-1, #fff); font: inherit; font-size: 11px; line-height: 1; font-weight: 700; cursor: help; transition: border-color .15s ease, color .15s ease, background .15s ease, box-shadow .15s ease; }
|
||||
.dim-panel .dim-presetHelpButton:hover { border-color: #1677ff; color: #0f5fce; background: color-mix(in srgb, #1677ff 8%, var(--dsw-alias-bg-layer-1, #fff)); }
|
||||
.dim-panel .dim-presetHelpButton:focus-visible { outline: none; border-color: #1677ff; box-shadow: 0 0 0 3px color-mix(in srgb, #1677ff 16%, transparent); }
|
||||
.dim-panel .dim-presetTooltip { position: absolute; top: calc(100% + 7px); left: 0; z-index: 30; width: min(320px, 100%); padding: 9px 10px; border: 1px solid var(--dsw-alias-border-l2, #dfe1e5); border-radius: 8px; color: var(--dsw-alias-label-primary, #1f2329); background: var(--dsw-alias-bg-layer-3, #fff); box-shadow: 0 10px 28px rgb(31 35 41 / 16%); font-size: 11px; line-height: 16px; font-weight: 400; overflow-wrap: anywhere; white-space: normal; opacity: 0; visibility: hidden; transform: translateY(-3px); pointer-events: none; transition: opacity .15s ease, transform .15s ease, visibility .15s ease; }
|
||||
.dim-panel .dim-presetHelp:hover .dim-presetTooltip, .dim-panel .dim-presetHelp:focus-within .dim-presetTooltip { opacity: 1; visibility: visible; transform: translateY(0); }
|
||||
.dim-panel .dim-presetStatus { grid-column: 2; grid-row: 1; color: var(--dsw-alias-label-tertiary, #8f959e); font-size: 12px; white-space: nowrap; }
|
||||
.dim-panel .dim-presetSelect { min-width: 0; max-width: 100%; grid-column: 1 / -1; grid-row: 2; height: 30px; padding: 0 8px; 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-1, #fff); font: inherit; font-size: 12px; }
|
||||
.dim-panel .dim-presetSelect:disabled { cursor: not-allowed; opacity: .55; }
|
||||
.dim-panel .dim-presetHelp { grid-column: 1 / -1; grid-row: 3; color: var(--dsw-alias-label-tertiary, #8f959e); font-size: 11px; line-height: 1.4; }
|
||||
.dim-panel .dim-presetError { grid-column: 1 / -1; grid-row: 4; margin: 0; color: var(--dsw-alias-state-error-primary, #d54941); font-size: 12px; line-height: 1.4; }
|
||||
.dim-panel .dim-presetError { grid-column: 1 / -1; grid-row: 3; margin: 0; color: var(--dsw-alias-state-error-primary, #d54941); font-size: 12px; line-height: 1.4; }
|
||||
.dim-directoryPickerBackdrop { --dim-blue: var(--dsw-alias-state-business-primary, #3370ff); --dim-blue-soft: color-mix(in srgb, var(--dim-blue) 9%, transparent); position: fixed; inset: 0; z-index: 1000; display: grid; place-items: center; padding: 24px; background: rgb(15 17 21 / 42%); backdrop-filter: blur(3px); }
|
||||
.dim-directoryPickerBackdrop, .dim-directoryPickerBackdrop *, .dim-directoryPickerBackdrop *::before, .dim-directoryPickerBackdrop *::after { box-sizing: border-box; }
|
||||
.dim-directoryPicker { width: min(720px, 100%); height: min(620px, calc(100vh - 48px)); min-height: 420px; display: grid; grid-template-rows: auto minmax(0, 1fr) auto; overflow: hidden; border: 1px solid var(--dsw-alias-border-l2, #dfe1e5); border-radius: 18px; outline: none; color: var(--dsw-alias-label-primary, #1f2329); background: var(--dsw-alias-bg-layer-1, #fff); box-shadow: 0 24px 72px rgb(15 17 21 / 24%); }
|
||||
|
|
|
|||
128
lib/index.js
128
lib/index.js
File diff suppressed because one or more lines are too long
|
|
@ -46,6 +46,7 @@ export function normalizeAgentPresetCatalog(value) {
|
|||
|
||||
export function AgentPresetEditor({ agentPreset = '', disabled = false, onSave }) {
|
||||
const catalog = React.useContext(AgentPresetCatalogContext) ?? EMPTY_AGENT_PRESET_CATALOG;
|
||||
const helpId = React.useId();
|
||||
const current = normalizeAgentPresetId(agentPreset);
|
||||
const [saving, setSaving] = React.useState(false);
|
||||
const [error, setError] = React.useState(null);
|
||||
|
|
@ -78,7 +79,20 @@ export function AgentPresetEditor({ agentPreset = '', disabled = false, onSave }
|
|||
|
||||
return h('div', { className: 'dim-preset' },
|
||||
h('div', { className: 'dim-presetHeader' },
|
||||
h('span', null, 'Agent Preset'),
|
||||
h('span', { className: 'dim-presetTitle' },
|
||||
h('span', null, 'Agent Preset'),
|
||||
h('span', { className: 'dim-presetHelp' },
|
||||
h('button', {
|
||||
type: 'button',
|
||||
className: 'dim-presetHelpButton',
|
||||
'aria-label': '查看 Agent Preset 说明',
|
||||
'aria-describedby': helpId,
|
||||
}, h('span', { 'aria-hidden': 'true' }, '?')),
|
||||
h('span', {
|
||||
id: helpId,
|
||||
className: 'dim-presetTooltip',
|
||||
role: 'tooltip',
|
||||
}, '只影响新建会话;若当前聊天已有会话,先发送 /new,再发送普通消息生效。'))),
|
||||
saving ? h('span', { className: 'dim-presetStatus' }, '保存中…') : null),
|
||||
React.createElement('select', {
|
||||
className: 'dim-presetSelect',
|
||||
|
|
@ -96,11 +110,6 @@ export function AgentPresetEditor({ agentPreset = '', disabled = false, onSave }
|
|||
: item.label && item.label !== item.id ? `${item.label}(${item.id})` : item.id,
|
||||
)),
|
||||
),
|
||||
h(
|
||||
'small',
|
||||
{ className: 'dim-presetHelp' },
|
||||
'只影响新建会话;若当前聊天已有会话,先发送 /new,再发送普通消息生效。',
|
||||
),
|
||||
error || currentUnavailable ? h(
|
||||
'p',
|
||||
{ className: 'dim-presetError', role: error ? 'alert' : 'status' },
|
||||
|
|
|
|||
|
|
@ -136,6 +136,7 @@ const EN = Object.freeze({
|
|||
'工作区路径必须指向一个目录。': 'The workspace path must point to a directory.',
|
||||
'找不到要修改的机器人。': 'The bot could not be found.',
|
||||
'Agent Preset': 'Agent Preset',
|
||||
'查看 Agent Preset 说明': 'View Agent Preset help',
|
||||
'跟随 Host 默认': 'Follow the Host default',
|
||||
'(已不可用)': ' (unavailable)',
|
||||
'只影响新建会话;若当前聊天已有会话,先发送 /new,再发送普通消息生效。': 'This affects only new sessions. If the current chat already has a session, send /new, then send a regular message to apply it.',
|
||||
|
|
|
|||
|
|
@ -143,13 +143,18 @@ const CSS = String.raw`
|
|||
.dim-panel .dim-workspaceEdit:disabled { cursor: not-allowed; opacity: .55; }
|
||||
.dim-panel .dim-workspacePath { min-width: 0; max-width: 100%; grid-column: 1 / -1; grid-row: 2; display: block; overflow-x: auto; overflow-y: hidden; color: var(--dsw-alias-label-primary, #1f2329); font: 12px/1.4 ui-monospace, SFMono-Regular, Menlo, monospace; white-space: nowrap; }
|
||||
.dim-panel .dim-preset { min-width: 0; display: grid; grid-template-columns: minmax(0, 1fr) max-content; align-items: center; column-gap: 10px; row-gap: 4px; margin-top: 6px; padding: 6px 10px; border: 1px solid var(--dsw-alias-border-l1, #eef0f3); border-radius: 9px; background: var(--dsw-alias-bg-module-platform, #f7f8fa); }
|
||||
.dim-panel .dim-presetHeader { display: contents; color: var(--dsw-alias-label-secondary, #646a73); font-size: 12px; line-height: normal; }
|
||||
.dim-panel .dim-presetHeader > span { grid-column: 1; grid-row: 1; white-space: nowrap; }
|
||||
.dim-panel .dim-presetHeader { position: relative; min-width: 0; grid-column: 1 / -1; grid-row: 1; display: flex; align-items: center; justify-content: space-between; gap: 10px; color: var(--dsw-alias-label-secondary, #646a73); font-size: 12px; line-height: normal; }
|
||||
.dim-panel .dim-presetTitle { min-width: 0; display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; }
|
||||
.dim-panel .dim-presetHelp { display: inline-flex; align-items: center; flex: none; }
|
||||
.dim-panel .dim-presetHelpButton { width: 17px; height: 17px; display: grid; place-items: center; padding: 0; border: 1px solid color-mix(in srgb, #1677ff 28%, var(--dsw-alias-border-l2, #dfe1e5)); border-radius: 50%; color: #1677ff; background: var(--dsw-alias-bg-layer-1, #fff); font: inherit; font-size: 11px; line-height: 1; font-weight: 700; cursor: help; transition: border-color .15s ease, color .15s ease, background .15s ease, box-shadow .15s ease; }
|
||||
.dim-panel .dim-presetHelpButton:hover { border-color: #1677ff; color: #0f5fce; background: color-mix(in srgb, #1677ff 8%, var(--dsw-alias-bg-layer-1, #fff)); }
|
||||
.dim-panel .dim-presetHelpButton:focus-visible { outline: none; border-color: #1677ff; box-shadow: 0 0 0 3px color-mix(in srgb, #1677ff 16%, transparent); }
|
||||
.dim-panel .dim-presetTooltip { position: absolute; top: calc(100% + 7px); left: 0; z-index: 30; width: min(320px, 100%); padding: 9px 10px; border: 1px solid var(--dsw-alias-border-l2, #dfe1e5); border-radius: 8px; color: var(--dsw-alias-label-primary, #1f2329); background: var(--dsw-alias-bg-layer-3, #fff); box-shadow: 0 10px 28px rgb(31 35 41 / 16%); font-size: 11px; line-height: 16px; font-weight: 400; overflow-wrap: anywhere; white-space: normal; opacity: 0; visibility: hidden; transform: translateY(-3px); pointer-events: none; transition: opacity .15s ease, transform .15s ease, visibility .15s ease; }
|
||||
.dim-panel .dim-presetHelp:hover .dim-presetTooltip, .dim-panel .dim-presetHelp:focus-within .dim-presetTooltip { opacity: 1; visibility: visible; transform: translateY(0); }
|
||||
.dim-panel .dim-presetStatus { grid-column: 2; grid-row: 1; color: var(--dsw-alias-label-tertiary, #8f959e); font-size: 12px; white-space: nowrap; }
|
||||
.dim-panel .dim-presetSelect { min-width: 0; max-width: 100%; grid-column: 1 / -1; grid-row: 2; height: 30px; padding: 0 8px; 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-1, #fff); font: inherit; font-size: 12px; }
|
||||
.dim-panel .dim-presetSelect:disabled { cursor: not-allowed; opacity: .55; }
|
||||
.dim-panel .dim-presetHelp { grid-column: 1 / -1; grid-row: 3; color: var(--dsw-alias-label-tertiary, #8f959e); font-size: 11px; line-height: 1.4; }
|
||||
.dim-panel .dim-presetError { grid-column: 1 / -1; grid-row: 4; margin: 0; color: var(--dsw-alias-state-error-primary, #d54941); font-size: 12px; line-height: 1.4; }
|
||||
.dim-panel .dim-presetError { grid-column: 1 / -1; grid-row: 3; margin: 0; color: var(--dsw-alias-state-error-primary, #d54941); font-size: 12px; line-height: 1.4; }
|
||||
.dim-directoryPickerBackdrop { --dim-blue: var(--dsw-alias-state-business-primary, #3370ff); --dim-blue-soft: color-mix(in srgb, var(--dim-blue) 9%, transparent); position: fixed; inset: 0; z-index: 1000; display: grid; place-items: center; padding: 24px; background: rgb(15 17 21 / 42%); backdrop-filter: blur(3px); }
|
||||
.dim-directoryPickerBackdrop, .dim-directoryPickerBackdrop *, .dim-directoryPickerBackdrop *::before, .dim-directoryPickerBackdrop *::after { box-sizing: border-box; }
|
||||
.dim-directoryPicker { width: min(720px, 100%); height: min(620px, calc(100vh - 48px)); min-height: 420px; display: grid; grid-template-rows: auto minmax(0, 1fr) auto; overflow: hidden; border: 1px solid var(--dsw-alias-border-l2, #dfe1e5); border-radius: 18px; outline: none; color: var(--dsw-alias-label-primary, #1f2329); background: var(--dsw-alias-bg-layer-1, #fff); box-shadow: 0 24px 72px rgb(15 17 21 / 24%); }
|
||||
|
|
|
|||
|
|
@ -578,11 +578,18 @@ test('bot cards keep the full workspace path on its own single line', async () =
|
|||
assert.match(styles, /\.dim-panel \.dim-workspaceEdit \{[^}]*grid-column: 2;[^}]*grid-row: 1;[^}]*white-space: nowrap;/);
|
||||
});
|
||||
|
||||
test('bot cards keep the Agent Preset selector below the workspace path', async () => {
|
||||
test('bot cards keep Agent Preset guidance in a keyboard-accessible help tooltip', async () => {
|
||||
const styles = await readFile(STYLES_URL, 'utf8');
|
||||
|
||||
assert.match(styles, /\.dim-panel \.dim-preset \{[^}]*grid-template-columns: minmax\(0, 1fr\) max-content;[^}]*margin-top: 6px;[^}]*padding: 6px 10px;/);
|
||||
assert.match(styles, /\.dim-panel \.dim-presetHeader \{[^}]*position: relative;[^}]*grid-column: 1 \/ -1;[^}]*display: flex;[^}]*justify-content: space-between;/);
|
||||
assert.match(styles, /\.dim-panel \.dim-presetTitle \{[^}]*display: inline-flex;[^}]*gap: 5px;[^}]*white-space: nowrap;/);
|
||||
assert.match(styles, /\.dim-panel \.dim-presetHelpButton:focus-visible \{[^}]*box-shadow:/);
|
||||
assert.match(styles, /\.dim-panel \.dim-presetTooltip \{[^}]*position: absolute;[^}]*width: min\(320px, 100%\);[^}]*white-space: normal;[^}]*opacity: 0;[^}]*visibility: hidden;[^}]*pointer-events: none;/);
|
||||
assert.match(styles, /\.dim-panel \.dim-presetHelp:hover \.dim-presetTooltip, \.dim-panel \.dim-presetHelp:focus-within \.dim-presetTooltip \{[^}]*opacity: 1;[^}]*visibility: visible;/);
|
||||
assert.match(styles, /\.dim-panel \.dim-presetSelect \{[^}]*grid-column: 1 \/ -1;[^}]*grid-row: 2;/);
|
||||
assert.match(styles, /\.dim-panel \.dim-presetError \{[^}]*grid-column: 1 \/ -1;[^}]*grid-row: 3;/);
|
||||
assert.doesNotMatch(styles, /\.dim-panel \.dim-presetHelp \{[^}]*grid-row: 3;/);
|
||||
});
|
||||
|
||||
test('the bundled DingTalk channel has no local sender approval workflow', async () => {
|
||||
|
|
|
|||
|
|
@ -680,7 +680,7 @@ function optionValues(select) {
|
|||
return select.children.map((option) => option.props.value);
|
||||
}
|
||||
|
||||
test('AgentPresetEditor lists Host presets and keeps the catalog label for the current id', () => {
|
||||
test('AgentPresetEditor lists Host presets and moves its session guidance into accessible help', () => {
|
||||
const renderer = create(React.createElement(
|
||||
AgentPresetCatalogContext.Provider,
|
||||
{ value: PRESET_CATALOG },
|
||||
|
|
@ -694,10 +694,18 @@ test('AgentPresetEditor lists Host presets and keeps the catalog label for the c
|
|||
assert.deepEqual(optionValues(select), ['', 'coding', 'default']);
|
||||
assert.equal(textOf(select.children[0]), '跟随 Host 默认');
|
||||
assert.equal(textOf(select.children[1]), 'Coding(coding)');
|
||||
const helpButton = renderer.root.findByProps({
|
||||
'aria-label': '查看 Agent Preset 说明',
|
||||
});
|
||||
const tooltip = renderer.root.findByProps({ role: 'tooltip' });
|
||||
assert.equal(helpButton.props.type, 'button');
|
||||
assert.ok(tooltip.props.id);
|
||||
assert.equal(helpButton.props['aria-describedby'], tooltip.props.id);
|
||||
assert.equal(
|
||||
textOf(renderer.root.findByProps({ className: 'dim-presetHelp' })),
|
||||
textOf(tooltip),
|
||||
'只影响新建会话;若当前聊天已有会话,先发送 /new,再发送普通消息生效。',
|
||||
);
|
||||
assert.equal(renderer.root.findAllByType('small').length, 0);
|
||||
renderer.unmount();
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue