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,711 @@
1
+ # Todoist (iOS) — Jetpack Compose Implementation Guide
2
+
3
+ Companion to [DESIGN.md](DESIGN.md) — the framework-neutral spec. This file ports Todoist's visual language to **Android with Jetpack Compose (Material 3)**: a color token object, a `Typography` set, paste-ready `@Composable`s (the priority checkbox, the hero task row, the tinted-shadow FAB, the quick-add card), `Modifier`s, motion, and haptics.
4
+
5
+ > Why a Compose guide for an iOS-referenced app? The DESIGN.md tokens are platform-neutral. This file keeps the *visual* identity (the whisper-quiet white canvas, Todoist Red as a strict verb color, the four-tier priority checkbox, and — critically — the **tinted red FAB shadow**) while making everything idiomatic Android — a `NavigationBar`/drawer instead of a UITabBar, `SwipeToDismissBox` instead of `.swipeActions`, `LocalHapticFeedback` instead of `.sensoryFeedback`, `sp`/`dp` instead of `pt`.
6
+
7
+ Assumes Compose BOM `2024.09+`, Kotlin `2.0+`, `minSdk 24`, Material 3. No remote images and no color extraction, so neither Coil nor `androidx.palette` is required.
8
+
9
+ ## 1. Color Tokens
10
+
11
+ ```kotlin
12
+ // ui/theme/TodoistColors.kt
13
+ import androidx.compose.ui.graphics.Color
14
+
15
+ object TodoistColors {
16
+ // Canvas & Surfaces
17
+ val Canvas = Color(0xFFFFFFFF)
18
+ val SurfaceGray = Color(0xFFFAFAFA)
19
+ val SurfaceGray2 = Color(0xFFF0F0F0)
20
+ val Divider = Color(0xFFEEEEEE)
21
+
22
+ // Text
23
+ val Ink = Color(0xFF202020) // intentional: warm near-black, never pure #000
24
+ val Secondary = Color(0xFF808080)
25
+ val Tertiary = Color(0xFFB0B0B0)
26
+
27
+ // Brand & Priorities
28
+ val Red = Color(0xFFDC4C3E) // FAB, P1, brand mark, primary CTA — verbs only
29
+ val RedPressed = Color(0xFFB53C30)
30
+ val RedTint = Color(0xFFFBE5E2)
31
+ val P2Orange = Color(0xFFEB8909)
32
+ val P3Blue = Color(0xFF246FE0)
33
+ val P4Gray = Color(0xFFB0B0B0)
34
+
35
+ // Semantic
36
+ val Success = Color(0xFF058527)
37
+ val Error = Color(0xFFD1453B)
38
+
39
+ // Dark mode
40
+ val DarkCanvas = Color(0xFF1F1F1F)
41
+ val DarkSurface = Color(0xFF282828)
42
+ val DarkSurface2 = Color(0xFF363636)
43
+ val DarkDivider = Color(0xFF3D3D3D)
44
+ val DarkText = Color(0xFFE8E8E8)
45
+ val DarkTextSec = Color(0xFFA0A0A0)
46
+ val RedDark = Color(0xFFE44332) // brightens slightly for dark contrast
47
+
48
+ // User-selectable project palette (subset — the colored dots)
49
+ val ProjBerryRed = Color(0xFFB8255F)
50
+ val ProjRed = Color(0xFFDB4035)
51
+ val ProjOrange = Color(0xFFFF9933)
52
+ val ProjYellow = Color(0xFFFAD000)
53
+ val ProjGreen = Color(0xFF299438)
54
+ val ProjMint = Color(0xFF6ACCBC)
55
+ val ProjTeal = Color(0xFF158FAD)
56
+ val ProjSky = Color(0xFF14AAF5)
57
+ val ProjBlue = Color(0xFF4073FF)
58
+ val ProjGrape = Color(0xFF884DFF)
59
+ val ProjViolet = Color(0xFFAF38EB)
60
+ val ProjMagenta = Color(0xFFE05194)
61
+ }
62
+ ```
63
+
64
+ Todoist is light-first (white canvas, content-forward). Wire a Material 3 `lightColorScheme` so ripples, dividers, and stock component defaults inherit the brand; provide the dark scheme (engineered for late-night planning).
65
+
66
+ ```kotlin
67
+ // ui/theme/Theme.kt
68
+ import androidx.compose.material3.lightColorScheme
69
+ import androidx.compose.material3.darkColorScheme
70
+ import androidx.compose.material3.MaterialTheme
71
+
72
+ private val TodoistLight = lightColorScheme(
73
+ primary = TodoistColors.Red,
74
+ onPrimary = Color.White,
75
+ background = TodoistColors.Canvas,
76
+ onBackground = TodoistColors.Ink,
77
+ surface = TodoistColors.SurfaceGray,
78
+ onSurface = TodoistColors.Ink,
79
+ surfaceVariant = TodoistColors.SurfaceGray2,
80
+ outline = TodoistColors.Divider,
81
+ error = TodoistColors.Error,
82
+ )
83
+
84
+ private val TodoistDark = darkColorScheme(
85
+ primary = TodoistColors.RedDark,
86
+ onPrimary = Color.White,
87
+ background = TodoistColors.DarkCanvas,
88
+ onBackground = TodoistColors.DarkText,
89
+ surface = TodoistColors.DarkSurface,
90
+ onSurface = TodoistColors.DarkText,
91
+ surfaceVariant = TodoistColors.DarkSurface2,
92
+ outline = TodoistColors.DarkDivider,
93
+ error = TodoistColors.Error,
94
+ )
95
+
96
+ @Composable
97
+ fun TodoistTheme(darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable () -> Unit) =
98
+ MaterialTheme(
99
+ colorScheme = if (darkTheme) TodoistDark else TodoistLight,
100
+ typography = TodoistTypography,
101
+ content = content,
102
+ )
103
+ ```
104
+
105
+ ## 2. Typography
106
+
107
+ Todoist deliberately uses the **platform font** — no custom face — to feel like a respectful native citizen. On Android the platform face is **Roboto**; use `FontFamily.Default` (Compose resolves Roboto / the device system font and picks the right optical variant). This mirrors Todoist's "SF Pro, no exceptions" decision.
108
+
109
+ ```kotlin
110
+ // ui/theme/TodoistType.kt
111
+ import androidx.compose.material3.Typography
112
+ import androidx.compose.ui.text.TextStyle
113
+ import androidx.compose.ui.text.font.FontFamily
114
+ import androidx.compose.ui.text.font.FontWeight
115
+ import androidx.compose.ui.unit.sp
116
+
117
+ private val Sys = FontFamily.Default // Roboto / system — Todoist uses the platform face by design
118
+
119
+ // Named ramp — mirrors DESIGN.md §3 exactly (pt → sp 1:1)
120
+ object TodoistText {
121
+ val LargeNav = TextStyle(Sys, fontWeight = FontWeight.Bold, fontSize = 34.sp, lineHeight = 39.sp, letterSpacing = (-0.4).sp)
122
+ val InlineNav = TextStyle(Sys, fontWeight = FontWeight.SemiBold, fontSize = 17.sp, lineHeight = 20.sp, letterSpacing = (-0.2).sp)
123
+ val SectionHdr = TextStyle(Sys, fontWeight = FontWeight.SemiBold, fontSize = 13.sp, lineHeight = 16.sp, letterSpacing = 0.6.sp) // UPPERCASE at call site
124
+ val TaskBody = TextStyle(Sys, fontWeight = FontWeight.Normal, fontSize = 16.sp, lineHeight = 22.sp, letterSpacing = (-0.1).sp)
125
+ val TaskBold = TextStyle(Sys, fontWeight = FontWeight.SemiBold, fontSize = 16.sp, lineHeight = 22.sp, letterSpacing = (-0.1).sp)
126
+ val Subtask = TextStyle(Sys, fontWeight = FontWeight.Normal, fontSize = 15.sp, lineHeight = 20.sp, letterSpacing = (-0.1).sp)
127
+ val Meta = TextStyle(Sys, fontWeight = FontWeight.Normal, fontSize = 13.sp, lineHeight = 16.sp)
128
+ val MetaOverdue = TextStyle(Sys, fontWeight = FontWeight.Medium, fontSize = 13.sp, lineHeight = 16.sp)
129
+ val SidebarSys = TextStyle(Sys, fontWeight = FontWeight.Medium, fontSize = 15.sp, lineHeight = 19.sp)
130
+ val SidebarProj = TextStyle(Sys, fontWeight = FontWeight.Normal, fontSize = 15.sp, lineHeight = 19.sp)
131
+ val QuickAdd = TextStyle(Sys, fontWeight = FontWeight.Normal, fontSize = 17.sp, lineHeight = 22.sp)
132
+ val Button = TextStyle(Sys, fontWeight = FontWeight.SemiBold, fontSize = 16.sp, lineHeight = 16.sp)
133
+ val FabGlyph = TextStyle(Sys, fontWeight = FontWeight.Normal, fontSize = 28.sp, lineHeight = 28.sp)
134
+ val Tab = TextStyle(Sys, fontWeight = FontWeight.Medium, fontSize = 10.sp, lineHeight = 10.sp, letterSpacing = 0.1.sp)
135
+ val Caption = TextStyle(Sys, fontWeight = FontWeight.Normal, fontSize = 12.sp, lineHeight = 16.sp)
136
+ val KarmaNum = TextStyle(Sys, fontWeight = FontWeight.Bold, fontSize = 28.sp, lineHeight = 28.sp, letterSpacing = (-0.2).sp)
137
+ }
138
+
139
+ // Map onto Material 3 slots so stock components inherit the brand
140
+ val TodoistTypography = Typography(
141
+ headlineLarge = TodoistText.LargeNav,
142
+ titleMedium = TodoistText.InlineNav,
143
+ bodyLarge = TodoistText.TaskBody,
144
+ bodyMedium = TodoistText.Meta,
145
+ labelLarge = TodoistText.Button,
146
+ labelSmall = TodoistText.Tab,
147
+ )
148
+ ```
149
+
150
+ ## 3. Signature Components
151
+
152
+ ### Priority Checkbox
153
+
154
+ The four-tier priority lives on the **checkbox stroke**, never the row background. Mirrors DESIGN-swiftui.md §3.
155
+
156
+ ```kotlin
157
+ import androidx.compose.animation.core.animateFloatAsState
158
+ import androidx.compose.animation.core.tween
159
+ import androidx.compose.foundation.background
160
+ import androidx.compose.foundation.border
161
+ import androidx.compose.foundation.clickable
162
+ import androidx.compose.foundation.interaction.MutableInteractionSource
163
+ import androidx.compose.foundation.layout.*
164
+ import androidx.compose.foundation.shape.CircleShape
165
+ import androidx.compose.material.icons.Icons
166
+ import androidx.compose.material.icons.filled.Check
167
+ import androidx.compose.material3.Icon
168
+ import androidx.compose.runtime.*
169
+ import androidx.compose.ui.Alignment
170
+ import androidx.compose.ui.Modifier
171
+ import androidx.compose.ui.draw.clip
172
+ import androidx.compose.ui.graphics.Color
173
+ import androidx.compose.ui.hapticfeedback.HapticFeedbackType
174
+ import androidx.compose.ui.platform.LocalHapticFeedback
175
+ import androidx.compose.ui.unit.dp
176
+
177
+ enum class Priority { P1, P2, P3, P4 }
178
+
179
+ val Priority.color: Color
180
+ get() = when (this) {
181
+ Priority.P1 -> TodoistColors.Red
182
+ Priority.P2 -> TodoistColors.P2Orange
183
+ Priority.P3 -> TodoistColors.P3Blue
184
+ Priority.P4 -> TodoistColors.P4Gray
185
+ }
186
+
187
+ val Priority.fillTint: Color
188
+ get() = when (this) {
189
+ Priority.P1 -> TodoistColors.Red.copy(alpha = 0.10f)
190
+ Priority.P2 -> TodoistColors.P2Orange.copy(alpha = 0.08f)
191
+ Priority.P3 -> TodoistColors.P3Blue.copy(alpha = 0.08f)
192
+ Priority.P4 -> Color.Transparent
193
+ }
194
+
195
+ @Composable
196
+ fun TodoistCheckbox(
197
+ priority: Priority,
198
+ checked: Boolean,
199
+ onCheckedChange: (Boolean) -> Unit,
200
+ modifier: Modifier = Modifier,
201
+ ) {
202
+ val haptics = LocalHapticFeedback.current
203
+ val interaction = remember { MutableInteractionSource() }
204
+
205
+ Box(
206
+ modifier = modifier
207
+ .size(44.dp) // 44.dp hit area — never compress
208
+ .clickable(interaction, indication = null) {
209
+ haptics.performHapticFeedback(HapticFeedbackType.TextHandleMove) // ~iOS light impact
210
+ onCheckedChange(!checked)
211
+ },
212
+ contentAlignment = Alignment.Center,
213
+ ) {
214
+ Box(
215
+ Modifier
216
+ .size(22.dp)
217
+ .clip(CircleShape)
218
+ .background(if (checked) priority.color else priority.fillTint)
219
+ .border(1.5.dp, priority.color, CircleShape),
220
+ contentAlignment = Alignment.Center,
221
+ ) {
222
+ if (checked) {
223
+ Icon(Icons.Filled.Check, contentDescription = null, tint = Color.White, modifier = Modifier.size(12.dp))
224
+ }
225
+ }
226
+ }
227
+ }
228
+ ```
229
+
230
+ ### Task Row (The Hero Component)
231
+
232
+ Edge-to-edge, 52.dp minimum, content + metadata, divider inset 64.dp from the left (aligned with task content, not the checkbox). On complete: strikethrough + fade.
233
+
234
+ ```kotlin
235
+ import androidx.compose.foundation.shape.RoundedCornerShape
236
+ import androidx.compose.material.icons.automirrored.outlined.Comment
237
+ import androidx.compose.material3.Text
238
+ import androidx.compose.ui.draw.drawBehind
239
+ import androidx.compose.ui.geometry.Offset
240
+ import androidx.compose.ui.text.style.TextDecoration
241
+ import androidx.compose.ui.text.style.TextOverflow
242
+
243
+ sealed interface TaskDate {
244
+ data object Today : TaskDate
245
+ data object Tomorrow : TaskDate
246
+ data class Overdue(val label: String) : TaskDate
247
+ data class Future(val label: String) : TaskDate
248
+ }
249
+
250
+ @Composable
251
+ fun TaskRow(
252
+ content: String,
253
+ priority: Priority,
254
+ date: TaskDate?,
255
+ project: Pair<String, Color>?,
256
+ commentCount: Int,
257
+ checked: Boolean,
258
+ onCheckedChange: (Boolean) -> Unit,
259
+ modifier: Modifier = Modifier,
260
+ ) {
261
+ Row(
262
+ modifier = modifier
263
+ .fillMaxWidth()
264
+ .background(TodoistColors.Canvas)
265
+ .heightIn(min = 52.dp)
266
+ .drawBehind {
267
+ val inset = 64.dp.toPx()
268
+ drawLine(
269
+ TodoistColors.Divider,
270
+ Offset(inset, size.height),
271
+ Offset(size.width, size.height),
272
+ 0.5.dp.toPx(),
273
+ )
274
+ }
275
+ .padding(horizontal = 16.dp, vertical = 12.dp),
276
+ verticalAlignment = Alignment.Top,
277
+ horizontalArrangement = Arrangement.spacedBy(12.dp),
278
+ ) {
279
+ TodoistCheckbox(priority, checked, onCheckedChange)
280
+
281
+ Column(Modifier.weight(1f), verticalArrangement = Arrangement.spacedBy(4.dp)) {
282
+ Text(
283
+ content,
284
+ style = TodoistText.TaskBody,
285
+ color = if (checked) TodoistColors.Tertiary else TodoistColors.Ink,
286
+ textDecoration = if (checked) TextDecoration.LineThrough else TextDecoration.None,
287
+ maxLines = 3,
288
+ overflow = TextOverflow.Ellipsis,
289
+ )
290
+ if (date != null || project != null || commentCount > 0) {
291
+ Row(horizontalArrangement = Arrangement.spacedBy(12.dp), verticalAlignment = Alignment.CenterVertically) {
292
+ date?.let { DatePill(it) }
293
+ project?.let { (name, c) -> ProjectTag(name, c) }
294
+ if (commentCount > 0) CommentBadge(commentCount)
295
+ }
296
+ }
297
+ }
298
+ }
299
+ }
300
+
301
+ @Composable
302
+ private fun DatePill(d: TaskDate) {
303
+ when (d) {
304
+ TaskDate.Today -> Text("Today", style = TodoistText.Meta, color = TodoistColors.Success)
305
+ TaskDate.Tomorrow -> Text("Tomorrow", style = TodoistText.Meta, color = TodoistColors.Ink)
306
+ is TaskDate.Overdue -> Text(d.label, style = TodoistText.MetaOverdue, color = TodoistColors.Red)
307
+ is TaskDate.Future -> Text(d.label, style = TodoistText.Meta, color = TodoistColors.Secondary)
308
+ }
309
+ }
310
+
311
+ @Composable
312
+ fun ProjectTag(name: String, color: Color) {
313
+ Row(horizontalArrangement = Arrangement.spacedBy(6.dp), verticalAlignment = Alignment.CenterVertically) {
314
+ Box(Modifier.size(8.dp).clip(CircleShape).background(color))
315
+ Text("# $name", style = TodoistText.Meta, color = TodoistColors.Secondary)
316
+ }
317
+ }
318
+
319
+ @Composable
320
+ private fun CommentBadge(count: Int) {
321
+ Row(horizontalArrangement = Arrangement.spacedBy(4.dp), verticalAlignment = Alignment.CenterVertically) {
322
+ Icon(Icons.AutoMirrored.Outlined.Comment, null, tint = TodoistColors.Secondary, modifier = Modifier.size(12.dp))
323
+ Text("$count", style = TodoistText.Meta, color = TodoistColors.Secondary)
324
+ }
325
+ }
326
+ ```
327
+
328
+ ### Floating Action Button (Tinted Red Shadow — The Signature)
329
+
330
+ This is one of the most-copied details in the app: the FAB shadow is **dyed Todoist Red**, not generic black. Compose `Modifier.shadow` accepts `spotColor`/`ambientColor` on API 28+; tint both to red.
331
+
332
+ ```kotlin
333
+ import androidx.compose.foundation.interaction.collectIsPressedAsState
334
+ import androidx.compose.material.icons.filled.Add
335
+ import androidx.compose.ui.draw.scale
336
+ import androidx.compose.ui.draw.shadow
337
+
338
+ @Composable
339
+ fun TodoistFAB(onClick: () -> Unit, modifier: Modifier = Modifier) {
340
+ val interaction = remember { MutableInteractionSource() }
341
+ val pressed by interaction.collectIsPressedAsState()
342
+ val scale by animateFloatAsState(if (pressed) 0.94f else 1f, label = "fabScale")
343
+ val haptics = LocalHapticFeedback.current
344
+
345
+ Box(
346
+ modifier = modifier
347
+ .size(56.dp)
348
+ .scale(scale)
349
+ .shadow(
350
+ elevation = if (pressed) 4.dp else 16.dp,
351
+ shape = CircleShape,
352
+ spotColor = TodoistColors.Red, // SIGNATURE: tinted red, not black
353
+ ambientColor = TodoistColors.Red,
354
+ )
355
+ .clip(CircleShape)
356
+ .background(if (pressed) TodoistColors.RedPressed else TodoistColors.Red)
357
+ .clickable(interaction, indication = null) {
358
+ haptics.performHapticFeedback(HapticFeedbackType.LongPress) // ~iOS medium impact
359
+ onClick()
360
+ }
361
+ .semantics { contentDescription = "Add task" },
362
+ contentAlignment = Alignment.Center,
363
+ ) {
364
+ Icon(Icons.Filled.Add, contentDescription = null, tint = Color.White, modifier = Modifier.size(28.dp))
365
+ }
366
+ }
367
+ ```
368
+
369
+ > Pre-API-28, `spotColor` is ignored (shadows are always black). Fall back to drawing a soft red radial glow behind the circle with `Modifier.drawBehind` so the signature reads on every device.
370
+
371
+ ### Quick-Add Card (Natural-Language Input)
372
+
373
+ Bottom-sheet, natural-language entry with inline smart-parsing chips. Use a Material 3 `ModalBottomSheet` for the container.
374
+
375
+ ```kotlin
376
+ import androidx.compose.foundation.horizontalScroll
377
+ import androidx.compose.foundation.rememberScrollState
378
+ import androidx.compose.foundation.text.BasicTextField
379
+ import androidx.compose.material.icons.filled.*
380
+ import androidx.compose.material3.HorizontalDivider
381
+ import androidx.compose.material3.Surface
382
+ import androidx.compose.ui.graphics.SolidColor
383
+ import androidx.compose.ui.text.input.TextFieldValue
384
+
385
+ @Composable
386
+ fun QuickAddCard(
387
+ onAdd: (String) -> Unit,
388
+ modifier: Modifier = Modifier,
389
+ ) {
390
+ var text by remember { mutableStateOf(TextFieldValue("")) }
391
+ var selectedDate by remember { mutableStateOf<String?>("Today") }
392
+ var selectedPriority by remember { mutableStateOf(Priority.P4) }
393
+ val haptics = LocalHapticFeedback.current
394
+
395
+ Surface(
396
+ color = TodoistColors.Canvas,
397
+ shape = RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp),
398
+ shadowElevation = 4.dp,
399
+ modifier = modifier,
400
+ ) {
401
+ Column(Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(16.dp)) {
402
+ Text("Add task", style = TodoistText.InlineNav, color = TodoistColors.Ink)
403
+
404
+ BasicTextField(
405
+ value = text,
406
+ onValueChange = { text = it },
407
+ textStyle = TodoistText.QuickAdd.copy(color = TodoistColors.Ink),
408
+ cursorBrush = SolidColor(TodoistColors.Red),
409
+ modifier = Modifier.fillMaxWidth(),
410
+ decorationBox = { inner ->
411
+ if (text.text.isEmpty()) {
412
+ Text("Take out the trash today p1 #home", style = TodoistText.QuickAdd, color = TodoistColors.Tertiary)
413
+ }
414
+ inner()
415
+ },
416
+ )
417
+
418
+ if (text.text.isNotEmpty()) {
419
+ Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
420
+ selectedDate?.let { SmartChip(it, TodoistColors.Success) }
421
+ if (selectedPriority != Priority.P4) {
422
+ SmartChip("P${selectedPriority.ordinal + 1}", selectedPriority.color)
423
+ }
424
+ }
425
+ }
426
+
427
+ HorizontalDivider(color = TodoistColors.Divider)
428
+
429
+ Row(
430
+ Modifier.horizontalScroll(rememberScrollState()),
431
+ horizontalArrangement = Arrangement.spacedBy(8.dp),
432
+ ) {
433
+ ActionChip(Icons.Filled.CalendarToday, selectedDate ?: "Date")
434
+ ActionChip(Icons.Outlined.Flag, "Priority")
435
+ ActionChip(Icons.Filled.Tag, "Project")
436
+ ActionChip(Icons.Filled.Label, "Labels")
437
+ ActionChip(Icons.Filled.Notifications, "Reminders")
438
+ }
439
+
440
+ Box(Modifier.fillMaxWidth(), contentAlignment = Alignment.CenterEnd) {
441
+ val enabled = text.text.isNotEmpty()
442
+ Box(
443
+ Modifier
444
+ .clip(RoundedCornerShape(8.dp))
445
+ .background(if (enabled) TodoistColors.Red else TodoistColors.SurfaceGray2)
446
+ .clickable(enabled = enabled) {
447
+ haptics.performHapticFeedback(HapticFeedbackType.LongPress) // ~iOS success
448
+ onAdd(text.text)
449
+ }
450
+ .padding(horizontal = 24.dp, vertical = 12.dp),
451
+ ) {
452
+ Text("Add task", style = TodoistText.Button, color = if (enabled) Color.White else TodoistColors.Tertiary)
453
+ }
454
+ }
455
+ }
456
+ }
457
+ }
458
+
459
+ @Composable
460
+ private fun SmartChip(label: String, color: Color) {
461
+ Box(
462
+ Modifier.clip(RoundedCornerShape(6.dp)).background(color.copy(alpha = 0.12f))
463
+ .padding(horizontal = 8.dp, vertical = 4.dp)
464
+ ) {
465
+ Text(label, style = TodoistText.Meta.copy(fontWeight = FontWeight.Medium), color = color)
466
+ }
467
+ }
468
+
469
+ @Composable
470
+ private fun ActionChip(icon: androidx.compose.ui.graphics.vector.ImageVector, label: String) {
471
+ Row(
472
+ Modifier.clip(RoundedCornerShape(50)).border(1.dp, TodoistColors.Divider, RoundedCornerShape(50))
473
+ .padding(horizontal = 12.dp, vertical = 8.dp),
474
+ horizontalArrangement = Arrangement.spacedBy(6.dp),
475
+ verticalAlignment = Alignment.CenterVertically,
476
+ ) {
477
+ Icon(icon, null, tint = TodoistColors.Ink, modifier = Modifier.size(12.dp))
478
+ Text(label, style = TodoistText.Meta.copy(fontWeight = FontWeight.Medium), color = TodoistColors.Ink)
479
+ }
480
+ }
481
+ ```
482
+
483
+ ### Section Header & Sidebar Row
484
+
485
+ ```kotlin
486
+ import androidx.compose.material.icons.filled.ChevronRight
487
+ import androidx.compose.material.icons.filled.ExpandMore
488
+
489
+ @Composable
490
+ fun TodoistSectionHeader(title: String, isOverdue: Boolean, collapsed: Boolean, onToggle: () -> Unit) {
491
+ Row(
492
+ Modifier
493
+ .fillMaxWidth()
494
+ .background(TodoistColors.Canvas)
495
+ .height(36.dp)
496
+ .drawBehind { drawLine(TodoistColors.Divider, Offset(0f, size.height), Offset(size.width, size.height), 0.5.dp.toPx()) }
497
+ .padding(horizontal = 16.dp),
498
+ verticalAlignment = Alignment.CenterVertically,
499
+ ) {
500
+ Text(
501
+ title.uppercase(),
502
+ style = TodoistText.SectionHdr,
503
+ color = if (isOverdue) TodoistColors.Red else TodoistColors.Secondary,
504
+ )
505
+ Spacer(Modifier.weight(1f))
506
+ Icon(
507
+ if (collapsed) Icons.Filled.ChevronRight else Icons.Filled.ExpandMore,
508
+ contentDescription = if (collapsed) "Expand" else "Collapse",
509
+ tint = if (isOverdue) TodoistColors.Red else TodoistColors.Secondary,
510
+ modifier = Modifier.size(48.dp).clickable(onClick = onToggle).padding(14.dp),
511
+ )
512
+ }
513
+ }
514
+
515
+ @Composable
516
+ fun SidebarRow(
517
+ icon: androidx.compose.ui.graphics.vector.ImageVector,
518
+ label: String,
519
+ count: Int?,
520
+ selected: Boolean,
521
+ overdue: Boolean,
522
+ onClick: () -> Unit,
523
+ ) {
524
+ Box {
525
+ Row(
526
+ Modifier
527
+ .fillMaxWidth()
528
+ .height(44.dp)
529
+ .background(if (selected) TodoistColors.Red.copy(alpha = 0.08f) else Color.Transparent)
530
+ .clickable(onClick = onClick)
531
+ .padding(horizontal = 16.dp),
532
+ verticalAlignment = Alignment.CenterVertically,
533
+ horizontalArrangement = Arrangement.spacedBy(12.dp),
534
+ ) {
535
+ Icon(icon, null, tint = TodoistColors.Ink, modifier = Modifier.size(20.dp))
536
+ Text(label, style = TodoistText.SidebarSys, color = TodoistColors.Ink)
537
+ Spacer(Modifier.weight(1f))
538
+ if (count != null && count > 0) {
539
+ Box(
540
+ Modifier
541
+ .then(if (overdue) Modifier.clip(CircleShape).background(TodoistColors.Red) else Modifier)
542
+ .padding(horizontal = 8.dp, vertical = 2.dp)
543
+ ) {
544
+ Text("$count", style = TodoistText.Meta, color = if (overdue) Color.White else TodoistColors.Secondary)
545
+ }
546
+ }
547
+ }
548
+ if (selected) {
549
+ Box(Modifier.width(3.dp).fillMaxHeight().background(TodoistColors.Red))
550
+ }
551
+ }
552
+ }
553
+ ```
554
+
555
+ ## 4. Swipe Actions & Task-Completion Collapse (the distinctive interaction)
556
+
557
+ Todoist has no color extraction. Its defining dynamic moves are **swipe-to-schedule** and the **strikethrough → collapse-upward** completion. On Android, swipe uses Material 3 `SwipeToDismissBox`; the collapse uses `AnimatedVisibility` + `shrinkVertically`.
558
+
559
+ ```kotlin
560
+ import androidx.compose.animation.AnimatedVisibility
561
+ import androidx.compose.animation.fadeOut
562
+ import androidx.compose.animation.shrinkVertically
563
+ import androidx.compose.animation.core.tween
564
+ import androidx.compose.material3.SwipeToDismissBox
565
+ import androidx.compose.material3.SwipeToDismissBoxValue
566
+ import androidx.compose.material3.rememberSwipeToDismissBoxState
567
+
568
+ @Composable
569
+ fun SwipeableTaskRow(
570
+ visible: Boolean,
571
+ onScheduleToday: () -> Unit,
572
+ onPostpone: () -> Unit,
573
+ rowContent: @Composable () -> Unit,
574
+ ) {
575
+ // Strikethrough already lives in TaskRow; here we collapse the row upward on complete (~250ms)
576
+ AnimatedVisibility(
577
+ visible = visible,
578
+ exit = shrinkVertically(animationSpec = tween(250)) + fadeOut(tween(250)),
579
+ ) {
580
+ val dismissState = rememberSwipeToDismissBoxState(
581
+ confirmValueChange = {
582
+ when (it) {
583
+ SwipeToDismissBoxValue.StartToEnd -> { onScheduleToday(); false } // swipe right → schedule (green)
584
+ SwipeToDismissBoxValue.EndToStart -> { onPostpone(); false } // swipe left → postpone (orange)
585
+ else -> false
586
+ }
587
+ }
588
+ )
589
+ SwipeToDismissBox(
590
+ state = dismissState,
591
+ backgroundContent = {
592
+ val toEnd = dismissState.dismissDirection == SwipeToDismissBoxValue.StartToEnd
593
+ Box(
594
+ Modifier
595
+ .fillMaxSize()
596
+ .background(if (toEnd) TodoistColors.Success else TodoistColors.P2Orange)
597
+ .padding(horizontal = 20.dp),
598
+ contentAlignment = if (toEnd) Alignment.CenterStart else Alignment.CenterEnd,
599
+ ) {
600
+ Icon(
601
+ if (toEnd) Icons.Filled.CalendarToday else Icons.Filled.Schedule,
602
+ contentDescription = null, tint = Color.White, modifier = Modifier.size(20.dp),
603
+ )
604
+ }
605
+ },
606
+ ) { rowContent() }
607
+ }
608
+ }
609
+ ```
610
+
611
+ Hoist `visible` and the completion logic into a `ViewModel`: tapping the checkbox flips `checked` (animating fill + check ~200ms), then after an 80ms hold sets `visible = false`, collapsing the row upward while the list below slides up.
612
+
613
+ ## 5. Navigation (sidebar drawer + iPad rail)
614
+
615
+ On iPhone Todoist uses a full-screen **drawer** (hamburger), not a tab bar; the iPad tab bar maps to a `NavigationBar`. Use a Material 3 `ModalNavigationDrawer` for phones. Android has no live blur — the large-title nav uses a 92%-opaque canvas `Surface` when content scrolls beneath, instead of `.regularMaterial`.
616
+
617
+ ```kotlin
618
+ import androidx.compose.material.icons.filled.*
619
+ import androidx.compose.material3.*
620
+
621
+ @Composable
622
+ fun TodoistTabBar(selected: Int, onSelect: (Int) -> Unit) { // iPad / large-screen only
623
+ NavigationBar(containerColor = TodoistColors.Canvas, tonalElevation = 0.dp) {
624
+ val items = listOf(
625
+ "Today" to Icons.Filled.CalendarToday,
626
+ "Upcoming" to Icons.Filled.EventNote,
627
+ "Search" to Icons.Filled.Search,
628
+ "Browse" to Icons.Filled.GridView,
629
+ )
630
+ items.forEachIndexed { i, (label, icon) ->
631
+ NavigationBarItem(
632
+ selected = selected == i,
633
+ onClick = { onSelect(i) },
634
+ icon = { Icon(icon, contentDescription = label, modifier = Modifier.size(22.dp)) },
635
+ label = { Text(label, style = TodoistText.Tab) },
636
+ colors = NavigationBarItemDefaults.colors(
637
+ selectedIconColor = TodoistColors.Red,
638
+ selectedTextColor = TodoistColors.Red,
639
+ unselectedIconColor = TodoistColors.Secondary,
640
+ unselectedTextColor = TodoistColors.Secondary,
641
+ indicatorColor = TodoistColors.Red.copy(alpha = 0.08f),
642
+ ),
643
+ )
644
+ }
645
+ }
646
+ }
647
+ ```
648
+
649
+ The FAB sits 24.dp above the bottom bar (or 88.dp above the home indicator when there is no bar) at the trailing edge — render it in the `Scaffold` `floatingActionButton` slot.
650
+
651
+ ## 6. Motion
652
+
653
+ | Moment | Compose recipe |
654
+ |--------|----------------|
655
+ | Checkbox tap | fill `animateColorAsState` transparent → priority color over 200ms `tween`; check icon fades in; `HapticFeedbackType.TextHandleMove` |
656
+ | Task complete | 80ms hold → `AnimatedVisibility` `shrinkVertically(tween(250))` + `fadeOut`; list below slides up |
657
+ | Task uncomplete | reverse — `expandVertically` + `fadeIn` |
658
+ | FAB tap | `animateFloatAsState(0.94f)` + shadow `16.dp → 4.dp`; `HapticFeedbackType.LongPress` |
659
+ | Quick-add sheet | Material 3 `ModalBottomSheet` (spring); commit → success-style haptic |
660
+ | Smart-parsing chip | `AnimatedVisibility` scale 0.8 → 1.0 + fade over 200ms; `HapticFeedbackType.TextHandleMove` per chip |
661
+ | Karma flame pulse | `rememberInfiniteTransition` alpha 0.7 → 1.0, 800ms `RepeatMode.Reverse` |
662
+
663
+ ```kotlin
664
+ // Karma flame ember pulse (DESIGN.md §4 Karma Flame)
665
+ @Composable
666
+ fun KarmaFlame() {
667
+ val t = rememberInfiniteTransition(label = "karma")
668
+ val a by t.animateFloat(0.7f, 1f, infiniteRepeatable(tween(800), RepeatMode.Reverse), label = "ember")
669
+ Icon(
670
+ Icons.Filled.LocalFireDepartment,
671
+ contentDescription = "Karma streak",
672
+ tint = TodoistColors.Red,
673
+ modifier = Modifier.size(14.dp).graphicsLayer { alpha = a },
674
+ )
675
+ }
676
+ ```
677
+
678
+ Haptics: prefer `LocalHapticFeedback`. For the lighter checkbox tick use `LocalView.current.performHapticFeedback(HapticFeedbackConstants.CLOCK_TICK)`; for the quick-add success a `Vibrator` `VibrationEffect.createOneShot(10, ...)` approximates iOS `.notificationOccurred(.success)`.
679
+
680
+ ## 7. Icons
681
+
682
+ Todoist uses standard system glyphs (no custom typeface, minimal custom iconography). The closest first-party set is `androidx.compose.material:material-icons-extended`; the flag and karma flame are good vector-drawable candidates if you want pixel parity.
683
+
684
+ | Purpose | SF Symbol (iOS) | Material Icon (Compose) |
685
+ |---------|-----------------|--------------------------|
686
+ | Checkbox empty | `circle` | `Icons.Outlined.Circle` |
687
+ | Checkbox complete | `circle.fill` + `checkmark` | filled circle + `Icons.Filled.Check` |
688
+ | Priority flag | `flag.fill` / `flag` | `Icons.Filled.Flag` / `Icons.Outlined.Flag` |
689
+ | FAB | `plus` | `Icons.Filled.Add` |
690
+ | Today filter | `calendar` | `Icons.Filled.CalendarToday` |
691
+ | Upcoming | `calendar.badge.clock` | `Icons.Filled.EventNote` |
692
+ | Filters & Labels | `magnifyingglass` | `Icons.Filled.Search` |
693
+ | Project (sidebar) | color dot | colored `Box` + `CircleShape` |
694
+ | Comment count | `bubble.right` | `Icons.AutoMirrored.Outlined.Comment` |
695
+ | Sort / filter | `slider.horizontal.3` | `Icons.Filled.Tune` |
696
+ | Menu (drawer) | `line.horizontal.3` | `Icons.Filled.Menu` |
697
+ | Karma flame | `flame.fill` | `Icons.Filled.LocalFireDepartment` |
698
+ | Schedule (swipe) | `calendar` | `Icons.Filled.CalendarToday` |
699
+ | Reminders (chip) | `bell` | `Icons.Filled.Notifications` |
700
+ | Labels (chip) | `tag` | `Icons.Filled.Label` |
701
+
702
+ ## 8. Minimum SDK & Accessibility Notes
703
+
704
+ - **minSdk 24** (Compose floor is 21; the tinted-shadow FAB needs API 28+ for `spotColor` — see fallback in §3). `compileSdk 34+`, Compose BOM `2024.09+`, Kotlin `2.0+`.
705
+ - **Edge-to-edge**: call `enableEdgeToEdge()` in the `Activity`. Apply `Scaffold` insets or `Modifier.windowInsetsPadding(WindowInsets.systemBars)` so the FAB sits 24.dp above the gesture nav and edge-to-edge task rows aren't clipped by the cutout.
706
+ - **Font scaling**: `sp` honors the user's font scale automatically — keep it on task content, sidebar items, and the large nav title. Pin layout-sensitive text: the 13sp UPPERCASE section headers, 13sp date metadata, the 28sp FAB glyph, and tab labels are layout-critical — derive from `dp` or wrap in `CompositionLocalProvider(LocalDensity provides Density(density, fontScale = 1f))`. The 22sp checkbox hit area must stay 44.dp regardless.
707
+ - **TalkBack**: the task row should merge into one element with `Modifier.semantics(mergeDescendants = true) { contentDescription = "$priority, $content, $dateText, $project, $commentCount comments" }`, and the checkbox must be a **separate** focusable element ("Mark complete" / "Mark incomplete"). Priority is non-decorative meaning — it must be in the spoken label, never implied by color alone.
708
+ - **Touch targets**: Material guidance is 48.dp minimum. The 56.dp FAB clears it; the 22.dp checkbox carries a 44.dp hit area via padding (do not compress even if the row visually looks smaller); the section-header chevron carries a 48.dp hit area.
709
+ - **Contrast**: Ink `#202020` on white passes WCAG AAA at all sizes. Secondary `#808080` on white only passes AA at 14sp+ Medium or 18sp+ — used carefully for 13sp metadata; if targeting strict compliance, bump metadata toward `#6E6E6E`. The P2 orange `#EB8909` on white is a known low-contrast pair for the date pill — it passes AA only at 16sp+ Bold, so keep the overdue/today states (red/green) for anything smaller.
710
+ - **Reduce motion**: when a reduced-motion preference is set, skip the 250ms collapse-upward (instant fade out) and the smart-chip scale-in.
711
+ - **Dynamic color**: Todoist *could* embrace Material You for a system-blended feel, but the brand depends on the exact carmine `#DC4C3E` (FAB, P1, brand mark) — keep `dynamicColorScheme` **disabled** so the verb-red and the four-tier priority colors never shift with the user's wallpaper.