@morya-ui/setup 0.3.5 → 0.3.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +119 -107
  3. package/bin/morya-ui-setup.js +14 -14
  4. package/catalog/skills.json +46 -46
  5. package/package.json +4 -3
  6. package/src/__tests__/mcp.test.mjs +141 -0
  7. package/src/cli.mjs +330 -312
  8. package/src/copy-template.mjs +78 -78
  9. package/src/fs-utils.mjs +24 -24
  10. package/src/install.mjs +134 -134
  11. package/src/mcp.mjs +220 -50
  12. package/src/package-json.mjs +30 -30
  13. package/src/skills.mjs +224 -223
  14. package/src/styles.mjs +119 -119
  15. package/template/.agents/skills/morya-ui-pages/SKILL.md +191 -188
  16. package/template/.agents/skills/morya-ui-pages/evals/evals.json +89 -89
  17. package/template/.agents/skills/morya-ui-pages/references/component-index.md +99 -99
  18. package/template/.agents/skills/morya-ui-pages/references/design-system.md +101 -101
  19. package/template/.agents/skills/morya-ui-pages/references/feedback.md +68 -68
  20. package/template/.agents/skills/morya-ui-pages/references/optional-companions.md +62 -62
  21. package/template/.agents/skills/morya-ui-pages/references/page-layouts.md +133 -133
  22. package/template/.agents/skills/morya-ui-pages/references/review-checklist.md +76 -63
  23. package/template/.agents/skills/morya-ui-pages/references/style-presets.md +68 -45
  24. package/template/.agents/skills/morya-ui-pages/references/surfaces.md +91 -91
  25. package/template/.agents/skills/morya-ui-pages/references/visual-craft.md +131 -129
  26. package/template/.cursor/rules/coding-style.mdc +41 -41
  27. package/template/.cursor/rules/component-usage.mdc +41 -41
  28. package/template/.cursor/rules/design-system.mdc +18 -17
  29. package/template/.cursor/rules/page-layout.mdc +97 -97
  30. package/template/AGENTS.md +33 -0
  31. package/template/DESIGN.md +81 -59
  32. package/template/scripts/check-raw-colors.mjs +74 -74
@@ -1,68 +1,68 @@
1
- # Message / Toast / MMessage
2
-
3
- **Default rule:** operation feedback uses the `message` API. Use `toast` only when you need a title plus detail, or an async / background notification feel.
4
-
5
- Authoritative selection + key API notes also live in MCP / skill decision **`feedback-choice`** ([decision-recipes.md](./decision-recipes.md)). Keep this file and that decision aligned.
6
-
7
- ## Three different things
8
-
9
- | Name | Shape | API | Typical use |
10
- | --- | --- | --- | --- |
11
- | Message service | Top-centered one-liner | `message.success('已保存')` | Most CRUD results |
12
- | Toast service | Corner notice with `summary` + optional `detail` | `toast.success({ summary, detail })` | Extra explanation, job results |
13
- | `MMessage` | Optional host for the `message` service | `<MMessage />` | Custom `appendTo` / placement only. Not an inline alert |
14
-
15
- ## Decision tree
16
-
17
- ```
18
- Need immediate feedback after a user action?
19
- ├─ No → maybe confirm dialog or field errorMessage only
20
- └─ Yes → must the error stay in the form until fixed?
21
- ├─ Yes → field invalid / errorMessage; form-level token alert (see login-page)
22
- └─ No → only one short line (no separate detail)?
23
- ├─ Yes → message.* ← default
24
- └─ No → summary + detail / async feel → toast.*
25
- ```
26
-
27
- ## Prefer `message`
28
-
29
- ```ts
30
- import { message } from 'morya-ui'
31
-
32
- message.success('已创建')
33
- message.info('已移入回收站')
34
- message.error('操作失败')
35
- ```
36
-
37
- ## Prefer `toast`
38
-
39
- ```ts
40
- import { toast } from 'morya-ui'
41
-
42
- toast.success({
43
- summary: '导入完成',
44
- detail: '成功 128 条,失败 2 条',
45
- })
46
- ```
47
-
48
- ## Prefer `<MMessage>` / form-level errors
49
-
50
- - Field validation: component `invalid` / `errorMessage` (preferred).
51
- - Form-level persistent errors (login/auth): token-styled `role="alert"` bar as in MCP `get_golden_page` `login-page`.
52
- - Note: `<MMessage>` today is primarily the **message service host** (`messages` / teleport). Do not invent a `severity` + default-slot Alert API unless docs add it.
53
-
54
- ```vue
55
- <p v-if="formError" class="form-alert" role="alert">{{ formError }}</p>
56
- ```
57
-
58
- ```css
59
- .form-alert {
60
- margin: 0 0 var(--m-space-4);
61
- padding: var(--m-space-3) var(--m-space-4);
62
- border: 1px solid color-mix(in srgb, var(--m-color-danger) 40%, var(--m-color-border));
63
- border-radius: var(--m-radius-md);
64
- background: color-mix(in srgb, var(--m-color-danger) 10%, var(--m-color-surface));
65
- color: var(--m-color-danger);
66
- }
67
- ```
68
-
1
+ # Message / Toast / MMessage
2
+
3
+ **Default rule:** operation feedback uses the `message` API. Use `toast` only when you need a title plus detail, or an async / background notification feel.
4
+
5
+ Authoritative selection + key API notes also live in MCP / skill decision **`feedback-choice`** ([decision-recipes.md](./decision-recipes.md)). Keep this file and that decision aligned.
6
+
7
+ ## Three different things
8
+
9
+ | Name | Shape | API | Typical use |
10
+ | --- | --- | --- | --- |
11
+ | Message service | Top-centered one-liner | `message.success('已保存')` | Most CRUD results |
12
+ | Toast service | Corner notice with `summary` + optional `detail` | `toast.success({ summary, detail })` | Extra explanation, job results |
13
+ | `MMessage` | Optional host for the `message` service | `<MMessage />` | Custom `appendTo` / placement only. Not an inline alert |
14
+
15
+ ## Decision tree
16
+
17
+ ```
18
+ Need immediate feedback after a user action?
19
+ ├─ No → maybe confirm dialog or field errorMessage only
20
+ └─ Yes → must the error stay in the form until fixed?
21
+ ├─ Yes → field invalid / errorMessage; form-level token alert (see login-page)
22
+ └─ No → only one short line (no separate detail)?
23
+ ├─ Yes → message.* ← default
24
+ └─ No → summary + detail / async feel → toast.*
25
+ ```
26
+
27
+ ## Prefer `message`
28
+
29
+ ```ts
30
+ import { message } from 'morya-ui'
31
+
32
+ message.success('已创建')
33
+ message.info('已移入回收站')
34
+ message.error('操作失败')
35
+ ```
36
+
37
+ ## Prefer `toast`
38
+
39
+ ```ts
40
+ import { toast } from 'morya-ui'
41
+
42
+ toast.success({
43
+ summary: '导入完成',
44
+ detail: '成功 128 条,失败 2 条',
45
+ })
46
+ ```
47
+
48
+ ## Prefer `<MMessage>` / form-level errors
49
+
50
+ - Field validation: component `invalid` / `errorMessage` (preferred).
51
+ - Form-level persistent errors (login/auth): token-styled `role="alert"` bar as in MCP `get_golden_page` `login-page`.
52
+ - Note: `<MMessage>` today is primarily the **message service host** (`messages` / teleport). Do not invent a `severity` + default-slot Alert API unless docs add it.
53
+
54
+ ```vue
55
+ <p v-if="formError" class="form-alert" role="alert">{{ formError }}</p>
56
+ ```
57
+
58
+ ```css
59
+ .form-alert {
60
+ margin: 0 0 var(--m-space-4);
61
+ padding: var(--m-space-3) var(--m-space-4);
62
+ border: 1px solid color-mix(in srgb, var(--m-color-danger) 40%, var(--m-color-border));
63
+ border-radius: var(--m-radius-md);
64
+ background: color-mix(in srgb, var(--m-color-danger) 10%, var(--m-color-surface));
65
+ color: var(--m-color-danger);
66
+ }
67
+ ```
68
+
@@ -1,62 +1,62 @@
1
- # Optional companions (craft bridge)
2
-
3
- `morya-ui-pages` is **standalone**: contract + page snippets / decision recipes + block-order checklists + [visual-craft.md](visual-craft.md) + [style-presets.md](style-presets.md) are enough. Golden pages are optional structure demos. **No named style-preset catalog.**
4
-
5
- Installed market skills are **soft upgrades** — never replace `M*` / `--m-*` / page-layout block order / MCP / the **user’s** style direction.
6
-
7
- ## Conflict rule (hard)
8
-
9
- **morya-ui-pages + DESIGN.md + MCP win.**
10
-
11
- Forbidden from any companion:
12
-
13
- - Second UI kit
14
- - Invented `M*` props or hex soup
15
- - Replacing Ops block-order shell with a marketing hero
16
- - Custom ARIA widgets replacing library overlays
17
- - **Unearned AI atmosphere** the user did not ask for (aurora, cream-serif-terracotta, dual neon, frosted glass, neumorph on dense tables)
18
- - Overriding an explicit user reference or description
19
-
20
- ## When to load
21
-
22
- | Need | Prefer companion | Else |
23
- | --- | --- | --- |
24
- | Express / brand POV | `frontend-design` | visual-craft design plan |
25
- | Named polish / audit / bolder / quieter | `impeccable` | visual-craft polish modes |
26
- | Mood keywords | `ui-ux-pro-max` (search only) | infer from prompt → `--m-*` |
27
- | a11y | `fixing-accessibility` | review-checklist |
28
- | Routine Ops | **none** | Ops polish + resolved direction |
29
-
30
- Load budget: max one visual companion; a11y may follow. If absent, do not ask to install mid-task.
31
-
32
- ## Frontend Design bridge
33
-
34
- 1. Ground subject / audience / job.
35
- 2. Resolve style direction first ([style-presets.md](style-presets.md)).
36
- 3. Short design plan; signature fits the **user’s** words.
37
- 4. Strip AI-default faces unless the user asked.
38
- 5. Remediate with `M*` + `--m-*`; flat shells by default.
39
-
40
- ## Impeccable bridge
41
-
42
- | User intent | Pass | Constraint |
43
- | --- | --- | --- |
44
- | 太平 / 大胆一点 | `bolder` | One signature inside current direction; ask before changing the whole face |
45
- | 太花 / 太像 AI | `quieter` | Strip unearned gradients / glow / glass |
46
- | 提交前 | `polish` | Ops polish + direction + a11y basics |
47
- | 文案 | `clarify` | Domain verbs |
48
- | 微交互 | `delight` | 1–2 moments; `useMotion` |
49
-
50
- **Brief wins.**
51
-
52
- ## Combined workflow
53
-
54
- ```text
55
- 1. Style direction → user reference/description → cues → ask if uncertain
56
- 2. Compose → recommend_page.suggestedSnippets / get_page_snippet + recommend_component
57
- 3. Optional structure → get_golden_page only for whole-page block-order check
58
- 4. Contract → get_component / validate_usage
59
- 5. Craft → visual-craft (flat shells by default)
60
- 6. Companion (opt.) → deepen inside the resolved direction
61
- 7. Gate → validate_usage + validate_page
62
- ```
1
+ # Optional companions (craft bridge)
2
+
3
+ `morya-ui-pages` is **standalone**: contract + page snippets / decision recipes + block-order checklists + [visual-craft.md](visual-craft.md) + [style-presets.md](style-presets.md) are enough. Golden pages are optional structure demos. **No named style-preset catalog.**
4
+
5
+ Installed market skills are **soft upgrades** — never replace `M*` / `--m-*` / page-layout block order / MCP / the **user’s** style direction.
6
+
7
+ ## Conflict rule (hard)
8
+
9
+ **morya-ui-pages + DESIGN.md + MCP win.**
10
+
11
+ Forbidden from any companion:
12
+
13
+ - Second UI kit
14
+ - Invented `M*` props or hex soup
15
+ - Replacing Ops block-order shell with a marketing hero
16
+ - Custom ARIA widgets replacing library overlays
17
+ - **Unearned AI atmosphere** the user did not ask for (aurora, cream-serif-terracotta, dual neon, frosted glass, neumorph on dense tables)
18
+ - Overriding an explicit user reference or description
19
+
20
+ ## When to load
21
+
22
+ | Need | Prefer companion | Else |
23
+ | --- | --- | --- |
24
+ | Express / brand POV | `frontend-design` | visual-craft design plan |
25
+ | Named polish / audit / bolder / quieter | `impeccable` | visual-craft polish modes |
26
+ | Mood keywords | `ui-ux-pro-max` (search only) | infer from prompt → `--m-*` |
27
+ | a11y | `fixing-accessibility` | review-checklist |
28
+ | Routine Ops | **none** | Ops polish + resolved direction |
29
+
30
+ Load budget: max one visual companion; a11y may follow. If absent, do not ask to install mid-task.
31
+
32
+ ## Frontend Design bridge
33
+
34
+ 1. Ground subject / audience / job.
35
+ 2. Resolve style direction first ([style-presets.md](style-presets.md)).
36
+ 3. Short design plan; signature fits the **user’s** words.
37
+ 4. Strip AI-default faces unless the user asked.
38
+ 5. Remediate with `M*` + `--m-*`; flat shells by default.
39
+
40
+ ## Impeccable bridge
41
+
42
+ | User intent | Pass | Constraint |
43
+ | --- | --- | --- |
44
+ | 太平 / 大胆一点 | `bolder` | One signature inside current direction; ask before changing the whole face |
45
+ | 太花 / 太像 AI | `quieter` | Strip unearned gradients / glow / glass |
46
+ | 提交前 | `polish` | Ops polish + direction + a11y basics |
47
+ | 文案 | `clarify` | Domain verbs |
48
+ | 微交互 | `delight` | 1–2 moments; `useMotion` |
49
+
50
+ **Brief wins.**
51
+
52
+ ## Combined workflow
53
+
54
+ ```text
55
+ 1. Style direction → user reference/description → cues → ask if uncertain
56
+ 2. Compose → recommend_page.suggestedSnippets / get_page_snippet + recommend_component
57
+ 3. Optional structure → get_golden_page only for whole-page block-order check
58
+ 4. Contract → get_component / validate_usage
59
+ 5. Craft → visual-craft (flat shells by default)
60
+ 6. Companion (opt.) → deepen inside the resolved direction
61
+ 7. Gate → validate_usage + validate_page
62
+ ```
@@ -1,133 +1,133 @@
1
- # Page layouts
2
-
3
- When generating a full page, pick a type and follow the **block-order checklist** below. Fill each block with MCP **`get_page_snippet`** / `recommend_page.suggestedSnippets` (composition-first). Optional: `get_golden_page` only to cross-check whole-page order or when the user asks to mirror a golden sample.
4
-
5
- Golden pages are **assembly demos / structure baselines**, not the default clone source. Do not add new craft variants (`list-page-*`); density / sider cues inform polish via style direction.
6
-
7
- | Type | Checklist below | Optional `get_golden_page` | Typical snippets |
8
- | --- | --- | --- | --- |
9
- | List | List page | `list-page` (`list-page-dense` / `list-page-rail` craft only) | `layout-app-shell`, `page-header-actions`, **`list-filters-stack`** (dense → `list-filters-dense`), `list-table`, `form-in-dialog`, `confirm-delete` |
10
- | Form (long / dedicated) | Form page | `form-page` | `page-content-form`, `form-header`, `form-body`, `form-actions` |
11
- | List create/edit dialog | List create/edit dialog | `form-in-dialog` | **`form-in-dialog`** (preferred) |
12
- | Detail | Detail page | `detail-page` | `detail-toolbar`, `form-in-dialog` |
13
- | Dashboard | Dashboard | `dashboard-page` | `dashboard-kpi-grid`, `dashboard-chart-card`, `dashboard-recent-table` |
14
- | Login | — (see [surfaces.md](surfaces.md)) | `login-page` | **`auth-split-shell`** |
15
- | Landing | — (see [surfaces.md](surfaces.md)) | `landing-page` | — |
16
- | Empty | — | `empty-state` | **`empty-block`** |
17
- | Result / 403 / terminal | — | `result-page` | **`result-block`** |
18
- | Settings | Settings page | `settings-page` | `form-header`, `form-body`, `form-actions` |
19
- | Wizard | Wizard | `wizard-form` | **`wizard-steps`** |
20
-
21
- Via MCP: `recommend_page({ style? })` → use **`suggestedSnippets`** + `recommend_component` / `get_page_snippet`; apply `styleDirection` (user reference/description — no preset catalog). Call `get_golden_page` only when needed for block-order check. Style: `get_style_direction`.
22
-
23
- **List craft variants** share the same block order; only density / chrome / copy change. Prefer style-direction cues over inventing new golden ids.
24
-
25
- ## Product defaults
26
-
27
- - **Short create/edit** (about ≤8 fields, single section): same-page `MDialog` + `MForm` — snippet `form-in-dialog`; do not invent a new route form for every entity.
28
- - **Long / multi-section / wizard**: dedicated form page (`form-page`) or `MDrawer` (`form-in-drawer`).
29
- - **One-line success/error**: `message` API; title + detail or async notify → `toast` (see [feedback.md](feedback.md)).
30
-
31
- ## List page — block order
32
-
33
- 1. `MLayout fillViewport` + optional `MLayoutSider bordered` → snippet `layout-app-shell`
34
- 2. Sider `MMenu` (**every item has `icon`**)
35
- 3. `MLayoutHeader` → `MBreadcrumb`
36
- 4. `MLayoutContent` → `MPageContent` (**add `fill` only when the height rule below applies**) → `page-content-list`
37
- 5. `MPageHeader` — page title + `#actions` primary (**one** filled primary in viewport) → `page-header-actions`
38
- 6. `MPageFilters` — 默认 **`list-filters-stack`**(`#actions` 查询/重置 + collapsible「高级筛选/收起」chevron + `#advanced` + FilterChips);条件少无高级区用 `list-filters`;dense craft 用 `list-filters-dense`
39
- 7. Optional `MPageFilterChips` — 已含在 `list-filters-stack`;单独增量用 `list-filter-chips`
40
- 8. Optional `MPageToolbar` — batch actions only → `list-toolbar` / `list-batch-toolbar`
41
- 9. `MTable` directly in content; status → `MStatus`; `#empty` → `MEmpty` → `list-table` + `list-status-dot` + `empty-block`
42
- 10. Pagination via `MTable paginator` or sibling `MPagination`
43
- 11. Short create/edit → same-page `MDialog` + `MForm` → **`form-in-dialog`**; delete → **`confirm-delete`**
44
-
45
- ### List height — decide, don’t always fill
46
-
47
- Use **`MPageContent fill` + `MTable fill paginator`** only when **most** of these are true:
48
-
49
- - The screen is a **full-viewport admin list** (`MLayout fillViewport`) whose **main job** is browsing one data table
50
- - Leaving the table content-sized would leave a large empty band with pagination floating mid-page
51
- - You want **table-body scroll** and pagination pinned to the **bottom of the page**
52
-
53
- Skip `fill` when any of these apply:
54
-
55
- - Embedded / secondary tables (dashboard “recent”, detail related lists, cards)
56
- - Short or sparse pages where a content-sized table looks fine
57
- - The page should **scroll as a whole document** (long filters + notes + table)
58
- - Tables inside `MDialog` / `MDrawer`
59
- - Mixed layouts where the table is not the sole middle region
60
-
61
- Do not invent `min-height` / `calc` hacks when `fill` is the right tool — and do not force `fill` when it isn’t.
62
-
63
- Craft: [visual-craft.md](visual-craft.md) § Ops polish.
64
-
65
- ## Form page — block order
66
-
67
- 1. `MLayout fillViewport` → `MLayoutHeader` → `MBreadcrumb`
68
- 2. `MPageContent width="narrow"` → `page-content-form`
69
- 3. `MPageHeader` (title + description) → `form-header`
70
- 4. `MPageSection variant="form"` → `MForm` → `form-body`
71
- 5. `MPageSection variant="actions"` — save (`primary`) + cancel (`secondary`) → `form-actions`
72
-
73
- ## Dashboard — block order
74
-
75
- 1. `MLayout fillViewport` → `MLayoutHeader` → `MBreadcrumb`
76
- 2. `MPageContent density="spacious"` → `MPageHeader` (title + short domain description when useful)
77
- 3. KPI row: `MGrid` + `MPageStat` (4 columns or responsive) — `dashboard-kpi-grid`
78
- 4. Main split: `MCard shadow="always"` + `MEmpty` (chart pending) and/or recent `MTable` — `dashboard-chart-card` / `dashboard-recent-table`
79
-
80
- Craft: spacious density + Ops polish; do not turn the first viewport into a marketing hero.
81
-
82
- ## Composition standards
83
-
84
- | Topic | Prefer | Usually avoid |
85
- | --- | --- | --- |
86
- | Shell | `MLayout fillViewport` + `MPageContent` | Padding on `MLayoutContent` |
87
- | Sections | `MPageFilters` / `MPageToolbar` / `MPageSection` | Custom `.page-*`; extra `MCard` wrappers |
88
- | List table | `MTable` in `MPageContent`; add `fill` only when the height rule applies | Border card solely to wrap the table; forcing `fill` on every table |
89
- | Spacing | `MSpace` / `MFlex` for peers; page gap from `MPageContent` | Nested padded divs stacking gaps |
90
- | Scroll | Full-viewport main lists may use table-body scroll via `fill`; otherwise layout / local `MScrollbar` | Forcing overflow on every content slot; stacked page + table scrollbars without reason |
91
- | Color | `--m-*` | Page-level hex / rgb |
92
- | Feedback | One-line → `message`; danger → confirm dialog | Toast for a single short string |
93
- | A11y | Labels + icon `aria-label` | Unlabeled icon controls |
94
-
95
- Inline style is acceptable for control widths (e.g. filter `width: 14rem`).
96
-
97
- ## Detail page — block order
98
-
99
- 1. Same admin chrome as list (breadcrumb → `MPageContent`)
100
- 2. `MPageHeader` — title, `MStatus` in `#actions`, primary/secondary/danger → `detail-toolbar`
101
- 3. Summary `MPageSection` + property `MCard` (definition grid with `--m-*` only)
102
- 4. Related data: `MCard` + `MTable` / tabs / timeline
103
- 5. Short edit → `form-in-dialog`; long edit → form page / `form-in-drawer`
104
-
105
- ## List create/edit dialog — block order
106
-
107
- 1. Stay on the list page (`MPageHeader` + filters/table; optional batch `MPageToolbar`)
108
- 2. `MDialog` ~`28–36rem` + `MForm` fields → snippet **`form-in-dialog`**
109
- 3. Actions in Dialog `#footer` (cancel secondary/text + save primary)
110
- 4. Success → `message.success` one-liner, then close
111
-
112
- ## Settings page — block order
113
-
114
- 1. Admin chrome + `MPageContent width="narrow"`
115
- 2. `MPageHeader` (title + short description)
116
- 3. `MTabs` with **`v-model` + `:tabs`** (not `:items` / `:value`)
117
- 4. Per tab: `MPageSection variant="form"` + `MForm` + save in `variant="actions"`
118
- 5. Dangerous zone last: `severity="danger"` + confirm
119
-
120
- ## Wizard — block order
121
-
122
- 1. Narrow `MPageContent` + `MPageHeader`
123
- 2. `MStepper v-model` + **`:steps`** (not `:items`) → snippet **`wizard-steps`**
124
- 3. One form/job per step; sticky `上一步` / `下一步` / `创建`
125
- 4. Success → `result-block` / `MResult`
126
-
127
- ## Hybrids
128
-
129
- - List + row edit dialog → `form-in-dialog` snippet on the list.
130
- - List + side detail → list + `form-in-drawer`.
131
- - Resource detail → detail checklist + `detail-toolbar`.
132
- - Settings without admin chrome → still use `MPageContent` + `MPageSection`; omit sider only if the host app already provides chrome.
133
- - Non-Ops surfaces (auth, landing, empty, wizard) → [surfaces.md](surfaces.md) + matching snippets, not Ops list chrome.
1
+ # Page layouts
2
+
3
+ When generating a full page, pick a type and follow the **block-order checklist** below. Fill each block with MCP **`get_page_snippet`** / `recommend_page.suggestedSnippets` (composition-first). Optional: `get_golden_page` only to cross-check whole-page order or when the user asks to mirror a golden sample.
4
+
5
+ Golden pages are **assembly demos / structure baselines**, not the default clone source. Do not add new craft variants (`list-page-*`); density / sider cues inform polish via style direction.
6
+
7
+ | Type | Checklist below | Optional `get_golden_page` | Typical snippets |
8
+ | --- | --- | --- | --- |
9
+ | List | List page | `list-page` (`list-page-dense` / `list-page-rail` craft only) | `layout-app-shell`, `page-header-actions`, **`list-filters-stack`** (dense → `list-filters-dense`), `list-table`, `form-in-dialog`, `confirm-delete` |
10
+ | Form (long / dedicated) | Form page | `form-page` | `page-content-form`, `form-header`, `form-body`, `form-actions` |
11
+ | List create/edit dialog | List create/edit dialog | `form-in-dialog` | **`form-in-dialog`** (preferred) |
12
+ | Detail | Detail page | `detail-page` | `detail-toolbar`, `form-in-dialog` |
13
+ | Dashboard | Dashboard | `dashboard-page` | `dashboard-kpi-grid`, `dashboard-chart-card`, `dashboard-recent-table` |
14
+ | Login | — (see [surfaces.md](surfaces.md)) | `login-page` | **`auth-split-shell`** |
15
+ | Landing | — (see [surfaces.md](surfaces.md)) | `landing-page` | — |
16
+ | Empty | — | `empty-state` | **`empty-block`** |
17
+ | Result / 403 / terminal | — | `result-page` | **`result-block`** |
18
+ | Settings | Settings page | `settings-page` | `form-header`, `form-body`, `form-actions` |
19
+ | Wizard | Wizard | `wizard-form` | **`wizard-steps`** |
20
+
21
+ Via MCP: `recommend_page({ style? })` → use **`suggestedSnippets`** + `recommend_component` / `get_page_snippet`; apply `styleDirection` (user reference/description — no preset catalog). Call `get_golden_page` only when needed for block-order check. Style: `get_style_direction`.
22
+
23
+ **List craft variants** share the same block order; only density / chrome / copy change. Prefer style-direction cues over inventing new golden ids.
24
+
25
+ ## Product defaults
26
+
27
+ - **Short create/edit** (about ≤8 fields, single section): same-page `MDialog` + `MForm` — snippet `form-in-dialog`; do not invent a new route form for every entity.
28
+ - **Long / multi-section / wizard**: dedicated form page (`form-page`) or `MDrawer` (`form-in-drawer`).
29
+ - **One-line success/error**: `message` API; title + detail or async notify → `toast` (see [feedback.md](feedback.md)).
30
+
31
+ ## List page — block order
32
+
33
+ 1. `MLayout fillViewport` + optional `MLayoutSider bordered` → snippet `layout-app-shell`
34
+ 2. Sider `MMenu` (**every item has `icon`**)
35
+ 3. `MLayoutHeader` → `MBreadcrumb`
36
+ 4. `MLayoutContent` → `MPageContent` (**add `fill` only when the height rule below applies**) → `page-content-list`
37
+ 5. `MPageHeader` — page title + `#actions` primary (**one** filled primary in viewport) → `page-header-actions`
38
+ 6. `MPageFilters` — 默认 **`list-filters-stack`**(`#actions` 查询/重置 + collapsible「高级筛选/收起」chevron + `#advanced` + FilterChips);条件少无高级区用 `list-filters`;dense craft 用 `list-filters-dense`
39
+ 7. Optional `MPageFilterChips` — 已含在 `list-filters-stack`;单独增量用 `list-filter-chips`
40
+ 8. Optional `MPageToolbar` — batch actions only → `list-toolbar` / `list-batch-toolbar`
41
+ 9. `MTable` directly in content; status → `MStatus`; `#empty` → `MEmpty` → `list-table` + `list-status-dot` + `empty-block`
42
+ 10. Pagination via `MTable paginator` or sibling `MPagination`
43
+ 11. Short create/edit → same-page `MDialog` + `MForm` → **`form-in-dialog`**; delete → **`confirm-delete`**
44
+
45
+ ### List height — decide, don’t always fill
46
+
47
+ Use **`MPageContent fill` + `MTable fill paginator`** only when **most** of these are true:
48
+
49
+ - The screen is a **full-viewport admin list** (`MLayout fillViewport`) whose **main job** is browsing one data table
50
+ - Leaving the table content-sized would leave a large empty band with pagination floating mid-page
51
+ - You want **table-body scroll** and pagination pinned to the **bottom of the page**
52
+
53
+ Skip `fill` when any of these apply:
54
+
55
+ - Embedded / secondary tables (dashboard “recent”, detail related lists, cards)
56
+ - Short or sparse pages where a content-sized table looks fine
57
+ - The page should **scroll as a whole document** (long filters + notes + table)
58
+ - Tables inside `MDialog` / `MDrawer`
59
+ - Mixed layouts where the table is not the sole middle region
60
+
61
+ Do not invent `min-height` / `calc` hacks when `fill` is the right tool — and do not force `fill` when it isn’t.
62
+
63
+ Craft: [visual-craft.md](visual-craft.md) § Ops polish.
64
+
65
+ ## Form page — block order
66
+
67
+ 1. `MLayout fillViewport` → `MLayoutHeader` → `MBreadcrumb`
68
+ 2. `MPageContent width="narrow"` → `page-content-form`
69
+ 3. `MPageHeader` (title + description) → `form-header`
70
+ 4. `MPageSection variant="form"` → `MForm` → `form-body`
71
+ 5. `MPageSection variant="actions"` — save (`primary`) + cancel (`secondary`) → `form-actions`
72
+
73
+ ## Dashboard — block order
74
+
75
+ 1. `MLayout fillViewport` → `MLayoutHeader` → `MBreadcrumb`
76
+ 2. `MPageContent density="spacious"` → `MPageHeader` (title + short domain description when useful)
77
+ 3. KPI row: `MGrid` + `MPageStat` (4 columns or responsive) — `dashboard-kpi-grid`
78
+ 4. Main split: `MCard shadow="always"` + `MEmpty` (chart pending) and/or recent `MTable` — `dashboard-chart-card` / `dashboard-recent-table`
79
+
80
+ Craft: spacious density + Ops polish; do not turn the first viewport into a marketing hero.
81
+
82
+ ## Composition standards
83
+
84
+ | Topic | Prefer | Usually avoid |
85
+ | --- | --- | --- |
86
+ | Shell | `MLayout fillViewport` + `MPageContent` | Padding on `MLayoutContent` |
87
+ | Sections | `MPageFilters` / `MPageToolbar` / `MPageSection` | Custom `.page-*`; extra `MCard` wrappers |
88
+ | List table | `MTable` in `MPageContent`; add `fill` only when the height rule applies | Border card solely to wrap the table; forcing `fill` on every table |
89
+ | Spacing | `MSpace` / `MFlex` for peers; page gap from `MPageContent` | Nested padded divs stacking gaps |
90
+ | Scroll | Full-viewport main lists may use table-body scroll via `fill`; otherwise layout / local `MScrollbar` | Forcing overflow on every content slot; stacked page + table scrollbars without reason |
91
+ | Color | `--m-*` | Page-level hex / rgb |
92
+ | Feedback | One-line → `message`; danger → confirm dialog | Toast for a single short string |
93
+ | A11y | Labels + icon `aria-label` | Unlabeled icon controls |
94
+
95
+ Inline style is acceptable for control widths (e.g. filter `width: 14rem`).
96
+
97
+ ## Detail page — block order
98
+
99
+ 1. Same admin chrome as list (breadcrumb → `MPageContent`)
100
+ 2. `MPageHeader` — title, `MStatus` in `#actions`, primary/secondary/danger → `detail-toolbar`
101
+ 3. Summary `MPageSection` + property `MCard` (definition grid with `--m-*` only)
102
+ 4. Related data: `MCard` + `MTable` / tabs / timeline
103
+ 5. Short edit → `form-in-dialog`; long edit → form page / `form-in-drawer`
104
+
105
+ ## List create/edit dialog — block order
106
+
107
+ 1. Stay on the list page (`MPageHeader` + filters/table; optional batch `MPageToolbar`)
108
+ 2. `MDialog` ~`28–36rem` + `MForm` fields → snippet **`form-in-dialog`**
109
+ 3. Actions in Dialog `#footer` (cancel secondary/text + save primary)
110
+ 4. Success → `message.success` one-liner, then close
111
+
112
+ ## Settings page — block order
113
+
114
+ 1. Admin chrome + `MPageContent width="narrow"`
115
+ 2. `MPageHeader` (title + short description)
116
+ 3. `MTabs` with **`v-model` + `:tabs`** (not `:items` / `:value`)
117
+ 4. Per tab: `MPageSection variant="form"` + `MForm` + save in `variant="actions"`
118
+ 5. Dangerous zone last: `severity="danger"` + confirm
119
+
120
+ ## Wizard — block order
121
+
122
+ 1. Narrow `MPageContent` + `MPageHeader`
123
+ 2. `MStepper v-model` + **`:steps`** (not `:items`) → snippet **`wizard-steps`**
124
+ 3. One form/job per step; sticky `上一步` / `下一步` / `创建`
125
+ 4. Success → `result-block` / `MResult`
126
+
127
+ ## Hybrids
128
+
129
+ - List + row edit dialog → `form-in-dialog` snippet on the list.
130
+ - List + side detail → list + `form-in-drawer`.
131
+ - Resource detail → detail checklist + `detail-toolbar`.
132
+ - Settings without admin chrome → still use `MPageContent` + `MPageSection`; omit sider only if the host app already provides chrome.
133
+ - Non-Ops surfaces (auth, landing, empty, wizard) → [surfaces.md](surfaces.md) + matching snippets, not Ops list chrome.