@morya-ui/setup 0.3.3 → 0.3.5

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 (31) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +107 -103
  3. package/bin/morya-ui-setup.js +14 -14
  4. package/catalog/skills.json +46 -46
  5. package/package.json +1 -1
  6. package/src/cli.mjs +312 -335
  7. package/src/copy-template.mjs +78 -78
  8. package/src/fs-utils.mjs +24 -24
  9. package/src/install.mjs +134 -63
  10. package/src/mcp.mjs +50 -50
  11. package/src/package-json.mjs +30 -30
  12. package/src/skills.mjs +223 -223
  13. package/src/styles.mjs +119 -119
  14. package/template/.agents/skills/morya-ui-pages/SKILL.md +188 -164
  15. package/template/.agents/skills/morya-ui-pages/evals/evals.json +89 -89
  16. package/template/.agents/skills/morya-ui-pages/references/component-index.md +99 -99
  17. package/template/.agents/skills/morya-ui-pages/references/decision-recipes.md +104 -5
  18. package/template/.agents/skills/morya-ui-pages/references/design-system.md +101 -100
  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 -34
  21. package/template/.agents/skills/morya-ui-pages/references/page-layouts.md +133 -119
  22. package/template/.agents/skills/morya-ui-pages/references/review-checklist.md +63 -61
  23. package/template/.agents/skills/morya-ui-pages/references/style-presets.md +45 -0
  24. package/template/.agents/skills/morya-ui-pages/references/surfaces.md +91 -89
  25. package/template/.agents/skills/morya-ui-pages/references/visual-craft.md +129 -196
  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 +17 -17
  29. package/template/.cursor/rules/page-layout.mdc +97 -78
  30. package/template/DESIGN.md +59 -59
  31. package/template/scripts/check-raw-colors.mjs +74 -74
@@ -1,89 +1,89 @@
1
- {
2
- "skill_name": "morya-ui-pages",
3
- "evals": [
4
- {
5
- "id": 1,
6
- "prompt": "我们内部教务系统用 Vue3 + morya-ui。请做一个「课程列表」后台页:按课程名搜索、按开课状态(全部/开课中/已结课)筛选;表格列:名称、状态、学分、更新时间;行内「编辑」进抽屉表单,「删除」要二次确认;右上角「新建课程」。保存/删除成功只要一句话提示。输出单个 Vue SFC,结构对齐列表黄金样例,并做 Ops 精致化(侧栏图标、状态用 MStatus、空态用 MEmpty、行操作不要一排实心按钮)。",
7
- "expected_output": "Ops list: MLayout/MPageHeader/MPageFilters/MTable rows, optional batch MPageToolbar, MSelect status, MDrawer edit, MConfirmDialog delete, message not toast, MStatus for status, MEmpty in #empty, menu icons, text/small row actions, craft pass applied, no second UI kit.",
8
- "files": []
9
- },
10
- {
11
- "id": 2,
12
- "prompt": "同一个 morya-ui 项目里,生成「新建员工」独立表单页:姓名、工作邮箱、部门(下拉)、入职日期;窄栏;页头有标题和一句说明;底栏保存(primary)/取消(secondary)。不要做成营销落地页,不要用 Toast 提示「已保存」。输出单个 Vue SFC。",
13
- "expected_output": "Ops form golden: narrow MPageContent, MPageHeader, MPageSection form/actions, MForm + MSelect/MDatePicker, message for success if shown, one primary, no landing hero.",
14
- "files": []
15
- },
16
- {
17
- "id": 3,
18
- "prompt": "运营后台首页仪表盘:四个 KPI(今日订单、待处理、转化率、退款率)、中间一块图表占位、右侧或下方「最近告警」表格(级别、内容、时间)。Vue3 + morya-ui,可先用静态假数据;告警级别可用 Tag,状态用 MStatus。",
19
- "expected_output": "Dashboard: MPageStat grid with domain labels, MCard shadow=always + MEmpty chart pending, recent MTable with MStatus, MLayout shell, --m-* only, spacious density.",
20
- "files": []
21
- },
22
- {
23
- "id": 4,
24
- "prompt": "给「青禾书房」这个独立书店品牌做登录页:左品牌、右表单(邮箱+密码+登录)。要有一点品牌感(token 氛围即可),但控件必须用 morya-ui;登录失败用表单区常驻错误(字段 errorMessage 或 token role=alert),不要一闪而过的 Toast,也不要把 MMessage 当成内嵌 Alert。输出单个 Vue SFC。",
25
- "expected_output": "Account+craft: split shell, MForm/MInputPassword/MButton, token role=alert or field error for failure, brand panel with --m-* color-mix, no MMessage severity alert, no second UI kit.",
26
- "files": []
27
- },
28
- {
29
- "id": 5,
30
- "prompt": "课程列表在零数据时太空了。请设计一个空状态区块(可嵌在列表页内容区):说明还没有课程、引导「创建第一门课程」;视觉克制,用 morya-ui 默认空态即可,不要自定义 dashed 框或径向光晕。只要空状态相关模板片段或带空状态的列表 SFC 均可。",
31
- "expected_output": "Flow empty: MPageHeader + MEmpty + next-action MButton, short copy, no custom dashed/radial shell, fits list content slot.",
32
- "files": []
33
- },
34
- {
35
- "id": 6,
36
- "prompt": "为「流水线 CI」产品写一个营销落地首页(不是后台):首屏只有品牌名、一句主标题、一句副文、一组 CTA;下面再分「为何选择」「能力」「客户」三节。技术实现用 Vue3 + morya-ui 组件做按钮/标签/折叠 FAQ;颜色走 --m-*,避免紫渐变和奶油衬线陶土那套 AI 默认脸。可有 1–2 个微动效,强度跟 useMotion / data-m-motion。输出单个 Vue SFC。",
37
- "expected_output": "Express landing: single-job hero, MButton CTAs, sections with one job each, MAccordion FAQ optional, no purple/cream-terracotta defaults, no admin MPageFilters shell, motion gated by useMotion / data-m-motion.",
38
- "files": []
39
- },
40
- {
41
- "id": 7,
42
- "prompt": "做一个三步「创建工作空间」向导:1 名称与地区 2 邀请成员(邮箱标签)3 确认。用 morya-ui 的 Stepper + Form;每步一个主任务;最后提交成功进入结果页(查看工作空间 / 返回)。输出一个或两个 SFC。",
43
- "expected_output": "Flow wizard: wizard-form golden — MStepper :steps, per-step MForm, MInputTags invites, clear next/back/submit, message success, validate_usage clean.",
44
- "files": []
45
- },
46
- {
47
- "id": 8,
48
- "prompt": "用户点了删除项目但权限不足:做一张「无权限」系统页(或全页占位),说明原因,并提供返回上一页、联系管理员。用 morya-ui,文案直接别玩梗。",
49
- "expected_output": "System surface: result-page golden — MResult status=403, #footer escape actions, no jokey 404 essay, on-token, validate_usage clean.",
50
- "files": []
51
- },
52
- {
53
- "id": 9,
54
- "prompt": "把上面的课程列表再 polish 一轮:去掉多余实心按钮、保证只有一个主按钮、表格状态改成 MStatus、补上 MEmpty。不要改成营销页。",
55
- "expected_output": "Ops quieter polish: one primary, MStatus, MEmpty, text row actions, still list golden structure.",
56
- "files": []
57
- },
58
- {
59
- "id": 10,
60
- "prompt": "给「用户管理」做资源详情页:面包屑、标题旁启用状态、编辑/返回/删除;摘要标签;基本信息属性网格;下方近期活动表。Vue3 + morya-ui,对齐详情黄金样例,不要做成落地页。",
61
- "expected_output": "Ops detail: MPageHeader + MStatus, property MCard, related MTable rows, --m-* only, no marketing hero.",
62
- "files": []
63
- },
64
- {
65
- "id": 11,
66
- "prompt": "用户列表页上「新建/编辑」不要另开路由:同页 MDialog(约 32rem)里放短表单(姓名、邮箱、角色),页脚取消/保存;保存成功用 message 一句话。输出单个 Vue SFC。",
67
- "expected_output": "form-in-dialog: list stays, MDialog + MForm + #footer, message.success not toast string, MTable rows.",
68
- "files": []
69
- },
70
- {
71
- "id": 12,
72
- "prompt": "做一个用户列表表格页:列姓名、角色、状态。状态列必须用 MStatus;行数据绑定用 rows(不要写 data prop);空表用 #empty + MEmpty。Vue3 + morya-ui,输出单个 SFC。",
73
- "expected_output": "Prop accuracy: MTable columns+rows (not :data), #cell or Status for status, #empty+MEmpty, validate_usage clean.",
74
- "files": []
75
- },
76
- {
77
- "id": 13,
78
- "prompt": "列表行删除:点删除后用 MConfirmDialog(危险确认),确认后 message.success('已删除')。不要用 toast,也不要手写 Dialog 当确认框。输出片段或 SFC 均可。",
79
- "expected_output": "confirm-choice + feedback-choice: MConfirmDialog v-model header/message acceptSeverity=danger @accept, message.success not toast, no hand Dialog confirm.",
80
- "files": []
81
- },
82
- {
83
- "id": 14,
84
- "prompt": "短新建弹窗:MDialog v-model + header + #footer(取消 secondary、保存 primary);表单字段 fluid。保存成功 message 一句话。不要用 v-model:visible。",
85
- "expected_output": "form-surface Dialog recipe: v-model not visible, #footer actions, fluid fields, message.success.",
86
- "files": []
87
- }
88
- ]
89
- }
1
+ {
2
+ "skill_name": "morya-ui-pages",
3
+ "evals": [
4
+ {
5
+ "id": 1,
6
+ "prompt": "我们内部教务系统用 Vue3 + morya-ui。请做一个「课程列表」后台页:按课程名搜索、按开课状态(全部/开课中/已结课)筛选;表格列:名称、状态、学分、更新时间;行内「编辑」进抽屉表单,「删除」要二次确认;右上角「新建课程」。保存/删除成功只要一句话提示。输出单个 Vue SFC,用 list-filters-stack / list-table / form-in-drawer / confirm-delete / page-header-actions 等 snippets 拼装并对齐 page-layouts 块顺序,并做 Ops 精致化(侧栏图标、状态用 MStatus、空态用 MEmpty、行操作不要一排实心按钮)。",
7
+ "expected_output": "Ops list composition-first: MLayout/MPageHeader/list-filters-stack (collapsible+#advanced+FilterChips)/MTable rows, page-header-actions one primary, form-in-drawer edit, confirm-delete, message not toast, MStatus, MEmpty in #empty, menu icons, text/small row actions, craft pass, no second UI kit; do not require whole golden-page clone.",
8
+ "files": []
9
+ },
10
+ {
11
+ "id": 2,
12
+ "prompt": "同一个 morya-ui 项目里,生成「新建员工」独立表单页:姓名、工作邮箱、部门(下拉)、入职日期;窄栏;页头有标题和一句说明;底栏保存(primary)/取消(secondary)。不要做成营销落地页,不要用 Toast 提示「已保存」。输出单个 Vue SFC。",
13
+ "expected_output": "Ops form snippets: page-content-form + form-header/body/actions, narrow MPageContent, MForm + MSelect/MDatePicker, message for success if shown, one primary, no landing hero.",
14
+ "files": []
15
+ },
16
+ {
17
+ "id": 3,
18
+ "prompt": "运营后台首页仪表盘:四个 KPI(今日订单、待处理、转化率、退款率)、中间一块图表占位、右侧或下方「最近告警」表格(级别、内容、时间)。Vue3 + morya-ui,可先用静态假数据;告警级别可用 Tag,状态用 MStatus。",
19
+ "expected_output": "Dashboard snippets: dashboard-kpi-grid, dashboard-chart-card, dashboard-recent-table, MLayout shell, --m-* only, spacious density.",
20
+ "files": []
21
+ },
22
+ {
23
+ "id": 4,
24
+ "prompt": "给「青禾书房」这个独立书店品牌做登录页:左品牌、右表单(邮箱+密码+登录)。要有一点品牌感(token 氛围即可),但控件必须用 morya-ui;登录失败用表单区常驻错误(字段 errorMessage 或 token role=alert),不要一闪而过的 Toast,也不要把 MMessage 当成内嵌 Alert。输出单个 Vue SFC。",
25
+ "expected_output": "Account+craft via auth-split-shell: split shell, MForm/MInputPassword/MButton, token role=alert or field error for failure, brand panel with flat --m-* color-mix (no stacked radial+linear aurora), no MMessage severity alert, no second UI kit.",
26
+ "files": []
27
+ },
28
+ {
29
+ "id": 5,
30
+ "prompt": "课程列表在零数据时太空了。请设计一个空状态区块(可嵌在列表页内容区):说明还没有课程、引导「创建第一门课程」;视觉克制,用 morya-ui 默认空态即可,不要自定义 dashed 框或径向光晕。只要空状态相关模板片段或带空状态的列表 SFC 均可。",
31
+ "expected_output": "Flow empty via empty-block: MEmpty + next-action MButton, short copy, no custom dashed/radial shell, fits list content slot.",
32
+ "files": []
33
+ },
34
+ {
35
+ "id": 6,
36
+ "prompt": "为「流水线 CI」产品写一个营销落地首页(不是后台):首屏只有品牌名、一句主标题、一句副文、一组 CTA;下面再分「为何选择」「能力」「客户」三节。技术实现用 Vue3 + morya-ui 组件做按钮/标签/折叠 FAQ;颜色走 --m-*,风格偏简洁扁平(不要紫渐变 aurora、奶油衬线陶土、霓虹毛玻璃)。可有 1–2 个微动效,强度跟 useMotion / data-m-motion。输出单个 Vue SFC。",
37
+ "expected_output": "Express landing: single-job hero, MButton CTAs, sections with one job each, MAccordion FAQ optional, flat/simple surfaces (no purple aurora / cream-terracotta / unsolicited glass-neon), no admin MPageFilters shell, motion gated by useMotion / data-m-motion.",
38
+ "files": []
39
+ },
40
+ {
41
+ "id": 7,
42
+ "prompt": "做一个三步「创建工作空间」向导:1 名称与地区 2 邀请成员(邮箱标签)3 确认。用 morya-ui 的 Stepper + Form;每步一个主任务;最后提交成功进入结果页(查看工作空间 / 返回)。输出一个或两个 SFC。",
43
+ "expected_output": "Flow wizard via wizard-steps (+ result-block): MStepper :steps, per-step MForm, MInputTags invites, clear next/back/submit, message success, validate_usage clean.",
44
+ "files": []
45
+ },
46
+ {
47
+ "id": 8,
48
+ "prompt": "用户点了删除项目但权限不足:做一张「无权限」系统页(或全页占位),说明原因,并提供返回上一页、联系管理员。用 morya-ui,文案直接别玩梗。",
49
+ "expected_output": "System surface via result-block: MResult status=403, #footer escape actions, no jokey 404 essay, on-token, validate_usage clean.",
50
+ "files": []
51
+ },
52
+ {
53
+ "id": 9,
54
+ "prompt": "把上面的课程列表再 polish 一轮:去掉多余实心按钮、保证只有一个主按钮、表格状态改成 MStatus、补上 MEmpty。不要改成营销页。",
55
+ "expected_output": "Ops quieter polish: one primary, MStatus, MEmpty, text row actions, still list block-order / snippets structure.",
56
+ "files": []
57
+ },
58
+ {
59
+ "id": 10,
60
+ "prompt": "给「用户管理」做资源详情页:面包屑、标题旁启用状态、编辑/返回/删除;摘要标签;基本信息属性网格;下方近期活动表。Vue3 + morya-ui,按 detail 块顺序 + detail-toolbar 拼装,不要做成落地页。",
61
+ "expected_output": "Ops detail composition: detail-toolbar MPageHeader + MStatus, property MCard, related MTable rows, --m-* only, no marketing hero.",
62
+ "files": []
63
+ },
64
+ {
65
+ "id": 11,
66
+ "prompt": "用户列表页上「新建/编辑」不要另开路由:同页 MDialog(约 32rem)里放短表单(姓名、邮箱、角色),页脚取消/保存;保存成功用 message 一句话。输出单个 Vue SFC。",
67
+ "expected_output": "form-in-dialog snippet: list stays, MDialog + MForm + #footer, message.success not toast string, MTable rows.",
68
+ "files": []
69
+ },
70
+ {
71
+ "id": 12,
72
+ "prompt": "做一个用户列表表格页:列姓名、角色、状态。状态列必须用 MStatus;行数据绑定用 rows(不要写 data prop);空表用 #empty + MEmpty。Vue3 + morya-ui,输出单个 SFC。",
73
+ "expected_output": "Prop accuracy: MTable columns+rows (not :data), #cell or Status for status, #empty+MEmpty, validate_usage clean.",
74
+ "files": []
75
+ },
76
+ {
77
+ "id": 13,
78
+ "prompt": "列表行删除:点删除后用 MConfirmDialog(危险确认),确认后 message.success('已删除')。不要用 toast,也不要手写 Dialog 当确认框。输出片段或 SFC 均可。",
79
+ "expected_output": "confirm-delete snippet + feedback-choice: MConfirmDialog v-model header/message acceptSeverity=danger @accept, message.success not toast, no hand Dialog confirm.",
80
+ "files": []
81
+ },
82
+ {
83
+ "id": 14,
84
+ "prompt": "短新建弹窗:MDialog v-model + header + #footer(取消 secondary、保存 primary);表单字段 fluid。保存成功 message 一句话。不要用 v-model:visible。",
85
+ "expected_output": "form-in-dialog / form-surface Dialog recipe: v-model not visible, #footer actions, fluid fields, message.success, relatedSnippets include form-in-dialog.",
86
+ "files": []
87
+ }
88
+ ]
89
+ }
@@ -1,99 +1,99 @@
1
- # Component index (scenario map)
2
-
3
- Full API: docs site `/components` or MCP (`get_component`, `search`, `validate_usage`).
4
-
5
- - **Selection + key props**: MCP `recommend_component`, or offline [decision-recipes.md](./decision-recipes.md) (generated from `packages/ui-mcp/src/decisions.ts`).
6
- - This file is a **catalog + decision-id index**, not a prop manual.
7
-
8
- ## Shell
9
-
10
- | Component | Use |
11
- | --- | --- |
12
- | `MConfigProvider` | Root locale / theme / density / defaults |
13
- | `MLayout` family | Admin chrome (`MLayoutSider` is the layout sider) |
14
- | `MSidebar` | Standalone nav rail (not a `MDrawer`, not a substitute for `MLayoutSider` inside `MLayout`) |
15
- | `MBreadcrumb` | Path |
16
- | `MPageContent` / `MPageFilters` / `MPageToolbar` / `MPageHeader` / `MPageSection` / `MPageStat` / `MPagePlaceholder` | Page composition |
17
- | `MDock` | App dock / launcher, not page actions |
18
-
19
- ## Actions
20
-
21
- `MButton` / `MButtonGroup` (primary `severity="primary"`, danger `severity="danger"`), `MSplitButton` (main action + menu), `MSpeedDial` (floating action cluster)
22
-
23
- ## Forms · inputs
24
-
25
- `MForm`, `MFormItem`, `MInput`, `MInputPassword`, `MInputNumber`, `MTextarea`, `MInputOtp`, `MInputColor`, `MInputGroup`, `MInputTags`, `MSelect`, `MTreeSelect`, `MCascadeSelect`, `MListbox`, `MSelectButton`, `MDatePicker`, `MAutoComplete`, `MCheckbox` / `MCheckboxGroup`, `MRadio` / `MRadioGroup`, `MSwitch`, `MToggleButton`, `MSlider`, `MRating`, `MKnob`, `MFileUpload`, `MFloatLabel`, `MIconField`, `MLabel`
26
-
27
- ## Layout helpers
28
-
29
- `MGrid` / `MGridItem`, `MFlex`, `MSpace`, `MFluid`, `MDivider`, `MFieldset`, `MSplitter`, `MToolbar`
30
-
31
- ## Data
32
-
33
- `MTable` (`columns` + **`rows`**, not `data`), `MTreeTable`, `MDataView`, `MTree`, `MPagination`, `MOrderList`, `MPickList`, `MStatus` / `MTag` / `MChip` / `MBadge`, `MAvatar` / `MAvatarGroup`, `MTimeline`, `MMeterGroup`, `MVirtualScroller`
34
-
35
- ## Feedback
36
-
37
- | API / component | When | Decision |
38
- | --- | --- | --- |
39
- | `message` | **Default** one-line CRUD result | `feedback-choice` |
40
- | `toast` | `summary` + `detail`, or async / background feel | `feedback-choice` |
41
- | `<MMessage>` | Optional host for the `message` service. **Not** an inline alert | `feedback-choice` |
42
- | field `errorMessage` or token `role="alert"` | Persistent form / auth error | `feedback-choice` |
43
- | `MEmpty` | No-data / first-use / filtered empty | `empty-result-choice` |
44
- | `MResult` | Terminal outcome: success, failure, 403 / 404 / 500 | `empty-result-choice` |
45
- | `MLoading` / `v-loading` / `loading.service` | **Default** region or fullscreen loading mask | `loading-choice` |
46
- | `MSkeleton` | Layout known; placeholder while content arrives | `loading-choice` |
47
- | `MProgressBar` | Determinate progress | `loading-choice` |
48
- | `MProgressSpinner` | Inline spinner only, not a region mask | `loading-choice` |
49
- | `MBlockUI` | Block interaction without a loading message | `loading-choice` |
50
-
51
- ## Overlays & menus
52
-
53
- `MDialog`, `MDrawer`, `MConfirmDialog` / `MConfirmPopup`, `MPopover`, `MTooltip`, `MDropdown` (**actions only**), `MContextMenu`, `MCommandMenu`, `MMenu` / `MMenubar` / `MTieredMenu` / `MMegaMenu`, `MTabs`, `MStepper`
54
-
55
- ## Surfaces / media
56
-
57
- `MCard`, `MPanel`, `MAccordion`, `MCarousel`, `MGallery`, `MIcon`, `MScrollbar`, `MInplace`, `MScrollTop`, `MTerminal`
58
-
59
- ## Scenario → decision
60
-
61
- Open MCP `recommend_component({ decision })` or the matching section in [decision-recipes.md](./decision-recipes.md) for **when / avoid / recipe props / anti-patterns**.
62
-
63
- | Intent | Decision id |
64
- | --- | --- |
65
- | Create / edit from a list (few–medium fields) vs long form page | `form-surface-choice` |
66
- | Dialog vs Drawer vs Popover vs Tooltip | `overlay-choice` |
67
- | Table vs DataView vs Tree / TreeTable | `data-display-choice` |
68
- | Select vs TreeSelect vs AutoComplete vs Radio / … | `selection-choice` |
69
- | Card vs Panel vs Fieldset | `surface-choice` |
70
- | PageContent vs Flex vs Space vs Grid | `layout-spacing-choice` |
71
- | PageFilters / Toolbar / Header / Section / Stat / Placeholder | `page-section-choice` |
72
- | Layout scroll vs MScrollbar vs built-in | `page-scroll-choice` |
73
- | Avoid double borders / extra Card wrappers | `surface-nesting-choice` |
74
- | Loading vs Skeleton vs Progress* vs BlockUI | `loading-choice` |
75
- | Status vs Tag vs Chip vs Badge | `status-label-choice` |
76
- | Empty vs Result | `empty-result-choice` |
77
- | Dropdown vs Menu vs ContextMenu vs CommandMenu | `action-menu-choice` |
78
- | message vs toast vs field / form alert | `feedback-choice` |
79
- | ConfirmDialog vs ConfirmPopup | `confirm-choice` |
80
- | Searchable list + paging | `page-section-choice` + `data-display-choice` (+ list golden) |
81
- | Delete / destructive | `confirm-choice` |
82
- | Login / auth | `feedback-choice` + `login-page` golden |
83
- | Marketing landing | `landing-page` golden (Express) |
84
- | Multi-step create | `wizard-form` golden |
85
- | Preferences / settings | `settings-page` golden |
86
- | Resizable two-pane | use `MSplitter` (see docs / `get_component`) |
87
-
88
- ## Common mistakes
89
-
90
- | Wrong | Right |
91
- | --- | --- |
92
- | `MDropdown` as form enum | `MSelect` (`selection-choice`) |
93
- | `MTable` `:data` | `:rows` (`data-display-choice`) |
94
- | `<MMessage severity>` as an inline alert | Field `errorMessage`, or token `role="alert"` (`feedback-choice`) |
95
- | Hand `<table>` | `MTable` |
96
- | Hand modal div | `MDialog` / `MConfirmDialog` |
97
- | Hand spinner or `MProgressSpinner` as a region / page mask | `MLoading` / `v-loading` (`loading-choice`) |
98
- | Extra `MCard` around every `MPage*` block | `surface-nesting-choice` |
99
- | Assume undocumented props | MCP / docs lookup + `validate_usage` |
1
+ # Component index (scenario map)
2
+
3
+ Full API: docs site `/components` or MCP (`get_component`, `search`, `validate_usage`).
4
+
5
+ - **Selection + key props**: MCP `recommend_component`, or offline [decision-recipes.md](./decision-recipes.md) (generated from `packages/ui-mcp/src/decisions.ts`).
6
+ - This file is a **catalog + decision-id index**, not a prop manual.
7
+
8
+ ## Shell
9
+
10
+ | Component | Use |
11
+ | --- | --- |
12
+ | `MConfigProvider` | Root locale / theme / density / defaults |
13
+ | `MLayout` family | Admin chrome (`MLayoutSider` is the layout sider) |
14
+ | `MSidebar` | Standalone nav rail (not a `MDrawer`, not a substitute for `MLayoutSider` inside `MLayout`) |
15
+ | `MBreadcrumb` | Path |
16
+ | `MPageContent` / `MPageFilters` / `MPageToolbar` / `MPageHeader` / `MPageSection` / `MPageStat` / `MPagePlaceholder` | Page composition |
17
+ | `MDock` | App dock / launcher, not page actions |
18
+
19
+ ## Actions
20
+
21
+ `MButton` / `MButtonGroup` (primary `severity="primary"`, danger `severity="danger"`), `MSplitButton` (main action + menu), `MSpeedDial` (floating action cluster)
22
+
23
+ ## Forms · inputs
24
+
25
+ `MForm`, `MFormItem`, `MInput`, `MInputPassword`, `MInputNumber`, `MTextarea`, `MInputOtp`, `MInputColor`, `MInputGroup`, `MInputTags`, `MSelect`, `MTreeSelect`, `MCascadeSelect`, `MListbox`, `MSelectButton`, `MDatePicker`, `MAutoComplete`, `MCheckbox` / `MCheckboxGroup`, `MRadio` / `MRadioGroup`, `MSwitch`, `MToggleButton`, `MSlider`, `MRating`, `MKnob`, `MFileUpload`, `MFloatLabel`, `MIconField`, `MLabel`
26
+
27
+ ## Layout helpers
28
+
29
+ `MGrid` / `MGridItem`, `MFlex`, `MSpace`, `MFluid`, `MDivider`, `MFieldset`, `MSplitter`, `MToolbar`
30
+
31
+ ## Data
32
+
33
+ `MTable` (`columns` + **`rows`**, not `data`), `MTreeTable`, `MDataView`, `MTree`, `MPagination`, `MOrderList`, `MPickList`, `MStatus` / `MTag` / `MChip` / `MBadge`, `MAvatar` / `MAvatarGroup`, `MTimeline`, `MMeterGroup`, `MVirtualScroller`
34
+
35
+ ## Feedback
36
+
37
+ | API / component | When | Decision |
38
+ | --- | --- | --- |
39
+ | `message` | **Default** one-line CRUD result | `feedback-choice` |
40
+ | `toast` | `summary` + `detail`, or async / background feel | `feedback-choice` |
41
+ | `<MMessage>` | Optional host for the `message` service. **Not** an inline alert | `feedback-choice` |
42
+ | field `errorMessage` or token `role="alert"` | Persistent form / auth error | `feedback-choice` |
43
+ | `MEmpty` | No-data / first-use / filtered empty | `empty-result-choice` |
44
+ | `MResult` | Terminal outcome: success, failure, 403 / 404 / 500 | `empty-result-choice` |
45
+ | `MLoading` / `v-loading` / `loading.service` | **Default** region or fullscreen loading mask | `loading-choice` |
46
+ | `MSkeleton` | Layout known; placeholder while content arrives | `loading-choice` |
47
+ | `MProgressBar` | Determinate progress | `loading-choice` |
48
+ | `MProgressSpinner` | Inline spinner only, not a region mask | `loading-choice` |
49
+ | `MBlockUI` | Block interaction without a loading message | `loading-choice` |
50
+
51
+ ## Overlays & menus
52
+
53
+ `MDialog`, `MDrawer`, `MConfirmDialog` / `MConfirmPopup`, `MPopover`, `MTooltip`, `MDropdown` (**actions only**), `MContextMenu`, `MCommandMenu`, `MMenu` / `MMenubar` / `MTieredMenu` / `MMegaMenu`, `MTabs`, `MStepper`
54
+
55
+ ## Surfaces / media
56
+
57
+ `MCard`, `MPanel`, `MAccordion`, `MCarousel`, `MGallery`, `MIcon`, `MScrollbar`, `MInplace`, `MScrollTop`, `MTerminal`
58
+
59
+ ## Scenario → decision
60
+
61
+ Open MCP `recommend_component({ decision })` or the matching section in [decision-recipes.md](./decision-recipes.md) for **when / avoid / recipe props / anti-patterns**.
62
+
63
+ | Intent | Decision id |
64
+ | --- | --- |
65
+ | Create / edit from a list (few–medium fields) vs long form page | `form-surface-choice` |
66
+ | Dialog vs Drawer vs Popover vs Tooltip | `overlay-choice` |
67
+ | Table vs DataView vs Tree / TreeTable | `data-display-choice` |
68
+ | Select vs TreeSelect vs AutoComplete vs Radio / … | `selection-choice` |
69
+ | Card vs Panel vs Fieldset | `surface-choice` |
70
+ | PageContent vs Flex vs Space vs Grid | `layout-spacing-choice` |
71
+ | PageFilters / Toolbar / Header / Section / Stat / Placeholder | `page-section-choice` |
72
+ | Layout scroll vs MScrollbar vs built-in | `page-scroll-choice` |
73
+ | Avoid double borders / extra Card wrappers | `surface-nesting-choice` |
74
+ | Loading vs Skeleton vs Progress* vs BlockUI | `loading-choice` |
75
+ | Status vs Tag vs Chip vs Badge | `status-label-choice` |
76
+ | Empty vs Result | `empty-result-choice` |
77
+ | Dropdown vs Menu vs ContextMenu vs CommandMenu | `action-menu-choice` |
78
+ | message vs toast vs field / form alert | `feedback-choice` |
79
+ | ConfirmDialog vs ConfirmPopup | `confirm-choice` |
80
+ | Searchable list + paging | `page-section-choice` + `data-display-choice` (+ list golden) |
81
+ | Delete / destructive | `confirm-choice` |
82
+ | Login / auth | `feedback-choice` + `login-page` golden |
83
+ | Marketing landing | `landing-page` golden (Express) |
84
+ | Multi-step create | `wizard-form` golden |
85
+ | Preferences / settings | `settings-page` golden |
86
+ | Resizable two-pane | use `MSplitter` (see docs / `get_component`) |
87
+
88
+ ## Common mistakes
89
+
90
+ | Wrong | Right |
91
+ | --- | --- |
92
+ | `MDropdown` as form enum | `MSelect` (`selection-choice`) |
93
+ | `MTable` `:data` | `:rows` (`data-display-choice`) |
94
+ | `<MMessage severity>` as an inline alert | Field `errorMessage`, or token `role="alert"` (`feedback-choice`) |
95
+ | Hand `<table>` | `MTable` |
96
+ | Hand modal div | `MDialog` / `MConfirmDialog` |
97
+ | Hand spinner or `MProgressSpinner` as a region / page mask | `MLoading` / `v-loading` (`loading-choice`) |
98
+ | Extra `MCard` around every `MPage*` block | `surface-nesting-choice` |
99
+ | Assume undocumented props | MCP / docs lookup + `validate_usage` |
@@ -6,7 +6,7 @@ Generated from `packages/ui-mcp/src/decisions.ts`. **Do not hand-edit** this fil
6
6
  pnpm --filter @morya-ui/mcp generate:recipes
7
7
  ```
8
8
 
9
- MCP: `recommend_component` (list / read by `decision` / query). Full prop manuals still come from `get_component` + `validate_usage`.
9
+ MCP: `recommend_component` (list / read by `decision` / query; options may include `relatedSnippets`). Full prop manuals still come from `get_component` + `validate_usage`. Prefer page snippets for composition; golden pages are optional block-order checks.
10
10
 
11
11
  This file is the **offline** mirror for agents without MCP.
12
12
 
@@ -31,7 +31,7 @@ This file is the **offline** mirror for agents without MCP.
31
31
 
32
32
  - v-model / modelValue 控制开关(不要用 visible)
33
33
  - header 或 title 设弹窗标题
34
- - width 约 32rem 适配短表单(见 form-in-dialog 黄金样例)
34
+ - width 约 32rem 适配短表单(见 form-in-dialog snippet)
35
35
  - 表单字段用 fluid;主按钮 severity="primary"
36
36
 
37
37
  **Recipe · slots**
@@ -44,6 +44,11 @@ This file is the **offline** mirror for agents without MCP.
44
44
  - @close 重置表单模型
45
45
  - 保存可用按钮 @click,或 MForm @submit + type="submit"
46
46
 
47
+ **Related snippets**
48
+
49
+ - `form-in-dialog`
50
+ - `page-header-actions`
51
+
47
52
  **Anti-patterns**
48
53
 
49
54
  - 用普通 Dialog 手写删除确认 → MConfirmDialog
@@ -77,6 +82,10 @@ This file is the **offline** mirror for agents without MCP.
77
82
 
78
83
  - @close 清理草稿
79
84
 
85
+ **Related snippets**
86
+
87
+ - `form-in-drawer`
88
+
80
89
  **Anti-patterns**
81
90
 
82
91
  - 极短 2–3 字段也用 Drawer → Dialog
@@ -110,6 +119,13 @@ This file is the **offline** mirror for agents without MCP.
110
119
  - MForm @submit(或 @submit.prevent)
111
120
  - 提交按钮 type="submit" + severity="primary"
112
121
 
122
+ **Related snippets**
123
+
124
+ - `page-content-form`
125
+ - `form-header`
126
+ - `form-body`
127
+ - `form-actions`
128
+
113
129
  **Anti-patterns**
114
130
 
115
131
  - 列表短 CRUD 开独立路由 → form-in-dialog
@@ -151,6 +167,10 @@ This file is the **offline** mirror for agents without MCP.
151
167
 
152
168
  - @close / @update:modelValue
153
169
 
170
+ **Related snippets**
171
+
172
+ - `form-in-dialog`
173
+
154
174
  **Anti-patterns**
155
175
 
156
176
  - Dialog + 手写「确定删除」→ MConfirmDialog
@@ -184,6 +204,10 @@ This file is the **offline** mirror for agents without MCP.
184
204
 
185
205
  - @close
186
206
 
207
+ **Related snippets**
208
+
209
+ - `form-in-drawer`
210
+
187
211
  **Anti-patterns**
188
212
 
189
213
  - 简单 Yes/No 确认用 Drawer → ConfirmDialog / ConfirmPopup
@@ -262,6 +286,7 @@ This file is the **offline** mirror for agents without MCP.
262
286
 
263
287
  - columns + rows(没有 data prop)
264
288
  - row-key 默认 id;不稳定时显式指定
289
+ - 全视口主列表可 MPageContent fill + MTable fill;嵌入/短页跳过
265
290
  - 分页:paginator + rows-per-page 或 v-model:page
266
291
  - 行选择:selectionMode + v-model:selection
267
292
 
@@ -274,6 +299,7 @@ This file is the **offline** mirror for agents without MCP.
274
299
 
275
300
  - :data → :rows
276
301
  - 手写 <table> → MTable
302
+ - 嵌入表硬套 fill → 去掉 fill
277
303
 
278
304
 
279
305
  ### DataView
@@ -725,17 +751,30 @@ This file is the **offline** mirror for agents without MCP.
725
751
 
726
752
  **Recipe · props**
727
753
 
728
- - 内放 MInput / MSelect 等筛选控件
729
- - 可 collapsible + #advanced
730
- - 不要外包 MCard
754
+ - 内放 MInput / MSelect;同行用 MSpace wrap
755
+ - 查询/重置放 #actions(与折叠切换同列)
756
+ - 默认 variant="filled";dense craft 用 plain + size="small"
757
+ - 有次要条件:collapsible + v-model:expanded + #advanced
758
+ - toggle 默认「高级筛选/收起」+ chevron;已选用 FilterChips
731
759
 
732
760
  **Recipe · slots**
733
761
 
762
+ - #actions 查询/重置
734
763
  - #advanced 高级筛选
764
+ - #active 可选;更常见是下方 FilterChips
765
+
766
+ **Related snippets**
767
+
768
+ - `list-filters-stack`
769
+ - `list-filters`
770
+ - `list-filters-collapsible`
771
+ - `list-filter-chips`
772
+ - `list-filters-dense`
735
773
 
736
774
  **Anti-patterns**
737
775
 
738
776
  - 表单字段组用 PageFilters → PageSection form / Fieldset
777
+ - 手写已选条 → list-filter-chips / list-filters-stack
739
778
 
740
779
 
741
780
  ### PageToolbar
@@ -882,6 +921,7 @@ This file is the **offline** mirror for agents without MCP.
882
921
 
883
922
  - MLayout fill-viewport(或 :fill-viewport="true")
884
923
  - 内容放 MLayoutContent
924
+ - 是否再 fill 表格:见下方「MPageContent fill + MTable fill」判断
885
925
  - 侧栏用 MLayoutSider + MMenu,不是随便一个 Drawer
886
926
 
887
927
  **Anti-patterns**
@@ -889,6 +929,33 @@ This file is the **offline** mirror for agents without MCP.
889
929
  - 在 Layout 外再包一层 100vh 滚动 → 去掉
890
930
 
891
931
 
932
+ ### MPageContent fill + MTable fill
933
+
934
+ **When**
935
+
936
+ - 全视口后台列表,页面主任务就是浏览一张表
937
+ - 内容高度表格会留下大块空白、分页悬在中间不好看
938
+ - 希望只有表体滚动、分页贴在页面最下方
939
+
940
+ **Avoid when**
941
+
942
+ - 仪表盘/详情里的嵌入小表
943
+ - 内容本身很短、内容高度即可
944
+ - 整页应作为文档滚动(长筛选+说明+表格)
945
+ - Dialog / Drawer 内表格
946
+
947
+ **Recipe · props**
948
+
949
+ - 先判断是否适合 fill,再写 MPageContent fill + MTable fill
950
+ - paginator 或同级 MPagination
951
+ - 适合时不要手写 min-height / calc
952
+
953
+ **Anti-patterns**
954
+
955
+ - 嵌入/短页硬套 fill → 去掉
956
+ - 适合 fill 却手写 calc → 改用 fill
957
+
958
+
892
959
  ### MScrollbar
893
960
 
894
961
  **When**
@@ -957,11 +1024,13 @@ This file is the **offline** mirror for agents without MCP.
957
1024
 
958
1025
  - MPageContent > MPageFilters + MTable
959
1026
  - 表格直接放 PageContent,不套 Card
1027
+ - 高度:全视口主列表再考虑 fill;嵌入/短页跳过
960
1028
  - 空态用 Table #empty + MEmpty
961
1029
 
962
1030
  **Anti-patterns**
963
1031
 
964
1032
  - Table 外包 MCard → 去掉 Card
1033
+ - 嵌入表硬套 fill → 去掉 fill
965
1034
 
966
1035
 
967
1036
  ### MCard
@@ -1267,6 +1336,10 @@ This file is the **offline** mirror for agents without MCP.
1267
1336
 
1268
1337
  - #extra 放下一步按钮(创建…)
1269
1338
 
1339
+ **Related snippets**
1340
+
1341
+ - `empty-block`
1342
+
1270
1343
  **Anti-patterns**
1271
1344
 
1272
1345
  - 403/404 用 Empty → Result
@@ -1296,6 +1369,10 @@ This file is the **offline** mirror for agents without MCP.
1296
1369
 
1297
1370
  - #footer 逃逸/下一步按钮
1298
1371
 
1372
+ **Related snippets**
1373
+
1374
+ - `result-block`
1375
+
1299
1376
  **Anti-patterns**
1300
1377
 
1301
1378
  - 表格无数据用 Result → Empty
@@ -1326,6 +1403,11 @@ This file is the **offline** mirror for agents without MCP.
1326
1403
  - 触发器放默认插槽(按钮/图标)
1327
1404
  - 危险项用文档 severity / 确认流
1328
1405
 
1406
+ **Related snippets**
1407
+
1408
+ - `row-actions-menu`
1409
+ - `list-row-actions`
1410
+
1329
1411
  **Anti-patterns**
1330
1412
 
1331
1413
  - 表单枚举用 Dropdown → Select
@@ -1443,6 +1525,11 @@ This file is the **offline** mirror for agents without MCP.
1443
1525
  - message.success('已保存') / info / warn / error
1444
1526
  - 大多数操作反馈的默认选择
1445
1527
 
1528
+ **Related snippets**
1529
+
1530
+ - `confirm-delete`
1531
+ - `form-in-dialog`
1532
+
1446
1533
  **Anti-patterns**
1447
1534
 
1448
1535
  - toast.add({ summary: '已保存' }) → message.success('已保存')
@@ -1488,6 +1575,10 @@ This file is the **offline** mirror for agents without MCP.
1488
1575
  - 表单级:token 样式的 role="alert" 条(见 login-page)
1489
1576
  - <MMessage> 只是 message 宿主,不是内嵌 Alert
1490
1577
 
1578
+ **Related snippets**
1579
+
1580
+ - `auth-split-shell`
1581
+
1491
1582
  **Anti-patterns**
1492
1583
 
1493
1584
  - 登录失败只闪 Toast → 表单区 alert / errorMessage
@@ -1525,6 +1616,10 @@ This file is the **offline** mirror for agents without MCP.
1525
1616
  - @accept 执行删除
1526
1617
  - @reject 关闭
1527
1618
 
1619
+ **Related snippets**
1620
+
1621
+ - `confirm-delete`
1622
+
1528
1623
  **Anti-patterns**
1529
1624
 
1530
1625
  - 普通 Dialog 手写「确定/取消」删除 → ConfirmDialog
@@ -1554,6 +1649,10 @@ This file is the **offline** mirror for agents without MCP.
1554
1649
 
1555
1650
  - @accept / @reject
1556
1651
 
1652
+ **Related snippets**
1653
+
1654
+ - `confirm-delete`
1655
+
1557
1656
  **Anti-patterns**
1558
1657
 
1559
1658
  - 无 target 的全局危险确认 → ConfirmDialog