@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,146 @@
|
|
|
1
|
+
# Chip
|
|
2
|
+
|
|
3
|
+
> Interactive filter/selection pill — toggle giữa selected/unselected khi tap.
|
|
4
|
+
|
|
5
|
+
**Package:** `@momo-kits/chip`
|
|
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
|
+
| `label` | string | — | required | Display text. 1-3 words |
|
|
17
|
+
| `size` | string | `"small"` \| `"large"` | `"small"` | Chip size |
|
|
18
|
+
| `selected` | boolean | `true` \| `false` | `false` | Selection state |
|
|
19
|
+
| `disabled` | boolean | `true` \| `false` | `false` | Non-interactive state |
|
|
20
|
+
| `leftIcon` | string | icon name | — | Optional icon trước label |
|
|
21
|
+
| `rightIcon` | string | icon name \| `"close"` | — | Optional icon sau label. `"close"` cho removable chip |
|
|
22
|
+
| `onPress` | function | — | — | Tap handler — toggle selected state |
|
|
23
|
+
| `onPressRightIcon` | function | — | — | Right icon tap — remove/deselect [VERIFY] |
|
|
24
|
+
|
|
25
|
+
> **Lưu ý cho ui-composer:** Chip dùng package riêng `@momo-kits/chip`, không nằm trong `@momo-kits/foundation`.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Variants
|
|
30
|
+
|
|
31
|
+
| Variant | Background | Text Color | Icon Color | Usage |
|
|
32
|
+
|---------|-----------|-----------|-----------|-------|
|
|
33
|
+
| **Unselected** | `Colors.black_04` | `Colors.black_17` | `Colors.black_12` | Default resting state |
|
|
34
|
+
| **Selected** | `Colors.pink_09` | `Colors.pink_03` | `Colors.pink_03` | Active / chosen state |
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## States
|
|
39
|
+
|
|
40
|
+
| State | Background | Text Color | Icon Color | Opacity | Interactive |
|
|
41
|
+
|-------|-----------|-----------|-----------|---------|-------------|
|
|
42
|
+
| **Unselected** | `Colors.black_04` | `Colors.black_17` | `Colors.black_12` | 1 | true |
|
|
43
|
+
| **Selected** | `Colors.pink_09` | `Colors.pink_03` | `Colors.pink_03` | 1 | true |
|
|
44
|
+
| **Pressed** | same as current | same as current | same as current | 0.8 | true |
|
|
45
|
+
| **Disabled** | `Colors.black_04` | `Colors.black_08` | `Colors.black_08` | 0.5 | false |
|
|
46
|
+
|
|
47
|
+
Transition giữa unselected ↔ selected là immediate (no animation).
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Variant-to-Context Map
|
|
52
|
+
|
|
53
|
+
| Variant | Khi nào dùng | Tránh khi | Ví dụ trong MoMo |
|
|
54
|
+
|---------|-------------|-----------|-------------------|
|
|
55
|
+
| Unselected (default) | Chip chưa được chọn trong filter group | Chỉ có 1 chip đơn lẻ — không có group | Filter dịch vụ trên màn hình tìm kiếm (Tất cả / Chuyển tiền / Thanh toán) |
|
|
56
|
+
| Selected | User đã chọn — active filter đang apply | Không có toggle behavior — dùng Tag | Filter "Chuyển tiền" đang active trong lịch sử GD |
|
|
57
|
+
| Removable (rightIcon=close) | User remove selection bằng tap X | Label dài >3 từ — chip bị stretch | Địa chỉ đã chọn trong form giao hàng, tags đã pick |
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## SSR Pattern
|
|
62
|
+
|
|
63
|
+
### Horizontal Filter Bar
|
|
64
|
+
```json
|
|
65
|
+
{
|
|
66
|
+
"id": "filter_chips",
|
|
67
|
+
"type": "row",
|
|
68
|
+
"scrollable": true,
|
|
69
|
+
"spacing": "Spacing.XS",
|
|
70
|
+
"forEach": "{{data.filterOptions}}",
|
|
71
|
+
"render": {
|
|
72
|
+
"component": "Chip",
|
|
73
|
+
"props": {
|
|
74
|
+
"label": "{{item.label}}",
|
|
75
|
+
"size": "small",
|
|
76
|
+
"selected": "{{state.selectedFilter == $index}}"
|
|
77
|
+
},
|
|
78
|
+
"onPress": "setState://selectedFilter=$index"
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Multi-select Wrap Group
|
|
84
|
+
```json
|
|
85
|
+
{
|
|
86
|
+
"id": "category_chips",
|
|
87
|
+
"type": "wrap",
|
|
88
|
+
"forEach": "{{data.categories}}",
|
|
89
|
+
"render": {
|
|
90
|
+
"component": "Chip",
|
|
91
|
+
"props": {
|
|
92
|
+
"label": "{{item.name}}",
|
|
93
|
+
"size": "large",
|
|
94
|
+
"selected": "{{item.selected}}",
|
|
95
|
+
"leftIcon": "{{item.icon}}"
|
|
96
|
+
},
|
|
97
|
+
"onPress": "setState://toggleCategory={{item.id}}"
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Removable Tags
|
|
103
|
+
```json
|
|
104
|
+
{
|
|
105
|
+
"id": "selected_tags",
|
|
106
|
+
"type": "wrap",
|
|
107
|
+
"forEach": "{{state.selectedItems}}",
|
|
108
|
+
"render": {
|
|
109
|
+
"component": "Chip",
|
|
110
|
+
"props": {
|
|
111
|
+
"label": "{{item.name}}",
|
|
112
|
+
"size": "small",
|
|
113
|
+
"selected": true,
|
|
114
|
+
"rightIcon": "close"
|
|
115
|
+
},
|
|
116
|
+
"onPressRightIcon": "setState://removeItem={{item.id}}"
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## Accessibility
|
|
124
|
+
|
|
125
|
+
- Mỗi chip cần accessible label gồm: text + current state (selected/not).
|
|
126
|
+
- Role: `"button"` hoặc `"toggle"` — screen readers phải announce interactive nature.
|
|
127
|
+
- Khi selected state thay đổi: announce "Selected" hoặc "Deselected".
|
|
128
|
+
- Trong chip group: navigable as a group với clear boundaries.
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Usage Guidelines
|
|
133
|
+
|
|
134
|
+
### Do
|
|
135
|
+
- Dùng Chip để filter content theo category, type, attribute.
|
|
136
|
+
- Dùng cho multi-select — user pick từ set of options.
|
|
137
|
+
- Dùng cho removable selections (dismiss bằng X icon).
|
|
138
|
+
- Giữ label ngắn — 1-3 words.
|
|
139
|
+
- Group related chips trong horizontal scrollable row hoặc wrapping layout.
|
|
140
|
+
|
|
141
|
+
### Don't
|
|
142
|
+
- Không dùng cho static status display — dùng **Tag**.
|
|
143
|
+
- Không dùng cho navigation actions — dùng **Button**.
|
|
144
|
+
- Không dùng cho notification counts — dùng **Badge**.
|
|
145
|
+
- Không nest interactive elements bên trong Chip.
|
|
146
|
+
- Không dùng text label dài gây stretch chip.
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# Collapse
|
|
2
|
+
|
|
3
|
+
> Expandable/collapsible content section — header + chevron toggle to show/hide content. Progressive disclosure.
|
|
4
|
+
|
|
5
|
+
**Package:** `@momo-kits/collapse`
|
|
6
|
+
**Platform:** RN ✅ | Compose ❌ (build with AnimatedVisibility)
|
|
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
|
+
| `title` | string | — | required | Header text label |
|
|
17
|
+
| `expanded` | boolean | `true` \| `false` | `false` | Controlled expand/collapse state |
|
|
18
|
+
| `defaultExpanded` | boolean | `true` \| `false` | `false` | Initial state khi uncontrolled [VERIFY] |
|
|
19
|
+
| `disabled` | boolean | `true` \| `false` | `false` | Non-interactive — header not tappable |
|
|
20
|
+
| `showDivider` | boolean | `true` \| `false` | `false` | Show Divider between header and content [VERIFY] |
|
|
21
|
+
| `children` | element | — | required | Content to show/hide — any components |
|
|
22
|
+
| `onChange` | function | — | — | Callback khi toggle. `"onChange": "setState://expanded"` |
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## States
|
|
27
|
+
|
|
28
|
+
| State | Header | Chevron | Content | Interactive |
|
|
29
|
+
|-------|--------|---------|---------|-------------|
|
|
30
|
+
| **Collapsed** | `Colors.black_17` text | Down (0°) | Hidden | true |
|
|
31
|
+
| **Expanded** | `Colors.black_17` text | Up (180°) | Visible | true |
|
|
32
|
+
| **Pressed** | Opacity 0.8 | — | — | true |
|
|
33
|
+
| **Disabled** | `Colors.black_08` text | `Colors.black_08` | Per current state | false |
|
|
34
|
+
|
|
35
|
+
Chevron rotates smoothly (180°) on toggle. Content animates with height transition.
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Variant-to-Context Map
|
|
40
|
+
|
|
41
|
+
| Context | Khi nào dùng | Tránh khi | Ví dụ trong MoMo |
|
|
42
|
+
|---------|-------------|-----------|-------------------|
|
|
43
|
+
| **FAQ / Help** | Q&A sections, supplementary info | Primary content → show directly | FAQ trong Help center |
|
|
44
|
+
| **Advanced settings** | Secondary options user rarely needs | Critical settings → show always | Cài đặt nâng cao, tùy chọn bổ sung |
|
|
45
|
+
| **Accordion** | Multiple collapse sections, one open at a time | Independent sections | Chi tiết giao dịch, điều khoản |
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## SSR Pattern
|
|
50
|
+
|
|
51
|
+
### FAQ Section
|
|
52
|
+
```json
|
|
53
|
+
{
|
|
54
|
+
"id": "faq_section",
|
|
55
|
+
"type": "section",
|
|
56
|
+
"forEach": "{{data.faqs}}",
|
|
57
|
+
"render": {
|
|
58
|
+
"component": "Collapse",
|
|
59
|
+
"props": {
|
|
60
|
+
"title": "{{item.question}}",
|
|
61
|
+
"expanded": false
|
|
62
|
+
},
|
|
63
|
+
"children": [
|
|
64
|
+
{
|
|
65
|
+
"component": "Text",
|
|
66
|
+
"props": {
|
|
67
|
+
"content": "{{item.answer}}",
|
|
68
|
+
"typography": "body_default_regular"
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
]
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Transaction Details Accordion
|
|
77
|
+
```json
|
|
78
|
+
{
|
|
79
|
+
"component": "Collapse",
|
|
80
|
+
"props": {
|
|
81
|
+
"title": "Chi tiết giao dịch",
|
|
82
|
+
"showDivider": true
|
|
83
|
+
},
|
|
84
|
+
"children": [
|
|
85
|
+
{
|
|
86
|
+
"component": "Text",
|
|
87
|
+
"props": {
|
|
88
|
+
"content": "{{data.transactionDetails}}",
|
|
89
|
+
"typography": "body_s_regular"
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
]
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## Accessibility
|
|
99
|
+
|
|
100
|
+
- Header role: button. Announce title + state ("Chi tiết giao dịch, collapsed").
|
|
101
|
+
- Content hidden from accessibility tree khi collapsed.
|
|
102
|
+
- Full header row is tap target, not just chevron.
|
|
103
|
+
- State change announced on toggle.
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## Usage Guidelines
|
|
108
|
+
|
|
109
|
+
### Do
|
|
110
|
+
- Dùng cho secondary/supplementary content — FAQ, advanced settings, details.
|
|
111
|
+
- Clear descriptive title — user knows what content is hidden.
|
|
112
|
+
- Start collapsed by default unless content is expected to be read immediately.
|
|
113
|
+
- Divider khi content is visually dense.
|
|
114
|
+
|
|
115
|
+
### Don't
|
|
116
|
+
- Không hide primary/critical content trong collapse.
|
|
117
|
+
- Không dùng cho navigation → dùng proper nav patterns.
|
|
118
|
+
- Không nest collapse deeply (collapse trong collapse) — confusing UX.
|
|
119
|
+
- Không dùng khi content chỉ 1-2 lines — show directly instead.
|
|
120
|
+
- Không remove chevron icon — user cần visual indicator.
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# DatePicker
|
|
2
|
+
|
|
3
|
+
> Calendar-based date selection — single date, date range, or multiple dates. Month grid (RN) or format-driven (Compose).
|
|
4
|
+
|
|
5
|
+
**Package:** `@momo-kits/date-picker` (RN) / built-in (Compose)
|
|
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
|
+
| **Mode** | `single` · `range` · `multiple` | `single` |
|
|
17
|
+
| **Platform** | RN (calendar grid) · Compose (format-driven DD-MM-YYYY) | per platform |
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Props
|
|
22
|
+
|
|
23
|
+
| Prop | Type | Values | Default | Description |
|
|
24
|
+
|------|------|--------|---------|-------------|
|
|
25
|
+
| `mode` | string | `"single"` \| `"range"` \| `"multiple"` | `"single"` | Selection mode |
|
|
26
|
+
| `value` | varies | Date (single), `{ start, end }` (range), `[Date]` (multiple) | — | Current selected value |
|
|
27
|
+
| `minDate` | date | — | — | Earliest selectable date. Dates before → disabled |
|
|
28
|
+
| `maxDate` | date | — | — | Latest selectable date. Dates after → disabled |
|
|
29
|
+
| `format` | string | date format pattern | `"DD-MM-YYYY"` | Display format (Compose) [VERIFY] |
|
|
30
|
+
| `showTimePicker` | boolean | `true` \| `false` | `false` | Include time selection (Compose: HH:mm) [VERIFY] |
|
|
31
|
+
| `onChange` | function | — | — | Callback khi date selected. `"onChange": "setState://selectedDate"` |
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Day Cell States
|
|
36
|
+
|
|
37
|
+
| State | Background | Text Color | Description |
|
|
38
|
+
|-------|-----------|-----------|-------------|
|
|
39
|
+
| **Default** | Transparent | `Colors.black_17` | Normal selectable date |
|
|
40
|
+
| **Today** | Transparent | `Colors.pink_03` | Current date highlight |
|
|
41
|
+
| **Selected** | `Colors.pink_03` circle | `Colors.white` | User-chosen date |
|
|
42
|
+
| **Disabled** | Transparent | `Colors.black_08` | Outside min/max range |
|
|
43
|
+
| **Range start** | `Colors.pink_03` (left-rounded) | `Colors.white` | First date in range |
|
|
44
|
+
| **Range end** | `Colors.pink_03` (right-rounded) | `Colors.white` | Last date in range |
|
|
45
|
+
| **In range** | `Colors.pink_09` (light pink) | `Colors.pink_03` | Dates between start/end |
|
|
46
|
+
| **Other month** | Transparent | `Colors.black_08` | Adjacent month dates |
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## Variant-to-Context Map
|
|
51
|
+
|
|
52
|
+
| Mode | Khi nào dùng | Tránh khi | Ví dụ trong MoMo |
|
|
53
|
+
|------|-------------|-----------|-------------------|
|
|
54
|
+
| **single** | Pick one specific date | Date range needed | Chọn ngày sinh, ngày hẹn |
|
|
55
|
+
| **range** | Select start + end date | Single date needed | Lọc lịch sử giao dịch, đặt phòng |
|
|
56
|
+
| **multiple** | Select multiple individual dates | Continuous range → dùng range mode | Chọn nhiều ngày nghỉ |
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## SSR Pattern
|
|
61
|
+
|
|
62
|
+
### Single Date Selection
|
|
63
|
+
```json
|
|
64
|
+
{
|
|
65
|
+
"component": "DatePicker",
|
|
66
|
+
"props": {
|
|
67
|
+
"mode": "single",
|
|
68
|
+
"value": "{{state.selectedDate}}",
|
|
69
|
+
"minDate": "{{data.today}}",
|
|
70
|
+
"maxDate": "{{data.maxBookingDate}}"
|
|
71
|
+
},
|
|
72
|
+
"onChange": "setState://selectedDate"
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Date Range Filter
|
|
77
|
+
```json
|
|
78
|
+
{
|
|
79
|
+
"component": "DatePicker",
|
|
80
|
+
"props": {
|
|
81
|
+
"mode": "range",
|
|
82
|
+
"value": {
|
|
83
|
+
"start": "{{state.startDate}}",
|
|
84
|
+
"end": "{{state.endDate}}"
|
|
85
|
+
},
|
|
86
|
+
"minDate": "{{data.earliestTransaction}}"
|
|
87
|
+
},
|
|
88
|
+
"onChange": "setState://dateRange"
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## Accessibility
|
|
95
|
+
|
|
96
|
+
- Each day cell announces full date: "26 tháng 3 năm 2026".
|
|
97
|
+
- Selected dates announce selected state.
|
|
98
|
+
- Disabled dates: announced as disabled, not focusable/tappable.
|
|
99
|
+
- Navigation arrows: "Tháng trước", "Tháng sau".
|
|
100
|
+
- Range mode: announce context "Ngày bắt đầu: 20 tháng 3. Ngày kết thúc: 26 tháng 3."
|
|
101
|
+
- Today distinguishable: "Hôm nay, 20 tháng 3 năm 2026".
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Usage Guidelines
|
|
106
|
+
|
|
107
|
+
### Do
|
|
108
|
+
- Dùng cho date selection trong forms, booking, scheduling.
|
|
109
|
+
- Highlight today cho reference point.
|
|
110
|
+
- Disable dates outside valid range.
|
|
111
|
+
- Show selected date in text field bên ngoài calendar cho confirmation.
|
|
112
|
+
- Range mode cho check-in/check-out, date filters.
|
|
113
|
+
|
|
114
|
+
### Don't
|
|
115
|
+
- Không dùng cho time-only selection → dùng dedicated time picker.
|
|
116
|
+
- Không allow selection of disabled dates.
|
|
117
|
+
- Không show quá nhiều months — month-by-month navigation.
|
|
118
|
+
- Không hide current month/year — user cần context.
|
|
119
|
+
- Không dùng cho relative dates ("7 ngày gần nhất") → dùng **Chip** preset options.
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Divider
|
|
2
|
+
|
|
3
|
+
> Horizontal line separator — phân chia content sections hoặc list items.
|
|
4
|
+
|
|
5
|
+
**Package:** `@momo-kits/foundation`
|
|
6
|
+
**Platform:** RN ✅ | Compose ✅
|
|
7
|
+
**Completeness:** done
|
|
8
|
+
**Figma node:** [VERIFY]
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Props
|
|
13
|
+
|
|
14
|
+
| Prop | Type | Values | Default | Description |
|
|
15
|
+
|------|------|--------|---------|-------------|
|
|
16
|
+
| `color` | string | `Colors.*` token | `"Colors.black_04"` | Line color [VERIFY] |
|
|
17
|
+
|
|
18
|
+
> Divider là component đơn giản nhất — chỉ 1 prop optional. Full width of parent container by default.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## States
|
|
23
|
+
|
|
24
|
+
| State | Color | Description |
|
|
25
|
+
|-------|-------|-------------|
|
|
26
|
+
| **Default** | `Colors.black_04` | Static, non-interactive |
|
|
27
|
+
|
|
28
|
+
Divider chỉ có 1 state. Không interactive.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Variant-to-Context Map
|
|
33
|
+
|
|
34
|
+
| Context | Khi nào dùng | Tránh khi | Ví dụ trong MoMo |
|
|
35
|
+
|---------|-------------|-----------|-------------------|
|
|
36
|
+
| **List separator** | Phân cách items trong vertical list | Spacing đủ clear → không cần divider | Danh sách giao dịch, contacts list |
|
|
37
|
+
| **Section boundary** | Phân chia content sections | Chỉ có 1 section → không cần | Phân chia "Thông tin" và "Số tiền" trong confirm screen |
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## SSR Pattern
|
|
42
|
+
|
|
43
|
+
### List with Dividers
|
|
44
|
+
```json
|
|
45
|
+
{
|
|
46
|
+
"id": "transaction_list",
|
|
47
|
+
"type": "section",
|
|
48
|
+
"forEach": "{{data.transactions}}",
|
|
49
|
+
"render": [
|
|
50
|
+
{
|
|
51
|
+
"component": "ListItem",
|
|
52
|
+
"props": {
|
|
53
|
+
"title": "{{item.title}}",
|
|
54
|
+
"rightText": "{{item.amount}}"
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"component": "Divider",
|
|
59
|
+
"props": {}
|
|
60
|
+
}
|
|
61
|
+
]
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Accessibility
|
|
68
|
+
|
|
69
|
+
- Divider là decorative — ẩn khỏi screen readers.
|
|
70
|
+
- Không dùng divider để convey meaning — chỉ visual separator.
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Usage Guidelines
|
|
75
|
+
|
|
76
|
+
### Do
|
|
77
|
+
- Dùng để separate list items trong vertical list.
|
|
78
|
+
- Dùng sparingly — rely on spacing trước.
|
|
79
|
+
- Parent layout control spacing above/below divider.
|
|
80
|
+
|
|
81
|
+
### Don't
|
|
82
|
+
- Không dùng cho purely decorative khi spacing đủ.
|
|
83
|
+
- Không stack multiple dividers.
|
|
84
|
+
- Không đặt divider ở top/bottom container khi không cần separation.
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# Icon
|
|
2
|
+
|
|
3
|
+
> Vector icon component — render icons từ design system icon set cho actions, navigation, và visual cues.
|
|
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
|
+
| `name` | string | icon name | required | Icon identifier từ icon set [VERIFY] |
|
|
17
|
+
| `size` | string | `"inline"` \| `"default"` \| `"standard"` \| `"featured"` \| `"hero"` | `"default"` | Icon size [VERIFY] |
|
|
18
|
+
| `color` | string | `Colors.*` token | `"Colors.black_17"` | Icon color. Có thể inherit từ parent [VERIFY] |
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Variants
|
|
23
|
+
|
|
24
|
+
| Size | Dimension | Usage |
|
|
25
|
+
|------|-----------|-------|
|
|
26
|
+
| **inline** | 16×16pt | Inline with text, small indicators |
|
|
27
|
+
| **default** | 20×20pt | Default cho most UI contexts |
|
|
28
|
+
| **standard** | 24×24pt | Navigation bars, action buttons, list items |
|
|
29
|
+
| **featured** | 32×32pt | Emphasized icons, feature highlights |
|
|
30
|
+
| **hero** | 48×48pt | Empty states, onboarding, large call-outs |
|
|
31
|
+
|
|
32
|
+
### Color Context
|
|
33
|
+
|
|
34
|
+
| Context | Color Token |
|
|
35
|
+
|---------|-----------|
|
|
36
|
+
| Primary content | `Colors.black_17` |
|
|
37
|
+
| Secondary | `Colors.black_15` |
|
|
38
|
+
| Hint/placeholder | `Colors.black_12` |
|
|
39
|
+
| Disabled | `Colors.black_08` |
|
|
40
|
+
| Accent/interactive | `Colors.pink_03` |
|
|
41
|
+
| Error | `Colors.red_03` |
|
|
42
|
+
| On dark background | `Colors.white` |
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## States
|
|
47
|
+
|
|
48
|
+
| State | Color | Description |
|
|
49
|
+
|-------|-------|-------------|
|
|
50
|
+
| **Default** | per `color` prop | Normal display |
|
|
51
|
+
| **Disabled** | `Colors.black_08` | Non-interactive context |
|
|
52
|
+
|
|
53
|
+
Icon là static display. States chỉ ảnh hưởng color.
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Variant-to-Context Map
|
|
58
|
+
|
|
59
|
+
| Size | Color | Khi nào dùng | Ví dụ trong MoMo |
|
|
60
|
+
|------|-------|-------------|-------------------|
|
|
61
|
+
| `standard` | `Colors.black_17` | Navigation bar, toolbar icons | Back arrow, search icon trong TopNav |
|
|
62
|
+
| `inline` | `Colors.black_12` | Inline with text | Icon trước hint text |
|
|
63
|
+
| `featured` | `Colors.pink_03` | Feature highlights | Service icons trên Home |
|
|
64
|
+
| `hero` | `Colors.black_12` | Empty state illustrations | Empty transaction list icon |
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## SSR Pattern
|
|
69
|
+
|
|
70
|
+
### Icon in Navigation Action
|
|
71
|
+
```json
|
|
72
|
+
{
|
|
73
|
+
"component": "Icon",
|
|
74
|
+
"props": {
|
|
75
|
+
"name": "navigation_search",
|
|
76
|
+
"size": "standard",
|
|
77
|
+
"color": "Colors.black_17"
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Icon Inline with Text
|
|
83
|
+
```json
|
|
84
|
+
{
|
|
85
|
+
"id": "info_row",
|
|
86
|
+
"type": "row",
|
|
87
|
+
"children": [
|
|
88
|
+
{
|
|
89
|
+
"component": "Icon",
|
|
90
|
+
"props": {
|
|
91
|
+
"name": "info_circle",
|
|
92
|
+
"size": "inline",
|
|
93
|
+
"color": "Colors.blue_03"
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
"component": "Text",
|
|
98
|
+
"props": {
|
|
99
|
+
"content": "Phí giao dịch miễn phí",
|
|
100
|
+
"typography": "caption_default_regular",
|
|
101
|
+
"color": "Colors.blue_03"
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
]
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## Accessibility
|
|
111
|
+
|
|
112
|
+
- Interactive icons: PHẢI có text accessible label. Icon-only button → provide label.
|
|
113
|
+
- Decorative icons (next to text label): ẩn khỏi screen readers.
|
|
114
|
+
- Không rely solely on icon color để convey state — pair với indicators.
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## Usage Guidelines
|
|
119
|
+
|
|
120
|
+
### Do
|
|
121
|
+
- Dùng predefined sizes consistently.
|
|
122
|
+
- Dùng `Colors.*` tokens cho tất cả icon colors.
|
|
123
|
+
- Provide accessible labels cho tất cả interactive icons.
|
|
124
|
+
- `standard` (24pt) cho navigation/toolbar. `inline` (16pt) cho text.
|
|
125
|
+
|
|
126
|
+
### Don't
|
|
127
|
+
- Không dùng icon là sole means of communication without accessible label.
|
|
128
|
+
- Không scale icons to arbitrary sizes giữa predefined steps.
|
|
129
|
+
- Không dùng raw hex colors — luôn reference design tokens.
|
|
130
|
+
- Không dùng overly detailed graphics làm icons.
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# Image
|
|
2
|
+
|
|
3
|
+
## Description
|
|
4
|
+
|
|
5
|
+
An image display component for rendering photos, illustrations, and banners with built-in loading state support. Image handles URL-based loading, displays a skeleton or placeholder while content is being fetched, and supports aspect ratio control to maintain proper proportions.
|
|
6
|
+
|
|
7
|
+
**Package:** `@momo-kits/foundation`
|
|
8
|
+
**Platform support:** RN ✅ | Compose ✅
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Features
|
|
13
|
+
|
|
14
|
+
| Feature | Description |
|
|
15
|
+
|--------------------|--------------------------------------------------------------|
|
|
16
|
+
| **URL loading** | Loads images from remote URLs with automatic caching |
|
|
17
|
+
| **Aspect ratio** | Maintains image proportions via configurable aspect ratio |
|
|
18
|
+
| **Loading state** | Displays a skeleton or placeholder while the image loads |
|
|
19
|
+
| **Error fallback** | Shows a fallback placeholder if the image fails to load |
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Loading States
|
|
24
|
+
|
|
25
|
+
| State | Visual |
|
|
26
|
+
|-------------|--------------------------------------------------------------|
|
|
27
|
+
| **Loading** | Skeleton placeholder (animated shimmer) matching the image dimensions |
|
|
28
|
+
| **Loaded** | Full image displayed, skeleton fades out |
|
|
29
|
+
| **Error** | Static fallback placeholder (generic image icon or custom) |
|
|
30
|
+
|
|
31
|
+
- The skeleton placeholder should match the expected dimensions of the final image to prevent layout shifts
|
|
32
|
+
- Transition from skeleton to loaded image should use a subtle fade-in
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Sizing
|
|
37
|
+
|
|
38
|
+
- Image dimensions are constrained by the parent container
|
|
39
|
+
- Aspect ratio can be explicitly set to maintain proportions regardless of container size
|
|
40
|
+
- Common aspect ratios: 1:1 (square), 16:9 (banner), 4:3 (photo), 3:2 (landscape)
|
|
41
|
+
- When only width or height is provided, the other dimension is calculated from the aspect ratio
|
|
42
|
+
- If no aspect ratio is specified, the image uses its natural dimensions constrained by the parent
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Layout
|
|
47
|
+
|
|
48
|
+
- Images fill their container by default (resize mode: cover)
|
|
49
|
+
- Other resize modes: contain (fit within bounds), stretch (fill exactly), center (no scaling)
|
|
50
|
+
- Corner radius can be applied for rounded images (use `Radius.*` tokens)
|
|
51
|
+
- For circular images (e.g., avatars), apply a radius equal to half the width/height
|
|
52
|
+
- Images should not overflow their container — clip content at the container bounds
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Accessibility
|
|
57
|
+
|
|
58
|
+
- **Alt text required:** Always provide descriptive alt text that conveys the content or purpose of the image
|
|
59
|
+
- **Decorative images:** If an image is purely decorative and adds no informational value, mark it as decorative so screen readers skip it
|
|
60
|
+
- **Loading announcement:** Screen readers should not announce the loading state repeatedly — announce once when the image finishes loading if it is meaningful content
|
|
61
|
+
- **Error state:** If the image fails to load, the fallback should convey that the content is unavailable
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Do's and Don'ts
|
|
66
|
+
|
|
67
|
+
### Do's
|
|
68
|
+
- Always provide alt text that describes the image content or purpose
|
|
69
|
+
- Set an explicit aspect ratio to prevent layout shifts during loading
|
|
70
|
+
- Use the skeleton loading state for all remotely loaded images
|
|
71
|
+
- Optimize image URLs for the target display size (avoid loading oversized assets)
|
|
72
|
+
- Use appropriate resize mode based on context (cover for banners, contain for logos)
|
|
73
|
+
- Apply `Radius.*` tokens for rounded corners
|
|
74
|
+
|
|
75
|
+
### Don'ts
|
|
76
|
+
- Don't use Image for vector icons — use the Icon component instead
|
|
77
|
+
- Don't leave alt text empty for meaningful images
|
|
78
|
+
- Don't load full-resolution images when a thumbnail would suffice
|
|
79
|
+
- Don't allow images to cause layout shifts by omitting dimensions or aspect ratio
|
|
80
|
+
- Don't use stretch resize mode for photos — it distorts the content
|
|
81
|
+
- Don't hard-code pixel dimensions when the layout should be responsive to the container
|