@maccesar/titools 4.23.1 → 5.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -3
- package/package.json +1 -1
- package/skills/alloy-guides/references/MODELS.md +2 -2
- package/skills/alloy-guides/references/MODELS_ADVANCED.md +1 -1
- package/skills/alloy-guides/references/VIEWS_XML.md +13 -13
- package/skills/alloy-howtos/references/best_practices.md +2 -2
- package/skills/alloy-howtos/references/cli_reference.md +1 -1
- package/skills/alloy-howtos/references/debugging_troubleshooting.md +1 -1
- package/skills/purgetss/SKILL.md +27 -24
- package/skills/purgetss/references/EXAMPLES.md +52 -41
- package/skills/purgetss/references/adopting-purgetss.md +137 -0
- package/skills/purgetss/references/animation-advanced.md +18 -5
- package/skills/purgetss/references/animation-system.md +21 -9
- package/skills/purgetss/references/app-branding.md +36 -97
- package/skills/purgetss/references/appearance-module.md +70 -5
- package/skills/purgetss/references/apply-directive.md +14 -6
- package/skills/purgetss/references/arbitrary-values.md +59 -23
- package/skills/purgetss/references/brand-padding-geometry.md +105 -0
- package/skills/purgetss/references/class-categories.md +684 -272
- package/skills/purgetss/references/class-index-properties.md +713 -607
- package/skills/purgetss/references/class-index.md +149 -84
- package/skills/purgetss/references/classic-projects.md +2 -2
- package/skills/purgetss/references/cli-commands.md +27 -213
- package/skills/purgetss/references/color-commands.md +218 -0
- package/skills/purgetss/references/configurable-properties.md +17 -2
- package/skills/purgetss/references/custom-fonts.md +21 -16
- package/skills/purgetss/references/custom-rules.md +7 -7
- package/skills/purgetss/references/customization-deep-dive.md +14 -11
- package/skills/purgetss/references/dynamic-component-creation.md +104 -61
- package/skills/purgetss/references/grid-layout.md +21 -24
- package/skills/purgetss/references/icon-fonts.md +37 -20
- package/skills/purgetss/references/installation-setup.md +1 -1
- package/skills/purgetss/references/ios-large-titles.md +12 -11
- package/skills/purgetss/references/migration-guide.md +101 -10
- package/skills/purgetss/references/multi-density-images.md +44 -24
- package/skills/purgetss/references/opacity-modifier.md +1 -1
- package/skills/purgetss/references/performance-tips.md +5 -4
- package/skills/purgetss/references/platform-modifiers.md +2 -2
- package/skills/purgetss/references/purgetss-ui-classic.md +21 -5
- package/skills/purgetss/references/semantic-colors.md +20 -13
- package/skills/purgetss/references/smart-mappings.md +8 -7
- package/skills/purgetss/references/svg-pipeline.md +21 -13
- package/skills/purgetss/references/tikit-components.md +2 -2
- package/skills/purgetss/references/titanium-resets.md +27 -17
- package/skills/purgetss/references/ui-ux-design.md +38 -26
- package/skills/purgetss/references/values-and-units.md +1 -2
- package/skills/purgetss/references/version-history.md +32 -4
- package/skills/ti-api/references/api-data-network.md +1 -1
- package/skills/ti-api/references/api-media.md +1 -1
- package/skills/ti-api/references/api-services.md +8 -5
- package/skills/ti-api/references/api-ui-lists.md +3 -2
- package/skills/ti-api/references/api-ui-text-input.md +1 -1
- package/skills/ti-expert/references/feedback-surfaces.md +1 -1
- package/skills/ti-guides/references/resources.md +1 -1
- package/skills/ti-guides/references/sdk-release-notes.md +22 -11
- package/skills/ti-howtos/references/extending-titanium.md +77 -0
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# Adopting PurgeTSS in an Existing Alloy App
|
|
2
|
+
|
|
3
|
+
How to move an Alloy app whose styles live in hand-written `.tss` files (per-controller files, `#id` rules, inline XML attributes) to PurgeTSS utility classes. For upgrading a project that already uses PurgeTSS from one version to another, see [migration-guide.md](migration-guide.md) instead.
|
|
4
|
+
|
|
5
|
+
> **Source note:** the official PurgeTSS docs have no adoption guide. This page is TiTools author guidance, assembled from behavior verified in the PurgeTSS source (v7.17.1), the Alloy style-priority rules and `utilities.tss`. Every class in the tables below exists in `utilities.tss` with the value shown.
|
|
6
|
+
|
|
7
|
+
## Ground Rules
|
|
8
|
+
|
|
9
|
+
- **Never delete the user's `.tss` files without explicit consent.** Convert a view, show the result, and wait for confirmation before removing the old rules (see `SKILL.md` § "RESPECT USER FILES").
|
|
10
|
+
- **One view at a time.** Convert, compile, check on both platforms, then move on.
|
|
11
|
+
- **Alloy only.** The utility-class workflow does not exist in Classic projects; see [classic-projects.md](classic-projects.md).
|
|
12
|
+
|
|
13
|
+
## What PurgeTSS Does to Your Styles
|
|
14
|
+
|
|
15
|
+
| File | What happens |
|
|
16
|
+
| --- | --- |
|
|
17
|
+
| `app/styles/app.tss` | On the first run it is backed up to `app/styles/_app.tss`. From then on PurgeTSS **rewrites `app.tss` on every run**: resets, then the contents of `_app.tss`, then only the utility classes your views use. Never edit `app.tss` directly. |
|
|
18
|
+
| `app/styles/_app.tss` | Your original global styles. Keep custom global classes here; they are copied into `app.tss` on each run. |
|
|
19
|
+
| `app/styles/<controller>.tss` | Not touched. PurgeTSS reads these files only so the classes they define are not reported as missing. |
|
|
20
|
+
| `alloy.jmk` | The first run adds a hook so `purgetss` runs on every Alloy compile. See [installation-setup.md](installation-setup.md). |
|
|
21
|
+
|
|
22
|
+
### The Priority Trap
|
|
23
|
+
|
|
24
|
+
Alloy applies styles from lowest to highest priority: `styles/app.tss` (global), then `styles/<controller>.tss`, then attributes in the XML markup, with theme and platform-specific files layered in between (Alloy guide, "Style Priorities"). PurgeTSS classes land in `app.tss`, the **lowest** layer. During a partial migration this means:
|
|
25
|
+
|
|
26
|
+
- A leftover rule in `styles/index.tss` for the same element beats the utility class, silently.
|
|
27
|
+
- An inline attribute such as `backgroundColor="#fff"` beats both.
|
|
28
|
+
|
|
29
|
+
When a class "does nothing" mid-migration, look for a leftover rule in the controller's `.tss` or an attribute on the XML tag before suspecting PurgeTSS.
|
|
30
|
+
|
|
31
|
+
## Workflow
|
|
32
|
+
|
|
33
|
+
### 1. Set up
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
cd your-app
|
|
37
|
+
purgetss init # creates ./purgetss/config.cjs
|
|
38
|
+
purgetss # first purge: backs up app.tss to _app.tss and installs the alloy.jmk hook
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Commit (or branch) before this step so the backup and the hook are easy to review.
|
|
42
|
+
|
|
43
|
+
### 2. Convert one view
|
|
44
|
+
|
|
45
|
+
Before:
|
|
46
|
+
|
|
47
|
+
```xml
|
|
48
|
+
<!-- app/views/index.xml -->
|
|
49
|
+
<View id="header">
|
|
50
|
+
<Label id="title" text="Welcome" />
|
|
51
|
+
</View>
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
```tss
|
|
55
|
+
// app/styles/index.tss
|
|
56
|
+
'#header': { backgroundColor: '#ffffff', height: 64, top: 0 }
|
|
57
|
+
'#title': { color: '#1f2937', font: { fontSize: 18, fontWeight: 'bold' } }
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
After:
|
|
61
|
+
|
|
62
|
+
```xml
|
|
63
|
+
<!-- app/views/index.xml -->
|
|
64
|
+
<View class="top-0 h-16 bg-white">
|
|
65
|
+
<Label class="text-lg font-bold text-gray-800" text="Welcome" />
|
|
66
|
+
</View>
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Keep the `id` attributes if controller code uses them (`$.header`); only the style rules move.
|
|
70
|
+
|
|
71
|
+
### 3. Remove the old rules (with consent)
|
|
72
|
+
|
|
73
|
+
Once the converted view looks right on both platforms, and the user agrees:
|
|
74
|
+
|
|
75
|
+
1. Delete the converted rules from `app/styles/index.tss`. Remove the file only if nothing is left in it.
|
|
76
|
+
2. Move any global class still needed from `_app.tss` into utility classes, or leave it in `_app.tss`.
|
|
77
|
+
3. Run `purgetss` (or compile) to regenerate `app.tss`.
|
|
78
|
+
|
|
79
|
+
## Translation Tables
|
|
80
|
+
|
|
81
|
+
### Properties
|
|
82
|
+
|
|
83
|
+
| Hand-written TSS | PurgeTSS class |
|
|
84
|
+
| --- | --- |
|
|
85
|
+
| `backgroundColor: '#ffffff'` | `bg-white` |
|
|
86
|
+
| `backgroundColor: '#f3f4f6'` | `bg-gray-100` |
|
|
87
|
+
| `color: '#1f2937'` | `text-gray-800` (sets `color` and `textColor`) |
|
|
88
|
+
| `font: { fontSize: 18 }` | `text-lg` |
|
|
89
|
+
| `font: { fontWeight: 'bold' }` | `font-bold` |
|
|
90
|
+
| `width: Ti.UI.FILL` | `w-screen` |
|
|
91
|
+
| `width: '100%'` | `w-full` |
|
|
92
|
+
| `height: Ti.UI.SIZE` | `h-auto` |
|
|
93
|
+
| `height: 64` | `h-16` |
|
|
94
|
+
| `height: 60` (not on the scale) | `h-(60)` |
|
|
95
|
+
| `top: 0` | `top-0` |
|
|
96
|
+
| `top: 16` | `mt-4` |
|
|
97
|
+
| `left: 16, right: 16` | `mx-4` |
|
|
98
|
+
| `borderRadius: 8` | `rounded-lg` |
|
|
99
|
+
| `borderWidth: 1, borderColor: '#e5e7eb'` | `border border-gray-200` |
|
|
100
|
+
| `opacity: 0.5` | `opacity-50` |
|
|
101
|
+
| `visible: false` | `hidden` |
|
|
102
|
+
| `layout: 'horizontal'` | `horizontal` |
|
|
103
|
+
| `layout: 'vertical'` | `vertical` |
|
|
104
|
+
| `elevation: 4` | `elevation-1` (the scale is ×4: `elevation-4` is `16`) |
|
|
105
|
+
|
|
106
|
+
Spacing classes multiply by 4 (`mt-4` = 16), and the numbers are unitless: Titanium resolves them with `ti.ui.defaultunit` (see [values-and-units.md](values-and-units.md)). For a value off the scale use an arbitrary value **without a unit**: `h-(60)`, not `h-(60px)`, which stops the build since v7.8.0 (see [arbitrary-values.md](arbitrary-values.md)). Colors in your brand palette belong in `config.cjs` (see [customization-deep-dive.md](customization-deep-dive.md)), not in arbitrary `bg-(#hex)` classes repeated across views.
|
|
107
|
+
|
|
108
|
+
### Platform and device conditionals
|
|
109
|
+
|
|
110
|
+
| Hand-written code | PurgeTSS |
|
|
111
|
+
| --- | --- |
|
|
112
|
+
| `if (OS_IOS) { $.box.top = 40 } else { $.box.top = 20 }` | `class="ios:mt-10 mt-5"` |
|
|
113
|
+
| `if (OS_ANDROID) { $.card.elevation = 4 }` | `class="android:elevation-1"` |
|
|
114
|
+
| Tablet width set in the controller | `class="tablet:w-6/12 w-screen"` |
|
|
115
|
+
|
|
116
|
+
See [platform-modifiers.md](platform-modifiers.md) for the full modifier list.
|
|
117
|
+
|
|
118
|
+
### Animations
|
|
119
|
+
|
|
120
|
+
| Hand-written animation | PurgeTSS Animation module |
|
|
121
|
+
| --- | --- |
|
|
122
|
+
| `Ti.UI.createAnimation({ opacity: 0, duration: 300 })` toggled by hand | `<Animation module="purgetss.ui" id="fade" class="close:opacity-0 open:opacity-100 duration-300" />` and `$.fade.play($.box)` |
|
|
123
|
+
| A scale-down press effect | `class="close:scale-100 open:scale-95 duration-150"` |
|
|
124
|
+
|
|
125
|
+
See [animation-system.md](animation-system.md).
|
|
126
|
+
|
|
127
|
+
## Pitfalls
|
|
128
|
+
|
|
129
|
+
| Pitfall | Consequence | Prevention |
|
|
130
|
+
| --- | --- | --- |
|
|
131
|
+
| Editing `app.tss` directly | Overwritten on the next run | Put custom global styles in `_app.tss` |
|
|
132
|
+
| Leaving the old rule in `<controller>.tss` | It overrides the utility class | Remove converted rules once the user agrees |
|
|
133
|
+
| Keeping inline attributes (`backgroundColor="…"`) | They override every class | Move them into classes |
|
|
134
|
+
| Flexbox classes (`flex-row`, `justify-between`) | Classes don't exist | `horizontal` / `vertical` layouts |
|
|
135
|
+
| `p-*` on a `View` or `Window` | No effect: `padding` exists only on `TextField`, `TextArea` and Android `CardView` | Margins on the children |
|
|
136
|
+
| `w-[100]` or `w-(100px)` | Stops the build | `w-(100)` |
|
|
137
|
+
| Converting every view at once | Hard to find what broke | One view per step, tested on both platforms |
|
|
@@ -138,7 +138,7 @@ Values: `repeat-0` through `repeat-12`.
|
|
|
138
138
|
|
|
139
139
|
### rotate-* and -rotate-*
|
|
140
140
|
|
|
141
|
-
Rotation in degrees. Range: **0** to **
|
|
141
|
+
Rotation in degrees. Range: **0** to **360**, positive and negative.
|
|
142
142
|
|
|
143
143
|
```css
|
|
144
144
|
'.rotate-0': { rotate: 0 }
|
|
@@ -149,7 +149,12 @@ Rotation in degrees. Range: **0** to **180**, positive and negative.
|
|
|
149
149
|
'.rotate-12': { rotate: 12 }
|
|
150
150
|
'.rotate-45': { rotate: 45 }
|
|
151
151
|
'.rotate-90': { rotate: 90 }
|
|
152
|
+
'.rotate-135': { rotate: 135 }
|
|
152
153
|
'.rotate-180': { rotate: 180 }
|
|
154
|
+
'.rotate-225': { rotate: 225 }
|
|
155
|
+
'.rotate-270': { rotate: 270 }
|
|
156
|
+
'.rotate-315': { rotate: 315 }
|
|
157
|
+
'.rotate-360': { rotate: 360 }
|
|
153
158
|
'.-rotate-0': { rotate: 0 }
|
|
154
159
|
'.-rotate-1': { rotate: -1 }
|
|
155
160
|
'.-rotate-2': { rotate: -2 }
|
|
@@ -158,7 +163,12 @@ Rotation in degrees. Range: **0** to **180**, positive and negative.
|
|
|
158
163
|
'.-rotate-12': { rotate: -12 }
|
|
159
164
|
'.-rotate-45': { rotate: -45 }
|
|
160
165
|
'.-rotate-90': { rotate: -90 }
|
|
166
|
+
'.-rotate-135': { rotate: -135 }
|
|
161
167
|
'.-rotate-180': { rotate: -180 }
|
|
168
|
+
'.-rotate-225': { rotate: -225 }
|
|
169
|
+
'.-rotate-270': { rotate: -270 }
|
|
170
|
+
'.-rotate-315': { rotate: -315 }
|
|
171
|
+
'.-rotate-360': { rotate: -360 }
|
|
162
172
|
```
|
|
163
173
|
|
|
164
174
|
### scale-*
|
|
@@ -180,6 +190,7 @@ Scales the matrix by the specified factor. Same value for horizontal and vertica
|
|
|
180
190
|
'.scale-110': { scale: 1.1 }
|
|
181
191
|
'.scale-125': { scale: 1.25 }
|
|
182
192
|
'.scale-150': { scale: 1.5 }
|
|
193
|
+
'.scale-200': { scale: 2 }
|
|
183
194
|
```
|
|
184
195
|
|
|
185
196
|
### Snap Classes
|
|
@@ -221,7 +232,7 @@ Prevents the drag system from promoting the active view on touch start. It does
|
|
|
221
232
|
|
|
222
233
|
### zoom-in-* / zoom-out-*
|
|
223
234
|
|
|
224
|
-
Animates zoom in and zoom out. Sets the View's scale to the specified value, then animates it back to 1. Range: **0** to **
|
|
235
|
+
Animates zoom in and zoom out. Sets the View's scale to the specified value, then animates it back to 1. Range: **0** to **200**.
|
|
225
236
|
|
|
226
237
|
```css
|
|
227
238
|
'.zoom-in-0': { animationProperties: { open: { scale: 0 }, complete: { scale: 1 } } }
|
|
@@ -234,7 +245,7 @@ Animates zoom in and zoom out. Sets the View's scale to the specified value, the
|
|
|
234
245
|
'.zoom-out-110': { animationProperties: { close: { scale: 1.1 }, complete: { scale: 1 } } }
|
|
235
246
|
```
|
|
236
247
|
|
|
237
|
-
Full range: `zoom-in-0`, `zoom-in-1`, `zoom-in-5`, `zoom-in-10`, `zoom-in-25`, `zoom-in-50`, `zoom-in-75`, `zoom-in-90`, `zoom-in-95`, `zoom-in-100`, `zoom-in-105`, `zoom-in-110`, `zoom-in-125`, `zoom-in-150` (and same for `zoom-out-*`).
|
|
248
|
+
Full range: `zoom-in-0`, `zoom-in-1`, `zoom-in-5`, `zoom-in-10`, `zoom-in-25`, `zoom-in-50`, `zoom-in-75`, `zoom-in-90`, `zoom-in-95`, `zoom-in-100`, `zoom-in-105`, `zoom-in-110`, `zoom-in-125`, `zoom-in-150`, `zoom-in-200` (and same for `zoom-out-*`).
|
|
238
249
|
|
|
239
250
|
---
|
|
240
251
|
|
|
@@ -278,7 +289,7 @@ At construction time, top-level `scale`, `rotate`, and `anchorPoint` are convert
|
|
|
278
289
|
|
|
279
290
|
`play()`, `toggle()`, `apply()`, and `sequence()` toggle internal open/close state. `open()` and `close()` set it explicitly. The active state is merged into the current base object when `animationProperties` exists.
|
|
280
291
|
|
|
281
|
-
After a top-level `play`, `toggle`, `open`, or `close`, `animationProperties.complete` starts as a second animation. `apply()` applies `complete` immediately. The public callback belongs to the base play/apply operation; it does not wait for the second top-level `complete` animation.
|
|
292
|
+
After a top-level `play`, `toggle`, `open`, or `close`, and after each view of a `sequence()`, `animationProperties.complete` starts as a second animation. `apply()` applies `complete` immediately. The public callback belongs to the base play/apply operation; it does not wait for the second top-level `complete` animation.
|
|
282
293
|
|
|
283
294
|
For each direct child with an active state, merge precedence is:
|
|
284
295
|
|
|
@@ -308,7 +319,7 @@ Drag precedence is precise:
|
|
|
308
319
|
- `snap.center` invokes `snapTo()` after a valid drop; `snap.back` returns a missed drop to its captured origin.
|
|
309
320
|
- No `snap.magnet` behavior exists.
|
|
310
321
|
|
|
311
|
-
Collision detection uses the dragged view's center.
|
|
322
|
+
Collision detection uses the dragged view's center and runs only for views registered with `detectCollisions()`, so register the dragged views as well as the targets. Hit testing during movement runs only when a `dragCB` was supplied; in that case the last non-null hover target is a fallback when the final hit test at release returns `null`. `dragCB(source, null)` is also called whenever a registered view is released.
|
|
312
323
|
|
|
313
324
|
`draggable(array)` immediately assigns each view `zIndex` from its array index. `keepZIndex` only disables later touch-start promotion. `swap()` restores z-order by the current draggable-registry order, not by arbitrary values present before registration.
|
|
314
325
|
|
|
@@ -423,3 +434,5 @@ function doAction(event) {
|
|
|
423
434
|
```
|
|
424
435
|
|
|
425
436
|
This demonstrates: `play` for sidebar/card toggle, `open:`/`close:` modifiers for different states, `draggable` with `bounds:` modifier, and multiple Animation objects controlling different UI elements.
|
|
437
|
+
|
|
438
|
+
If this window can close, add an `onClose` handler that calls `$.draggableAnimation.undraggable($.myCard)` so the global `orientationchange` listener is removed.
|
|
@@ -84,7 +84,7 @@ The `play`, `toggle`, `open`, `close`, `apply`, and `sequence` methods accept an
|
|
|
84
84
|
| --- | --- |
|
|
85
85
|
| `open:` | Properties applied during open state |
|
|
86
86
|
| `close:` | Properties applied during close state |
|
|
87
|
-
| `complete:` | Additional properties applied after the active `play`/`toggle`/`open`/`close` state, or immediately after `apply` |
|
|
87
|
+
| `complete:` | Additional properties applied after the active `play`/`toggle`/`open`/`close` state (and after each view of a `sequence`), or immediately after `apply` |
|
|
88
88
|
| `children:` | Global properties for all children of a View |
|
|
89
89
|
| `child:` | Individual properties for specific children |
|
|
90
90
|
| `bounds:` | Drag boundaries within parent |
|
|
@@ -93,7 +93,9 @@ The `play`, `toggle`, `open`, `close`, `apply`, and `sequence` methods accept an
|
|
|
93
93
|
|
|
94
94
|
### Timing and Special Classes
|
|
95
95
|
|
|
96
|
-
`delay-*`, `duration-*`, `rotate-*`, `scale-*`, `repeat-*`, `zoom-in-*`, `zoom-out-*`, `drag-apply`, `drag-animate`, `ease-in`, `ease-out`, `ease-linear`, `ease-in-out`, `vertical-constraint`, `horizontal-constraint`.
|
|
96
|
+
`delay-*`, `duration-*`, `rotate-*`, `scale-*`, `repeat-*`, `zoom-in-*`, `zoom-out-*`, `drag-apply`, `drag-animate`, `ease-in`, `ease-out`, `ease-linear`, `ease-in-out`, `vertical-constraint`, `horizontal-constraint`, `debug`.
|
|
97
|
+
|
|
98
|
+
The `debug` class sets `debug: true` (in Classic, pass `debug: true` to `createAnimation()`). The object then logs every method call and internal step with `console.warn('::ti.animation:: …')`.
|
|
97
99
|
|
|
98
100
|
---
|
|
99
101
|
|
|
@@ -101,6 +103,8 @@ The `play`, `toggle`, `open`, `close`, `apply`, and `sequence` methods accept an
|
|
|
101
103
|
|
|
102
104
|
Runs the animation for a single view or an array of views. Toggles between open and close states on repeated calls.
|
|
103
105
|
|
|
106
|
+
`play` and `toggle` do nothing while the object's internal `playing` flag is set. The flag turns on when a native animation starts and off at the first completion event, so with an array it clears when the first view finishes. `open`, `close`, `apply`, and `sequence` do not check it.
|
|
107
|
+
|
|
104
108
|
```javascript
|
|
105
109
|
$.myAnimation.play($.myView)
|
|
106
110
|
```
|
|
@@ -262,6 +266,10 @@ function showPanel() {
|
|
|
262
266
|
function closePanel() {
|
|
263
267
|
$.panelAnim.close($.panel, () => { $.panel.hide() })
|
|
264
268
|
}
|
|
269
|
+
|
|
270
|
+
function onOverlayTap({ source }) {
|
|
271
|
+
if (source.id === 'panel') closePanel()
|
|
272
|
+
}
|
|
265
273
|
```
|
|
266
274
|
|
|
267
275
|
Key classes: `zoom-in-110` (pop effect), `opacity-to-100` (fade overlay), `close:duration-0 open:duration-100` (instant close, animated open).
|
|
@@ -341,6 +349,8 @@ function onClose() {
|
|
|
341
349
|
|
|
342
350
|
After calling `draggable()`, enable collision detection based on center-point hit testing.
|
|
343
351
|
|
|
352
|
+
Include the dragged views themselves in the `views` list: drop callbacks, `snap-center`, and `snap-back` run only for a view registered with `detectCollisions()`.
|
|
353
|
+
|
|
344
354
|
```javascript
|
|
345
355
|
$.myAnimation.draggable(views)
|
|
346
356
|
$.myAnimation.detectCollisions(views, dragCB, dropCB)
|
|
@@ -351,9 +361,11 @@ $.myAnimation.detectCollisions(views, dragCB, dropCB)
|
|
|
351
361
|
| Parameter | Type | Description |
|
|
352
362
|
| --- | --- | --- |
|
|
353
363
|
| `views` | `View/Array` | Views to register for collision detection |
|
|
354
|
-
| `dragCB` | `Function(source, target)` | Called during drag; `target` is the view under the drag center, or `null` when leaving |
|
|
364
|
+
| `dragCB` | `Function(source, target)` | Called during drag; `target` is the view under the drag center, or `null` when leaving. Also called with `null` whenever a registered view is released |
|
|
355
365
|
| `dropCB` | `Function(source, target)` | Called on drop when a collision target is found |
|
|
356
366
|
|
|
367
|
+
Hit testing during movement runs only when a `dragCB` was supplied. Without one, the drop uses only the final hit test at release; the last-hovered target is not available as a fallback.
|
|
368
|
+
|
|
357
369
|
### Snap Classes
|
|
358
370
|
|
|
359
371
|
Off by default -- opt-in via classes on the `<Animation>` object:
|
|
@@ -436,12 +448,12 @@ $.myAnimation.sequence(views, callback)
|
|
|
436
448
|
```
|
|
437
449
|
|
|
438
450
|
```javascript
|
|
439
|
-
$.
|
|
451
|
+
$.revealAnim.sequence([$.title, $.subtitle, $.cta], () => {
|
|
440
452
|
console.log('All views animated in sequence')
|
|
441
453
|
})
|
|
442
454
|
|
|
443
455
|
// Use close() to force state back before revealing again
|
|
444
|
-
$.revealAnim.close(
|
|
456
|
+
$.revealAnim.close([$.title, $.subtitle, $.cta])
|
|
445
457
|
```
|
|
446
458
|
|
|
447
459
|
---
|
|
@@ -459,7 +471,7 @@ $.myAnimation.swap(view1, view2)
|
|
|
459
471
|
- Resets the source transform while persisting the exchanged positions
|
|
460
472
|
- Temporarily elevates z-index; then assigns z-index from the current draggable-registry order rather than restoring arbitrary original values
|
|
461
473
|
- Updates `_originLeft`/`_originTop` for subsequent drag operations
|
|
462
|
-
- **
|
|
474
|
+
- **Position resolution**: `view2`'s destination is read from `view2.rect`, but `view1`'s home comes from its stored drag origin or its `top`/`left`, with no `rect` fallback. Give `view1` explicit `top`/`left` unless it has already been dragged or moved by a helper
|
|
463
475
|
- **Bounce-back safe**: completes any in-progress bounce-back before swapping
|
|
464
476
|
|
|
465
477
|
### Memory Card Game Example
|
|
@@ -469,7 +481,7 @@ let firstCard = null
|
|
|
469
481
|
function onCardTap({ source }) {
|
|
470
482
|
$.flipAnim.open(source)
|
|
471
483
|
if (!firstCard) { firstCard = source; return }
|
|
472
|
-
if (firstCard.
|
|
484
|
+
if (firstCard.value === source.value) {
|
|
473
485
|
firstCard = null
|
|
474
486
|
} else {
|
|
475
487
|
$.gameAnim.swap(firstCard, source)
|
|
@@ -552,7 +564,7 @@ $.puzzleAnim.draggable(pieces)
|
|
|
552
564
|
$.puzzleAnim.detectCollisions(pieces.concat(slots),
|
|
553
565
|
null,
|
|
554
566
|
(source, target) => {
|
|
555
|
-
if (source.
|
|
567
|
+
if (source.value === target.value) {
|
|
556
568
|
$.puzzleAnim.undraggable(source)
|
|
557
569
|
source.applyProperties({ opacity: 0.6 })
|
|
558
570
|
}
|
|
@@ -643,7 +655,7 @@ $.anim.transition(screensB, fanOut)
|
|
|
643
655
|
|
|
644
656
|
```javascript
|
|
645
657
|
const photos = [$.photo1, $.photo2, $.photo3]
|
|
646
|
-
function doFan() { $.galleryAnim.transition(photos,
|
|
658
|
+
function doFan() { $.galleryAnim.transition(photos, fanOut) }
|
|
647
659
|
function doStack() { $.galleryAnim.transition(photos, stack) }
|
|
648
660
|
$.galleryAnim.draggable(photos) // photos keep rotation/scale while dragging
|
|
649
661
|
```
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# App Icons & Branding
|
|
2
2
|
|
|
3
|
-
The `purgetss brand` command generates the complete Titanium branding set from one main SVG or PNG logo: launcher icons, adaptive icons, iOS 18+ Dark/Tinted variants, marketplace artwork, and both splash sets. Per-piece overrides are available when needed. Alloy and Classic layouts are auto-detected, and since v7.14.0 a normal run follows the platforms enabled in `tiapp.xml`.
|
|
3
|
+
The `purgetss brand` command generates the complete Titanium branding set from one main SVG or PNG logo: launcher icons, adaptive icons, iOS 18+ Dark/Tinted variants, marketplace artwork, and both splash sets. Per-piece overrides are available when needed. Alloy and Classic layouts are auto-detected, and since v7.14.0 a normal run follows the platforms enabled in `tiapp.xml`. The rule: if an enabled platform can consume the file, `brand` generates or updates it.
|
|
4
4
|
|
|
5
|
-
The command also creates Titanium-consumed Classic paths that a fresh Classic template does not seed, including the 11 Android `Resources/android/images/res-*` splash variants. An explicit `--only` is an intentional override that can prepare assets for a disabled deployment target.
|
|
5
|
+
The command also creates Titanium-consumed Classic paths that a fresh Classic template does not seed, including the 11 Android `Resources/android/images/res-*` splash variants. An explicit `--only` is an intentional override that can prepare assets for a disabled deployment target. A normal run names the pieces it left out (`Skipped for disabled deployment target(s): …`), and stops with a warning when no selected piece matches an enabled target.
|
|
6
6
|
|
|
7
7
|
For the terse flag reference, see the [`brand` command reference](./cli-commands.md#brand-command). For sibling UI assets, see [Multi-Density Images](./multi-density-images.md).
|
|
8
8
|
|
|
@@ -30,8 +30,7 @@ For the terse flag reference, see the [`brand` command reference](./cli-commands
|
|
|
30
30
|
- [iPhone launch images](#iphone-launch-images)
|
|
31
31
|
- [iOS 18+ Dark and Tinted variants](#ios-18-dark-and-tinted-variants)
|
|
32
32
|
- [Brand color](#brand-color)
|
|
33
|
-
- [Padding
|
|
34
|
-
- [Rounded non-icon artwork](#rounded-non-icon-artwork)
|
|
33
|
+
- [Padding and geometry](#padding-and-geometry)
|
|
35
34
|
- [Cleanup legacy branding artifacts](#cleanup-legacy-branding-artifacts)
|
|
36
35
|
- [Troubleshooting](#troubleshooting)
|
|
37
36
|
- [Flag reference](#flag-reference)
|
|
@@ -64,7 +63,7 @@ Pass `--dry-run` to preview without writing any files:
|
|
|
64
63
|
purgetss brand --dry-run
|
|
65
64
|
```
|
|
66
65
|
|
|
67
|
-
You may also pass a source directly. When
|
|
66
|
+
You may also pass a source directly. When the project (Alloy or Classic) has no canonical `purgetss/brand/logo.{svg,png}`, the confirmed in-place run **moves** that positional `.svg`/`.png` to `purgetss/brand/logo.<ext>` and reports the destination; `--dry-run` only reports where it would go. An existing canonical logo is never replaced, and the positional source is then used from where it is.
|
|
68
67
|
|
|
69
68
|
## The `purgetss/brand/` convention
|
|
70
69
|
|
|
@@ -121,6 +120,8 @@ You can also pass a path directly or point to a logo from the config. Useful whe
|
|
|
121
120
|
purgetss brand ./docs/snap-logo.svg
|
|
122
121
|
```
|
|
123
122
|
|
|
123
|
+
A positional logo is moved into `purgetss/brand/logo.<ext>` when no canonical logo exists yet (see [Quick start](#quick-start)). To keep a master in `docs/`, point to it from the config instead, or use a `--<piece>-logo` flag.
|
|
124
|
+
|
|
124
125
|
Or in `purgetss/config.cjs`, where each piece takes its own `logo`:
|
|
125
126
|
|
|
126
127
|
```javascript
|
|
@@ -236,7 +237,7 @@ And these live at the top level:
|
|
|
236
237
|
|
|
237
238
|
| Key | Default | Purpose |
|
|
238
239
|
| --- | --- | --- |
|
|
239
|
-
| `background` | `'#FFFFFF'` | The background every piece inherits unless it declares its own: the Android adaptive background layer, the `DefaultIcon-ios.png` flatten, the splash canvases, and the marketplace flatten
|
|
240
|
+
| `background` | `'#FFFFFF'` | The background every piece inherits unless it declares its own: the Android adaptive background layer, the `DefaultIcon-ios.png` flatten, the splash canvases, and the marketplace flatten. |
|
|
240
241
|
| `artworkCornerRadius` | `'0%'` | Shared radius for the four supported non-icon artwork pieces. It never changes store or launcher icons. |
|
|
241
242
|
| `splashCornerRadius` | — | Optional splash-only override for `iosSplash` and `androidSplash`. |
|
|
242
243
|
| `confirmOverwrites` | `true` | Whether `brand` asks before overwriting project files in place. |
|
|
@@ -304,7 +305,7 @@ The output is automatically routed to the right directory for your project layou
|
|
|
304
305
|
|
|
305
306
|
```text
|
|
306
307
|
<project>/
|
|
307
|
-
├── DefaultIcon.png ← 1024×1024, universal fallback (brand.icon.padding)
|
|
308
|
+
├── DefaultIcon.png ← 1024×1024, universal fallback, opaque (brand.icon.padding)
|
|
308
309
|
├── DefaultIcon-ios.png ← 1024×1024, iOS flattened on brand.background
|
|
309
310
|
├── DefaultIcon-Dark.png ← 1024×1024, iOS 18+ dark (transparent per Apple HIG)
|
|
310
311
|
├── DefaultIcon-Tinted.png ← 1024×1024, iOS 18+ tinted (grayscale on black)
|
|
@@ -531,7 +532,7 @@ The second one colors the notification's accent, not the icon. Create or merge `
|
|
|
531
532
|
|
|
532
533
|
Titanium builds `LaunchLogo.imageset` itself on every iOS build, resizing one source into the five sizes it needs. It looks for `LaunchLogo.png` first and falls back to `DefaultIcon.png`.
|
|
533
534
|
|
|
534
|
-
So there is nothing for PurgeTSS to generate there, but there is something to choose. With only `DefaultIcon.png` around, the launch screen shows your app icon
|
|
535
|
+
So there is nothing for PurgeTSS to generate there, but there is something to choose. With only `DefaultIcon.png` around, the launch screen shows your app icon with its configured icon inset (`0%` by default). Dropping a `logo-launch.svg` (or `.png`) into `purgetss/brand/` makes `brand` write a `LaunchLogo.png`, and the launch screen shows the full logotype instead:
|
|
535
536
|
|
|
536
537
|
```bash
|
|
537
538
|
cp docs/my-wordmark.svg purgetss/brand/logo-launch.svg
|
|
@@ -580,7 +581,7 @@ purgetss brand --no-dark --no-tinted
|
|
|
580
581
|
> Upstream work in progress
|
|
581
582
|
> As of April 2026, Titanium SDK picks up `DefaultIcon-ios.png` automatically but does **not** yet wire `DefaultIcon-Dark.png` / `DefaultIcon-Tinted.png` into the generated iOS appiconset. Upstream tracking: [tidev/titanium-sdk#14122](https://github.com/tidev/titanium-sdk/issues/14122).
|
|
582
583
|
>
|
|
583
|
-
> Until that
|
|
584
|
+
> Until that issue is resolved, after your first iOS build you may need to add the two PNGs manually into `build/iphone/Assets.xcassets/AppIcon.appiconset/` in Xcode (via the "Appearance" column in the asset catalog editor). Once #14122 is resolved, the command becomes fully end-to-end.
|
|
584
585
|
|
|
585
586
|
## Brand color
|
|
586
587
|
|
|
@@ -598,7 +599,7 @@ purgetss brand --bg-color "#0B1326"
|
|
|
598
599
|
|
|
599
600
|
Any piece can opt out with its own `background`. That is what `dark: { background: null }` does in the default config, which keeps `DefaultIcon-Dark.png` transparent per Apple HIG.
|
|
600
601
|
|
|
601
|
-
If you never pass the flag, background stays `#FFFFFF`. `iTunesConnect.png
|
|
602
|
+
If you never pass the flag, background stays `#FFFFFF`. `iTunesConnect.png`, `MarketplaceArtwork.png` and `MarketplaceArtworkFeature.png` are always flattened to opaque output on the resolved background.
|
|
602
603
|
|
|
603
604
|
### Matching the launch background
|
|
604
605
|
|
|
@@ -606,93 +607,9 @@ If you never pass the flag, background stays `#FFFFFF`. `iTunesConnect.png` and
|
|
|
606
607
|
|
|
607
608
|
`purgetss brand --notes` prints that setup with the project's current `brand.background` already filled in.
|
|
608
609
|
|
|
610
|
+
## Padding and geometry
|
|
609
611
|
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
Padding belongs to the piece, not to the project. Each piece has its own key and its own flag:
|
|
613
|
-
|
|
614
|
-
| Piece | Config | Flag | Default |
|
|
615
|
-
| --- | --- | --- | --- |
|
|
616
|
-
| `adaptive` | `brand.adaptive.padding` | `--android-adaptive-padding` | `18%` |
|
|
617
|
-
| `legacy-icon` | `brand.legacyIcon.padding` | `--android-legacy-padding` | `10%` |
|
|
618
|
-
| `appicon` | `brand.appicon.padding` | `--appicon-padding` | `10%` |
|
|
619
|
-
| `icon` | `brand.icon.padding` | `--ios-padding` | `0%` |
|
|
620
|
-
| `feature-graphic` | `brand.featureGraphic.padding` | `--feature-graphic-padding` | `12%` |
|
|
621
|
-
| `launch-logo` | `brand.launchLogo.padding` | `--launch-logo-padding` | `12%` |
|
|
622
|
-
| `android-splash` | `brand.androidSplash.padding` | `--android-splash-padding` | `26%` |
|
|
623
|
-
| `ios-splash` | `brand.iosSplash.padding` | `--ios-splash-padding` | `26%` |
|
|
624
|
-
|
|
625
|
-
`--padding` is a shortcut for the two Android launcher paddings in a single run, and `--splash-padding` for the two splash paddings. `--ios-padding` moves the four square iOS/marketplace pieces together (`icon`, `dark`, `tinted`, `marketplace`); in config each of them has its own key.
|
|
626
|
-
|
|
627
|
-
There is deliberately **no global padding value that cascades down**. The defaults answer to different constraints: `18%` answers to the Android launcher mask, while finished square iOS/store artwork stays full-bleed at `0%`. One inherited number could silently break the launcher mask or add an unwanted frame to finished artwork. `background`, which has no such trap, is inherited from `brand.background`.
|
|
628
|
-
|
|
629
|
-
### How the source is read, and how sharp the output is
|
|
630
|
-
|
|
631
|
-
Two things are worth knowing about what happens to your `logo.svg` or `logo.png` before any padding is applied.
|
|
632
|
-
|
|
633
|
-
**The container is what counts, not the artwork's bounding box.** An SVG is read at its `viewBox`, a raster at its full canvas, and neither is trimmed to where the pixels actually are. So whatever margin a designer baked into the file **adds** to the padding configured per piece. A round logo exported inside a 2048×2048 PNG with 25% of its own air, generated at `adaptive: { padding: '18%' }`, ends up covering about 32% of the icon canvas, not 64%. If a mark comes out smaller than the numbers suggest, that is almost always why: crop the source or lower the padding.
|
|
634
|
-
|
|
635
|
-
**The masters are sized to the run.** The source is rasterized once into two intermediate masters, and every piece scales down from them, so their resolution is the ceiling on output sharpness. Rather than a fixed size, `brand` measures the largest number of pixels any selected piece will ask for and builds the masters at exactly that. A default run reports it:
|
|
636
|
-
|
|
637
|
-
```text
|
|
638
|
-
• Masters at 942 px — the largest any selected piece asks for
|
|
639
|
-
```
|
|
640
|
-
|
|
641
|
-
Lower a padding and the figure rises with it (`--splash-padding 4` needs 1413 px), so output never goes soft against a fixed ceiling. Every destination is a reduction, never an upscale.
|
|
642
|
-
|
|
643
|
-
The one case this cannot fix is a raster source that is simply too small: a 512-px PNG cannot produce a sharp 942-px icon. Prefer SVG, or a PNG of at least 1024×1024.
|
|
644
|
-
|
|
645
|
-
### Splash padding
|
|
646
|
-
|
|
647
|
-
The 28 splash images (`default.png`, the 11 `res-*`, and the 16 iPhone launch images) share one rule: the logo is fitted into a square whose side is a share of the canvas's **shorter** side.
|
|
648
|
-
|
|
649
|
-
Measuring against the shorter side is what lets a single number work across canvases as different as 1440×2560 and 800×480: at 800×480 the limit comes from the height, at 240×400 from the width, and the logo keeps the same visual weight in portrait and in landscape.
|
|
650
|
-
|
|
651
|
-
| `androidSplash.padding` / `iosSplash.padding` | Logo | `default.png` (1440×2560) | `res-notlong-port-mdpi` (320×480) |
|
|
652
|
-
| --- | --- | --- | --- |
|
|
653
|
-
| `20%` | 60% of the shorter side | 864 px | 192 px |
|
|
654
|
-
| `26%` (default) | 48% | 691 px | 153 px |
|
|
655
|
-
| `30%` | 40% | 576 px | 128 px |
|
|
656
|
-
| `35%` | 30% | 432 px | 96 px |
|
|
657
|
-
|
|
658
|
-
The `26%` default is calibrated against the Titanium template itself: the Alloy logo in the stock `default.png` measures 665×488 px on a 1440×2560 canvas, so `26%` lands within 4% of the size Titanium ships.
|
|
659
|
-
|
|
660
|
-
Before v7.13.0 none of this was configurable: `default.png` used a hardcoded box of 72% × 26% of its own canvas, and the `res-*` set a separate hardcoded 60%. Two rules for the same piece, neither adjustable.
|
|
661
|
-
|
|
662
|
-
## Rounded non-icon artwork
|
|
663
|
-
|
|
664
|
-
`brand.artworkCornerRadius` rounds artwork only in the 16 iPhone launch images, Android `default.png` plus its 11 qualifier variants, `MarketplaceArtworkFeature.png`, and `LaunchLogo.png`. A piece may override it with `cornerRadius`; `brand.splashCornerRadius` is an optional shared override for the two legacy splash pieces.
|
|
665
|
-
|
|
666
|
-
Values are integer numbers or percentage strings from `0` through `50`, measured against the shorter side of the resized artwork. `0%` preserves the previous output byte for byte; `50%` makes square artwork circular and a wordmark capsule-shaped. Normal and `--dry-run` summaries report the effective padding and radius.
|
|
667
|
-
|
|
668
|
-
Precedence is:
|
|
669
|
-
|
|
670
|
-
- Feature Graphic / LaunchLogo: piece-specific flag → `--artwork-corner-radius` → piece config → `brand.artworkCornerRadius` → `0%`.
|
|
671
|
-
- Legacy splashes: platform flag → `--splash-corner-radius` → `--artwork-corner-radius` → piece config → `brand.splashCornerRadius` → `brand.artworkCornerRadius` → `0%`.
|
|
672
|
-
|
|
673
|
-
Store and launcher icons remain unmasked for platform processing. `cornerRadius` is rejected in `DefaultIcon*`, `iTunesConnect.png`, `MarketplaceArtwork.png`, adaptive, legacy, and app icons, Android 12+ `splash_icon.png`, notification icons, and any other unsupported piece; invalid, fractional, negative, non-numeric, or greater-than-50 values also abort before files are written.
|
|
674
|
-
|
|
675
|
-
### Adaptive icon padding
|
|
676
|
-
|
|
677
|
-
Android's adaptive canvas is 108 dp. The mask leaves roughly 72 dp visible, and the **guaranteed** safe area is a 66 dp circle inscribed in it. What each padding means in those terms:
|
|
678
|
-
|
|
679
|
-
| Padding | Logo | vs. the 66 dp safe circle | vs. the ~72 dp the mask shows |
|
|
680
|
-
| --- | --- | --- | --- |
|
|
681
|
-
| `15%` | 75.6 dp | outside | **outside** — clipped on any launcher |
|
|
682
|
-
| `16%` | 73.4 dp | outside | **outside** |
|
|
683
|
-
| `18%` | 69.1 dp | corners outside | inside — **the default** |
|
|
684
|
-
| `19.44%` | 66.0 dp | exactly on it | inside |
|
|
685
|
-
| `20%` | 64.8 dp | inside | inside — most conservative |
|
|
686
|
-
|
|
687
|
-
`18%` sits between the guaranteed circle and the mask edge: a logo that carries its own margin never reaches those corners, which is why it is a safe default in practice. Drop to `20%` if your mark runs edge to edge and you see clipping on a circular launcher.
|
|
688
|
-
|
|
689
|
-
A useful visual check is the "corners" heuristic: imagine a circle inscribed in your 1024×1024 canvas with the given padding. If your logo's outermost corners fit inside that circle, you're safe on circular launchers (Pixel default, Oppo Android 15). If they poke out, they'll be clipped.
|
|
690
|
-
|
|
691
|
-
The official Android spec floor is `19.44%` (108dp canvas, 66dp inscribed safe-zone circle). That is the theoretical worst-case for aggressive adaptive masks, which is why the adaptive default sits close to it.
|
|
692
|
-
|
|
693
|
-
### Legacy icon padding
|
|
694
|
-
|
|
695
|
-
Legacy `ic_launcher.png` does not go through the same adaptive mask, so it can usually run tighter. That is why the default for `brand.legacyIcon.padding` is `10%`.
|
|
612
|
+
Per-piece padding, how the source is read, the shared splash sizing rule, rounded non-icon artwork and the adaptive-mask math are in [Brand Padding & Geometry](./brand-padding-geometry.md).
|
|
696
613
|
|
|
697
614
|
## Cleanup legacy branding artifacts
|
|
698
615
|
|
|
@@ -765,6 +682,28 @@ Adaptive padding is probably too generous. Lower it:
|
|
|
765
682
|
purgetss brand --android-adaptive-padding 17
|
|
766
683
|
```
|
|
767
684
|
|
|
685
|
+
### A white frame appears around a dark icon
|
|
686
|
+
|
|
687
|
+
PurgeTSS does not require a white frame. Square iOS/store pieces (`icon`, `dark`, `tinted`, `marketplace`) default to `0%` since v7.14.0, so finished edge-to-edge artwork stays full-bleed. If an older or customized config still has `brand.icon.padding: '4%'`, change it to `0%` and regenerate.
|
|
688
|
+
|
|
689
|
+
Android launcher pieces keep safe-zone padding on purpose (`18%` adaptive, `10%` legacy and appicon). If the source is already a finished opaque icon, that inset exposes `brand.background`. Set the inherited background once to a color matching the artwork's perimeter, or give the Android pieces a transparent mark instead of the finished icon canvas:
|
|
690
|
+
|
|
691
|
+
```javascript
|
|
692
|
+
brand: {
|
|
693
|
+
background: '#020109',
|
|
694
|
+
icon: { padding: '0%' },
|
|
695
|
+
adaptive: { logo: './purgetss/brand/logo-adaptive.png', padding: '18%' },
|
|
696
|
+
legacyIcon: { padding: '10%' },
|
|
697
|
+
appicon: { padding: '10%' }
|
|
698
|
+
}
|
|
699
|
+
```
|
|
700
|
+
|
|
701
|
+
When the main logo is opaque to its edges and a padded piece sits on a contrasting background, `brand` warns before generating the pieces (it checks `icon`, `marketplace`, `adaptive`, `legacy-icon` and `appicon`): `The source is opaque to its edges (edge color ≈ #…)` followed by `A contrasting frame will be visible in: …`, naming each affected piece with its padding and background. Pieces with their own `logo` are not checked.
|
|
702
|
+
|
|
703
|
+
### "The source logo is not close to square"
|
|
704
|
+
|
|
705
|
+
`brand` prints this warning when the main logo's aspect ratio is wider than 1.25:1 or taller than 1:1.25. Launcher icons and the Android 12+ system splash center the mark inside a mask, so a wordmark comes out cramped. Drop a square `logo-adaptive.svg` (and `logo-splash-icon.svg` if you use `--splash-icon`) as described in [Community-Discovered Patterns](#community-discovered-patterns).
|
|
706
|
+
|
|
768
707
|
### The monochrome version looks like a white blob
|
|
769
708
|
|
|
770
709
|
Your colored logo likely has multi-color detail that does not survive automatic whitening. Provide a dedicated silhouette:
|
|
@@ -784,7 +723,7 @@ Apple requires App Store icons to have no alpha channel. `DefaultIcon-ios.png` i
|
|
|
784
723
|
|
|
785
724
|
### The dark variant doesn't show on my iPhone
|
|
786
725
|
|
|
787
|
-
Dark variants require iOS 18+ and Titanium SDK automatic wiring (tracked upstream in [titanium-sdk#14122](https://github.com/tidev/titanium-sdk/issues/14122)). Until that
|
|
726
|
+
Dark variants require iOS 18+ and Titanium SDK automatic wiring (tracked upstream in [titanium-sdk#14122](https://github.com/tidev/titanium-sdk/issues/14122)). Until that issue is resolved, you may need to add `DefaultIcon-Dark.png` and `DefaultIcon-Tinted.png` manually into the Xcode appiconset after the first iOS build.
|
|
788
727
|
|
|
789
728
|
### I get "Input image exceeds pixel limit" on an SVG from Affinity / Illustrator
|
|
790
729
|
|