feat(ai): exclude badge/pill/tag from card-row equalization (P3 dashboard 等宽)

equalizeHorizontalSiblings (the dashboard column-equalization pass) is the same
logic as the equalizeCardRow ported in I4, except it also excludes badge/pill/tag
roles from card candidates. Add those exclusions so equalize_card_row covers both
— closing the P3 "dashboard 等宽" item.

The other two P3 items are architectural non-gaps, not ports:
- 变量 seeding: plans carry no palette (variables.rs is a deliberate no-op); the
  design-system path (design_system_to_seed_commands) already seeds variables.
- intent-modify: the Rust Design path is AGENTIC — an agent::Provider whose
  modify-level tools (update_node / batch_design / ...) handle create-vs-modify
  organically, so the 2-way Design/Chat gate suffices. TS's 3-way classify
  existed for its non-agentic routing and would be redundant here.
This commit is contained in:
Fini 2026-06-06 23:01:03 +08:00
parent 418da9af84
commit c66e4d9a1e
2 changed files with 32 additions and 2 deletions

View file

@ -439,7 +439,10 @@ fn size_number(node: &Value, key: &str) -> f64 {
}
/// Equalize a row of fixed-width card frames to `fill_container` so they stretch
/// evenly (port of `equalizeCardRow`). Pure property fix — taffy then lays out.
/// evenly (port of `equalizeCardRow` AND the near-identical
/// `equalizeHorizontalSiblings` in design-canvas-ops.ts — the dashboard 等宽
/// pass; the badge/pill/tag exclusions come from the latter). Pure property fix
/// — taffy then lays out.
fn equalize_card_row(node: &mut Value) {
if node.get("layout").and_then(Value::as_str) != Some("horizontal") {
return;
@ -458,7 +461,14 @@ fn equalize_card_row(node: &mut Value) {
.enumerate()
.filter(|(_, c)| {
c.get("type").and_then(Value::as_str) == Some("frame")
&& !matches!(role_of(c), Some("divider") | Some("phone-mockup"))
&& !matches!(
role_of(c),
Some("divider")
| Some("phone-mockup")
| Some("badge")
| Some("pill")
| Some("tag")
)
&& size_number(c, "height") > 88.0
})
.map(|(i, _)| i)

View file

@ -223,6 +223,26 @@ fn card_row_left_alone_when_widths_similar() {
assert_eq!(row["children"][0]["width"], json!(200));
}
#[test]
fn badge_pill_tag_rows_are_not_equalized() {
// The dashboard-pass (equalizeHorizontalSiblings) excludes badge/pill/tag,
// so a row of those keeps its widths even with a low width ratio.
for role in ["badge", "pill", "tag"] {
let mut row = json!({
"type":"frame","layout":"horizontal","children":[
{"type":"frame","role":role,"width":240,"height":200,"children":[]},
{"type":"frame","role":role,"width":120,"height":210,"children":[]}
]
});
equalize_card_row(&mut row);
assert_eq!(
row["children"][0]["width"],
json!(240),
"{role} row must not be equalized"
);
}
}
#[test]
fn form_inputs_promoted_when_fill_sibling_present() {
let mut form = json!({