Files
yidaima/RuoYi-Vue/docs/superpowers/plans/2026-07-03-style-preset-ui-only.md

7.7 KiB

Style Preset UI Only Implementation Plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: Make page style presets affect generated UI tokens only, without changing generated page canvas/layout.

Architecture: Keep automatic layout selection inside PageCompositionService.chooseLayout(). Resolve the selected PageStylePreset only to write stylePreset, styleTokens, and composition metadata into layout JSON. Remove the canvas override path so presets cannot change table/card/split/dense layout structure.

Tech Stack: Java, JUnit 4, Jackson, Spring service classes in ruoyi-generator.


File Structure

  • Modify: ruoyi-generator/src/test/java/com/ruoyi/generator/service/front/PageCompositionServiceStylePresetTest.java
    • Owns regression tests for PageCompositionService style preset behavior.
  • Modify: ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/PageCompositionService.java
    • Owns deterministic page canvas selection and layout JSON composition.
  • Modify: ruoyi-generator/src/test/java/com/ruoyi/generator/service/front/PageStylePresetRegistryTest.java
    • Owns registry contract tests for style tokens, density, and fallback.
  • Modify: ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/PageStylePresetRegistry.java
    • Owns available visual preset definitions.

Task 1: Lock Style Presets Out Of Canvas Selection

Files:

  • Modify: ruoyi-generator/src/test/java/com/ruoyi/generator/service/front/PageCompositionServiceStylePresetTest.java

  • Modify: ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/PageCompositionService.java

  • Step 1: Write the failing frontend regression test

Replace cardPortalPresetPrefersCardCanvasForFrontendLists with:

@Test
public void cardPortalPresetKeepsAutomaticallySelectedFrontendCanvas()
{
    FrontProjectPageDesign design = design("frontend", "list");

    service.compose(design, table(), Arrays.asList(
            column("title", "title", "1", "1", "1"),
            column("status", "status", "1", "1", "1")), null, null, true, "card_portal");

    Map<String, Object> layout = readLayout(design);
    assertEquals("frontend-list-v1", layout.get("canvas"));
    assertEquals("card_portal", layout.get("stylePreset"));
    assertTrue(((Map<?, ?>) layout.get("styleTokens")).containsKey("primary"));
    Map<?, ?> composition = (Map<?, ?>) layout.get("composition");
    assertEquals("card_portal", composition.get("stylePreset"));
    assertTrue(String.valueOf(composition.get("reasons")).contains("card_portal"));
}
  • Step 2: Write the failing admin regression test

Replace dataDensePresetPrefersDenseCanvasForAdminLists with:

@Test
public void dataDensePresetKeepsAutomaticallySelectedAdminCanvas()
{
    FrontProjectPageDesign design = design("admin", "list");

    service.compose(design, table(), Arrays.asList(
            column("code", "code", "1", "1", "1"),
            column("name", "name", "1", "1", "1")), null, null, true, "data_dense");

    Map<String, Object> layout = readLayout(design);
    assertEquals("admin-list-v1", layout.get("canvas"));
    assertEquals("data_dense", layout.get("stylePreset"));
    assertTrue(((Map<?, ?>) layout.get("styleTokens")).containsKey("primary"));
}
  • Step 3: Run tests to verify they fail

Run:

mvn -pl ruoyi-generator -Dtest=PageCompositionServiceStylePresetTest test

Expected: both tests fail because the current implementation changes canvas to frontend-list-card-v1 and admin-list-dense-v1.

  • Step 4: Implement minimal service change

In PageCompositionService.compose(...), replace:

stylePreset = stylePresetRegistry.resolve(stylePresetCode);
applyStylePreset(decision, pageType, scope, stylePreset);

with:

stylePreset = stylePresetRegistry.resolve(stylePresetCode);
decision.addReason("style preset " + stylePreset.getCode() + " applied visual tokens");

Then remove the unused applyStylePreset(...) method.

  • Step 5: Run tests to verify they pass

Run:

mvn -pl ruoyi-generator -Dtest=PageCompositionServiceStylePresetTest test

Expected: Tests run: 2, Failures: 0, Errors: 0.

Task 2: Remove Canvas Mapping From The Registry Contract

Files:

  • Modify: ruoyi-generator/src/test/java/com/ruoyi/generator/service/front/PageStylePresetRegistryTest.java

  • Modify: ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/PageStylePresetRegistry.java

  • Step 1: Write the failing registry contract test

Replace resolvesKnownPresetWithCanvasAndTokens with:

@Test
public void resolvesKnownPresetWithTokensOnly()
{
    PageStylePresetRegistry registry = new PageStylePresetRegistry();

    PageStylePresetRegistry.PageStylePreset preset = registry.resolve("card_portal");

    assertEquals("card_portal", preset.getCode());
    assertEquals("#167d83", preset.token("primary", ""));
    assertEquals("#f6c85b", preset.token("accent", ""));
    assertEquals("comfortable", preset.getDensity());
    assertTrue(registry.options().size() >= 4);
}

Replace unknownPresetFallsBackToBusinessClean with:

@Test
public void unknownPresetFallsBackToBusinessCleanTokens()
{
    PageStylePresetRegistry registry = new PageStylePresetRegistry();

    PageStylePresetRegistry.PageStylePreset preset = registry.resolve("not_real");

    assertEquals("business_clean", preset.getCode());
    assertEquals("#167d83", preset.token("primary", ""));
    assertEquals("1200px", preset.token("contentWidth", ""));
}
  • Step 2: Run registry test before implementation

Run:

mvn -pl ruoyi-generator -Dtest=PageStylePresetRegistryTest test

Expected: test compilation fails after removing frontend/admin canvas assertions from tests only if production still exposes unused API is not a compile failure; if tests pass immediately, continue with the cleanup as refactor under the Task 1 green state.

  • Step 3: Remove registry canvas API and definitions

In PageStylePresetRegistry, remove:

private final Map<String, String> frontendCanvases = new LinkedHashMap<String, String>();
private final Map<String, String> adminCanvases = new LinkedHashMap<String, String>();

Remove all .frontend(...) and .admin(...) calls from preset definitions. Remove the private builder methods frontend(...) and admin(...). Remove public methods frontendCanvas(...) and adminCanvas(...).

  • Step 4: Run registry tests

Run:

mvn -pl ruoyi-generator -Dtest=PageStylePresetRegistryTest test

Expected: Tests run: 2, Failures: 0, Errors: 0.

Task 3: Final Verification

Files:

  • Test: ruoyi-generator/src/test/java/com/ruoyi/generator/service/front/PageCompositionServiceStylePresetTest.java

  • Test: ruoyi-generator/src/test/java/com/ruoyi/generator/service/front/PageStylePresetRegistryTest.java

  • Step 1: Run focused tests together

Run:

mvn -pl ruoyi-generator -Dtest=PageCompositionServiceStylePresetTest,PageStylePresetRegistryTest test

Expected: both test classes pass.

  • Step 2: Inspect diff for scope

Run:

git diff -- ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/PageCompositionService.java ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/PageStylePresetRegistry.java ruoyi-generator/src/test/java/com/ruoyi/generator/service/front/PageCompositionServiceStylePresetTest.java ruoyi-generator/src/test/java/com/ruoyi/generator/service/front/PageStylePresetRegistryTest.java

Expected: diff only changes style preset canvas coupling and corresponding tests.