Compare commits

...

3 Commits

Author SHA1 Message Date
Lambda
07ba3e440f feat(issues): trim trigger preview popover copy and drop redundant reason lines
The active hover popover stacked header + reason + presence, repeating the
same fact across lines and again against the chip. Tighten it:

- Drop the reason line for assignee / @mention: the header (name · source)
  already conveys why they fire. Keep reason only for squad-leader (the link
  is non-obvious) and the unknown fallback, both trimmed of the duplicated
  name.
- Shorten presence (Starts right away. / Offline now — starts once online.)
  and de-jargon the skip/manage hints (no more 'trigger').
- Align the popover title to the chip wording (Will start when sent).

All four locales updated; removes the two now-unused reason keys.

Refs MUL-3211

Co-authored-by: multica-agent <github@multica.ai>
2026-06-17 14:42:43 +08:00
Lambda
dd148b9b65 feat(issues): align restore hint to will-start phrasing
Carry the trigger-chip copy unification into the suppressed-agent restore
hint (trigger_click_to_restore), the last surface still mixing 'trigger'
with the chip's 'start' wording:

- en: Won't start this time. Click to restore.
- CJK: skip-state term realigned to the 'start' verb, rest unchanged.

Refs MUL-3211

Co-authored-by: multica-agent <github@multica.ai>
2026-06-17 14:41:11 +08:00
Lambda
9e0614612d feat(issues): unify trigger chip copy to will-start phrasing
Make the comment trigger chip's on/off states symmetric around the verb
'start' instead of mixing natural language with the 'trigger' jargon:

- on:           Will start when sent
- skipped:      Won't start this time
- all skipped:  No agents will start
- multi on:     N agents will start when sent

Updates all four locales (en/zh-Hans/ja/ko); CJK on-state copy already
reads as future-conditional so only the skip states are realigned to the
'start' verb. Updates the component test expectations to match.

Refs MUL-3211

Co-authored-by: multica-agent <github@multica.ai>
2026-06-17 14:41:11 +08:00
6 changed files with 60 additions and 64 deletions

View File

@@ -45,7 +45,7 @@ describe("CommentTriggerChips", () => {
);
const chip = screen.getByRole("button");
expect(chip).toHaveTextContent("Starts working when sent");
expect(chip).toHaveTextContent("Will start when sent");
expect(chip).toHaveAttribute("aria-pressed", "false");
fireEvent.click(chip);
@@ -62,7 +62,7 @@ describe("CommentTriggerChips", () => {
);
const chip = screen.getByRole("button");
expect(chip).toHaveTextContent("Won't be triggered");
expect(chip).toHaveTextContent("Won't start this time");
expect(chip).toHaveAttribute("aria-pressed", "true");
});
@@ -75,7 +75,7 @@ describe("CommentTriggerChips", () => {
/>,
);
expect(screen.getByRole("button")).toHaveTextContent("2 agents start working when sent");
expect(screen.getByRole("button")).toHaveTextContent("2 agents will start when sent");
});
it("counts only non-suppressed agents in the sentence", () => {
@@ -87,7 +87,7 @@ describe("CommentTriggerChips", () => {
/>,
);
expect(screen.getByRole("button")).toHaveTextContent("1 agent starts working when sent");
expect(screen.getByRole("button")).toHaveTextContent("1 agent will start when sent");
});
it("switches to the none-will-trigger state when every agent is suppressed", () => {
@@ -99,7 +99,7 @@ describe("CommentTriggerChips", () => {
/>,
);
expect(screen.getByRole("button")).toHaveTextContent("No agents will be triggered");
expect(screen.getByRole("button")).toHaveTextContent("No agents will start");
});
it("opens the popover on click and toggles a row", () => {
@@ -114,7 +114,6 @@ describe("CommentTriggerChips", () => {
fireEvent.click(screen.getByRole("button"));
expect(screen.getByText("This comment will trigger")).toBeInTheDocument();
const row = screen.getByRole("button", { name: /Bob/ });
expect(row).toHaveTextContent("Bob");
fireEvent.click(row);

View File

@@ -46,16 +46,19 @@ function sourceLabel(source: string, t: IssuesT): string {
}
}
function sourceReason(agent: CommentTriggerPreviewAgent, t: IssuesT): string {
// Assignee / @mention reasons are intentionally omitted: the header
// (name · source) already says why they fire, so a reason line there would
// just restate it. Only the squad-leader link (non-obvious) and the unknown
// fallback carry information the header doesn't.
function sourceReason(agent: CommentTriggerPreviewAgent, t: IssuesT): string | null {
switch (agent.source) {
case "issue_assignee":
return t(($) => $.comment.trigger_reason_issue_assignee, { name: agent.name });
case "mention_agent":
return t(($) => $.comment.trigger_reason_mention_agent, { name: agent.name });
return null;
case "mention_squad_leader":
return t(($) => $.comment.trigger_reason_mention_squad_leader, { name: agent.name });
return t(($) => $.comment.trigger_reason_mention_squad_leader);
default:
return agent.reason || t(($) => $.comment.trigger_reason_unknown, { name: agent.name });
return agent.reason || t(($) => $.comment.trigger_reason_unknown);
}
}
@@ -92,10 +95,12 @@ function TriggerAgentTooltipBody({
<div>{t(($) => $.comment.trigger_click_to_restore)}</div>
) : (
<>
<div>
{sourceReason(agent, t)}
{presenceLine ? ` ${presenceLine}` : ""}
</div>
{(() => {
// Reason (when present) and presence share one line; either may be
// absent, so join only the parts that exist to avoid a stray space.
const line = [sourceReason(agent, t), presenceLine].filter(Boolean).join(" ");
return line ? <div>{line}</div> : null;
})()}
<div className="text-muted-foreground">{t(($) => $.comment.trigger_click_to_skip)}</div>
</>
)}

View File

@@ -290,21 +290,19 @@
"trigger_source_mention_squad_leader": "squad",
"trigger_source_unknown": "trigger",
"trigger_skipped_label": "Skipped",
"trigger_wont_trigger": "Won't be triggered",
"trigger_none_will_trigger": "No agents will be triggered",
"trigger_reason_issue_assignee": "{{name}} is assigned here and will be notified by this comment.",
"trigger_reason_mention_agent": "{{name}} is mentioned in this comment.",
"trigger_reason_mention_squad_leader": "{{name}} leads a squad mentioned in this comment.",
"trigger_reason_unknown": "{{name}} will be triggered by this comment.",
"trigger_will_start": "Starts working when sent",
"trigger_will_start_count_one": "{{count}} agent starts working when sent",
"trigger_will_start_count_other": "{{count}} agents start working when sent",
"trigger_starts_now": "It will start working right away.",
"trigger_starts_when_online": "It is offline now and will start once online.",
"trigger_click_to_skip": "Click to skip triggering this time.",
"trigger_click_to_manage": "Click to manage who gets triggered this time.",
"trigger_click_to_restore": "Won't be triggered this time. Click to restore.",
"trigger_preview_title": "This comment will trigger",
"trigger_wont_trigger": "Won't start this time",
"trigger_none_will_trigger": "No agents will start",
"trigger_reason_mention_squad_leader": "Leads a squad mentioned here.",
"trigger_reason_unknown": "Will start from this comment.",
"trigger_will_start": "Will start when sent",
"trigger_will_start_count_one": "{{count}} agent will start when sent",
"trigger_will_start_count_other": "{{count}} agents will start when sent",
"trigger_starts_now": "Starts right away.",
"trigger_starts_when_online": "Offline now — starts once online.",
"trigger_click_to_skip": "Click to skip this time.",
"trigger_click_to_manage": "Click to choose who runs this time.",
"trigger_click_to_restore": "Won't start this time. Click to restore.",
"trigger_preview_title": "Will start when sent",
"trigger_chip_aria": "{{name}} trigger: {{state}}",
"resolve": {
"resolve_thread_action": "Resolve thread",

View File

@@ -282,20 +282,18 @@
"trigger_source_mention_squad_leader": "Squad",
"trigger_source_unknown": "トリガー",
"trigger_skipped_label": "スキップ",
"trigger_wont_trigger": "トリガーされません",
"trigger_none_will_trigger": "いずれもトリガーされません",
"trigger_reason_issue_assignee": "{{name}} はこのイシューの担当で、このコメントで通知されます。",
"trigger_reason_mention_agent": "このコメントで {{name}} がメンションされています。",
"trigger_reason_mention_squad_leader": "{{name}} はメンションされた Squad のリーダーです。",
"trigger_reason_unknown": "このコメントで {{name}} がトリガーされます。",
"trigger_wont_trigger": "今回は開始しません",
"trigger_none_will_trigger": "いずれも開始しません",
"trigger_reason_mention_squad_leader": "メンションされた Squad のリーダー。",
"trigger_reason_unknown": "このコメントで開始します。",
"trigger_will_start": "送信後に作業を開始します",
"trigger_will_start_count_other": "送信後に {{count}} 体のエージェントが作業を開始します",
"trigger_starts_now": "すぐに作業を開始します。",
"trigger_starts_when_online": "現在オフラインのため、オンラインになり次第開始します。",
"trigger_click_to_skip": "クリックすると今回はトリガーされません。",
"trigger_click_to_manage": "クリックして今回のトリガー対象を管理します。",
"trigger_click_to_restore": "今回はトリガーされません。クリックで元に戻せます。",
"trigger_preview_title": "このコメントでトリガーされる対象",
"trigger_starts_now": "すぐに開始します。",
"trigger_starts_when_online": "オフライン中。オンラインになり次第開始します。",
"trigger_click_to_skip": "クリックで今回はスキップ。",
"trigger_click_to_manage": "クリックして今回実行する対象を選択。",
"trigger_click_to_restore": "今回は開始しません。クリックで元に戻せます。",
"trigger_preview_title": "送信後に開始する対象",
"trigger_chip_aria": "{{name}} のトリガー: {{state}}",
"resolve": {
"resolve_thread_action": "スレッドを解決",

View File

@@ -290,20 +290,18 @@
"trigger_source_mention_squad_leader": "Squad",
"trigger_source_unknown": "트리거",
"trigger_skipped_label": "건너뜀",
"trigger_wont_trigger": "트리거되지 않습니다",
"trigger_none_will_trigger": "모두 트리거되지 않습니다",
"trigger_reason_issue_assignee": "{{name}}님은 이 이슈의 담당자이며 이 댓글로 알림을 받습니다.",
"trigger_reason_mention_agent": "이 댓글에서 {{name}}님을 멘션했습니다.",
"trigger_reason_mention_squad_leader": "{{name}}님은 멘션된 Squad의 리더입니다.",
"trigger_reason_unknown": "이 댓글로 {{name}}님이 트리거됩니다.",
"trigger_wont_trigger": "이번에는 시작하지 않습니다",
"trigger_none_will_trigger": "어떤 에이전트도 시작하지 않습니다",
"trigger_reason_mention_squad_leader": "멘션된 Squad의 리더입니다.",
"trigger_reason_unknown": "이 댓글로 시작합니다.",
"trigger_will_start": "전송 후 작업을 시작합니다",
"trigger_will_start_count_other": "전송 후 에이전트 {{count}}개가 작업을 시작합니다",
"trigger_starts_now": "바로 작업을 시작합니다.",
"trigger_starts_now": "바로 시작합니다.",
"trigger_starts_when_online": "현재 오프라인이며 온라인이 되면 시작합니다.",
"trigger_click_to_skip": "클릭하면 이번에는 트리거되지 않습니다.",
"trigger_click_to_manage": "클릭하여 이번 트리거 대상을 관리합니다.",
"trigger_click_to_restore": "이번에는 트리거되지 않습니다. 클릭하면 복원됩니다.",
"trigger_preview_title": "이 댓글로 트리거되는 대상",
"trigger_click_to_skip": "클릭하면 이번에는 건너뜁니다.",
"trigger_click_to_manage": "클릭하여 이번에 실행할 대상을 선택합니다.",
"trigger_click_to_restore": "이번에는 시작하지 않습니다. 클릭하면 복원됩니다.",
"trigger_preview_title": "전송 후 시작할 대상",
"trigger_chip_aria": "{{name}} 트리거: {{state}}",
"resolve": {
"resolve_thread_action": "스레드 해결",

View File

@@ -287,20 +287,18 @@
"trigger_source_mention_squad_leader": "squad",
"trigger_source_unknown": "将触发",
"trigger_skipped_label": "已跳过",
"trigger_wont_trigger": "不会触发",
"trigger_none_will_trigger": "全部不会触发",
"trigger_reason_issue_assignee": "{{name}} 是当前 issue 的 assignee这条评论会唤醒它。",
"trigger_reason_mention_agent": "这条评论 @ 了 {{name}}。",
"trigger_reason_mention_squad_leader": "{{name}} 是被 @ Squad 的 leader。",
"trigger_reason_unknown": "这条评论会触发 {{name}}。",
"trigger_wont_trigger": "本次不会开始",
"trigger_none_will_trigger": "都不会开始",
"trigger_reason_mention_squad_leader": "被 @ Squad 的 leader。",
"trigger_reason_unknown": "将由这条评论开始。",
"trigger_will_start": "发送后开始工作",
"trigger_will_start_count_other": "发送后 {{count}} 个智能体开始工作",
"trigger_starts_now": "立即开始工作。",
"trigger_starts_now": "立即开始。",
"trigger_starts_when_online": "当前离线,上线后开始。",
"trigger_click_to_skip": "点击本次不触发。",
"trigger_click_to_manage": "点击管理本次触发对象。",
"trigger_click_to_restore": "本次不触发,点击恢复。",
"trigger_preview_title": "这条评论将触发",
"trigger_click_to_skip": "点击本次跳过。",
"trigger_click_to_manage": "点击选择本次运行的对象。",
"trigger_click_to_restore": "本次不会开始,点击恢复。",
"trigger_preview_title": "发送后将开始",
"trigger_chip_aria": "{{name}} 触发状态:{{state}}",
"resolve": {
"resolve_thread_action": "解决该讨论",