@morya-ui/setup 0.2.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.
- package/LICENSE +21 -0
- package/README.md +93 -0
- package/bin/morya-ui-setup.js +14 -0
- package/package.json +35 -0
- package/src/cli.mjs +200 -0
- package/src/copy-template.mjs +62 -0
- package/src/fs-utils.mjs +23 -0
- package/src/install.mjs +63 -0
- package/src/mcp.mjs +50 -0
- package/src/package-json.mjs +30 -0
- package/src/styles.mjs +109 -0
- package/template/.agents/skills/morya-ui-pages/SKILL.md +150 -0
- package/template/.agents/skills/morya-ui-pages/evals/evals.json +53 -0
- package/template/.agents/skills/morya-ui-pages/references/component-index.md +72 -0
- package/template/.agents/skills/morya-ui-pages/references/design-system.md +90 -0
- package/template/.agents/skills/morya-ui-pages/references/feedback.md +66 -0
- package/template/.agents/skills/morya-ui-pages/references/optional-companions.md +29 -0
- package/template/.agents/skills/morya-ui-pages/references/page-layouts.md +76 -0
- package/template/.agents/skills/morya-ui-pages/references/review-checklist.md +49 -0
- package/template/.agents/skills/morya-ui-pages/references/surfaces.md +89 -0
- package/template/.agents/skills/morya-ui-pages/references/visual-craft.md +83 -0
- package/template/.cursor/rules/coding-style.mdc +41 -0
- package/template/.cursor/rules/component-usage.mdc +41 -0
- package/template/.cursor/rules/design-system.mdc +17 -0
- package/template/.cursor/rules/page-layout.mdc +67 -0
- package/template/DESIGN.md +121 -0
- package/template/design-tokens/tokens.css +55 -0
- package/template/design-tokens/tokens.json +77 -0
- package/template/docs/components.md +144 -0
- package/template/docs/feedback-message-vs-toast.md +103 -0
- package/template/docs/golden-pages/dashboard-page.vue +103 -0
- package/template/docs/golden-pages/empty-state.vue +66 -0
- package/template/docs/golden-pages/form-page.vue +107 -0
- package/template/docs/golden-pages/landing-page.vue +328 -0
- package/template/docs/golden-pages/list-page.vue +127 -0
- package/template/docs/golden-pages/login-page.vue +191 -0
- package/template/scripts/check-raw-colors.mjs +74 -0
- package/template/src/examples/DashboardPageExample.vue +103 -0
- package/template/src/examples/EmptyStateExample.vue +66 -0
- package/template/src/examples/FormPageExample.vue +107 -0
- package/template/src/examples/LandingPageExample.vue +328 -0
- package/template/src/examples/ListPageExample.vue +127 -0
- package/template/src/examples/LoginPageExample.vue +191 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Review checklist
|
|
2
|
+
|
|
3
|
+
## Contract (all lanes)
|
|
4
|
+
|
|
5
|
+
- [ ] Only `morya-ui` UI primitives (no second kit)
|
|
6
|
+
- [ ] `morya-ui/styles.css` imported at app/demo entry
|
|
7
|
+
- [ ] `MConfigProvider` at a sensible root when building a full screen
|
|
8
|
+
- [ ] No invented props / events / slots (MCP or docs checked)
|
|
9
|
+
- [ ] Select vs Dropdown roles correct
|
|
10
|
+
- [ ] One-line results use `message`; summary+detail / async use `toast`
|
|
11
|
+
- [ ] Destructive flows use confirm dialogs
|
|
12
|
+
|
|
13
|
+
## Ops
|
|
14
|
+
|
|
15
|
+
- [ ] Matches golden / [page-layouts.md](page-layouts.md) block order
|
|
16
|
+
- [ ] `MPage*` used instead of ad-hoc page chrome where applicable
|
|
17
|
+
- [ ] Tables not wrapped in decorative `MCard` solely for borders
|
|
18
|
+
- [ ] Filters / toolbar / form actions follow documented patterns
|
|
19
|
+
- [ ] No marketing hero bolted onto a CRUD shell
|
|
20
|
+
|
|
21
|
+
## Account / Flow / System
|
|
22
|
+
|
|
23
|
+
- [ ] Primary CTA obvious; escape paths present (back / home / support)
|
|
24
|
+
- [ ] Auth errors persistent via `<MMessage>` or field errors where appropriate
|
|
25
|
+
- [ ] Empty uses `MEmpty` (or table `#empty` with `MEmpty`); success / HTTP errors use `MResult`
|
|
26
|
+
- [ ] Empty / success states tell the user the next action
|
|
27
|
+
- [ ] Inline status prefers `MStatus`; chip-like labels use `MTag`
|
|
28
|
+
- [ ] Wizard steps: one job each; actions labeled clearly
|
|
29
|
+
|
|
30
|
+
## Express
|
|
31
|
+
|
|
32
|
+
- [ ] Short design plan existed (subject, palette roles, signature)
|
|
33
|
+
- [ ] First viewport has one job (not a dashboard of promos)
|
|
34
|
+
- [ ] Controls still `M*`; colors/spacing map to `--m-*` / theme
|
|
35
|
+
- [ ] Avoided AI-default looks unless brief requested them ([visual-craft.md](visual-craft.md))
|
|
36
|
+
- [ ] Motion limited and respectful of reduced-motion
|
|
37
|
+
|
|
38
|
+
## Tokens, a11y, responsive
|
|
39
|
+
|
|
40
|
+
- [ ] No raw hex/rgb theme colors in new CSS (control widths OK inline)
|
|
41
|
+
- [ ] Labels visible; icon buttons have `aria-label`
|
|
42
|
+
- [ ] Usable on a narrow viewport
|
|
43
|
+
- [ ] Focus visible on interactive elements
|
|
44
|
+
|
|
45
|
+
## Optional MCP
|
|
46
|
+
|
|
47
|
+
- [ ] `validate_page` / `validate_usage` reviewed when available
|
|
48
|
+
|
|
49
|
+
If the project has `pnpm check:colors`, suggest running it after edits.
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Surface taxonomy
|
|
2
|
+
|
|
3
|
+
Pick a lane, then a surface. Prefer project golden pages for **Ops**; use the recipes below for everything else. Always implement interactive controls with `morya-ui`.
|
|
4
|
+
|
|
5
|
+
## Ops (admin / console)
|
|
6
|
+
|
|
7
|
+
| Surface | Job | Compose from |
|
|
8
|
+
| --- | --- | --- |
|
|
9
|
+
| List | Scan, filter, act on many rows | Golden list + [page-layouts.md](page-layouts.md) |
|
|
10
|
+
| Form | Create / edit one entity | Golden form |
|
|
11
|
+
| Dashboard | Orient + jump to work | Golden dashboard |
|
|
12
|
+
| Detail | Read-heavy record + secondary actions | `MPageHeader` + `MDescriptions`-style sections via `MCard`/`MPageSection`, actions in toolbar; edit via route or `MDrawer`/`MDialog` |
|
|
13
|
+
| Settings | Grouped preferences | Narrow `MPageContent` + stacked `MPageSection` / `MTabs` + `MForm` |
|
|
14
|
+
| Hybrid list | List + drawer/dialog | List golden + overlay recipe |
|
|
15
|
+
|
|
16
|
+
## Account
|
|
17
|
+
|
|
18
|
+
| Surface | Job | Recipe |
|
|
19
|
+
| --- | --- | --- |
|
|
20
|
+
| Login / register | Authenticate with trust | Golden: `docs/golden-pages/login-page.vue` — split brand + `MForm` (`MInput`, `MInputPassword`); form-level errors via token `role="alert"` (not Toast) |
|
|
21
|
+
| Invite / accept | Join org | Same shell; show org name clearly |
|
|
22
|
+
| Forgot / reset | Recover access | Short form + success state with next step |
|
|
23
|
+
| Profile / account | Edit self | Settings-like sections; avatar via `MAvatar` |
|
|
24
|
+
|
|
25
|
+
Keep credential forms quiet: one primary CTA, clear labels, no decorative noise beside the brand panel.
|
|
26
|
+
|
|
27
|
+
## Flow
|
|
28
|
+
|
|
29
|
+
| Surface | Job | Recipe |
|
|
30
|
+
| --- | --- | --- |
|
|
31
|
+
| Empty state | Invite first action | Golden: `docs/golden-pages/empty-state.vue` — `MEmpty` + primary/secondary `MButton` in `#extra` |
|
|
32
|
+
| Onboarding | Teach the product path | `MStepper` or paced cards; one decision per step; finish → Ops home |
|
|
33
|
+
| Wizard | Multi-step create | `MStepper` + `MForm` per step + sticky actions (`上一步` / `下一步` / `提交`) |
|
|
34
|
+
| Success / result | Confirm completion | `MResult` (`status="success"` / `error` …) + next actions (`查看详情` / `返回列表`) |
|
|
35
|
+
|
|
36
|
+
Copy must tell the user **what to do next**, not celebrate the system.
|
|
37
|
+
|
|
38
|
+
## System
|
|
39
|
+
|
|
40
|
+
| Surface | Job | Recipe |
|
|
41
|
+
| --- | --- | --- |
|
|
42
|
+
| 404 / not found | Reorient | `MResult status="404"` + `返回首页` / `返回上一页` |
|
|
43
|
+
| Permission denied | Explain + escape | `MResult status="403"` + request access / switch account / go home |
|
|
44
|
+
| Maintenance / error | Honest status | `MResult status="500"` or persistent `<MMessage>` banner; what happened + retry + support |
|
|
45
|
+
|
|
46
|
+
Avoid witty 404 essays that hide the exit paths.
|
|
47
|
+
|
|
48
|
+
## Express (marketing / public)
|
|
49
|
+
|
|
50
|
+
Use when the brief is landing, pricing, launch, or docs marketing — **not** for Ops CRUD shells.
|
|
51
|
+
|
|
52
|
+
| Surface | Job | Recipe |
|
|
53
|
+
| --- | --- | --- |
|
|
54
|
+
| Landing | Convert / explain product | Golden: `docs/golden-pages/landing-page.vue` — one-job hero; CTAs → `MButton`; chips → `MTag`; FAQ → `MAccordion` |
|
|
55
|
+
| Pricing | Choose a plan | Clear plan cards (`MCard`) + primary CTA; highlight recommended plan without clutter |
|
|
56
|
+
| Feature showcase | Prove capability | Alternating media/copy; live `M*` demo only if lightweight |
|
|
57
|
+
| Docs marketing chrome | Frame documentation | Header + nav using `M*` where suitable; content area stays readable |
|
|
58
|
+
|
|
59
|
+
Before coding Express: short design plan in [visual-craft.md](visual-craft.md). Map colors to `--m-*` / theme overrides; do not paste a second kit.
|
|
60
|
+
|
|
61
|
+
**Anti-patterns for Express:** inset hero cards instead of a full-bleed thesis; pill-stat strips in the first viewport; purple-on-white / cream-terracotta / broadsheet defaults when the brief did not ask for them.
|
|
62
|
+
|
|
63
|
+
## Overlay
|
|
64
|
+
|
|
65
|
+
When the dialog/drawer **is** the task:
|
|
66
|
+
|
|
67
|
+
| Surface | Recipe |
|
|
68
|
+
| --- | --- |
|
|
69
|
+
| Edit / create dialog | `MDialog` + compact `MForm` + footer actions |
|
|
70
|
+
| Detail drawer | `MDrawer` + header + sections + optional edit |
|
|
71
|
+
| Confirm | `MConfirmDialog` / `MConfirmPopup` — do not reinvent |
|
|
72
|
+
| Command menu | `MCommandMenu` for keyboard-first jump / actions |
|
|
73
|
+
|
|
74
|
+
Host page stays stable; focus management comes from the overlay component.
|
|
75
|
+
|
|
76
|
+
## Lane mixing
|
|
77
|
+
|
|
78
|
+
| Ask | Treat as |
|
|
79
|
+
| --- | --- |
|
|
80
|
+
| “后台列表 + 好看一点” | Ops first, light craft (spacing/type), no landing hero |
|
|
81
|
+
| “登录页有品牌感” | Account + Express craft on brand panel only |
|
|
82
|
+
| “产品官网” | Express; Ops patterns do not apply |
|
|
83
|
+
| “空状态设计精致一点” | Flow empty + visual-craft signature (one risk) |
|
|
84
|
+
|
|
85
|
+
## MCP hints
|
|
86
|
+
|
|
87
|
+
- Ops whole page: `recommend_page` → `get_golden_page` → `get_design_rules`
|
|
88
|
+
- Section: `get_page_snippet`
|
|
89
|
+
- Any lane: `search` / `get_component` before unfamiliar APIs
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Visual craft (distilled)
|
|
2
|
+
|
|
3
|
+
Portable craft for morya-ui consumers. Inspired by **Frontend Design**, **Impeccable**, and **UI-UX-Pro-Max** — without requiring those skills to be installed. Implementation must still honor the morya-ui contract.
|
|
4
|
+
|
|
5
|
+
## When to lean on craft
|
|
6
|
+
|
|
7
|
+
| Lane | Craft intensity |
|
|
8
|
+
| --- | --- |
|
|
9
|
+
| Ops CRUD | Low — clarity, density, golden structure |
|
|
10
|
+
| Account / Flow / System | Medium — trust, hierarchy, one calm brand cue |
|
|
11
|
+
| Express | High — design plan + one signature risk |
|
|
12
|
+
|
|
13
|
+
## Design plan (Express & branded moments)
|
|
14
|
+
|
|
15
|
+
Before code, decide:
|
|
16
|
+
|
|
17
|
+
1. **Color** — 4–6 roles (bg, surface, text, muted, accent, danger). Prefer existing `--m-*`. If the project already customizes theme, extend that system; do not invent a parallel hex soup in scoped CSS.
|
|
18
|
+
2. **Type** — display vs body vs utility. For Ops, stick to theme fonts. For Express, a distinctive pairing is OK if fonts are loadable and fallbacks exist.
|
|
19
|
+
3. **Layout concept** — one sentence + rough hierarchy (ASCII wireframe optional).
|
|
20
|
+
4. **Signature** — the single memorable element (motion, crop, editorial type, product artifact). Everything else quieter.
|
|
21
|
+
|
|
22
|
+
Critique the plan: if it looks like the plan you would write for *any* SaaS, revise until it fits **this** subject.
|
|
23
|
+
|
|
24
|
+
## Anti-default looks (AI clusters)
|
|
25
|
+
|
|
26
|
+
Avoid spending free axes on these unless the brief asks:
|
|
27
|
+
|
|
28
|
+
1. Warm cream (~`#F4F1EA`) + high-contrast serif + terracotta
|
|
29
|
+
2. Near-black + single acid-green / vermilion accent
|
|
30
|
+
3. Broadsheet: hairline rules, zero radius, dense newspaper columns
|
|
31
|
+
4. Purple-on-white / purple-to-indigo gradient SaaS cliché
|
|
32
|
+
5. Glow stacks, pill chip clouds, emoji as decoration, multi-layer shadows as personality
|
|
33
|
+
|
|
34
|
+
Also avoid: Inter/Roboto/Arial as the *expressive* display choice on Express surfaces when the brief allows character (utility UI may keep system/theme fonts).
|
|
35
|
+
|
|
36
|
+
## Hierarchy & composition
|
|
37
|
+
|
|
38
|
+
- **Hero is a thesis** (Express): one job in the first viewport — not stats + schedule + promos together.
|
|
39
|
+
- **Structure encodes meaning**: numbered steps only when order is real information.
|
|
40
|
+
- **Cards**: default off for Express heroes; use `MCard` when it groups an interaction or plan choice.
|
|
41
|
+
- **Motion**: orchestrate 2–3 intentional moments max; respect `prefers-reduced-motion`. Prefer transform/opacity over layout thrash.
|
|
42
|
+
- **Density**: Ops may be compact; Express needs breathing room — match the lane.
|
|
43
|
+
|
|
44
|
+
## UX writing
|
|
45
|
+
|
|
46
|
+
- Name controls by user intent (`保存更改`), not system guts (`提交表单实体`).
|
|
47
|
+
- Active voice; same verb through the flow (Publish → Published).
|
|
48
|
+
- Errors: what failed + how to fix; no vague apology.
|
|
49
|
+
- Empty states: invitation to act, not a dead end.
|
|
50
|
+
- Ops copy stays plain; Express may have voice, still specific to the product.
|
|
51
|
+
|
|
52
|
+
## Polish modes (Impeccable-inspired)
|
|
53
|
+
|
|
54
|
+
When the user asks to improve an existing surface, pick a mode:
|
|
55
|
+
|
|
56
|
+
| Mode | Intent |
|
|
57
|
+
| --- | --- |
|
|
58
|
+
| `audit` | Hierarchy, contrast, a11y, spacing, anti-patterns — report then fix |
|
|
59
|
+
| `clarify` | Labels, errors, empty copy, button verbs |
|
|
60
|
+
| `quieter` | Remove competing accents, chips, shadows; keep one focus |
|
|
61
|
+
| `bolder` | Strengthen the signature only; do not shout everywhere |
|
|
62
|
+
| `typeset` | Scale, weight, line-length, truncation |
|
|
63
|
+
| `adapt` | Responsive breakpoints; touch targets |
|
|
64
|
+
| `delight` | One tasteful micro-interaction — never clutter |
|
|
65
|
+
|
|
66
|
+
Always remediate with `M*` + tokens, not raw replacement controls.
|
|
67
|
+
|
|
68
|
+
## Industry / mood (UI-UX-Pro-Max-inspired)
|
|
69
|
+
|
|
70
|
+
For Express briefs that only say “modern / professional / playful”:
|
|
71
|
+
|
|
72
|
+
1. Infer industry from the product (fintech ≠ kids education).
|
|
73
|
+
2. Pick mood keywords (e.g. “editorial + precise”, “warm workshop”, “clinical calm”).
|
|
74
|
+
3. Map mood → token roles and signature — **then** implement with morya-ui.
|
|
75
|
+
4. Discard any suggestion to switch stacks (shadcn, generic Tailwind kit, etc.).
|
|
76
|
+
|
|
77
|
+
## Quality floor (all lanes)
|
|
78
|
+
|
|
79
|
+
- Responsive to a usable mobile layout
|
|
80
|
+
- Visible `:focus-visible`
|
|
81
|
+
- Keyboard reaches primary actions
|
|
82
|
+
- No raw theme colors that break dark mode when the app supports it
|
|
83
|
+
- Icons decorative vs informative handled correctly (`aria-hidden` vs `aria-label`)
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Vue 3 + TypeScript 业务代码风格(Morya UI 项目)
|
|
3
|
+
globs: "**/*.{ts,vue}"
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# 编码风格
|
|
8
|
+
|
|
9
|
+
## Vue
|
|
10
|
+
|
|
11
|
+
- 使用 `<script setup lang="ts">`。
|
|
12
|
+
- 组件名 PascalCase;模板中用 `M*` 前缀组件。
|
|
13
|
+
- `v-model` 与组件库 emit 对齐(如 `v-model:page`)。
|
|
14
|
+
- 页面级样式 `scoped`;仅使用 `--m-*` 与设计令牌。
|
|
15
|
+
|
|
16
|
+
## TypeScript
|
|
17
|
+
|
|
18
|
+
- Props/emit 显式类型;避免 `any`。
|
|
19
|
+
- 异步提交:`loading` ref + `try/finally`。
|
|
20
|
+
|
|
21
|
+
## 文件组织
|
|
22
|
+
|
|
23
|
+
```text
|
|
24
|
+
src/
|
|
25
|
+
views/ # 路由页面
|
|
26
|
+
components/ # 业务组件
|
|
27
|
+
composables/ # 复用逻辑
|
|
28
|
+
api/ # 请求层
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## 命名
|
|
32
|
+
|
|
33
|
+
- 页面:`UserListView.vue` / `UserFormView.vue`
|
|
34
|
+
- 路由 path kebab-case:`/users/create`
|
|
35
|
+
|
|
36
|
+
## 检查
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
pnpm check:colors # 裸色值扫描
|
|
40
|
+
pnpm typecheck
|
|
41
|
+
```
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Morya UI 组件用法与选型(Vue 业务代码)
|
|
3
|
+
globs: src/**/*.vue
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# 组件用法
|
|
8
|
+
|
|
9
|
+
## 引入
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
import { MButton, MInput } from 'morya-ui'
|
|
13
|
+
// 按需:import MButton from 'morya-ui/button'
|
|
14
|
+
// import 'morya-ui/button/style'
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## 必选模式
|
|
18
|
+
|
|
19
|
+
- 表单:`MForm` + `MFormItem` + 字段组件;提交用 `@submit` + `type="submit"`。
|
|
20
|
+
- 表格:`MTable` 的 `columns` + `data` + `row-key`;单元格用 `#cell-{key}` 插槽。
|
|
21
|
+
- 浮层:详情/编辑 `MDialog`;侧栏 `MDrawer`;删除确认 `MConfirmDialog`。
|
|
22
|
+
- 反馈(**默认 Message**):
|
|
23
|
+
- 单行操作结果 → `message.success/info/warn/error('…')`
|
|
24
|
+
- 有标题 + 详情 / 异步通知 → `toast.*({ summary, detail })`
|
|
25
|
+
- 表单区常驻错误 → `<MMessage>` 或字段 `errorMessage`
|
|
26
|
+
- 详见 `docs/feedback-message-vs-toast.md`
|
|
27
|
+
|
|
28
|
+
## Props 约定
|
|
29
|
+
|
|
30
|
+
- 尺寸:`size="small" | "large"`(默认 medium)。
|
|
31
|
+
- 危险:`severity="danger"` 或 `invalid` + `errorMessage`。
|
|
32
|
+
- 清除:优先 `clearable`(Select 亦支持 `showClear` 别名)。
|
|
33
|
+
- 宽度:表单字段 `fluid`;页面级宽度用 layout CSS + `max-width`。
|
|
34
|
+
|
|
35
|
+
## 禁止
|
|
36
|
+
|
|
37
|
+
- 同一页面混用其他 UI 库。
|
|
38
|
+
- 用 `MDropdown` 代替 Select 做枚举选择。
|
|
39
|
+
- 手写 table/modal 替代 `MTable` / `MDialog`。
|
|
40
|
+
|
|
41
|
+
完整清单:`docs/components.md`
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Morya UI 设计系统第一信源。生成或修改 UI 前必读 DESIGN.md 与 design-tokens。
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Morya UI 设计系统
|
|
7
|
+
|
|
8
|
+
1. **先读** 项目根目录 `DESIGN.md`,再读 `docs/components.md`。
|
|
9
|
+
2. **只用** `morya-ui` 的 `M*` 组件;全局样式 `morya-ui/styles.css`。
|
|
10
|
+
3. **颜色/间距/圆角** 使用 `--m-*` CSS 变量,禁止裸 hex/rgb(见 `scripts/check-raw-colors.mjs`)。
|
|
11
|
+
4. **页面结构** 对齐 `docs/golden-pages/`(列表 / 表单 / 仪表盘 / 登录 / 落地 / 空状态),不要发明新布局范式。
|
|
12
|
+
5. **表单选项** 用 `MSelect` / `MTreeSelect`;**动作菜单** 用 `MDropdown`。
|
|
13
|
+
6. 不确定 API 时查文档站或 MCP,**禁止臆造 prop**。
|
|
14
|
+
7. 根节点用 `MConfigProvider`;后台布局用 `MLayout` 系列。
|
|
15
|
+
8. **操作反馈默认 `message` API**;仅 `summary + detail` 或异步通知用 `toast`;表单常驻错误用 `<MMessage>`。见 `docs/feedback-message-vs-toast.md`。
|
|
16
|
+
|
|
17
|
+
Token 参考:`design-tokens/tokens.json`
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: 生成 Morya UI 业务页面(列表/表单/仪表盘)时的布局规范
|
|
3
|
+
alwaysApply: false
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# 页面布局(Agent Requested)
|
|
7
|
+
|
|
8
|
+
生成完整页面时,先确定类型并 **复制黄金样例结构**:
|
|
9
|
+
|
|
10
|
+
| 类型 | 模板 |
|
|
11
|
+
| --- | --- |
|
|
12
|
+
| 列表页 | `docs/golden-pages/list-page.vue` |
|
|
13
|
+
| 表单页 | `docs/golden-pages/form-page.vue` |
|
|
14
|
+
| 仪表盘 | `docs/golden-pages/dashboard-page.vue` |
|
|
15
|
+
| 登录页 | `docs/golden-pages/login-page.vue` |
|
|
16
|
+
| 营销落地 | `docs/golden-pages/landing-page.vue` |
|
|
17
|
+
| 空状态 | `docs/golden-pages/empty-state.vue` |
|
|
18
|
+
|
|
19
|
+
## 列表页区块顺序
|
|
20
|
+
|
|
21
|
+
1. `MLayout fillViewport` + 可选 `MLayoutSider bordered`
|
|
22
|
+
2. `MLayoutHeader` → `MBreadcrumb`
|
|
23
|
+
3. `MLayoutContent` → `MPageContent`
|
|
24
|
+
4. `MPageFilters`(内 `MSpace` + Input/Select + 查询/重置)
|
|
25
|
+
5. `MPageToolbar`(标题 + `#actions` 主操作)
|
|
26
|
+
6. `MTable`(直接放置,通常不必包 `MCard`)
|
|
27
|
+
7. 分页由 `MTable paginator` 或同级 `MPagination`
|
|
28
|
+
|
|
29
|
+
## 表单页区块顺序
|
|
30
|
+
|
|
31
|
+
1. `MLayout fillViewport` → `MLayoutHeader` → `MBreadcrumb`
|
|
32
|
+
2. `MPageContent width="narrow"`
|
|
33
|
+
3. `MPageHeader`(标题 + 说明)
|
|
34
|
+
4. `MPageSection variant="form"` → `MForm`
|
|
35
|
+
5. `MPageSection variant="actions"`:保存(primary)+ 取消(secondary)
|
|
36
|
+
|
|
37
|
+
## 仪表盘区块顺序
|
|
38
|
+
|
|
39
|
+
1. `MLayout fillViewport` → `MLayoutHeader` → `MBreadcrumb`
|
|
40
|
+
2. `MPageContent density="spacious"` → `MPageHeader`
|
|
41
|
+
3. KPI:`MGrid` + `MPageStat`(4 列或响应式)
|
|
42
|
+
4. 主区两栏:`MCard` + `MPagePlaceholder` / 最近列表 `MTable`
|
|
43
|
+
|
|
44
|
+
## 页面标准
|
|
45
|
+
|
|
46
|
+
推荐实践(非强制),完整列表见 MCP `get_design_rules` → `standards`:
|
|
47
|
+
|
|
48
|
+
| 主题 | 推荐 | 通常不必 |
|
|
49
|
+
| --- | --- | --- |
|
|
50
|
+
| 骨架 | `MLayout fillViewport` + `MPageContent` | 手写 `min-height:100vh`;`MLayoutContent` 再写 padding |
|
|
51
|
+
| 区块 | `MPageFilters` / `MPageToolbar` / `MPageSection` | 手写 `.page-*`;`MCard` 再包一层 |
|
|
52
|
+
| 列表表格 | `MTable` 直接放在 `MPageContent` | 用 `MCard` 再包 bordered 表格 |
|
|
53
|
+
| 控件间距 | 同行用 `MSpace` / `MFlex`;区块靠 `MPageContent` gap | 外包 padded `div` 叠间距 |
|
|
54
|
+
| 滚动 | 组件内置滚动壳用 `MScrollbar`;Dialog/Drawer 等内容留给业务 | 在用户内容区强行内置滚动 |
|
|
55
|
+
| 颜色 | `--m-*` Token | 页面级 hex / 裸 rgb() |
|
|
56
|
+
| 反馈 | 单行结果用 `message`;危险操作用 `MConfirmDialog` | 仅一行文案却用 toast |
|
|
57
|
+
| 无障碍 | 图标按钮 `aria-label`、表单可见 label | — |
|
|
58
|
+
|
|
59
|
+
仅允许控件宽度等局部 inline style(如筛选项 `width: 14rem`)。
|
|
60
|
+
|
|
61
|
+
## MCP
|
|
62
|
+
|
|
63
|
+
- 整页:`recommend_page` → `get_golden_page` → `get_design_rules`
|
|
64
|
+
- 局部:`get_page_snippet`(如 `filters` / `toolbar` / `form-actions` / `scrollable-panel`)
|
|
65
|
+
- 可选:`validate_page`(参考建议,不阻断)
|
|
66
|
+
|
|
67
|
+
引用可运行示例:`src/examples/*PageExample.vue`
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# Morya UI 设计系统(AI 第一信源)
|
|
2
|
+
|
|
3
|
+
> 基于 `morya-ui` v0.1.x。生成或审查业务页面时,**必须先遵守本文**,再查阅 `docs/components.md` 与 `docs/golden-pages/`。
|
|
4
|
+
|
|
5
|
+
## 1. 设计原则
|
|
6
|
+
|
|
7
|
+
1. **组件优先**:布局、表单、表格、浮层一律使用库内 `M*` 组件,不手写等价 DOM 结构。
|
|
8
|
+
2. **令牌优先**:颜色、间距、圆角、阴影、动效使用 `--m-*` CSS 变量;禁止裸 `#hex` / `rgb()`(`scripts/check-raw-colors.mjs` 会扫描)。
|
|
9
|
+
3. **语义一致**:主操作 `MButton` `severity="primary"`;危险操作用 `severity="danger"` 或 `MConfirmDialog`。
|
|
10
|
+
4. **可访问性**:表单控件带 `label`;图标按钮带 `aria-label`;浮层可 Esc 关闭(组件默认支持)。
|
|
11
|
+
5. **ConfigProvider 包裹**:应用根节点使用 `MConfigProvider`,统一 locale、主题、密度、浮层挂载。
|
|
12
|
+
|
|
13
|
+
## 2. 应用骨架
|
|
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 has-sider>
|
|
24
|
+
<MLayoutSider>...</MLayoutSider>
|
|
25
|
+
<MLayout>
|
|
26
|
+
<MLayoutHeader>...</MLayoutHeader>
|
|
27
|
+
<MLayoutContent>...</MLayoutContent>
|
|
28
|
+
</MLayout>
|
|
29
|
+
</MLayout>
|
|
30
|
+
</MConfigProvider>
|
|
31
|
+
</template>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
- 管理后台:`MLayout fillViewport` + `MLayoutSider` + `MLayoutHeader` + `MLayoutContent`
|
|
35
|
+
- 页面内容堆叠:`MPageContent`(内置于 `MLayoutContent`)
|
|
36
|
+
- 列表筛选 / 工具栏:`MPageFilters` + `MPageToolbar`
|
|
37
|
+
- 表单引导 / 表面:`MPageHeader` + `MPageSection variant="form|actions"`
|
|
38
|
+
- 仪表盘 KPI / 占位:`MPageStat` + `MPagePlaceholder`
|
|
39
|
+
- 其他分区:`MCard`(图表/明细模块)/ `MPanel` / `MFieldset`
|
|
40
|
+
- 栅格:`MGrid` + `MGridItem` 或 `MFlex` + `MSpace`
|
|
41
|
+
|
|
42
|
+
## 3. 页面类型与黄金样例
|
|
43
|
+
|
|
44
|
+
| 类型 | 参考文件 | 必备区块 |
|
|
45
|
+
| --- | --- | --- |
|
|
46
|
+
| 列表页 | `docs/golden-pages/list-page.vue` | 面包屑、筛选区、工具栏、表格、分页 |
|
|
47
|
+
| 表单页 | `docs/golden-pages/form-page.vue` | 面包屑、分组表单、`MForm` / `MFormItem`、提交/取消 |
|
|
48
|
+
| 仪表盘 | `docs/golden-pages/dashboard-page.vue` | 统计卡片栅格、图表区占位、快捷入口 / 最近列表 |
|
|
49
|
+
| 登录页 | `docs/golden-pages/login-page.vue` | 品牌区 + `MForm` / `MInputPassword`;表单级错误用 token 告警条 |
|
|
50
|
+
| 营销落地 | `docs/golden-pages/landing-page.vue` | 单任务首屏、分节、`MButton` / `MTag` / `MAccordion` |
|
|
51
|
+
| 空状态 | `docs/golden-pages/empty-state.vue` | `MEmpty` + 说明 + 主 CTA;可嵌列表 `#empty` |
|
|
52
|
+
|
|
53
|
+
生成 **Ops** 页面时:结构对齐对应黄金样例,用 `MPage*` 拼装,尽量少写 scoped CSS。
|
|
54
|
+
生成 **Account / Express / Flow** 页面时:对齐上表样例;允许有节制的 scoped 布局,但颜色/间距仍用 `--m-*`。
|
|
55
|
+
|
|
56
|
+
## 4. 表单约定
|
|
57
|
+
|
|
58
|
+
- 使用 `MForm` + `MFormItem`,`name` 与校验规则对应。
|
|
59
|
+
- 字段组件自带 `label` / `invalid` / `helpText` 时优先用组件 prop(如 `MInput`、`MSelect`),复杂表单再用 `MFormItem` 包一层。
|
|
60
|
+
- 尺寸:默认 medium;密集后台可 `size="small"` 或 ConfigProvider `globalDensity`。
|
|
61
|
+
- 宽度:筛选项 `fluid` 慎用;表单页主栏 `max-width: 40rem` 左右。
|
|
62
|
+
|
|
63
|
+
## 5. 数据展示
|
|
64
|
+
|
|
65
|
+
- 表格:`MTable` + 列定义;行操作放 `MButton` text/link 或 `MDropdown`。
|
|
66
|
+
- 分页:`MPagination` 与表格同级,右对齐或居中。
|
|
67
|
+
- 空态:表格 `emptyMessage` 或自定义 `#empty` 插槽;禁止空白区域无提示。
|
|
68
|
+
|
|
69
|
+
## 6. 浮层与反馈
|
|
70
|
+
|
|
71
|
+
| 场景 | 组件 |
|
|
72
|
+
| --- | --- |
|
|
73
|
+
| 确认删除 | `MConfirmDialog` 或 `MConfirmPopup` |
|
|
74
|
+
| 详情 / 编辑弹窗 | `MDialog` |
|
|
75
|
+
| 侧滑筛选 / 详情 | `MDrawer` |
|
|
76
|
+
| **操作结果(默认)** | **`message` API**(单行:已保存 / 已删除) |
|
|
77
|
+
| 标题 + 详情 / 异步通知 | `toast` API(`summary` + `detail`) |
|
|
78
|
+
| 表单区常驻错误 | token 告警条 / 字段 `errorMessage` |
|
|
79
|
+
| 字段说明 | `MTooltip` |
|
|
80
|
+
|
|
81
|
+
**选型细则见 [`docs/feedback-message-vs-toast.md`](docs/feedback-message-vs-toast.md)。AI 生成代码时:无 `detail` 的操作回执一律用 `message`,不要默认 Toast。**
|
|
82
|
+
|
|
83
|
+
## 7. 设计令牌(摘要)
|
|
84
|
+
|
|
85
|
+
完整定义见 `design-tokens/tokens.json`。
|
|
86
|
+
|
|
87
|
+
| 用途 | 变量 |
|
|
88
|
+
| --- | --- |
|
|
89
|
+
| 页面背景 | `--m-color-surface` |
|
|
90
|
+
| 正文 | `--m-color-text` |
|
|
91
|
+
| 次要文字 | `--m-color-text-muted` |
|
|
92
|
+
| 边框 | `--m-color-border` |
|
|
93
|
+
| 品牌 / 链接 | `--m-color-primary` |
|
|
94
|
+
| 错误 | `--m-color-danger` |
|
|
95
|
+
| 区块间距 | `--m-space-4` / `--m-space-6` |
|
|
96
|
+
| 卡片圆角 | `--m-radius-md` |
|
|
97
|
+
| 卡片阴影 | `--m-shadow-md` |
|
|
98
|
+
|
|
99
|
+
## 8. 禁止项
|
|
100
|
+
|
|
101
|
+
- 禁止引入第二套 UI 库(Element Plus、Naive UI 等)混用同一页面。
|
|
102
|
+
- 禁止在业务 CSS 中写死主题色;暗色模式必须能随 `[data-theme="dark"]` 生效。
|
|
103
|
+
- 禁止用 `<div onclick>` 代替 `<button>` / `MButton`。
|
|
104
|
+
- 禁止 Select 与 Dropdown 混用:选项选择用 `MSelect` / `MTreeSelect`;动作菜单用 `MDropdown`。
|
|
105
|
+
- 禁止跳过 `import 'morya-ui/styles.css'`。
|
|
106
|
+
|
|
107
|
+
## 9. AI 工作流
|
|
108
|
+
|
|
109
|
+
1. 读本文 → 确定页面类型(列表 / 表单 / 仪表盘)。
|
|
110
|
+
2. 打开对应 `docs/golden-pages/*.vue` 与 `src/examples/*.vue`。
|
|
111
|
+
3. 查 `docs/components.md` 选型。
|
|
112
|
+
4. 不确定 API 时查文档站或 MCP,**不要臆造 prop 名**。
|
|
113
|
+
5. 完成后运行 `pnpm check:colors`(若已配置)。
|
|
114
|
+
6. 操作反馈见 `docs/feedback-message-vs-toast.md`:**默认 `message`,有 detail 才用 `toast`**。
|
|
115
|
+
|
|
116
|
+
## 10. 相关资源
|
|
117
|
+
|
|
118
|
+
- 包入口:`morya-ui`
|
|
119
|
+
- 全局样式:`morya-ui/styles.css`
|
|
120
|
+
- 按需引入:`morya-ui/button` 等 + 对应 `style`
|
|
121
|
+
- 主题 API:`useTheme` / `useDensity` / `useMotion`(同包导出)
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Morya UI design tokens (compiled view for AI / static tooling).
|
|
3
|
+
* Runtime source of truth: morya-ui/styles.css
|
|
4
|
+
* Do not hand-edit hex values in business code — use --m-* variables.
|
|
5
|
+
*/
|
|
6
|
+
:root {
|
|
7
|
+
--m-color-primary: #2563eb;
|
|
8
|
+
--m-color-primary-hover: #1d4ed8;
|
|
9
|
+
--m-color-surface: #ffffff;
|
|
10
|
+
--m-color-text: #0f172a;
|
|
11
|
+
--m-color-text-muted: #64748b;
|
|
12
|
+
--m-color-border: #e2e8f0;
|
|
13
|
+
--m-color-focus-ring: #2563eb;
|
|
14
|
+
--m-color-success: #159570;
|
|
15
|
+
--m-color-info: #2563eb;
|
|
16
|
+
--m-color-warning: #d97706;
|
|
17
|
+
--m-color-help: #9333ea;
|
|
18
|
+
--m-color-danger: #dc2626;
|
|
19
|
+
--m-color-contrast: #0f172a;
|
|
20
|
+
--m-color-contrast-fg: #ffffff;
|
|
21
|
+
--m-overlay-scrim: rgb(15 23 42 / 0.55);
|
|
22
|
+
|
|
23
|
+
--m-control-height-small: 28px;
|
|
24
|
+
--m-control-height-medium: 34px;
|
|
25
|
+
--m-control-height-large: 40px;
|
|
26
|
+
--m-radius-control: 3px;
|
|
27
|
+
--m-space-1: 0.25rem;
|
|
28
|
+
--m-space-2: 0.5rem;
|
|
29
|
+
--m-space-3: 0.75rem;
|
|
30
|
+
--m-space-4: 1rem;
|
|
31
|
+
--m-space-6: 1.5rem;
|
|
32
|
+
--m-space-8: 2rem;
|
|
33
|
+
--m-radius-sm: 0.25rem;
|
|
34
|
+
--m-radius-md: 0.5rem;
|
|
35
|
+
--m-radius-lg: 0.75rem;
|
|
36
|
+
--m-shadow-sm: 0 1px 2px rgb(15 23 42 / 0.25);
|
|
37
|
+
--m-shadow-md: 0 0.75rem 2rem rgb(15 23 42 / 0.16);
|
|
38
|
+
--m-shadow-lg: 0 1rem 3rem rgb(15 23 42 / 0.25);
|
|
39
|
+
--m-font-sans: Inter, ui-sans-serif, system-ui, sans-serif;
|
|
40
|
+
--m-motion-fast: 150ms;
|
|
41
|
+
--m-motion-normal: 250ms;
|
|
42
|
+
--m-motion-ease: cubic-bezier(0.2, 0, 0, 1);
|
|
43
|
+
--m-z-base: 1000;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
[data-theme="dark"] {
|
|
47
|
+
--m-color-primary: #60a5fa;
|
|
48
|
+
--m-color-primary-hover: #93c5fd;
|
|
49
|
+
--m-color-surface: #0f172a;
|
|
50
|
+
--m-color-text: #f8fafc;
|
|
51
|
+
--m-color-text-muted: #94a3b8;
|
|
52
|
+
--m-color-border: #334155;
|
|
53
|
+
--m-color-danger: #fca5a5;
|
|
54
|
+
--m-overlay-scrim: rgb(2 6 23 / 0.72);
|
|
55
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://design-tokens.github.io/community-group/format/",
|
|
3
|
+
"meta": {
|
|
4
|
+
"name": "morya-ui",
|
|
5
|
+
"version": "0.1.1",
|
|
6
|
+
"source": "morya-ui/src/theme/styles.css",
|
|
7
|
+
"prefix": "m"
|
|
8
|
+
},
|
|
9
|
+
"color": {
|
|
10
|
+
"primary": { "value": "#2563eb", "dark": "#60a5fa" },
|
|
11
|
+
"primary-hover": { "value": "#1d4ed8", "dark": "#93c5fd" },
|
|
12
|
+
"surface": { "value": "#ffffff", "dark": "#0f172a" },
|
|
13
|
+
"text": { "value": "#0f172a", "dark": "#f8fafc" },
|
|
14
|
+
"text-muted": { "value": "#64748b", "dark": "#94a3b8" },
|
|
15
|
+
"border": { "value": "#e2e8f0", "dark": "#334155" },
|
|
16
|
+
"focus-ring": { "value": "#2563eb", "dark": "#93c5fd" },
|
|
17
|
+
"success": { "value": "#159570", "dark": "#5eead4" },
|
|
18
|
+
"info": { "value": "#2563eb", "dark": "#93c5fd" },
|
|
19
|
+
"warning": { "value": "#d97706", "dark": "#fbbf24" },
|
|
20
|
+
"help": { "value": "#9333ea", "dark": "#c084fc" },
|
|
21
|
+
"danger": { "value": "#dc2626", "dark": "#fca5a5" },
|
|
22
|
+
"contrast": { "value": "#0f172a", "dark": "#f8fafc" },
|
|
23
|
+
"contrast-fg": { "value": "#ffffff", "dark": "#0f172a" },
|
|
24
|
+
"overlay-scrim": { "value": "rgb(15 23 42 / 0.55)", "dark": "rgb(2 6 23 / 0.72)" }
|
|
25
|
+
},
|
|
26
|
+
"control": {
|
|
27
|
+
"height": { "small": "28px", "medium": "34px", "large": "40px" },
|
|
28
|
+
"font": { "small": "14px", "medium": "14px", "large": "15px" },
|
|
29
|
+
"padding-x": { "small": "10px", "medium": "12px", "large": "14px" },
|
|
30
|
+
"affix-size": "2rem"
|
|
31
|
+
},
|
|
32
|
+
"space": {
|
|
33
|
+
"1": "0.25rem",
|
|
34
|
+
"2": "0.5rem",
|
|
35
|
+
"3": "0.75rem",
|
|
36
|
+
"4": "1rem",
|
|
37
|
+
"6": "1.5rem",
|
|
38
|
+
"8": "2rem"
|
|
39
|
+
},
|
|
40
|
+
"radius": {
|
|
41
|
+
"control": "3px",
|
|
42
|
+
"sm": "0.25rem",
|
|
43
|
+
"md": "0.5rem",
|
|
44
|
+
"lg": "0.75rem",
|
|
45
|
+
"full": "9999px"
|
|
46
|
+
},
|
|
47
|
+
"shadow": {
|
|
48
|
+
"sm": "0 1px 2px rgb(15 23 42 / 0.25)",
|
|
49
|
+
"md": "0 0.75rem 2rem rgb(15 23 42 / 0.16)",
|
|
50
|
+
"lg": "0 1rem 3rem rgb(15 23 42 / 0.25)"
|
|
51
|
+
},
|
|
52
|
+
"font": {
|
|
53
|
+
"sans": "Inter, ui-sans-serif, system-ui, sans-serif",
|
|
54
|
+
"size": { "xs": "0.75rem", "sm": "0.8125rem", "md": "0.875rem", "lg": "1.125rem" }
|
|
55
|
+
},
|
|
56
|
+
"motion": {
|
|
57
|
+
"fast": "150ms",
|
|
58
|
+
"normal": "250ms",
|
|
59
|
+
"ease": "cubic-bezier(0.2, 0, 0, 1)"
|
|
60
|
+
},
|
|
61
|
+
"zIndex": {
|
|
62
|
+
"base": 1000,
|
|
63
|
+
"dropdown": "calc(var(--m-z-base) + 50)",
|
|
64
|
+
"toast": "calc(var(--m-z-base) + 100)"
|
|
65
|
+
},
|
|
66
|
+
"cssVarMap": {
|
|
67
|
+
"color.primary": "--m-color-primary",
|
|
68
|
+
"color.surface": "--m-color-surface",
|
|
69
|
+
"color.text": "--m-color-text",
|
|
70
|
+
"color.textMuted": "--m-color-text-muted",
|
|
71
|
+
"color.border": "--m-color-border",
|
|
72
|
+
"color.danger": "--m-color-danger",
|
|
73
|
+
"space.4": "--m-space-4",
|
|
74
|
+
"radius.md": "--m-radius-md",
|
|
75
|
+
"shadow.md": "--m-shadow-md"
|
|
76
|
+
}
|
|
77
|
+
}
|