@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,89 +1,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
+ {
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` |
@@ -1,101 +1,101 @@
1
- # Design system (consumer summary)
2
-
3
- Canonical long form lives in project-root `DESIGN.md` when the AI config pack is merged. This file is the portable subset for agents.
4
-
5
- ## Principles
6
-
7
- 1. **Components first** — layout, forms, tables, overlays use `M*` from `morya-ui`, not equivalent hand-rolled DOM.
8
- 2. **Tokens first** — color, space, radius, shadow, motion via `--m-*`. No raw `#hex` / `rgb()` in page styles.
9
- 3. **Semantic actions** — primary work uses `MButton severity="primary"`; destructive uses `severity="danger"` or confirm dialogs.
10
- 4. **Accessibility** — fields have visible labels; icon buttons have `aria-label`; overlays dismiss with Esc (library default).
11
- 5. **ConfigProvider** — wrap the app (or isolated demo) in `MConfigProvider` for locale, theme, density, overlay mount.
12
-
13
- ## App shell
14
-
15
- ```vue
16
- <script setup lang="ts">
17
- import { MConfigProvider, zhCN } from 'morya-ui'
18
- import 'morya-ui/styles.css'
19
- </script>
20
-
21
- <template>
22
- <MConfigProvider :locale="zhCN">
23
- <MLayout fill-viewport has-sider>
24
- <MLayoutSider bordered>
25
- <MMenu
26
- :model="[
27
- { key: 'users', label: 'Users', icon: 'user', to: '/users' },
28
- { key: 'roles', label: 'Roles', icon: 'shield', to: '/roles' },
29
- ]"
30
- />
31
- </MLayoutSider>
32
- <MLayout>
33
- <MLayoutHeader>...</MLayoutHeader>
34
- <MLayoutContent>...</MLayoutContent>
35
- </MLayout>
36
- </MLayout>
37
- </MConfigProvider>
38
- </template>
39
- ```
40
-
41
- | Role | Prefer |
42
- | --- | --- |
43
- | Admin chrome | `MLayout fillViewport` + sider / header / content |
44
- | Sider nav | `MMenu` |
45
- | Page stack | `MPageContent` inside `MLayoutContent` |
46
- | List chrome | `MPageHeader` + `MPageFilters` (+ optional batch `MPageToolbar`) |
47
- | Form surfaces | `MPageHeader` + `MPageSection variant="form|actions"` |
48
- | Dashboard KPI / chart pending | `MPageStat` + `MCard shadow="always"` + `MEmpty` |
49
- | Module cards | `MCard` / `MPanel` / `MFieldset` |
50
- | Grid / spacing | `MGrid` + `MGridItem`, or `MFlex` / `MSpace` |
51
-
52
- ## Forms
53
-
54
- - `MForm` + `MFormItem` with `name` aligned to rules.
55
- - Prefer field props (`label`, `invalid`, `helpText`) when the control supports them; wrap with `MFormItem` for denser / complex forms.
56
- - Default size medium; dense apps may use `size="small"` or ConfigProvider density.
57
- - Form pages: keep the main column narrow (`MPageContent width="narrow"` or ~`40rem`).
58
-
59
- ## Data display
60
-
61
- - `MTable` with `columns` + **`rows`** + `row-key` (default `id`). There is no `data` prop.
62
- - Height: only for **full-viewport admin lists** whose main job is one table, use `MPageContent fill` + `MTable fill paginator`. Skip `fill` for embedded/short/document-scroll tables — see [page-layouts.md](page-layouts.md) § List height.
63
- - Row status → `MStatus`; categories / closable labels → `MTag`.
64
- - Row actions: text/link `MButton` or `MDropdown` (avoid a row of filled buttons).
65
- - Pagination: table `paginator` or sibling `MPagination`.
66
- - Empty states: `MEmpty` in `#empty` / Flow golden — never a silent blank table.
67
- - Terminal outcomes (success / 403 / 404 / 500): `MResult` — do not reuse `MEmpty` for errors.
68
- - Visual polish: [visual-craft.md](visual-craft.md) (Ops polish + atmosphere).
69
-
70
- ## Overlays
71
-
72
- | Need | Component |
73
- | --- | --- |
74
- | Delete confirm | `MConfirmDialog` / `MConfirmPopup` |
75
- | Detail / edit modal | `MDialog` |
76
- | Side filter / detail | `MDrawer` |
77
- | Field hint | `MTooltip` |
78
-
79
- ## Token cheat sheet
80
-
81
- | Use | Variable |
82
- | --- | --- |
83
- | Page background | `--m-color-surface` |
84
- | Body text | `--m-color-text` |
85
- | Muted text | `--m-color-text-muted` |
86
- | Border | `--m-color-border` |
87
- | Brand / link | `--m-color-primary` |
88
- | Danger | `--m-color-danger` |
89
- | Section gap | `--m-space-4` / `--m-space-6` |
90
- | Card radius | `--m-radius-md` |
91
- | Card shadow | `--m-shadow-md` |
92
-
93
- Full set: MCP `get_design_rules`. Runtime truth remains `morya-ui/styles.css`.
94
-
95
- ## Bans
96
-
97
- - Second UI library on the same page.
98
- - Hard-coded theme colors that break `[data-theme="dark"]`.
99
- - `<div @click>` instead of `MButton` / `<button>`.
100
- - Using `MDropdown` for form enum selection (use `MSelect` / `MTreeSelect`).
101
- - Skipping `import 'morya-ui/styles.css'`.
1
+ # Design system (consumer summary)
2
+
3
+ Canonical long form lives in project-root `DESIGN.md` when the AI config pack is merged. This file is the portable subset for agents.
4
+
5
+ ## Principles
6
+
7
+ 1. **Components first** — layout, forms, tables, overlays use `M*` from `morya-ui`, not equivalent hand-rolled DOM.
8
+ 2. **Tokens first** — color, space, radius, shadow, motion via `--m-*`. No raw `#hex` / `rgb()` in page styles.
9
+ 3. **Semantic actions** — primary work uses `MButton severity="primary"`; destructive uses `severity="danger"` or confirm dialogs.
10
+ 4. **Accessibility** — fields have visible labels; icon buttons have `aria-label`; overlays dismiss with Esc (library default).
11
+ 5. **ConfigProvider** — wrap the app (or isolated demo) in `MConfigProvider` for locale, theme, density, overlay mount.
12
+
13
+ ## App shell
14
+
15
+ ```vue
16
+ <script setup lang="ts">
17
+ import { MConfigProvider, zhCN } from 'morya-ui'
18
+ import 'morya-ui/styles.css'
19
+ </script>
20
+
21
+ <template>
22
+ <MConfigProvider :locale="zhCN">
23
+ <MLayout fill-viewport has-sider>
24
+ <MLayoutSider bordered>
25
+ <MMenu
26
+ :model="[
27
+ { key: 'users', label: 'Users', icon: 'user', to: '/users' },
28
+ { key: 'roles', label: 'Roles', icon: 'shield', to: '/roles' },
29
+ ]"
30
+ />
31
+ </MLayoutSider>
32
+ <MLayout>
33
+ <MLayoutHeader>...</MLayoutHeader>
34
+ <MLayoutContent>...</MLayoutContent>
35
+ </MLayout>
36
+ </MLayout>
37
+ </MConfigProvider>
38
+ </template>
39
+ ```
40
+
41
+ | Role | Prefer |
42
+ | --- | --- |
43
+ | Admin chrome | `MLayout fillViewport` + sider / header / content |
44
+ | Sider nav | `MMenu` |
45
+ | Page stack | `MPageContent` inside `MLayoutContent` |
46
+ | List chrome | `MPageHeader` + `MPageFilters` (+ optional batch `MPageToolbar`) |
47
+ | Form surfaces | `MPageHeader` + `MPageSection variant="form|actions"` |
48
+ | Dashboard KPI / chart pending | `MPageStat` + `MCard shadow="always"` + `MEmpty` |
49
+ | Module cards | `MCard` / `MPanel` / `MFieldset` |
50
+ | Grid / spacing | `MGrid` + `MGridItem`, or `MFlex` / `MSpace` |
51
+
52
+ ## Forms
53
+
54
+ - `MForm` + `MFormItem` with `name` aligned to rules.
55
+ - Prefer field props (`label`, `invalid`, `helpText`) when the control supports them; wrap with `MFormItem` for denser / complex forms.
56
+ - Default size medium; dense apps may use `size="small"` or ConfigProvider density.
57
+ - Form pages: keep the main column narrow (`MPageContent width="narrow"` or ~`40rem`).
58
+
59
+ ## Data display
60
+
61
+ - `MTable` with `columns` + **`rows`** + `row-key` (default `id`). There is no `data` prop.
62
+ - Height: only for **full-viewport admin lists** whose main job is one table, use `MPageContent fill` + `MTable fill paginator`. Skip `fill` for embedded/short/document-scroll tables — see [page-layouts.md](page-layouts.md) § List height.
63
+ - Row status → `MStatus`; categories / closable labels → `MTag`.
64
+ - Row actions: text/link `MButton` or `MDropdown` (avoid a row of filled buttons).
65
+ - Pagination: table `paginator` or sibling `MPagination`.
66
+ - Empty states: `MEmpty` in `#empty` / Flow golden — never a silent blank table.
67
+ - Terminal outcomes (success / 403 / 404 / 500): `MResult` — do not reuse `MEmpty` for errors.
68
+ - Visual polish: [visual-craft.md](visual-craft.md) (Ops polish + atmosphere).
69
+
70
+ ## Overlays
71
+
72
+ | Need | Component |
73
+ | --- | --- |
74
+ | Delete confirm | `MConfirmDialog` / `MConfirmPopup` |
75
+ | Detail / edit modal | `MDialog` |
76
+ | Side filter / detail | `MDrawer` |
77
+ | Field hint | `MTooltip` |
78
+
79
+ ## Token cheat sheet
80
+
81
+ | Use | Variable |
82
+ | --- | --- |
83
+ | Page background | `--m-color-surface` |
84
+ | Body text | `--m-color-text` |
85
+ | Muted text | `--m-color-text-muted` |
86
+ | Border | `--m-color-border` |
87
+ | Brand / link | `--m-color-primary` |
88
+ | Danger | `--m-color-danger` |
89
+ | Section gap | `--m-space-4` / `--m-space-6` |
90
+ | Card radius | `--m-radius-md` |
91
+ | Card shadow | `--m-shadow-md` |
92
+
93
+ Full set: MCP `get_design_rules`. Runtime truth remains `morya-ui/styles.css`.
94
+
95
+ ## Bans
96
+
97
+ - Second UI library on the same page.
98
+ - Hard-coded theme colors that break `[data-theme="dark"]`.
99
+ - `<div @click>` instead of `MButton` / `<button>`.
100
+ - Using `MDropdown` for form enum selection (use `MSelect` / `MTreeSelect`).
101
+ - Skipping `import 'morya-ui/styles.css'`.