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,695 @@
1
+ # Slack (iOS) — Jetpack Compose Implementation Guide
2
+
3
+ Companion to [DESIGN.md](DESIGN.md) — the framework-neutral spec. This file ports Slack's visual language to **Android with Jetpack Compose (Material 3)**: a color token object, 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. This file keeps the *visual* identity (the workspace-customizable Aubergine sidebar, rounded-square avatars, inline reaction pill chips, first-class threads, the colored mention pills) while making everything idiomatic Android — a `ModalNavigationDrawer` for the sidebar, `NavigationBar` instead of a UITabBar, `sp`/`dp` instead of `pt`.
6
+
7
+ Assumes Compose BOM `2024.09+`, Kotlin `2.0+`, `minSdk 24`, Material 3, and [Coil](https://coil-kt.github.io/coil/) `2.6+` for DM/message avatars.
8
+
9
+ ## 1. Color Tokens
10
+
11
+ ```kotlin
12
+ // ui/theme/SlackColors.kt
13
+ import androidx.compose.ui.graphics.Color
14
+
15
+ object SlackColors {
16
+ // Sidebar (default Aubergine theme — workspace-customizable)
17
+ val Aubergine = Color(0xFF4A154B)
18
+ val AubergineDark = Color(0xFF3F0E40)
19
+ val AubergineActive = Color(0xFF1164A3) // selected channel row bg
20
+ val SidebarText = Color(0xFFCFC3CF) // muted lavender-white
21
+ val SidebarActiveText = Color(0xFFFFFFFF)
22
+
23
+ // Brand 4-color logo palette (logo + some chrome)
24
+ val LogoYellow = Color(0xFFECB22E)
25
+ val LogoPink = Color(0xFFE01E5A)
26
+ val LogoGreen = Color(0xFF2EB67D)
27
+ val LogoBlue = Color(0xFF36C5F0)
28
+
29
+ // Canvas (Light content area)
30
+ val Canvas = Color(0xFFFFFFFF)
31
+ val Surface = Color(0xFFF8F8F8)
32
+ val Pressed = Color(0xFFE6E6E6)
33
+ val Divider = Color(0xFFDDDDDD)
34
+
35
+ // Canvas (Dark content area) — charcoal, not black
36
+ val DarkCanvas = Color(0xFF1A1D21)
37
+ val DarkSurface1 = Color(0xFF222529)
38
+ val DarkSurface2 = Color(0xFF2C2D30)
39
+ val DarkDivider = Color(0xFF35373B)
40
+
41
+ // Text
42
+ val TextPrimary = Color(0xFF1D1C1D)
43
+ val TextSecondary = Color(0xFF616061)
44
+ val TextTertiary = Color(0xFF868686)
45
+ val DarkTextPrimary = Color(0xFFD1D2D3)
46
+ val DarkTextSecondary = Color(0xFFABABAD)
47
+
48
+ // Semantic & status
49
+ val OnlineGreen = Color(0xFF007A5A) // darker than logo green — dot legibility
50
+ val MentionRed = Color(0xFFE01E5A)
51
+ val TypingBlue = Color(0xFF1264A3) // typing + Huddles strip
52
+ val LinkBlue = Color(0xFF1264A3)
53
+
54
+ // Mention pill backgrounds (light)
55
+ val MentionChannelBg = Color(0xFFF5E3BE)
56
+ val MentionHereBg = Color(0xFFFEF9E7)
57
+ val MentionUserBg = Color(0xFFF9D5DB)
58
+ val ReactionSelfBg = Color(0xFFE3F2FC)
59
+ }
60
+ ```
61
+
62
+ Slack's content area is white (light) / charcoal (dark) — the saturated color lives only in the sidebar. Wire a Material 3 `lightColorScheme`/`darkColorScheme` for the **content canvas**. Aubergine is *not* `primary` — it is the sidebar's color and is passed in as a value (workspace-customizable). Use `OnlineGreen` for send/primary actions.
63
+
64
+ ```kotlin
65
+ // ui/theme/Theme.kt
66
+ import androidx.compose.material3.*
67
+ import androidx.compose.runtime.Composable
68
+ import androidx.compose.foundation.isSystemInDarkTheme
69
+
70
+ private val SlackLight = lightColorScheme(
71
+ primary = SlackColors.OnlineGreen, // send / primary actions
72
+ onPrimary = Color.White,
73
+ background = SlackColors.Canvas,
74
+ onBackground = SlackColors.TextPrimary,
75
+ surface = SlackColors.Canvas,
76
+ onSurface = SlackColors.TextPrimary,
77
+ surfaceVariant = SlackColors.Surface,
78
+ outline = SlackColors.Divider,
79
+ error = SlackColors.MentionRed,
80
+ )
81
+
82
+ private val SlackDark = darkColorScheme(
83
+ primary = SlackColors.OnlineGreen,
84
+ onPrimary = Color.White,
85
+ background = SlackColors.DarkCanvas,
86
+ onBackground = SlackColors.DarkTextPrimary,
87
+ surface = SlackColors.DarkSurface1,
88
+ onSurface = SlackColors.DarkTextPrimary,
89
+ surfaceVariant = SlackColors.DarkSurface2,
90
+ outline = SlackColors.DarkDivider,
91
+ error = SlackColors.MentionRed,
92
+ )
93
+
94
+ @Composable
95
+ fun SlackTheme(
96
+ dark: Boolean = isSystemInDarkTheme(),
97
+ content: @Composable () -> Unit,
98
+ ) = MaterialTheme(
99
+ colorScheme = if (dark) SlackDark else SlackLight,
100
+ typography = SlackTypography,
101
+ content = content,
102
+ )
103
+ ```
104
+
105
+ ## 2. Typography
106
+
107
+ Slack Lato (proprietary; evolved from Lato) is the voice. Drop the TTFs in `res/font/` and build a `FontFamily`. Fall back to **Lato** (Apache 2.0, ships well as a bundled font) — visually very close; the system font (Roboto) loses Lato's warmth. Use weights 400 / 600 / 700 only — never 300/500/900.
108
+
109
+ ```kotlin
110
+ // ui/theme/SlackType.kt
111
+ import androidx.compose.material3.Typography
112
+ import androidx.compose.ui.text.TextStyle
113
+ import androidx.compose.ui.text.font.Font
114
+ import androidx.compose.ui.text.font.FontFamily
115
+ import androidx.compose.ui.text.font.FontWeight
116
+ import androidx.compose.ui.unit.sp
117
+
118
+ val SlackLato = FontFamily(
119
+ Font(R.font.slack_lato_regular, FontWeight.Normal), // 400 — body
120
+ Font(R.font.slack_lato_semibold, FontWeight.SemiBold), // 600 — reactions / threads
121
+ Font(R.font.slack_lato_bold, FontWeight.Bold), // 700 — names / headings
122
+ )
123
+
124
+ // Named ramp — mirrors DESIGN.md §3 exactly (pt → sp 1:1)
125
+ object SlackText {
126
+ val WorkspaceName = TextStyle(SlackLato, fontWeight = FontWeight.Bold, fontSize = 18.sp, lineHeight = 22.sp, letterSpacing = (-0.2).sp)
127
+ val ChannelActive = TextStyle(SlackLato, fontWeight = FontWeight.Bold, fontSize = 15.sp, lineHeight = 20.sp)
128
+ val ChannelDefault = TextStyle(SlackLato, fontWeight = FontWeight.Normal, fontSize = 15.sp, lineHeight = 20.sp)
129
+ val ChannelHeader = TextStyle(SlackLato, fontWeight = FontWeight.Bold, fontSize = 17.sp, lineHeight = 20.sp)
130
+ val ChannelTopic = TextStyle(SlackLato, fontWeight = FontWeight.Normal, fontSize = 13.sp, lineHeight = 17.sp)
131
+ val Username = TextStyle(SlackLato, fontWeight = FontWeight.Bold, fontSize = 15.sp, lineHeight = 20.sp)
132
+ val Timestamp = TextStyle(SlackLato, fontWeight = FontWeight.Normal, fontSize = 12.sp, lineHeight = 14.sp)
133
+ val MessageBody = TextStyle(SlackLato, fontWeight = FontWeight.Normal, fontSize = 15.sp, lineHeight = 23.sp)
134
+ val ThreadCount = TextStyle(SlackLato, fontWeight = FontWeight.SemiBold, fontSize = 13.sp, lineHeight = 13.sp)
135
+ val ReactionCount = TextStyle(SlackLato, fontWeight = FontWeight.SemiBold, fontSize = 12.sp, lineHeight = 12.sp)
136
+ val MentionText = TextStyle(SlackLato, fontWeight = FontWeight.Bold, fontSize = 15.sp, lineHeight = 23.sp)
137
+ val ButtonPrimary = TextStyle(SlackLato, fontWeight = FontWeight.Bold, fontSize = 15.sp, lineHeight = 15.sp)
138
+ val ButtonSecondary = TextStyle(SlackLato, fontWeight = FontWeight.SemiBold, fontSize = 14.sp, lineHeight = 14.sp)
139
+ val TabLabel = TextStyle(SlackLato, fontWeight = FontWeight.SemiBold, fontSize = 11.sp, lineHeight = 11.sp, letterSpacing = 0.1.sp)
140
+ val SectionHeader = TextStyle(SlackLato, fontWeight = FontWeight.Bold, fontSize = 11.sp, lineHeight = 13.sp, letterSpacing = 1.0.sp)
141
+ val CodeInline = TextStyle(FontFamily.Monospace, fontWeight = FontWeight.Normal, fontSize = 13.sp, lineHeight = 18.sp)
142
+ }
143
+
144
+ val SlackTypography = Typography(
145
+ headlineSmall = SlackText.ChannelHeader,
146
+ titleMedium = SlackText.Username,
147
+ bodyMedium = SlackText.MessageBody,
148
+ labelMedium = SlackText.Timestamp,
149
+ labelSmall = SlackText.TabLabel,
150
+ )
151
+ ```
152
+
153
+ ## 3. Signature Components
154
+
155
+ ### Aubergine Sidebar (workspace-customizable)
156
+
157
+ Full-height pane in `#4A154B` (or workspace-custom) — workspace header + section headers + channel rows. Channel text is muted lavender by default, bold white for unread, bold white on a blue row when active. On Android the swipe-in sidebar is a `ModalNavigationDrawer`.
158
+
159
+ ```kotlin
160
+ import androidx.compose.foundation.background
161
+ import androidx.compose.foundation.layout.*
162
+ import androidx.compose.foundation.lazy.LazyColumn
163
+ import androidx.compose.foundation.shape.RoundedCornerShape
164
+ import androidx.compose.material.icons.Icons
165
+ import androidx.compose.material.icons.filled.Lock
166
+ import androidx.compose.material3.*
167
+ import androidx.compose.runtime.Composable
168
+ import androidx.compose.ui.Alignment
169
+ import androidx.compose.ui.Modifier
170
+ import androidx.compose.ui.draw.clip
171
+ import androidx.compose.ui.graphics.Color
172
+ import androidx.compose.ui.layout.ContentScale
173
+ import androidx.compose.ui.unit.dp
174
+ import coil.compose.AsyncImage
175
+
176
+ sealed interface ChannelType {
177
+ data object Public : ChannelType
178
+ data object Private : ChannelType
179
+ data class Dm(val avatarUrl: String) : ChannelType
180
+ }
181
+
182
+ data class ChannelRow(
183
+ val type: ChannelType,
184
+ val name: String,
185
+ val isUnread: Boolean,
186
+ val mentionCount: Int,
187
+ )
188
+
189
+ data class SidebarSection(val title: String, val channels: List<ChannelRow>)
190
+
191
+ @Composable
192
+ fun SlackSidebar(
193
+ workspaceName: String,
194
+ sidebarColor: Color, // pass SlackColors.Aubergine or a workspace-custom hex
195
+ sections: List<SidebarSection>,
196
+ activeChannel: String?,
197
+ onSelect: (ChannelRow) -> Unit,
198
+ ) {
199
+ Column(
200
+ Modifier
201
+ .fillMaxHeight()
202
+ .width(280.dp)
203
+ .background(sidebarColor),
204
+ ) {
205
+ // Workspace header
206
+ Row(
207
+ Modifier.fillMaxWidth().height(56.dp).padding(horizontal = 16.dp),
208
+ verticalAlignment = Alignment.CenterVertically,
209
+ horizontalArrangement = Arrangement.spacedBy(12.dp),
210
+ ) {
211
+ Box(
212
+ Modifier.size(32.dp).clip(RoundedCornerShape(4.dp)).background(SlackColors.LogoBlue),
213
+ contentAlignment = Alignment.Center,
214
+ ) { Text(workspaceName.take(1), color = Color.White, style = SlackText.Username) }
215
+ Column(Modifier.weight(1f)) {
216
+ Text(workspaceName, style = SlackText.WorkspaceName, color = Color.White, maxLines = 1)
217
+ Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(4.dp)) {
218
+ Box(Modifier.size(8.dp).clip(CircleShape).background(SlackColors.OnlineGreen))
219
+ Text("You", style = SlackText.ChannelTopic, color = SlackColors.SidebarText)
220
+ }
221
+ }
222
+ }
223
+
224
+ LazyColumn(Modifier.fillMaxSize()) {
225
+ sections.forEach { section ->
226
+ item {
227
+ Text(
228
+ section.title.uppercase(),
229
+ style = SlackText.SectionHeader,
230
+ color = SlackColors.SidebarText.copy(alpha = 0.5f),
231
+ modifier = Modifier.padding(start = 16.dp, end = 16.dp, top = 16.dp, bottom = 4.dp),
232
+ )
233
+ }
234
+ items(section.channels) { ch ->
235
+ SidebarChannelRow(ch, isActive = ch.name == activeChannel, onClick = { onSelect(ch) })
236
+ }
237
+ }
238
+ }
239
+ }
240
+ }
241
+
242
+ @Composable
243
+ fun SidebarChannelRow(channel: ChannelRow, isActive: Boolean, onClick: () -> Unit) {
244
+ val nameStyle = if (isActive || channel.isUnread) SlackText.ChannelActive else SlackText.ChannelDefault
245
+ val nameColor = if (isActive || channel.isUnread) Color.White else SlackColors.SidebarText
246
+
247
+ Row(
248
+ Modifier
249
+ .fillMaxWidth()
250
+ .height(32.dp)
251
+ .background(if (isActive) SlackColors.AubergineActive else Color.Transparent)
252
+ .clickableNoRipple(onClick)
253
+ .padding(horizontal = 16.dp),
254
+ verticalAlignment = Alignment.CenterVertically,
255
+ horizontalArrangement = Arrangement.spacedBy(12.dp),
256
+ ) {
257
+ when (val t = channel.type) {
258
+ ChannelType.Public -> Text("#", color = nameColor, style = SlackText.ChannelDefault, modifier = Modifier.width(20.dp))
259
+ ChannelType.Private -> Icon(Icons.Filled.Lock, null, tint = nameColor, modifier = Modifier.size(14.dp).width(20.dp))
260
+ is ChannelType.Dm -> AsyncImage(
261
+ model = t.avatarUrl, contentDescription = null, contentScale = ContentScale.Crop,
262
+ modifier = Modifier.size(20.dp).clip(RoundedCornerShape(3.dp)),
263
+ )
264
+ }
265
+ Text(channel.name, style = nameStyle, color = nameColor, modifier = Modifier.weight(1f))
266
+ if (channel.mentionCount > 0) {
267
+ Box(
268
+ Modifier.clip(CircleShape).background(SlackColors.MentionRed).padding(horizontal = 6.dp, vertical = 2.dp),
269
+ ) { Text("${channel.mentionCount}", style = SlackText.ReactionCount, color = Color.White) }
270
+ }
271
+ }
272
+ }
273
+
274
+ import androidx.compose.foundation.clickable
275
+ import androidx.compose.foundation.interaction.MutableInteractionSource
276
+ import androidx.compose.foundation.shape.CircleShape
277
+ import androidx.compose.runtime.remember
278
+ import androidx.compose.ui.composed
279
+ fun Modifier.clickableNoRipple(onClick: () -> Unit): Modifier = composed {
280
+ clickable(remember { MutableInteractionSource() }, indication = null, onClick = onClick)
281
+ }
282
+ ```
283
+
284
+ ### Message Row
285
+
286
+ 16.dp horizontal padding; 12.dp top margin for a new sender (4.dp for collapsed consecutive). Leading is a **36.dp rounded-square** avatar (4.dp corner — Slack's signature, NOT a circle) with an 8.dp online dot. Body → reaction chips → thread indicator.
287
+
288
+ ```kotlin
289
+ import androidx.compose.foundation.border
290
+ import androidx.compose.foundation.lazy.LazyRow
291
+
292
+ data class Reaction(val emoji: String, val count: Int, val youReacted: Boolean)
293
+
294
+ @Composable
295
+ fun SlackMessageRow(
296
+ username: String,
297
+ avatarUrl: String?,
298
+ statusEmoji: String?,
299
+ status: String?,
300
+ isOnline: Boolean,
301
+ timestamp: String,
302
+ body: String,
303
+ reactions: List<Reaction>,
304
+ threadReplyCount: Int?,
305
+ threadLastReply: String?,
306
+ isNewSender: Boolean,
307
+ modifier: Modifier = Modifier,
308
+ ) {
309
+ Row(
310
+ modifier = modifier
311
+ .fillMaxWidth()
312
+ .padding(horizontal = 16.dp, vertical = if (isNewSender) 8.dp else 2.dp),
313
+ horizontalArrangement = Arrangement.spacedBy(12.dp),
314
+ ) {
315
+ if (isNewSender) {
316
+ Box {
317
+ if (avatarUrl != null) {
318
+ AsyncImage(
319
+ model = avatarUrl, contentDescription = null, contentScale = ContentScale.Crop,
320
+ modifier = Modifier.size(36.dp).clip(RoundedCornerShape(4.dp)), // rounded square
321
+ )
322
+ } else {
323
+ Box(Modifier.size(36.dp).clip(RoundedCornerShape(4.dp)).background(SlackColors.LogoGreen))
324
+ }
325
+ if (isOnline) {
326
+ Box(
327
+ Modifier
328
+ .align(Alignment.BottomEnd)
329
+ .size(10.dp)
330
+ .clip(CircleShape)
331
+ .background(SlackColors.Canvas)
332
+ .padding(1.dp)
333
+ ) {
334
+ Box(Modifier.fillMaxSize().clip(CircleShape).background(SlackColors.OnlineGreen))
335
+ }
336
+ }
337
+ }
338
+ } else {
339
+ Spacer(Modifier.width(36.dp))
340
+ }
341
+
342
+ Column(verticalArrangement = Arrangement.spacedBy(4.dp)) {
343
+ if (isNewSender) {
344
+ Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(6.dp)) {
345
+ Text(username, style = SlackText.Username, color = SlackColors.TextPrimary)
346
+ statusEmoji?.let { Text(it) }
347
+ status?.let { Text(it, style = SlackText.ChannelTopic, color = SlackColors.TextSecondary, maxLines = 1) }
348
+ Text(timestamp, style = SlackText.Timestamp, color = SlackColors.TextSecondary)
349
+ }
350
+ }
351
+ Text(body, style = SlackText.MessageBody, color = SlackColors.TextPrimary)
352
+ if (reactions.isNotEmpty()) {
353
+ LazyRow(horizontalArrangement = Arrangement.spacedBy(4.dp)) {
354
+ items(reactions) { ReactionChip(it) }
355
+ item { AddReactionChip() }
356
+ }
357
+ }
358
+ if (threadReplyCount != null && threadReplyCount > 0) {
359
+ ThreadIndicator(threadReplyCount, threadLastReply ?: "")
360
+ }
361
+ }
362
+ }
363
+ }
364
+ ```
365
+
366
+ ### Reaction Chip
367
+
368
+ Pill (full radius), `Surface` default → `ReactionSelfBg` with a 1.dp blue border when you've reacted.
369
+
370
+ ```kotlin
371
+ import androidx.compose.material.icons.filled.AddReaction
372
+ import androidx.compose.ui.hapticfeedback.HapticFeedbackType
373
+ import androidx.compose.ui.platform.LocalHapticFeedback
374
+
375
+ @Composable
376
+ fun ReactionChip(r: Reaction) {
377
+ val haptics = LocalHapticFeedback.current
378
+ Row(
379
+ Modifier
380
+ .clip(CircleShape)
381
+ .background(if (r.youReacted) SlackColors.ReactionSelfBg else SlackColors.Surface)
382
+ .then(if (r.youReacted) Modifier.border(1.dp, SlackColors.TypingBlue, CircleShape) else Modifier)
383
+ .clickableNoRipple { haptics.performHapticFeedback(HapticFeedbackType.LongPress) }
384
+ .padding(horizontal = 8.dp, vertical = 4.dp),
385
+ verticalAlignment = Alignment.CenterVertically,
386
+ horizontalArrangement = Arrangement.spacedBy(4.dp),
387
+ ) {
388
+ Text(r.emoji, style = SlackText.MessageBody)
389
+ Text("${r.count}", style = SlackText.ReactionCount, color = SlackColors.TextPrimary)
390
+ }
391
+ }
392
+
393
+ @Composable
394
+ fun AddReactionChip() {
395
+ Box(
396
+ Modifier.clip(CircleShape).background(SlackColors.Surface).padding(horizontal = 8.dp, vertical = 4.dp),
397
+ ) { Icon(Icons.Filled.AddReaction, "Add reaction", tint = SlackColors.TextSecondary, modifier = Modifier.size(14.dp)) }
398
+ }
399
+ ```
400
+
401
+ ### Thread Indicator (threads are first-class)
402
+
403
+ ```kotlin
404
+ import androidx.compose.material.icons.automirrored.filled.KeyboardArrowRight
405
+
406
+ @Composable
407
+ fun ThreadIndicator(replyCount: Int, lastReply: String, onClick: () -> Unit = {}) {
408
+ Row(
409
+ Modifier.fillMaxWidth().clickableNoRipple(onClick),
410
+ verticalAlignment = Alignment.CenterVertically,
411
+ horizontalArrangement = Arrangement.spacedBy(6.dp),
412
+ ) {
413
+ // up to 3 overlapping rounded-square replier avatars
414
+ Box {
415
+ val palette = listOf(SlackColors.LogoYellow, SlackColors.LogoPink, SlackColors.LogoGreen)
416
+ repeat(minOf(3, replyCount)) { i ->
417
+ Box(
418
+ Modifier
419
+ .padding(start = (i * 10).dp)
420
+ .size(16.dp)
421
+ .clip(RoundedCornerShape(3.dp))
422
+ .background(palette[i % 3])
423
+ .border(1.dp, SlackColors.Canvas, RoundedCornerShape(3.dp))
424
+ )
425
+ }
426
+ }
427
+ Text(
428
+ "$replyCount ${if (replyCount == 1) "reply" else "replies"}",
429
+ style = SlackText.ThreadCount,
430
+ color = SlackColors.LinkBlue,
431
+ )
432
+ Text("• $lastReply", style = SlackText.Timestamp, color = SlackColors.TextSecondary)
433
+ Spacer(Modifier.weight(1f))
434
+ Icon(Icons.AutoMirrored.Filled.KeyboardArrowRight, null, tint = SlackColors.TextSecondary, modifier = Modifier.size(12.dp))
435
+ }
436
+ }
437
+ ```
438
+
439
+ ### Mention Pill (inline)
440
+
441
+ `@channel` green, `@here` yellow, `@user` red — colored background, bold text, 4.dp corner (not a pill).
442
+
443
+ ```kotlin
444
+ import androidx.compose.foundation.text.appendInlineContent
445
+ import androidx.compose.ui.text.AnnotatedString
446
+
447
+ sealed interface Mention {
448
+ data object Channel : Mention
449
+ data object Here : Mention
450
+ data class User(val name: String) : Mention
451
+ }
452
+
453
+ @Composable
454
+ fun MentionPill(mention: Mention) {
455
+ val (label, bg, fg) = when (mention) {
456
+ Mention.Channel -> Triple("@channel", SlackColors.LogoGreen.copy(alpha = 0.2f), Color(0xFF0F7B6C))
457
+ Mention.Here -> Triple("@here", SlackColors.LogoYellow.copy(alpha = 0.2f), Color(0xFF665208))
458
+ is Mention.User -> Triple("@${mention.name}", SlackColors.MentionUserBg, Color(0xFF5A2731))
459
+ }
460
+ Text(
461
+ label,
462
+ style = SlackText.MentionText,
463
+ color = fg,
464
+ modifier = Modifier
465
+ .clip(RoundedCornerShape(4.dp))
466
+ .background(bg)
467
+ .padding(horizontal = 4.dp, vertical = 1.dp),
468
+ )
469
+ }
470
+ ```
471
+
472
+ ### Huddles Banner & Message Composer
473
+
474
+ ```kotlin
475
+ import androidx.compose.foundation.text.BasicTextField
476
+ import androidx.compose.material.icons.filled.Add
477
+ import androidx.compose.material.icons.filled.Send
478
+
479
+ @Composable
480
+ fun HuddlesBanner(onJoin: () -> Unit) {
481
+ Row(
482
+ Modifier.fillMaxWidth().height(56.dp).background(SlackColors.TypingBlue).padding(horizontal = 16.dp),
483
+ verticalAlignment = Alignment.CenterVertically,
484
+ horizontalArrangement = Arrangement.spacedBy(12.dp),
485
+ ) {
486
+ // 4-color pinwheel
487
+ Column {
488
+ Row { Box(Modifier.size(8.dp).background(SlackColors.LogoYellow)); Box(Modifier.size(8.dp).background(SlackColors.LogoPink)) }
489
+ Row { Box(Modifier.size(8.dp).background(SlackColors.LogoGreen)); Box(Modifier.size(8.dp).background(SlackColors.LogoBlue)) }
490
+ }
491
+ Text("Huddle in progress", style = SlackText.ButtonPrimary, color = Color.White)
492
+ Spacer(Modifier.weight(1f))
493
+ Box(
494
+ Modifier.clip(RoundedCornerShape(4.dp)).background(Color.White).clickableNoRipple(onJoin)
495
+ .padding(horizontal = 16.dp, vertical = 8.dp),
496
+ ) { Text("Join", style = SlackText.ButtonSecondary, color = SlackColors.TypingBlue) }
497
+ }
498
+ }
499
+
500
+ @Composable
501
+ fun MessageComposer(channelName: String, modifier: Modifier = Modifier) {
502
+ var text by remember { mutableStateOf("") }
503
+ val haptics = LocalHapticFeedback.current
504
+
505
+ Row(
506
+ modifier = modifier
507
+ .fillMaxWidth()
508
+ .background(SlackColors.Canvas)
509
+ .padding(8.dp),
510
+ verticalAlignment = Alignment.Bottom,
511
+ horizontalArrangement = Arrangement.spacedBy(8.dp),
512
+ ) {
513
+ Icon(Icons.Filled.Add, "Attach", tint = SlackColors.TextSecondary, modifier = Modifier.size(40.dp).padding(8.dp))
514
+ BasicTextField(
515
+ value = text,
516
+ onValueChange = { text = it },
517
+ textStyle = SlackText.MessageBody.copy(color = SlackColors.TextPrimary),
518
+ modifier = Modifier
519
+ .weight(1f)
520
+ .clip(RoundedCornerShape(8.dp))
521
+ .background(SlackColors.Surface)
522
+ .padding(horizontal = 12.dp, vertical = 10.dp),
523
+ decorationBox = { inner ->
524
+ if (text.isEmpty()) Text("Message #$channelName", style = SlackText.MessageBody, color = SlackColors.TextSecondary)
525
+ inner()
526
+ },
527
+ )
528
+ Box(
529
+ Modifier
530
+ .size(32.dp)
531
+ .clip(RoundedCornerShape(4.dp)) // square, 4dp — Slack's send button
532
+ .background(if (text.isEmpty()) SlackColors.TextTertiary else SlackColors.OnlineGreen)
533
+ .clickableNoRipple {
534
+ if (text.isNotEmpty()) {
535
+ haptics.performHapticFeedback(HapticFeedbackType.LongPress)
536
+ text = ""
537
+ }
538
+ },
539
+ contentAlignment = Alignment.Center,
540
+ ) { Icon(Icons.AutoMirrored.Filled.Send, "Send", tint = Color.White, modifier = Modifier.size(16.dp)) }
541
+ }
542
+ }
543
+ ```
544
+
545
+ ## 4. Workspace-Customizable Sidebar Theme
546
+
547
+ Slack's signature: every workspace can pick its own sidebar color (admins can set any hex). iOS hands a `WorkspaceTheme` per screen; in Compose model it as a `CompositionLocal` and pick readable channel-text color from luminance so any custom hex stays accessible.
548
+
549
+ ```kotlin
550
+ import androidx.compose.runtime.compositionLocalOf
551
+ import androidx.compose.runtime.CompositionLocalProvider
552
+ import androidx.compose.ui.graphics.luminance
553
+
554
+ data class WorkspaceTheme(
555
+ val sidebarColor: Color = SlackColors.Aubergine,
556
+ val activeChannelColor: Color = SlackColors.AubergineActive,
557
+ ) {
558
+ companion object {
559
+ val Aubergine = WorkspaceTheme()
560
+ val Monument = WorkspaceTheme(Color(0xFF2C2D30), Color(0xFF481349))
561
+ val Tangerine = WorkspaceTheme(Color(0xFFCA4400), Color(0xFF6B140C))
562
+ fun custom(sidebar: Color, active: Color) = WorkspaceTheme(sidebar, active)
563
+ }
564
+ }
565
+
566
+ val LocalWorkspaceTheme = compositionLocalOf { WorkspaceTheme.Aubergine }
567
+
568
+ @Composable
569
+ fun ProvideWorkspaceTheme(theme: WorkspaceTheme, content: @Composable () -> Unit) =
570
+ CompositionLocalProvider(LocalWorkspaceTheme provides theme, content = content)
571
+
572
+ // Channel text must remain legible on any chosen sidebar hex
573
+ fun sidebarTextColor(sidebar: Color): Color =
574
+ if (sidebar.luminance() > 0.5f) SlackColors.TextPrimary else SlackColors.SidebarText
575
+ ```
576
+
577
+ ## 5. Navigation
578
+
579
+ Slack's sidebar is the `ModalNavigationDrawer` (swipe-right to open, swipe-left to close — matches the spec). The five destinations (Home, DMs, Activity, Later, Search) are a Material 3 `NavigationBar`. Active state is a **bold neutral icon, not a color shift**. Solid surface, no blur. Threads are first-class: on phones the thread "pane" is a full-screen destination that slides in from the right.
580
+
581
+ ```kotlin
582
+ import androidx.compose.material.icons.automirrored.filled.Chat
583
+ import androidx.compose.material.icons.filled.*
584
+
585
+ @Composable
586
+ fun SlackBottomBar(selected: Int, unreadActivity: Int, onSelect: (Int) -> Unit) {
587
+ NavigationBar(
588
+ containerColor = SlackColors.Canvas, // solid, no blur
589
+ tonalElevation = 0.dp,
590
+ ) {
591
+ data class Tab(val label: String, val icon: androidx.compose.ui.graphics.vector.ImageVector, val badge: Int = 0)
592
+ val tabs = listOf(
593
+ Tab("Home", Icons.Filled.Home),
594
+ Tab("DMs", Icons.AutoMirrored.Filled.Chat),
595
+ Tab("Activity", Icons.Filled.Notifications, badge = unreadActivity),
596
+ Tab("Later", Icons.Filled.BookmarkBorder),
597
+ Tab("Search", Icons.Filled.Search),
598
+ )
599
+ tabs.forEachIndexed { i, t ->
600
+ NavigationBarItem(
601
+ selected = selected == i,
602
+ onClick = { onSelect(i) },
603
+ icon = {
604
+ if (t.badge > 0) {
605
+ BadgedBox(badge = { Badge(containerColor = SlackColors.MentionRed) { Text("${t.badge}") } }) {
606
+ Icon(t.icon, t.label, modifier = Modifier.size(24.dp))
607
+ }
608
+ } else {
609
+ Icon(t.icon, t.label, modifier = Modifier.size(24.dp))
610
+ }
611
+ },
612
+ label = { Text(t.label, style = SlackText.TabLabel) },
613
+ colors = NavigationBarItemDefaults.colors(
614
+ selectedIconColor = SlackColors.TextPrimary, // bold neutral, no color shift
615
+ selectedTextColor = SlackColors.TextPrimary,
616
+ unselectedIconColor = SlackColors.TextSecondary,
617
+ unselectedTextColor = SlackColors.TextSecondary,
618
+ indicatorColor = Color.Transparent,
619
+ ),
620
+ )
621
+ }
622
+ }
623
+ }
624
+
625
+ // Sidebar wrapper
626
+ @Composable
627
+ fun SlackScaffold(drawerState: DrawerState, sidebar: @Composable () -> Unit, content: @Composable () -> Unit) {
628
+ ModalNavigationDrawer(
629
+ drawerState = drawerState,
630
+ drawerContent = { ModalDrawerSheet(drawerContainerColor = Color.Transparent) { sidebar() } },
631
+ content = content,
632
+ )
633
+ }
634
+ ```
635
+
636
+ ## 6. Motion
637
+
638
+ | Moment | Compose recipe |
639
+ |--------|----------------|
640
+ | Sidebar open/close | `ModalNavigationDrawer` 1:1 drag; commit `spring(dampingRatio = 0.8f, stiffness = 600f)` ~250ms + `HapticFeedbackType.TextHandleMove` |
641
+ | Message send | send button `animateFloatAsState` 1 → 0.9 → 1 over 200ms; message enters via `AnimatedVisibility` `scaleIn(0.96f) + fadeIn()` 250ms |
642
+ | Reaction add | chip `Animatable` 0 → 1.15 → 1 `spring(stiffness = 500f)` ~300ms + soft haptic |
643
+ | Thread pane open | nav transition `slideInHorizontally { it }` (from right) 250ms ease-out |
644
+ | Huddle join | full-screen `fadeIn` + `HapticFeedbackType.Confirm` (success) |
645
+ | Typing indicator | `rememberInfiniteTransition` opacity 1.0 ↔ 0.6 over 1.2s |
646
+
647
+ ```kotlin
648
+ // Reaction chip pop-in
649
+ @Composable
650
+ fun rememberChipPop(trigger: Any): Float {
651
+ val scale = remember { Animatable(0f) }
652
+ LaunchedEffect(trigger) {
653
+ scale.animateTo(1.15f, spring(dampingRatio = 0.6f, stiffness = 500f))
654
+ scale.animateTo(1f, spring(dampingRatio = 0.7f))
655
+ }
656
+ return scale.value
657
+ }
658
+ ```
659
+
660
+ Keep reactions gentle — a single spring scale, never elaborate. Haptics: prefer `LocalHapticFeedback`; soft on send/reaction (`LongPress`), `Confirm` on huddle join, `TextHandleMove` on workspace switch. Honor reduce-motion by skipping the sidebar spring and chip pop while still firing haptics.
661
+
662
+ ## 7. Icons
663
+
664
+ Slack ships custom glyphs (4-color pinwheel, channel `#`); the closest first-party set is `androidx.compose.material:material-icons-extended`. The public-channel `#` renders as a **text character** (universal glyph), not an icon — icons only for private/muted. The pinwheel ships as a vector drawable.
665
+
666
+ | Purpose | SF Symbol (iOS) | Material Icon (Compose) |
667
+ |---------|-----------------|--------------------------|
668
+ | Home (tab) | `house` / `house.fill` | `Icons.Filled.Home` |
669
+ | DMs (tab) | `bubble.left.and.bubble.right` | `Icons.AutoMirrored.Filled.Chat` |
670
+ | Activity (tab) | `bell` / `bell.fill` | `Icons.Filled.Notifications` |
671
+ | Later (tab) | `bookmark` / `bookmark.fill` | `Icons.Filled.BookmarkBorder` / `Icons.Filled.Bookmark` |
672
+ | Search (tab) | `magnifyingglass` | `Icons.Filled.Search` |
673
+ | Channel (public) | `number` | text `#` (universal glyph) |
674
+ | Channel (private) | `lock.fill` | `Icons.Filled.Lock` |
675
+ | Mute | `bell.slash` | `Icons.Filled.NotificationsOff` |
676
+ | Huddle start | `headphones` | `Icons.Filled.Headphones` |
677
+ | Channel info | `info.circle` | `Icons.Filled.Info` |
678
+ | Send | `paperplane.fill` | `Icons.AutoMirrored.Filled.Send` |
679
+ | Attach | `plus` | `Icons.Filled.Add` |
680
+ | Emoji picker | `face.smiling` | `Icons.Filled.AddReaction` |
681
+ | Mention | `at` | `Icons.Filled.AlternateEmail` |
682
+ | Voice note | `mic` | `Icons.Filled.Mic` |
683
+ | Formatting | `textformat` | `Icons.Filled.TextFormat` |
684
+ | Thread chevron | `chevron.right` | `Icons.AutoMirrored.Filled.KeyboardArrowRight` |
685
+
686
+ ## 8. Minimum SDK & Accessibility Notes
687
+
688
+ - **minSdk 24**. `compileSdk 34+`, Compose BOM `2024.09+`, Kotlin `2.0+`.
689
+ - **Edge-to-edge**: call `enableEdgeToEdge()`; system-bar icon color follows light/dark. Apply `Scaffold` insets so the top nav clears the status bar and the tab bar clears gesture nav; the composer must rise above the IME (`Modifier.imePadding()`). The sidebar (`ModalNavigationDrawer`) is edge-to-edge.
690
+ - **Font scaling**: `sp` honors user scale on message body, username, channel name, thread indicator. **Pin timestamps, reaction counts, tab labels, and section headers to fixed sizes** (layout-sensitive) via a fixed-`fontScale` `LocalDensity`. Code inline scales in the monospace family.
691
+ - **TalkBack**: merge a message row into one element — `Modifier.semantics(mergeDescendants = true)` with a combined label: "Sarah Chen, online, status on vacation, 10:42 AM. {body}. 3 reactions. 5 replies in thread." The reaction chips and thread indicator are nested actions.
692
+ - **Touch targets**: reaction chips are ~28.dp tall — give them a 44.dp effective hit via padding; send button is 32.dp visual / 44.dp hit; sidebar rows are 32.dp full-row tappable.
693
+ - **Contrast**: `#1D1C1D` on `#FFFFFF` passes WCAG AAA; `#CFC3CF` on `#4A154B` passes AA at 15sp. Mention pills have carefully-paired bg/fg. For a workspace-custom sidebar hex, run `sidebarTextColor()` (luminance split) so channel text never fails contrast.
694
+ - **RTL**: the sidebar drawer flips to the right edge automatically with `ModalNavigationDrawer` under an RTL `LayoutDirection`; the thread pane slide direction flips with it.
695
+ - **Dynamic color**: do **not** enable Material You `dynamicColorScheme()` for the content canvas — Slack's identity is the fixed white/charcoal canvas plus the aubergine sidebar. The sidebar's color IS the customization point, and it is workspace-data-driven (any admin hex), not wallpaper-driven — that is the intentional theming surface.