Skip to content

Commit f800fc4

Browse files
bfoss765claude
andcommitted
fix: shortcut bar height and layout to match Figma design
- Fix bar being too tall on fresh install by removing hasHomeIndicator dependency from cellSize() — safeAreaInsets aren't set on first launch - Fix Spend button clipped on iPhone 12 Pro Max by reducing margins (16→10px) and spacing (8→4px) - Update cell layout: remove 6px top padding, icon placeholder 30→36px - Change font from caption2 to 12px medium weight per Figma spec - Update corner radius from 8 to 16px - Replace PNG shortcut icons with SVG from Figma design - Update CLAUDE.md with Figma SVG iOS compatibility documentation - Bump version to 8.5.5 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 4b1cf20 commit f800fc4

50 files changed

Lines changed: 228 additions & 317 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CLAUDE.md

Lines changed: 119 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,116 @@ The shortcut bar displays different button combinations based on wallet state:
540540
4. Implement action handler in `HomeViewController+Shortcuts.swift`
541541
5. Update `reloadShortcuts()` logic if needed
542542

543+
### Figma MCP Asset Download Workflow (MANDATORY)
544+
545+
#### Overview
546+
The Figma MCP server exposes image assets via temporary localhost URLs (e.g., `http://localhost:3845/assets/{hash}.svg`). These URLs are **ephemeral** — they only exist while Figma Desktop is running and the MCP server is active. **Image files MUST be downloaded and saved to the project's asset catalog** so they can be committed to git and verified in the UI.
547+
548+
#### ⚠️ CRITICAL: Always Download Assets During Development
549+
When implementing UI from Figma designs, you MUST:
550+
1. **Download every image asset** referenced in the design context to a local file
551+
2. **Save it to the correct asset catalog location** in the project
552+
3. **Verify the asset displays correctly** in the running app before committing
553+
4. **Never reference localhost URLs in code** — they are only a transport mechanism
554+
555+
#### Step-by-Step Asset Download Process
556+
557+
**Step 1: Get design context from Figma MCP**
558+
Use `get_design_context` to retrieve the design. Image URLs appear as constants:
559+
```javascript
560+
const imgMayaLogo = "http://localhost:3845/assets/4b039921e0c1cdbe2b8ca56814e78264985c97a0.svg";
561+
```
562+
563+
**Step 2: Download each image asset**
564+
```bash
565+
# Download SVG asset from Figma MCP server
566+
curl -s -o /path/to/project/DashWallet/Resources/AppAssets.xcassets/IconName.imageset/icon.svg \
567+
"http://localhost:3845/assets/{hash}.svg"
568+
569+
# Download PNG asset if needed
570+
curl -s -o /path/to/project/DashWallet/Resources/AppAssets.xcassets/IconName.imageset/icon.png \
571+
"http://localhost:3845/assets/{hash}.png"
572+
```
573+
574+
**Step 3: Create or update Contents.json**
575+
```json
576+
{
577+
"images" : [
578+
{
579+
"filename" : "icon.svg",
580+
"idiom" : "universal"
581+
}
582+
],
583+
"info" : {
584+
"author" : "xcode",
585+
"version" : 1
586+
},
587+
"properties" : {
588+
"preserves-vector-representation" : true,
589+
"template-rendering-intent" : "template"
590+
}
591+
}
592+
```
593+
594+
**Step 4: Verify the asset in the running app**
595+
- Build and run the app in Simulator
596+
- Navigate to the screen that uses the asset
597+
- Confirm the icon/image renders correctly (right icon, right color, right size)
598+
- Only after visual verification should the asset be staged for commit
599+
600+
**Step 5: Verify the file is valid before committing**
601+
```bash
602+
# Confirm file type
603+
file /path/to/imageset/icon.svg
604+
# Expected: SVG Scalable Vector Graphics image
605+
606+
# Confirm non-zero file size
607+
ls -la /path/to/imageset/icon.svg
608+
```
609+
610+
#### Batch Download Pattern
611+
When a design has multiple assets, download them all at once:
612+
```bash
613+
# Example: Download all assets for a new screen
614+
curl -s -o asset1.svg "http://localhost:3845/assets/{hash1}.svg"
615+
curl -s -o asset2.svg "http://localhost:3845/assets/{hash2}.svg"
616+
curl -s -o asset3.svg "http://localhost:3845/assets/{hash3}.svg"
617+
```
618+
619+
#### Important Notes
620+
- **Localhost URLs expire** when Figma Desktop closes or the MCP server stops
621+
- **Always download immediately** when you get design context — don't defer downloads
622+
- **SVG preferred over PNG** — SVGs scale perfectly and have smaller file sizes
623+
- **Verify before committing** — wrong or placeholder assets are a common source of UI bugs
624+
- **Asset catalog structure**: Each image needs its own `.imageset` folder with a `Contents.json`
625+
626+
#### ⚠️ CRITICAL: Clean SVGs for iOS Compatibility
627+
Figma MCP exports SVGs with **web-specific features that iOS cannot render**. You MUST clean every SVG after downloading:
628+
629+
| Figma SVG Feature | iOS Problem | Fix |
630+
|---|---|---|
631+
| `fill="var(--fill-0, #78C4F5)"` | CSS custom properties not supported — paths render invisible | Replace with plain hex: `fill="#78C4F5"` |
632+
| `width="100%" height="100%"` | iOS needs explicit pixel dimensions | Use viewBox dimensions: `width="36" height="36"` |
633+
| `preserveAspectRatio="none"` | Web-specific, causes rendering issues | Remove attribute |
634+
| `style="display: block;"` | Web-specific inline style | Remove attribute |
635+
| `overflow="visible"` | Web-specific | Remove attribute |
636+
637+
**Example cleanup:**
638+
```xml
639+
<!-- ❌ RAW from Figma MCP — will NOT render on iOS -->
640+
<svg preserveAspectRatio="none" width="100%" height="100%" overflow="visible"
641+
style="display: block;" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
642+
<path d="M18 0C8.06..." fill="var(--fill-0, #78C4F5)"/>
643+
</svg>
644+
645+
<!-- ✅ CLEANED for iOS asset catalog -->
646+
<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
647+
<path d="M18 0C8.06..." fill="#78C4F5"/>
648+
</svg>
649+
```
650+
651+
**If icons appear blank after adding SVGs**, the first thing to check is whether the SVG contains `var(--fill-0, ...)` or `width="100%"`.
652+
543653
### Icon Implementation Best Practices
544654

545655
#### When Updating Icons from Figma
@@ -549,14 +659,19 @@ The shortcut bar displays different button combinations based on wallet state:
549659
find /path/to/project -name "*.svg" -o -name "*.png" | grep -i "icon_name"
550660
```
551661

552-
2. **Use SVG directly from Figma** - Don't convert to PNG unnecessarily
553-
- Download SVG from Figma localhost server
662+
2. **Download SVG directly from Figma MCP** - Don't convert to PNG unnecessarily
663+
```bash
664+
# Download from Figma MCP localhost server and save to asset catalog
665+
curl -s -o /path/to/imageset/icon.svg "http://localhost:3845/assets/{hash}.svg"
666+
```
554667
- Save directly to appropriate imageset folder
555-
- Update Contents.json to reference SVG
668+
- Update Contents.json to reference the SVG filename
669+
- Verify the downloaded file is valid: `file /path/to/icon.svg`
556670

557-
3. **Verify icon usage** - Always test that the correct icon appears
671+
3. **Verify icon in running app** - Always build and visually confirm the correct icon appears
558672
- Wrong icons often indicate using placeholder or copied assets
559673
- Check that imageset name matches the one referenced in code
674+
- Run the app and navigate to the relevant screen before considering the task complete
560675

561676
4. **Clean up old assets** - Remove unused PNG files when replacing with SVG
562677
```bash

DashWallet.xcodeproj/project.pbxproj

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10483,7 +10483,7 @@
1048310483
"$(inherited)",
1048410484
"@executable_path/Frameworks",
1048510485
);
10486-
MARKETING_VERSION = 8.5.3;
10486+
MARKETING_VERSION = 8.5.5;
1048710487
OTHER_LDFLAGS = (
1048810488
"$(inherited)",
1048910489
"-ObjC",
@@ -10624,7 +10624,7 @@
1062410624
"$(inherited)",
1062510625
"@executable_path/Frameworks",
1062610626
);
10627-
MARKETING_VERSION = 8.5.3;
10627+
MARKETING_VERSION = 8.5.5;
1062810628
OTHER_LDFLAGS = (
1062910629
"$(inherited)",
1063010630
"-ObjC",
@@ -10799,7 +10799,7 @@
1079910799
EXCLUDED_ARCHS = "";
1080010800
IBSC_MODULE = WatchApp_Extension;
1080110801
INFOPLIST_FILE = WatchApp/Info.plist;
10802-
MARKETING_VERSION = 8.5.3;
10802+
MARKETING_VERSION = 8.5.5;
1080310803
PRODUCT_BUNDLE_IDENTIFIER = org.dashfoundation.dash.watchkitapp;
1080410804
PRODUCT_NAME = "$(TARGET_NAME)";
1080510805
SDKROOT = watchos;
@@ -10821,7 +10821,7 @@
1082110821
EXCLUDED_ARCHS = "";
1082210822
IBSC_MODULE = WatchApp_Extension;
1082310823
INFOPLIST_FILE = WatchApp/Info.plist;
10824-
MARKETING_VERSION = 8.5.3;
10824+
MARKETING_VERSION = 8.5.5;
1082510825
PRODUCT_BUNDLE_IDENTIFIER = org.dashfoundation.dash.watchkitapp;
1082610826
PRODUCT_NAME = "$(TARGET_NAME)";
1082710827
SDKROOT = watchos;
@@ -10846,7 +10846,7 @@
1084610846
"@executable_path/Frameworks",
1084710847
"@executable_path/../../Frameworks",
1084810848
);
10849-
MARKETING_VERSION = 8.5.3;
10849+
MARKETING_VERSION = 8.5.5;
1085010850
PRODUCT_BUNDLE_IDENTIFIER = org.dashfoundation.dash.watchkitapp.watchkitextension;
1085110851
PRODUCT_NAME = "${TARGET_NAME}";
1085210852
SDKROOT = watchos;
@@ -10873,7 +10873,7 @@
1087310873
"@executable_path/Frameworks",
1087410874
"@executable_path/../../Frameworks",
1087510875
);
10876-
MARKETING_VERSION = 8.5.3;
10876+
MARKETING_VERSION = 8.5.5;
1087710877
PRODUCT_BUNDLE_IDENTIFIER = org.dashfoundation.dash.watchkitapp.watchkitextension;
1087810878
PRODUCT_NAME = "${TARGET_NAME}";
1087910879
SDKROOT = watchos;
@@ -10905,7 +10905,7 @@
1090510905
"@executable_path/Frameworks",
1090610906
"@executable_path/../../Frameworks",
1090710907
);
10908-
MARKETING_VERSION = 8.5.3;
10908+
MARKETING_VERSION = 8.5.5;
1090910909
PRODUCT_BUNDLE_IDENTIFIER = org.dashfoundation.dash.TodayExtension;
1091010910
PRODUCT_NAME = "$(TARGET_NAME)";
1091110911
SKIP_INSTALL = YES;
@@ -10934,7 +10934,7 @@
1093410934
"@executable_path/Frameworks",
1093510935
"@executable_path/../../Frameworks",
1093610936
);
10937-
MARKETING_VERSION = 8.5.3;
10937+
MARKETING_VERSION = 8.5.5;
1093810938
PRODUCT_BUNDLE_IDENTIFIER = org.dashfoundation.dash.TodayExtension;
1093910939
PRODUCT_NAME = "$(TARGET_NAME)";
1094010940
SKIP_INSTALL = YES;
@@ -10984,7 +10984,7 @@
1098410984
"$(inherited)",
1098510985
"@executable_path/Frameworks",
1098610986
);
10987-
MARKETING_VERSION = 8.5.3;
10987+
MARKETING_VERSION = 8.5.5;
1098810988
OTHER_LDFLAGS = (
1098910989
"$(inherited)",
1099010990
"-ObjC",
@@ -11119,7 +11119,7 @@
1111911119
"$(inherited)",
1112011120
"@executable_path/Frameworks",
1112111121
);
11122-
MARKETING_VERSION = 8.5.3;
11122+
MARKETING_VERSION = 8.5.5;
1112311123
OTHER_LDFLAGS = (
1112411124
"$(inherited)",
1112511125
"-ObjC",
@@ -11265,7 +11265,7 @@
1126511265
"$(inherited)",
1126611266
"@executable_path/Frameworks",
1126711267
);
11268-
MARKETING_VERSION = 8.5.3;
11268+
MARKETING_VERSION = 8.5.5;
1126911269
OTHER_LDFLAGS = (
1127011270
"$(inherited)",
1127111271
"-ObjC",
@@ -11409,7 +11409,7 @@
1140911409
"$(inherited)",
1141011410
"@executable_path/Frameworks",
1141111411
);
11412-
MARKETING_VERSION = 8.5.3;
11412+
MARKETING_VERSION = 8.5.5;
1141311413
OTHER_LDFLAGS = (
1141411414
"$(inherited)",
1141511415
"-ObjC",
@@ -11613,7 +11613,7 @@
1161311613
"$(inherited)",
1161411614
"@executable_path/Frameworks",
1161511615
);
11616-
MARKETING_VERSION = 8.5.3;
11616+
MARKETING_VERSION = 8.5.5;
1161711617
OTHER_LDFLAGS = (
1161811618
"$(inherited)",
1161911619
"-ObjC",
@@ -11727,7 +11727,7 @@
1172711727
"@executable_path/Frameworks",
1172811728
"@executable_path/../../Frameworks",
1172911729
);
11730-
MARKETING_VERSION = 8.5.3;
11730+
MARKETING_VERSION = 8.5.5;
1173111731
PRODUCT_BUNDLE_IDENTIFIER = org.dashfoundation.dash.TodayExtension;
1173211732
PRODUCT_NAME = "$(TARGET_NAME)";
1173311733
SKIP_INSTALL = YES;
@@ -11783,7 +11783,7 @@
1178311783
EXCLUDED_ARCHS = "";
1178411784
IBSC_MODULE = WatchApp_Extension;
1178511785
INFOPLIST_FILE = WatchApp/Info.plist;
11786-
MARKETING_VERSION = 8.5.3;
11786+
MARKETING_VERSION = 8.5.5;
1178711787
PRODUCT_BUNDLE_IDENTIFIER = org.dashfoundation.dash.watchkitapp;
1178811788
PRODUCT_NAME = "$(TARGET_NAME)";
1178911789
SDKROOT = watchos;
@@ -11808,7 +11808,7 @@
1180811808
"@executable_path/Frameworks",
1180911809
"@executable_path/../../Frameworks",
1181011810
);
11811-
MARKETING_VERSION = 8.5.3;
11811+
MARKETING_VERSION = 8.5.5;
1181211812
PRODUCT_BUNDLE_IDENTIFIER = org.dashfoundation.dash.watchkitapp.watchkitextension;
1181311813
PRODUCT_NAME = "${TARGET_NAME}";
1181411814
SDKROOT = watchos;
@@ -11925,7 +11925,7 @@
1192511925
"$(inherited)",
1192611926
"@executable_path/Frameworks",
1192711927
);
11928-
MARKETING_VERSION = 8.5.3;
11928+
MARKETING_VERSION = 8.5.5;
1192911929
OTHER_LDFLAGS = (
1193011930
"$(inherited)",
1193111931
"-ObjC",
@@ -12038,7 +12038,7 @@
1203812038
"@executable_path/Frameworks",
1203912039
"@executable_path/../../Frameworks",
1204012040
);
12041-
MARKETING_VERSION = 8.5.3;
12041+
MARKETING_VERSION = 8.5.5;
1204212042
PRODUCT_BUNDLE_IDENTIFIER = org.dashfoundation.dash.TodayExtension;
1204312043
PRODUCT_NAME = "$(TARGET_NAME)";
1204412044
SKIP_INSTALL = YES;
@@ -12093,7 +12093,7 @@
1209312093
EXCLUDED_ARCHS = "";
1209412094
IBSC_MODULE = WatchApp_Extension;
1209512095
INFOPLIST_FILE = WatchApp/Info.plist;
12096-
MARKETING_VERSION = 8.5.3;
12096+
MARKETING_VERSION = 8.5.5;
1209712097
PRODUCT_BUNDLE_IDENTIFIER = org.dashfoundation.dash.watchkitapp;
1209812098
PRODUCT_NAME = "$(TARGET_NAME)";
1209912099
SDKROOT = watchos;
@@ -12118,7 +12118,7 @@
1211812118
"@executable_path/Frameworks",
1211912119
"@executable_path/../../Frameworks",
1212012120
);
12121-
MARKETING_VERSION = 8.5.3;
12121+
MARKETING_VERSION = 8.5.5;
1212212122
PRODUCT_BUNDLE_IDENTIFIER = org.dashfoundation.dash.watchkitapp.watchkitextension;
1212312123
PRODUCT_NAME = "${TARGET_NAME}";
1212412124
SDKROOT = watchos;
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Lines changed: 6 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,16 @@
11
{
22
"images" : [
33
{
4-
"filename" : "Buy & Sell.png",
5-
"idiom" : "universal",
6-
"scale" : "1x"
7-
},
8-
{
9-
"appearances" : [
10-
{
11-
"appearance" : "luminosity",
12-
"value" : "dark"
13-
}
14-
],
15-
"filename" : "Buy & Sell 1.png",
16-
"idiom" : "universal",
17-
"scale" : "1x"
18-
},
19-
{
20-
"filename" : "Buy & Sell@2x.png",
21-
"idiom" : "universal",
22-
"scale" : "2x"
23-
},
24-
{
25-
"appearances" : [
26-
{
27-
"appearance" : "luminosity",
28-
"value" : "dark"
29-
}
30-
],
31-
"filename" : "Buy & Sell@2x 1.png",
32-
"idiom" : "universal",
33-
"scale" : "2x"
34-
},
35-
{
36-
"filename" : "Buy & Sell@3x.png",
37-
"idiom" : "universal",
38-
"scale" : "3x"
39-
},
40-
{
41-
"appearances" : [
42-
{
43-
"appearance" : "luminosity",
44-
"value" : "dark"
45-
}
46-
],
47-
"filename" : "Buy & Sell@3x 1.png",
48-
"idiom" : "universal",
49-
"scale" : "3x"
4+
"filename" : "buySell.svg",
5+
"idiom" : "universal"
506
}
517
],
528
"info" : {
539
"author" : "xcode",
5410
"version" : 1
11+
},
12+
"properties" : {
13+
"preserves-vector-representation" : true,
14+
"template-rendering-intent" : "original"
5515
}
5616
}
Lines changed: 4 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)