@momo-kits/native-kits 0.157.5-debug → 0.158.1-beta.1-debug
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/.claude/settings.local.json +11 -0
- package/.claude/skills/design-system/SKILL.md +88 -0
- package/.claude/skills/design-system/references/components/avatar.md +134 -0
- package/.claude/skills/design-system/references/components/badge.md +127 -0
- package/.claude/skills/design-system/references/components/bottom-tab.md +177 -0
- package/.claude/skills/design-system/references/components/bottomsheet.md +170 -0
- package/.claude/skills/design-system/references/components/button.md +206 -0
- package/.claude/skills/design-system/references/components/carousel.md +117 -0
- package/.claude/skills/design-system/references/components/checkbox.md +98 -0
- package/.claude/skills/design-system/references/components/chip.md +146 -0
- package/.claude/skills/design-system/references/components/collapse.md +120 -0
- package/.claude/skills/design-system/references/components/date-picker.md +119 -0
- package/.claude/skills/design-system/references/components/divider.md +84 -0
- package/.claude/skills/design-system/references/components/icon.md +130 -0
- package/.claude/skills/design-system/references/components/image.md +81 -0
- package/.claude/skills/design-system/references/components/information.md +107 -0
- package/.claude/skills/design-system/references/components/input-dropdown.md +138 -0
- package/.claude/skills/design-system/references/components/input-money.md +157 -0
- package/.claude/skills/design-system/references/components/input-otp.md +132 -0
- package/.claude/skills/design-system/references/components/input-phone-number.md +140 -0
- package/.claude/skills/design-system/references/components/input-search.md +124 -0
- package/.claude/skills/design-system/references/components/input-text-area.md +133 -0
- package/.claude/skills/design-system/references/components/input.md +152 -0
- package/.claude/skills/design-system/references/components/loader.md +87 -0
- package/.claude/skills/design-system/references/components/pagination.md +105 -0
- package/.claude/skills/design-system/references/components/popup-notify.md +128 -0
- package/.claude/skills/design-system/references/components/progress-info.md +114 -0
- package/.claude/skills/design-system/references/components/radio.md +86 -0
- package/.claude/skills/design-system/references/components/rating.md +126 -0
- package/.claude/skills/design-system/references/components/skeleton.md +120 -0
- package/.claude/skills/design-system/references/components/slider.md +141 -0
- package/.claude/skills/design-system/references/components/snackbar.md +97 -0
- package/.claude/skills/design-system/references/components/stepper.md +100 -0
- package/.claude/skills/design-system/references/components/steps.md +91 -0
- package/.claude/skills/design-system/references/components/suggest-action.md +95 -0
- package/.claude/skills/design-system/references/components/swipe.md +121 -0
- package/.claude/skills/design-system/references/components/switch.md +98 -0
- package/.claude/skills/design-system/references/components/tab-view.md +120 -0
- package/.claude/skills/design-system/references/components/tag.md +118 -0
- package/.claude/skills/design-system/references/components/text.md +151 -0
- package/.claude/skills/design-system/references/components/toast.md +99 -0
- package/.claude/skills/design-system/references/components/tooltip.md +138 -0
- package/.claude/skills/design-system/references/components/top-nav-miniapp.md +94 -0
- package/.claude/skills/design-system/references/components/top-nav.md +226 -0
- package/.claude/skills/design-system/references/components/uploader.md +115 -0
- package/.claude/skills/design-system/references/navigation/bottom-tab.md +131 -0
- package/.claude/skills/design-system/references/navigation/bottomsheet.md +161 -0
- package/.claude/skills/design-system/references/navigation/modal.md +133 -0
- package/.claude/skills/design-system/references/navigation/navigation-options.md +225 -0
- package/.claude/skills/design-system/references/navigation/navigator.md +111 -0
- package/.claude/skills/design-system/references/navigation/setup.md +134 -0
- package/.claude/skills/design-system/references/navigation/stack.md +128 -0
- package/.claude/skills/design-system/references/spec-convention.md +80 -0
- package/.claude/skills/design-system/references/tokens/colors.md +131 -0
- package/.claude/skills/design-system/references/tokens/spacing-radius.md +144 -0
- package/.claude/skills/design-system/references/tokens/theme.md +125 -0
- package/.claude/skills/design-system/references/tokens/typography.md +135 -0
- package/.claude/skills/design-system-kits/SKILL.md +102 -0
- package/.claude/skills/design-system-kits/references/code-convention.md +118 -0
- package/.claude/skills/design-system-kits/references/components/avatar.md +45 -0
- package/.claude/skills/design-system-kits/references/components/badge.md +27 -0
- package/.claude/skills/design-system-kits/references/components/button.md +65 -0
- package/.claude/skills/design-system-kits/references/components/carousel.md +51 -0
- package/.claude/skills/design-system-kits/references/components/checkbox.md +39 -0
- package/.claude/skills/design-system-kits/references/components/chip.md +54 -0
- package/.claude/skills/design-system-kits/references/components/collapse.md +63 -0
- package/.claude/skills/design-system-kits/references/components/date-picker.md +36 -0
- package/.claude/skills/design-system-kits/references/components/divider.md +21 -0
- package/.claude/skills/design-system-kits/references/components/icon.md +382 -0
- package/.claude/skills/design-system-kits/references/components/image.md +62 -0
- package/.claude/skills/design-system-kits/references/components/information.md +61 -0
- package/.claude/skills/design-system-kits/references/components/input-dropdown.md +92 -0
- package/.claude/skills/design-system-kits/references/components/input-money.md +128 -0
- package/.claude/skills/design-system-kits/references/components/input-otp.md +85 -0
- package/.claude/skills/design-system-kits/references/components/input-phone-number.md +96 -0
- package/.claude/skills/design-system-kits/references/components/input-search.md +127 -0
- package/.claude/skills/design-system-kits/references/components/input-text-area.md +100 -0
- package/.claude/skills/design-system-kits/references/components/input.md +126 -0
- package/.claude/skills/design-system-kits/references/components/loader.md +41 -0
- package/.claude/skills/design-system-kits/references/components/pagination.md +47 -0
- package/.claude/skills/design-system-kits/references/components/popup-notify.md +69 -0
- package/.claude/skills/design-system-kits/references/components/popup-promotion.md +35 -0
- package/.claude/skills/design-system-kits/references/components/progress-info.md +55 -0
- package/.claude/skills/design-system-kits/references/components/radio.md +42 -0
- package/.claude/skills/design-system-kits/references/components/rating.md +36 -0
- package/.claude/skills/design-system-kits/references/components/skeleton.md +25 -0
- package/.claude/skills/design-system-kits/references/components/slider.md +53 -0
- package/.claude/skills/design-system-kits/references/components/snackbar.md +52 -0
- package/.claude/skills/design-system-kits/references/components/stepper.md +46 -0
- package/.claude/skills/design-system-kits/references/components/steps.md +57 -0
- package/.claude/skills/design-system-kits/references/components/suggest-action.md +44 -0
- package/.claude/skills/design-system-kits/references/components/swipe.md +44 -0
- package/.claude/skills/design-system-kits/references/components/switch.md +43 -0
- package/.claude/skills/design-system-kits/references/components/tab-view.md +56 -0
- package/.claude/skills/design-system-kits/references/components/tag.md +50 -0
- package/.claude/skills/design-system-kits/references/components/text.md +56 -0
- package/.claude/skills/design-system-kits/references/components/toast.md +51 -0
- package/.claude/skills/design-system-kits/references/components/tooltip.md +95 -0
- package/.claude/skills/design-system-kits/references/components/uploader.md +48 -0
- package/.claude/skills/design-system-kits/references/design-spec-structure.md +356 -0
- package/.claude/skills/design-system-kits/references/design-spec-to-code.md +596 -0
- package/.claude/skills/design-system-kits/references/navigation/bottom-tab.md +155 -0
- package/.claude/skills/design-system-kits/references/navigation/bottomsheet.md +94 -0
- package/.claude/skills/design-system-kits/references/navigation/modal.md +125 -0
- package/.claude/skills/design-system-kits/references/navigation/navigation-options.md +430 -0
- package/.claude/skills/design-system-kits/references/navigation/navigator.md +177 -0
- package/.claude/skills/design-system-kits/references/navigation/setup.md +94 -0
- package/.claude/skills/design-system-kits/references/navigation/stack.md +152 -0
- package/.claude/skills/design-system-kits/references/screen-layout-rule.md +125 -0
- package/.claude/skills/design-system-kits/references/tokens/colors.md +183 -0
- package/.claude/skills/design-system-kits/references/tokens/spacing-radius.md +45 -0
- package/.claude/skills/design-system-kits/references/tokens/theme.md +97 -0
- package/.claude/skills/design-system-kits/references/tokens/typography.md +105 -0
- package/.claude/skills/vibe-design/SKILL.md +306 -0
- package/compose/build.gradle.kts +1 -1
- package/compose/src/androidMain/kotlin/vn/momo/kits/platform/Platform.android.kt +7 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Avatar.kt +157 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Carousel.kt +123 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Collapse.kt +224 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Loader.kt +108 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupPromotion.kt +2 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/ProgressInfo.kt +338 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Rating.kt +87 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Slider.kt +348 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Stepper.kt +256 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Steps.kt +494 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/SuggestAction.kt +131 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Swipe.kt +215 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/TabView.kt +531 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Uploader.kt +192 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Spacing.kt +3 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Theme.kt +5 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/AutomationId.kt +2 -11
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/Platform.kt +5 -1
- package/compose/src/iosMain/kotlin/vn/momo/kits/platform/Platform.ios.kt +12 -0
- package/gradle.properties +1 -1
- package/ios/Popup/PopupPromotion.swift +2 -2
- package/local.properties +8 -0
- package/package.json +1 -1
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# BottomSheet
|
|
2
|
+
|
|
3
|
+
> Slides up from bottom — reveals additional content/actions while maintaining parent screen context. Overlay container.
|
|
4
|
+
|
|
5
|
+
**Package:** `@momo-kits/foundation`
|
|
6
|
+
**Platform:** RN ✅ | Compose ✅
|
|
7
|
+
**Completeness:** need_update — thiếu Figma
|
|
8
|
+
**Figma node:** [VERIFY]
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Variant Axes
|
|
13
|
+
|
|
14
|
+
| Axis | Options | Default |
|
|
15
|
+
|------|---------|---------|
|
|
16
|
+
| **Type** | `standard` · `surface` | `standard` |
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Props
|
|
21
|
+
|
|
22
|
+
| Prop | Type | Values | Default | Description |
|
|
23
|
+
|------|------|--------|---------|-------------|
|
|
24
|
+
| `type` | string | `"standard"` \| `"surface"` | `"standard"` | Standard: with handle + backdrop. Surface: no handle, integrated feel [VERIFY] |
|
|
25
|
+
| `visible` | boolean | `true` \| `false` | `false` | Controlled visibility |
|
|
26
|
+
| `barrierDismissible` | boolean | `true` \| `false` | `true` | Tap backdrop to dismiss |
|
|
27
|
+
| `showHandle` | boolean | `true` \| `false` | `true` | Show drag handle indicator [VERIFY] |
|
|
28
|
+
| `children` | element | — | required | Sheet content — any components. Scrollable if exceeds height |
|
|
29
|
+
| `onDismiss` | function | — | — | Callback khi dismissed. `"onDismiss": "action://closeSheet"` |
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Variants
|
|
34
|
+
|
|
35
|
+
| Type | Handle | Backdrop | Use Case |
|
|
36
|
+
|------|--------|---------|----------|
|
|
37
|
+
| **standard** | Visible (36x4, `Colors.black_06`) | `Colors.black_20` at 40% opacity | Action lists, selections, additional info |
|
|
38
|
+
| **surface** | Hidden | None or minimal | Integrated content that feels part of screen |
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## States
|
|
43
|
+
|
|
44
|
+
| State | Appearance |
|
|
45
|
+
|-------|-----------|
|
|
46
|
+
| **Hidden** | Not rendered |
|
|
47
|
+
| **Opening** | Slide up from bottom (300ms ease-out), backdrop fade in |
|
|
48
|
+
| **Visible** | Sheet visible, content scrollable if needed. Max 90% screen height |
|
|
49
|
+
| **Closing** | Slide down (250ms ease-in), backdrop fade out |
|
|
50
|
+
|
|
51
|
+
Dismiss triggers: swipe down on handle/content, tap backdrop (if barrierDismissible), system back button, programmatic.
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Variant-to-Context Map
|
|
56
|
+
|
|
57
|
+
| Context | Khi nào dùng | Tránh khi | Ví dụ trong MoMo |
|
|
58
|
+
|---------|-------------|-----------|-------------------|
|
|
59
|
+
| **Action list** | Secondary actions cho list item | Primary actions → show visible | Share, Export, Report options |
|
|
60
|
+
| **Selection** | Choose from <10 options | >10 options → full screen with search | Chọn ngân hàng, chọn lý do |
|
|
61
|
+
| **Filter/Sort** | Filter or sort options | Complex multi-field filter → new screen | Lọc giao dịch, sắp xếp |
|
|
62
|
+
| **Information** | Additional details without leaving context | Critical decisions → dùng PopupNotify | Chi tiết giao dịch, thông tin thêm |
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## SSR Pattern
|
|
67
|
+
|
|
68
|
+
### Action List BottomSheet
|
|
69
|
+
```json
|
|
70
|
+
{
|
|
71
|
+
"component": "BottomSheet",
|
|
72
|
+
"props": {
|
|
73
|
+
"visible": "{{state.showActions}}",
|
|
74
|
+
"barrierDismissible": true
|
|
75
|
+
},
|
|
76
|
+
"children": [
|
|
77
|
+
{
|
|
78
|
+
"component": "Text",
|
|
79
|
+
"props": {
|
|
80
|
+
"content": "Chia sẻ",
|
|
81
|
+
"typography": "body_default_regular"
|
|
82
|
+
},
|
|
83
|
+
"onPress": "action://share"
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
"component": "Divider",
|
|
87
|
+
"props": {}
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"component": "Text",
|
|
91
|
+
"props": {
|
|
92
|
+
"content": "Báo cáo",
|
|
93
|
+
"typography": "body_default_regular"
|
|
94
|
+
},
|
|
95
|
+
"onPress": "action://report"
|
|
96
|
+
}
|
|
97
|
+
],
|
|
98
|
+
"onDismiss": "setState://showActions=false"
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Selection BottomSheet
|
|
103
|
+
```json
|
|
104
|
+
{
|
|
105
|
+
"component": "BottomSheet",
|
|
106
|
+
"props": {
|
|
107
|
+
"visible": "{{state.showBankPicker}}"
|
|
108
|
+
},
|
|
109
|
+
"children": [
|
|
110
|
+
{
|
|
111
|
+
"component": "Text",
|
|
112
|
+
"props": {
|
|
113
|
+
"content": "Chọn ngân hàng",
|
|
114
|
+
"typography": "headline_s_bold"
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
"id": "bank_options",
|
|
119
|
+
"type": "section",
|
|
120
|
+
"forEach": "{{data.banks}}",
|
|
121
|
+
"render": {
|
|
122
|
+
"component": "Radio",
|
|
123
|
+
"props": {
|
|
124
|
+
"value": "{{item.id}}",
|
|
125
|
+
"groupValue": "{{state.selectedBank}}",
|
|
126
|
+
"label": "{{item.name}}"
|
|
127
|
+
},
|
|
128
|
+
"onChange": "setState://selectedBank={{item.id}}"
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
"component": "Button",
|
|
133
|
+
"props": {
|
|
134
|
+
"variant": "primary",
|
|
135
|
+
"label": "Xác nhận"
|
|
136
|
+
},
|
|
137
|
+
"onPress": "action://confirmBank"
|
|
138
|
+
}
|
|
139
|
+
],
|
|
140
|
+
"onDismiss": "setState://showBankPicker=false"
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## Accessibility
|
|
147
|
+
|
|
148
|
+
- Focus trap khi sheet open — cannot interact with content behind.
|
|
149
|
+
- Handle: accessible label "Kéo xuống để đóng".
|
|
150
|
+
- Content announces on open.
|
|
151
|
+
- Back button / ESC dismisses.
|
|
152
|
+
- All interactive elements meet 44dp touch target.
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## Usage Guidelines
|
|
157
|
+
|
|
158
|
+
### Do
|
|
159
|
+
- Dùng cho secondary actions, filter/sort, selections (<10 items).
|
|
160
|
+
- Show handle cho swipe-to-dismiss affordance.
|
|
161
|
+
- Allow backdrop tap to dismiss cho non-critical sheets.
|
|
162
|
+
- Keep content concise and scannable.
|
|
163
|
+
|
|
164
|
+
### Don't
|
|
165
|
+
- Không nest bottom sheets trong bottom sheets.
|
|
166
|
+
- Không dùng cho lengthy forms → navigate to new screen.
|
|
167
|
+
- Không disable swipe-to-dismiss unless data loss possible.
|
|
168
|
+
- Không >90% screen height.
|
|
169
|
+
- Không dùng cho critical confirmations → dùng **PopupNotify**.
|
|
170
|
+
- Không dùng cho persistent content — sheet is dismissible.
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
# Button
|
|
2
|
+
|
|
3
|
+
> Interactive element trigger action — CTA chính và phụ cho mọi screen trong MoMo.
|
|
4
|
+
|
|
5
|
+
**Package:** `@momo-kits/foundation`
|
|
6
|
+
**Platform:** RN ✅ | Compose ✅
|
|
7
|
+
**Completeness:** need_update — Figma variant naming typo known ("sencondary")
|
|
8
|
+
**Figma node:** [VERIFY]
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Variant Axes
|
|
13
|
+
|
|
14
|
+
| Property | Type | Values | Description |
|
|
15
|
+
|----------|------|--------|-------------|
|
|
16
|
+
| type | variant | primary · secondary · tonal · outline · danger · textlink · disabled | Visual variant — determines colors and emphasis |
|
|
17
|
+
| size | variant | large · medium · small | Button size |
|
|
18
|
+
| full | boolean | true · false | Full-width mode |
|
|
19
|
+
|
|
20
|
+
> **Note:** Figma treats `disabled` as variant trong `type`. Logically nó là state. ui-composer có thể dùng `type: "disabled"` hoặc `disabled: true` [VERIFY].
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Props
|
|
25
|
+
|
|
26
|
+
| Prop | Type | Values | Default | Description |
|
|
27
|
+
|------|------|--------|---------|-------------|
|
|
28
|
+
| `title` | string | — | required | Button label text. Sentence case. Max 20 chars. Start with verb |
|
|
29
|
+
| `type` | string | `"primary"` \| `"secondary"` \| `"tonal"` \| `"outline"` \| `"danger"` \| `"textlink"` \| `"disabled"` | `"primary"` | Visual variant |
|
|
30
|
+
| `size` | string | `"large"` \| `"medium"` \| `"small"` | `"large"` | Button size |
|
|
31
|
+
| `full` | boolean | `true` \| `false` | `false` | Full-width mode — stretches to parent width |
|
|
32
|
+
| `disabled` | boolean | `true` \| `false` | `false` | Non-interactive. Overrides variant colors |
|
|
33
|
+
| `loading` | boolean | `true` \| `false` | `false` | Spinner replaces label. Non-interactive during loading |
|
|
34
|
+
| `iconLeft` | string | icon name | — | Optional icon before label |
|
|
35
|
+
| `iconRight` | string | icon name | — | Optional icon after label |
|
|
36
|
+
| `onPress` | function | — | — | Tap handler. `"onPress": "action://submit"` |
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Variants
|
|
41
|
+
|
|
42
|
+
| Variant | Background | Text Color | Border | Emphasis | Usage |
|
|
43
|
+
|---------|-----------|-----------|--------|----------|-------|
|
|
44
|
+
| **primary** | `Colors.pink_03` | `Colors.white` | none | Highest | Main CTA. Chỉ 1 per screen |
|
|
45
|
+
| **secondary** | `Colors.white` | `Colors.pink_03` | `Colors.pink_03` | High | Supporting action. Pair với Primary |
|
|
46
|
+
| **tonal** | `Colors.pink_09` | `Colors.pink_03` | none | Medium | Soft emphasis. Grouped actions |
|
|
47
|
+
| **outline** | `Colors.white` | `Colors.black_17` | `Colors.black_04` | Low | Neutral, optional actions |
|
|
48
|
+
| **danger** | `Colors.red_03` | `Colors.white` | none | Override | Destructive/irreversible only |
|
|
49
|
+
| **textlink** | transparent | `Colors.pink_03` | none | Lowest | Inline text action. Skip, Show all |
|
|
50
|
+
|
|
51
|
+
**Variant hierarchy:** primary > secondary > tonal/outline > textlink. Danger overrides all — dùng độc lập.
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## States
|
|
56
|
+
|
|
57
|
+
| State | Background | Text Color | Border | Opacity | Spinner | Interactive |
|
|
58
|
+
|-------|-----------|-----------|--------|---------|---------|-------------|
|
|
59
|
+
| **Default** | per variant | per variant | per variant | 1 | — | true |
|
|
60
|
+
| **Pressed** | per variant | per variant | per variant | 0.8 | — | true |
|
|
61
|
+
| **Disabled** | `Colors.black_04` | `Colors.black_08` | none | 1 | — | false |
|
|
62
|
+
| **Loading** | per variant | — | per variant | 1 | matches text color | false |
|
|
63
|
+
|
|
64
|
+
- Pressed: entire button opacity 0.8. Immediate transition.
|
|
65
|
+
- Loading: spinner replaces label text. Button maintains exact size. Prevents double-tap.
|
|
66
|
+
- Disabled: overrides ALL variant colors → grey.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Variant-to-Context Map
|
|
71
|
+
|
|
72
|
+
| Variant | Khi nào dùng | Tránh khi | Ví dụ trong MoMo |
|
|
73
|
+
|---------|-------------|-----------|-------------------|
|
|
74
|
+
| **primary** | Main action trên screen. Max 1 per view | Có 2+ primary actions — hạ bớt xuống secondary | "Chuyển tiền" button trên form transfer |
|
|
75
|
+
| **secondary** | Supporting action alongside Primary | Standalone không có Primary kèm — dùng Primary | "Hủy" bên cạnh "Xác nhận" trên popup confirm |
|
|
76
|
+
| **tonal** | Grouped actions cần soft emphasis | Action quan trọng cần nổi bật — dùng Primary | "Chọn phương thức" trên màn thanh toán |
|
|
77
|
+
| **outline** | Neutral, optional, low-emphasis | Action chính — quá subtle | "Xem chi tiết" trên card giao dịch |
|
|
78
|
+
| **danger** | Destructive, irreversible action | Non-destructive actions | "Xóa tài khoản" trên Settings, "Hủy giao dịch" |
|
|
79
|
+
| **textlink** | Inline text action, lowest emphasis | Primary action — quá subtle | "Bỏ qua" trên onboarding, "Xem tất cả" trên section |
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## SSR Pattern
|
|
84
|
+
|
|
85
|
+
### Fixed Bottom CTA
|
|
86
|
+
```json
|
|
87
|
+
{
|
|
88
|
+
"id": "bottom_cta",
|
|
89
|
+
"type": "footer",
|
|
90
|
+
"children": [
|
|
91
|
+
{
|
|
92
|
+
"component": "Button",
|
|
93
|
+
"props": {
|
|
94
|
+
"title": "Chuyển tiền",
|
|
95
|
+
"type": "primary",
|
|
96
|
+
"size": "large",
|
|
97
|
+
"full": true,
|
|
98
|
+
"loading": "{{state.isSubmitting}}"
|
|
99
|
+
},
|
|
100
|
+
"onPress": "action://transfer"
|
|
101
|
+
}
|
|
102
|
+
]
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Horizontal Pair (Confirm/Cancel)
|
|
107
|
+
```json
|
|
108
|
+
{
|
|
109
|
+
"id": "action_pair",
|
|
110
|
+
"type": "row",
|
|
111
|
+
"spacing": "Spacing.S",
|
|
112
|
+
"children": [
|
|
113
|
+
{
|
|
114
|
+
"component": "Button",
|
|
115
|
+
"props": {
|
|
116
|
+
"title": "Hủy",
|
|
117
|
+
"type": "secondary",
|
|
118
|
+
"size": "medium"
|
|
119
|
+
},
|
|
120
|
+
"onPress": "action://cancel"
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
"component": "Button",
|
|
124
|
+
"props": {
|
|
125
|
+
"title": "Xác nhận",
|
|
126
|
+
"type": "primary",
|
|
127
|
+
"size": "medium"
|
|
128
|
+
},
|
|
129
|
+
"onPress": "action://confirm"
|
|
130
|
+
}
|
|
131
|
+
]
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Destructive Confirmation
|
|
136
|
+
```json
|
|
137
|
+
{
|
|
138
|
+
"id": "destructive_pair",
|
|
139
|
+
"type": "row",
|
|
140
|
+
"spacing": "Spacing.S",
|
|
141
|
+
"children": [
|
|
142
|
+
{
|
|
143
|
+
"component": "Button",
|
|
144
|
+
"props": {
|
|
145
|
+
"title": "Giữ lại",
|
|
146
|
+
"type": "outline",
|
|
147
|
+
"size": "medium"
|
|
148
|
+
},
|
|
149
|
+
"onPress": "action://keep"
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
"component": "Button",
|
|
153
|
+
"props": {
|
|
154
|
+
"title": "Xóa tài khoản",
|
|
155
|
+
"type": "danger",
|
|
156
|
+
"size": "medium"
|
|
157
|
+
},
|
|
158
|
+
"onPress": "action://deleteAccount"
|
|
159
|
+
}
|
|
160
|
+
]
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Loading Action
|
|
165
|
+
```json
|
|
166
|
+
{
|
|
167
|
+
"component": "Button",
|
|
168
|
+
"props": {
|
|
169
|
+
"title": "Đang xử lý...",
|
|
170
|
+
"type": "primary",
|
|
171
|
+
"size": "large",
|
|
172
|
+
"full": true,
|
|
173
|
+
"loading": true
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## Accessibility
|
|
181
|
+
|
|
182
|
+
- Screen reader announce: label + role (button) + state (disabled/loading).
|
|
183
|
+
- Icon-only buttons: PHẢI có text accessible label.
|
|
184
|
+
- Loading state: announce "Đang xử lý" hoặc equivalent.
|
|
185
|
+
- Color contrast: tất cả variant text-on-background meet WCAG AA (4.5:1).
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## Usage Guidelines
|
|
190
|
+
|
|
191
|
+
### Do
|
|
192
|
+
- Dùng Primary cho 1 action quan trọng nhất trên screen.
|
|
193
|
+
- Sentence case: "Chuyển tiền" không phải "CHUYỂN TIỀN".
|
|
194
|
+
- Label 1-3 words, bắt đầu bằng verb.
|
|
195
|
+
- Loading state cho async actions — prevent double-tap.
|
|
196
|
+
- Pair Primary + Secondary khi có 2 choices.
|
|
197
|
+
- Danger CHỈ cho destructive/irreversible.
|
|
198
|
+
|
|
199
|
+
### Don't
|
|
200
|
+
- Không đặt 2+ Primary buttons trên cùng 1 view area.
|
|
201
|
+
- Không mix sizes trong cùng button group.
|
|
202
|
+
- Không dùng Danger cho non-destructive actions.
|
|
203
|
+
- Không dùng TextLink cho primary actions — quá subtle.
|
|
204
|
+
- Không disable button mà không communicate lý do.
|
|
205
|
+
- Không mix Primary + Danger trong cùng group.
|
|
206
|
+
- Label không quá 20 ký tự, không dùng "!" hay ".".
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# Carousel
|
|
2
|
+
|
|
3
|
+
> Horizontal scrollable content container — snap-to-item behavior for banners, galleries, onboarding. Pairs with Pagination.
|
|
4
|
+
|
|
5
|
+
**Package:** `@momo-kits/carousel`
|
|
6
|
+
**Platform:** RN ✅ | Compose ❌ (use HorizontalPager)
|
|
7
|
+
**Completeness:** need_update — thiếu Figma
|
|
8
|
+
**Figma node:** [VERIFY]
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Props
|
|
13
|
+
|
|
14
|
+
| Prop | Type | Values | Default | Description |
|
|
15
|
+
|------|------|--------|---------|-------------|
|
|
16
|
+
| `items` | array | — | required | Data array for carousel items |
|
|
17
|
+
| `renderItem` | function | — | required | Render function per item [VERIFY] |
|
|
18
|
+
| `autoPlay` | boolean | `true` \| `false` | `false` | Auto-advance between items |
|
|
19
|
+
| `autoPlayInterval` | number | milliseconds | `3000` | Interval between auto-advances [VERIFY] |
|
|
20
|
+
| `loop` | boolean | `true` \| `false` | `false` | Seamless wrap from last → first item [VERIFY] |
|
|
21
|
+
| `showPagination` | boolean | `true` \| `false` | `true` | Show PaginationDot below carousel [VERIFY] |
|
|
22
|
+
| `paginationType` | string | `"dot"` \| `"scroll"` | `"dot"` | Pagination variant (see Pagination component) [VERIFY] |
|
|
23
|
+
| `peek` | number | dp | `0` | Amount of adjacent item visible at edges (16-24dp recommended) [VERIFY] |
|
|
24
|
+
| `onChange` | function | — | — | Callback khi current item changes. `"onChange": "setState://currentBanner"` |
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## States
|
|
29
|
+
|
|
30
|
+
| State | Appearance |
|
|
31
|
+
|-------|-----------|
|
|
32
|
+
| **Idle** | Current item fully visible, pagination updated |
|
|
33
|
+
| **Scrolling** | Items move horizontally, pagination animates |
|
|
34
|
+
| **Auto-playing** | Items advance automatically at interval |
|
|
35
|
+
| **Paused** | Auto-play paused due to user touch interaction |
|
|
36
|
+
|
|
37
|
+
Auto-play pauses on user interaction, resumes after release.
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Variant-to-Context Map
|
|
42
|
+
|
|
43
|
+
| Context | Khi nào dùng | Tránh khi | Ví dụ trong MoMo |
|
|
44
|
+
|---------|-------------|-----------|-------------------|
|
|
45
|
+
| **Promotional banners** | Featured content at screen top | Critical content every user must see | Banner khuyến mãi trên Home |
|
|
46
|
+
| **Image gallery** | Browse product/service images | Long lists → dùng FlatList | Ảnh merchant, ảnh sản phẩm |
|
|
47
|
+
| **Onboarding** | Step-by-step intro slides | Navigation between sections → dùng TabView | Welcome slides, feature intro |
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## SSR Pattern
|
|
52
|
+
|
|
53
|
+
### Banner Carousel with Pagination
|
|
54
|
+
```json
|
|
55
|
+
{
|
|
56
|
+
"id": "banner_section",
|
|
57
|
+
"type": "section",
|
|
58
|
+
"children": [
|
|
59
|
+
{
|
|
60
|
+
"component": "Carousel",
|
|
61
|
+
"props": {
|
|
62
|
+
"items": "{{data.banners}}",
|
|
63
|
+
"autoPlay": true,
|
|
64
|
+
"autoPlayInterval": 5000,
|
|
65
|
+
"loop": true,
|
|
66
|
+
"showPagination": true,
|
|
67
|
+
"paginationType": "dot",
|
|
68
|
+
"peek": 0
|
|
69
|
+
},
|
|
70
|
+
"onChange": "setState://currentBanner"
|
|
71
|
+
}
|
|
72
|
+
]
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Image Gallery with Scroll Pagination
|
|
77
|
+
```json
|
|
78
|
+
{
|
|
79
|
+
"component": "Carousel",
|
|
80
|
+
"props": {
|
|
81
|
+
"items": "{{data.merchantImages}}",
|
|
82
|
+
"autoPlay": false,
|
|
83
|
+
"showPagination": true,
|
|
84
|
+
"paginationType": "scroll",
|
|
85
|
+
"peek": 16
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Accessibility
|
|
93
|
+
|
|
94
|
+
- Items navigable via swipe gestures on assistive technology.
|
|
95
|
+
- Auto-play MUST pause khi screen reader active.
|
|
96
|
+
- Each item: descriptive accessible label.
|
|
97
|
+
- Announce current position: "Mục 2 trong 5".
|
|
98
|
+
- Provide way to pause auto-play without specific gesture.
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## Usage Guidelines
|
|
103
|
+
|
|
104
|
+
### Do
|
|
105
|
+
- Dùng cho promotional banners, image galleries, onboarding slides.
|
|
106
|
+
- Always include pagination indicators.
|
|
107
|
+
- Peek adjacent items → signal scrollability.
|
|
108
|
+
- Keep 3-8 items — manageable count.
|
|
109
|
+
- Auto-play interval ≥3 seconds.
|
|
110
|
+
|
|
111
|
+
### Don't
|
|
112
|
+
- Không dùng cho long lists → dùng FlatList / LazyColumn.
|
|
113
|
+
- Không dùng cho section navigation → dùng **TabView** / **BottomTab**.
|
|
114
|
+
- Không set autoPlayInterval <3000ms — user cần time to read.
|
|
115
|
+
- Không hide pagination khi >1 item.
|
|
116
|
+
- Không nest carousels — scroll conflict.
|
|
117
|
+
- Không rely on carousel cho critical content — items may be missed.
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# CheckBox
|
|
2
|
+
|
|
3
|
+
> Multi-selection control — chọn nhiều options hoặc indicate agreement. Supports indeterminate state.
|
|
4
|
+
|
|
5
|
+
**Package:** `@momo-kits/foundation`
|
|
6
|
+
**Platform:** RN ✅ | Compose ✅
|
|
7
|
+
**Completeness:** need_update — thiếu Figma
|
|
8
|
+
**Figma node:** [VERIFY]
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Props
|
|
13
|
+
|
|
14
|
+
| Prop | Type | Values | Default | Description |
|
|
15
|
+
|------|------|--------|---------|-------------|
|
|
16
|
+
| `checked` | boolean | `true` \| `false` | `false` | Checked state |
|
|
17
|
+
| `indeterminate` | boolean | `true` \| `false` | `false` | Partial selection state (select-all parent) [VERIFY] |
|
|
18
|
+
| `label` | string | — | — | Text label bên phải checkbox |
|
|
19
|
+
| `disabled` | boolean | `true` \| `false` | `false` | Non-interactive state |
|
|
20
|
+
| `onChange` | function | — | — | Callback khi toggle. `"onChange": "setState://option"` |
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## States
|
|
25
|
+
|
|
26
|
+
| State | Box Appearance | Icon | Label Color | Interactive |
|
|
27
|
+
|-------|---------------|------|------------|-------------|
|
|
28
|
+
| **Unchecked** | `Colors.black_04` border, no fill | none | `Colors.black_17` | true |
|
|
29
|
+
| **Checked** | `Colors.pink_03` fill | white checkmark | `Colors.black_17` | true |
|
|
30
|
+
| **Indeterminate** | `Colors.pink_03` fill | white minus | `Colors.black_17` | true |
|
|
31
|
+
| **Disabled Unchecked** | `Colors.black_08` border, no fill | none | `Colors.black_08` | false |
|
|
32
|
+
| **Disabled Checked** | `Colors.black_08` fill | white checkmark | `Colors.black_08` | false |
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Variant-to-Context Map
|
|
37
|
+
|
|
38
|
+
| Context | Khi nào dùng | Tránh khi | Ví dụ trong MoMo |
|
|
39
|
+
|---------|-------------|-----------|-------------------|
|
|
40
|
+
| **Multi-select** | Chọn nhiều options từ list | Chọn 1 exclusive → dùng Radio | Chọn nhiều dịch vụ, filter multi-category |
|
|
41
|
+
| **Agreement** | Consent/terms checkbox | — | "Tôi đồng ý điều khoản" trên form |
|
|
42
|
+
| **Select all** | Parent checkbox cho group (indeterminate khi partial) | — | "Chọn tất cả" trên danh sách |
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## SSR Pattern
|
|
47
|
+
|
|
48
|
+
### Agreement Checkbox
|
|
49
|
+
```json
|
|
50
|
+
{
|
|
51
|
+
"component": "CheckBox",
|
|
52
|
+
"props": {
|
|
53
|
+
"checked": "{{state.agreedToTerms}}",
|
|
54
|
+
"label": "Tôi đồng ý với Điều khoản sử dụng"
|
|
55
|
+
},
|
|
56
|
+
"onChange": "setState://agreedToTerms"
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Multi-select List
|
|
61
|
+
```json
|
|
62
|
+
{
|
|
63
|
+
"id": "service_options",
|
|
64
|
+
"type": "section",
|
|
65
|
+
"forEach": "{{data.services}}",
|
|
66
|
+
"render": {
|
|
67
|
+
"component": "CheckBox",
|
|
68
|
+
"props": {
|
|
69
|
+
"checked": "{{item.selected}}",
|
|
70
|
+
"label": "{{item.name}}"
|
|
71
|
+
},
|
|
72
|
+
"onChange": "setState://toggleService={{item.id}}"
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## Accessibility
|
|
80
|
+
|
|
81
|
+
- Screen readers announce: label, state (checked/unchecked/indeterminate), role (checkbox).
|
|
82
|
+
- Entire row (box + label) tappable.
|
|
83
|
+
- State changes announce immediately.
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Usage Guidelines
|
|
88
|
+
|
|
89
|
+
### Do
|
|
90
|
+
- Dùng cho selecting multiple options từ list.
|
|
91
|
+
- Dùng cho agreement/consent checkboxes.
|
|
92
|
+
- Dùng indeterminate cho "select all" parent.
|
|
93
|
+
- Luôn provide visible label.
|
|
94
|
+
|
|
95
|
+
### Don't
|
|
96
|
+
- Không dùng cho single on/off toggle → dùng **Switch**.
|
|
97
|
+
- Không dùng cho mutually exclusive choices → dùng **Radio**.
|
|
98
|
+
- Không dùng cho filter controls trong toolbar → dùng **Chip**.
|