feat: improve mobile touch semantics

This commit is contained in:
kris
2026-03-30 01:11:41 +08:00
parent 18351993df
commit 62caaa0ab0
3 changed files with 23 additions and 2 deletions

View File

@@ -4438,11 +4438,21 @@ function actionTag(label, action, attrs = "", options = {}) {
classes.push("clickable-tag");
}
const title = options.disabledReason || options.title || "";
if (targetAction) {
return `
<button
class="${classes.join(" ")}"
type="button"
data-action="${escapeHtml(targetAction)}"
${options.disabledReason ? `data-disabled-reason="${escapeHtml(options.disabledReason)}" aria-disabled="true"` : ""}
${title ? `title="${escapeHtml(title)}"` : ""}
${attrs}
>${escapeHtml(label)}</button>
`.replace(/\s+/g, " ").trim();
}
return `
<span
class="${classes.join(" ")}"
${targetAction ? `data-action="${escapeHtml(targetAction)}"` : ""}
${options.disabledReason ? `data-disabled-reason="${escapeHtml(options.disabledReason)}" aria-disabled="true"` : ""}
${title ? `title="${escapeHtml(title)}"` : ""}
${attrs}
>${escapeHtml(label)}</span>

View File

@@ -1019,6 +1019,7 @@ select {
display: inline-flex;
align-items: center;
justify-content: center;
appearance: none;
padding: 5px 9px;
border-radius: 999px;
background: #f6f9fe;
@@ -1026,6 +1027,8 @@ select {
color: var(--muted);
font-size: 11px;
line-height: 1.1;
font-family: inherit;
text-decoration: none;
}
.row-meta .tag {

View File

@@ -100,6 +100,14 @@ test("mobile touch targets raise tappable buttons, tabs, and action tags closer
assert.match(CSS, /@media \(max-width: 760px\)[\s\S]*\.btn,\s*[\s\S]*\.tab,\s*[\s\S]*\.tag\.clickable-tag\s*\{[\s\S]*display:\s*inline-flex/);
});
test("action tags render interactive controls as buttons instead of passive spans", () => {
const actionTagSource = extractBetween(APP, "function actionTag(", "function renderPipelineButton(");
assert.match(actionTagSource, /if \(targetAction\) \{/);
assert.match(actionTagSource, /<button/);
assert.match(actionTagSource, /type="button"/);
assert.match(actionTagSource, /<span/);
});
test("mobile screen heads split the first action into a primary rail and keep the rest in a secondary strip", () => {
assert.match(APP, /function splitPrimaryAction\(actionsHtml\)/);
assert.match(APP, /class="action-row-primary"/);