designmd-forge 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (907) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +119 -0
  3. package/dist/__tests__/designStore.test.js +41 -0
  4. package/dist/__tests__/linter.test.js +23 -0
  5. package/dist/__tests__/sectionParser.test.js +60 -0
  6. package/dist/__tests__/server.test.js +129 -0
  7. package/dist/constants.js +12 -0
  8. package/dist/data/authoring-guide.md +113 -0
  9. package/dist/data/designs/airbnb.md +545 -0
  10. package/dist/data/designs/airtable.md +554 -0
  11. package/dist/data/designs/apple.md +562 -0
  12. package/dist/data/designs/binance.md +634 -0
  13. package/dist/data/designs/bmw-m.md +503 -0
  14. package/dist/data/designs/bmw.md +544 -0
  15. package/dist/data/designs/bugatti.md +454 -0
  16. package/dist/data/designs/cal.md +542 -0
  17. package/dist/data/designs/card-heavy.md +250 -0
  18. package/dist/data/designs/claude.md +589 -0
  19. package/dist/data/designs/clay.md +541 -0
  20. package/dist/data/designs/clickhouse.md +544 -0
  21. package/dist/data/designs/cohere.md +451 -0
  22. package/dist/data/designs/coinbase.md +570 -0
  23. package/dist/data/designs/composio.md +506 -0
  24. package/dist/data/designs/content-first.md +236 -0
  25. package/dist/data/designs/cursor.md +537 -0
  26. package/dist/data/designs/data-dashboard.md +300 -0
  27. package/dist/data/designs/dell-1996.md +632 -0
  28. package/dist/data/designs/elevenlabs.md +504 -0
  29. package/dist/data/designs/enterprise-neutral.md +252 -0
  30. package/dist/data/designs/expo.md +526 -0
  31. package/dist/data/designs/ferrari.md +531 -0
  32. package/dist/data/designs/figma.md +578 -0
  33. package/dist/data/designs/framer.md +544 -0
  34. package/dist/data/designs/hashicorp.md +575 -0
  35. package/dist/data/designs/hp.md +670 -0
  36. package/dist/data/designs/ibm.md +550 -0
  37. package/dist/data/designs/intercom.md +546 -0
  38. package/dist/data/designs/ios-acorns-android.md +430 -0
  39. package/dist/data/designs/ios-acorns-expo.md +381 -0
  40. package/dist/data/designs/ios-acorns-swiftui.md +378 -0
  41. package/dist/data/designs/ios-acorns.md +384 -0
  42. package/dist/data/designs/ios-airbnb-android.md +658 -0
  43. package/dist/data/designs/ios-airbnb-expo.md +457 -0
  44. package/dist/data/designs/ios-airbnb-swiftui.md +464 -0
  45. package/dist/data/designs/ios-airbnb.md +410 -0
  46. package/dist/data/designs/ios-alltrails-android.md +451 -0
  47. package/dist/data/designs/ios-alltrails-expo.md +400 -0
  48. package/dist/data/designs/ios-alltrails-swiftui.md +343 -0
  49. package/dist/data/designs/ios-alltrails.md +344 -0
  50. package/dist/data/designs/ios-amazon-android.md +686 -0
  51. package/dist/data/designs/ios-amazon-expo.md +433 -0
  52. package/dist/data/designs/ios-amazon-music-android.md +416 -0
  53. package/dist/data/designs/ios-amazon-music-expo.md +368 -0
  54. package/dist/data/designs/ios-amazon-music-swiftui.md +436 -0
  55. package/dist/data/designs/ios-amazon-music.md +389 -0
  56. package/dist/data/designs/ios-amazon-swiftui.md +460 -0
  57. package/dist/data/designs/ios-amazon.md +440 -0
  58. package/dist/data/designs/ios-apple-fitness-android.md +462 -0
  59. package/dist/data/designs/ios-apple-fitness-expo.md +373 -0
  60. package/dist/data/designs/ios-apple-fitness-swiftui.md +373 -0
  61. package/dist/data/designs/ios-apple-fitness.md +399 -0
  62. package/dist/data/designs/ios-apple-maps-android.md +646 -0
  63. package/dist/data/designs/ios-apple-maps-expo.md +557 -0
  64. package/dist/data/designs/ios-apple-maps-swiftui.md +588 -0
  65. package/dist/data/designs/ios-apple-maps.md +447 -0
  66. package/dist/data/designs/ios-apple-music-android.md +737 -0
  67. package/dist/data/designs/ios-apple-music-expo.md +596 -0
  68. package/dist/data/designs/ios-apple-music-swiftui.md +578 -0
  69. package/dist/data/designs/ios-apple-music.md +494 -0
  70. package/dist/data/designs/ios-apple-notes-android.md +675 -0
  71. package/dist/data/designs/ios-apple-notes-expo.md +468 -0
  72. package/dist/data/designs/ios-apple-notes-swiftui.md +489 -0
  73. package/dist/data/designs/ios-apple-notes.md +413 -0
  74. package/dist/data/designs/ios-apple-tv-android.md +405 -0
  75. package/dist/data/designs/ios-apple-tv-expo.md +341 -0
  76. package/dist/data/designs/ios-apple-tv-swiftui.md +348 -0
  77. package/dist/data/designs/ios-apple-tv.md +390 -0
  78. package/dist/data/designs/ios-apple-wallet-android.md +617 -0
  79. package/dist/data/designs/ios-apple-wallet-expo.md +487 -0
  80. package/dist/data/designs/ios-apple-wallet-swiftui.md +425 -0
  81. package/dist/data/designs/ios-apple-wallet.md +360 -0
  82. package/dist/data/designs/ios-asana-android.md +435 -0
  83. package/dist/data/designs/ios-asana-expo.md +411 -0
  84. package/dist/data/designs/ios-asana-swiftui.md +416 -0
  85. package/dist/data/designs/ios-asana.md +433 -0
  86. package/dist/data/designs/ios-audible-android.md +450 -0
  87. package/dist/data/designs/ios-audible-expo.md +328 -0
  88. package/dist/data/designs/ios-audible-swiftui.md +418 -0
  89. package/dist/data/designs/ios-audible.md +364 -0
  90. package/dist/data/designs/ios-bandcamp-android.md +471 -0
  91. package/dist/data/designs/ios-bandcamp-expo.md +378 -0
  92. package/dist/data/designs/ios-bandcamp-swiftui.md +374 -0
  93. package/dist/data/designs/ios-bandcamp.md +372 -0
  94. package/dist/data/designs/ios-bear-android.md +496 -0
  95. package/dist/data/designs/ios-bear-expo.md +449 -0
  96. package/dist/data/designs/ios-bear-swiftui.md +479 -0
  97. package/dist/data/designs/ios-bear.md +412 -0
  98. package/dist/data/designs/ios-bereal-android.md +392 -0
  99. package/dist/data/designs/ios-bereal-expo.md +299 -0
  100. package/dist/data/designs/ios-bereal-swiftui.md +319 -0
  101. package/dist/data/designs/ios-bereal.md +336 -0
  102. package/dist/data/designs/ios-binance-android.md +481 -0
  103. package/dist/data/designs/ios-binance-expo.md +404 -0
  104. package/dist/data/designs/ios-binance-swiftui.md +418 -0
  105. package/dist/data/designs/ios-binance.md +410 -0
  106. package/dist/data/designs/ios-bluesky-android.md +442 -0
  107. package/dist/data/designs/ios-bluesky-expo.md +362 -0
  108. package/dist/data/designs/ios-bluesky-swiftui.md +328 -0
  109. package/dist/data/designs/ios-bluesky.md +338 -0
  110. package/dist/data/designs/ios-booking-android.md +471 -0
  111. package/dist/data/designs/ios-booking-expo.md +364 -0
  112. package/dist/data/designs/ios-booking-swiftui.md +377 -0
  113. package/dist/data/designs/ios-booking.md +346 -0
  114. package/dist/data/designs/ios-bumble-android.md +756 -0
  115. package/dist/data/designs/ios-bumble-expo.md +629 -0
  116. package/dist/data/designs/ios-bumble-swiftui.md +546 -0
  117. package/dist/data/designs/ios-bumble.md +424 -0
  118. package/dist/data/designs/ios-cal-ai-android.md +664 -0
  119. package/dist/data/designs/ios-cal-ai-expo.md +415 -0
  120. package/dist/data/designs/ios-cal-ai-swiftui.md +486 -0
  121. package/dist/data/designs/ios-cal-ai.md +387 -0
  122. package/dist/data/designs/ios-calm-android.md +431 -0
  123. package/dist/data/designs/ios-calm-expo.md +384 -0
  124. package/dist/data/designs/ios-calm-swiftui.md +327 -0
  125. package/dist/data/designs/ios-calm.md +356 -0
  126. package/dist/data/designs/ios-canva-android.md +469 -0
  127. package/dist/data/designs/ios-canva-expo.md +374 -0
  128. package/dist/data/designs/ios-canva-swiftui.md +422 -0
  129. package/dist/data/designs/ios-canva.md +395 -0
  130. package/dist/data/designs/ios-cash-app-android.md +601 -0
  131. package/dist/data/designs/ios-cash-app-expo.md +453 -0
  132. package/dist/data/designs/ios-cash-app-swiftui.md +463 -0
  133. package/dist/data/designs/ios-cash-app.md +365 -0
  134. package/dist/data/designs/ios-character-ai-android.md +489 -0
  135. package/dist/data/designs/ios-character-ai-expo.md +420 -0
  136. package/dist/data/designs/ios-character-ai-swiftui.md +417 -0
  137. package/dist/data/designs/ios-character-ai.md +392 -0
  138. package/dist/data/designs/ios-charles-schwab-android.md +454 -0
  139. package/dist/data/designs/ios-charles-schwab-expo.md +388 -0
  140. package/dist/data/designs/ios-charles-schwab-swiftui.md +394 -0
  141. package/dist/data/designs/ios-charles-schwab.md +380 -0
  142. package/dist/data/designs/ios-chatgpt-android.md +753 -0
  143. package/dist/data/designs/ios-chatgpt-expo.md +644 -0
  144. package/dist/data/designs/ios-chatgpt-swiftui.md +653 -0
  145. package/dist/data/designs/ios-chatgpt.md +466 -0
  146. package/dist/data/designs/ios-chime-android.md +438 -0
  147. package/dist/data/designs/ios-chime-expo.md +419 -0
  148. package/dist/data/designs/ios-chime-swiftui.md +383 -0
  149. package/dist/data/designs/ios-chime.md +389 -0
  150. package/dist/data/designs/ios-chipotle-android.md +397 -0
  151. package/dist/data/designs/ios-chipotle-expo.md +301 -0
  152. package/dist/data/designs/ios-chipotle-swiftui.md +345 -0
  153. package/dist/data/designs/ios-chipotle.md +340 -0
  154. package/dist/data/designs/ios-citymapper-android.md +466 -0
  155. package/dist/data/designs/ios-citymapper-expo.md +420 -0
  156. package/dist/data/designs/ios-citymapper-swiftui.md +424 -0
  157. package/dist/data/designs/ios-citymapper.md +394 -0
  158. package/dist/data/designs/ios-claude-android.md +625 -0
  159. package/dist/data/designs/ios-claude-expo.md +671 -0
  160. package/dist/data/designs/ios-claude-swiftui.md +649 -0
  161. package/dist/data/designs/ios-claude.md +447 -0
  162. package/dist/data/designs/ios-clickup-android.md +484 -0
  163. package/dist/data/designs/ios-clickup-expo.md +423 -0
  164. package/dist/data/designs/ios-clickup-swiftui.md +416 -0
  165. package/dist/data/designs/ios-clickup.md +431 -0
  166. package/dist/data/designs/ios-clubhouse-android.md +524 -0
  167. package/dist/data/designs/ios-clubhouse-expo.md +425 -0
  168. package/dist/data/designs/ios-clubhouse-swiftui.md +447 -0
  169. package/dist/data/designs/ios-clubhouse.md +406 -0
  170. package/dist/data/designs/ios-coffee-meets-bagel-android.md +461 -0
  171. package/dist/data/designs/ios-coffee-meets-bagel-expo.md +372 -0
  172. package/dist/data/designs/ios-coffee-meets-bagel-swiftui.md +368 -0
  173. package/dist/data/designs/ios-coffee-meets-bagel.md +376 -0
  174. package/dist/data/designs/ios-coinbase-android.md +611 -0
  175. package/dist/data/designs/ios-coinbase-expo.md +500 -0
  176. package/dist/data/designs/ios-coinbase-swiftui.md +490 -0
  177. package/dist/data/designs/ios-coinbase.md +409 -0
  178. package/dist/data/designs/ios-copilot-android.md +625 -0
  179. package/dist/data/designs/ios-copilot-expo.md +423 -0
  180. package/dist/data/designs/ios-copilot-swiftui.md +471 -0
  181. package/dist/data/designs/ios-copilot.md +367 -0
  182. package/dist/data/designs/ios-craft-android.md +459 -0
  183. package/dist/data/designs/ios-craft-expo.md +417 -0
  184. package/dist/data/designs/ios-craft-swiftui.md +449 -0
  185. package/dist/data/designs/ios-craft.md +449 -0
  186. package/dist/data/designs/ios-crunchyroll-android.md +432 -0
  187. package/dist/data/designs/ios-crunchyroll-expo.md +388 -0
  188. package/dist/data/designs/ios-crunchyroll-swiftui.md +417 -0
  189. package/dist/data/designs/ios-crunchyroll.md +388 -0
  190. package/dist/data/designs/ios-crypto-com-android.md +461 -0
  191. package/dist/data/designs/ios-crypto-com-expo.md +404 -0
  192. package/dist/data/designs/ios-crypto-com-swiftui.md +419 -0
  193. package/dist/data/designs/ios-crypto-com.md +410 -0
  194. package/dist/data/designs/ios-deepseek-android.md +471 -0
  195. package/dist/data/designs/ios-deepseek-expo.md +391 -0
  196. package/dist/data/designs/ios-deepseek-swiftui.md +354 -0
  197. package/dist/data/designs/ios-deepseek.md +393 -0
  198. package/dist/data/designs/ios-deezer-android.md +475 -0
  199. package/dist/data/designs/ios-deezer-expo.md +400 -0
  200. package/dist/data/designs/ios-deezer-swiftui.md +430 -0
  201. package/dist/data/designs/ios-deezer.md +388 -0
  202. package/dist/data/designs/ios-deliveroo-android.md +493 -0
  203. package/dist/data/designs/ios-deliveroo-expo.md +424 -0
  204. package/dist/data/designs/ios-deliveroo-swiftui.md +398 -0
  205. package/dist/data/designs/ios-deliveroo.md +420 -0
  206. package/dist/data/designs/ios-delta-android.md +439 -0
  207. package/dist/data/designs/ios-delta-expo.md +381 -0
  208. package/dist/data/designs/ios-delta-swiftui.md +400 -0
  209. package/dist/data/designs/ios-delta.md +397 -0
  210. package/dist/data/designs/ios-discord-android.md +611 -0
  211. package/dist/data/designs/ios-discord-expo.md +618 -0
  212. package/dist/data/designs/ios-discord-swiftui.md +630 -0
  213. package/dist/data/designs/ios-discord.md +451 -0
  214. package/dist/data/designs/ios-disney-plus-android.md +464 -0
  215. package/dist/data/designs/ios-disney-plus-expo.md +358 -0
  216. package/dist/data/designs/ios-disney-plus-swiftui.md +412 -0
  217. package/dist/data/designs/ios-disney-plus.md +355 -0
  218. package/dist/data/designs/ios-dominos-android.md +417 -0
  219. package/dist/data/designs/ios-dominos-expo.md +316 -0
  220. package/dist/data/designs/ios-dominos-swiftui.md +340 -0
  221. package/dist/data/designs/ios-dominos.md +347 -0
  222. package/dist/data/designs/ios-doordash-android.md +527 -0
  223. package/dist/data/designs/ios-doordash-expo.md +323 -0
  224. package/dist/data/designs/ios-doordash-swiftui.md +301 -0
  225. package/dist/data/designs/ios-doordash.md +393 -0
  226. package/dist/data/designs/ios-dropbox-android.md +522 -0
  227. package/dist/data/designs/ios-dropbox-expo.md +393 -0
  228. package/dist/data/designs/ios-dropbox-swiftui.md +400 -0
  229. package/dist/data/designs/ios-dropbox.md +374 -0
  230. package/dist/data/designs/ios-duolingo-android.md +641 -0
  231. package/dist/data/designs/ios-duolingo-expo.md +597 -0
  232. package/dist/data/designs/ios-duolingo-swiftui.md +539 -0
  233. package/dist/data/designs/ios-duolingo.md +409 -0
  234. package/dist/data/designs/ios-ebay-android.md +436 -0
  235. package/dist/data/designs/ios-ebay-expo.md +344 -0
  236. package/dist/data/designs/ios-ebay-swiftui.md +308 -0
  237. package/dist/data/designs/ios-ebay.md +355 -0
  238. package/dist/data/designs/ios-espn-android.md +468 -0
  239. package/dist/data/designs/ios-espn-expo.md +387 -0
  240. package/dist/data/designs/ios-espn-swiftui.md +410 -0
  241. package/dist/data/designs/ios-espn.md +384 -0
  242. package/dist/data/designs/ios-etsy-android.md +439 -0
  243. package/dist/data/designs/ios-etsy-expo.md +351 -0
  244. package/dist/data/designs/ios-etsy-swiftui.md +296 -0
  245. package/dist/data/designs/ios-etsy.md +355 -0
  246. package/dist/data/designs/ios-evernote-android.md +419 -0
  247. package/dist/data/designs/ios-evernote-expo.md +379 -0
  248. package/dist/data/designs/ios-evernote-swiftui.md +380 -0
  249. package/dist/data/designs/ios-evernote.md +416 -0
  250. package/dist/data/designs/ios-expedia-android.md +451 -0
  251. package/dist/data/designs/ios-expedia-expo.md +433 -0
  252. package/dist/data/designs/ios-expedia-swiftui.md +399 -0
  253. package/dist/data/designs/ios-expedia.md +431 -0
  254. package/dist/data/designs/ios-facebook-android.md +628 -0
  255. package/dist/data/designs/ios-facebook-expo.md +471 -0
  256. package/dist/data/designs/ios-facebook-swiftui.md +459 -0
  257. package/dist/data/designs/ios-facebook.md +452 -0
  258. package/dist/data/designs/ios-feeld-android.md +431 -0
  259. package/dist/data/designs/ios-feeld-expo.md +379 -0
  260. package/dist/data/designs/ios-feeld-swiftui.md +401 -0
  261. package/dist/data/designs/ios-feeld.md +378 -0
  262. package/dist/data/designs/ios-fidelity-android.md +426 -0
  263. package/dist/data/designs/ios-fidelity-expo.md +396 -0
  264. package/dist/data/designs/ios-fidelity-swiftui.md +398 -0
  265. package/dist/data/designs/ios-fidelity.md +387 -0
  266. package/dist/data/designs/ios-figma-android.md +578 -0
  267. package/dist/data/designs/ios-figma-expo.md +504 -0
  268. package/dist/data/designs/ios-figma-swiftui.md +542 -0
  269. package/dist/data/designs/ios-figma.md +404 -0
  270. package/dist/data/designs/ios-fitbit-android.md +439 -0
  271. package/dist/data/designs/ios-fitbit-expo.md +389 -0
  272. package/dist/data/designs/ios-fitbit-swiftui.md +380 -0
  273. package/dist/data/designs/ios-fitbit.md +396 -0
  274. package/dist/data/designs/ios-flickr-android.md +506 -0
  275. package/dist/data/designs/ios-flickr-expo.md +434 -0
  276. package/dist/data/designs/ios-flickr-swiftui.md +421 -0
  277. package/dist/data/designs/ios-flickr.md +394 -0
  278. package/dist/data/designs/ios-flighty-android.md +418 -0
  279. package/dist/data/designs/ios-flighty-expo.md +353 -0
  280. package/dist/data/designs/ios-flighty-swiftui.md +337 -0
  281. package/dist/data/designs/ios-flighty.md +357 -0
  282. package/dist/data/designs/ios-flo-android.md +447 -0
  283. package/dist/data/designs/ios-flo-expo.md +363 -0
  284. package/dist/data/designs/ios-flo-swiftui.md +355 -0
  285. package/dist/data/designs/ios-flo.md +351 -0
  286. package/dist/data/designs/ios-garmin-connect-android.md +531 -0
  287. package/dist/data/designs/ios-garmin-connect-expo.md +429 -0
  288. package/dist/data/designs/ios-garmin-connect-swiftui.md +459 -0
  289. package/dist/data/designs/ios-garmin-connect.md +419 -0
  290. package/dist/data/designs/ios-gas-android.md +438 -0
  291. package/dist/data/designs/ios-gas-expo.md +350 -0
  292. package/dist/data/designs/ios-gas-swiftui.md +329 -0
  293. package/dist/data/designs/ios-gas.md +387 -0
  294. package/dist/data/designs/ios-gemini-android.md +568 -0
  295. package/dist/data/designs/ios-gemini-expo.md +416 -0
  296. package/dist/data/designs/ios-gemini-swiftui.md +424 -0
  297. package/dist/data/designs/ios-gemini.md +351 -0
  298. package/dist/data/designs/ios-github-android.md +507 -0
  299. package/dist/data/designs/ios-github-expo.md +486 -0
  300. package/dist/data/designs/ios-github-swiftui.md +459 -0
  301. package/dist/data/designs/ios-github.md +394 -0
  302. package/dist/data/designs/ios-gmail-android.md +548 -0
  303. package/dist/data/designs/ios-gmail-expo.md +457 -0
  304. package/dist/data/designs/ios-gmail-swiftui.md +470 -0
  305. package/dist/data/designs/ios-gmail.md +441 -0
  306. package/dist/data/designs/ios-goodreads-android.md +436 -0
  307. package/dist/data/designs/ios-goodreads-expo.md +407 -0
  308. package/dist/data/designs/ios-goodreads-swiftui.md +378 -0
  309. package/dist/data/designs/ios-goodreads.md +385 -0
  310. package/dist/data/designs/ios-google-calendar-android.md +565 -0
  311. package/dist/data/designs/ios-google-calendar-expo.md +616 -0
  312. package/dist/data/designs/ios-google-calendar-swiftui.md +585 -0
  313. package/dist/data/designs/ios-google-calendar.md +431 -0
  314. package/dist/data/designs/ios-google-maps-android.md +614 -0
  315. package/dist/data/designs/ios-google-maps-expo.md +515 -0
  316. package/dist/data/designs/ios-google-maps-swiftui.md +484 -0
  317. package/dist/data/designs/ios-google-maps.md +451 -0
  318. package/dist/data/designs/ios-grammarly-android.md +449 -0
  319. package/dist/data/designs/ios-grammarly-expo.md +383 -0
  320. package/dist/data/designs/ios-grammarly-swiftui.md +381 -0
  321. package/dist/data/designs/ios-grammarly.md +392 -0
  322. package/dist/data/designs/ios-grindr-android.md +494 -0
  323. package/dist/data/designs/ios-grindr-expo.md +358 -0
  324. package/dist/data/designs/ios-grindr-swiftui.md +357 -0
  325. package/dist/data/designs/ios-grindr.md +356 -0
  326. package/dist/data/designs/ios-grok-android.md +471 -0
  327. package/dist/data/designs/ios-grok-expo.md +388 -0
  328. package/dist/data/designs/ios-grok-swiftui.md +397 -0
  329. package/dist/data/designs/ios-grok.md +357 -0
  330. package/dist/data/designs/ios-groupme-android.md +551 -0
  331. package/dist/data/designs/ios-groupme-expo.md +442 -0
  332. package/dist/data/designs/ios-groupme-swiftui.md +439 -0
  333. package/dist/data/designs/ios-groupme.md +424 -0
  334. package/dist/data/designs/ios-grubhub-android.md +506 -0
  335. package/dist/data/designs/ios-grubhub-expo.md +428 -0
  336. package/dist/data/designs/ios-grubhub-swiftui.md +408 -0
  337. package/dist/data/designs/ios-grubhub.md +427 -0
  338. package/dist/data/designs/ios-happn-android.md +464 -0
  339. package/dist/data/designs/ios-happn-expo.md +411 -0
  340. package/dist/data/designs/ios-happn-swiftui.md +401 -0
  341. package/dist/data/designs/ios-happn.md +400 -0
  342. package/dist/data/designs/ios-headspace-android.md +688 -0
  343. package/dist/data/designs/ios-headspace-expo.md +574 -0
  344. package/dist/data/designs/ios-headspace-swiftui.md +498 -0
  345. package/dist/data/designs/ios-headspace.md +430 -0
  346. package/dist/data/designs/ios-hevy-android.md +473 -0
  347. package/dist/data/designs/ios-hevy-expo.md +405 -0
  348. package/dist/data/designs/ios-hevy-swiftui.md +367 -0
  349. package/dist/data/designs/ios-hevy.md +410 -0
  350. package/dist/data/designs/ios-hinge-android.md +743 -0
  351. package/dist/data/designs/ios-hinge-expo.md +580 -0
  352. package/dist/data/designs/ios-hinge-swiftui.md +512 -0
  353. package/dist/data/designs/ios-hinge.md +405 -0
  354. package/dist/data/designs/ios-hopper-android.md +440 -0
  355. package/dist/data/designs/ios-hopper-expo.md +353 -0
  356. package/dist/data/designs/ios-hopper-swiftui.md +340 -0
  357. package/dist/data/designs/ios-hopper.md +354 -0
  358. package/dist/data/designs/ios-hulu-android.md +435 -0
  359. package/dist/data/designs/ios-hulu-expo.md +331 -0
  360. package/dist/data/designs/ios-hulu-swiftui.md +374 -0
  361. package/dist/data/designs/ios-hulu.md +353 -0
  362. package/dist/data/designs/ios-iheartradio-android.md +481 -0
  363. package/dist/data/designs/ios-iheartradio-expo.md +417 -0
  364. package/dist/data/designs/ios-iheartradio-swiftui.md +423 -0
  365. package/dist/data/designs/ios-iheartradio.md +381 -0
  366. package/dist/data/designs/ios-imessage-android.md +426 -0
  367. package/dist/data/designs/ios-imessage-expo.md +384 -0
  368. package/dist/data/designs/ios-imessage-swiftui.md +378 -0
  369. package/dist/data/designs/ios-imessage.md +394 -0
  370. package/dist/data/designs/ios-instacart-android.md +471 -0
  371. package/dist/data/designs/ios-instacart-expo.md +349 -0
  372. package/dist/data/designs/ios-instacart-swiftui.md +378 -0
  373. package/dist/data/designs/ios-instacart.md +360 -0
  374. package/dist/data/designs/ios-instagram-android.md +646 -0
  375. package/dist/data/designs/ios-instagram-expo.md +310 -0
  376. package/dist/data/designs/ios-instagram-swiftui.md +333 -0
  377. package/dist/data/designs/ios-instagram.md +376 -0
  378. package/dist/data/designs/ios-jira-android.md +432 -0
  379. package/dist/data/designs/ios-jira-expo.md +375 -0
  380. package/dist/data/designs/ios-jira-swiftui.md +433 -0
  381. package/dist/data/designs/ios-jira.md +424 -0
  382. package/dist/data/designs/ios-kakaotalk-android.md +491 -0
  383. package/dist/data/designs/ios-kakaotalk-expo.md +418 -0
  384. package/dist/data/designs/ios-kakaotalk-swiftui.md +406 -0
  385. package/dist/data/designs/ios-kakaotalk.md +414 -0
  386. package/dist/data/designs/ios-kayak-android.md +466 -0
  387. package/dist/data/designs/ios-kayak-expo.md +407 -0
  388. package/dist/data/designs/ios-kayak-swiftui.md +426 -0
  389. package/dist/data/designs/ios-kayak.md +392 -0
  390. package/dist/data/designs/ios-kick-android.md +487 -0
  391. package/dist/data/designs/ios-kick-expo.md +434 -0
  392. package/dist/data/designs/ios-kick-swiftui.md +429 -0
  393. package/dist/data/designs/ios-kick.md +389 -0
  394. package/dist/data/designs/ios-kik-android.md +433 -0
  395. package/dist/data/designs/ios-kik-expo.md +363 -0
  396. package/dist/data/designs/ios-kik-swiftui.md +363 -0
  397. package/dist/data/designs/ios-kik.md +392 -0
  398. package/dist/data/designs/ios-kindle-android.md +439 -0
  399. package/dist/data/designs/ios-kindle-expo.md +356 -0
  400. package/dist/data/designs/ios-kindle-swiftui.md +372 -0
  401. package/dist/data/designs/ios-kindle.md +369 -0
  402. package/dist/data/designs/ios-klarna-android.md +420 -0
  403. package/dist/data/designs/ios-klarna-expo.md +349 -0
  404. package/dist/data/designs/ios-klarna-swiftui.md +360 -0
  405. package/dist/data/designs/ios-klarna.md +356 -0
  406. package/dist/data/designs/ios-lemon8-android.md +492 -0
  407. package/dist/data/designs/ios-lemon8-expo.md +413 -0
  408. package/dist/data/designs/ios-lemon8-swiftui.md +428 -0
  409. package/dist/data/designs/ios-lemon8.md +378 -0
  410. package/dist/data/designs/ios-life360-android.md +474 -0
  411. package/dist/data/designs/ios-life360-expo.md +375 -0
  412. package/dist/data/designs/ios-life360-swiftui.md +390 -0
  413. package/dist/data/designs/ios-life360.md +402 -0
  414. package/dist/data/designs/ios-line-android.md +517 -0
  415. package/dist/data/designs/ios-line-expo.md +402 -0
  416. package/dist/data/designs/ios-line-swiftui.md +361 -0
  417. package/dist/data/designs/ios-line.md +362 -0
  418. package/dist/data/designs/ios-linear-android.md +457 -0
  419. package/dist/data/designs/ios-linear-expo.md +367 -0
  420. package/dist/data/designs/ios-linear-swiftui.md +401 -0
  421. package/dist/data/designs/ios-linear.md +368 -0
  422. package/dist/data/designs/ios-linkedin-android.md +620 -0
  423. package/dist/data/designs/ios-linkedin-expo.md +469 -0
  424. package/dist/data/designs/ios-linkedin-swiftui.md +472 -0
  425. package/dist/data/designs/ios-linkedin.md +444 -0
  426. package/dist/data/designs/ios-locket-android.md +500 -0
  427. package/dist/data/designs/ios-locket-expo.md +375 -0
  428. package/dist/data/designs/ios-locket-swiftui.md +375 -0
  429. package/dist/data/designs/ios-locket.md +381 -0
  430. package/dist/data/designs/ios-lyft-android.md +406 -0
  431. package/dist/data/designs/ios-lyft-expo.md +333 -0
  432. package/dist/data/designs/ios-lyft-swiftui.md +315 -0
  433. package/dist/data/designs/ios-lyft.md +337 -0
  434. package/dist/data/designs/ios-marriott-bonvoy-android.md +488 -0
  435. package/dist/data/designs/ios-marriott-bonvoy-expo.md +412 -0
  436. package/dist/data/designs/ios-marriott-bonvoy-swiftui.md +461 -0
  437. package/dist/data/designs/ios-marriott-bonvoy.md +379 -0
  438. package/dist/data/designs/ios-mastodon-android.md +476 -0
  439. package/dist/data/designs/ios-mastodon-expo.md +379 -0
  440. package/dist/data/designs/ios-mastodon-swiftui.md +349 -0
  441. package/dist/data/designs/ios-mastodon.md +337 -0
  442. package/dist/data/designs/ios-match-android.md +496 -0
  443. package/dist/data/designs/ios-match-expo.md +393 -0
  444. package/dist/data/designs/ios-match-swiftui.md +450 -0
  445. package/dist/data/designs/ios-match.md +382 -0
  446. package/dist/data/designs/ios-max-android.md +454 -0
  447. package/dist/data/designs/ios-max-expo.md +342 -0
  448. package/dist/data/designs/ios-max-swiftui.md +332 -0
  449. package/dist/data/designs/ios-max.md +352 -0
  450. package/dist/data/designs/ios-mcdonalds-android.md +497 -0
  451. package/dist/data/designs/ios-mcdonalds-expo.md +382 -0
  452. package/dist/data/designs/ios-mcdonalds-swiftui.md +394 -0
  453. package/dist/data/designs/ios-mcdonalds.md +410 -0
  454. package/dist/data/designs/ios-messenger-android.md +523 -0
  455. package/dist/data/designs/ios-messenger-expo.md +379 -0
  456. package/dist/data/designs/ios-messenger-swiftui.md +369 -0
  457. package/dist/data/designs/ios-messenger.md +361 -0
  458. package/dist/data/designs/ios-microsoft-teams-android.md +446 -0
  459. package/dist/data/designs/ios-microsoft-teams-expo.md +362 -0
  460. package/dist/data/designs/ios-microsoft-teams-swiftui.md +384 -0
  461. package/dist/data/designs/ios-microsoft-teams.md +359 -0
  462. package/dist/data/designs/ios-midjourney-android.md +503 -0
  463. package/dist/data/designs/ios-midjourney-expo.md +406 -0
  464. package/dist/data/designs/ios-midjourney-swiftui.md +376 -0
  465. package/dist/data/designs/ios-midjourney.md +407 -0
  466. package/dist/data/designs/ios-miro-android.md +475 -0
  467. package/dist/data/designs/ios-miro-expo.md +421 -0
  468. package/dist/data/designs/ios-miro-swiftui.md +407 -0
  469. package/dist/data/designs/ios-miro.md +424 -0
  470. package/dist/data/designs/ios-monday-android.md +426 -0
  471. package/dist/data/designs/ios-monday-expo.md +382 -0
  472. package/dist/data/designs/ios-monday-swiftui.md +386 -0
  473. package/dist/data/designs/ios-monday.md +415 -0
  474. package/dist/data/designs/ios-monzo-android.md +423 -0
  475. package/dist/data/designs/ios-monzo-expo.md +391 -0
  476. package/dist/data/designs/ios-monzo-swiftui.md +371 -0
  477. package/dist/data/designs/ios-monzo.md +382 -0
  478. package/dist/data/designs/ios-myfitnesspal-android.md +631 -0
  479. package/dist/data/designs/ios-myfitnesspal-expo.md +489 -0
  480. package/dist/data/designs/ios-myfitnesspal-swiftui.md +500 -0
  481. package/dist/data/designs/ios-myfitnesspal.md +408 -0
  482. package/dist/data/designs/ios-netflix-android.md +570 -0
  483. package/dist/data/designs/ios-netflix-expo.md +528 -0
  484. package/dist/data/designs/ios-netflix-swiftui.md +543 -0
  485. package/dist/data/designs/ios-netflix.md +476 -0
  486. package/dist/data/designs/ios-nextdoor-android.md +399 -0
  487. package/dist/data/designs/ios-nextdoor-expo.md +317 -0
  488. package/dist/data/designs/ios-nextdoor-swiftui.md +343 -0
  489. package/dist/data/designs/ios-nextdoor.md +332 -0
  490. package/dist/data/designs/ios-nike-run-club-android.md +598 -0
  491. package/dist/data/designs/ios-nike-run-club-expo.md +459 -0
  492. package/dist/data/designs/ios-nike-run-club-swiftui.md +474 -0
  493. package/dist/data/designs/ios-nike-run-club.md +400 -0
  494. package/dist/data/designs/ios-noom-android.md +455 -0
  495. package/dist/data/designs/ios-noom-expo.md +362 -0
  496. package/dist/data/designs/ios-noom-swiftui.md +369 -0
  497. package/dist/data/designs/ios-noom.md +404 -0
  498. package/dist/data/designs/ios-notion-android.md +575 -0
  499. package/dist/data/designs/ios-notion-expo.md +543 -0
  500. package/dist/data/designs/ios-notion-swiftui.md +562 -0
  501. package/dist/data/designs/ios-notion.md +506 -0
  502. package/dist/data/designs/ios-nubank-android.md +447 -0
  503. package/dist/data/designs/ios-nubank-expo.md +391 -0
  504. package/dist/data/designs/ios-nubank-swiftui.md +391 -0
  505. package/dist/data/designs/ios-nubank.md +388 -0
  506. package/dist/data/designs/ios-obsidian-android.md +456 -0
  507. package/dist/data/designs/ios-obsidian-expo.md +401 -0
  508. package/dist/data/designs/ios-obsidian-swiftui.md +412 -0
  509. package/dist/data/designs/ios-obsidian.md +363 -0
  510. package/dist/data/designs/ios-okcupid-android.md +496 -0
  511. package/dist/data/designs/ios-okcupid-expo.md +378 -0
  512. package/dist/data/designs/ios-okcupid-swiftui.md +343 -0
  513. package/dist/data/designs/ios-okcupid.md +364 -0
  514. package/dist/data/designs/ios-opentable-android.md +426 -0
  515. package/dist/data/designs/ios-opentable-expo.md +350 -0
  516. package/dist/data/designs/ios-opentable-swiftui.md +328 -0
  517. package/dist/data/designs/ios-opentable.md +411 -0
  518. package/dist/data/designs/ios-oura-android.md +426 -0
  519. package/dist/data/designs/ios-oura-expo.md +353 -0
  520. package/dist/data/designs/ios-oura-swiftui.md +327 -0
  521. package/dist/data/designs/ios-oura.md +356 -0
  522. package/dist/data/designs/ios-overcast-android.md +508 -0
  523. package/dist/data/designs/ios-overcast-expo.md +420 -0
  524. package/dist/data/designs/ios-overcast-swiftui.md +427 -0
  525. package/dist/data/designs/ios-overcast.md +414 -0
  526. package/dist/data/designs/ios-pandora-android.md +477 -0
  527. package/dist/data/designs/ios-pandora-expo.md +406 -0
  528. package/dist/data/designs/ios-pandora-swiftui.md +413 -0
  529. package/dist/data/designs/ios-pandora.md +366 -0
  530. package/dist/data/designs/ios-panera-android.md +414 -0
  531. package/dist/data/designs/ios-panera-expo.md +352 -0
  532. package/dist/data/designs/ios-panera-swiftui.md +369 -0
  533. package/dist/data/designs/ios-panera.md +412 -0
  534. package/dist/data/designs/ios-paramount-plus-android.md +415 -0
  535. package/dist/data/designs/ios-paramount-plus-expo.md +363 -0
  536. package/dist/data/designs/ios-paramount-plus-swiftui.md +372 -0
  537. package/dist/data/designs/ios-paramount-plus.md +400 -0
  538. package/dist/data/designs/ios-paypal-android.md +535 -0
  539. package/dist/data/designs/ios-paypal-expo.md +429 -0
  540. package/dist/data/designs/ios-paypal-swiftui.md +466 -0
  541. package/dist/data/designs/ios-paypal.md +393 -0
  542. package/dist/data/designs/ios-peacock-android.md +453 -0
  543. package/dist/data/designs/ios-peacock-expo.md +393 -0
  544. package/dist/data/designs/ios-peacock-swiftui.md +420 -0
  545. package/dist/data/designs/ios-peacock.md +411 -0
  546. package/dist/data/designs/ios-peloton-android.md +470 -0
  547. package/dist/data/designs/ios-peloton-expo.md +401 -0
  548. package/dist/data/designs/ios-peloton-swiftui.md +409 -0
  549. package/dist/data/designs/ios-peloton.md +415 -0
  550. package/dist/data/designs/ios-perplexity-android.md +553 -0
  551. package/dist/data/designs/ios-perplexity-expo.md +703 -0
  552. package/dist/data/designs/ios-perplexity-swiftui.md +602 -0
  553. package/dist/data/designs/ios-perplexity.md +453 -0
  554. package/dist/data/designs/ios-pinterest-android.md +551 -0
  555. package/dist/data/designs/ios-pinterest-expo.md +466 -0
  556. package/dist/data/designs/ios-pinterest-swiftui.md +464 -0
  557. package/dist/data/designs/ios-pinterest.md +427 -0
  558. package/dist/data/designs/ios-plenty-of-fish-android.md +462 -0
  559. package/dist/data/designs/ios-plenty-of-fish-expo.md +380 -0
  560. package/dist/data/designs/ios-plenty-of-fish-swiftui.md +429 -0
  561. package/dist/data/designs/ios-plenty-of-fish.md +387 -0
  562. package/dist/data/designs/ios-plex-android.md +403 -0
  563. package/dist/data/designs/ios-plex-expo.md +333 -0
  564. package/dist/data/designs/ios-plex-swiftui.md +349 -0
  565. package/dist/data/designs/ios-plex.md +379 -0
  566. package/dist/data/designs/ios-pluto-tv-android.md +413 -0
  567. package/dist/data/designs/ios-pluto-tv-expo.md +379 -0
  568. package/dist/data/designs/ios-pluto-tv-swiftui.md +411 -0
  569. package/dist/data/designs/ios-pluto-tv.md +362 -0
  570. package/dist/data/designs/ios-pocket-casts-android.md +492 -0
  571. package/dist/data/designs/ios-pocket-casts-expo.md +430 -0
  572. package/dist/data/designs/ios-pocket-casts-swiftui.md +479 -0
  573. package/dist/data/designs/ios-pocket-casts.md +427 -0
  574. package/dist/data/designs/ios-postman-android.md +472 -0
  575. package/dist/data/designs/ios-postman-expo.md +372 -0
  576. package/dist/data/designs/ios-postman-swiftui.md +377 -0
  577. package/dist/data/designs/ios-postman.md +405 -0
  578. package/dist/data/designs/ios-prime-video-android.md +447 -0
  579. package/dist/data/designs/ios-prime-video-expo.md +365 -0
  580. package/dist/data/designs/ios-prime-video-swiftui.md +333 -0
  581. package/dist/data/designs/ios-prime-video.md +351 -0
  582. package/dist/data/designs/ios-quora-android.md +513 -0
  583. package/dist/data/designs/ios-quora-expo.md +362 -0
  584. package/dist/data/designs/ios-quora-swiftui.md +375 -0
  585. package/dist/data/designs/ios-quora.md +359 -0
  586. package/dist/data/designs/ios-raya-android.md +401 -0
  587. package/dist/data/designs/ios-raya-expo.md +366 -0
  588. package/dist/data/designs/ios-raya-swiftui.md +393 -0
  589. package/dist/data/designs/ios-raya.md +366 -0
  590. package/dist/data/designs/ios-reddit-android.md +605 -0
  591. package/dist/data/designs/ios-reddit-expo.md +553 -0
  592. package/dist/data/designs/ios-reddit-swiftui.md +514 -0
  593. package/dist/data/designs/ios-reddit.md +460 -0
  594. package/dist/data/designs/ios-resy-android.md +430 -0
  595. package/dist/data/designs/ios-resy-expo.md +344 -0
  596. package/dist/data/designs/ios-resy-swiftui.md +330 -0
  597. package/dist/data/designs/ios-resy.md +412 -0
  598. package/dist/data/designs/ios-revolut-android.md +433 -0
  599. package/dist/data/designs/ios-revolut-expo.md +379 -0
  600. package/dist/data/designs/ios-revolut-swiftui.md +372 -0
  601. package/dist/data/designs/ios-revolut.md +353 -0
  602. package/dist/data/designs/ios-robinhood-android.md +587 -0
  603. package/dist/data/designs/ios-robinhood-expo.md +416 -0
  604. package/dist/data/designs/ios-robinhood-swiftui.md +431 -0
  605. package/dist/data/designs/ios-robinhood.md +380 -0
  606. package/dist/data/designs/ios-runna-android.md +485 -0
  607. package/dist/data/designs/ios-runna-expo.md +388 -0
  608. package/dist/data/designs/ios-runna-swiftui.md +413 -0
  609. package/dist/data/designs/ios-runna.md +390 -0
  610. package/dist/data/designs/ios-shazam-android.md +436 -0
  611. package/dist/data/designs/ios-shazam-expo.md +348 -0
  612. package/dist/data/designs/ios-shazam-swiftui.md +394 -0
  613. package/dist/data/designs/ios-shazam.md +338 -0
  614. package/dist/data/designs/ios-signal-android.md +462 -0
  615. package/dist/data/designs/ios-signal-expo.md +361 -0
  616. package/dist/data/designs/ios-signal-swiftui.md +350 -0
  617. package/dist/data/designs/ios-signal.md +357 -0
  618. package/dist/data/designs/ios-skype-android.md +398 -0
  619. package/dist/data/designs/ios-skype-expo.md +368 -0
  620. package/dist/data/designs/ios-skype-swiftui.md +369 -0
  621. package/dist/data/designs/ios-skype.md +406 -0
  622. package/dist/data/designs/ios-skyscanner-android.md +451 -0
  623. package/dist/data/designs/ios-skyscanner-expo.md +423 -0
  624. package/dist/data/designs/ios-skyscanner-swiftui.md +419 -0
  625. package/dist/data/designs/ios-skyscanner.md +421 -0
  626. package/dist/data/designs/ios-slack-android.md +695 -0
  627. package/dist/data/designs/ios-slack-expo.md +601 -0
  628. package/dist/data/designs/ios-slack-swiftui.md +594 -0
  629. package/dist/data/designs/ios-slack.md +474 -0
  630. package/dist/data/designs/ios-sleep-cycle-android.md +436 -0
  631. package/dist/data/designs/ios-sleep-cycle-expo.md +380 -0
  632. package/dist/data/designs/ios-sleep-cycle-swiftui.md +409 -0
  633. package/dist/data/designs/ios-sleep-cycle.md +386 -0
  634. package/dist/data/designs/ios-snapchat-android.md +671 -0
  635. package/dist/data/designs/ios-snapchat-expo.md +528 -0
  636. package/dist/data/designs/ios-snapchat-swiftui.md +557 -0
  637. package/dist/data/designs/ios-snapchat.md +478 -0
  638. package/dist/data/designs/ios-sofi-android.md +446 -0
  639. package/dist/data/designs/ios-sofi-expo.md +387 -0
  640. package/dist/data/designs/ios-sofi-swiftui.md +379 -0
  641. package/dist/data/designs/ios-sofi.md +385 -0
  642. package/dist/data/designs/ios-soundcloud-android.md +488 -0
  643. package/dist/data/designs/ios-soundcloud-expo.md +364 -0
  644. package/dist/data/designs/ios-soundcloud-swiftui.md +399 -0
  645. package/dist/data/designs/ios-soundcloud.md +359 -0
  646. package/dist/data/designs/ios-southwest-android.md +446 -0
  647. package/dist/data/designs/ios-southwest-expo.md +389 -0
  648. package/dist/data/designs/ios-southwest-swiftui.md +405 -0
  649. package/dist/data/designs/ios-southwest.md +405 -0
  650. package/dist/data/designs/ios-spotify-android.md +427 -0
  651. package/dist/data/designs/ios-spotify-expo.md +321 -0
  652. package/dist/data/designs/ios-spotify-swiftui.md +312 -0
  653. package/dist/data/designs/ios-spotify.md +366 -0
  654. package/dist/data/designs/ios-starbucks-android.md +622 -0
  655. package/dist/data/designs/ios-starbucks-expo.md +497 -0
  656. package/dist/data/designs/ios-starbucks-swiftui.md +500 -0
  657. package/dist/data/designs/ios-starbucks.md +440 -0
  658. package/dist/data/designs/ios-strava-android.md +656 -0
  659. package/dist/data/designs/ios-strava-expo.md +501 -0
  660. package/dist/data/designs/ios-strava-swiftui.md +465 -0
  661. package/dist/data/designs/ios-strava.md +433 -0
  662. package/dist/data/designs/ios-strong-android.md +479 -0
  663. package/dist/data/designs/ios-strong-expo.md +396 -0
  664. package/dist/data/designs/ios-strong-swiftui.md +363 -0
  665. package/dist/data/designs/ios-strong.md +415 -0
  666. package/dist/data/designs/ios-substack-android.md +440 -0
  667. package/dist/data/designs/ios-substack-expo.md +395 -0
  668. package/dist/data/designs/ios-substack-swiftui.md +371 -0
  669. package/dist/data/designs/ios-substack.md +372 -0
  670. package/dist/data/designs/ios-swiggy-android.md +549 -0
  671. package/dist/data/designs/ios-swiggy-expo.md +443 -0
  672. package/dist/data/designs/ios-swiggy-swiftui.md +471 -0
  673. package/dist/data/designs/ios-swiggy.md +432 -0
  674. package/dist/data/designs/ios-taco-bell-android.md +529 -0
  675. package/dist/data/designs/ios-taco-bell-expo.md +407 -0
  676. package/dist/data/designs/ios-taco-bell-swiftui.md +419 -0
  677. package/dist/data/designs/ios-taco-bell.md +430 -0
  678. package/dist/data/designs/ios-telegram-android.md +676 -0
  679. package/dist/data/designs/ios-telegram-expo.md +594 -0
  680. package/dist/data/designs/ios-telegram-swiftui.md +518 -0
  681. package/dist/data/designs/ios-telegram.md +458 -0
  682. package/dist/data/designs/ios-the-league-android.md +454 -0
  683. package/dist/data/designs/ios-the-league-expo.md +391 -0
  684. package/dist/data/designs/ios-the-league-swiftui.md +409 -0
  685. package/dist/data/designs/ios-the-league.md +368 -0
  686. package/dist/data/designs/ios-things-3-android.md +421 -0
  687. package/dist/data/designs/ios-things-3-expo.md +351 -0
  688. package/dist/data/designs/ios-things-3-swiftui.md +359 -0
  689. package/dist/data/designs/ios-things-3.md +339 -0
  690. package/dist/data/designs/ios-threads-android.md +588 -0
  691. package/dist/data/designs/ios-threads-expo.md +468 -0
  692. package/dist/data/designs/ios-threads-swiftui.md +452 -0
  693. package/dist/data/designs/ios-threads.md +424 -0
  694. package/dist/data/designs/ios-threema-android.md +496 -0
  695. package/dist/data/designs/ios-threema-expo.md +415 -0
  696. package/dist/data/designs/ios-threema-swiftui.md +446 -0
  697. package/dist/data/designs/ios-threema.md +397 -0
  698. package/dist/data/designs/ios-tidal-android.md +398 -0
  699. package/dist/data/designs/ios-tidal-expo.md +323 -0
  700. package/dist/data/designs/ios-tidal-swiftui.md +340 -0
  701. package/dist/data/designs/ios-tidal.md +351 -0
  702. package/dist/data/designs/ios-tiktok-android.md +654 -0
  703. package/dist/data/designs/ios-tiktok-expo.md +578 -0
  704. package/dist/data/designs/ios-tiktok-swiftui.md +595 -0
  705. package/dist/data/designs/ios-tiktok.md +387 -0
  706. package/dist/data/designs/ios-tinder-android.md +681 -0
  707. package/dist/data/designs/ios-tinder-expo.md +512 -0
  708. package/dist/data/designs/ios-tinder-swiftui.md +497 -0
  709. package/dist/data/designs/ios-tinder.md +415 -0
  710. package/dist/data/designs/ios-todoist-android.md +711 -0
  711. package/dist/data/designs/ios-todoist-expo.md +607 -0
  712. package/dist/data/designs/ios-todoist-swiftui.md +573 -0
  713. package/dist/data/designs/ios-todoist.md +418 -0
  714. package/dist/data/designs/ios-trello-android.md +412 -0
  715. package/dist/data/designs/ios-trello-expo.md +332 -0
  716. package/dist/data/designs/ios-trello-swiftui.md +359 -0
  717. package/dist/data/designs/ios-trello.md +344 -0
  718. package/dist/data/designs/ios-tripadvisor-android.md +450 -0
  719. package/dist/data/designs/ios-tripadvisor-expo.md +322 -0
  720. package/dist/data/designs/ios-tripadvisor-swiftui.md +326 -0
  721. package/dist/data/designs/ios-tripadvisor.md +356 -0
  722. package/dist/data/designs/ios-tubi-android.md +453 -0
  723. package/dist/data/designs/ios-tubi-expo.md +419 -0
  724. package/dist/data/designs/ios-tubi-swiftui.md +463 -0
  725. package/dist/data/designs/ios-tubi.md +383 -0
  726. package/dist/data/designs/ios-tumblr-android.md +462 -0
  727. package/dist/data/designs/ios-tumblr-expo.md +374 -0
  728. package/dist/data/designs/ios-tumblr-swiftui.md +380 -0
  729. package/dist/data/designs/ios-tumblr.md +337 -0
  730. package/dist/data/designs/ios-turo-android.md +500 -0
  731. package/dist/data/designs/ios-turo-expo.md +454 -0
  732. package/dist/data/designs/ios-turo-swiftui.md +447 -0
  733. package/dist/data/designs/ios-turo.md +392 -0
  734. package/dist/data/designs/ios-twitch-android.md +412 -0
  735. package/dist/data/designs/ios-twitch-expo.md +342 -0
  736. package/dist/data/designs/ios-twitch-swiftui.md +328 -0
  737. package/dist/data/designs/ios-twitch.md +354 -0
  738. package/dist/data/designs/ios-uber-android.md +637 -0
  739. package/dist/data/designs/ios-uber-eats-android.md +502 -0
  740. package/dist/data/designs/ios-uber-eats-expo.md +407 -0
  741. package/dist/data/designs/ios-uber-eats-swiftui.md +393 -0
  742. package/dist/data/designs/ios-uber-eats.md +353 -0
  743. package/dist/data/designs/ios-uber-expo.md +512 -0
  744. package/dist/data/designs/ios-uber-swiftui.md +483 -0
  745. package/dist/data/designs/ios-uber.md +395 -0
  746. package/dist/data/designs/ios-united-airlines-android.md +494 -0
  747. package/dist/data/designs/ios-united-airlines-expo.md +408 -0
  748. package/dist/data/designs/ios-united-airlines-swiftui.md +453 -0
  749. package/dist/data/designs/ios-united-airlines.md +388 -0
  750. package/dist/data/designs/ios-venmo-android.md +654 -0
  751. package/dist/data/designs/ios-venmo-expo.md +458 -0
  752. package/dist/data/designs/ios-venmo-swiftui.md +469 -0
  753. package/dist/data/designs/ios-venmo.md +436 -0
  754. package/dist/data/designs/ios-vercel-android.md +454 -0
  755. package/dist/data/designs/ios-vercel-expo.md +387 -0
  756. package/dist/data/designs/ios-vercel-swiftui.md +374 -0
  757. package/dist/data/designs/ios-vercel.md +399 -0
  758. package/dist/data/designs/ios-vero-android.md +498 -0
  759. package/dist/data/designs/ios-vero-expo.md +376 -0
  760. package/dist/data/designs/ios-vero-swiftui.md +374 -0
  761. package/dist/data/designs/ios-vero.md +394 -0
  762. package/dist/data/designs/ios-viber-android.md +377 -0
  763. package/dist/data/designs/ios-viber-expo.md +375 -0
  764. package/dist/data/designs/ios-viber-swiftui.md +378 -0
  765. package/dist/data/designs/ios-viber.md +403 -0
  766. package/dist/data/designs/ios-vimeo-android.md +465 -0
  767. package/dist/data/designs/ios-vimeo-expo.md +347 -0
  768. package/dist/data/designs/ios-vimeo-swiftui.md +383 -0
  769. package/dist/data/designs/ios-vimeo.md +403 -0
  770. package/dist/data/designs/ios-vrbo-android.md +488 -0
  771. package/dist/data/designs/ios-vrbo-expo.md +395 -0
  772. package/dist/data/designs/ios-vrbo-swiftui.md +421 -0
  773. package/dist/data/designs/ios-vrbo.md +383 -0
  774. package/dist/data/designs/ios-vsco-android.md +490 -0
  775. package/dist/data/designs/ios-vsco-expo.md +413 -0
  776. package/dist/data/designs/ios-vsco-swiftui.md +449 -0
  777. package/dist/data/designs/ios-vsco.md +412 -0
  778. package/dist/data/designs/ios-walmart-android.md +479 -0
  779. package/dist/data/designs/ios-walmart-expo.md +370 -0
  780. package/dist/data/designs/ios-walmart-swiftui.md +387 -0
  781. package/dist/data/designs/ios-walmart.md +366 -0
  782. package/dist/data/designs/ios-waze-android.md +695 -0
  783. package/dist/data/designs/ios-waze-expo.md +587 -0
  784. package/dist/data/designs/ios-waze-swiftui.md +601 -0
  785. package/dist/data/designs/ios-waze.md +453 -0
  786. package/dist/data/designs/ios-webull-android.md +429 -0
  787. package/dist/data/designs/ios-webull-expo.md +384 -0
  788. package/dist/data/designs/ios-webull-swiftui.md +406 -0
  789. package/dist/data/designs/ios-webull.md +375 -0
  790. package/dist/data/designs/ios-wechat-android.md +545 -0
  791. package/dist/data/designs/ios-wechat-expo.md +398 -0
  792. package/dist/data/designs/ios-wechat-swiftui.md +394 -0
  793. package/dist/data/designs/ios-wechat.md +363 -0
  794. package/dist/data/designs/ios-whatsapp-android.md +568 -0
  795. package/dist/data/designs/ios-whatsapp-expo.md +502 -0
  796. package/dist/data/designs/ios-whatsapp-swiftui.md +483 -0
  797. package/dist/data/designs/ios-whatsapp.md +425 -0
  798. package/dist/data/designs/ios-whoop-android.md +635 -0
  799. package/dist/data/designs/ios-whoop-expo.md +562 -0
  800. package/dist/data/designs/ios-whoop-swiftui.md +553 -0
  801. package/dist/data/designs/ios-whoop.md +419 -0
  802. package/dist/data/designs/ios-wise-android.md +428 -0
  803. package/dist/data/designs/ios-wise-expo.md +357 -0
  804. package/dist/data/designs/ios-wise-swiftui.md +356 -0
  805. package/dist/data/designs/ios-wise.md +361 -0
  806. package/dist/data/designs/ios-x-twitter-android.md +618 -0
  807. package/dist/data/designs/ios-x-twitter-expo.md +442 -0
  808. package/dist/data/designs/ios-x-twitter-swiftui.md +429 -0
  809. package/dist/data/designs/ios-x-twitter.md +432 -0
  810. package/dist/data/designs/ios-yelp-android.md +455 -0
  811. package/dist/data/designs/ios-yelp-expo.md +397 -0
  812. package/dist/data/designs/ios-yelp-swiftui.md +369 -0
  813. package/dist/data/designs/ios-yelp.md +398 -0
  814. package/dist/data/designs/ios-youtube-android.md +668 -0
  815. package/dist/data/designs/ios-youtube-expo.md +435 -0
  816. package/dist/data/designs/ios-youtube-music-android.md +450 -0
  817. package/dist/data/designs/ios-youtube-music-expo.md +404 -0
  818. package/dist/data/designs/ios-youtube-music-swiftui.md +434 -0
  819. package/dist/data/designs/ios-youtube-music.md +381 -0
  820. package/dist/data/designs/ios-youtube-swiftui.md +496 -0
  821. package/dist/data/designs/ios-youtube.md +466 -0
  822. package/dist/data/designs/ios-zalo-android.md +510 -0
  823. package/dist/data/designs/ios-zalo-expo.md +389 -0
  824. package/dist/data/designs/ios-zalo-swiftui.md +431 -0
  825. package/dist/data/designs/ios-zalo.md +388 -0
  826. package/dist/data/designs/ios-zomato-android.md +527 -0
  827. package/dist/data/designs/ios-zomato-expo.md +437 -0
  828. package/dist/data/designs/ios-zomato-swiftui.md +433 -0
  829. package/dist/data/designs/ios-zomato.md +439 -0
  830. package/dist/data/designs/ios-zoom-android.md +423 -0
  831. package/dist/data/designs/ios-zoom-expo.md +355 -0
  832. package/dist/data/designs/ios-zoom-swiftui.md +379 -0
  833. package/dist/data/designs/ios-zoom.md +357 -0
  834. package/dist/data/designs/ios-zwift-android.md +402 -0
  835. package/dist/data/designs/ios-zwift-expo.md +402 -0
  836. package/dist/data/designs/ios-zwift-swiftui.md +378 -0
  837. package/dist/data/designs/ios-zwift.md +411 -0
  838. package/dist/data/designs/kraken.md +125 -0
  839. package/dist/data/designs/lamborghini.md +288 -0
  840. package/dist/data/designs/linear.app.md +548 -0
  841. package/dist/data/designs/lovable.md +298 -0
  842. package/dist/data/designs/mastercard.md +365 -0
  843. package/dist/data/designs/material-clean.md +289 -0
  844. package/dist/data/designs/meta.md +683 -0
  845. package/dist/data/designs/midnight-pro.md +256 -0
  846. package/dist/data/designs/minimal-brutalist.md +245 -0
  847. package/dist/data/designs/minimax.md +746 -0
  848. package/dist/data/designs/mintlify.md +852 -0
  849. package/dist/data/designs/miro.md +825 -0
  850. package/dist/data/designs/mistral.ai.md +773 -0
  851. package/dist/data/designs/mongodb.md +767 -0
  852. package/dist/data/designs/nike.md +575 -0
  853. package/dist/data/designs/nintendo-2001.md +649 -0
  854. package/dist/data/designs/notion.md +821 -0
  855. package/dist/data/designs/nova-mobile-design-md.md +235 -0
  856. package/dist/data/designs/nvidia.md +640 -0
  857. package/dist/data/designs/ollama.md +539 -0
  858. package/dist/data/designs/opencode.ai.md +521 -0
  859. package/dist/data/designs/pinterest.md +597 -0
  860. package/dist/data/designs/playful-color.md +253 -0
  861. package/dist/data/designs/playstation.md +661 -0
  862. package/dist/data/designs/posthog.md +690 -0
  863. package/dist/data/designs/raycast.md +669 -0
  864. package/dist/data/designs/renault.md +589 -0
  865. package/dist/data/designs/replicate.md +616 -0
  866. package/dist/data/designs/resend.md +585 -0
  867. package/dist/data/designs/revolut.md +636 -0
  868. package/dist/data/designs/runwayml.md +244 -0
  869. package/dist/data/designs/sanity.md +357 -0
  870. package/dist/data/designs/sentry.md +551 -0
  871. package/dist/data/designs/shopify.md +516 -0
  872. package/dist/data/designs/slack.md +482 -0
  873. package/dist/data/designs/soft-glass.md +258 -0
  874. package/dist/data/designs/spacex.md +363 -0
  875. package/dist/data/designs/spotify.md +246 -0
  876. package/dist/data/designs/starbucks.md +580 -0
  877. package/dist/data/designs/stripe.md +487 -0
  878. package/dist/data/designs/supabase.md +462 -0
  879. package/dist/data/designs/superhuman.md +448 -0
  880. package/dist/data/designs/tesla.md +286 -0
  881. package/dist/data/designs/theverge.md +339 -0
  882. package/dist/data/designs/together.ai.md +633 -0
  883. package/dist/data/designs/uber.md +636 -0
  884. package/dist/data/designs/vercel.md +736 -0
  885. package/dist/data/designs/vodafone.md +538 -0
  886. package/dist/data/designs/voltagent.md +521 -0
  887. package/dist/data/designs/warp.md +526 -0
  888. package/dist/data/designs/webflow.md +588 -0
  889. package/dist/data/designs/wired.md +497 -0
  890. package/dist/data/designs/wise.md +544 -0
  891. package/dist/data/designs/x.ai.md +465 -0
  892. package/dist/data/designs/zapier.md +537 -0
  893. package/dist/data/index.json +2600 -0
  894. package/dist/httpServer.js +83 -0
  895. package/dist/index.js +13 -0
  896. package/dist/server.js +32 -0
  897. package/dist/services/designStore.js +59 -0
  898. package/dist/services/linter.js +87 -0
  899. package/dist/services/sectionParser.js +154 -0
  900. package/dist/tools/authoring.js +131 -0
  901. package/dist/tools/browse.js +232 -0
  902. package/dist/tools/diff.js +88 -0
  903. package/dist/tools/getDesign.js +216 -0
  904. package/dist/tools/guardrails.js +87 -0
  905. package/dist/tools/lint.js +104 -0
  906. package/dist/types.js +1 -0
  907. package/package.json +65 -0
@@ -0,0 +1,676 @@
1
+ # Telegram (iOS) — Jetpack Compose Implementation Guide
2
+
3
+ Companion to [DESIGN.md](DESIGN.md) — the framework-neutral spec. This file ports Telegram's visual language to **Android with Jetpack Compose (Material 3)**: a themeable color system, a `Typography` set, paste-ready `@Composable`s, `Modifier`s, motion, and haptics.
4
+
5
+ > Why a Compose guide for an iOS-referenced app? The DESIGN.md tokens are platform-neutral. Telegram's whole identity is that the *accent is a single user-chosen variable* and the UI rhythm (bubble shape, type scale, gesture language) holds steady no matter what color is poured in. This file keeps that identity — a themeable accent via `CompositionLocal`, the 17dp bubble with a 6dp notch tail, the floating voice pill, Lottie animated emoji — while making everything idiomatic Android: `NavigationBar` instead of a UITabBar, a translucent `Surface` instead of `.regularMaterial` blur, `sp`/`dp` instead of `pt`.
6
+
7
+ Assumes Compose BOM `2024.09+`, Kotlin `2.0+`, `minSdk 24`, Material 3, [Coil](https://coil-kt.github.io/coil/) `2.6+` for avatars, and `com.airbnb.android:lottie-compose` `6.4+` for animated emoji & sticker playback. No color extraction — Telegram's accent comes from the theme, not media, so `androidx.palette` is not required.
8
+
9
+ ## 1. Color Tokens
10
+
11
+ Telegram's entire color system is themeable — the accent flows through as a single variable. Model it as a `TelegramTheme` data class hoisted into a `CompositionLocal` so every consuming composable re-tints live when the user picks a new accent.
12
+
13
+ ```kotlin
14
+ // ui/theme/TelegramColors.kt
15
+ import androidx.compose.ui.graphics.Color
16
+
17
+ object TelegramColors {
18
+ // Default Accent (user-themeable)
19
+ val Accent = Color(0xFF0088CC)
20
+ val AccentLight = Color(0xFF40A7E3)
21
+ val AccentPressed = Color(0xFF0071B0)
22
+
23
+ // Bubble (default blue theme)
24
+ val BubbleOutgoing = Color(0xFF2B86FD)
25
+ val BubbleOutgoingTop = Color(0xFF2B86FD) // gradient top
26
+ val BubbleOutgoingBot = Color(0xFF61B3FF) // gradient bottom
27
+ val BubbleIncomingLight = Color(0xFFFFFFFF)
28
+ val BubbleIncomingDark = Color(0xFF2A2A2A)
29
+ val SecretOutgoing = Color(0xFF4EA53C)
30
+
31
+ // Canvas
32
+ val CanvasLight = Color(0xFFFFFFFF)
33
+ val CanvasDark = Color(0xFF212121)
34
+ val CanvasOLED = Color(0xFF000000)
35
+ val ChatBGBlue = Color(0xFFDBE7F4) // default soft-blue wallpaper
36
+ val Surface1Light = Color(0xFFF7F7F7)
37
+ val Surface2Light = Color(0xFFEFEFF4)
38
+ val Surface1Dark = Color(0xFF1C1C1C)
39
+ val Surface2Dark = Color(0xFF2C2C2E)
40
+ val DividerLight = Color(0xFFC7C7CC)
41
+ val DividerDark = Color(0xFF383838)
42
+ val OLEDSurface = Color(0xFF0A0A0A)
43
+
44
+ // Text
45
+ val TextPrimary = Color(0xFF000000)
46
+ val TextSecondary = Color(0xFF707579)
47
+ val TextTertiary = Color(0xFFA0A6AD)
48
+ val TextPrimaryDark = Color(0xFFFFFFFF)
49
+ val TextSecondaryDark = Color(0xFF8D8E93)
50
+
51
+ // Semantic
52
+ val ReadBlue = Color(0xFF0088CC)
53
+ val SentGray = Color(0xFFB1B1B1)
54
+ val ErrorRed = Color(0xFFE53935)
55
+ val Destructive = Color(0xFFE35561)
56
+ val OnlineGreen = Color(0xFF4DD364)
57
+ val PremiumA = Color(0xFFAE6FFD)
58
+ val PremiumB = Color(0xFFCE6BFF)
59
+ }
60
+
61
+ // Sender color palette (group chats) — assign by stable sender id
62
+ object TgSenderColors {
63
+ private val palette = listOf(
64
+ Color(0xFFFC5C51), Color(0xFFFA790F), Color(0xFF895DD5), Color(0xFF0FB297),
65
+ Color(0xFF00C1A6), Color(0xFF3CA5EC), Color(0xFFFF5274),
66
+ )
67
+ fun forSender(id: Int): Color = palette[(id % palette.size + palette.size) % palette.size]
68
+ }
69
+ ```
70
+
71
+ ### Themeable accent via CompositionLocal
72
+
73
+ ```kotlin
74
+ // ui/theme/Theme.kt
75
+ import androidx.compose.material3.darkColorScheme
76
+ import androidx.compose.material3.lightColorScheme
77
+ import androidx.compose.material3.MaterialTheme
78
+ import androidx.compose.runtime.*
79
+ import androidx.compose.ui.graphics.Color
80
+
81
+ data class TelegramTheme(
82
+ val accent: Color = TelegramColors.Accent,
83
+ val outgoingBubble: Color = TelegramColors.BubbleOutgoing,
84
+ val useGradientBubbles: Boolean = false,
85
+ val isDark: Boolean = false,
86
+ val isOLED: Boolean = false,
87
+ ) {
88
+ val canvas: Color get() = when {
89
+ isOLED -> TelegramColors.CanvasOLED
90
+ isDark -> TelegramColors.CanvasDark
91
+ else -> TelegramColors.CanvasLight
92
+ }
93
+ val textPrimary: Color get() = if (isDark) TelegramColors.TextPrimaryDark else TelegramColors.TextPrimary
94
+ val textSecondary: Color get() = if (isDark) TelegramColors.TextSecondaryDark else TelegramColors.TextSecondary
95
+ val incomingBubble: Color get() = if (isDark) TelegramColors.BubbleIncomingDark else TelegramColors.BubbleIncomingLight
96
+ }
97
+
98
+ val LocalTelegramTheme = staticCompositionLocalOf { TelegramTheme() }
99
+
100
+ @Composable
101
+ fun TelegramAppTheme(
102
+ theme: TelegramTheme = TelegramTheme(),
103
+ content: @Composable () -> Unit,
104
+ ) {
105
+ // Derive a Material 3 scheme from the live accent so ripples/dividers inherit it
106
+ val scheme = if (theme.isDark) {
107
+ darkColorScheme(
108
+ primary = theme.accent,
109
+ background = theme.canvas,
110
+ surface = if (theme.isOLED) TelegramColors.OLEDSurface else TelegramColors.Surface1Dark,
111
+ onSurface = TelegramColors.TextPrimaryDark,
112
+ outline = TelegramColors.DividerDark,
113
+ error = TelegramColors.ErrorRed,
114
+ )
115
+ } else {
116
+ lightColorScheme(
117
+ primary = theme.accent,
118
+ background = theme.canvas,
119
+ surface = TelegramColors.Surface1Light,
120
+ onSurface = TelegramColors.TextPrimary,
121
+ outline = TelegramColors.DividerLight,
122
+ error = TelegramColors.ErrorRed,
123
+ )
124
+ }
125
+ CompositionLocalProvider(LocalTelegramTheme provides theme) {
126
+ MaterialTheme(colorScheme = scheme, typography = TelegramTypography, content = content)
127
+ }
128
+ }
129
+ ```
130
+
131
+ Change `theme.accent` (e.g. to `TgSenderColors`-style green, rose, or purple) at the app root and every consuming view re-tints live — that *is* the Telegram product.
132
+
133
+ ## 2. Typography
134
+
135
+ Telegram ships **no proprietary font** on mobile — it uses the platform UI font. On iOS that's SF Pro; the Android system equivalent is Roboto, so use `FontFamily.Default` and `FontFamily.Monospace` for code blocks. Sizes follow Apple HIG / Material parity at 1:1 pt→sp.
136
+
137
+ ```kotlin
138
+ // ui/theme/TelegramType.kt
139
+ import androidx.compose.material3.Typography
140
+ import androidx.compose.ui.text.TextStyle
141
+ import androidx.compose.ui.text.font.FontFamily
142
+ import androidx.compose.ui.text.font.FontStyle
143
+ import androidx.compose.ui.text.font.FontWeight
144
+ import androidx.compose.ui.unit.sp
145
+
146
+ private val Sans = FontFamily.Default // Roboto on Android (Telegram uses the system UI font)
147
+ private val Mono = FontFamily.Monospace // code blocks / pre
148
+
149
+ // Named ramp — mirrors DESIGN.md §3 exactly (pt → sp 1:1, weights preserved)
150
+ object TelegramText {
151
+ val LargeTitle = TextStyle(Sans, fontWeight = FontWeight.Bold, fontSize = 34.sp, lineHeight = 38.sp, letterSpacing = 0.37.sp)
152
+ val ScreenTitle = TextStyle(Sans, fontWeight = FontWeight.SemiBold, fontSize = 17.sp, lineHeight = 20.sp, letterSpacing = (-0.4).sp)
153
+ val ContactName = TextStyle(Sans, fontWeight = FontWeight.SemiBold, fontSize = 17.sp, lineHeight = 21.sp, letterSpacing = (-0.4).sp)
154
+ val BubbleBody = TextStyle(Sans, fontWeight = FontWeight.Normal, fontSize = 17.sp, lineHeight = 22.sp, letterSpacing = (-0.4).sp)
155
+ val GroupSender = TextStyle(Sans, fontWeight = FontWeight.SemiBold, fontSize = 14.sp, lineHeight = 17.sp, letterSpacing = (-0.2).sp)
156
+ val MessagePreview = TextStyle(Sans, fontWeight = FontWeight.Normal, fontSize = 15.sp, lineHeight = 20.sp, letterSpacing = (-0.2).sp)
157
+ val TimestampList = TextStyle(Sans, fontWeight = FontWeight.Normal, fontSize = 13.sp, lineHeight = 16.sp)
158
+ val TimestampBubble = TextStyle(Sans, fontWeight = FontWeight.Normal, fontSize = 11.sp, lineHeight = 11.sp)
159
+ val SectionHeader = TextStyle(Sans, fontWeight = FontWeight.Normal, fontSize = 13.sp, lineHeight = 16.sp)
160
+ val Body = TextStyle(Sans, fontWeight = FontWeight.Normal, fontSize = 17.sp, lineHeight = 24.sp, letterSpacing = (-0.4).sp)
161
+ val Callout = TextStyle(Sans, fontWeight = FontWeight.Normal, fontSize = 16.sp, lineHeight = 21.sp, letterSpacing = (-0.3).sp)
162
+ val Footnote = TextStyle(Sans, fontWeight = FontWeight.Normal, fontSize = 13.sp, lineHeight = 17.sp, letterSpacing = (-0.1).sp)
163
+ val Caption = TextStyle(Sans, fontWeight = FontWeight.Normal, fontSize = 12.sp, lineHeight = 16.sp)
164
+ val TabLabel = TextStyle(Sans, fontWeight = FontWeight.Medium, fontSize = 10.sp, lineHeight = 10.sp, letterSpacing = 0.1.sp)
165
+ val Button = TextStyle(Sans, fontWeight = FontWeight.SemiBold, fontSize = 17.sp, lineHeight = 17.sp, letterSpacing = (-0.4).sp)
166
+ val Code = TextStyle(Mono, fontWeight = FontWeight.Normal, fontSize = 15.sp, lineHeight = 21.sp)
167
+ val Blockquote = TextStyle(Sans, fontWeight = FontWeight.Normal, fontStyle = FontStyle.Italic, fontSize = 17.sp, lineHeight = 22.sp, letterSpacing = (-0.4).sp)
168
+ }
169
+
170
+ // Map onto Material 3 slots so stock components inherit the scale
171
+ val TelegramTypography = Typography(
172
+ headlineLarge = TelegramText.LargeTitle,
173
+ titleMedium = TelegramText.ContactName,
174
+ bodyLarge = TelegramText.BubbleBody,
175
+ bodyMedium = TelegramText.MessagePreview,
176
+ labelSmall = TelegramText.TabLabel,
177
+ )
178
+ ```
179
+
180
+ ## 3. Signature Components
181
+
182
+ ### Compose Bar (with morphing send)
183
+
184
+ ```kotlin
185
+ import androidx.compose.foundation.background
186
+ import androidx.compose.foundation.layout.*
187
+ import androidx.compose.foundation.text.BasicTextField
188
+ import androidx.compose.material.icons.Icons
189
+ import androidx.compose.material.icons.filled.*
190
+ import androidx.compose.material3.*
191
+ import androidx.compose.runtime.*
192
+ import androidx.compose.ui.Alignment
193
+ import androidx.compose.ui.Modifier
194
+ import androidx.compose.ui.draw.rotate
195
+ import androidx.compose.ui.hapticfeedback.HapticFeedbackType
196
+ import androidx.compose.ui.platform.LocalHapticFeedback
197
+ import androidx.compose.ui.unit.dp
198
+
199
+ @Composable
200
+ fun TgComposeBar(
201
+ onSend: (String) -> Unit,
202
+ onSendSilent: (String) -> Unit,
203
+ onSchedule: () -> Unit,
204
+ modifier: Modifier = Modifier,
205
+ ) {
206
+ val theme = LocalTelegramTheme.current
207
+ var text by remember { mutableStateOf("") }
208
+ var menuOpen by remember { mutableStateOf(false) }
209
+ val haptics = LocalHapticFeedback.current
210
+
211
+ Row(
212
+ modifier = modifier
213
+ .fillMaxWidth()
214
+ .background(if (theme.isDark) TelegramColors.Surface1Dark else TelegramColors.CanvasLight)
215
+ .padding(horizontal = 16.dp, vertical = 10.dp),
216
+ verticalAlignment = Alignment.CenterVertically,
217
+ horizontalArrangement = Arrangement.spacedBy(16.dp),
218
+ ) {
219
+ Icon(
220
+ Icons.Filled.AttachFile, "Attach",
221
+ tint = theme.textSecondary,
222
+ modifier = Modifier.size(22.dp).rotate(45f),
223
+ )
224
+ BasicTextField(
225
+ value = text,
226
+ onValueChange = { text = it },
227
+ textStyle = TelegramText.Callout.copy(color = theme.textPrimary),
228
+ modifier = Modifier.weight(1f),
229
+ decorationBox = { inner ->
230
+ if (text.isEmpty()) Text("Message", style = TelegramText.Callout, color = TelegramColors.TextTertiary)
231
+ inner()
232
+ },
233
+ )
234
+ Icon(Icons.Filled.EmojiEmotions, "Emoji", tint = theme.textSecondary, modifier = Modifier.size(22.dp))
235
+
236
+ if (text.isEmpty()) {
237
+ Icon(Icons.Filled.Mic, "Voice message", tint = theme.accent, modifier = Modifier.size(22.dp))
238
+ } else {
239
+ Box {
240
+ Icon(
241
+ Icons.Filled.Send, "Send",
242
+ tint = theme.accent,
243
+ modifier = Modifier
244
+ .size(22.dp)
245
+ .combinedClickableSend(
246
+ onClick = {
247
+ haptics.performHapticFeedback(HapticFeedbackType.TextHandleMove) // soft impact on send
248
+ onSend(text); text = ""
249
+ },
250
+ onLongClick = { menuOpen = true },
251
+ ),
252
+ )
253
+ DropdownMenu(menuOpen, onDismissRequest = { menuOpen = false }) {
254
+ DropdownMenuItem(
255
+ text = { Text("Send Without Sound") },
256
+ leadingIcon = { Icon(Icons.Filled.NotificationsOff, null) },
257
+ onClick = { menuOpen = false; onSendSilent(text); text = "" },
258
+ )
259
+ DropdownMenuItem(
260
+ text = { Text("Schedule Message") },
261
+ leadingIcon = { Icon(Icons.Filled.Schedule, null) },
262
+ onClick = { menuOpen = false; onSchedule() },
263
+ )
264
+ DropdownMenuItem(
265
+ text = { Text("Send When Online") },
266
+ leadingIcon = { Icon(Icons.Filled.Person, null) },
267
+ onClick = { menuOpen = false; onSend(text); text = "" },
268
+ )
269
+ }
270
+ }
271
+ }
272
+ }
273
+ }
274
+
275
+ // long-press the send button = the signature silent/scheduled-send gesture
276
+ import androidx.compose.foundation.combinedClickable
277
+ import androidx.compose.foundation.interaction.MutableInteractionSource
278
+ @Composable
279
+ private fun Modifier.combinedClickableSend(onClick: () -> Unit, onLongClick: () -> Unit): Modifier =
280
+ this.combinedClickable(
281
+ interactionSource = remember { MutableInteractionSource() },
282
+ indication = null,
283
+ onClick = onClick,
284
+ onLongClick = onLongClick,
285
+ )
286
+ ```
287
+
288
+ ### Outgoing Bubble (themeable solid + gradient variant, 6dp notch tail)
289
+
290
+ ```kotlin
291
+ import androidx.compose.foundation.shape.RoundedCornerShape
292
+ import androidx.compose.foundation.layout.Box
293
+ import androidx.compose.ui.draw.clip
294
+ import androidx.compose.ui.graphics.Brush
295
+
296
+ @Composable
297
+ fun TgOutgoingBubble(
298
+ text: String,
299
+ timestamp: String,
300
+ isRead: Boolean,
301
+ modifier: Modifier = Modifier,
302
+ ) {
303
+ val theme = LocalTelegramTheme.current
304
+ // 17dp all corners EXCEPT bottom-trailing = 6dp (subtle notch, not a full point)
305
+ val shape = RoundedCornerShape(topStart = 17.dp, topEnd = 17.dp, bottomStart = 17.dp, bottomEnd = 6.dp)
306
+
307
+ Row(modifier.fillMaxWidth().padding(end = 8.dp), horizontalArrangement = Arrangement.End) {
308
+ Spacer(Modifier.weight(0.2f))
309
+ Column(
310
+ modifier = Modifier
311
+ .clip(shape)
312
+ .then(
313
+ if (theme.useGradientBubbles)
314
+ Modifier.background(Brush.verticalGradient(listOf(TelegramColors.BubbleOutgoingTop, TelegramColors.BubbleOutgoingBot)))
315
+ else Modifier.background(theme.outgoingBubble)
316
+ )
317
+ .padding(horizontal = 12.dp, vertical = 8.dp),
318
+ horizontalAlignment = Alignment.End,
319
+ ) {
320
+ Text(text, style = TelegramText.BubbleBody, color = TelegramColors.TextPrimaryDark)
321
+ Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(2.dp)) {
322
+ Text(timestamp, style = TelegramText.TimestampBubble, color = TelegramColors.TextPrimaryDark.copy(alpha = 0.8f))
323
+ Icon(
324
+ if (isRead) Icons.Filled.DoneAll else Icons.Filled.Done,
325
+ contentDescription = if (isRead) "Read" else "Sent",
326
+ tint = TelegramColors.TextPrimaryDark.copy(alpha = 0.9f),
327
+ modifier = Modifier.size(12.dp),
328
+ )
329
+ }
330
+ }
331
+ }
332
+ }
333
+ ```
334
+
335
+ ### Incoming Bubble (tail notch mirrored to bottom-leading)
336
+
337
+ ```kotlin
338
+ import androidx.compose.foundation.border
339
+
340
+ @Composable
341
+ fun TgIncomingBubble(
342
+ text: String,
343
+ senderName: String?,
344
+ senderId: Int?,
345
+ modifier: Modifier = Modifier,
346
+ ) {
347
+ val theme = LocalTelegramTheme.current
348
+ val shape = RoundedCornerShape(topStart = 17.dp, topEnd = 17.dp, bottomStart = 6.dp, bottomEnd = 17.dp)
349
+
350
+ Row(modifier.fillMaxWidth().padding(start = 8.dp)) {
351
+ Column(
352
+ modifier = Modifier
353
+ .clip(shape)
354
+ .background(theme.incomingBubble)
355
+ .then(if (theme.isDark) Modifier else Modifier.border(1.dp, Color(0xFFE5E5E5), shape))
356
+ .padding(horizontal = 12.dp, vertical = 8.dp),
357
+ ) {
358
+ if (senderName != null && senderId != null) {
359
+ Text(senderName, style = TelegramText.GroupSender, color = TgSenderColors.forSender(senderId))
360
+ }
361
+ Text(text, style = TelegramText.BubbleBody, color = theme.textPrimary)
362
+ }
363
+ Spacer(Modifier.weight(0.2f))
364
+ }
365
+ }
366
+ ```
367
+
368
+ ### Floating Voice Mini-Player
369
+
370
+ ```kotlin
371
+ import androidx.compose.foundation.shape.CircleShape
372
+ import androidx.compose.ui.draw.shadow
373
+
374
+ @Composable
375
+ fun TgVoiceMiniPlayer(
376
+ title: String,
377
+ progress: Float,
378
+ onClose: () -> Unit,
379
+ modifier: Modifier = Modifier,
380
+ ) {
381
+ val theme = LocalTelegramTheme.current
382
+ Row(
383
+ modifier = modifier
384
+ .fillMaxWidth()
385
+ .padding(horizontal = 16.dp)
386
+ .height(40.dp)
387
+ .shadow(16.dp, RoundedCornerShape(22.dp), spotColor = Color.Black.copy(alpha = 0.16f))
388
+ .clip(RoundedCornerShape(22.dp))
389
+ .background(if (theme.isDark) TelegramColors.Surface1Dark else TelegramColors.CanvasLight)
390
+ .padding(horizontal = 14.dp),
391
+ verticalAlignment = Alignment.CenterVertically,
392
+ horizontalArrangement = Arrangement.spacedBy(12.dp),
393
+ ) {
394
+ Icon(Icons.Filled.Pause, "Pause", tint = theme.accent, modifier = Modifier.size(14.dp))
395
+ Column(Modifier.weight(1f), verticalArrangement = Arrangement.spacedBy(2.dp)) {
396
+ Text(title, style = TelegramText.Footnote.copy(fontWeight = FontWeight.SemiBold), color = theme.textPrimary, maxLines = 1)
397
+ Box(
398
+ Modifier
399
+ .fillMaxWidth()
400
+ .height(2.dp)
401
+ .clip(CircleShape)
402
+ .background(TelegramColors.DividerLight),
403
+ ) {
404
+ Box(
405
+ Modifier
406
+ .fillMaxWidth(progress)
407
+ .height(2.dp)
408
+ .clip(CircleShape)
409
+ .background(theme.accent),
410
+ )
411
+ }
412
+ }
413
+ Icon(
414
+ Icons.Filled.Close, "Close",
415
+ tint = theme.textSecondary,
416
+ modifier = Modifier.size(13.dp).clickableNoRipple(onClose),
417
+ )
418
+ }
419
+ }
420
+
421
+ import androidx.compose.foundation.clickable
422
+ @Composable
423
+ private fun Modifier.clickableNoRipple(onClick: () -> Unit): Modifier =
424
+ this.clickable(interactionSource = remember { MutableInteractionSource() }, indication = null, onClick = onClick)
425
+ ```
426
+
427
+ This pill should be rendered just below the top app bar in the chat `Scaffold` and survive chat navigation (hoist its state into a shared `ViewModel`) — persistence across chats is the Telegram differentiator.
428
+
429
+ ### Swipe-from-Edge to Reply
430
+
431
+ ```kotlin
432
+ import androidx.compose.animation.core.animateFloatAsState
433
+ import androidx.compose.animation.core.spring
434
+ import androidx.compose.foundation.gestures.detectHorizontalDragGestures
435
+ import androidx.compose.ui.geometry.Offset
436
+ import androidx.compose.ui.input.pointer.pointerInput
437
+ import androidx.compose.ui.platform.LocalDensity
438
+ import kotlin.math.roundToInt
439
+
440
+ @Composable
441
+ fun TgSwipeToReply(
442
+ onReply: () -> Unit,
443
+ content: @Composable () -> Unit,
444
+ ) {
445
+ val theme = LocalTelegramTheme.current
446
+ val haptics = LocalHapticFeedback.current
447
+ val density = LocalDensity.current
448
+ val thresholdPx = with(density) { 60.dp.toPx() }
449
+ var offset by remember { mutableFloatStateOf(0f) }
450
+ var ticked by remember { mutableStateOf(false) }
451
+ val animated by animateFloatAsState(offset, spring(dampingRatio = 0.8f, stiffness = 600f), label = "replyOffset")
452
+
453
+ Box(
454
+ Modifier.pointerInput(Unit) {
455
+ detectHorizontalDragGestures(
456
+ onDragEnd = {
457
+ if (offset >= thresholdPx) onReply()
458
+ offset = 0f; ticked = false
459
+ },
460
+ ) { _, dragAmount ->
461
+ offset = (offset + dragAmount).coerceIn(0f, thresholdPx + 20f)
462
+ if (offset >= thresholdPx && !ticked) {
463
+ ticked = true
464
+ haptics.performHapticFeedback(HapticFeedbackType.TextHandleMove) // soft tick at threshold
465
+ }
466
+ }
467
+ },
468
+ ) {
469
+ Icon(
470
+ Icons.Filled.Reply, null,
471
+ tint = theme.accent,
472
+ modifier = Modifier
473
+ .align(Alignment.CenterStart)
474
+ .offset { IntOffset((-32 + animated * 0.3f).roundToInt(), 0) }
475
+ .graphicsAlpha((animated / thresholdPx).coerceIn(0f, 1f)),
476
+ )
477
+ Box(Modifier.offset { IntOffset(animated.roundToInt(), 0) }) { content() }
478
+ }
479
+ }
480
+
481
+ import androidx.compose.ui.draw.alpha
482
+ import androidx.compose.ui.unit.IntOffset
483
+ private fun Modifier.graphicsAlpha(a: Float) = this.alpha(a)
484
+ ```
485
+
486
+ ### Animated Emoji / Sticker (Lottie)
487
+
488
+ Telegram's crown jewel: a single-emoji message renders large and plays a vector animation once on arrival. iOS uses `lottie-ios`; Compose uses `lottie-compose`.
489
+
490
+ ```kotlin
491
+ import com.airbnb.lottie.compose.*
492
+
493
+ @Composable
494
+ fun TgAnimatedEmoji(
495
+ assetName: String, // e.g. "emoji/heart.json" in assets/
496
+ sizeDp: Int = 72, // single emoji renders at 72dp
497
+ modifier: Modifier = Modifier,
498
+ ) {
499
+ val composition by rememberLottieComposition(LottieCompositionSpec.Asset(assetName))
500
+ // play once on arrival; bump iterations to loop "interactive" stickers
501
+ val progress by animateLottieCompositionAsState(
502
+ composition,
503
+ iterations = 1,
504
+ speed = 1f,
505
+ )
506
+ LottieAnimation(
507
+ composition = composition,
508
+ progress = { progress },
509
+ modifier = modifier.size(sizeDp.dp),
510
+ )
511
+ }
512
+ ```
513
+
514
+ For "interactive" emoji (heart/rocket) that play full-screen across both chats, render a `LottieAnimation` at ~1024dp in a `Box` overlay (`Popup` or top-level `ZStack`) and auto-dismiss on `progress == 1f`.
515
+
516
+ ## 4. Chat List Row
517
+
518
+ ```kotlin
519
+ @Composable
520
+ fun TgChatListRow(
521
+ avatarUrl: String,
522
+ name: String,
523
+ preview: String,
524
+ timestamp: String,
525
+ unreadCount: Int,
526
+ isPinned: Boolean,
527
+ isMuted: Boolean,
528
+ modifier: Modifier = Modifier,
529
+ ) {
530
+ val theme = LocalTelegramTheme.current
531
+ Row(
532
+ modifier = modifier
533
+ .fillMaxWidth()
534
+ .height(76.dp)
535
+ .background(if (isPinned) TelegramColors.Surface1Light else theme.canvas)
536
+ .padding(horizontal = 16.dp),
537
+ verticalAlignment = Alignment.CenterVertically,
538
+ horizontalArrangement = Arrangement.spacedBy(12.dp),
539
+ ) {
540
+ coil.compose.AsyncImage(
541
+ model = avatarUrl, contentDescription = null,
542
+ modifier = Modifier.size(54.dp).clip(CircleShape),
543
+ contentScale = androidx.compose.ui.layout.ContentScale.Crop,
544
+ )
545
+ Column(Modifier.weight(1f), verticalArrangement = Arrangement.spacedBy(4.dp)) {
546
+ Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(4.dp)) {
547
+ Text(name, style = TelegramText.ContactName, color = theme.textPrimary, maxLines = 1)
548
+ if (isMuted) Icon(Icons.Filled.NotificationsOff, null, tint = theme.textSecondary, modifier = Modifier.size(11.dp))
549
+ }
550
+ Text(preview, style = TelegramText.MessagePreview, color = theme.textSecondary, maxLines = 1)
551
+ }
552
+ Column(horizontalAlignment = Alignment.End, verticalArrangement = Arrangement.spacedBy(4.dp)) {
553
+ Text(timestamp, style = TelegramText.TimestampList, color = theme.textSecondary)
554
+ Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(4.dp)) {
555
+ if (isPinned) Icon(Icons.Filled.PushPin, null, tint = theme.textSecondary, modifier = Modifier.size(11.dp))
556
+ if (unreadCount > 0) {
557
+ Box(
558
+ Modifier
559
+ .clip(RoundedCornerShape(10.dp))
560
+ .background(if (isMuted) TelegramColors.TextTertiary else theme.accent)
561
+ .padding(horizontal = 7.dp, vertical = 2.dp),
562
+ ) {
563
+ Text("$unreadCount", style = TelegramText.TimestampList.copy(fontWeight = FontWeight.SemiBold), color = Color.White)
564
+ }
565
+ }
566
+ }
567
+ }
568
+ }
569
+ }
570
+ ```
571
+
572
+ ## 5. Navigation (Tab Bar)
573
+
574
+ Telegram's iOS tab bar is a `.regularMaterial` blur over the canvas with **custom outlined glyphs** (not SF Symbols everywhere). Android has no first-class live blur — use a translucent `NavigationBar` (`containerColor` at ~92% alpha) and ship the brand-specific glyphs (the Telegram plane, the channel megaphone) as vector drawables. The active tint reads from the live themed accent.
575
+
576
+ ```kotlin
577
+ @Composable
578
+ fun TgBottomBar(selected: Int, onSelect: (Int) -> Unit) {
579
+ val theme = LocalTelegramTheme.current
580
+ NavigationBar(
581
+ containerColor = theme.canvas.copy(alpha = 0.92f), // translucent — no live blur on Android
582
+ tonalElevation = 0.dp,
583
+ ) {
584
+ val items = listOf(
585
+ "Contacts" to Icons.Filled.Contacts,
586
+ "Calls" to Icons.Filled.Call,
587
+ "Chats" to Icons.Filled.ChatBubble, // swap for custom Telegram bubble drawable
588
+ "Settings" to Icons.Filled.Settings,
589
+ )
590
+ items.forEachIndexed { i, (label, icon) ->
591
+ NavigationBarItem(
592
+ selected = selected == i,
593
+ onClick = { onSelect(i) },
594
+ icon = { Icon(icon, label, modifier = Modifier.size(28.dp)) },
595
+ label = { Text(label, style = TelegramText.TabLabel) },
596
+ alwaysShowLabel = true,
597
+ colors = NavigationBarItemDefaults.colors(
598
+ selectedIconColor = theme.accent,
599
+ selectedTextColor = theme.accent,
600
+ unselectedIconColor = TelegramColors.TextSecondaryDark,
601
+ unselectedTextColor = TelegramColors.TextSecondaryDark,
602
+ indicatorColor = Color.Transparent,
603
+ ),
604
+ )
605
+ }
606
+ }
607
+ }
608
+ ```
609
+
610
+ ## 6. Motion
611
+
612
+ | Moment | Compose recipe |
613
+ |--------|----------------|
614
+ | Bubble arrival | enter `slideInVertically` + slight overshoot `spring(dampingRatio = 0.6f)` |
615
+ | Animated emoji | Lottie `iterations = 1`, plays once on arrival; interactive emoji full-screen overlay |
616
+ | Swipe-to-reply | `detectHorizontalDragGestures`, soft haptic tick at 60dp threshold |
617
+ | Silent-send long-press | `combinedClickable(onLongClick)` → `DropdownMenu` (Android long-press ~500ms) |
618
+ | Voice mini-player entry | `AnimatedVisibility` + `slideInVertically(initialOffsetY = { -it })` over ~200ms |
619
+ | Reactions palette | `scaleIn() + fadeIn()` from bubble center, `spring`, ~300ms |
620
+ | Context menu open | bubble `scale 1.0 → 1.05`, translucent scrim, menu fans below |
621
+
622
+ ```kotlin
623
+ // Bubble arrival — slide up + overshoot
624
+ @Composable
625
+ fun BubbleAppear(visible: Boolean, content: @Composable () -> Unit) {
626
+ androidx.compose.animation.AnimatedVisibility(
627
+ visible = visible,
628
+ enter = androidx.compose.animation.slideInVertically(
629
+ animationSpec = spring(dampingRatio = 0.6f, stiffness = 400f),
630
+ initialOffsetY = { it / 3 },
631
+ ) + androidx.compose.animation.fadeIn(),
632
+ ) { content() }
633
+ }
634
+ ```
635
+
636
+ Haptics: prefer `LocalHapticFeedback`. For a true *soft* impact on send (matching iOS `.impact(flexibility: .soft)`), use `LocalView.current.performHapticFeedback(HapticFeedbackConstants.CLOCK_TICK)` (API 30+) or a `Vibrator` `VibrationEffect.createOneShot(8, 80)` — light and brief, like Telegram's send tick.
637
+
638
+ ## 7. Icons
639
+
640
+ Telegram uses a **mix** of system glyphs and a proprietary outlined set. Use Material Icons (`material-icons-extended`) where semantically equivalent; ship brand-specific glyphs (the Telegram plane, channel megaphone, sticker face, premium gradient star) as vector drawables loaded via `ImageVector.vectorResource(R.drawable.…)`.
641
+
642
+ | Component | SF Symbol (iOS) | Material Icon (Compose) |
643
+ |-----------|-----------------|--------------------------|
644
+ | Send | `paperplane.fill` | `Icons.Filled.Send` (or custom Telegram plane drawable) |
645
+ | Mic | `mic.fill` | `Icons.Filled.Mic` |
646
+ | Attach | `paperclip` (rotated 45°) | `Icons.Filled.AttachFile` (`.rotate(45f)`) |
647
+ | Emoji | `face.smiling` | `Icons.Filled.EmojiEmotions` |
648
+ | Sticker | custom outlined sticker | vector drawable |
649
+ | Read ticks | `checkmark` / `checkmark.circle.fill` | `Icons.Filled.Done` / `Icons.Filled.DoneAll` |
650
+ | Phone | `phone.fill` | `Icons.Filled.Call` |
651
+ | Video | `video.fill` | `Icons.Filled.Videocam` |
652
+ | Lock (secret chat) | `lock.fill` | `Icons.Filled.Lock` |
653
+ | Pinned | `pin.fill` | `Icons.Filled.PushPin` |
654
+ | Muted | `speaker.slash.fill` | `Icons.Filled.NotificationsOff` |
655
+ | Chats tab | `bubble.left.and.bubble.right.fill` | `Icons.Filled.ChatBubble` (or custom) |
656
+ | Contacts tab | `person.2.fill` | `Icons.Filled.Contacts` |
657
+ | Calls tab | `phone.fill` | `Icons.Filled.Call` |
658
+ | Settings tab | `gearshape.fill` | `Icons.Filled.Settings` |
659
+ | Channel broadcast | custom megaphone | vector drawable |
660
+ | Premium star | custom gradient star | vector drawable |
661
+ | Reply | `arrowshape.turn.up.left.fill` | `Icons.Filled.Reply` |
662
+ | Schedule | `calendar` | `Icons.Filled.Schedule` |
663
+ | Silent | `speaker.slash` | `Icons.Filled.NotificationsOff` |
664
+
665
+ ## 8. Minimum SDK & Accessibility Notes
666
+
667
+ - **minSdk 24** (Compose floor is 21; Lottie + `RoundedCornerShape` per-corner + motion are comfortable at 24). `compileSdk 34+`, Compose BOM `2024.09+`, Kotlin `2.0+`.
668
+ - **Edge-to-edge**: call `enableEdgeToEdge()` in the `Activity`. System-bar icon contrast must follow the live theme (dark icons on the white canvas, light icons on `#212121`/OLED). Apply `Scaffold` insets so the compose bar hugs the keyboard/gesture inset; render the voice mini-player just below the top app bar inside the insets.
669
+ - **Themeable accent**: the entire system reads `LocalTelegramTheme.current.accent`. Provide a new `TelegramTheme` at the app root and **every** consuming composable recomposes and re-tints live — this is the core product behavior, so never hardcode a blue.
670
+ - **OLED mode**: expose `isOLED` as a stored user preference distinct from system dark; when true the canvas becomes pure `#000000` and surfaces lift to `#0A0A0A`.
671
+ - **Font scaling**: `sp` honors the user's font scale — scale bubble body, contact names, previews. Pin the **11sp in-bubble timestamp** and **10sp tab labels** (clamp via `CompositionLocalProvider(LocalDensity provides Density(density, fontScale = 1f))`).
672
+ - **TalkBack**: merge bubble text + timestamp + read state into one node — `Modifier.semantics(mergeDescendants = true) { contentDescription = "$text, $timestamp, ${if (isRead) "read" else "sent"}" }`. The swipe-to-reply gesture and decorative tail notch should be `Modifier.clearAndSetSemantics {}`.
673
+ - **RTL**: `RoundedCornerShape(topStart=…, bottomStart=…)` auto-mirrors under `LayoutDirection.Rtl`, so the bubble tail notch flips correctly for Arabic/Persian/Hebrew with no extra code.
674
+ - **Reduce motion**: detect `Settings.Global.ANIMATOR_DURATION_SCALE == 0f` (or a stored pref) — render Lottie emoji as a static first frame (`progress = { 0f }`) and skip the bubble-arrival overshoot.
675
+ - **Inline Markdown**: parse `**bold**`, `__italic__`, `||spoiler||`, `` `code` `` into an `AnnotatedString` with `SpanStyle`s; render spoiler as a blurred/`drawWithContent`-masked span that clears on tap.
676
+ - **Dynamic color**: Telegram already *is* a user-theming system. Do **not** layer Material You `dynamicColorScheme()` on top — the accent must come from the user's explicit Telegram theme choice, not the wallpaper, or two competing theming systems fight.