diff --git a/app.config.js b/app.config.js
index 22787090bb..df5324f13e 100644
--- a/app.config.js
+++ b/app.config.js
@@ -237,6 +237,10 @@ module.exports = function (_config) {
'expo-video',
'expo-localization',
'expo-web-browser',
+ [
+ 'react-native-nano-icons',
+ {iconSets: [{inputDir: './assets/nano-icons/app-icons'}]},
+ ],
[
'react-native-edge-to-edge',
{android: {enforceNavigationBarContrast: false}},
diff --git a/assets/nano-icons/app-icons/arrow-top-right.svg b/assets/nano-icons/app-icons/arrow-top-right.svg
new file mode 100644
index 0000000000..e91825d5f3
--- /dev/null
+++ b/assets/nano-icons/app-icons/arrow-top-right.svg
@@ -0,0 +1 @@
+
diff --git a/assets/nano-icons/app-icons/bell-filled.svg b/assets/nano-icons/app-icons/bell-filled.svg
new file mode 100644
index 0000000000..fe75d77198
--- /dev/null
+++ b/assets/nano-icons/app-icons/bell-filled.svg
@@ -0,0 +1 @@
+
diff --git a/assets/nano-icons/app-icons/bell.svg b/assets/nano-icons/app-icons/bell.svg
new file mode 100644
index 0000000000..69a07f2270
--- /dev/null
+++ b/assets/nano-icons/app-icons/bell.svg
@@ -0,0 +1 @@
+
diff --git a/assets/nano-icons/app-icons/bookmark-filled.svg b/assets/nano-icons/app-icons/bookmark-filled.svg
new file mode 100644
index 0000000000..809970c48d
--- /dev/null
+++ b/assets/nano-icons/app-icons/bookmark-filled.svg
@@ -0,0 +1 @@
+
diff --git a/assets/nano-icons/app-icons/bookmark.svg b/assets/nano-icons/app-icons/bookmark.svg
new file mode 100644
index 0000000000..676174b8cf
--- /dev/null
+++ b/assets/nano-icons/app-icons/bookmark.svg
@@ -0,0 +1 @@
+
diff --git a/assets/nano-icons/app-icons/bubble.svg b/assets/nano-icons/app-icons/bubble.svg
new file mode 100644
index 0000000000..7dd254546e
--- /dev/null
+++ b/assets/nano-icons/app-icons/bubble.svg
@@ -0,0 +1 @@
+
diff --git a/assets/nano-icons/app-icons/circle-check.svg b/assets/nano-icons/app-icons/circle-check.svg
new file mode 100644
index 0000000000..b555a74d6e
--- /dev/null
+++ b/assets/nano-icons/app-icons/circle-check.svg
@@ -0,0 +1 @@
+
diff --git a/assets/nano-icons/app-icons/clock.svg b/assets/nano-icons/app-icons/clock.svg
new file mode 100644
index 0000000000..4ee902bf5a
--- /dev/null
+++ b/assets/nano-icons/app-icons/clock.svg
@@ -0,0 +1 @@
+
diff --git a/assets/nano-icons/app-icons/earth.svg b/assets/nano-icons/app-icons/earth.svg
new file mode 100644
index 0000000000..22f39e3955
--- /dev/null
+++ b/assets/nano-icons/app-icons/earth.svg
@@ -0,0 +1 @@
+
diff --git a/assets/nano-icons/app-icons/heart-filled.svg b/assets/nano-icons/app-icons/heart-filled.svg
new file mode 100644
index 0000000000..a6e0777f05
--- /dev/null
+++ b/assets/nano-icons/app-icons/heart-filled.svg
@@ -0,0 +1 @@
+
diff --git a/assets/nano-icons/app-icons/heart.svg b/assets/nano-icons/app-icons/heart.svg
new file mode 100644
index 0000000000..c11c6dc833
--- /dev/null
+++ b/assets/nano-icons/app-icons/heart.svg
@@ -0,0 +1 @@
+
diff --git a/assets/nano-icons/app-icons/home-filled.svg b/assets/nano-icons/app-icons/home-filled.svg
new file mode 100644
index 0000000000..3d532c294c
--- /dev/null
+++ b/assets/nano-icons/app-icons/home-filled.svg
@@ -0,0 +1 @@
+
diff --git a/assets/nano-icons/app-icons/home.svg b/assets/nano-icons/app-icons/home.svg
new file mode 100644
index 0000000000..917f9fac0f
--- /dev/null
+++ b/assets/nano-icons/app-icons/home.svg
@@ -0,0 +1 @@
+
diff --git a/assets/nano-icons/app-icons/inbox.svg b/assets/nano-icons/app-icons/inbox.svg
new file mode 100644
index 0000000000..461ec3cc82
--- /dev/null
+++ b/assets/nano-icons/app-icons/inbox.svg
@@ -0,0 +1 @@
+
diff --git a/assets/nano-icons/app-icons/menu.svg b/assets/nano-icons/app-icons/menu.svg
new file mode 100644
index 0000000000..71a1ec0fc9
--- /dev/null
+++ b/assets/nano-icons/app-icons/menu.svg
@@ -0,0 +1 @@
+
diff --git a/assets/nano-icons/app-icons/message-filled.svg b/assets/nano-icons/app-icons/message-filled.svg
new file mode 100644
index 0000000000..2b355bb2ac
--- /dev/null
+++ b/assets/nano-icons/app-icons/message-filled.svg
@@ -0,0 +1 @@
+
diff --git a/assets/nano-icons/app-icons/message.svg b/assets/nano-icons/app-icons/message.svg
new file mode 100644
index 0000000000..41efcbd4fb
--- /dev/null
+++ b/assets/nano-icons/app-icons/message.svg
@@ -0,0 +1 @@
+
diff --git a/assets/nano-icons/app-icons/mute.svg b/assets/nano-icons/app-icons/mute.svg
new file mode 100644
index 0000000000..90262ea7d9
--- /dev/null
+++ b/assets/nano-icons/app-icons/mute.svg
@@ -0,0 +1 @@
+
diff --git a/assets/nano-icons/app-icons/pause.svg b/assets/nano-icons/app-icons/pause.svg
new file mode 100644
index 0000000000..e88ade5c07
--- /dev/null
+++ b/assets/nano-icons/app-icons/pause.svg
@@ -0,0 +1 @@
+
diff --git a/assets/nano-icons/app-icons/pin.svg b/assets/nano-icons/app-icons/pin.svg
new file mode 100644
index 0000000000..d1de5f2cdf
--- /dev/null
+++ b/assets/nano-icons/app-icons/pin.svg
@@ -0,0 +1 @@
+
diff --git a/assets/nano-icons/app-icons/play.svg b/assets/nano-icons/app-icons/play.svg
new file mode 100644
index 0000000000..239f4f8e77
--- /dev/null
+++ b/assets/nano-icons/app-icons/play.svg
@@ -0,0 +1 @@
+
diff --git a/assets/nano-icons/app-icons/reply.svg b/assets/nano-icons/app-icons/reply.svg
new file mode 100644
index 0000000000..c0397689b9
--- /dev/null
+++ b/assets/nano-icons/app-icons/reply.svg
@@ -0,0 +1 @@
+
diff --git a/assets/nano-icons/app-icons/repost-corner2.svg b/assets/nano-icons/app-icons/repost-corner2.svg
new file mode 100644
index 0000000000..a1efb8b17e
--- /dev/null
+++ b/assets/nano-icons/app-icons/repost-corner2.svg
@@ -0,0 +1 @@
+
diff --git a/assets/nano-icons/app-icons/repost.svg b/assets/nano-icons/app-icons/repost.svg
new file mode 100644
index 0000000000..250c216649
--- /dev/null
+++ b/assets/nano-icons/app-icons/repost.svg
@@ -0,0 +1 @@
+
diff --git a/assets/nano-icons/app-icons/search-filled.svg b/assets/nano-icons/app-icons/search-filled.svg
new file mode 100644
index 0000000000..b3364d577e
--- /dev/null
+++ b/assets/nano-icons/app-icons/search-filled.svg
@@ -0,0 +1 @@
+
diff --git a/assets/nano-icons/app-icons/search.svg b/assets/nano-icons/app-icons/search.svg
new file mode 100644
index 0000000000..b007141551
--- /dev/null
+++ b/assets/nano-icons/app-icons/search.svg
@@ -0,0 +1 @@
+
diff --git a/assets/nano-icons/app-icons/share.svg b/assets/nano-icons/app-icons/share.svg
new file mode 100644
index 0000000000..6b003cb531
--- /dev/null
+++ b/assets/nano-icons/app-icons/share.svg
@@ -0,0 +1 @@
+
diff --git a/assets/nano-icons/app-icons/unmute.svg b/assets/nano-icons/app-icons/unmute.svg
new file mode 100644
index 0000000000..6bdbc95589
--- /dev/null
+++ b/assets/nano-icons/app-icons/unmute.svg
@@ -0,0 +1 @@
+
diff --git a/assets/nano-icons/nanoicons/app-icons.glyphmap.json b/assets/nano-icons/nanoicons/app-icons.glyphmap.json
new file mode 100644
index 0000000000..46db6aaa86
--- /dev/null
+++ b/assets/nano-icons/nanoicons/app-icons.glyphmap.json
@@ -0,0 +1 @@
+{"m":{"f":"app-icons","u":1024,"z":1020,"s":59648,"h":"f31796d2f6d13414a394ceff67db6d504f46e260cf1e305618733472f96c181d"},"i":{"arrow-top-right":[1024,[[59648,"#000"]]],"bell-filled":[1024,[[59649,"#000"]]],"bell":[1024,[[59650,"#000"]]],"bookmark-filled":[1024,[[59651,"#000"]]],"bookmark":[1024,[[59652,"#000"]]],"bubble":[1024,[[59653,"#000"]]],"circle-check":[1024,[[59654,"#000"]]],"clock":[1024,[[59655,"#000"]]],"earth":[1024,[[59656,"#000"]]],"heart-filled":[1024,[[59657,"#000"]]],"heart":[1024,[[59658,"#000"]]],"home-filled":[1024,[[59659,"#000"]]],"home":[1024,[[59660,"#000"]]],"inbox":[1024,[[59661,"#000"]]],"menu":[1024,[[59662,"#000"]]],"message-filled":[1024,[[59663,"#000"]]],"message":[1024,[[59664,"#000"]]],"mute":[1024,[[59665,"#000"]]],"pause":[1024,[[59666,"#000"]]],"pin":[1024,[[59667,"#000"]]],"play":[1024,[[59668,"#000"]]],"reply":[1024,[[59669,"#000"]]],"repost-corner2":[1024,[[59670,"#000"]]],"repost":[1024,[[59671,"#000"]]],"search-filled":[1024,[[59672,"#000"]]],"search":[1024,[[59673,"#000"]]],"share":[1024,[[59674,"#000"]]],"unmute":[1024,[[59675,"#000"]]]}}
\ No newline at end of file
diff --git a/assets/nano-icons/nanoicons/app-icons.ttf b/assets/nano-icons/nanoicons/app-icons.ttf
new file mode 100644
index 0000000000..c07c52449b
Binary files /dev/null and b/assets/nano-icons/nanoicons/app-icons.ttf differ
diff --git a/package.json b/package.json
index 3ae22dc51a..3fc47a26e5 100644
--- a/package.json
+++ b/package.json
@@ -238,6 +238,7 @@
"react-native-gesture-handler": "~2.32.0",
"react-native-keyboard-controller": "1.21.9",
"react-native-mmkv": "^3.3.3",
+ "react-native-nano-icons": "^0.2.1",
"react-native-pager-view": "6.8.0",
"react-native-progress": "^5.0.1",
"react-native-qrcode-styled": "^0.3.3",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 86133a02ef..7de34eb0a6 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -656,6 +656,9 @@ importers:
react-native-mmkv:
specifier: ^3.3.3
version: 3.3.3(react-native@0.86.0(patch_hash=dd549527bb84c88acc7b0b1d521c9f4b666fda484c75cd0b282f8e9838524909)(@babel/core@7.29.0(supports-color@8.1.1))(@react-native/jest-preset@0.86.0(@babel/core@7.29.0(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.0(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)
+ react-native-nano-icons:
+ specifier: ^0.2.1
+ version: 0.2.1(@expo/config@57.0.8(@typescript/typescript6@6.0.2)(supports-color@8.1.1))(@typescript/typescript6@6.0.2)(expo@57.0.8)(react-native@0.86.0(patch_hash=dd549527bb84c88acc7b0b1d521c9f4b666fda484c75cd0b282f8e9838524909)(@babel/core@7.29.0(supports-color@8.1.1))(@react-native/jest-preset@0.86.0(@babel/core@7.29.0(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.0(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1)
react-native-pager-view:
specifier: 6.8.0
version: 6.8.0(patch_hash=c8316acd33c9aef6531e8c272c2bfab7bd02af1255969eeaab2bad5ab48531cc)(react-native@0.86.0(patch_hash=dd549527bb84c88acc7b0b1d521c9f4b666fda484c75cd0b282f8e9838524909)(@babel/core@7.29.0(supports-color@8.1.1))(@react-native/jest-preset@0.86.0(@babel/core@7.29.0(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.0(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)
@@ -4650,6 +4653,10 @@ packages:
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
engines: {node: '>=10'}
+ chalk@5.6.2:
+ resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==}
+ engines: {node: ^12.17.0 || ^14.13 || >=16.0.0}
+
char-regex@1.0.2:
resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==}
engines: {node: '>=10'}
@@ -4722,6 +4729,10 @@ packages:
resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==}
engines: {node: '>=6'}
+ cli-spinners@3.4.0:
+ resolution: {integrity: sha512-bXfOC4QcT1tKXGorxL3wbJm6XJPDqEnij2gQ2m7ESQuE+/z9YFIWnl/5RpTiKWbMq3EVKR4fRLJGn6DVfu0mpw==}
+ engines: {node: '>=18.20'}
+
cli-table@0.3.11:
resolution: {integrity: sha512-IqLQi4lO0nIB4tcdTpN4LCB9FI3uqrJZK7RC515EnhZ6qBaglkIgICb1wjeAqpdoOabm1+SuQtkXIPdYC93jhQ==}
engines: {node: '>= 0.2.0'}
@@ -5013,6 +5024,9 @@ packages:
csstype@3.2.3:
resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==}
+ cubic2quad@1.2.1:
+ resolution: {integrity: sha512-wT5Y7mO8abrV16gnssKdmIhIbA9wSkeMzhh27jAguKrV82i24wER0vL5TGhUJ9dbJNDcigoRZ0IAHFEEEI4THQ==}
+
data-urls@3.0.2:
resolution: {integrity: sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==}
engines: {node: '>=12'}
@@ -5913,6 +5927,9 @@ packages:
debug:
optional: true
+ fonteditor-core@2.6.3:
+ resolution: {integrity: sha512-YUryIKjkenjZ41E7JvM3V+02Ak4mTHDDTwBWgs9KBzypzHqLZHuua1UDRevZNTKawmnq1dbBAa70Jddl2+F4FQ==}
+
fontfaceobserver@2.3.0:
resolution: {integrity: sha512-6FPvD/IVyT4ZlNe7Wcn5Fb/4ChigpucKYSvD6a+0iMoLn2inpo711eyIcKjmDtE5XNcgAkSH9uN/nfAeZzHEfg==}
@@ -6405,6 +6422,10 @@ packages:
resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==}
engines: {node: '>=8'}
+ is-interactive@2.0.0:
+ resolution: {integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==}
+ engines: {node: '>=12'}
+
is-map@2.0.3:
resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==}
engines: {node: '>= 0.4'}
@@ -6484,6 +6505,10 @@ packages:
resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==}
engines: {node: '>=10'}
+ is-unicode-supported@2.1.0:
+ resolution: {integrity: sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==}
+ engines: {node: '>=18'}
+
is-weakmap@2.0.2:
resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==}
engines: {node: '>= 0.4'}
@@ -6987,6 +7012,10 @@ packages:
resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==}
engines: {node: '>=10'}
+ log-symbols@7.0.1:
+ resolution: {integrity: sha512-ja1E3yCr9i/0hmBVaM0bfwDjnGy8I/s6PP4DFp+yP+a+mrHO4Rm7DtmnqROTUkHIkqffC84YY7AeqX6oFk0WFg==}
+ engines: {node: '>=18'}
+
log-update@6.1.0:
resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==}
engines: {node: '>=18'}
@@ -7146,6 +7175,9 @@ packages:
engines: {node: ^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0}
hasBin: true
+ microbuffer@1.0.0:
+ resolution: {integrity: sha512-O/SUXauVN4x6RaEJFqSPcXNtLFL+QzJHKZlyDVYFwcDDRVca3Fa/37QXXC+4zAGGa4YhHrHxKXuuHvLDIQECtA==}
+
micromatch@4.0.8:
resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
engines: {node: '>=8.6'}
@@ -7542,6 +7574,10 @@ packages:
resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==}
engines: {node: '>=10'}
+ ora@9.4.1:
+ resolution: {integrity: sha512-6VlU9MLXbjVQD04AZCMX28hVtA5bUoadvUqO76MUCVA0ilwJbMiHsITRPfyVm6p/BC0Av/BXMujx39WCe1LEqw==}
+ engines: {node: '>=20'}
+
orderedmap@2.1.1:
resolution: {integrity: sha512-TvAWxi0nDe1j/rtMcWcIj94+Ffe6n7zhow33h40SKxmsmozs6dz/e+EajymfoFcHd7sxNn8yHM8839uixMOV6g==}
@@ -7666,6 +7702,9 @@ packages:
resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
engines: {node: '>=8'}
+ pathkit-wasm@1.0.0:
+ resolution: {integrity: sha512-oREIcGpwnBBto6PfB3C20aIw9jBPLcSNVF1AlL5tGlXsoL2zqWVuD0mi8WMJQHHNemm6aR1hHH2lz+TO551Fgw==}
+
pend@1.2.0:
resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==}
@@ -8068,6 +8107,10 @@ packages:
pure-rand@6.1.0:
resolution: {integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==}
+ pyodide@0.29.4:
+ resolution: {integrity: sha512-tCseTsqU3kSxZIjkue5zXxTMNEwrKZwOIIEQRBA/VzHxFN1hoCxe4w41phfCdHd9it9RcCNQb5K/Re0InqMgvA==}
+ engines: {node: '>=18.0.0'}
+
qrcode@1.5.4:
resolution: {integrity: sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==}
engines: {node: '>=10.13.0'}
@@ -8233,6 +8276,20 @@ packages:
react: '*'
react-native: '*'
+ react-native-nano-icons@0.2.1:
+ resolution: {integrity: sha512-aQD7MdOLJzP/dBtuzEZbkdsVWrPec47UTfFc1Y/TveS/dXWhumA0ujlT4shFiY5GcL2s35z7NA8ZbxZWibggQQ==}
+ hasBin: true
+ peerDependencies:
+ '@expo/config': '>=9.0.0'
+ expo: '*'
+ react: '*'
+ react-native: '*'
+ peerDependenciesMeta:
+ '@expo/config':
+ optional: true
+ expo:
+ optional: true
+
react-native-pager-view@6.8.0:
resolution: {integrity: sha512-/wgFV8nB4TLnQ6j9e3TvNrHbPF5TINMZHaXt86GOV0NSJNMVGkWguniJVKrYLm85LL8KVhRkgdh43Rdu7PvW1A==}
peerDependencies:
@@ -8844,6 +8901,10 @@ packages:
resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==}
engines: {node: '>= 0.8'}
+ stdin-discarder@0.3.2:
+ resolution: {integrity: sha512-eCPu1qRxPVkl5605OTWF8Wz40b4Mf45NY5LQmVPQ599knfs5QhASUm9GbJ5BDMDOXgrnh0wyEdvzmL//YMlw0A==}
+ engines: {node: '>=18'}
+
stop-iteration-iterator@1.1.0:
resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==}
engines: {node: '>= 0.4'}
@@ -8972,6 +9033,10 @@ packages:
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
engines: {node: '>= 0.4'}
+ svg2ttf@6.1.0:
+ resolution: {integrity: sha512-EjxgcmhKcBpx/3fR1hPwVtJAbUc/ZsDpwOTF74SI3PbzCg4pDHnxVmoSuqgEqxVJGqqkSCI6+82cucpn2D5aOw==}
+ hasBin: true
+
svgo@2.8.2:
resolution: {integrity: sha512-TyzE4NVGLUFy+H/Uy4N6c3G0HEeprsVfge6Lmq+0FdQQ/zqoVYB62IsBZORsiL+o96s6ff/V6/3UQo/C0cgCAA==}
engines: {node: '>=10.13.0'}
@@ -8982,6 +9047,9 @@ packages:
engines: {node: '>=16'}
hasBin: true
+ svgpath@2.6.0:
+ resolution: {integrity: sha512-OIWR6bKzXvdXYyO4DK/UWa1VA1JeKq8E+0ug2DG98Y/vOmMpfZNj+TIG988HjfYSqtcy/hFOtZq/n/j5GSESNg==}
+
symbol-tree@3.2.4:
resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==}
@@ -9647,6 +9715,10 @@ packages:
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
engines: {node: '>=10'}
+ yoctocolors@2.2.0:
+ resolution: {integrity: sha512-xYqdZFUK/VYazNl/oCDYN+3WloWQwMfZxBoiNt6qNyk+xfOdi598muWE42rNZFp1kNOiqW936q5RhUdnpqElSg==}
+ engines: {node: '>=18'}
+
zod@3.25.76:
resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==}
@@ -14166,6 +14238,8 @@ snapshots:
ansi-styles: 4.3.0
supports-color: 7.2.0
+ chalk@5.6.2: {}
+
char-regex@1.0.2: {}
char-regex@2.0.2: {}
@@ -14248,6 +14322,8 @@ snapshots:
cli-spinners@2.9.2: {}
+ cli-spinners@3.4.0: {}
+
cli-table@0.3.11:
dependencies:
colors: 1.0.3
@@ -14570,6 +14646,8 @@ snapshots:
csstype@3.2.3: {}
+ cubic2quad@1.2.1: {}
+
data-urls@3.0.2:
dependencies:
abab: 2.0.6
@@ -15641,6 +15719,10 @@ snapshots:
optionalDependencies:
debug: 4.4.3(supports-color@8.1.1)
+ fonteditor-core@2.6.3:
+ dependencies:
+ '@xmldom/xmldom': 0.8.13
+
fontfaceobserver@2.3.0: {}
for-each@0.3.5:
@@ -16151,6 +16233,8 @@ snapshots:
is-interactive@1.0.0: {}
+ is-interactive@2.0.0: {}
+
is-map@2.0.3: {}
is-negative-zero@2.0.3: {}
@@ -16215,6 +16299,8 @@ snapshots:
is-unicode-supported@0.1.0: {}
+ is-unicode-supported@2.1.0: {}
+
is-weakmap@2.0.2: {}
is-weakref@1.1.1:
@@ -16958,6 +17044,11 @@ snapshots:
chalk: 4.1.2
is-unicode-supported: 0.1.0
+ log-symbols@7.0.1:
+ dependencies:
+ is-unicode-supported: 2.1.0
+ yoctocolors: 2.2.0
+
log-update@6.1.0:
dependencies:
ansi-escapes: 7.3.0
@@ -17228,6 +17319,8 @@ snapshots:
- supports-color
- utf-8-validate
+ microbuffer@1.0.0: {}
+
micromatch@4.0.8:
dependencies:
braces: 3.0.3
@@ -17471,6 +17564,17 @@ snapshots:
strip-ansi: 6.0.1
wcwidth: 1.0.1
+ ora@9.4.1:
+ dependencies:
+ chalk: 5.6.2
+ cli-cursor: 5.0.0
+ cli-spinners: 3.4.0
+ is-interactive: 2.0.0
+ is-unicode-supported: 2.1.0
+ log-symbols: 7.0.1
+ stdin-discarder: 0.3.2
+ string-width: 8.2.1
+
orderedmap@2.1.1: {}
own-keys@1.0.1:
@@ -17601,6 +17705,8 @@ snapshots:
path-type@4.0.0: {}
+ pathkit-wasm@1.0.0: {}
+
pend@1.2.0: {}
picocolors@1.1.1: {}
@@ -18022,6 +18128,14 @@ snapshots:
pure-rand@6.1.0: {}
+ pyodide@0.29.4:
+ dependencies:
+ '@types/emscripten': 1.41.5
+ ws: 8.20.1
+ transitivePeerDependencies:
+ - bufferutil
+ - utf-8-validate
+
qrcode@1.5.4:
dependencies:
dijkstrajs: 1.0.3
@@ -18236,6 +18350,29 @@ snapshots:
react: 19.2.3
react-native: 0.86.0(patch_hash=dd549527bb84c88acc7b0b1d521c9f4b666fda484c75cd0b282f8e9838524909)(@babel/core@7.29.0(supports-color@8.1.1))(@react-native/jest-preset@0.86.0(@babel/core@7.29.0(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.0(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1)
+ react-native-nano-icons@0.2.1(@expo/config@57.0.8(@typescript/typescript6@6.0.2)(supports-color@8.1.1))(@typescript/typescript6@6.0.2)(expo@57.0.8)(react-native@0.86.0(patch_hash=dd549527bb84c88acc7b0b1d521c9f4b666fda484c75cd0b282f8e9838524909)(@babel/core@7.29.0(supports-color@8.1.1))(@react-native/jest-preset@0.86.0(@babel/core@7.29.0(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.0(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1):
+ dependencies:
+ '@expo/config-plugins': 57.0.8(@typescript/typescript6@6.0.2)(supports-color@8.1.1)
+ '@xmldom/xmldom': 0.9.10
+ chalk: 5.6.2
+ fonteditor-core: 2.6.3
+ ora: 9.4.1
+ pathkit-wasm: 1.0.0
+ plist: 3.1.1
+ pyodide: 0.29.4
+ react: 19.2.3
+ react-native: 0.86.0(patch_hash=dd549527bb84c88acc7b0b1d521c9f4b666fda484c75cd0b282f8e9838524909)(@babel/core@7.29.0(supports-color@8.1.1))(@react-native/jest-preset@0.86.0(@babel/core@7.29.0(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.0(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1)
+ svg2ttf: 6.1.0
+ xcode: 3.0.1
+ optionalDependencies:
+ '@expo/config': 57.0.8(@typescript/typescript6@6.0.2)(supports-color@8.1.1)
+ expo: 57.0.8(patch_hash=1722861d12907a2d412d04230545b2fcbfa5547a79f99d763cb3e8de6f3a6f2a)(b32afa45429c882ad113a248f683620a)
+ transitivePeerDependencies:
+ - bufferutil
+ - supports-color
+ - typescript
+ - utf-8-validate
+
react-native-pager-view@6.8.0(patch_hash=c8316acd33c9aef6531e8c272c2bfab7bd02af1255969eeaab2bad5ab48531cc)(react-native@0.86.0(patch_hash=dd549527bb84c88acc7b0b1d521c9f4b666fda484c75cd0b282f8e9838524909)(@babel/core@7.29.0(supports-color@8.1.1))(@react-native/jest-preset@0.86.0(@babel/core@7.29.0(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.0(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.18)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3):
dependencies:
react: 19.2.3
@@ -18947,6 +19084,8 @@ snapshots:
statuses@2.0.2: {}
+ stdin-discarder@0.3.2: {}
+
stop-iteration-iterator@1.1.0:
dependencies:
es-errors: 1.3.0
@@ -19079,6 +19218,15 @@ snapshots:
supports-preserve-symlinks-flag@1.0.0: {}
+ svg2ttf@6.1.0:
+ dependencies:
+ '@xmldom/xmldom': 0.9.10
+ argparse: 2.0.1
+ cubic2quad: 1.2.1
+ lodash: 4.18.1
+ microbuffer: 1.0.0
+ svgpath: 2.6.0
+
svgo@2.8.2:
dependencies:
commander: 7.2.0
@@ -19099,6 +19247,8 @@ snapshots:
picocolors: 1.1.1
sax: 1.6.0
+ svgpath@2.6.0: {}
+
symbol-tree@3.2.4: {}
tagged-tag@1.0.0: {}
@@ -19809,6 +19959,8 @@ snapshots:
yocto-queue@0.1.0: {}
+ yoctocolors@2.2.0: {}
+
zod@3.25.76: {}
zxing-wasm@3.1.3(@types/emscripten@1.41.5):
diff --git a/src/components/Post/Embed/ExternalEmbed/index.tsx b/src/components/Post/Embed/ExternalEmbed/index.tsx
index a496780524..b2b92d88e9 100644
--- a/src/components/Post/Embed/ExternalEmbed/index.tsx
+++ b/src/components/Post/Embed/ExternalEmbed/index.tsx
@@ -15,7 +15,7 @@ import {toNiceDomain} from '#/lib/strings/url-helpers'
import {useExternalEmbedsPrefs} from '#/state/preferences'
import {atoms as a, useTheme} from '#/alf'
import {Divider} from '#/components/Divider'
-import {Earth_Stroke2_Corner0_Rounded as Globe} from '#/components/icons/Globe'
+import {EarthIcon as Globe} from '#/components/icons/nano'
import {Link} from '#/components/Link'
import {Text} from '#/components/Typography'
import {IS_NATIVE} from '#/env'
diff --git a/src/components/Post/Embed/StandardSiteEmbed/index.tsx b/src/components/Post/Embed/StandardSiteEmbed/index.tsx
index 0c50723a15..9527e96b80 100644
--- a/src/components/Post/Embed/StandardSiteEmbed/index.tsx
+++ b/src/components/Post/Embed/StandardSiteEmbed/index.tsx
@@ -13,9 +13,8 @@ import {atoms as a, useBreakpoints, useTheme, utils, web} from '#/alf'
import {ButtonIcon, ButtonText} from '#/components/Button'
import {Divider} from '#/components/Divider'
import {useInteractionState} from '#/components/hooks/useInteractionState'
-import {ArrowTopRight_Stroke2_Corner0_Rounded as ArrowTopRightIcon} from '#/components/icons/Arrow'
-import {Clock_Stroke2_Corner0_Rounded as Clock} from '#/components/icons/Clock'
import {StandardSite} from '#/components/icons/community/StandardSite'
+import {ArrowTopRightIcon, ClockIcon as Clock} from '#/components/icons/nano'
import {Link} from '#/components/Link'
import {MediaInsetBorder} from '#/components/MediaInsetBorder'
import {matchStandardSitePublisher} from '#/components/Post/Embed/StandardSiteEmbed/publishers'
diff --git a/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerNative.tsx b/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerNative.tsx
index a8ea65a43b..340e029144 100644
--- a/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerNative.tsx
+++ b/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerNative.tsx
@@ -8,10 +8,12 @@ import {useAutoplayDisabled} from '#/state/preferences'
import {atoms as a, useTheme} from '#/alf'
import {AltBadgeWithDialog} from '#/components/AltBadgeWithDialog'
import {useIsWithinMessage} from '#/components/dms/MessageContext'
-import {Mute_Stroke2_Corner0_Rounded as MuteIcon} from '#/components/icons/Mute'
-import {Pause_Filled_Corner0_Rounded as PauseIcon} from '#/components/icons/Pause'
-import {Play_Filled_Corner0_Rounded as PlayIcon} from '#/components/icons/Play'
-import {SpeakerVolumeFull_Stroke2_Corner0_Rounded as UnmuteIcon} from '#/components/icons/Speaker'
+import {
+ MuteIcon,
+ PauseIcon,
+ PlayIcon,
+ UnmuteIcon,
+} from '#/components/icons/nano'
import {KeepAwake} from '#/components/KeepAwake'
import {MediaInsetBorder} from '#/components/MediaInsetBorder'
import {useReportDialogMetadataContext} from '#/components/moderation/ReportDialog/ReportDialogMetadataContext'
diff --git a/src/components/PostControls/BookmarkButton.tsx b/src/components/PostControls/BookmarkButton.tsx
index 8d43947823..37bfd25bd9 100644
--- a/src/components/PostControls/BookmarkButton.tsx
+++ b/src/components/PostControls/BookmarkButton.tsx
@@ -10,7 +10,10 @@ import {useFeedFeedbackContext} from '#/state/feed-feedback'
import {useBookmarkMutation} from '#/state/queries/bookmarks/useBookmarkMutation'
import {useRequireAuth} from '#/state/session'
import {useTheme} from '#/alf'
-import {Bookmark, BookmarkFilled} from '#/components/icons/Bookmark'
+import {
+ BookmarkFilledIcon as BookmarkFilled,
+ BookmarkIcon as Bookmark,
+} from '#/components/icons/nano'
import {Trash_Stroke2_Corner0_Rounded as TrashIcon} from '#/components/icons/Trash'
import * as toast from '#/components/Toast'
import {useAnalytics} from '#/analytics'
diff --git a/src/components/PostControls/PostMenu/index.tsx b/src/components/PostControls/PostMenu/index.tsx
index 23a3e52401..c7ef7d2c48 100644
--- a/src/components/PostControls/PostMenu/index.tsx
+++ b/src/components/PostControls/PostMenu/index.tsx
@@ -5,7 +5,7 @@ import {useLingui} from '@lingui/react/macro'
import {type Shadow} from '#/state/cache/post-shadow'
import {EventStopper} from '#/view/com/util/EventStopper'
-import {DotGrid3x1_Stroke2_Corner0_Rounded as DotsHorizontal} from '#/components/icons/DotGrid'
+import {MenuIcon as DotsHorizontal} from '#/components/icons/nano'
import * as Menu from '#/components/Menu'
import {useMenuControl} from '#/components/Menu'
import {type app} from '#/lexicons'
diff --git a/src/components/PostControls/RepostButton.tsx b/src/components/PostControls/RepostButton.tsx
index 734cafa3c8..fa8296125a 100644
--- a/src/components/PostControls/RepostButton.tsx
+++ b/src/components/PostControls/RepostButton.tsx
@@ -9,8 +9,8 @@ import {useRequireAuth} from '#/state/session'
import {atoms as a, useTheme} from '#/alf'
import {Button, ButtonText} from '#/components/Button'
import * as Dialog from '#/components/Dialog'
+import {RepostIcon} from '#/components/icons/nano'
import {CloseQuote_Stroke2_Corner1_Rounded as QuoteIcon} from '#/components/icons/Quote'
-import {Repost_Stroke2_Corner3_Rounded as RepostIcon} from '#/components/icons/Repost'
import {useFormatPostStatCount} from '#/components/PostControls/util'
import {Text} from '#/components/Typography'
import {
diff --git a/src/components/PostControls/ShareMenu/index.tsx b/src/components/PostControls/ShareMenu/index.tsx
index 6c2188b612..ffdbff8735 100644
--- a/src/components/PostControls/ShareMenu/index.tsx
+++ b/src/components/PostControls/ShareMenu/index.tsx
@@ -12,7 +12,7 @@ import {type Shadow} from '#/state/cache/post-shadow'
import {useFeedFeedbackContext} from '#/state/feed-feedback'
import {EventStopper} from '#/view/com/util/EventStopper'
import {native} from '#/alf'
-import {ArrowShareRight_Stroke2_Corner2_Rounded as ArrowShareRightIcon} from '#/components/icons/ArrowShareRight'
+import {ShareIcon as ArrowShareRightIcon} from '#/components/icons/nano'
import * as Menu from '#/components/Menu'
import {useMenuControl} from '#/components/Menu'
import {useAnalytics} from '#/analytics'
diff --git a/src/components/PostControls/index.tsx b/src/components/PostControls/index.tsx
index 6457267780..15797b88bc 100644
--- a/src/components/PostControls/index.tsx
+++ b/src/components/PostControls/index.tsx
@@ -19,7 +19,7 @@ import {
useProgressGuideControls,
} from '#/state/shell/progress-guide'
import {atoms as a, useBreakpoints, useTheme} from '#/alf'
-import {Reply as Bubble} from '#/components/icons/Reply'
+import {ReplyIcon as Bubble} from '#/components/icons/nano'
import {useFormatPostStatCount} from '#/components/PostControls/util'
import * as Skele from '#/components/Skeleton'
import * as Toast from '#/components/Toast'
diff --git a/src/components/icons/nano.tsx b/src/components/icons/nano.tsx
new file mode 100644
index 0000000000..0538fee53a
--- /dev/null
+++ b/src/components/icons/nano.tsx
@@ -0,0 +1,109 @@
+import {type ColorValue, StyleSheet} from 'react-native'
+import {createNanoIconSet} from 'react-native-nano-icons'
+
+import {useTheme} from '#/alf'
+import {type Props, sizes} from '#/components/icons/common'
+import glyphMap from '../../../assets/nano-icons/nanoicons/app-icons.glyphmap.json'
+
+const NanoIcon = createNanoIconSet(glyphMap)
+
+type IconName = keyof (typeof glyphMap)['i']
+
+/**
+ * Drop-in replacement for `createSinglePathSVG` backed by a font glyph instead
+ * of a react-native-svg subtree. Each icon renders as one native text glyph
+ * rather than SvgView + Group + Path, which is three native views per icon.
+ *
+ * The prop contract deliberately mirrors `useCommonSVGProps` so call sites and
+ * wrappers such as `PostControlButtonIcon` do not have to change.
+ *
+ * Only icons that are a single filled path can move here. Anything using the
+ * `gradient` prop (`StarterPackIcon`) or several fill colours (`VerifiedCheck`)
+ * must stay on react-native-svg.
+ */
+export function createNanoIcon(name: IconName) {
+ return function Icon({fill, size, style, width, testID}: Props) {
+ const t = useTheme()
+ const flattened = StyleSheet.flatten(style)
+
+ /*
+ * Mirrors useCommonSVGProps: an explicit `size` token wins, then a raw
+ * `width`, then the default. `fill` wins over a color inherited via style.
+ */
+ const resolvedSize = Number(size ? sizes[size] : width || sizes.md)
+ const color = (fill || flattened?.color || t.palette.primary_500) as
+ ColorValue | ColorValue[]
+
+ return (
+ /*
+ * The a11y rule wants an accessibilityHint alongside accessibilityLabel,
+ * but a hint would be exactly wrong here: the label is empty precisely to
+ * remove this glyph from the accessibility tree, and a hint would put
+ * content back into it. See the accessibilityLabel comment below.
+ */
+ // oxlint-disable-next-line react-native-a11y/has-accessibility-hint
+
+ )
+ }
+}
+
+/* Post action bar */
+export const ReplyIcon = createNanoIcon('reply')
+export const RepostIcon = createNanoIcon('repost')
+export const HeartIcon = createNanoIcon('heart')
+export const HeartFilledIcon = createNanoIcon('heart-filled')
+export const BookmarkIcon = createNanoIcon('bookmark')
+export const BookmarkFilledIcon = createNanoIcon('bookmark-filled')
+export const ShareIcon = createNanoIcon('share')
+export const MenuIcon = createNanoIcon('menu')
+
+/* Feed rows and post embeds */
+export const PinIcon = createNanoIcon('pin')
+export const EarthIcon = createNanoIcon('earth')
+export const PlayIcon = createNanoIcon('play')
+export const PauseIcon = createNanoIcon('pause')
+export const MuteIcon = createNanoIcon('mute')
+export const UnmuteIcon = createNanoIcon('unmute')
+export const ArrowTopRightIcon = createNanoIcon('arrow-top-right')
+export const ClockIcon = createNanoIcon('clock')
+
+/* Feed loading skeletons - 8 rows x 3 icons per placeholder, one per profile tab */
+export const BubbleIcon = createNanoIcon('bubble')
+export const RepostCorner2Icon = createNanoIcon('repost-corner2')
+
+/* Shell chrome, mounted for the whole session */
+export const HomeIcon = createNanoIcon('home')
+export const HomeFilledIcon = createNanoIcon('home-filled')
+export const SearchIcon = createNanoIcon('search')
+export const SearchFilledIcon = createNanoIcon('search-filled')
+export const MessageIcon = createNanoIcon('message')
+export const MessageFilledIcon = createNanoIcon('message-filled')
+export const BellIcon = createNanoIcon('bell')
+export const BellFilledIcon = createNanoIcon('bell-filled')
+export const InboxIcon = createNanoIcon('inbox')
+export const CircleCheckIcon = createNanoIcon('circle-check')
diff --git a/src/lib/custom-animations/LikeIcon.tsx b/src/lib/custom-animations/LikeIcon.tsx
index 4ab9582aae..21d4e43db7 100644
--- a/src/lib/custom-animations/LikeIcon.tsx
+++ b/src/lib/custom-animations/LikeIcon.tsx
@@ -7,9 +7,9 @@ import Animated, {
import {useTheme} from '#/alf'
import {
- Heart2_Filled_Stroke2_Corner0_Rounded as HeartIconFilled,
- Heart2_Stroke2_Corner0_Rounded as HeartIconOutline,
-} from '#/components/icons/Heart2'
+ HeartFilledIcon as HeartIconFilled,
+ HeartIcon as HeartIconOutline,
+} from '#/components/icons/nano'
const keyframe = new Keyframe({
0: {
diff --git a/src/style.css b/src/style.css
index 48bacf81b9..46b24fdfc6 100644
--- a/src/style.css
+++ b/src/style.css
@@ -12,6 +12,22 @@
* HTML & BODY STYLES IN `web/index.html` and `bskyweb/templates/base.html`
*/
+/*
+ * Nano Icons font, used by the icons in `#/components/icons/nano`.
+ *
+ * On native the Expo config plugin links the TTF into the app bundle, but on
+ * web the library reads the family straight off CSS and never registers it at
+ * runtime - without this the icons render as tofu.
+ */
+@font-face {
+ font-family: 'app-icons';
+ src: url('../assets/nano-icons/nanoicons/app-icons.ttf') format('truetype');
+ font-weight: normal;
+ font-style: normal;
+ /* Icon glyphs have no sensible fallback, so never swap in one. */
+ font-display: block;
+}
+
/* Buttons and inputs have a font set by UA, so we'll have to reset that */
button,
input,
diff --git a/src/view/com/posts/PostFeedReason.tsx b/src/view/com/posts/PostFeedReason.tsx
index 54fdbfe465..2a87fcf126 100644
--- a/src/view/com/posts/PostFeedReason.tsx
+++ b/src/view/com/posts/PostFeedReason.tsx
@@ -9,8 +9,7 @@ import {createSanitizedDisplayName} from '#/lib/moderation/create-sanitized-disp
import {makeProfileLink} from '#/lib/routes/links'
import {useSession} from '#/state/session'
import {atoms as a, useTheme} from '#/alf'
-import {Pin_Stroke2_Corner0_Rounded as PinIcon} from '#/components/icons/Pin'
-import {Repost_Stroke2_Corner3_Rounded as RepostIcon} from '#/components/icons/Repost'
+import {PinIcon, RepostIcon} from '#/components/icons/nano'
import {Link} from '#/components/Link'
import {ProfileHoverCard} from '#/components/ProfileHoverCard'
import {Text} from '#/components/Typography'
diff --git a/src/view/com/util/LoadingPlaceholder.tsx b/src/view/com/util/LoadingPlaceholder.tsx
index 97b8587933..e3d9f9123c 100644
--- a/src/view/com/util/LoadingPlaceholder.tsx
+++ b/src/view/com/util/LoadingPlaceholder.tsx
@@ -9,12 +9,12 @@ import {
import {s} from '#/lib/styles'
import {atoms as a, useTheme} from '#/alf'
-import {Bubble_Stroke2_Corner2_Rounded as Bubble} from '#/components/icons/Bubble'
import {
- Heart2_Filled_Stroke2_Corner0_Rounded as HeartIconFilled,
- Heart2_Stroke2_Corner0_Rounded as HeartIconOutline,
-} from '#/components/icons/Heart2'
-import {Repost_Stroke2_Corner2_Rounded as Repost} from '#/components/icons/Repost'
+ BubbleIcon as Bubble,
+ HeartFilledIcon as HeartIconFilled,
+ HeartIcon as HeartIconOutline,
+ RepostCorner2Icon as Repost,
+} from '#/components/icons/nano'
export function LoadingPlaceholder({
width,
diff --git a/src/view/shell/bottom-bar/BottomBar.tsx b/src/view/shell/bottom-bar/BottomBar.tsx
index c33d2b7b8e..10dc3cae9a 100644
--- a/src/view/shell/bottom-bar/BottomBar.tsx
+++ b/src/view/shell/bottom-bar/BottomBar.tsx
@@ -34,23 +34,17 @@ import {Button, ButtonText} from '#/components/Button'
import {useDialogControl} from '#/components/Dialog'
import {SwitchAccountDialog} from '#/components/dialogs/SwitchAccount'
import {
- Bell_Filled_Corner0_Rounded as BellFilled,
- Bell_Stroke2_Corner0_Rounded as Bell,
-} from '#/components/icons/Bell'
-import {CircleCheck_Stroke2_Corner0_Rounded as CircleCheckIcon} from '#/components/icons/CircleCheck'
-import {
- HomeOpen_Filled_Corner0_Rounded as HomeFilled,
- HomeOpen_Stoke2_Corner0_Rounded as Home,
-} from '#/components/icons/HomeOpen'
-import {Inbox_Stroke2_Corner2_Rounded as InboxIcon} from '#/components/icons/Inbox'
-import {
- MagnifyingGlass_Filled_Stroke2_Corner0_Rounded as MagnifyingGlassFilled,
- MagnifyingGlass_Stroke2_Corner0_Rounded as MagnifyingGlass,
-} from '#/components/icons/MagnifyingGlass'
-import {
- Message_Stroke2_Corner0_Rounded as Message,
- Message_Stroke2_Corner0_Rounded_Filled as MessageFilled,
-} from '#/components/icons/Message'
+ BellFilledIcon as BellFilled,
+ BellIcon as Bell,
+ CircleCheckIcon,
+ HomeFilledIcon as HomeFilled,
+ HomeIcon as Home,
+ InboxIcon,
+ MessageFilledIcon as MessageFilled,
+ MessageIcon as Message,
+ SearchFilledIcon as MagnifyingGlassFilled,
+ SearchIcon as MagnifyingGlass,
+} from '#/components/icons/nano'
import * as Menu from '#/components/Menu'
import * as Toast from '#/components/Toast'
import {Text} from '#/components/Typography'