fix(orchestrator): refine chat-generated mobile layouts
This commit is contained in:
parent
7826163240
commit
efb4b84e7d
|
|
@ -20,6 +20,7 @@ pub struct NormInfo {
|
|||
/// 移动端宽度上限(含)—— ≤ 此值视为移动端单屏。
|
||||
const MOBILE_MAX_WIDTH: f64 = 480.0;
|
||||
const MOBILE_DEFAULT_HEIGHT: f64 = 812.0;
|
||||
const MOBILE_DEFAULT_ROOT_GAP: f64 = 20.0;
|
||||
|
||||
/// subtask 的 id / label 命中即视为"状态栏"区块 —— 移动端由
|
||||
/// scaffold 注入固定状态栏,plan 里若带状态栏 subtask 则剔除。
|
||||
|
|
@ -124,7 +125,9 @@ pub fn normalize(plan: &mut OrchestratorPlan, req: &DesignRequest) -> NormInfo {
|
|||
|
||||
if is_mobile {
|
||||
plan.root_frame.layout = Some("vertical".into());
|
||||
plan.root_frame.gap = Some(0.0);
|
||||
if plan.root_frame.gap.unwrap_or(0.0) <= 0.0 {
|
||||
plan.root_frame.gap = Some(MOBILE_DEFAULT_ROOT_GAP);
|
||||
}
|
||||
plan.root_frame.padding = Some(0.0);
|
||||
if plan.root_frame.height <= 0.0 {
|
||||
plan.root_frame.height = MOBILE_DEFAULT_HEIGHT;
|
||||
|
|
@ -249,7 +252,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn normalize_mobile_forces_vertical_root_layout() {
|
||||
fn normalize_mobile_forces_vertical_root_layout_and_keeps_positive_gap() {
|
||||
let mut p = plan(390.0, vec![subtask("hero", "Hero")]);
|
||||
p.root_frame.layout = Some("none".into());
|
||||
p.root_frame.gap = Some(12.0);
|
||||
|
|
@ -258,10 +261,20 @@ mod tests {
|
|||
normalize(&mut p, &req());
|
||||
|
||||
assert_eq!(p.root_frame.layout.as_deref(), Some("vertical"));
|
||||
assert_eq!(p.root_frame.gap, Some(0.0));
|
||||
assert_eq!(p.root_frame.gap, Some(12.0));
|
||||
assert_eq!(p.root_frame.padding, Some(0.0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn normalize_mobile_zero_gap_uses_section_spacing() {
|
||||
let mut p = plan(390.0, vec![subtask("hero", "Hero")]);
|
||||
p.root_frame.gap = Some(0.0);
|
||||
|
||||
normalize(&mut p, &req());
|
||||
|
||||
assert_eq!(p.root_frame.gap, Some(20.0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn normalize_mobile_zero_height_uses_default_viewport() {
|
||||
let mut p = plan(390.0, vec![subtask("hero", "Hero")]);
|
||||
|
|
|
|||
|
|
@ -535,6 +535,13 @@ Overall design: {}\n\n\
|
|||
CRITICAL LAYOUT CONSTRAINTS:\n\
|
||||
- {}\n\
|
||||
- Target content amount: ~{:.0}px tall. Generate enough elements to fill this area.\n\
|
||||
- DENSITY: Do NOT pack the area edge-to-edge. Prefer fewer, stronger modules with visible negative space; most sections should have 3-5 primary rows/cards at most.\n\
|
||||
- VISUAL HIERARCHY: Each section must have one clear focal element, secondary supporting text, and quieter metadata. Avoid equal-weight blocks competing for attention.\n\
|
||||
- SPACING CONSISTENCY: Use a single outer content gutter and consistent internal gaps. Do not create nested wrappers with conflicting padding or content touching edges.\n\
|
||||
- CRAFT POLISH: Add refinement through restrained 1px low-contrast borders, tonal surfaces, small state badges, and subtle shadows. Avoid template-like thick outlines, giant pills, or flat blocks with no micro-detail.\n\
|
||||
- MEDIA CONSISTENCY: Use photographic images sparingly and keep them visually consistent in subject, crop, tone, and radius. For food/category UI, prefer cohesive icon or illustration tiles over random unrelated photos.\n\
|
||||
- ICON SCALE: Icons support content; keep most icons 16-22px inside 36-48px controls. Avoid oversized circular icon bubbles or repeated identical icon treatments unless the design brief calls for them.\n\
|
||||
- ACCENT DISCIPLINE: Reserve saturated accent color for one primary CTA or promo plus small highlights. Do not apply it to every icon, label, border, and large surface at once.\n\
|
||||
- {}\n\
|
||||
- NEVER set x or y on children inside layout frames.\n\
|
||||
- Use \"fill_container\" for children that stretch, \"fit_content\" for shrink-wrap sizing.\n\
|
||||
|
|
|
|||
|
|
@ -160,6 +160,12 @@ fn subagent_prompt_carries_ts_layout_contract() {
|
|||
assert!(cr.user_prompt.contains("NO BLANK PLACEHOLDERS"));
|
||||
assert!(cr.user_prompt.contains("MOBILE NAV SURFACE"));
|
||||
assert!(cr.user_prompt.contains("TYPOGRAPHY HIERARCHY"));
|
||||
assert!(cr.user_prompt.contains("DENSITY"));
|
||||
assert!(cr.user_prompt.contains("VISUAL HIERARCHY"));
|
||||
assert!(cr.user_prompt.contains("SPACING CONSISTENCY"));
|
||||
assert!(cr.user_prompt.contains("CRAFT POLISH"));
|
||||
assert!(cr.user_prompt.contains("MEDIA CONSISTENCY"));
|
||||
assert!(cr.user_prompt.contains("ICON SCALE"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
Loading…
Reference in a new issue