@maccesar/titools 2.2.12 → 2.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.
Files changed (98) hide show
  1. package/README.md +255 -713
  2. package/bin/titools.js +1 -1
  3. package/lib/commands/update.js +5 -6
  4. package/lib/config.js +1 -0
  5. package/lib/downloader.js +10 -0
  6. package/package.json +1 -1
  7. package/skills/alloy-guides/SKILL.md +46 -48
  8. package/skills/alloy-guides/references/CONTROLLERS.md +4 -6
  9. package/skills/alloy-guides/references/MODELS.md +340 -184
  10. package/skills/alloy-guides/references/VIEWS_DYNAMIC.md +3 -4
  11. package/skills/alloy-guides/references/VIEWS_STYLES.md +44 -46
  12. package/skills/alloy-guides/references/VIEWS_WITHOUT_CONTROLLERS.md +4 -5
  13. package/skills/alloy-guides/references/VIEWS_XML.md +51 -17
  14. package/skills/alloy-guides/references/WIDGETS.md +1 -1
  15. package/skills/alloy-howtos/SKILL.md +12 -13
  16. package/skills/alloy-howtos/references/cli_reference.md +40 -41
  17. package/skills/alloy-howtos/references/samples.md +3 -4
  18. package/skills/purgetss/SKILL.md +369 -356
  19. package/skills/purgetss/references/EXAMPLES.md +24 -25
  20. package/skills/purgetss/references/animation-advanced.md +555 -0
  21. package/skills/purgetss/references/animation-system.md +395 -995
  22. package/skills/purgetss/references/apply-directive.md +111 -141
  23. package/skills/purgetss/references/arbitrary-values.md +206 -480
  24. package/skills/purgetss/references/class-categories.md +277 -0
  25. package/skills/purgetss/references/class-index.md +1 -420
  26. package/skills/purgetss/references/cli-commands.md +446 -556
  27. package/skills/purgetss/references/configurable-properties.md +163 -599
  28. package/skills/purgetss/references/custom-rules.md +33 -76
  29. package/skills/purgetss/references/customization-deep-dive.md +319 -518
  30. package/skills/purgetss/references/dynamic-component-creation.md +33 -37
  31. package/skills/purgetss/references/grid-layout.md +42 -371
  32. package/skills/purgetss/references/icon-fonts.md +82 -475
  33. package/skills/purgetss/references/installation-setup.md +159 -331
  34. package/skills/purgetss/references/migration-guide.md +54 -109
  35. package/skills/purgetss/references/opacity-modifier.md +25 -222
  36. package/skills/purgetss/references/performance-tips.md +2 -2
  37. package/skills/purgetss/references/platform-modifiers.md +21 -407
  38. package/skills/purgetss/references/tikit-components.md +237 -104
  39. package/skills/purgetss/references/titanium-resets.md +20 -21
  40. package/skills/purgetss/references/ui-ux-design.md +171 -1702
  41. package/skills/ti-api/SKILL.md +109 -0
  42. package/skills/ti-api/references/api-android.md +675 -0
  43. package/skills/ti-api/references/api-app-platform.md +636 -0
  44. package/skills/ti-api/references/api-core.md +764 -0
  45. package/skills/ti-api/references/api-data-network.md +641 -0
  46. package/skills/ti-api/references/api-media.md +655 -0
  47. package/skills/ti-api/references/api-modules-ble-bluetooth.md +657 -0
  48. package/skills/ti-api/references/api-modules-coremotion-urlsession.md +411 -0
  49. package/skills/ti-api/references/api-modules-map.md +632 -0
  50. package/skills/ti-api/references/api-modules-nfc.md +725 -0
  51. package/skills/ti-api/references/api-modules-social-misc.md +526 -0
  52. package/skills/ti-api/references/api-services.md +700 -0
  53. package/skills/ti-api/references/api-ui-android.md +499 -0
  54. package/skills/ti-api/references/api-ui-extras.md +702 -0
  55. package/skills/ti-api/references/api-ui-ios-animator.md +378 -0
  56. package/skills/ti-api/references/api-ui-ios.md +756 -0
  57. package/skills/ti-api/references/api-ui-lists.md +581 -0
  58. package/skills/ti-api/references/api-ui-text-input.md +607 -0
  59. package/skills/ti-api/references/api-ui-views.md +572 -0
  60. package/skills/ti-api/references/api-ui-windows-navigation.md +676 -0
  61. package/skills/ti-api/references/api-xml-global.md +743 -0
  62. package/skills/ti-expert/SKILL.md +46 -45
  63. package/skills/ti-expert/references/adaptive-layouts.md +414 -0
  64. package/skills/ti-expert/references/alloy-builtins.md +16 -20
  65. package/skills/ti-expert/references/alloy-structure.md +40 -42
  66. package/skills/ti-expert/references/anti-patterns.md +34 -0
  67. package/skills/ti-expert/references/code-conventions.md +5 -3
  68. package/skills/ti-expert/references/error-handling.md +14 -7
  69. package/skills/ti-expert/references/examples.md +4 -2
  70. package/skills/ti-expert/references/performance-optimization.md +26 -24
  71. package/skills/ti-expert/references/security-device.md +17 -14
  72. package/skills/ti-expert/references/security-fundamentals.md +60 -101
  73. package/skills/ti-expert/references/state-management.md +15 -14
  74. package/skills/ti-expert/references/testing-e2e-ci.md +30 -21
  75. package/skills/ti-expert/references/theming.md +12 -20
  76. package/skills/ti-guides/SKILL.md +13 -17
  77. package/skills/ti-guides/references/advanced-data-and-images.md +30 -10
  78. package/skills/ti-guides/references/application-frameworks.md +3 -3
  79. package/skills/ti-guides/references/coding-best-practices.md +31 -2
  80. package/skills/ti-guides/references/commonjs-advanced.md +46 -4
  81. package/skills/ti-guides/references/hello-world.md +9 -13
  82. package/skills/ti-guides/references/hyperloop-native-access.md +4 -1
  83. package/skills/ti-guides/references/javascript-primer.md +13 -5
  84. package/skills/ti-guides/references/resources.md +0 -2
  85. package/skills/ti-guides/references/style-and-conventions.md +1 -0
  86. package/skills/ti-guides/references/tiapp-config.md +0 -32
  87. package/skills/ti-howtos/SKILL.md +43 -45
  88. package/skills/ti-howtos/references/buffer-codec-streams.md +25 -3
  89. package/skills/ti-howtos/references/debugging-profiling.md +14 -25
  90. package/skills/ti-howtos/references/google-maps-v2.md +3 -3
  91. package/skills/ti-howtos/references/ios-map-kit.md +8 -1
  92. package/skills/ti-howtos/references/notification-services.md +0 -1
  93. package/skills/ti-howtos/references/webpack-build-pipeline.md +3 -0
  94. package/skills/ti-ui/SKILL.md +47 -49
  95. package/skills/ti-ui/references/application-structures.md +3 -2
  96. package/skills/ti-ui/references/orientation.md +17 -9
  97. package/skills/ti-ui/references/platform-ui-ios.md +63 -0
  98. package/skills/ti-ui/references/scrolling-views.md +39 -0
@@ -1,969 +1,302 @@
1
- # UI/UX Design Patterns for Titanium SDK with PurgeTSS
1
+ # UI/UX Design Patterns for Titanium with PurgeTSS
2
2
 
3
- A guide to building accessible and performant mobile UIs using Titanium SDK and PurgeTSS utility classes.
3
+ This guide collects practical UI patterns that stay aligned with Titanium layout behavior and verified PurgeTSS conventions.
4
4
 
5
- ## 1. Common UI Components
5
+ ## Core Rules
6
6
 
7
- ### Cards
7
+ - PurgeTSS is not Tailwind CSS. Verify classes before recommending them.
8
+ - Titanium does not support Flexbox. Use `horizontal`, `vertical`, or the default composite layout.
9
+ - Do not use `p-*` on `View`, `Window`, `ScrollView`, or `TableView`. Use margins on children instead.
10
+ - Prefer `w-screen` over `w-full` when you need `Ti.UI.FILL`.
11
+ - For dynamic components, prefer `$.UI.create()` over manual `Ti.UI.create*()` styling.
8
12
 
9
- Cards are versatile containers for content and actions on a single subject.
13
+ ## Cards
10
14
 
11
- #### Elevated Card
15
+ ### Elevated Card
12
16
 
13
17
  ```xml
14
- <View class="mb-4 rounded-xl bg-white shadow-lg">
15
- <ImageView class="mb-4 h-48 w-full rounded-lg" image="/images/card-image.jpg" />
16
- <Label class="mb-2 text-xl font-bold text-gray-800" text="Card Title" />
17
- <Label class="mb-4 text-sm text-gray-600" text="Card description goes here with details about the content." />
18
- <View class="horizontal mt-4">
19
- <Button class="bg-brand-500 mr-2 rounded-lg px-4 py-2 text-white" title="Action" />
20
- <Button class="rounded-lg bg-gray-200 px-4 py-2 text-gray-700" title="Learn More" />
21
- </View>
22
- </View>
23
- ```
18
+ <View class="rounded-xl bg-white shadow-lg">
19
+ <ImageView class="h-48 w-screen rounded-t-xl" image="/images/card-image.jpg" />
24
20
 
25
- #### Outlined Card
21
+ <Label class="mx-4 mt-4 text-xl font-bold text-gray-800" text="Card Title" />
22
+ <Label class="mx-4 mt-2 text-sm text-gray-600" text="Card description goes here." />
26
23
 
27
- ```xml
28
- <View class="mb-4 rounded-xl border border-gray-300 bg-white">
29
- <Label class="mb-2 text-lg font-semibold text-gray-800" text="Outlined Card" />
30
- <Label class="text-sm text-gray-600" text="Clean borders without elevation" />
24
+ <View class="horizontal mx-4 mt-4 mb-4">
25
+ <Button class="rounded-lg bg-blue-500 text-white" title="Action" />
26
+ <Button class="ml-2 rounded-lg bg-gray-200 text-gray-700" title="Learn More" />
27
+ </View>
31
28
  </View>
32
29
  ```
33
30
 
34
- #### Card with Image Overlay
31
+ ### Outlined Card
35
32
 
36
33
  ```xml
37
- <View class="relative mb-4 h-64 overflow-hidden rounded-xl">
38
- <ImageView class="absolute left-0 top-0 h-full w-full" image="/images/cover.jpg" />
39
- <View class="absolute bottom-0 left-0 w-full bg-gradient-to-t from-black to-transparent">
40
- <Label class="mb-4 ml-4 text-xl font-bold text-white" text="Overlay Title" />
41
- <Label class="mb-4 ml-4 text-sm text-gray-200" text="Subtitle text" />
42
- </View>
34
+ <View class="rounded-xl border-(1) border-gray-300 bg-white">
35
+ <Label class="mx-4 mt-4 text-lg font-semibold text-gray-800" text="Outlined Card" />
36
+ <Label class="mx-4 mt-2 mb-4 h-auto text-sm text-gray-600" text="Clean borders without elevation." />
43
37
  </View>
44
38
  ```
45
39
 
46
- #### Horizontal Card
40
+ ### Card with Image Overlay
47
41
 
48
42
  ```xml
49
- <View class="horizontal mb-3 rounded-lg bg-white shadow">
50
- <ImageView class="ml-3 mr-4 h-20 w-20 rounded-lg" image="/images/thumbnail.jpg" />
51
- <View class="vertical mr-3 w-full">
52
- <Label class="text-lg font-semibold text-gray-800" text="Title" />
53
- <Label class="text-sm text-gray-600" text="Description text that wraps to multiple lines if needed" />
54
- <Label class="text-brand-500 mt-1 text-xs" text="Read more →" />
43
+ <View class="h-48 w-screen rounded-xl">
44
+ <ImageView class="h-48 w-screen rounded-xl" image="/images/cover.jpg" />
45
+
46
+ <View class="bottom-0 w-screen bg-(#88000000) rounded-b-xl">
47
+ <Label class="mx-4 mt-4 text-xl font-bold text-white" text="Overlay Title" />
48
+ <Label class="mx-4 mt-2 mb-4 h-auto text-sm text-gray-200" text="Subtitle text" />
55
49
  </View>
56
50
  </View>
57
51
  ```
58
52
 
59
- ### Lists
60
-
61
- Lists display multiple items vertically and are essential for mobile UIs.
53
+ ## Lists
62
54
 
63
- #### Simple List Item
55
+ ### Simple List Item
64
56
 
65
57
  ```xml
66
58
  <View class="border-b border-gray-200 bg-white">
67
- <Label class="mx-4 my-4 text-base text-gray-800" text="List item content" />
59
+ <Label class="mx-4 my-4 h-auto text-base text-gray-800" text="List item content" />
68
60
  </View>
69
61
  ```
70
62
 
71
- #### List with Avatar
63
+ ### List with Avatar
72
64
 
73
65
  ```xml
74
66
  <View class="horizontal border-b border-gray-200 bg-white">
75
- <View class="bg-brand-500 ml-4 mr-4 h-12 w-12 rounded-full">
67
+ <View class="ml-4 my-4 rounded-full-12 bg-blue-500">
76
68
  <Label class="center text-lg font-bold text-white" text="JD" />
77
69
  </View>
78
- <View class="vertical mr-4">
70
+
71
+ <View class="vertical ml-3 my-4">
79
72
  <Label class="text-base font-semibold text-gray-800" text="John Doe" />
80
73
  <Label class="text-sm text-gray-500" text="john.doe@example.com" />
81
74
  </View>
82
75
  </View>
83
76
  ```
84
77
 
85
- #### List with Actions
78
+ ### ListView Template
86
79
 
87
80
  ```xml
88
- <View class="border-b border-gray-200 bg-white">
89
- <View class="horizontal">
90
- <View class="horizontal">
91
- <View class="ml-4 mr-4 h-12 w-12 rounded-lg bg-blue-100">
92
- <Label class="center fas fa-folder text-xl text-blue-500" />
93
- </View>
94
- <View class="vertical">
95
- <Label class="text-base font-semibold text-gray-800" text="Project Folder" />
96
- <Label class="text-sm text-gray-500" text="24 files" />
97
- </View>
98
- </View>
99
- <Label class="fas fa-chevron-right mr-4 text-gray-400" />
100
- </View>
101
- </View>
102
- ```
103
-
104
- #### List with Dividers
105
-
106
- ```xml
107
- <View class="bg-white">
108
- <!-- Item 1 -->
109
- <View class="border-b border-gray-100">
110
- <Label class="mx-4 my-4 text-base text-gray-800" text="Item 1" />
111
- </View>
112
- <!-- Item 2 -->
113
- <View class="border-b border-gray-100">
114
- <Label class="mx-4 my-4 text-base text-gray-800" text="Item 2" />
115
- </View>
116
- <!-- Item 3 -->
117
- <View>
118
- <Label class="mx-4 my-4 text-base text-gray-800" text="Item 3" />
119
- </View>
120
- </View>
121
- ```
122
-
123
- #### ListView with Custom Template
124
-
125
- ```xml
126
- <ListView id="myList" defaultItemTemplate="cardTemplate">
81
+ <ListView id="myList">
127
82
  <Templates>
128
- <ItemTemplate name="cardTemplate" class="h-auto">
129
- <View bindId="container" class="mx-4 mb-2 rounded-lg bg-white shadow">
130
- <View class="horizontal">
131
- <View bindId="iconContainer" class="bg-brand-100 mr-3 h-10 w-10 rounded-full">
132
- <Label bindId="icon" class="center fas fa-home text-brand-500" />
133
- </View>
134
- <View class="vertical">
135
- <Label bindId="title" class="text-base font-semibold text-gray-800" />
136
- <Label bindId="subtitle" class="text-sm text-gray-500" />
137
- </View>
83
+ <ItemTemplate name="cardTemplate" class="h-20">
84
+ <View bindId="container" class="horizontal mx-4 my-2 rounded-lg bg-white shadow-lg">
85
+ <View bindId="iconWrap" class="ml-4 my-4 rounded-full-10 bg-blue-100">
86
+ <Label bindId="icon" class="center fas fa-home text-blue-500" />
87
+ </View>
88
+
89
+ <View class="vertical ml-3 my-4">
90
+ <Label bindId="title" class="text-base font-semibold text-gray-800" />
91
+ <Label bindId="subtitle" class="text-sm text-gray-500" />
138
92
  </View>
139
93
  </View>
140
94
  </ItemTemplate>
141
95
  </Templates>
142
- <ListSection/>
143
- </ListView>
144
- ```
145
96
 
146
- ```javascript
147
- // Controller
148
- const items = [
149
- {
150
- container: {},
151
- icon: { text: "\uf015" }, // fa-home
152
- title: { text: "Item 1" },
153
- subtitle: { text: "First item description" }
154
- },
155
- {
156
- container: {},
157
- icon: { text: "\uf007" }, // fa-user
158
- title: { text: "Item 2" },
159
- subtitle: { text: "Second item description" }
160
- }
161
- ]
162
-
163
- $.myList.sections[0].setItems(items)
97
+ <ListSection />
98
+ </ListView>
164
99
  ```
165
100
 
166
- ### Forms
101
+ > **⚠️ ListView Performance**
102
+ > Prefer fixed item heights for production ListView templates. Avoid relying on `Ti.UI.SIZE` in scrolling cells when performance matters.
167
103
 
168
- Forms collect user input through various controls.
104
+ ## Forms
169
105
 
170
- #### Text Input
106
+ ### Text Input
171
107
 
172
108
  ```xml
173
109
  <View class="mb-4">
174
110
  <Label class="mb-2 text-sm font-medium text-gray-700" text="Email Address" />
175
- <TextField class="focus:border-brand-500 w-full rounded-lg border border-gray-300 bg-white px-4 py-3 text-base text-gray-800" hintText="you@example.com" keyboardType="Ti.UI.KEYBOARD_TYPE_EMAIL" autocapitalization="Ti.UI.TEXT_AUTOCAPITALIZATION_NONE" autocorrect="false" />
111
+ <TextField class="w-screen rounded-lg border-(1) border-gray-300 bg-white px-4 py-3 text-base text-gray-800" hintText="you@example.com" keyboardType="Ti.UI.KEYBOARD_TYPE_EMAIL" autocapitalization="Ti.UI.TEXT_AUTOCAPITALIZATION_NONE" autocorrect="false" />
176
112
  </View>
177
113
  ```
178
114
 
179
- #### Text Area
115
+ ### Text Area
180
116
 
181
117
  ```xml
182
118
  <View class="mb-4">
183
119
  <Label class="mb-2 text-sm font-medium text-gray-700" text="Message" />
184
- <TextArea class="h-32 w-full rounded-lg border border-gray-300 bg-white px-4 py-3 text-base text-gray-800" hintText="Type your message here..." autocapitalization="Ti.UI.TEXT_AUTOCAPITALIZATION_SENTENCES" />
185
- </View>
186
- ```
187
-
188
- #### Password Input
189
-
190
- ```xml
191
- <View class="mb-4">
192
- <Label class="mb-2 text-sm font-medium text-gray-700" text="Password" />
193
- <TextField class="w-full rounded-lg border border-gray-300 bg-white px-4 py-3 text-base text-gray-800" passwordMask="true" hintText="Enter password" />
194
- </View>
195
- ```
196
-
197
- #### Select/Dropdown (using Picker)
198
-
199
- ```xml
200
- <View class="mb-4">
201
- <Label class="mb-2 text-sm font-medium text-gray-700" text="Category" />
202
- <Picker class="w-full rounded-lg border border-gray-300 bg-white" selectionIndicator="true">
203
- <PickerRow title="Option 1" />
204
- <PickerRow title="Option 2" />
205
- <PickerRow title="Option 3" />
206
- </Picker>
120
+ <TextArea class="h-32 w-screen rounded-lg border-(1) border-gray-300 bg-white px-4 py-3 text-base text-gray-800" hintText="Type your message here..." />
207
121
  </View>
208
122
  ```
209
123
 
210
- #### Switch Toggle
211
-
212
- ```xml
213
- <View class="horizontal mb-4 rounded-lg border border-gray-200 bg-white">
214
- <View class="vertical">
215
- <Label class="text-base font-medium text-gray-800" text="Notifications" />
216
- <Label class="text-sm text-gray-500" text="Receive push notifications" />
217
- </View>
218
- <Switch class="ml-4" value="true" />
219
- </View>
220
- ```
221
-
222
- #### Slider
124
+ ### Validation State
223
125
 
224
126
  ```xml
225
127
  <View class="mb-4">
226
- <View class="horizontal mb-2">
227
- <Label class="text-sm font-medium text-gray-700" text="Volume" />
228
- <Label id="sliderValue" class="ml-auto text-sm text-gray-500" text="50%" />
229
- </View>
230
- <Slider class="w-full" min="0" max="100" value="50" />
231
- </View>
232
- ```
233
-
234
- #### Form with Validation States
235
-
236
- ```xml
237
- <!-- Error State -->
238
- <View class="mb-4">
239
- <Label class="mb-2 text-sm font-medium text-red-600" text="Email Address" />
240
- <TextField class="w-full rounded-lg border border-red-500 bg-white px-4 py-3 text-base" hintText="Invalid email" />
241
- <Label class="mt-1 text-xs text-red-500" text="Please enter a valid email address" />
242
- </View>
243
-
244
- <!-- Success State -->
245
- <View class="mb-4">
246
- <Label class="mb-2 text-sm font-medium text-green-600" text="Email Address" />
247
- <TextField class="w-full rounded-lg border border-green-500 bg-white px-4 py-3 text-base" hintText="Valid email" />
248
- <Label class="fas fa-check-circle mt-1 text-xs text-green-500" text=" Valid email" />
249
- </View>
250
- ```
251
-
252
- #### Form Section
253
-
254
- ```xml
255
- <View class="mb-6 rounded-lg bg-white shadow">
256
- <Label class="mx-6 mb-6 mt-6 text-xl font-bold text-gray-800" text="Account Information" />
257
-
258
- <View class="mb-4">
259
- <Label class="mb-2 text-sm font-medium text-gray-700" text="Full Name" />
260
- <TextField class="w-full rounded-lg border border-gray-300 bg-white px-4 py-3" hintText="John Doe" />
261
- </View>
262
-
263
- <View class="mb-4">
264
- <Label class="mb-2 text-sm font-medium text-gray-700" text="Email" />
265
- <TextField class="w-full rounded-lg border border-gray-300 bg-white px-4 py-3" hintText="john@example.com" keyboardType="Ti.UI.KEYBOARD_TYPE_EMAIL" />
266
- </View>
267
-
268
- <View class="mb-6">
269
- <Label class="mb-2 text-sm font-medium text-gray-700" text="Phone" />
270
- <TextField class="w-full rounded-lg border border-gray-300 bg-white px-4 py-3" hintText="+1 (555) 000-0000" keyboardType="Ti.UI.KEYBOARD_TYPE_PHONE" />
271
- </View>
272
-
273
- <Button class="bg-brand-500 w-full rounded-lg py-3 text-base font-semibold text-white" title="Save Changes" />
274
- </View>
275
- ```
276
-
277
- ### Buttons
278
-
279
- Buttons trigger actions and are primary interactive elements.
280
-
281
- #### Primary Button
282
-
283
- ```xml
284
- <Button class="bg-brand-500 rounded-lg px-6 py-3 text-base font-semibold text-white shadow-md" title="Primary Action" />
285
- ```
286
-
287
- #### Secondary Button
288
-
289
- ```xml
290
- <Button class="rounded-lg border border-gray-300 bg-white px-6 py-3 text-base font-semibold text-gray-700" title="Secondary Action" />
291
- ```
292
-
293
- #### Outline Button
294
-
295
- ```xml
296
- <Button class="border-brand-500 text-brand-500 rounded-lg border-2 bg-transparent px-6 py-3 text-base font-semibold" title="Outline" />
297
- ```
298
-
299
- #### Text Button
300
-
301
- ```xml
302
- <Button class="text-brand-500 bg-transparent text-base font-semibold" title="Text Only" />
303
- ```
304
-
305
- #### Icon Button
306
-
307
- ```xml
308
- <!-- EFFICIENT: Single Label with icon, size, and styling -->
309
- <Label class="rounded-full-12 bg-brand-500 fa-solid fa-plus text-center text-xl text-white" />
310
-
311
- <!-- ALTERNATIVE: View + Label (more verbose) -->
312
- <View class="bg-brand-500 h-12 w-12 rounded-full">
313
- <Label class="center fas fa-plus text-xl text-white" />
128
+ <Label class="mb-2 text-sm font-medium text-gray-700" text="Email Address" />
129
+ <TextField class="w-screen rounded-lg border-(1) border-red-500 bg-white px-4 py-3 text-base text-gray-800" hintText="Invalid email" />
130
+ <Label class="mt-1 text-xs text-red-500" text="Please enter a valid email address." />
314
131
  </View>
315
132
  ```
316
133
 
317
- :::tip SINGLE-LABEL ICON BUTTONS
318
- For circular icon buttons, you can use a single `Label` with:
319
- - `rounded-full-XX` (includes size) - Creates the circle and sets dimensions
320
- - Font Awesome icon class (e.g., `fa-solid fa-plus`)
321
- - `text-center` - Centers the icon
322
- - Background color and text color
134
+ > **⚠️ Input Padding**
135
+ > Padding utilities (`p-`, `px-`, `py-`) work on `TextField` and `TextArea`, but NOT on `Button` (especially iOS/Mac) and NOT on container views (`View`, `Window`, `ScrollView`, `TableView`). Use margins on children to simulate internal spacing on containers.
323
136
 
324
- This eliminates the need for a wrapper `View`, reducing DOM depth.
325
- :::
137
+ ## Buttons
326
138
 
327
- #### Floating Action Button (FAB)
139
+ ### Primary Button
328
140
 
329
141
  ```xml
330
- <!-- SIMPLIFIED: Single Label with positioning -->
331
- <Label class="rounded-full-14 bg-brand-500 fa-solid fa-plus absolute bottom-6 right-6 text-center text-2xl text-white shadow-lg" />
332
-
333
- <!-- ALTERNATIVE: View wrapper approach -->
334
- <View class="absolute bottom-6 right-6">
335
- <View class="bg-brand-500 h-14 w-14 rounded-full shadow-lg">
336
- <Label class="center fas fa-plus text-2xl text-white" />
337
- </View>
338
- </View>
142
+ <Button class="rounded-lg bg-blue-500 text-base font-semibold text-white" title="Save Changes" />
339
143
  ```
340
144
 
341
- #### Button with Icon
145
+ ### Secondary Button
342
146
 
343
147
  ```xml
344
- <View class="horizontal bg-brand-500 rounded-lg px-6 py-3 shadow-md">
345
- <Label class="fas fa-arrow-left mr-2 text-lg text-white" />
346
- <Label class="text-base font-semibold text-white" text="Back" />
347
- </View>
148
+ <Button class="rounded-lg bg-gray-200 text-base font-semibold text-gray-800" title="Cancel" />
348
149
  ```
349
150
 
350
- #### Button Group
151
+ ### Outline Button
351
152
 
352
153
  ```xml
353
- <View class="horizontal rounded-lg bg-gray-200">
354
- <View class="w-1/3 rounded-md bg-white py-2 shadow-sm">
355
- <Label class="text-center text-sm font-semibold text-gray-800" text="Day" />
356
- </View>
357
- <View class="w-1/3 py-2">
358
- <Label class="text-center text-sm font-medium text-gray-500" text="Week" />
359
- </View>
360
- <View class="w-1/3 py-2">
361
- <Label class="text-center text-sm font-medium text-gray-500" text="Month" />
362
- </View>
363
- </View>
154
+ <Button class="rounded-lg border-(1) border-blue-500 text-base font-semibold text-blue-500" title="Learn More" />
364
155
  ```
365
156
 
366
- #### Button Sizes
157
+ ### Icon Button
367
158
 
368
159
  ```xml
369
- <!-- Small -->
370
- <Button class="bg-brand-500 rounded px-4 py-2 text-sm font-semibold text-white" title="Small" />
371
-
372
- <!-- Medium (Default) -->
373
- <Button class="bg-brand-500 rounded-lg px-6 py-3 text-base font-semibold text-white" title="Medium" />
374
-
375
- <!-- Large -->
376
- <Button class="bg-brand-500 rounded-xl px-8 py-4 text-lg font-semibold text-white" title="Large" />
160
+ <Button class="rounded-lg bg-blue-500 text-white" title="Save" />
161
+ <Label class="fas fa-save ml-2 text-white" />
377
162
  ```
378
163
 
379
- ### Navigation Bars
380
-
381
- Navigation bars provide hierarchy and navigation context.
164
+ ## Navigation Patterns
382
165
 
383
- #### Top Navigation Bar with Title
166
+ ### Top Bar with Title and Action
384
167
 
385
168
  ```xml
386
- <View class="horizontal h-14 border-b border-gray-200 bg-white">
387
- <Label class="fas fa-arrow-left ml-4 text-xl text-gray-600" />
388
- <Label class="w-screen text-center text-lg font-semibold text-gray-800" text="Screen Title" />
389
- <Label class="fas fa-ellipsis-v mr-4 text-xl text-gray-600" />
169
+ <View class="h-14 w-screen bg-white border-b border-gray-200">
170
+ <Label class="left-4 center text-lg font-bold text-gray-800" text="Dashboard" />
171
+ <Label class="right-4 center fas fa-bars text-gray-700" />
390
172
  </View>
391
173
  ```
392
174
 
393
- #### Navigation Bar with Actions
175
+ ### Bottom Tab Bar
394
176
 
395
177
  ```xml
396
- <View class="bg-brand-500 horizontal h-14">
397
- <Label class="fas fa-bars ml-4 text-xl text-white" />
398
- <Label class="w-screen text-center text-lg font-semibold text-white" text="Dashboard" />
399
- <View class="horizontal mr-4">
400
- <Label class="fas fa-search mr-4 text-xl text-white" />
401
- <Label class="fas fa-bell text-xl text-white" />
402
- </View>
403
- </View>
404
- ```
405
-
406
- #### Tab Bar (Bottom)
407
-
408
- ```xml
409
- <View class="horizontal h-16 border-t border-gray-200 bg-white">
178
+ <View class="bottom-0 h-16 w-screen bg-white border-t border-gray-200 horizontal">
410
179
  <View class="vertical w-1/3">
411
- <Label class="fas fa-home text-brand-500 mx-auto mb-1 text-xl" />
412
- <Label class="text-brand-500 text-center text-xs font-medium" text="Home" />
180
+ <Label class="mx-auto mt-2 fas fa-home text-blue-500" />
181
+ <Label class="mx-auto mt-1 text-xs text-blue-500" text="Home" />
413
182
  </View>
183
+
414
184
  <View class="vertical w-1/3">
415
- <Label class="fas fa-search mx-auto mb-1 text-xl text-gray-400" />
416
- <Label class="text-center text-xs text-gray-400" text="Search" />
185
+ <Label class="mx-auto mt-2 fas fa-search text-gray-400" />
186
+ <Label class="mx-auto mt-1 text-xs text-gray-400" text="Search" />
417
187
  </View>
188
+
418
189
  <View class="vertical w-1/3">
419
- <Label class="fas fa-user mx-auto mb-1 text-xl text-gray-400" />
420
- <Label class="text-center text-xs text-gray-400" text="Profile" />
190
+ <Label class="mx-auto mt-2 fas fa-user text-gray-400" />
191
+ <Label class="mx-auto mt-1 text-xs text-gray-400" text="Profile" />
421
192
  </View>
422
193
  </View>
423
194
  ```
424
195
 
425
- #### Segment Control
426
-
427
- ```xml
428
- <View class="horizontal mx-4 my-4 rounded-lg bg-gray-200">
429
- <View id="segment1" class="w-1/2 rounded-md bg-white py-2 shadow-sm">
430
- <Label class="text-center text-sm font-semibold text-gray-800" text="Active" />
431
- </View>
432
- <View id="segment2" class="w-1/2 py-2">
433
- <Label class="text-center text-sm font-medium text-gray-500" text="Inactive" />
434
- </View>
435
- </View>
436
- ```
196
+ ## Modals, Sheets, and Feedback
437
197
 
438
- #### Breadcrumb Navigation
198
+ ### Full-Screen Overlay
439
199
 
440
200
  ```xml
441
- <View class="horizontal bg-gray-50">
442
- <Label class="text-brand-500 text-sm" text="Home" />
443
- <Label class="fas fa-chevron-right mx-2 my-3 text-xs text-gray-400" />
444
- <Label class="text-brand-500 text-sm" text="Products" />
445
- <Label class="fas fa-chevron-right mx-2 my-3 text-xs text-gray-400" />
446
- <Label class="my-3 text-sm font-medium text-gray-800" text="Category" />
447
- </View>
448
- ```
449
-
450
- ### Modals and Dialogs
451
-
452
- Modals focus user attention on specific content or actions.
453
-
454
- #### Alert Dialog
201
+ <View class="h-screen w-screen bg-(#88000000)">
202
+ <View class="mx-6 mt-24 rounded-xl bg-white shadow-lg">
203
+ <Label class="mx-4 mt-4 text-lg font-bold text-gray-800" text="Confirm Action" />
204
+ <Label class="mx-4 mt-2 text-sm text-gray-600" text="Are you sure you want to continue?" />
455
205
 
456
- ```javascript
457
- const dialog = Ti.UI.createAlertDialog({
458
- cancel: 0,
459
- title: 'Delete Item',
460
- buttonNames: ['Cancel', 'Delete'],
461
- message: 'Are you sure you want to delete this item? This action cannot be undone.'
462
- })
463
-
464
- dialog.addEventListener('click', (e) => {
465
- if (e.index === 1) {
466
- // Delete action
467
- }
468
- })
469
-
470
- dialog.show()
471
- ```
472
-
473
- #### Full Screen Modal (iOS)
474
-
475
- ```xml
476
- <!-- modal.xml -->
477
- <Window class="bg-white" modal="true">
478
- <View class="vertical h-full">
479
- <!-- Header -->
480
- <View class="horizontal border-b border-gray-200 bg-white">
481
- <Label id="closeBtn" class="text-brand-500 text-base font-semibold" text="Cancel" />
482
- <Label class="w-screen text-center text-lg font-semibold text-gray-800" text="Modal Title" />
483
- <Label id="saveBtn" class="text-brand-500 text-base font-semibold" text="Save" />
206
+ <View class="horizontal mx-4 mt-4 mb-4">
207
+ <Button class="rounded-lg bg-gray-200 text-gray-700" title="Cancel" />
208
+ <Button class="ml-2 rounded-lg bg-red-500 text-white" title="Delete" />
484
209
  </View>
485
-
486
- <!-- Content -->
487
- <ScrollView class="h-full">
488
- <View>
489
- <Label class="mx-4 my-4 text-base text-gray-800" text="Modal content goes here..." />
490
- </View>
491
- </ScrollView>
492
210
  </View>
493
- </Window>
494
- ```
495
-
496
- ```javascript
497
- // Open modal
498
- const modal = Alloy.createController('modal').getView()
499
- modal.open({ modal: true })
211
+ </View>
500
212
  ```
501
213
 
502
- #### Bottom Sheet (Android-style)
214
+ ### Bottom Sheet
503
215
 
504
216
  ```xml
505
- <View class="absolute bottom-0 left-0 w-full rounded-t-xl bg-white shadow-2xl">
506
- <View class="mx-auto mb-4 mt-3 h-1 w-12 rounded-full bg-gray-300" />
507
- <View>
508
- <Label class="mx-4 mb-4 mt-4 text-lg font-semibold text-gray-800" text="Choose Action" />
509
- <View class="vertical">
510
- <View class="border-b border-gray-100">
511
- <Label class="mx-4 my-3 text-base text-gray-800" text="Action 1" />
512
- </View>
513
- <View class="border-b border-gray-100">
514
- <Label class="mx-4 my-3 text-base text-gray-800" text="Action 2" />
515
- </View>
516
- <View>
517
- <Label class="mx-4 my-3 text-base font-semibold text-red-500" text="Delete" />
518
- </View>
519
- </View>
217
+ <View class="bottom-0 w-screen rounded-t-xl bg-white shadow-lg">
218
+ <View class="mx-auto mt-2 h-1 w-10 rounded bg-gray-300" />
219
+ <Label class="mx-4 mt-4 text-lg font-bold text-gray-800" text="Share" />
220
+ <View class="vertical mx-4 mt-4 mb-4">
221
+ <Label class="text-base text-gray-700" text="Copy link" />
222
+ <Label class="mt-3 text-base text-gray-700" text="Send message" />
223
+ <Label class="mt-3 text-base text-gray-700" text="Open in browser" />
520
224
  </View>
521
225
  </View>
522
226
  ```
523
227
 
524
- ### Toasts and Snackbars
525
-
526
- Brief notifications that provide feedback.
527
-
528
- #### Simple Toast
529
-
530
- ```javascript
531
- // Native toast (Android only)
532
- var toast = Ti.UI.createNotification({
533
- message: "Operation successful",
534
- duration: Ti.UI.NOTIFICATION_DURATION_SHORT
535
- })
536
- toast.show()
537
- ```
538
-
539
- #### Custom Snackbar
228
+ ### Snackbar
540
229
 
541
230
  ```xml
542
- <View id="snackbar" class="absolute bottom-4 left-4 right-4 hidden rounded-lg bg-gray-800 shadow-lg">
231
+ <View id="snackbar" class="bottom-4 left-4 right-4 hidden rounded-lg bg-gray-800 shadow-lg">
543
232
  <View class="horizontal">
544
- <Label class="w-screen text-base text-white" text="File deleted successfully" />
545
- <Label id="undoBtn" class="text-brand-400 text-base font-semibold" text="UNDO" />
233
+ <Label class="mx-4 my-4 h-auto text-base text-white" text="File deleted successfully" />
234
+ <Label id="undoBtn" class="my-4 mr-4 h-auto text-base font-semibold text-blue-400" text="UNDO" />
546
235
  </View>
547
236
  </View>
548
237
  ```
549
238
 
550
- ```javascript
551
- // Show snackbar
552
- $.snackbar.setVisible(true)
553
- setTimeout(() => {
554
- $.snackbar.setVisible(false)
555
- }, 3000)
556
- ```
239
+ ## Layout Patterns
557
240
 
558
- #### Success Toast
559
-
560
- ```xml
561
- <View class="horizontal absolute left-4 right-4 top-4 rounded-lg bg-green-500 shadow-lg">
562
- <Label class="fas fa-check-circle mr-3 text-xl text-white" />
563
- <Label class="text-base font-medium text-white" text="Changes saved successfully!" />
564
- </View>
565
- ```
566
-
567
- #### Error Toast
568
-
569
- ```xml
570
- <View class="horizontal absolute left-4 right-4 top-4 rounded-lg bg-red-500 shadow-lg">
571
- <Label class="fas fa-exclamation-circle mr-3 text-xl text-white" />
572
- <Label class="text-base font-medium text-white" text="An error occurred. Please try again." />
573
- </View>
574
- ```
575
-
576
- ---
577
-
578
- ## 2. Layout Patterns
579
-
580
- ### Screen Structure
581
-
582
- #### Standard Screen Layout
241
+ ### Standard Screen Layout
583
242
 
584
243
  ```xml
585
244
  <Window class="bg-gray-100">
586
- <ScrollView class="h-full w-full">
587
- <!-- Header -->
588
- <View class="border-b border-gray-200 bg-white">
589
- <Label class="mx-4 my-4 text-2xl font-bold text-gray-800" text="Screen Title" />
590
- </View>
591
-
592
- <!-- Content -->
593
- <View>
594
- <!-- Main content goes here -->
245
+ <View class="vertical h-screen w-screen">
246
+ <View class="h-14 w-screen border-b border-gray-200 bg-white">
247
+ <Label class="left-4 center text-xl font-bold text-gray-800" text="Screen Title" />
595
248
  </View>
596
249
 
597
- <!-- Footer -->
598
- <View class="border-t border-gray-200 bg-white">
599
- <Label class="text-center text-sm text-gray-500" text="Footer content" />
600
- </View>
601
- </ScrollView>
602
- </Window>
603
- ```
604
-
605
- #### Tab Bar Screen Structure
606
-
607
- ```xml
608
- <TabGroup>
609
- <!-- Tab 1 -->
610
- <Tab>
611
- <Window class="bg-gray-100">
612
- <ScrollView class="h-full w-full">
613
- <Label class="mb-4 text-lg font-semibold text-gray-800" text="Home" />
614
- <!-- Content -->
615
- </ScrollView>
616
- </Window>
617
- </Tab>
618
-
619
- <!-- Tab 2 -->
620
- <Tab>
621
- <Window class="bg-gray-100">
622
- <ScrollView class="h-full w-full">
623
- <Label class="mb-4 text-lg font-semibold text-gray-800" text="Search" />
624
- <!-- Content -->
625
- </ScrollView>
626
- </Window>
627
- </Tab>
628
-
629
- <!-- Tab 3 -->
630
- <Tab>
631
- <Window class="bg-gray-100">
632
- <ScrollView class="h-full w-full">
633
- <Label class="mb-4 text-lg font-semibold text-gray-800" text="Profile" />
634
- <!-- Content -->
635
- </ScrollView>
636
- </Window>
637
- </Tab>
638
- </TabGroup>
639
- ```
640
-
641
- ### Spacing System
642
-
643
- PurgeTSS uses a consistent spacing scale based on 4px increments:
644
-
645
- | Class | Spacing | Usage |
646
- | ----- | ------- | ----------- |
647
- | `p-0` | 0px | No padding |
648
- | `p-1` | 4px | Extra small |
649
- | `p-2` | 8px | Small |
650
- | `p-3` | 12px | Medium |
651
- | `p-4` | 16px | Standard |
652
- | `p-5` | 20px | Large |
653
- | `p-6` | 24px | Extra large |
654
- | `p-8` | 32px | Double |
655
-
656
- **Note:** Padding classes (`p-*`) work on some elements like TextField, TextArea, Button, and Label, but do NOT work on View. For View spacing, use margin classes on child elements instead.
657
-
658
- #### Margin Examples
659
-
660
- ```xml
661
- <!-- All sides -->
662
- <View class="m-4">...</View>
663
-
664
- <!-- Horizontal -->
665
- <View class="mx-4">...</View>
666
-
667
- <!-- Vertical -->
668
- <View class="my-4">...</View>
669
-
670
- <!-- Individual sides -->
671
- <View class="mb-4 ml-2 mr-4 mt-2">...</View>
672
- ```
673
-
674
- #### Padding Examples
675
-
676
- ```xml
677
- <!-- All sides (works on TextField, TextArea, Button, Label) -->
678
- <TextField class="p-4" hintText="Input with padding" />
679
-
680
- <!-- Horizontal (works on TextField, TextArea, Button, Label) -->
681
- <TextField class="px-4" hintText="Input with horizontal padding" />
682
-
683
- <!-- Vertical (works on TextField, TextArea, Button, Label) -->
684
- <TextField class="py-4" hintText="Input with vertical padding" />
685
-
686
- <!-- Individual sides (works on TextField, TextArea, Button, Label) -->
687
- <TextField class="pb-4 pl-2 pr-4 pt-2" hintText="Input with individual padding" />
688
- ```
689
-
690
- #### Gap (Spacing between children)
691
-
692
- ```xml
693
- <View class="gap-2"> <!-- 8px between all children -->
694
- <View class="h-10 bg-red-500" />
695
- <View class="h-10 bg-blue-500" />
696
- <View class="h-10 bg-green-500" />
697
- </View>
698
- ```
699
-
700
- ### Responsive Patterns
701
-
702
- #### Responsive Grid
703
-
704
- ```xml
705
- <!-- Two columns on large screens, one column on small -->
706
- <View class="grid">
707
- <View class="col-span-6 md:col-span-12">
708
- <Label text="Responsive Item" />
250
+ <ScrollView class="h-screen w-screen">
251
+ <View class="vertical">
252
+ <Label class="mx-4 mt-4 text-base text-gray-700" text="Main content goes here." />
253
+ </View>
254
+ </ScrollView>
709
255
  </View>
710
- </View>
256
+ </Window>
711
257
  ```
712
258
 
713
- #### Adaptive Layout (Tablet vs Phone)
259
+ ### Two-Column Tablet Layout
714
260
 
715
261
  ```xml
716
- <!-- Use platform modifiers for adaptive layouts -->
717
- <View class="horizontal">
718
- <!-- Sidebar on tablets, full width on phones -->
719
- <View class="w-1/4 md:w-full">
720
- <Label text="Sidebar" />
262
+ <View class="horizontal w-screen">
263
+ <View class="tablet:w-(30%) handheld:w-screen bg-white">
264
+ <Label class="mx-4 my-4 text-base font-semibold text-gray-800" text="Sidebar" />
721
265
  </View>
722
266
 
723
- <!-- Main content -->
724
- <View class="w-3/4 md:w-full">
725
- <Label text="Main Content" />
267
+ <View class="tablet:w-(70%) handheld:w-screen bg-gray-50">
268
+ <Label class="mx-4 my-4 text-base text-gray-700" text="Main content" />
726
269
  </View>
727
270
  </View>
728
271
  ```
729
272
 
730
- #### Percentage-Based Widths
731
-
732
- ```xml
733
- <!-- Half width -->
734
- <View class="w-(50%)">...</View>
735
-
736
- <!-- One-third width -->
737
- <View class="w-(33.33%)">...</View>
738
-
739
- <!-- Custom percentage -->
740
- <View class="w-(75%)">...</View>
741
- ```
742
-
743
- ---
744
-
745
- ## 3. Typography
746
-
747
- ### Font Scales
748
-
749
- PurgeTSS provides consistent font size utilities:
750
-
751
- | Class | Size | Usage |
752
- | ----------- | ---- | ------------------- |
753
- | `text-xs` | 12px | Captions, labels |
754
- | `text-sm` | 14px | Secondary text |
755
- | `text-base` | 16px | Body text (default) |
756
- | `text-lg` | 18px | Subheadings |
757
- | `text-xl` | 20px | Headings |
758
- | `text-2xl` | 24px | Large headings |
759
- | `text-3xl` | 30px | Display headings |
760
- | `text-4xl` | 36px | Hero text |
761
-
762
- #### Typography Examples
763
-
764
- ```xml
765
- <!-- Display heading -->
766
- <Label class="text-4xl font-bold text-gray-900" text="Hero Title" />
767
-
768
- <!-- Page heading -->
769
- <Label class="text-2xl font-bold text-gray-800" text="Page Title" />
770
-
771
- <!-- Section heading -->
772
- <Label class="text-xl font-semibold text-gray-800" text="Section Title" />
773
-
774
- <!-- Body text -->
775
- <Label class="text-base text-gray-600" text="Regular body text content" />
776
-
777
- <!-- Caption -->
778
- <Label class="text-xs text-gray-500" text="Caption text" />
779
- ```
780
-
781
- ### Font Weights
782
-
783
- ```xml
784
- <Label class="font-light" text="Light weight (300)" />
785
- <Label class="font-normal" text="Normal weight (400)" />
786
- <Label class="font-medium" text="Medium weight (500)" />
787
- <Label class="font-semibold" text="Semibold weight (600)" />
788
- <Label class="font-bold" text="Bold weight (700)" />
789
- ```
790
-
791
- ### Text Alignment and Truncation
792
-
793
- #### Text Alignment
794
-
795
- ```xml
796
- <Label class="text-left" text="Left aligned" />
797
- <Label class="text-center" text="Center aligned" />
798
- <Label class="text-right" text="Right aligned" />
799
- ```
800
-
801
- #### Text Truncation
273
+ ### Percentage Layout
802
274
 
803
275
  ```xml
804
- <!-- Single line truncation -->
805
- <Label class="truncate" text="Very long text that will be truncated with ellipsis..." />
806
-
807
- <!-- Multi-line truncation -->
808
- <Label class="line-clamp-2" text="Long text that will truncate after 2 lines with ellipsis..." />
809
- <Label class="line-clamp-3" text="Long text that will truncate after 3 lines with ellipsis..." />
810
- ```
811
-
812
- #### Text Transformations
813
-
814
- ```xml
815
- <Label class="uppercase" text="uppercase text" />
816
- <Label class="lowercase" text="LOWERCASE TEXT" />
817
- <Label class="capitalize" text="capitalize each word" />
818
- ```
819
-
820
- ---
821
-
822
- ## 4. Colors and Themes
823
-
824
- ### Semantic Color Naming
825
-
826
- Use semantic color names for better maintainability:
827
-
828
- #### Primary Colors
829
-
830
- ```xml
831
- <!-- Brand colors -->
832
- <View class="bg-brand-500">...</View>
833
- <View class="bg-brand-600">...</View>
834
- <View class="bg-brand-700">...</View>
835
-
836
- <!-- Gray scale -->
837
- <View class="bg-gray-50">...</View>
838
- <View class="bg-gray-100">...</View>
839
- <View class="bg-gray-200">...</View>
840
- <View class="bg-gray-300">...</View>
841
- <View class="bg-gray-400">...</View>
842
- <View class="bg-gray-500">...</View>
843
- <View class="bg-gray-600">...</View>
844
- <View class="bg-gray-700">...</View>
845
- <View class="bg-gray-800">...</View>
846
- <View class="bg-gray-900">...</View>
847
- ```
848
-
849
- #### Semantic Colors
850
-
851
- ```xml
852
- <!-- Success -->
853
- <View class="bg-green-500">...</View>
854
- <Label class="text-green-500" text="Success message" />
855
-
856
- <!-- Warning -->
857
- <View class="bg-yellow-500">...</View>
858
- <Label class="text-yellow-500" text="Warning message" />
859
-
860
- <!-- Error -->
861
- <View class="bg-red-500">...</View>
862
- <Label class="text-red-500" text="Error message" />
863
-
864
- <!-- Info -->
865
- <View class="bg-blue-500">...</View>
866
- <Label class="text-blue-500" text="Info message" />
867
- ```
868
-
869
- ### Dark Mode Considerations
870
-
871
- Use semantic color names that adapt to theme:
872
-
873
- ```xml
874
- <!-- Adaptive background -->
875
- <View class="bg-white dark:bg-gray-900">...</View>
876
-
877
- <!-- Adaptive text -->
878
- <Label class="text-gray-800 dark:text-gray-100" text="Adaptive text" />
879
-
880
- <!-- Adaptive borders -->
881
- <View class="border-gray-200 dark:border-gray-700">...</View>
882
- ```
883
-
884
- ### Platform-Specific Colors
885
-
886
- #### iOS System Colors
887
-
888
- ```xml
889
- <!-- iOS blue -->
890
- <Button class="bg-ios-blue text-white" title="iOS Button" />
891
-
892
- <!-- iOS system background -->
893
- <Window class="bg-ios-system-background">
894
- <View class="bg-ios-secondary-system-background">
895
- <Label class="text-ios-label" text="iOS Text" />
276
+ <View class="horizontal w-screen">
277
+ <View class="w-(48%) mr-2 rounded-lg bg-blue-100">
278
+ <Label class="mx-4 my-4 text-blue-700" text="Left panel" />
896
279
  </View>
897
- </Window>
898
- ```
899
-
900
- #### Material Design Colors
901
-
902
- ```xml
903
- <!-- Material primary -->
904
- <Button class="bg-material-primary text-white" title="Material Button" />
905
280
 
906
- <!-- Material surface -->
907
- <View class="bg-material-surface">
908
- <Label class="text-material-on-surface" text="Material Text" />
281
+ <View class="w-(48%) ml-2 rounded-lg bg-green-100">
282
+ <Label class="mx-4 my-4 text-green-700" text="Right panel" />
283
+ </View>
909
284
  </View>
910
285
  ```
911
286
 
912
- ---
913
-
914
- ## 5. Icons
915
-
916
- ### Font Awesome 7 Icon Fonts
917
-
918
- Font Awesome 7 uses style prefixes for different icon sets:
919
-
920
- ```xml
921
- <!-- Solid icons (free) -->
922
- <Label class="fas fa-home" />
923
- <Label class="fas fa-user" />
924
- <Label class="fas fa-envelope" />
925
-
926
- <!-- Regular icons (free) -->
927
- <Label class="far fa-heart" />
928
- <Label class="far fa-star" />
929
- <Label class="far fa-bookmark" />
930
-
931
- <!-- Brand icons (free) -->
932
- <Label class="fab fa-twitter" />
933
- <Label class="fab fa-facebook" />
934
- <Label class="fab fa-github" />
935
-
936
- <!-- Pro-only styles (require Font Awesome Pro) -->
937
- <Label class="fal fa-camera" /> <!-- Light -->
938
- <Label class="fass fa-star" /> <!-- Sharp Solid -->
939
- ```
940
-
941
- ### Icon Sizing and Alignment
287
+ ## Typography and Icons
942
288
 
943
- #### Icon Sizes
944
-
945
- ```xml
946
- <Label class="fas fa-home text-xs" /> <!-- 12px -->
947
- <Label class="fas fa-home text-sm" /> <!-- 14px -->
948
- <Label class="fas fa-home text-base" /> <!-- 16px -->
949
- <Label class="fas fa-home text-lg" /> <!-- 18px -->
950
- <Label class="fas fa-home text-xl" /> <!-- 20px -->
951
- <Label class="fas fa-home text-2xl" /> <!-- 24px -->
952
- <Label class="fas fa-home text-3xl" /> <!-- 30px -->
953
- <Label class="fas fa-home text-4xl" /> <!-- 36px -->
954
- ```
955
-
956
- #### Icon Colors
957
-
958
- ```xml
959
- <Label class="fas fa-home text-gray-500" />
960
- <Label class="fas fa-home text-brand-500" />
961
- <Label class="fas fa-home text-(#FF5733)" /> <!-- Arbitrary color -->
962
- ```
289
+ ### Typography Scale
963
290
 
964
- ### Icon with Text Patterns
291
+ - `text-xs`: 12px
292
+ - `text-sm`: 14px
293
+ - `text-base`: 16px
294
+ - `text-lg`: 18px
295
+ - `text-xl`: 20px
296
+ - `text-2xl`: 24px
297
+ - `text-3xl`: 30px
965
298
 
966
- #### Icon with Label
299
+ ### Icon Pattern
967
300
 
968
301
  ```xml
969
302
  <View class="horizontal">
@@ -972,905 +305,41 @@ Font Awesome 7 uses style prefixes for different icon sets:
972
305
  </View>
973
306
  ```
974
307
 
975
- #### Circular Icon Button
308
+ ## Accessibility
976
309
 
977
- ```xml
978
- <!-- EFFICIENT: Single Label approach -->
979
- <Label class="rounded-full-12 bg-brand-500 fa-solid fa-plus text-center text-xl text-white" />
980
-
981
- <!-- ALTERNATIVE: View wrapper (more verbose) -->
982
- <View class="bg-brand-500 h-12 w-12 rounded-full">
983
- <Label class="center fas fa-plus text-xl text-white" />
984
- </View>
985
- ```
310
+ - Keep primary touch targets around `44x44` or larger.
311
+ - Pair icons with visible labels or `accessibilityLabel` values.
312
+ - Preserve contrast between text and background.
313
+ - Avoid using color alone for validation or state.
986
314
 
987
- #### Header with Icon Buttons
315
+ Example:
988
316
 
989
317
  ```xml
990
- <!-- Container with auto width - items will be centered -->
991
- <View class="horizontal mx-3 mt-3 w-auto">
992
- <!-- Icon buttons with horizontal spacing -->
993
- <Label id="backButton" class="rounded-full-12 fa-solid fa-arrow-left mx-1 bg-white/20 text-center text-xl text-white" />
994
- <Label id="shareButton" class="rounded-full-12 fa-solid fa-share-nodes mx-1 bg-white/20 text-center text-xl text-white" />
995
- <Label id="favoriteButton" class="rounded-full-12 fa-solid fa-heart mx-1 bg-white/20 text-center text-xl text-white" />
996
- </View>
997
-
998
- <!-- To shift all items to one side, add ml-xx or mr-xx to the container -->
999
- <View class="horizontal ml-0 mr-3 mt-3 w-auto">
1000
- <Label class="rounded-full-12 fa-solid fa-arrow-left ... mx-1 bg-white/20" />
1001
- <Label class="rounded-full-12 fa-solid fa-share-nodes ... mx-1 bg-white/20" />
1002
- </View>
318
+ <Button class="h-12 rounded-lg bg-blue-500 text-white" title="Continue" accessibilityLabel="Continue to next step" />
1003
319
  ```
1004
320
 
1005
- **Key pattern:**
1006
- - `horizontal w-auto` - Container takes width of children, centers them in available space
1007
- - `mx-1` on each child - Consistent horizontal spacing between icons
1008
- - `ml-0`/`mr-3` on container - Shifts the entire group to left/right edge
1009
-
1010
- #### Icon Badge
1011
-
1012
- ```xml
1013
- <View class="relative">
1014
- <Label class="fas fa-bell text-xl" />
1015
- <View class="absolute -right-1 -top-1 h-4 w-4 rounded-full bg-red-500">
1016
- <Label class="center text-xs font-bold text-white" text="3" />
1017
- </View>
1018
- </View>
1019
- ```
1020
-
1021
- #### Icon Group
1022
-
1023
- ```xml
1024
- <View class="horizontal">
1025
- <Label class="fab fa-twitter mr-4 text-2xl text-blue-400" />
1026
- <Label class="fab fa-facebook mr-4 text-2xl text-blue-600" />
1027
- <Label class="fab fa-instagram mr-4 text-2xl text-pink-500" />
1028
- <Label class="fab fa-github text-2xl text-gray-800" />
1029
- </View>
1030
- ```
1031
-
1032
- ---
1033
-
1034
- ## 6. Accessibility
1035
-
1036
- ### Accessibility Labels
1037
-
1038
- All interactive elements should have accessibility labels:
1039
-
1040
- ```xml
1041
- <!-- Button with label -->
1042
- <Button class="bg-brand-500 text-white" title="Save" accessibilityLabel="Save changes" />
1043
-
1044
- <!-- Icon button with label (simplified) -->
1045
- <Label class="rounded-full-12 bg-brand-500 fa-solid fa-plus text-center text-white" accessibilityLabel="Add new item" />
1046
-
1047
- <!-- Image with label -->
1048
- <ImageView image="/images/avatar.jpg" accessibilityLabel="User avatar" />
1049
- ```
1050
-
1051
- ### Touch Target Sizes
1052
-
1053
- Ensure touch targets are at least 44dp for iOS and 48dp for Android:
1054
-
1055
- ```xml
1056
- <!-- Minimum touch target (44dp) -->
1057
- <Button class="min-w-44 min-h-44 bg-brand-500" title="Button" />
1058
-
1059
- <!-- Icon button with proper touch target (simplified) -->
1060
- <Label class="rounded-full-12 fa-solid fa-cog text-center text-xl" accessibilityLabel="Settings" />
1061
- ```
1062
-
1063
- ### Color Contrast
1064
-
1065
- Ensure sufficient color contrast for text:
1066
-
1067
- ```xml
1068
- <!-- Good contrast examples -->
1069
- <View class="bg-white">
1070
- <Label class="text-gray-900" text="Dark text on white background" />
1071
- </View>
1072
-
1073
- <View class="bg-gray-900">
1074
- <Label class="text-white" text="White text on dark background" />
1075
- </View>
1076
-
1077
- <View class="bg-brand-500">
1078
- <Label class="font-semibold text-white" text="White text on brand color" />
1079
- </View>
1080
- ```
1081
-
1082
- ### Screen Reader Support
1083
-
1084
- ```xml
1085
- <!-- Hide decorative elements -->
1086
- <View class="absolute right-0 top-0" accessibilityHidden="true">
1087
- <Label class="fas fa-star text-yellow-500" />
1088
- </View>
1089
-
1090
- <!-- Provide hints for complex controls -->
1091
- <Slider accessibilityLabel="Volume" accessibilityHint="Adjust the volume level" accessibilityValue="50 percent" />
1092
-
1093
- <!-- State changes -->
1094
- <Switch id="notificationSwitch" accessibilityLabel="Enable notifications" />
1095
- ```
1096
-
1097
- ```javascript
1098
- // Update accessibility value on state change
1099
- $.notificationSwitch.addEventListener('change', (e) => {
1100
- $.notificationSwitch.accessibilityValue = e.value ? 'On' : 'Off'
1101
- })
1102
- ```
1103
-
1104
- ---
1105
-
1106
- ## 7. Performance Best Practices
1107
-
1108
- ### ListView Performance
1109
-
1110
- **CRITICAL**: Never use `Ti.UI.SIZE` in ListView templates - causes jerky scrolling.
1111
-
1112
- ```xml
1113
- <!-- BAD - Causes performance issues -->
1114
- <ItemTemplate name="bad">
1115
- <Label bindId="title" height="Ti.UI.SIZE" />
1116
- </ItemTemplate>
1117
-
1118
- <!-- GOOD - Use fixed heights -->
1119
- <ItemTemplate name="good">
1120
- <Label bindId="title" height="40" />
1121
- </ItemTemplate>
1122
- ```
1123
-
1124
- ### View Recycling
1125
-
1126
- ListViews recycle views. Always update via data, not direct access:
1127
-
1128
- ```javascript
1129
- // BAD - Direct modification
1130
- function handleClick(e) {
1131
- e.source.text = "Updated"
1132
- }
1133
-
1134
- // GOOD - Update via data
1135
- function handleClick(e) {
1136
- const item = e.section.getItemAt(e.itemIndex)
1137
- item.title.text = "Updated"
1138
- e.section.updateItemAt(e.itemIndex, item)
1139
- }
1140
- ```
1141
-
1142
- ### Batch Updates
1143
-
1144
- Use `applyProperties` to reduce bridge crossings:
1145
-
1146
- ```javascript
1147
- // BAD - Multiple property updates
1148
- view.backgroundColor = 'red'
1149
- view.width = 100
1150
- view.height = 50
1151
-
1152
- // GOOD - Single batch update
1153
- view.applyProperties({
1154
- backgroundColor: 'red',
1155
- width: 100,
1156
- height: 50
1157
- })
1158
- ```
1159
-
1160
- ### Minimize Template Count
1161
-
1162
- Fewer templates = better native cell reuse:
1163
-
1164
- ```xml
1165
- <!-- GOOD - One flexible template -->
1166
- <ItemTemplate name="flexible">
1167
- <ImageView bindId="icon" />
1168
- <Label bindId="title" />
1169
- <Label bindId="subtitle" /> <!-- Hidden if not needed -->
1170
- </ItemTemplate>
1171
-
1172
- <!-- BAD - Multiple similar templates -->
1173
- <ItemTemplate name="withIcon">...</ItemTemplate>
1174
- <ItemTemplate name="withoutIcon">...</ItemTemplate>
1175
- <ItemTemplate name="withSubtitle">...</ItemTemplate>
1176
- ```
1177
-
1178
- ---
1179
-
1180
- ## 8. Platform-Specific Patterns
1181
-
1182
- ### iOS Patterns
1183
-
1184
- #### Navigation Window
1185
-
1186
- ```xml
1187
- <NavigationWindow id="navWindow">
1188
- <Window class="bg-white">
1189
- <View>
1190
- <Label class="text-lg font-semibold" text="Main Screen" />
1191
- <Button id="pushBtn" class="mt-4" title="Push Next Screen" />
1192
- </View>
1193
- </Window>
1194
- </NavigationWindow>
1195
- ```
1196
-
1197
- ```javascript
1198
- // Push new window
1199
- $.pushBtn.addEventListener('click', () => {
1200
- const nextWin = Ti.UI.createWindow({
1201
- title: 'Next Screen',
1202
- backgroundColor: 'white'
1203
- })
1204
- $.navWindow.openWindow(nextWin, { animated: true })
1205
- })
1206
- ```
1207
-
1208
- #### Tab Bar
1209
-
1210
- ```xml
1211
- <TabGroup id="tabGroup">
1212
- <Tab id="homeTab" icon="fa-home.png" title="Home">
1213
- <Window class="bg-white">
1214
- <ScrollView class="h-full w-full">
1215
- <Label class="text-lg font-semibold" text="Home Screen" />
1216
- </ScrollView>
1217
- </Window>
1218
- </Tab>
1219
-
1220
- <Tab id="searchTab" icon="fa-search.png" title="Search">
1221
- <Window class="bg-white">
1222
- <ScrollView class="h-full w-full">
1223
- <Label class="text-lg font-semibold" text="Search Screen" />
1224
- </ScrollView>
1225
- </Window>
1226
- </Tab>
1227
-
1228
- <Tab id="profileTab" icon="fa-user.png" title="Profile">
1229
- <Window class="bg-white">
1230
- <ScrollView class="h-full w-full">
1231
- <Label class="text-lg font-semibold" text="Profile Screen" />
1232
- </ScrollView>
1233
- </Window>
1234
- </Tab>
1235
- </TabGroup>
1236
- ```
1237
-
1238
- #### iOS Swipe Actions
1239
-
1240
- ```javascript
1241
- const section = $.myList.sections[0]
1242
-
1243
- // Define edit actions
1244
- const deleteAction = Ti.UI.iOS.createListViewDeleteOptions({
1245
- title: 'Delete'
1246
- })
1247
-
1248
- const moreAction = Ti.UI.iOS.createListViewEditAction({
1249
- title: 'More',
1250
- backgroundColor: 'blue',
1251
- style: Ti.UI.iOS.LIST_VIEW_EDIT_ACTION_STYLE_NORMAL
1252
- })
1253
-
1254
- // Enable editing
1255
- section.editActions = [deleteAction, moreAction]
1256
- section.canEdit = true
1257
-
1258
- // Handle actions
1259
- $.myList.addEventListener('editaction', (e) => {
1260
- if (e.action === deleteAction) {
1261
- section.deleteItemsAt(e.itemIndex, 1)
1262
- } else if (e.action === moreAction) {
1263
- // Handle more action
1264
- }
1265
- })
1266
- ```
1267
-
1268
- ### Android Patterns
1269
-
1270
- #### Action Bar
1271
-
1272
- ```javascript
1273
- const activity = Ti.Android.currentActivity
1274
-
1275
- activity.onCreateOptionsMenu = (e) => {
1276
- const menu = e.menu
1277
-
1278
- const searchItem = menu.add({
1279
- title: 'Search',
1280
- icon: Ti.Android.R.drawable.ic_menu_search,
1281
- showAsAction: Ti.Android.SHOW_AS_ACTION_IF_ROOM
1282
- })
1283
-
1284
- const settingsItem = menu.add({
1285
- title: 'Settings',
1286
- icon: Ti.Android.R.drawable.ic_menu_preferences,
1287
- showAsAction: Ti.Android.SHOW_AS_ACTION_IF_ROOM
1288
- })
1289
- }
1290
-
1291
- activity.onOptionsItemSelected = (e) => {
1292
- switch (e.itemId) {
1293
- case 0:
1294
- // Handle search
1295
- return true
1296
- case 1:
1297
- // Handle settings
1298
- return true
1299
- }
1300
- return false
1301
- }
1302
- ```
1303
-
1304
- #### Back Button Handling
1305
-
1306
- ```javascript
1307
- $.window.addEventListener('androidback', (e) => {
1308
- e.cancelBubble = true
1309
-
1310
- if (canGoBack()) {
1311
- closeCurrentWindow()
1312
- } else {
1313
- showExitConfirmation()
1314
- }
1315
- })
1316
- ```
1317
-
1318
- #### Material Design Theme
1319
-
1320
- ```xml
1321
- <!-- tiapp.xml -->
1322
- <android xmlns:android="http://schemas.android.com/apk/res/android">
1323
- <manifest>
1324
- <application android:theme="@style/Theme.Titanium.Material3.DayNight"/>
1325
- </manifest>
1326
- </android>
1327
- ```
1328
-
1329
- #### Notifications
1330
-
1331
- ```javascript
1332
- // Create notification channel (Android 8.0+)
1333
- const channel = Ti.Android.createNotificationChannel({
1334
- name: 'My Channel',
1335
- id: 'my_channel_id',
1336
- importance: Ti.Android.NOTIFICATION_IMPORTANCE_HIGH
1337
- })
1338
-
1339
- Ti.Android.NotificationManager.createNotificationChannel(channel)
1340
-
1341
- // Create and show notification
1342
- const notification = Ti.Android.createNotification({
1343
- number: 1,
1344
- channelId: 'my_channel_id',
1345
- contentTitle: 'New Message',
1346
- contentText: 'You have a new message'
1347
- })
1348
-
1349
- Ti.Android.NotificationManager.notify(1, notification)
1350
- ```
1351
-
1352
- ---
1353
-
1354
- ## 8. Complete UI Patterns with Controllers
1355
-
1356
- These patterns demonstrate real-world UI implementations with both XML views and their corresponding controller JavaScript code.
1357
-
1358
- ### Loading State Pattern (Skeleton)
1359
-
1360
- Show skeleton screens while loading data, then transition to content or error states.
1361
-
1362
- ```xml
1363
- <View id="loadingState" class="wh-screen vertical">
1364
- <View class="mx-4 mt-4 h-20 w-screen animate-pulse rounded-lg bg-gray-200" />
1365
- <View class="mx-4 mt-4 h-4 w-8/12 animate-pulse rounded bg-gray-200" />
1366
- <View class="mx-4 mt-2 h-4 w-6/12 animate-pulse rounded bg-gray-200" />
1367
- </View>
1368
-
1369
- <View id="contentState" class="wh-screen hidden">
1370
- <!-- Actual content goes here -->
1371
- <Label class="mx-4 my-4 text-lg font-semibold text-gray-800" text="Content loaded!" />
1372
- </View>
1373
-
1374
- <View id="errorState" class="wh-screen vertical hidden">
1375
- <Label class="fa-solid fa-exclamation-circle mt-20 text-6xl text-gray-400" />
1376
- <Label class="mt-4 text-lg text-gray-500" text="L('error_loading')" />
1377
- <Button class="bg-primary mt-4 h-10 rounded-lg px-6 text-white" title="L('retry')" onClick="loadData" />
1378
- </View>
1379
- ```
1380
-
1381
- ```javascript
1382
- // Controller
1383
- function setState(state) {
1384
- const states = ['loadingState', 'contentState', 'errorState']
1385
- states.forEach(s => { $[s].visible = s === state })
1386
- }
1387
-
1388
- async function loadData() {
1389
- setState('loadingState')
1390
- try {
1391
- const data = await api.fetchData()
1392
- renderContent(data)
1393
- setState('contentState')
1394
- } catch (error) {
1395
- setState('errorState')
1396
- }
1397
- }
1398
-
1399
- // Initial load
1400
- loadData()
1401
- ```
1402
-
1403
- ### Pull-to-Refresh Pattern
1404
-
1405
- Enable users to refresh content by pulling down on a ListView.
1406
-
1407
- ```xml
1408
- <ListView id="listView" class="wh-screen">
1409
- <RefreshControl id="refreshControl" onRefresh="onRefresh" />
1410
- <ListSection id="section" />
1411
- </ListView>
1412
- ```
1413
-
1414
- ```javascript
1415
- // Controller
1416
- let isRefreshing = false
1417
-
1418
- async function onRefresh() {
1419
- if (isRefreshing) return
1420
- isRefreshing = true
1421
- try {
1422
- const data = await api.fetchLatest()
1423
- renderItems(data)
1424
- } catch (error) {
1425
- showError(error.message)
1426
- } finally {
1427
- $.refreshControl.endRefreshing()
1428
- isRefreshing = false
1429
- }
1430
- }
1431
-
1432
- function renderItems(data) {
1433
- const items = data.map(item => ({
1434
- properties: { itemId: item.id },
1435
- title: { text: item.name }
1436
- }))
1437
- $.section.setItems(items)
1438
- }
1439
- ```
1440
-
1441
- ### SearchBar with ListView
1442
-
1443
- Implement debounced search with real-time filtering.
1444
-
1445
- ```xml
1446
- <Window class="bg-gray-50">
1447
- <SearchBar id="searchBar" class="w-screen" hintText="L('search_contacts')" showCancel="true" onChange="onSearchChange" onCancel="onSearchCancel" />
1448
- <ListView id="listView" class="wh-screen" top="50">
1449
- <Templates>
1450
- <ItemTemplate name="contact" height="64">
1451
- <View class="horizontal h-16 w-screen bg-white">
1452
- <Label bindId="avatar" class="fa-solid fa-user-circle ml-4 text-3xl text-gray-400" />
1453
- <View class="vertical ml-3">
1454
- <Label bindId="name" class="text-base font-semibold" />
1455
- <Label bindId="phone" class="text-sm text-gray-500" />
1456
- </View>
1457
- </View>
1458
- </ItemTemplate>
1459
- </Templates>
1460
- <ListSection id="section" />
1461
- </ListView>
1462
- </Window>
1463
- ```
1464
-
1465
- ```javascript
1466
- // Controller
1467
- let allContacts = []
1468
- let searchTimeout = null
1469
-
1470
- function onSearchChange(e) {
1471
- clearTimeout(searchTimeout)
1472
- searchTimeout = setTimeout(() => {
1473
- filterContacts(e.value)
1474
- }, 300)
1475
- }
1476
-
1477
- function onSearchCancel() {
1478
- $.searchBar.value = ''
1479
- filterContacts('')
1480
- }
1481
-
1482
- function filterContacts(query) {
1483
- const q = query.toLowerCase().trim()
1484
- const filtered = q
1485
- ? allContacts.filter(c => c.name.toLowerCase().includes(q) || c.phone.includes(q))
1486
- : allContacts
1487
- renderContacts(filtered)
1488
- }
1489
-
1490
- function renderContacts(contacts) {
1491
- $.section.items = contacts.map(c => ({
1492
- template: 'contact',
1493
- properties: { itemId: c.id },
1494
- name: { text: c.name },
1495
- phone: { text: c.phone }
1496
- }))
1497
- }
1498
-
1499
- function cleanup() {
1500
- clearTimeout(searchTimeout)
1501
- $.destroy()
1502
- }
1503
-
1504
- $.cleanup = cleanup
1505
-
1506
- // Load initial data
1507
- async function loadContacts() {
1508
- try {
1509
- allContacts = await api.fetchContacts()
1510
- renderContacts(allContacts)
1511
- } catch (error) {
1512
- Ti.UI.createAlertDialog({
1513
- title: L('error'),
1514
- message: error.message
1515
- }).show()
1516
- }
1517
- }
1518
-
1519
- loadContacts()
1520
- ```
1521
-
1522
- ### Complete CRUD with ListView
1523
-
1524
- Full product list with create, read, update, and delete operations.
1525
-
1526
- ```xml
1527
- <Window class="bg-gray-50">
1528
- <ListView id="listView" class="wh-screen">
1529
- <RefreshControl id="refresh" onRefresh="onRefresh" />
1530
- <Templates>
1531
- <ItemTemplate name="product" height="80">
1532
- <View class="horizontal mb-2 h-20 w-screen bg-white">
1533
- <ImageView bindId="image" class="wh-16 ml-3 rounded-lg" />
1534
- <View class="vertical ml-3 w-auto">
1535
- <Label bindId="name" class="text-base font-semibold" />
1536
- <Label bindId="price" class="text-sm text-green-600" />
1537
- <Label bindId="stock" class="text-xs text-gray-400" />
1538
- </View>
1539
- </View>
1540
- </ItemTemplate>
1541
- </Templates>
1542
- <ListSection id="section" dataCollection="products">
1543
- <ListItem template="product" image:image="{imageUrl}" name:text="{name}" price:text="${price}" stock:text="{stock} in stock" />
1544
- </ListSection>
1545
- </ListView>
1546
-
1547
- <Button id="addBtn" class="bg-primary rounded-full-14 absolute bottom-6 right-6 shadow-lg" onClick="onAddProduct">
1548
- <Label class="fa-solid fa-plus text-xl text-white" />
1549
- </Button>
1550
- </Window>
1551
- ```
1552
-
1553
- ```javascript
1554
- // Controller
1555
- const productService = require('/services/productService')
1556
-
1557
- // Handle item click
1558
- function onItemClick(e) {
1559
- const item = e.section.getItemAt(e.itemIndex)
1560
- const productId = item.properties.itemId
1561
-
1562
- const detailWin = Alloy.createController('productDetail', { id: productId }).getView()
1563
- detailWin.open()
1564
- }
1565
-
1566
- // Refresh data
1567
- async function onRefresh() {
1568
- try {
1569
- const products = await productService.fetchAll()
1570
- Alloy.Collections.products.reset(products)
1571
- } catch (error) {
1572
- showError(error.message)
1573
- } finally {
1574
- $.refresh.endRefreshing()
1575
- }
1576
- }
1577
-
1578
- // Add new product
1579
- function onAddProduct() {
1580
- const formWin = Alloy.createController('productForm', { mode: 'create' }).getView()
1581
- formWin.open({ modal: true })
1582
- }
1583
-
1584
- // Show error message
1585
- function showError(message) {
1586
- Ti.UI.createAlertDialog({
1587
- title: L('error'),
1588
- message: message
1589
- }).show()
1590
- }
1591
-
1592
- // Event listeners
1593
- $.listView.addEventListener('itemclick', onItemClick)
1594
-
1595
- // Cleanup
1596
- function cleanup() {
1597
- $.listView.removeEventListener('itemclick', onItemClick)
1598
- $.destroy()
1599
- }
1600
-
1601
- $.cleanup = cleanup
1602
-
1603
- // Load initial data
1604
- onRefresh()
1605
- ```
1606
-
1607
- ### Form with Real-Time Validation
1608
-
1609
- Registration form with field-level validation and error feedback.
1610
-
1611
- ```xml
1612
- <Window class="bg-gray-50">
1613
- <ScrollView class="wh-screen">
1614
- <View class="vertical">
1615
- <Label class="mx-4 mb-6 mt-6 text-2xl font-bold text-gray-800" text="L('create_account')" />
1616
-
1617
- <!-- Name Field -->
1618
- <View class="mb-4">
1619
- <Label id="nameLabel" class="mx-4 mb-2 text-sm font-medium text-gray-700" text="L('full_name')" />
1620
- <TextField id="nameField" class="border-(1) return-key-type-next mx-4 mt-1 h-12 w-screen rounded-lg border-gray-300 px-3" hintText="L('enter_name')" onChange="validateName" />
1621
- <Label id="nameError" class="mx-4 mt-1 hidden text-xs text-red-500" />
1622
- </View>
1623
-
1624
- <!-- Email Field -->
1625
- <View class="mb-4">
1626
- <Label id="emailLabel" class="mx-4 mb-2 text-sm font-medium text-gray-700" text="L('email')" />
1627
- <TextField id="emailField" class="border-(1) return-key-type-next mx-4 mt-1 h-12 w-screen rounded-lg border-gray-300 px-3" keyboardType="Ti.UI.KEYBOARD_TYPE_EMAIL" autocapitalization="Ti.UI.TEXT_AUTOCAPITALIZATION_NONE" hintText="L('enter_email')" onChange="validateEmail" />
1628
- <Label id="emailError" class="mx-4 mt-1 hidden text-xs text-red-500" />
1629
- </View>
1630
-
1631
- <!-- Password Field -->
1632
- <View class="mb-4">
1633
- <Label id="passwordLabel" class="mx-4 mb-2 text-sm font-medium text-gray-700" text="L('password')" />
1634
- <TextField id="passwordField" class="border-(1) return-key-type-done mx-4 mt-1 h-12 w-screen rounded-lg border-gray-300 px-3" passwordMask="true" hintText="L('enter_password')" onChange="validatePassword" />
1635
- <Label id="passwordError" class="mx-4 mt-1 hidden text-xs text-red-500" />
1636
- </View>
1637
-
1638
- <!-- Terms Switch -->
1639
- <View class="horizontal mx-4 mb-6">
1640
- <Switch id="termsSwitch" onChange="validateTerms" />
1641
- <Label class="ml-3 text-sm text-gray-700" text="L('agree_to_terms')" />
1642
- </View>
1643
-
1644
- <!-- Submit Button -->
1645
- <Button id="submitBtn" class="bg-primary mx-4 h-12 rounded-lg text-base font-semibold text-white" title="L('create_account')" onClick="onSubmit" enabled="false" />
1646
- </View>
1647
- </ScrollView>
1648
- </Window>
1649
- ```
1650
-
1651
- ```javascript
1652
- // Controller
1653
- const validationState = {
1654
- name: false,
1655
- email: false,
1656
- password: false,
1657
- terms: false
1658
- }
1659
-
1660
- function validateName(e) {
1661
- const value = e.value.trim()
1662
- const isValid = value.length >= 2
1663
-
1664
- if (!isValid && value.length > 0) {
1665
- $.nameError.text = L('name_too_short')
1666
- $.nameError.visible = true
1667
- $.nameField.borderColor = '#EF4444'
1668
- $.nameLabel.color = '#EF4444'
1669
- } else {
1670
- $.nameError.visible = false
1671
- $.nameField.borderColor = isValid ? '#10B981' : '#D1D5DB'
1672
- $.nameLabel.color = isValid ? '#10B981' : '#374151'
1673
- }
1674
-
1675
- validationState.name = isValid
1676
- updateSubmitButton()
1677
- }
1678
-
1679
- function validateEmail(e) {
1680
- const value = e.value.trim()
1681
- const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
1682
- const isValid = emailRegex.test(value)
1683
-
1684
- if (!isValid && value.length > 0) {
1685
- $.emailError.text = L('invalid_email')
1686
- $.emailError.visible = true
1687
- $.emailField.borderColor = '#EF4444'
1688
- $.emailLabel.color = '#EF4444'
1689
- } else {
1690
- $.emailError.visible = false
1691
- $.emailField.borderColor = isValid ? '#10B981' : '#D1D5DB'
1692
- $.emailLabel.color = isValid ? '#10B981' : '#374151'
1693
- }
1694
-
1695
- validationState.email = isValid
1696
- updateSubmitButton()
1697
- }
1698
-
1699
- function validatePassword(e) {
1700
- const value = e.value
1701
- const isValid = value.length >= 8
1702
-
1703
- if (!isValid && value.length > 0) {
1704
- $.passwordError.text = L('password_too_short')
1705
- $.passwordError.visible = true
1706
- $.passwordField.borderColor = '#EF4444'
1707
- $.passwordLabel.color = '#EF4444'
1708
- } else {
1709
- $.passwordError.visible = false
1710
- $.passwordField.borderColor = isValid ? '#10B981' : '#D1D5DB'
1711
- $.passwordLabel.color = isValid ? '#10B981' : '#374151'
1712
- }
1713
-
1714
- validationState.password = isValid
1715
- updateSubmitButton()
1716
- }
1717
-
1718
- function validateTerms(e) {
1719
- validationState.terms = e.value
1720
- updateSubmitButton()
1721
- }
1722
-
1723
- function updateSubmitButton() {
1724
- const allValid = Object.values(validationState).every(v => v === true)
1725
- $.submitBtn.enabled = allValid
1726
- $.submitBtn.opacity = allValid ? 1.0 : 0.5
1727
- }
1728
-
1729
- async function onSubmit() {
1730
- if (!$.submitBtn.enabled) return
1731
-
1732
- $.submitBtn.enabled = false
1733
- $.submitBtn.title = L('creating_account')
1734
-
1735
- try {
1736
- const userData = {
1737
- name: $.nameField.value.trim(),
1738
- email: $.emailField.value.trim(),
1739
- password: $.passwordField.value
1740
- }
1741
-
1742
- await api.createAccount(userData)
1743
-
1744
- Ti.UI.createAlertDialog({
1745
- title: L('success'),
1746
- message: L('account_created')
1747
- }).show()
1748
-
1749
- $.getView().close()
1750
- } catch (error) {
1751
- Ti.UI.createAlertDialog({
1752
- title: L('error'),
1753
- message: error.message
1754
- }).show()
1755
- $.submitBtn.enabled = true
1756
- $.submitBtn.title = L('create_account')
1757
- }
1758
- }
1759
- ```
1760
-
1761
- ### TabGroup Pattern
1762
-
1763
- Standard tab-based navigation with separate screens.
1764
-
1765
- ```xml
1766
- <!-- index.xml -->
1767
- <TabGroup id="tabGroup" class="tabs-bg-white active-tint-blue-500">
1768
- <Tab title="L('home')" icon="/images/icons/home.png">
1769
- <Require src="tabs/home" />
1770
- </Tab>
1771
-
1772
- <Tab title="L('search')" icon="/images/icons/search.png">
1773
- <Require src="tabs/search" />
1774
- </Tab>
1775
-
1776
- <Tab title="L('favorites')" icon="/images/icons/heart.png">
1777
- <Require src="tabs/favorites" />
1778
- </Tab>
1779
-
1780
- <Tab title="L('profile')" icon="/images/icons/user.png">
1781
- <Require src="tabs/profile" />
1782
- </Tab>
1783
- </TabGroup>
1784
- ```
1785
-
1786
- ```javascript
1787
- // index.js
1788
- $.tabGroup.open()
1789
-
1790
- function cleanup() {
1791
- $.destroy()
1792
- }
1793
-
1794
- $.cleanup = cleanup
1795
- ```
1796
-
1797
- ```xml
1798
- <!-- tabs/home.xml -->
1799
- <Window class="bg-gray-50">
1800
- <ScrollView class="wh-screen">
1801
- <View class="vertical">
1802
- <Label class="mx-4 my-4 text-2xl font-bold text-gray-800" text="L('home')" />
1803
- <!-- Home content -->
1804
- </View>
1805
- </ScrollView>
1806
- </Window>
1807
- ```
1808
-
1809
- ```xml
1810
- <!-- tabs/search.xml -->
1811
- <Window class="bg-gray-50">
1812
- <SearchBar id="searchBar" class="w-screen" hintText="L('search')" />
1813
- <ListView id="results" class="wh-screen" top="50">
1814
- <ListSection id="section" />
1815
- </ListView>
1816
- </Window>
1817
- ```
1818
-
1819
- ---
1820
-
1821
- ## Quick Reference Card
1822
-
1823
- ### Common PurgeTSS Classes
1824
-
1825
- | Category | Classes | Examples |
1826
- | --------------- | -------------------------------------------- | ------------------------------- |
1827
- | **Spacing** | `p-{0-8}`, `m-{0-8}`, `px-{0-8}`, `py-{0-8}` | `p-4`, `mx-2`, `py-6` |
1828
- | **Colors** | `bg-{color}-{shade}`, `text-{color}-{shade}` | `bg-brand-500`, `text-gray-800` |
1829
- | **Typography** | `text-{xs,sm,base,lg,xl,2xl,3xl,4xl}` | `text-xl`, `text-2xl` |
1830
- | **Font Weight** | `font-{light,normal,medium,semibold,bold}` | `font-semibold`, `font-bold` |
1831
- | **Borders** | `border`, `border-{color}`, `rounded-{size}` | `border-gray-300`, `rounded-lg` |
1832
- | **Shadows** | `shadow-{sm,md,lg,xl,2xl}` | `shadow-md`, `shadow-lg` |
1833
- | **Width** | `w-{size}`, `w-{percentage}` | `w-full`, `w-(50%)` |
1834
- | **Height** | `h-{size}`, `h-screen` | `h-10`, `h-screen` |
1835
- | **Display** | `hidden`, `visible` | `hidden`, `visible` |
1836
- | **Icons** | `fas`, `far`, `fab fa-{icon}` | `fas fa-home`, `fab fa-twitter` |
1837
-
1838
- ### Platform Modifiers
1839
-
1840
- ```xml
1841
- <!-- iOS-only -->
1842
- <View class="ios:p-4 ios:bg-white">...</View>
1843
-
1844
- <!-- Android-only -->
1845
- <View class="android:p-4 android:bg-gray-100">...</View>
1846
-
1847
- <!-- Platform-specific values -->
1848
- <View class="ios:bg-white android:bg-gray-100 p-4">...</View>
1849
- ```
1850
-
1851
- ---
1852
-
1853
- ## Best Practices Summary
321
+ ## Performance Notes
1854
322
 
1855
- 1. **Use `dp` units** for cross-platform consistency
1856
- 2. **Prefer ListView over TableView** for large datasets
1857
- 3. **Avoid `Ti.UI.SIZE` in ListViews** - use fixed heights
1858
- 4. **Provide accessibility labels** for all interactive elements
1859
- 5. **Ensure minimum touch target size** of 44dp (iOS) / 48dp (Android)
1860
- 6. **Use semantic color names** for better theming support
1861
- 7. **Test on both platforms** to ensure consistent experience
1862
- 8. **Follow platform conventions** - iOS NavigationWindow, Android Action Bar
1863
- 9. **Use PurgeTSS utility classes** for consistent styling
1864
- 10. **Batch property updates** using `applyProperties()` for better performance
1865
- 11. **Padding classes do NOT work on View** - use margin on children instead
1866
- 12. **Always specify Font Awesome icons** - `fas fa-home`, not just `fas`
323
+ - Prefer `ListView` templates for long lists.
324
+ - Use fixed heights for high-density scrolling content when possible.
325
+ - Avoid manual inline styling when a class can express the same result.
326
+ - Keep overlays and large composited layouts simple on lower-end devices.
1867
327
 
1868
- ---
328
+ ## Quick Reference
1869
329
 
1870
- ## Additional Resources
330
+ | Need | Preferred Pattern |
331
+ | --- | --- |
332
+ | Full-width container | `w-screen` |
333
+ | Stack items vertically | `vertical` |
334
+ | Row of actions | `horizontal` |
335
+ | Fill space in overlay/modal | `h-screen w-screen` |
336
+ | Card spacing | Margins on children |
337
+ | Input inner spacing | `px-*`, `py-*` on input controls |
338
+ | Tablet adaptation | `tablet:*`, `handheld:*` |
339
+ | Overlay background | `bg-(#88000000)` |
1871
340
 
1872
- - [PurgeTSS Documentation](https://purgetss.com)
1873
- - [Titanium SDK Documentation](https://docs.appcelerator.com)
1874
- - [iOS Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines/)
1875
- - [Material Design Guidelines](https://material.io/design)
1876
- - [Web Content Accessibility Guidelines (WCAG)](https://www.w3.org/WAI/WCAG21/quickref/)
341
+ > **⚠️ Common Pitfalls**
342
+ > - Do not use `md:*`, `lg:*`, `focus:*`, or other web-responsive/state prefixes.
343
+ > - Do not assume `w-full` behaves like `Ti.UI.FILL`.
344
+ > - Do not put `p-*` on container views.
345
+ > - Do not rely on Flexbox classes such as `flex-row`, `justify-between`, or `items-center`.