@omit-design/preset-mobile 0.2.4 → 0.3.0
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/PATTERNS.md +9 -129
- package/package.json +3 -7
- package/patterns.config.json +0 -13
- package/templates/dashboard.tmpl.tsx +0 -90
- package/templates/detail-view.tmpl.tsx +0 -60
- package/templates/dialog-view.tmpl.tsx +0 -34
- package/templates/form-view.tmpl.tsx +0 -52
- package/templates/list-view.tmpl.tsx +0 -58
- package/templates/sheet-action.tmpl.tsx +0 -52
- package/templates/tab-view.tmpl.tsx +0 -51
- package/templates/welcome-view.tmpl.tsx +0 -38
package/PATTERNS.md
CHANGED
|
@@ -1,134 +1,14 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Patterns are project-local
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Starting in 0.3.x, **patterns no longer live in `@omit-design/preset-mobile`**. They live in your project's `patterns/` directory and are owned by you.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
The recommended creation flow is:
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
1. Write a PRD in the workspace's **Library → PRDs** tab
|
|
8
|
+
2. Click "Copy Claude prompt" and paste into Claude Code
|
|
9
|
+
3. The `new-design` skill picks an existing pattern, or — if nothing fits — calls `add-pattern` to create one and writes it into `<project>/patterns/<name>/`
|
|
10
|
+
4. Review and tweak the new pattern in **Library → Patterns**
|
|
8
11
|
|
|
9
|
-
|
|
12
|
+
Eight starter patterns ship with `omit-design init` (`list-view`, `detail-view`, `form-view`, `sheet-action`, `dialog-view`, `welcome-view`, `dashboard`, `tab-view`). Use `init --no-starters` to opt out.
|
|
10
13
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
**用途**:一屏内展示同质条目的集合,每个条目可点击进详情。
|
|
14
|
-
|
|
15
|
-
**骨架**:
|
|
16
|
-
- `OmHeader` — 标题(含或不含返回)
|
|
17
|
-
- 可选:`OmSearchBar` / tab 条 / 分类胶囊
|
|
18
|
-
- `IonList` 或原生 `div` 包裹一组行(`OmListRow` / `OmCouponCard` / `OmSettingRow` / 自定义卡)
|
|
19
|
-
- 列表空态:`OmEmptyState` 居中提示
|
|
20
|
-
|
|
21
|
-
**Template**:[./templates/list-view.tmpl.tsx](./templates/list-view.tmpl.tsx)
|
|
22
|
-
|
|
23
|
-
**何时不用**:条目数 ≤ 3 → 用 `dashboard` 或单独卡片
|
|
24
|
-
|
|
25
|
-
---
|
|
26
|
-
|
|
27
|
-
## detail-view
|
|
28
|
-
|
|
29
|
-
**用途**:从列表跳进的单条详情,通常带主操作按钮。
|
|
30
|
-
|
|
31
|
-
**骨架**:
|
|
32
|
-
- `OmHeader` + `IonBackButton`(返回上一级)
|
|
33
|
-
- `OmCard`(基本信息)
|
|
34
|
-
- 0~N 个 `OmCard` / 列表分块(关联信息分区)
|
|
35
|
-
- 底部 1 个主操作 `OmButton expand="block"` 或「取消 / 确认」双按钮
|
|
36
|
-
|
|
37
|
-
**Template**:[./templates/detail-view.tmpl.tsx](./templates/detail-view.tmpl.tsx)
|
|
38
|
-
|
|
39
|
-
**何时不用**:编辑场景 → 用 `form-view`
|
|
40
|
-
|
|
41
|
-
---
|
|
42
|
-
|
|
43
|
-
## form-view
|
|
44
|
-
|
|
45
|
-
**用途**:新建或编辑一条记录。
|
|
46
|
-
|
|
47
|
-
**骨架**:
|
|
48
|
-
- `OmHeader` + `IonBackButton`(返回/取消)
|
|
49
|
-
- 一组 `OmInput` / `OmSelect`,按业务分组
|
|
50
|
-
- 内联错误态(红框 + 红色辅助文案)
|
|
51
|
-
- 底部固定 `OmButton expand="block"` 提交
|
|
52
|
-
- 可选:提交结果用 `OmDialog` 弹出
|
|
53
|
-
|
|
54
|
-
**Template**:[./templates/form-view.tmpl.tsx](./templates/form-view.tmpl.tsx)
|
|
55
|
-
|
|
56
|
-
---
|
|
57
|
-
|
|
58
|
-
## sheet-action
|
|
59
|
-
|
|
60
|
-
**用途**:从底部弹起的操作菜单 / 详情抽屉,避免离开当前上下文。设计稿语境下不走 JS 回调,而是每个 sheet 一张独立稿(同 `dialog-view` 哲学)。
|
|
61
|
-
|
|
62
|
-
**骨架**:
|
|
63
|
-
- `OmPage padding="none"`
|
|
64
|
-
- `OmSheet title="..." dismissHref="..."` 内部放:
|
|
65
|
-
- 一组按钮条(菜单形态)
|
|
66
|
-
- 或纯信息块(明细形态)
|
|
67
|
-
- 关闭行为:点击 scrim / 右上 × / 菜单条任意一项跳转走
|
|
68
|
-
|
|
69
|
-
**Template**:[./templates/sheet-action.tmpl.tsx](./templates/sheet-action.tmpl.tsx)
|
|
70
|
-
|
|
71
|
-
**何时不用**:只展示一句提示 + 单按钮 → `dialog-view`;需要录入 → `form-view`
|
|
72
|
-
|
|
73
|
-
---
|
|
74
|
-
|
|
75
|
-
## dialog-view
|
|
76
|
-
|
|
77
|
-
**用途**:把一个"对话框状态"当成一张独立的设计稿。设计稿工具语境下,弹窗不是 JS 回调,而是一张可独立访问的稿 — 每个状态有 URL、侧边目录里可点。
|
|
78
|
-
|
|
79
|
-
**骨架**:
|
|
80
|
-
- `OmPage padding="none" header={<OmHeader .../>}`(通常复用来源页的 header)
|
|
81
|
-
- 背景层:来源页的 frozen 快照(表单禁用,仅作视觉背景),或纯渐变背景
|
|
82
|
-
- `OmDialog` — icon / title / subtitle + 一个主按钮;按钮通过 `confirmHref` 跳转到下一张稿
|
|
83
|
-
|
|
84
|
-
**Template**:[./templates/dialog-view.tmpl.tsx](./templates/dialog-view.tmpl.tsx)
|
|
85
|
-
|
|
86
|
-
**何时不用**:需要输入 / 选项 → 独立 `form-view`;纯操作菜单 → `sheet-action`
|
|
87
|
-
|
|
88
|
-
---
|
|
89
|
-
|
|
90
|
-
## welcome-view
|
|
91
|
-
|
|
92
|
-
**用途**:启动 / 欢迎 / 引导页。品牌 logo + 一句话欢迎语 + 单一主 CTA。不接任何表单。
|
|
93
|
-
|
|
94
|
-
**骨架**:
|
|
95
|
-
- `OmPage padding="none"` 自己控制留白
|
|
96
|
-
- 品牌头区:LOGO + 品名(可含副标题)
|
|
97
|
-
- 欢迎语:主标题 + 描述
|
|
98
|
-
- 底部单一 `OmButton expand="block"` 主操作
|
|
99
|
-
- 可选:最底部版本号
|
|
100
|
-
|
|
101
|
-
**Template**:[./templates/welcome-view.tmpl.tsx](./templates/welcome-view.tmpl.tsx)
|
|
102
|
-
|
|
103
|
-
**何时不用**:带输入 → `form-view`;功能介绍多屏滑动 → 需新增 `onboarding-carousel` 模式
|
|
104
|
-
|
|
105
|
-
---
|
|
106
|
-
|
|
107
|
-
## dashboard
|
|
108
|
-
|
|
109
|
-
**用途**:工作台 / 首页式聚合页 — 顶部状态指标(数字卡)+ 功能宫格入口。
|
|
110
|
-
非 tab 导航、非列表、非表单,而是多入口聚合。
|
|
111
|
-
|
|
112
|
-
**骨架**:
|
|
113
|
-
- `OmHeader` + 返回
|
|
114
|
-
- 若干 `OmStatCard`(指标区)
|
|
115
|
-
- 3 列 `OmMenuCard` 宫格(主功能入口,可用 `disabled + badge="二期"` 标灰态)
|
|
116
|
-
|
|
117
|
-
**Template**:[./templates/dashboard.tmpl.tsx](./templates/dashboard.tmpl.tsx)
|
|
118
|
-
|
|
119
|
-
**何时不用**:单一主操作 → `welcome-view`;扁平列表 → `list-view`
|
|
120
|
-
|
|
121
|
-
---
|
|
122
|
-
|
|
123
|
-
## tab-view
|
|
124
|
-
|
|
125
|
-
**用途**:底部主导航 tab 之一 — 主品牌 header + 主体内容 + 底部 4 个 tab 切换。
|
|
126
|
-
|
|
127
|
-
**骨架**:
|
|
128
|
-
- `OmAppBar variant="brand"` 顶部品牌标题 + 右上角头像
|
|
129
|
-
- 主体内容(表单 / 列表 / 卡片 / 空态)
|
|
130
|
-
- 底部 `OmTabBar` 多个主 tab
|
|
131
|
-
|
|
132
|
-
**Template**:[./templates/tab-view.tmpl.tsx](./templates/tab-view.tmpl.tsx)
|
|
133
|
-
|
|
134
|
-
**何时不用**:无底部 tab 导航(如独立表单页)→ `form-view`
|
|
14
|
+
For the description and skeleton of each starter, read its `README.md` under your project's `patterns/<name>/`.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@omit-design/preset-mobile",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Mobile design preset for omit-design: Om* whitelist components, --om-* / --ion-* token map, Ionic 8 runtime.",
|
|
6
6
|
"main": "./index.ts",
|
|
@@ -13,20 +13,16 @@
|
|
|
13
13
|
"./components": "./components/index.ts",
|
|
14
14
|
"./tokens": "./tokens/index.ts",
|
|
15
15
|
"./preset.manifest": "./preset.manifest.ts",
|
|
16
|
-
"./theme/variables.css": "./theme/variables.css"
|
|
17
|
-
"./templates/*": "./templates/*",
|
|
18
|
-
"./PATTERNS.md": "./PATTERNS.md"
|
|
16
|
+
"./theme/variables.css": "./theme/variables.css"
|
|
19
17
|
},
|
|
20
18
|
"files": [
|
|
21
19
|
"index.ts",
|
|
22
20
|
"components",
|
|
23
21
|
"tokens",
|
|
24
22
|
"theme",
|
|
25
|
-
"templates",
|
|
26
23
|
"preset.manifest.ts",
|
|
27
24
|
"catalog.tsx",
|
|
28
25
|
"PATTERNS.md",
|
|
29
|
-
"patterns.config.json",
|
|
30
26
|
"README.md"
|
|
31
27
|
],
|
|
32
28
|
"license": "MIT",
|
|
@@ -42,7 +38,7 @@
|
|
|
42
38
|
},
|
|
43
39
|
"peerDependencies": {
|
|
44
40
|
"@ionic/react": "^8",
|
|
45
|
-
"@omit-design/engine": "^0.
|
|
41
|
+
"@omit-design/engine": "^0.3.0",
|
|
46
42
|
"ionicons": "^7 || ^8",
|
|
47
43
|
"react": "^19",
|
|
48
44
|
"react-router-dom": "^6"
|
package/patterns.config.json
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "./patterns.schema.json",
|
|
3
|
-
"patterns": {
|
|
4
|
-
"list-view": ["OmListRow", "OmCouponCard", "OmSettingRow", "OmProductCard", "OmMenuCard", "OmEmptyState"],
|
|
5
|
-
"detail-view": ["OmCard"],
|
|
6
|
-
"form-view": ["OmInput", "OmSelect", "OmNumpad"],
|
|
7
|
-
"sheet-action": ["OmSheet"],
|
|
8
|
-
"dialog-view": ["OmDialog"],
|
|
9
|
-
"welcome-view": ["OmButton"],
|
|
10
|
-
"dashboard": ["OmStatCard", "OmMenuCard"],
|
|
11
|
-
"tab-view": ["OmTabBar"]
|
|
12
|
-
}
|
|
13
|
-
}
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
// @pattern: dashboard
|
|
2
|
-
// TEMPLATE — 复制到 design/<filename>/<filename>.tsx 后:
|
|
3
|
-
// 1. 替换 meta + hero 文案
|
|
4
|
-
// 2. STATS / TILES 换成真实 mock import
|
|
5
|
-
// 3. 给 TILES 加合适 ionicons + href
|
|
6
|
-
|
|
7
|
-
export const meta = {
|
|
8
|
-
name: "TODO Dashboard",
|
|
9
|
-
pattern: "dashboard",
|
|
10
|
-
description: "TODO one-line description",
|
|
11
|
-
source: "prd",
|
|
12
|
-
} as const;
|
|
13
|
-
|
|
14
|
-
import { IonBackButton } from "@ionic/react";
|
|
15
|
-
import {
|
|
16
|
-
appsOutline,
|
|
17
|
-
cashOutline,
|
|
18
|
-
receiptOutline,
|
|
19
|
-
} from "ionicons/icons";
|
|
20
|
-
import {
|
|
21
|
-
OmHeader,
|
|
22
|
-
OmMenuCard,
|
|
23
|
-
OmPage,
|
|
24
|
-
OmStatCard,
|
|
25
|
-
} from "@omit-design/preset-mobile";
|
|
26
|
-
|
|
27
|
-
interface Stat {
|
|
28
|
-
label: string;
|
|
29
|
-
value: string;
|
|
30
|
-
caption?: string;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
interface Tile {
|
|
34
|
-
id: string;
|
|
35
|
-
icon: string;
|
|
36
|
-
label: string;
|
|
37
|
-
href?: string;
|
|
38
|
-
disabled?: boolean;
|
|
39
|
-
badge?: string;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// TODO: 替换为真实 mock import
|
|
43
|
-
const STATS: Stat[] = [
|
|
44
|
-
{ label: "Today's revenue", value: "$0.00", caption: "Includes settled amount" },
|
|
45
|
-
{ label: "Order count", value: "0", caption: "orders" },
|
|
46
|
-
];
|
|
47
|
-
|
|
48
|
-
const TILES: Tile[] = [
|
|
49
|
-
{ id: "pos", icon: cashOutline, label: "POS", href: "/designs/TODO" },
|
|
50
|
-
{ id: "orders", icon: receiptOutline, label: "Orders", href: "/designs/TODO" },
|
|
51
|
-
];
|
|
52
|
-
|
|
53
|
-
export function TodoDashboardPage() {
|
|
54
|
-
return (
|
|
55
|
-
<OmPage
|
|
56
|
-
padding="lg"
|
|
57
|
-
header={
|
|
58
|
-
<OmHeader
|
|
59
|
-
title="TODO Dashboard"
|
|
60
|
-
start={<IonBackButton defaultHref="/designs/TODO-from" />}
|
|
61
|
-
/>
|
|
62
|
-
}
|
|
63
|
-
>
|
|
64
|
-
<div>
|
|
65
|
-
{STATS.map((s) => (
|
|
66
|
-
<OmStatCard
|
|
67
|
-
key={s.label}
|
|
68
|
-
label={s.label}
|
|
69
|
-
value={s.value}
|
|
70
|
-
caption={s.caption}
|
|
71
|
-
/>
|
|
72
|
-
))}
|
|
73
|
-
</div>
|
|
74
|
-
|
|
75
|
-
<div>
|
|
76
|
-
{TILES.map((t) => (
|
|
77
|
-
<OmMenuCard
|
|
78
|
-
key={t.id}
|
|
79
|
-
icon={t.icon ?? appsOutline}
|
|
80
|
-
label={t.label}
|
|
81
|
-
href={t.href}
|
|
82
|
-
disabled={t.disabled}
|
|
83
|
-
badge={t.badge}
|
|
84
|
-
/>
|
|
85
|
-
))}
|
|
86
|
-
</div>
|
|
87
|
-
</OmPage>
|
|
88
|
-
);
|
|
89
|
-
}
|
|
90
|
-
export default TodoDashboardPage;
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
// @pattern: detail-view
|
|
2
|
-
// TEMPLATE — 复制到 design/<filename>/<filename>.tsx 后:
|
|
3
|
-
// 1. 替换 meta + 字段
|
|
4
|
-
// 2. 把 RECORD 换成真实 mock import
|
|
5
|
-
// 3. 调整 IonBackButton 的 defaultHref
|
|
6
|
-
// 4. 主操作改成业务跳转
|
|
7
|
-
|
|
8
|
-
export const meta = {
|
|
9
|
-
name: "TODO Detail page",
|
|
10
|
-
pattern: "detail-view",
|
|
11
|
-
description: "TODO one-line description",
|
|
12
|
-
source: "prd",
|
|
13
|
-
} as const;
|
|
14
|
-
|
|
15
|
-
import { IonBackButton } from "@ionic/react";
|
|
16
|
-
import {
|
|
17
|
-
OmButton,
|
|
18
|
-
OmCard,
|
|
19
|
-
OmHeader,
|
|
20
|
-
OmPage,
|
|
21
|
-
} from "@omit-design/preset-mobile";
|
|
22
|
-
|
|
23
|
-
interface Record {
|
|
24
|
-
id: string;
|
|
25
|
-
title: string;
|
|
26
|
-
amount: number;
|
|
27
|
-
status: string;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// TODO: 替换为真实 mock import
|
|
31
|
-
const RECORD: Record = {
|
|
32
|
-
id: "TODO",
|
|
33
|
-
title: "Sample title",
|
|
34
|
-
amount: 0,
|
|
35
|
-
status: "TODO status",
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
export function TodoDetailPage() {
|
|
39
|
-
return (
|
|
40
|
-
<OmPage
|
|
41
|
-
padding="lg"
|
|
42
|
-
header={
|
|
43
|
-
<OmHeader
|
|
44
|
-
title="TODO Detail"
|
|
45
|
-
start={<IonBackButton defaultHref="/designs/TODO" />}
|
|
46
|
-
/>
|
|
47
|
-
}
|
|
48
|
-
>
|
|
49
|
-
<OmCard title={RECORD.title} subtitle={`#${RECORD.id}`}>
|
|
50
|
-
<p>Amount: ${RECORD.amount.toFixed(2)}</p>
|
|
51
|
-
<p>Status: {RECORD.status}</p>
|
|
52
|
-
</OmCard>
|
|
53
|
-
|
|
54
|
-
{/* TODO: 关联信息分块 —— 增加更多 OmCard */}
|
|
55
|
-
|
|
56
|
-
<OmButton expand="block">Primary action</OmButton>
|
|
57
|
-
</OmPage>
|
|
58
|
-
);
|
|
59
|
-
}
|
|
60
|
-
export default TodoDetailPage;
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
// @pattern: dialog-view
|
|
2
|
-
// TEMPLATE — 复制到 design/<filename>/<filename>.tsx 后:
|
|
3
|
-
// 1. 替换 meta
|
|
4
|
-
// 2. icon 用合适的 ionicons
|
|
5
|
-
// 3. cancelHref / confirmHref 指向真实路由
|
|
6
|
-
// 4. iconColor / confirmColor 按场景设(danger / warning / success / primary)
|
|
7
|
-
|
|
8
|
-
export const meta = {
|
|
9
|
-
name: "TODO Dialog",
|
|
10
|
-
pattern: "dialog-view",
|
|
11
|
-
description: "TODO one-line description",
|
|
12
|
-
source: "prd",
|
|
13
|
-
} as const;
|
|
14
|
-
|
|
15
|
-
import { informationCircleOutline } from "ionicons/icons";
|
|
16
|
-
import { OmDialog, OmPage } from "@omit-design/preset-mobile";
|
|
17
|
-
|
|
18
|
-
export function TodoDialogPage() {
|
|
19
|
-
return (
|
|
20
|
-
<OmPage padding="none">
|
|
21
|
-
<OmDialog
|
|
22
|
-
icon={informationCircleOutline}
|
|
23
|
-
iconColor="primary"
|
|
24
|
-
title="TODO Title"
|
|
25
|
-
subtitle="TODO subtitle description."
|
|
26
|
-
cancelText="Cancel"
|
|
27
|
-
cancelHref="/designs/TODO-from"
|
|
28
|
-
confirmText="Confirm"
|
|
29
|
-
confirmHref="/designs/TODO-next"
|
|
30
|
-
/>
|
|
31
|
-
</OmPage>
|
|
32
|
-
);
|
|
33
|
-
}
|
|
34
|
-
export default TodoDialogPage;
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
// @pattern: form-view
|
|
2
|
-
// TEMPLATE — 复制到 design/<filename>/<filename>.tsx 后:
|
|
3
|
-
// 1. 替换 meta + 字段
|
|
4
|
-
// 2. 调整 useState 初始值与字段标签
|
|
5
|
-
// 3. 提交按钮 navigate 到下一张稿
|
|
6
|
-
// 4. IonBackButton defaultHref 改成上一级
|
|
7
|
-
|
|
8
|
-
export const meta = {
|
|
9
|
-
name: "TODO Form page",
|
|
10
|
-
pattern: "form-view",
|
|
11
|
-
description: "TODO one-line description",
|
|
12
|
-
source: "prd",
|
|
13
|
-
} as const;
|
|
14
|
-
|
|
15
|
-
import { useState } from "react";
|
|
16
|
-
import { useNavigate } from "react-router-dom";
|
|
17
|
-
import { IonBackButton } from "@ionic/react";
|
|
18
|
-
import {
|
|
19
|
-
OmButton,
|
|
20
|
-
OmHeader,
|
|
21
|
-
OmInput,
|
|
22
|
-
OmPage,
|
|
23
|
-
} from "@omit-design/preset-mobile";
|
|
24
|
-
|
|
25
|
-
export function TodoFormPage() {
|
|
26
|
-
const navigate = useNavigate();
|
|
27
|
-
const [field1, setField1] = useState("");
|
|
28
|
-
const [field2, setField2] = useState("");
|
|
29
|
-
|
|
30
|
-
return (
|
|
31
|
-
<OmPage
|
|
32
|
-
padding="lg"
|
|
33
|
-
header={
|
|
34
|
-
<OmHeader
|
|
35
|
-
title="TODO Form"
|
|
36
|
-
start={<IonBackButton defaultHref="/designs/TODO" />}
|
|
37
|
-
/>
|
|
38
|
-
}
|
|
39
|
-
>
|
|
40
|
-
<OmInput label="Field one" value={field1} onChange={setField1} />
|
|
41
|
-
<OmInput label="Field two" value={field2} onChange={setField2} />
|
|
42
|
-
|
|
43
|
-
<OmButton
|
|
44
|
-
expand="block"
|
|
45
|
-
onClick={() => navigate("/designs/TODO-next")}
|
|
46
|
-
>
|
|
47
|
-
Submit
|
|
48
|
-
</OmButton>
|
|
49
|
-
</OmPage>
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
export default TodoFormPage;
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
// @pattern: list-view
|
|
2
|
-
// TEMPLATE — 复制到 design/<filename>/<filename>.tsx 后:
|
|
3
|
-
// 1. 替换 meta.name / description
|
|
4
|
-
// 2. 把 ITEMS 换成真实 mock import
|
|
5
|
-
// 3. 替换 IonBackButton 的 defaultHref
|
|
6
|
-
// 4. 调整空态文案
|
|
7
|
-
|
|
8
|
-
export const meta = {
|
|
9
|
-
name: "TODO List page",
|
|
10
|
-
pattern: "list-view",
|
|
11
|
-
description: "TODO one-line description",
|
|
12
|
-
source: "prd",
|
|
13
|
-
} as const;
|
|
14
|
-
|
|
15
|
-
import { IonBackButton, IonList } from "@ionic/react";
|
|
16
|
-
import {
|
|
17
|
-
OmEmptyState,
|
|
18
|
-
OmHeader,
|
|
19
|
-
OmListRow,
|
|
20
|
-
OmPage,
|
|
21
|
-
} from "@omit-design/preset-mobile";
|
|
22
|
-
|
|
23
|
-
interface Item {
|
|
24
|
-
id: string;
|
|
25
|
-
title: string;
|
|
26
|
-
detail?: string;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// TODO: 替换为 import { items } from ""./mock/<group>" 相对路径";
|
|
30
|
-
const ITEMS: Item[] = [
|
|
31
|
-
{ id: "1", title: "Sample item 1", detail: "Subinfo" },
|
|
32
|
-
{ id: "2", title: "Sample item 2" },
|
|
33
|
-
];
|
|
34
|
-
|
|
35
|
-
export function TodoListPage() {
|
|
36
|
-
return (
|
|
37
|
-
<OmPage
|
|
38
|
-
padding="none"
|
|
39
|
-
header={
|
|
40
|
-
<OmHeader
|
|
41
|
-
title="TODO Title"
|
|
42
|
-
start={<IonBackButton defaultHref="/designs/TODO" />}
|
|
43
|
-
/>
|
|
44
|
-
}
|
|
45
|
-
>
|
|
46
|
-
{ITEMS.length === 0 ? (
|
|
47
|
-
<OmEmptyState title="No data" description="TODO empty-state description" />
|
|
48
|
-
) : (
|
|
49
|
-
<IonList lines="none">
|
|
50
|
-
{ITEMS.map((it) => (
|
|
51
|
-
<OmListRow key={it.id} title={it.title} detail={it.detail} />
|
|
52
|
-
))}
|
|
53
|
-
</IonList>
|
|
54
|
-
)}
|
|
55
|
-
</OmPage>
|
|
56
|
-
);
|
|
57
|
-
}
|
|
58
|
-
export default TodoListPage;
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
// @pattern: sheet-action
|
|
2
|
-
// TEMPLATE — 复制到 design/<filename>/<filename>.tsx 后:
|
|
3
|
-
// 1. 替换 meta
|
|
4
|
-
// 2. 替换 ITEMS 为业务菜单项
|
|
5
|
-
// 3. dismissHref 改成来源页路径
|
|
6
|
-
|
|
7
|
-
export const meta = {
|
|
8
|
-
name: "TODO Action menu",
|
|
9
|
-
pattern: "sheet-action",
|
|
10
|
-
description: "TODO one-line description",
|
|
11
|
-
source: "prd",
|
|
12
|
-
} as const;
|
|
13
|
-
|
|
14
|
-
import { useNavigate } from "react-router-dom";
|
|
15
|
-
import { IonIcon } from "@ionic/react";
|
|
16
|
-
import { ellipsisHorizontalOutline } from "ionicons/icons";
|
|
17
|
-
import { OmPage, OmSheet } from "@omit-design/preset-mobile";
|
|
18
|
-
|
|
19
|
-
interface MenuItem {
|
|
20
|
-
label: string;
|
|
21
|
-
icon: string;
|
|
22
|
-
href: string;
|
|
23
|
-
danger?: boolean;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const ITEMS: MenuItem[] = [
|
|
27
|
-
{ label: "TODO Item one", icon: ellipsisHorizontalOutline, href: "/designs/TODO" },
|
|
28
|
-
{ label: "TODO Item two", icon: ellipsisHorizontalOutline, href: "/designs/TODO" },
|
|
29
|
-
];
|
|
30
|
-
|
|
31
|
-
export function TodoSheetActionPage() {
|
|
32
|
-
const navigate = useNavigate();
|
|
33
|
-
return (
|
|
34
|
-
<OmPage padding="none">
|
|
35
|
-
<OmSheet title="TODO Title" dismissHref="/designs/TODO-from">
|
|
36
|
-
<div>
|
|
37
|
-
{ITEMS.map((it) => (
|
|
38
|
-
<button
|
|
39
|
-
key={it.label}
|
|
40
|
-
type="button"
|
|
41
|
-
onClick={() => navigate(it.href)}
|
|
42
|
-
>
|
|
43
|
-
<IonIcon icon={it.icon} />
|
|
44
|
-
{it.label}
|
|
45
|
-
</button>
|
|
46
|
-
))}
|
|
47
|
-
</div>
|
|
48
|
-
</OmSheet>
|
|
49
|
-
</OmPage>
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
export default TodoSheetActionPage;
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
// @pattern: tab-view
|
|
2
|
-
// TEMPLATE — 复制到 design/<filename>/<filename>.tsx 后:
|
|
3
|
-
// 1. 替换 meta + 品牌文案
|
|
4
|
-
// 2. 主体内容替换为业务(列表/表单/空态)
|
|
5
|
-
// 3. TABS 列表通常项目级常量 —— 抽到 shell 文件复用更好
|
|
6
|
-
//
|
|
7
|
-
// 注:tab-view 通常由 MemberShell 等 shell 文件统一管理 OmTabBar。
|
|
8
|
-
// 本 template 展示扁平结构,首批落地后可重构为 shell。
|
|
9
|
-
|
|
10
|
-
export const meta = {
|
|
11
|
-
name: "TODO Tab page",
|
|
12
|
-
pattern: "tab-view",
|
|
13
|
-
description: "TODO one-line description",
|
|
14
|
-
source: "prd",
|
|
15
|
-
} as const;
|
|
16
|
-
|
|
17
|
-
import {
|
|
18
|
-
cubeOutline,
|
|
19
|
-
peopleOutline,
|
|
20
|
-
receiptOutline,
|
|
21
|
-
settingsOutline,
|
|
22
|
-
} from "ionicons/icons";
|
|
23
|
-
import {
|
|
24
|
-
OmAppBar,
|
|
25
|
-
OmPage,
|
|
26
|
-
OmTabBar,
|
|
27
|
-
type OmTabItem,
|
|
28
|
-
} from "@omit-design/preset-mobile";
|
|
29
|
-
|
|
30
|
-
const TABS: OmTabItem[] = [
|
|
31
|
-
{ tab: "stored", href: "/designs/TODO-stored", label: "Stored", icon: cubeOutline },
|
|
32
|
-
{ tab: "orders", href: "/designs/TODO-orders", label: "Orders", icon: receiptOutline },
|
|
33
|
-
{ tab: "member", href: "/designs/TODO-member", label: "Members", icon: peopleOutline },
|
|
34
|
-
{ tab: "settings", href: "/designs/TODO-settings", label: "Settings", icon: settingsOutline },
|
|
35
|
-
];
|
|
36
|
-
|
|
37
|
-
export function TodoTabPage() {
|
|
38
|
-
return (
|
|
39
|
-
<OmPage
|
|
40
|
-
padding="lg"
|
|
41
|
-
header={<OmAppBar variant="brand" brandTitle="TODO Brand" />}
|
|
42
|
-
>
|
|
43
|
-
<div>
|
|
44
|
-
{/* TODO: 主体内容 —— 表单 / 列表 / 空态 */}
|
|
45
|
-
<h1>TODO Tab page body</h1>
|
|
46
|
-
</div>
|
|
47
|
-
<OmTabBar items={TABS} />
|
|
48
|
-
</OmPage>
|
|
49
|
-
);
|
|
50
|
-
}
|
|
51
|
-
export default TodoTabPage;
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
// @pattern: welcome-view
|
|
2
|
-
// TEMPLATE — 复制到 design/<filename>/<filename>.tsx 后:
|
|
3
|
-
// 1. 替换 meta
|
|
4
|
-
// 2. 接入真实品牌 logo 组件(可选)
|
|
5
|
-
// 3. CTA navigate 到下一张稿
|
|
6
|
-
// 4. tagline / version 走 mock 或常量
|
|
7
|
-
|
|
8
|
-
export const meta = {
|
|
9
|
-
name: "TODO Welcome page",
|
|
10
|
-
pattern: "welcome-view",
|
|
11
|
-
description: "TODO one-line description",
|
|
12
|
-
source: "prd",
|
|
13
|
-
} as const;
|
|
14
|
-
|
|
15
|
-
import { useNavigate } from "react-router-dom";
|
|
16
|
-
import { OmButton, OmPage } from "@omit-design/preset-mobile";
|
|
17
|
-
|
|
18
|
-
export function TodoWelcomePage() {
|
|
19
|
-
const navigate = useNavigate();
|
|
20
|
-
|
|
21
|
-
return (
|
|
22
|
-
<OmPage padding="none">
|
|
23
|
-
{/* TODO: 替换为品牌 logo 组件 */}
|
|
24
|
-
<div>
|
|
25
|
-
<h1>Welcome</h1>
|
|
26
|
-
<p>TODO welcome message</p>
|
|
27
|
-
</div>
|
|
28
|
-
|
|
29
|
-
<OmButton
|
|
30
|
-
expand="block"
|
|
31
|
-
onClick={() => navigate("/designs/TODO-next")}
|
|
32
|
-
>
|
|
33
|
-
Get started
|
|
34
|
-
</OmButton>
|
|
35
|
-
</OmPage>
|
|
36
|
-
);
|
|
37
|
-
}
|
|
38
|
-
export default TodoWelcomePage;
|