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.
- package/LICENSE +21 -0
- package/README.md +119 -0
- package/dist/__tests__/designStore.test.js +41 -0
- package/dist/__tests__/linter.test.js +23 -0
- package/dist/__tests__/sectionParser.test.js +60 -0
- package/dist/__tests__/server.test.js +129 -0
- package/dist/constants.js +12 -0
- package/dist/data/authoring-guide.md +113 -0
- package/dist/data/designs/airbnb.md +545 -0
- package/dist/data/designs/airtable.md +554 -0
- package/dist/data/designs/apple.md +562 -0
- package/dist/data/designs/binance.md +634 -0
- package/dist/data/designs/bmw-m.md +503 -0
- package/dist/data/designs/bmw.md +544 -0
- package/dist/data/designs/bugatti.md +454 -0
- package/dist/data/designs/cal.md +542 -0
- package/dist/data/designs/card-heavy.md +250 -0
- package/dist/data/designs/claude.md +589 -0
- package/dist/data/designs/clay.md +541 -0
- package/dist/data/designs/clickhouse.md +544 -0
- package/dist/data/designs/cohere.md +451 -0
- package/dist/data/designs/coinbase.md +570 -0
- package/dist/data/designs/composio.md +506 -0
- package/dist/data/designs/content-first.md +236 -0
- package/dist/data/designs/cursor.md +537 -0
- package/dist/data/designs/data-dashboard.md +300 -0
- package/dist/data/designs/dell-1996.md +632 -0
- package/dist/data/designs/elevenlabs.md +504 -0
- package/dist/data/designs/enterprise-neutral.md +252 -0
- package/dist/data/designs/expo.md +526 -0
- package/dist/data/designs/ferrari.md +531 -0
- package/dist/data/designs/figma.md +578 -0
- package/dist/data/designs/framer.md +544 -0
- package/dist/data/designs/hashicorp.md +575 -0
- package/dist/data/designs/hp.md +670 -0
- package/dist/data/designs/ibm.md +550 -0
- package/dist/data/designs/intercom.md +546 -0
- package/dist/data/designs/ios-acorns-android.md +430 -0
- package/dist/data/designs/ios-acorns-expo.md +381 -0
- package/dist/data/designs/ios-acorns-swiftui.md +378 -0
- package/dist/data/designs/ios-acorns.md +384 -0
- package/dist/data/designs/ios-airbnb-android.md +658 -0
- package/dist/data/designs/ios-airbnb-expo.md +457 -0
- package/dist/data/designs/ios-airbnb-swiftui.md +464 -0
- package/dist/data/designs/ios-airbnb.md +410 -0
- package/dist/data/designs/ios-alltrails-android.md +451 -0
- package/dist/data/designs/ios-alltrails-expo.md +400 -0
- package/dist/data/designs/ios-alltrails-swiftui.md +343 -0
- package/dist/data/designs/ios-alltrails.md +344 -0
- package/dist/data/designs/ios-amazon-android.md +686 -0
- package/dist/data/designs/ios-amazon-expo.md +433 -0
- package/dist/data/designs/ios-amazon-music-android.md +416 -0
- package/dist/data/designs/ios-amazon-music-expo.md +368 -0
- package/dist/data/designs/ios-amazon-music-swiftui.md +436 -0
- package/dist/data/designs/ios-amazon-music.md +389 -0
- package/dist/data/designs/ios-amazon-swiftui.md +460 -0
- package/dist/data/designs/ios-amazon.md +440 -0
- package/dist/data/designs/ios-apple-fitness-android.md +462 -0
- package/dist/data/designs/ios-apple-fitness-expo.md +373 -0
- package/dist/data/designs/ios-apple-fitness-swiftui.md +373 -0
- package/dist/data/designs/ios-apple-fitness.md +399 -0
- package/dist/data/designs/ios-apple-maps-android.md +646 -0
- package/dist/data/designs/ios-apple-maps-expo.md +557 -0
- package/dist/data/designs/ios-apple-maps-swiftui.md +588 -0
- package/dist/data/designs/ios-apple-maps.md +447 -0
- package/dist/data/designs/ios-apple-music-android.md +737 -0
- package/dist/data/designs/ios-apple-music-expo.md +596 -0
- package/dist/data/designs/ios-apple-music-swiftui.md +578 -0
- package/dist/data/designs/ios-apple-music.md +494 -0
- package/dist/data/designs/ios-apple-notes-android.md +675 -0
- package/dist/data/designs/ios-apple-notes-expo.md +468 -0
- package/dist/data/designs/ios-apple-notes-swiftui.md +489 -0
- package/dist/data/designs/ios-apple-notes.md +413 -0
- package/dist/data/designs/ios-apple-tv-android.md +405 -0
- package/dist/data/designs/ios-apple-tv-expo.md +341 -0
- package/dist/data/designs/ios-apple-tv-swiftui.md +348 -0
- package/dist/data/designs/ios-apple-tv.md +390 -0
- package/dist/data/designs/ios-apple-wallet-android.md +617 -0
- package/dist/data/designs/ios-apple-wallet-expo.md +487 -0
- package/dist/data/designs/ios-apple-wallet-swiftui.md +425 -0
- package/dist/data/designs/ios-apple-wallet.md +360 -0
- package/dist/data/designs/ios-asana-android.md +435 -0
- package/dist/data/designs/ios-asana-expo.md +411 -0
- package/dist/data/designs/ios-asana-swiftui.md +416 -0
- package/dist/data/designs/ios-asana.md +433 -0
- package/dist/data/designs/ios-audible-android.md +450 -0
- package/dist/data/designs/ios-audible-expo.md +328 -0
- package/dist/data/designs/ios-audible-swiftui.md +418 -0
- package/dist/data/designs/ios-audible.md +364 -0
- package/dist/data/designs/ios-bandcamp-android.md +471 -0
- package/dist/data/designs/ios-bandcamp-expo.md +378 -0
- package/dist/data/designs/ios-bandcamp-swiftui.md +374 -0
- package/dist/data/designs/ios-bandcamp.md +372 -0
- package/dist/data/designs/ios-bear-android.md +496 -0
- package/dist/data/designs/ios-bear-expo.md +449 -0
- package/dist/data/designs/ios-bear-swiftui.md +479 -0
- package/dist/data/designs/ios-bear.md +412 -0
- package/dist/data/designs/ios-bereal-android.md +392 -0
- package/dist/data/designs/ios-bereal-expo.md +299 -0
- package/dist/data/designs/ios-bereal-swiftui.md +319 -0
- package/dist/data/designs/ios-bereal.md +336 -0
- package/dist/data/designs/ios-binance-android.md +481 -0
- package/dist/data/designs/ios-binance-expo.md +404 -0
- package/dist/data/designs/ios-binance-swiftui.md +418 -0
- package/dist/data/designs/ios-binance.md +410 -0
- package/dist/data/designs/ios-bluesky-android.md +442 -0
- package/dist/data/designs/ios-bluesky-expo.md +362 -0
- package/dist/data/designs/ios-bluesky-swiftui.md +328 -0
- package/dist/data/designs/ios-bluesky.md +338 -0
- package/dist/data/designs/ios-booking-android.md +471 -0
- package/dist/data/designs/ios-booking-expo.md +364 -0
- package/dist/data/designs/ios-booking-swiftui.md +377 -0
- package/dist/data/designs/ios-booking.md +346 -0
- package/dist/data/designs/ios-bumble-android.md +756 -0
- package/dist/data/designs/ios-bumble-expo.md +629 -0
- package/dist/data/designs/ios-bumble-swiftui.md +546 -0
- package/dist/data/designs/ios-bumble.md +424 -0
- package/dist/data/designs/ios-cal-ai-android.md +664 -0
- package/dist/data/designs/ios-cal-ai-expo.md +415 -0
- package/dist/data/designs/ios-cal-ai-swiftui.md +486 -0
- package/dist/data/designs/ios-cal-ai.md +387 -0
- package/dist/data/designs/ios-calm-android.md +431 -0
- package/dist/data/designs/ios-calm-expo.md +384 -0
- package/dist/data/designs/ios-calm-swiftui.md +327 -0
- package/dist/data/designs/ios-calm.md +356 -0
- package/dist/data/designs/ios-canva-android.md +469 -0
- package/dist/data/designs/ios-canva-expo.md +374 -0
- package/dist/data/designs/ios-canva-swiftui.md +422 -0
- package/dist/data/designs/ios-canva.md +395 -0
- package/dist/data/designs/ios-cash-app-android.md +601 -0
- package/dist/data/designs/ios-cash-app-expo.md +453 -0
- package/dist/data/designs/ios-cash-app-swiftui.md +463 -0
- package/dist/data/designs/ios-cash-app.md +365 -0
- package/dist/data/designs/ios-character-ai-android.md +489 -0
- package/dist/data/designs/ios-character-ai-expo.md +420 -0
- package/dist/data/designs/ios-character-ai-swiftui.md +417 -0
- package/dist/data/designs/ios-character-ai.md +392 -0
- package/dist/data/designs/ios-charles-schwab-android.md +454 -0
- package/dist/data/designs/ios-charles-schwab-expo.md +388 -0
- package/dist/data/designs/ios-charles-schwab-swiftui.md +394 -0
- package/dist/data/designs/ios-charles-schwab.md +380 -0
- package/dist/data/designs/ios-chatgpt-android.md +753 -0
- package/dist/data/designs/ios-chatgpt-expo.md +644 -0
- package/dist/data/designs/ios-chatgpt-swiftui.md +653 -0
- package/dist/data/designs/ios-chatgpt.md +466 -0
- package/dist/data/designs/ios-chime-android.md +438 -0
- package/dist/data/designs/ios-chime-expo.md +419 -0
- package/dist/data/designs/ios-chime-swiftui.md +383 -0
- package/dist/data/designs/ios-chime.md +389 -0
- package/dist/data/designs/ios-chipotle-android.md +397 -0
- package/dist/data/designs/ios-chipotle-expo.md +301 -0
- package/dist/data/designs/ios-chipotle-swiftui.md +345 -0
- package/dist/data/designs/ios-chipotle.md +340 -0
- package/dist/data/designs/ios-citymapper-android.md +466 -0
- package/dist/data/designs/ios-citymapper-expo.md +420 -0
- package/dist/data/designs/ios-citymapper-swiftui.md +424 -0
- package/dist/data/designs/ios-citymapper.md +394 -0
- package/dist/data/designs/ios-claude-android.md +625 -0
- package/dist/data/designs/ios-claude-expo.md +671 -0
- package/dist/data/designs/ios-claude-swiftui.md +649 -0
- package/dist/data/designs/ios-claude.md +447 -0
- package/dist/data/designs/ios-clickup-android.md +484 -0
- package/dist/data/designs/ios-clickup-expo.md +423 -0
- package/dist/data/designs/ios-clickup-swiftui.md +416 -0
- package/dist/data/designs/ios-clickup.md +431 -0
- package/dist/data/designs/ios-clubhouse-android.md +524 -0
- package/dist/data/designs/ios-clubhouse-expo.md +425 -0
- package/dist/data/designs/ios-clubhouse-swiftui.md +447 -0
- package/dist/data/designs/ios-clubhouse.md +406 -0
- package/dist/data/designs/ios-coffee-meets-bagel-android.md +461 -0
- package/dist/data/designs/ios-coffee-meets-bagel-expo.md +372 -0
- package/dist/data/designs/ios-coffee-meets-bagel-swiftui.md +368 -0
- package/dist/data/designs/ios-coffee-meets-bagel.md +376 -0
- package/dist/data/designs/ios-coinbase-android.md +611 -0
- package/dist/data/designs/ios-coinbase-expo.md +500 -0
- package/dist/data/designs/ios-coinbase-swiftui.md +490 -0
- package/dist/data/designs/ios-coinbase.md +409 -0
- package/dist/data/designs/ios-copilot-android.md +625 -0
- package/dist/data/designs/ios-copilot-expo.md +423 -0
- package/dist/data/designs/ios-copilot-swiftui.md +471 -0
- package/dist/data/designs/ios-copilot.md +367 -0
- package/dist/data/designs/ios-craft-android.md +459 -0
- package/dist/data/designs/ios-craft-expo.md +417 -0
- package/dist/data/designs/ios-craft-swiftui.md +449 -0
- package/dist/data/designs/ios-craft.md +449 -0
- package/dist/data/designs/ios-crunchyroll-android.md +432 -0
- package/dist/data/designs/ios-crunchyroll-expo.md +388 -0
- package/dist/data/designs/ios-crunchyroll-swiftui.md +417 -0
- package/dist/data/designs/ios-crunchyroll.md +388 -0
- package/dist/data/designs/ios-crypto-com-android.md +461 -0
- package/dist/data/designs/ios-crypto-com-expo.md +404 -0
- package/dist/data/designs/ios-crypto-com-swiftui.md +419 -0
- package/dist/data/designs/ios-crypto-com.md +410 -0
- package/dist/data/designs/ios-deepseek-android.md +471 -0
- package/dist/data/designs/ios-deepseek-expo.md +391 -0
- package/dist/data/designs/ios-deepseek-swiftui.md +354 -0
- package/dist/data/designs/ios-deepseek.md +393 -0
- package/dist/data/designs/ios-deezer-android.md +475 -0
- package/dist/data/designs/ios-deezer-expo.md +400 -0
- package/dist/data/designs/ios-deezer-swiftui.md +430 -0
- package/dist/data/designs/ios-deezer.md +388 -0
- package/dist/data/designs/ios-deliveroo-android.md +493 -0
- package/dist/data/designs/ios-deliveroo-expo.md +424 -0
- package/dist/data/designs/ios-deliveroo-swiftui.md +398 -0
- package/dist/data/designs/ios-deliveroo.md +420 -0
- package/dist/data/designs/ios-delta-android.md +439 -0
- package/dist/data/designs/ios-delta-expo.md +381 -0
- package/dist/data/designs/ios-delta-swiftui.md +400 -0
- package/dist/data/designs/ios-delta.md +397 -0
- package/dist/data/designs/ios-discord-android.md +611 -0
- package/dist/data/designs/ios-discord-expo.md +618 -0
- package/dist/data/designs/ios-discord-swiftui.md +630 -0
- package/dist/data/designs/ios-discord.md +451 -0
- package/dist/data/designs/ios-disney-plus-android.md +464 -0
- package/dist/data/designs/ios-disney-plus-expo.md +358 -0
- package/dist/data/designs/ios-disney-plus-swiftui.md +412 -0
- package/dist/data/designs/ios-disney-plus.md +355 -0
- package/dist/data/designs/ios-dominos-android.md +417 -0
- package/dist/data/designs/ios-dominos-expo.md +316 -0
- package/dist/data/designs/ios-dominos-swiftui.md +340 -0
- package/dist/data/designs/ios-dominos.md +347 -0
- package/dist/data/designs/ios-doordash-android.md +527 -0
- package/dist/data/designs/ios-doordash-expo.md +323 -0
- package/dist/data/designs/ios-doordash-swiftui.md +301 -0
- package/dist/data/designs/ios-doordash.md +393 -0
- package/dist/data/designs/ios-dropbox-android.md +522 -0
- package/dist/data/designs/ios-dropbox-expo.md +393 -0
- package/dist/data/designs/ios-dropbox-swiftui.md +400 -0
- package/dist/data/designs/ios-dropbox.md +374 -0
- package/dist/data/designs/ios-duolingo-android.md +641 -0
- package/dist/data/designs/ios-duolingo-expo.md +597 -0
- package/dist/data/designs/ios-duolingo-swiftui.md +539 -0
- package/dist/data/designs/ios-duolingo.md +409 -0
- package/dist/data/designs/ios-ebay-android.md +436 -0
- package/dist/data/designs/ios-ebay-expo.md +344 -0
- package/dist/data/designs/ios-ebay-swiftui.md +308 -0
- package/dist/data/designs/ios-ebay.md +355 -0
- package/dist/data/designs/ios-espn-android.md +468 -0
- package/dist/data/designs/ios-espn-expo.md +387 -0
- package/dist/data/designs/ios-espn-swiftui.md +410 -0
- package/dist/data/designs/ios-espn.md +384 -0
- package/dist/data/designs/ios-etsy-android.md +439 -0
- package/dist/data/designs/ios-etsy-expo.md +351 -0
- package/dist/data/designs/ios-etsy-swiftui.md +296 -0
- package/dist/data/designs/ios-etsy.md +355 -0
- package/dist/data/designs/ios-evernote-android.md +419 -0
- package/dist/data/designs/ios-evernote-expo.md +379 -0
- package/dist/data/designs/ios-evernote-swiftui.md +380 -0
- package/dist/data/designs/ios-evernote.md +416 -0
- package/dist/data/designs/ios-expedia-android.md +451 -0
- package/dist/data/designs/ios-expedia-expo.md +433 -0
- package/dist/data/designs/ios-expedia-swiftui.md +399 -0
- package/dist/data/designs/ios-expedia.md +431 -0
- package/dist/data/designs/ios-facebook-android.md +628 -0
- package/dist/data/designs/ios-facebook-expo.md +471 -0
- package/dist/data/designs/ios-facebook-swiftui.md +459 -0
- package/dist/data/designs/ios-facebook.md +452 -0
- package/dist/data/designs/ios-feeld-android.md +431 -0
- package/dist/data/designs/ios-feeld-expo.md +379 -0
- package/dist/data/designs/ios-feeld-swiftui.md +401 -0
- package/dist/data/designs/ios-feeld.md +378 -0
- package/dist/data/designs/ios-fidelity-android.md +426 -0
- package/dist/data/designs/ios-fidelity-expo.md +396 -0
- package/dist/data/designs/ios-fidelity-swiftui.md +398 -0
- package/dist/data/designs/ios-fidelity.md +387 -0
- package/dist/data/designs/ios-figma-android.md +578 -0
- package/dist/data/designs/ios-figma-expo.md +504 -0
- package/dist/data/designs/ios-figma-swiftui.md +542 -0
- package/dist/data/designs/ios-figma.md +404 -0
- package/dist/data/designs/ios-fitbit-android.md +439 -0
- package/dist/data/designs/ios-fitbit-expo.md +389 -0
- package/dist/data/designs/ios-fitbit-swiftui.md +380 -0
- package/dist/data/designs/ios-fitbit.md +396 -0
- package/dist/data/designs/ios-flickr-android.md +506 -0
- package/dist/data/designs/ios-flickr-expo.md +434 -0
- package/dist/data/designs/ios-flickr-swiftui.md +421 -0
- package/dist/data/designs/ios-flickr.md +394 -0
- package/dist/data/designs/ios-flighty-android.md +418 -0
- package/dist/data/designs/ios-flighty-expo.md +353 -0
- package/dist/data/designs/ios-flighty-swiftui.md +337 -0
- package/dist/data/designs/ios-flighty.md +357 -0
- package/dist/data/designs/ios-flo-android.md +447 -0
- package/dist/data/designs/ios-flo-expo.md +363 -0
- package/dist/data/designs/ios-flo-swiftui.md +355 -0
- package/dist/data/designs/ios-flo.md +351 -0
- package/dist/data/designs/ios-garmin-connect-android.md +531 -0
- package/dist/data/designs/ios-garmin-connect-expo.md +429 -0
- package/dist/data/designs/ios-garmin-connect-swiftui.md +459 -0
- package/dist/data/designs/ios-garmin-connect.md +419 -0
- package/dist/data/designs/ios-gas-android.md +438 -0
- package/dist/data/designs/ios-gas-expo.md +350 -0
- package/dist/data/designs/ios-gas-swiftui.md +329 -0
- package/dist/data/designs/ios-gas.md +387 -0
- package/dist/data/designs/ios-gemini-android.md +568 -0
- package/dist/data/designs/ios-gemini-expo.md +416 -0
- package/dist/data/designs/ios-gemini-swiftui.md +424 -0
- package/dist/data/designs/ios-gemini.md +351 -0
- package/dist/data/designs/ios-github-android.md +507 -0
- package/dist/data/designs/ios-github-expo.md +486 -0
- package/dist/data/designs/ios-github-swiftui.md +459 -0
- package/dist/data/designs/ios-github.md +394 -0
- package/dist/data/designs/ios-gmail-android.md +548 -0
- package/dist/data/designs/ios-gmail-expo.md +457 -0
- package/dist/data/designs/ios-gmail-swiftui.md +470 -0
- package/dist/data/designs/ios-gmail.md +441 -0
- package/dist/data/designs/ios-goodreads-android.md +436 -0
- package/dist/data/designs/ios-goodreads-expo.md +407 -0
- package/dist/data/designs/ios-goodreads-swiftui.md +378 -0
- package/dist/data/designs/ios-goodreads.md +385 -0
- package/dist/data/designs/ios-google-calendar-android.md +565 -0
- package/dist/data/designs/ios-google-calendar-expo.md +616 -0
- package/dist/data/designs/ios-google-calendar-swiftui.md +585 -0
- package/dist/data/designs/ios-google-calendar.md +431 -0
- package/dist/data/designs/ios-google-maps-android.md +614 -0
- package/dist/data/designs/ios-google-maps-expo.md +515 -0
- package/dist/data/designs/ios-google-maps-swiftui.md +484 -0
- package/dist/data/designs/ios-google-maps.md +451 -0
- package/dist/data/designs/ios-grammarly-android.md +449 -0
- package/dist/data/designs/ios-grammarly-expo.md +383 -0
- package/dist/data/designs/ios-grammarly-swiftui.md +381 -0
- package/dist/data/designs/ios-grammarly.md +392 -0
- package/dist/data/designs/ios-grindr-android.md +494 -0
- package/dist/data/designs/ios-grindr-expo.md +358 -0
- package/dist/data/designs/ios-grindr-swiftui.md +357 -0
- package/dist/data/designs/ios-grindr.md +356 -0
- package/dist/data/designs/ios-grok-android.md +471 -0
- package/dist/data/designs/ios-grok-expo.md +388 -0
- package/dist/data/designs/ios-grok-swiftui.md +397 -0
- package/dist/data/designs/ios-grok.md +357 -0
- package/dist/data/designs/ios-groupme-android.md +551 -0
- package/dist/data/designs/ios-groupme-expo.md +442 -0
- package/dist/data/designs/ios-groupme-swiftui.md +439 -0
- package/dist/data/designs/ios-groupme.md +424 -0
- package/dist/data/designs/ios-grubhub-android.md +506 -0
- package/dist/data/designs/ios-grubhub-expo.md +428 -0
- package/dist/data/designs/ios-grubhub-swiftui.md +408 -0
- package/dist/data/designs/ios-grubhub.md +427 -0
- package/dist/data/designs/ios-happn-android.md +464 -0
- package/dist/data/designs/ios-happn-expo.md +411 -0
- package/dist/data/designs/ios-happn-swiftui.md +401 -0
- package/dist/data/designs/ios-happn.md +400 -0
- package/dist/data/designs/ios-headspace-android.md +688 -0
- package/dist/data/designs/ios-headspace-expo.md +574 -0
- package/dist/data/designs/ios-headspace-swiftui.md +498 -0
- package/dist/data/designs/ios-headspace.md +430 -0
- package/dist/data/designs/ios-hevy-android.md +473 -0
- package/dist/data/designs/ios-hevy-expo.md +405 -0
- package/dist/data/designs/ios-hevy-swiftui.md +367 -0
- package/dist/data/designs/ios-hevy.md +410 -0
- package/dist/data/designs/ios-hinge-android.md +743 -0
- package/dist/data/designs/ios-hinge-expo.md +580 -0
- package/dist/data/designs/ios-hinge-swiftui.md +512 -0
- package/dist/data/designs/ios-hinge.md +405 -0
- package/dist/data/designs/ios-hopper-android.md +440 -0
- package/dist/data/designs/ios-hopper-expo.md +353 -0
- package/dist/data/designs/ios-hopper-swiftui.md +340 -0
- package/dist/data/designs/ios-hopper.md +354 -0
- package/dist/data/designs/ios-hulu-android.md +435 -0
- package/dist/data/designs/ios-hulu-expo.md +331 -0
- package/dist/data/designs/ios-hulu-swiftui.md +374 -0
- package/dist/data/designs/ios-hulu.md +353 -0
- package/dist/data/designs/ios-iheartradio-android.md +481 -0
- package/dist/data/designs/ios-iheartradio-expo.md +417 -0
- package/dist/data/designs/ios-iheartradio-swiftui.md +423 -0
- package/dist/data/designs/ios-iheartradio.md +381 -0
- package/dist/data/designs/ios-imessage-android.md +426 -0
- package/dist/data/designs/ios-imessage-expo.md +384 -0
- package/dist/data/designs/ios-imessage-swiftui.md +378 -0
- package/dist/data/designs/ios-imessage.md +394 -0
- package/dist/data/designs/ios-instacart-android.md +471 -0
- package/dist/data/designs/ios-instacart-expo.md +349 -0
- package/dist/data/designs/ios-instacart-swiftui.md +378 -0
- package/dist/data/designs/ios-instacart.md +360 -0
- package/dist/data/designs/ios-instagram-android.md +646 -0
- package/dist/data/designs/ios-instagram-expo.md +310 -0
- package/dist/data/designs/ios-instagram-swiftui.md +333 -0
- package/dist/data/designs/ios-instagram.md +376 -0
- package/dist/data/designs/ios-jira-android.md +432 -0
- package/dist/data/designs/ios-jira-expo.md +375 -0
- package/dist/data/designs/ios-jira-swiftui.md +433 -0
- package/dist/data/designs/ios-jira.md +424 -0
- package/dist/data/designs/ios-kakaotalk-android.md +491 -0
- package/dist/data/designs/ios-kakaotalk-expo.md +418 -0
- package/dist/data/designs/ios-kakaotalk-swiftui.md +406 -0
- package/dist/data/designs/ios-kakaotalk.md +414 -0
- package/dist/data/designs/ios-kayak-android.md +466 -0
- package/dist/data/designs/ios-kayak-expo.md +407 -0
- package/dist/data/designs/ios-kayak-swiftui.md +426 -0
- package/dist/data/designs/ios-kayak.md +392 -0
- package/dist/data/designs/ios-kick-android.md +487 -0
- package/dist/data/designs/ios-kick-expo.md +434 -0
- package/dist/data/designs/ios-kick-swiftui.md +429 -0
- package/dist/data/designs/ios-kick.md +389 -0
- package/dist/data/designs/ios-kik-android.md +433 -0
- package/dist/data/designs/ios-kik-expo.md +363 -0
- package/dist/data/designs/ios-kik-swiftui.md +363 -0
- package/dist/data/designs/ios-kik.md +392 -0
- package/dist/data/designs/ios-kindle-android.md +439 -0
- package/dist/data/designs/ios-kindle-expo.md +356 -0
- package/dist/data/designs/ios-kindle-swiftui.md +372 -0
- package/dist/data/designs/ios-kindle.md +369 -0
- package/dist/data/designs/ios-klarna-android.md +420 -0
- package/dist/data/designs/ios-klarna-expo.md +349 -0
- package/dist/data/designs/ios-klarna-swiftui.md +360 -0
- package/dist/data/designs/ios-klarna.md +356 -0
- package/dist/data/designs/ios-lemon8-android.md +492 -0
- package/dist/data/designs/ios-lemon8-expo.md +413 -0
- package/dist/data/designs/ios-lemon8-swiftui.md +428 -0
- package/dist/data/designs/ios-lemon8.md +378 -0
- package/dist/data/designs/ios-life360-android.md +474 -0
- package/dist/data/designs/ios-life360-expo.md +375 -0
- package/dist/data/designs/ios-life360-swiftui.md +390 -0
- package/dist/data/designs/ios-life360.md +402 -0
- package/dist/data/designs/ios-line-android.md +517 -0
- package/dist/data/designs/ios-line-expo.md +402 -0
- package/dist/data/designs/ios-line-swiftui.md +361 -0
- package/dist/data/designs/ios-line.md +362 -0
- package/dist/data/designs/ios-linear-android.md +457 -0
- package/dist/data/designs/ios-linear-expo.md +367 -0
- package/dist/data/designs/ios-linear-swiftui.md +401 -0
- package/dist/data/designs/ios-linear.md +368 -0
- package/dist/data/designs/ios-linkedin-android.md +620 -0
- package/dist/data/designs/ios-linkedin-expo.md +469 -0
- package/dist/data/designs/ios-linkedin-swiftui.md +472 -0
- package/dist/data/designs/ios-linkedin.md +444 -0
- package/dist/data/designs/ios-locket-android.md +500 -0
- package/dist/data/designs/ios-locket-expo.md +375 -0
- package/dist/data/designs/ios-locket-swiftui.md +375 -0
- package/dist/data/designs/ios-locket.md +381 -0
- package/dist/data/designs/ios-lyft-android.md +406 -0
- package/dist/data/designs/ios-lyft-expo.md +333 -0
- package/dist/data/designs/ios-lyft-swiftui.md +315 -0
- package/dist/data/designs/ios-lyft.md +337 -0
- package/dist/data/designs/ios-marriott-bonvoy-android.md +488 -0
- package/dist/data/designs/ios-marriott-bonvoy-expo.md +412 -0
- package/dist/data/designs/ios-marriott-bonvoy-swiftui.md +461 -0
- package/dist/data/designs/ios-marriott-bonvoy.md +379 -0
- package/dist/data/designs/ios-mastodon-android.md +476 -0
- package/dist/data/designs/ios-mastodon-expo.md +379 -0
- package/dist/data/designs/ios-mastodon-swiftui.md +349 -0
- package/dist/data/designs/ios-mastodon.md +337 -0
- package/dist/data/designs/ios-match-android.md +496 -0
- package/dist/data/designs/ios-match-expo.md +393 -0
- package/dist/data/designs/ios-match-swiftui.md +450 -0
- package/dist/data/designs/ios-match.md +382 -0
- package/dist/data/designs/ios-max-android.md +454 -0
- package/dist/data/designs/ios-max-expo.md +342 -0
- package/dist/data/designs/ios-max-swiftui.md +332 -0
- package/dist/data/designs/ios-max.md +352 -0
- package/dist/data/designs/ios-mcdonalds-android.md +497 -0
- package/dist/data/designs/ios-mcdonalds-expo.md +382 -0
- package/dist/data/designs/ios-mcdonalds-swiftui.md +394 -0
- package/dist/data/designs/ios-mcdonalds.md +410 -0
- package/dist/data/designs/ios-messenger-android.md +523 -0
- package/dist/data/designs/ios-messenger-expo.md +379 -0
- package/dist/data/designs/ios-messenger-swiftui.md +369 -0
- package/dist/data/designs/ios-messenger.md +361 -0
- package/dist/data/designs/ios-microsoft-teams-android.md +446 -0
- package/dist/data/designs/ios-microsoft-teams-expo.md +362 -0
- package/dist/data/designs/ios-microsoft-teams-swiftui.md +384 -0
- package/dist/data/designs/ios-microsoft-teams.md +359 -0
- package/dist/data/designs/ios-midjourney-android.md +503 -0
- package/dist/data/designs/ios-midjourney-expo.md +406 -0
- package/dist/data/designs/ios-midjourney-swiftui.md +376 -0
- package/dist/data/designs/ios-midjourney.md +407 -0
- package/dist/data/designs/ios-miro-android.md +475 -0
- package/dist/data/designs/ios-miro-expo.md +421 -0
- package/dist/data/designs/ios-miro-swiftui.md +407 -0
- package/dist/data/designs/ios-miro.md +424 -0
- package/dist/data/designs/ios-monday-android.md +426 -0
- package/dist/data/designs/ios-monday-expo.md +382 -0
- package/dist/data/designs/ios-monday-swiftui.md +386 -0
- package/dist/data/designs/ios-monday.md +415 -0
- package/dist/data/designs/ios-monzo-android.md +423 -0
- package/dist/data/designs/ios-monzo-expo.md +391 -0
- package/dist/data/designs/ios-monzo-swiftui.md +371 -0
- package/dist/data/designs/ios-monzo.md +382 -0
- package/dist/data/designs/ios-myfitnesspal-android.md +631 -0
- package/dist/data/designs/ios-myfitnesspal-expo.md +489 -0
- package/dist/data/designs/ios-myfitnesspal-swiftui.md +500 -0
- package/dist/data/designs/ios-myfitnesspal.md +408 -0
- package/dist/data/designs/ios-netflix-android.md +570 -0
- package/dist/data/designs/ios-netflix-expo.md +528 -0
- package/dist/data/designs/ios-netflix-swiftui.md +543 -0
- package/dist/data/designs/ios-netflix.md +476 -0
- package/dist/data/designs/ios-nextdoor-android.md +399 -0
- package/dist/data/designs/ios-nextdoor-expo.md +317 -0
- package/dist/data/designs/ios-nextdoor-swiftui.md +343 -0
- package/dist/data/designs/ios-nextdoor.md +332 -0
- package/dist/data/designs/ios-nike-run-club-android.md +598 -0
- package/dist/data/designs/ios-nike-run-club-expo.md +459 -0
- package/dist/data/designs/ios-nike-run-club-swiftui.md +474 -0
- package/dist/data/designs/ios-nike-run-club.md +400 -0
- package/dist/data/designs/ios-noom-android.md +455 -0
- package/dist/data/designs/ios-noom-expo.md +362 -0
- package/dist/data/designs/ios-noom-swiftui.md +369 -0
- package/dist/data/designs/ios-noom.md +404 -0
- package/dist/data/designs/ios-notion-android.md +575 -0
- package/dist/data/designs/ios-notion-expo.md +543 -0
- package/dist/data/designs/ios-notion-swiftui.md +562 -0
- package/dist/data/designs/ios-notion.md +506 -0
- package/dist/data/designs/ios-nubank-android.md +447 -0
- package/dist/data/designs/ios-nubank-expo.md +391 -0
- package/dist/data/designs/ios-nubank-swiftui.md +391 -0
- package/dist/data/designs/ios-nubank.md +388 -0
- package/dist/data/designs/ios-obsidian-android.md +456 -0
- package/dist/data/designs/ios-obsidian-expo.md +401 -0
- package/dist/data/designs/ios-obsidian-swiftui.md +412 -0
- package/dist/data/designs/ios-obsidian.md +363 -0
- package/dist/data/designs/ios-okcupid-android.md +496 -0
- package/dist/data/designs/ios-okcupid-expo.md +378 -0
- package/dist/data/designs/ios-okcupid-swiftui.md +343 -0
- package/dist/data/designs/ios-okcupid.md +364 -0
- package/dist/data/designs/ios-opentable-android.md +426 -0
- package/dist/data/designs/ios-opentable-expo.md +350 -0
- package/dist/data/designs/ios-opentable-swiftui.md +328 -0
- package/dist/data/designs/ios-opentable.md +411 -0
- package/dist/data/designs/ios-oura-android.md +426 -0
- package/dist/data/designs/ios-oura-expo.md +353 -0
- package/dist/data/designs/ios-oura-swiftui.md +327 -0
- package/dist/data/designs/ios-oura.md +356 -0
- package/dist/data/designs/ios-overcast-android.md +508 -0
- package/dist/data/designs/ios-overcast-expo.md +420 -0
- package/dist/data/designs/ios-overcast-swiftui.md +427 -0
- package/dist/data/designs/ios-overcast.md +414 -0
- package/dist/data/designs/ios-pandora-android.md +477 -0
- package/dist/data/designs/ios-pandora-expo.md +406 -0
- package/dist/data/designs/ios-pandora-swiftui.md +413 -0
- package/dist/data/designs/ios-pandora.md +366 -0
- package/dist/data/designs/ios-panera-android.md +414 -0
- package/dist/data/designs/ios-panera-expo.md +352 -0
- package/dist/data/designs/ios-panera-swiftui.md +369 -0
- package/dist/data/designs/ios-panera.md +412 -0
- package/dist/data/designs/ios-paramount-plus-android.md +415 -0
- package/dist/data/designs/ios-paramount-plus-expo.md +363 -0
- package/dist/data/designs/ios-paramount-plus-swiftui.md +372 -0
- package/dist/data/designs/ios-paramount-plus.md +400 -0
- package/dist/data/designs/ios-paypal-android.md +535 -0
- package/dist/data/designs/ios-paypal-expo.md +429 -0
- package/dist/data/designs/ios-paypal-swiftui.md +466 -0
- package/dist/data/designs/ios-paypal.md +393 -0
- package/dist/data/designs/ios-peacock-android.md +453 -0
- package/dist/data/designs/ios-peacock-expo.md +393 -0
- package/dist/data/designs/ios-peacock-swiftui.md +420 -0
- package/dist/data/designs/ios-peacock.md +411 -0
- package/dist/data/designs/ios-peloton-android.md +470 -0
- package/dist/data/designs/ios-peloton-expo.md +401 -0
- package/dist/data/designs/ios-peloton-swiftui.md +409 -0
- package/dist/data/designs/ios-peloton.md +415 -0
- package/dist/data/designs/ios-perplexity-android.md +553 -0
- package/dist/data/designs/ios-perplexity-expo.md +703 -0
- package/dist/data/designs/ios-perplexity-swiftui.md +602 -0
- package/dist/data/designs/ios-perplexity.md +453 -0
- package/dist/data/designs/ios-pinterest-android.md +551 -0
- package/dist/data/designs/ios-pinterest-expo.md +466 -0
- package/dist/data/designs/ios-pinterest-swiftui.md +464 -0
- package/dist/data/designs/ios-pinterest.md +427 -0
- package/dist/data/designs/ios-plenty-of-fish-android.md +462 -0
- package/dist/data/designs/ios-plenty-of-fish-expo.md +380 -0
- package/dist/data/designs/ios-plenty-of-fish-swiftui.md +429 -0
- package/dist/data/designs/ios-plenty-of-fish.md +387 -0
- package/dist/data/designs/ios-plex-android.md +403 -0
- package/dist/data/designs/ios-plex-expo.md +333 -0
- package/dist/data/designs/ios-plex-swiftui.md +349 -0
- package/dist/data/designs/ios-plex.md +379 -0
- package/dist/data/designs/ios-pluto-tv-android.md +413 -0
- package/dist/data/designs/ios-pluto-tv-expo.md +379 -0
- package/dist/data/designs/ios-pluto-tv-swiftui.md +411 -0
- package/dist/data/designs/ios-pluto-tv.md +362 -0
- package/dist/data/designs/ios-pocket-casts-android.md +492 -0
- package/dist/data/designs/ios-pocket-casts-expo.md +430 -0
- package/dist/data/designs/ios-pocket-casts-swiftui.md +479 -0
- package/dist/data/designs/ios-pocket-casts.md +427 -0
- package/dist/data/designs/ios-postman-android.md +472 -0
- package/dist/data/designs/ios-postman-expo.md +372 -0
- package/dist/data/designs/ios-postman-swiftui.md +377 -0
- package/dist/data/designs/ios-postman.md +405 -0
- package/dist/data/designs/ios-prime-video-android.md +447 -0
- package/dist/data/designs/ios-prime-video-expo.md +365 -0
- package/dist/data/designs/ios-prime-video-swiftui.md +333 -0
- package/dist/data/designs/ios-prime-video.md +351 -0
- package/dist/data/designs/ios-quora-android.md +513 -0
- package/dist/data/designs/ios-quora-expo.md +362 -0
- package/dist/data/designs/ios-quora-swiftui.md +375 -0
- package/dist/data/designs/ios-quora.md +359 -0
- package/dist/data/designs/ios-raya-android.md +401 -0
- package/dist/data/designs/ios-raya-expo.md +366 -0
- package/dist/data/designs/ios-raya-swiftui.md +393 -0
- package/dist/data/designs/ios-raya.md +366 -0
- package/dist/data/designs/ios-reddit-android.md +605 -0
- package/dist/data/designs/ios-reddit-expo.md +553 -0
- package/dist/data/designs/ios-reddit-swiftui.md +514 -0
- package/dist/data/designs/ios-reddit.md +460 -0
- package/dist/data/designs/ios-resy-android.md +430 -0
- package/dist/data/designs/ios-resy-expo.md +344 -0
- package/dist/data/designs/ios-resy-swiftui.md +330 -0
- package/dist/data/designs/ios-resy.md +412 -0
- package/dist/data/designs/ios-revolut-android.md +433 -0
- package/dist/data/designs/ios-revolut-expo.md +379 -0
- package/dist/data/designs/ios-revolut-swiftui.md +372 -0
- package/dist/data/designs/ios-revolut.md +353 -0
- package/dist/data/designs/ios-robinhood-android.md +587 -0
- package/dist/data/designs/ios-robinhood-expo.md +416 -0
- package/dist/data/designs/ios-robinhood-swiftui.md +431 -0
- package/dist/data/designs/ios-robinhood.md +380 -0
- package/dist/data/designs/ios-runna-android.md +485 -0
- package/dist/data/designs/ios-runna-expo.md +388 -0
- package/dist/data/designs/ios-runna-swiftui.md +413 -0
- package/dist/data/designs/ios-runna.md +390 -0
- package/dist/data/designs/ios-shazam-android.md +436 -0
- package/dist/data/designs/ios-shazam-expo.md +348 -0
- package/dist/data/designs/ios-shazam-swiftui.md +394 -0
- package/dist/data/designs/ios-shazam.md +338 -0
- package/dist/data/designs/ios-signal-android.md +462 -0
- package/dist/data/designs/ios-signal-expo.md +361 -0
- package/dist/data/designs/ios-signal-swiftui.md +350 -0
- package/dist/data/designs/ios-signal.md +357 -0
- package/dist/data/designs/ios-skype-android.md +398 -0
- package/dist/data/designs/ios-skype-expo.md +368 -0
- package/dist/data/designs/ios-skype-swiftui.md +369 -0
- package/dist/data/designs/ios-skype.md +406 -0
- package/dist/data/designs/ios-skyscanner-android.md +451 -0
- package/dist/data/designs/ios-skyscanner-expo.md +423 -0
- package/dist/data/designs/ios-skyscanner-swiftui.md +419 -0
- package/dist/data/designs/ios-skyscanner.md +421 -0
- package/dist/data/designs/ios-slack-android.md +695 -0
- package/dist/data/designs/ios-slack-expo.md +601 -0
- package/dist/data/designs/ios-slack-swiftui.md +594 -0
- package/dist/data/designs/ios-slack.md +474 -0
- package/dist/data/designs/ios-sleep-cycle-android.md +436 -0
- package/dist/data/designs/ios-sleep-cycle-expo.md +380 -0
- package/dist/data/designs/ios-sleep-cycle-swiftui.md +409 -0
- package/dist/data/designs/ios-sleep-cycle.md +386 -0
- package/dist/data/designs/ios-snapchat-android.md +671 -0
- package/dist/data/designs/ios-snapchat-expo.md +528 -0
- package/dist/data/designs/ios-snapchat-swiftui.md +557 -0
- package/dist/data/designs/ios-snapchat.md +478 -0
- package/dist/data/designs/ios-sofi-android.md +446 -0
- package/dist/data/designs/ios-sofi-expo.md +387 -0
- package/dist/data/designs/ios-sofi-swiftui.md +379 -0
- package/dist/data/designs/ios-sofi.md +385 -0
- package/dist/data/designs/ios-soundcloud-android.md +488 -0
- package/dist/data/designs/ios-soundcloud-expo.md +364 -0
- package/dist/data/designs/ios-soundcloud-swiftui.md +399 -0
- package/dist/data/designs/ios-soundcloud.md +359 -0
- package/dist/data/designs/ios-southwest-android.md +446 -0
- package/dist/data/designs/ios-southwest-expo.md +389 -0
- package/dist/data/designs/ios-southwest-swiftui.md +405 -0
- package/dist/data/designs/ios-southwest.md +405 -0
- package/dist/data/designs/ios-spotify-android.md +427 -0
- package/dist/data/designs/ios-spotify-expo.md +321 -0
- package/dist/data/designs/ios-spotify-swiftui.md +312 -0
- package/dist/data/designs/ios-spotify.md +366 -0
- package/dist/data/designs/ios-starbucks-android.md +622 -0
- package/dist/data/designs/ios-starbucks-expo.md +497 -0
- package/dist/data/designs/ios-starbucks-swiftui.md +500 -0
- package/dist/data/designs/ios-starbucks.md +440 -0
- package/dist/data/designs/ios-strava-android.md +656 -0
- package/dist/data/designs/ios-strava-expo.md +501 -0
- package/dist/data/designs/ios-strava-swiftui.md +465 -0
- package/dist/data/designs/ios-strava.md +433 -0
- package/dist/data/designs/ios-strong-android.md +479 -0
- package/dist/data/designs/ios-strong-expo.md +396 -0
- package/dist/data/designs/ios-strong-swiftui.md +363 -0
- package/dist/data/designs/ios-strong.md +415 -0
- package/dist/data/designs/ios-substack-android.md +440 -0
- package/dist/data/designs/ios-substack-expo.md +395 -0
- package/dist/data/designs/ios-substack-swiftui.md +371 -0
- package/dist/data/designs/ios-substack.md +372 -0
- package/dist/data/designs/ios-swiggy-android.md +549 -0
- package/dist/data/designs/ios-swiggy-expo.md +443 -0
- package/dist/data/designs/ios-swiggy-swiftui.md +471 -0
- package/dist/data/designs/ios-swiggy.md +432 -0
- package/dist/data/designs/ios-taco-bell-android.md +529 -0
- package/dist/data/designs/ios-taco-bell-expo.md +407 -0
- package/dist/data/designs/ios-taco-bell-swiftui.md +419 -0
- package/dist/data/designs/ios-taco-bell.md +430 -0
- package/dist/data/designs/ios-telegram-android.md +676 -0
- package/dist/data/designs/ios-telegram-expo.md +594 -0
- package/dist/data/designs/ios-telegram-swiftui.md +518 -0
- package/dist/data/designs/ios-telegram.md +458 -0
- package/dist/data/designs/ios-the-league-android.md +454 -0
- package/dist/data/designs/ios-the-league-expo.md +391 -0
- package/dist/data/designs/ios-the-league-swiftui.md +409 -0
- package/dist/data/designs/ios-the-league.md +368 -0
- package/dist/data/designs/ios-things-3-android.md +421 -0
- package/dist/data/designs/ios-things-3-expo.md +351 -0
- package/dist/data/designs/ios-things-3-swiftui.md +359 -0
- package/dist/data/designs/ios-things-3.md +339 -0
- package/dist/data/designs/ios-threads-android.md +588 -0
- package/dist/data/designs/ios-threads-expo.md +468 -0
- package/dist/data/designs/ios-threads-swiftui.md +452 -0
- package/dist/data/designs/ios-threads.md +424 -0
- package/dist/data/designs/ios-threema-android.md +496 -0
- package/dist/data/designs/ios-threema-expo.md +415 -0
- package/dist/data/designs/ios-threema-swiftui.md +446 -0
- package/dist/data/designs/ios-threema.md +397 -0
- package/dist/data/designs/ios-tidal-android.md +398 -0
- package/dist/data/designs/ios-tidal-expo.md +323 -0
- package/dist/data/designs/ios-tidal-swiftui.md +340 -0
- package/dist/data/designs/ios-tidal.md +351 -0
- package/dist/data/designs/ios-tiktok-android.md +654 -0
- package/dist/data/designs/ios-tiktok-expo.md +578 -0
- package/dist/data/designs/ios-tiktok-swiftui.md +595 -0
- package/dist/data/designs/ios-tiktok.md +387 -0
- package/dist/data/designs/ios-tinder-android.md +681 -0
- package/dist/data/designs/ios-tinder-expo.md +512 -0
- package/dist/data/designs/ios-tinder-swiftui.md +497 -0
- package/dist/data/designs/ios-tinder.md +415 -0
- package/dist/data/designs/ios-todoist-android.md +711 -0
- package/dist/data/designs/ios-todoist-expo.md +607 -0
- package/dist/data/designs/ios-todoist-swiftui.md +573 -0
- package/dist/data/designs/ios-todoist.md +418 -0
- package/dist/data/designs/ios-trello-android.md +412 -0
- package/dist/data/designs/ios-trello-expo.md +332 -0
- package/dist/data/designs/ios-trello-swiftui.md +359 -0
- package/dist/data/designs/ios-trello.md +344 -0
- package/dist/data/designs/ios-tripadvisor-android.md +450 -0
- package/dist/data/designs/ios-tripadvisor-expo.md +322 -0
- package/dist/data/designs/ios-tripadvisor-swiftui.md +326 -0
- package/dist/data/designs/ios-tripadvisor.md +356 -0
- package/dist/data/designs/ios-tubi-android.md +453 -0
- package/dist/data/designs/ios-tubi-expo.md +419 -0
- package/dist/data/designs/ios-tubi-swiftui.md +463 -0
- package/dist/data/designs/ios-tubi.md +383 -0
- package/dist/data/designs/ios-tumblr-android.md +462 -0
- package/dist/data/designs/ios-tumblr-expo.md +374 -0
- package/dist/data/designs/ios-tumblr-swiftui.md +380 -0
- package/dist/data/designs/ios-tumblr.md +337 -0
- package/dist/data/designs/ios-turo-android.md +500 -0
- package/dist/data/designs/ios-turo-expo.md +454 -0
- package/dist/data/designs/ios-turo-swiftui.md +447 -0
- package/dist/data/designs/ios-turo.md +392 -0
- package/dist/data/designs/ios-twitch-android.md +412 -0
- package/dist/data/designs/ios-twitch-expo.md +342 -0
- package/dist/data/designs/ios-twitch-swiftui.md +328 -0
- package/dist/data/designs/ios-twitch.md +354 -0
- package/dist/data/designs/ios-uber-android.md +637 -0
- package/dist/data/designs/ios-uber-eats-android.md +502 -0
- package/dist/data/designs/ios-uber-eats-expo.md +407 -0
- package/dist/data/designs/ios-uber-eats-swiftui.md +393 -0
- package/dist/data/designs/ios-uber-eats.md +353 -0
- package/dist/data/designs/ios-uber-expo.md +512 -0
- package/dist/data/designs/ios-uber-swiftui.md +483 -0
- package/dist/data/designs/ios-uber.md +395 -0
- package/dist/data/designs/ios-united-airlines-android.md +494 -0
- package/dist/data/designs/ios-united-airlines-expo.md +408 -0
- package/dist/data/designs/ios-united-airlines-swiftui.md +453 -0
- package/dist/data/designs/ios-united-airlines.md +388 -0
- package/dist/data/designs/ios-venmo-android.md +654 -0
- package/dist/data/designs/ios-venmo-expo.md +458 -0
- package/dist/data/designs/ios-venmo-swiftui.md +469 -0
- package/dist/data/designs/ios-venmo.md +436 -0
- package/dist/data/designs/ios-vercel-android.md +454 -0
- package/dist/data/designs/ios-vercel-expo.md +387 -0
- package/dist/data/designs/ios-vercel-swiftui.md +374 -0
- package/dist/data/designs/ios-vercel.md +399 -0
- package/dist/data/designs/ios-vero-android.md +498 -0
- package/dist/data/designs/ios-vero-expo.md +376 -0
- package/dist/data/designs/ios-vero-swiftui.md +374 -0
- package/dist/data/designs/ios-vero.md +394 -0
- package/dist/data/designs/ios-viber-android.md +377 -0
- package/dist/data/designs/ios-viber-expo.md +375 -0
- package/dist/data/designs/ios-viber-swiftui.md +378 -0
- package/dist/data/designs/ios-viber.md +403 -0
- package/dist/data/designs/ios-vimeo-android.md +465 -0
- package/dist/data/designs/ios-vimeo-expo.md +347 -0
- package/dist/data/designs/ios-vimeo-swiftui.md +383 -0
- package/dist/data/designs/ios-vimeo.md +403 -0
- package/dist/data/designs/ios-vrbo-android.md +488 -0
- package/dist/data/designs/ios-vrbo-expo.md +395 -0
- package/dist/data/designs/ios-vrbo-swiftui.md +421 -0
- package/dist/data/designs/ios-vrbo.md +383 -0
- package/dist/data/designs/ios-vsco-android.md +490 -0
- package/dist/data/designs/ios-vsco-expo.md +413 -0
- package/dist/data/designs/ios-vsco-swiftui.md +449 -0
- package/dist/data/designs/ios-vsco.md +412 -0
- package/dist/data/designs/ios-walmart-android.md +479 -0
- package/dist/data/designs/ios-walmart-expo.md +370 -0
- package/dist/data/designs/ios-walmart-swiftui.md +387 -0
- package/dist/data/designs/ios-walmart.md +366 -0
- package/dist/data/designs/ios-waze-android.md +695 -0
- package/dist/data/designs/ios-waze-expo.md +587 -0
- package/dist/data/designs/ios-waze-swiftui.md +601 -0
- package/dist/data/designs/ios-waze.md +453 -0
- package/dist/data/designs/ios-webull-android.md +429 -0
- package/dist/data/designs/ios-webull-expo.md +384 -0
- package/dist/data/designs/ios-webull-swiftui.md +406 -0
- package/dist/data/designs/ios-webull.md +375 -0
- package/dist/data/designs/ios-wechat-android.md +545 -0
- package/dist/data/designs/ios-wechat-expo.md +398 -0
- package/dist/data/designs/ios-wechat-swiftui.md +394 -0
- package/dist/data/designs/ios-wechat.md +363 -0
- package/dist/data/designs/ios-whatsapp-android.md +568 -0
- package/dist/data/designs/ios-whatsapp-expo.md +502 -0
- package/dist/data/designs/ios-whatsapp-swiftui.md +483 -0
- package/dist/data/designs/ios-whatsapp.md +425 -0
- package/dist/data/designs/ios-whoop-android.md +635 -0
- package/dist/data/designs/ios-whoop-expo.md +562 -0
- package/dist/data/designs/ios-whoop-swiftui.md +553 -0
- package/dist/data/designs/ios-whoop.md +419 -0
- package/dist/data/designs/ios-wise-android.md +428 -0
- package/dist/data/designs/ios-wise-expo.md +357 -0
- package/dist/data/designs/ios-wise-swiftui.md +356 -0
- package/dist/data/designs/ios-wise.md +361 -0
- package/dist/data/designs/ios-x-twitter-android.md +618 -0
- package/dist/data/designs/ios-x-twitter-expo.md +442 -0
- package/dist/data/designs/ios-x-twitter-swiftui.md +429 -0
- package/dist/data/designs/ios-x-twitter.md +432 -0
- package/dist/data/designs/ios-yelp-android.md +455 -0
- package/dist/data/designs/ios-yelp-expo.md +397 -0
- package/dist/data/designs/ios-yelp-swiftui.md +369 -0
- package/dist/data/designs/ios-yelp.md +398 -0
- package/dist/data/designs/ios-youtube-android.md +668 -0
- package/dist/data/designs/ios-youtube-expo.md +435 -0
- package/dist/data/designs/ios-youtube-music-android.md +450 -0
- package/dist/data/designs/ios-youtube-music-expo.md +404 -0
- package/dist/data/designs/ios-youtube-music-swiftui.md +434 -0
- package/dist/data/designs/ios-youtube-music.md +381 -0
- package/dist/data/designs/ios-youtube-swiftui.md +496 -0
- package/dist/data/designs/ios-youtube.md +466 -0
- package/dist/data/designs/ios-zalo-android.md +510 -0
- package/dist/data/designs/ios-zalo-expo.md +389 -0
- package/dist/data/designs/ios-zalo-swiftui.md +431 -0
- package/dist/data/designs/ios-zalo.md +388 -0
- package/dist/data/designs/ios-zomato-android.md +527 -0
- package/dist/data/designs/ios-zomato-expo.md +437 -0
- package/dist/data/designs/ios-zomato-swiftui.md +433 -0
- package/dist/data/designs/ios-zomato.md +439 -0
- package/dist/data/designs/ios-zoom-android.md +423 -0
- package/dist/data/designs/ios-zoom-expo.md +355 -0
- package/dist/data/designs/ios-zoom-swiftui.md +379 -0
- package/dist/data/designs/ios-zoom.md +357 -0
- package/dist/data/designs/ios-zwift-android.md +402 -0
- package/dist/data/designs/ios-zwift-expo.md +402 -0
- package/dist/data/designs/ios-zwift-swiftui.md +378 -0
- package/dist/data/designs/ios-zwift.md +411 -0
- package/dist/data/designs/kraken.md +125 -0
- package/dist/data/designs/lamborghini.md +288 -0
- package/dist/data/designs/linear.app.md +548 -0
- package/dist/data/designs/lovable.md +298 -0
- package/dist/data/designs/mastercard.md +365 -0
- package/dist/data/designs/material-clean.md +289 -0
- package/dist/data/designs/meta.md +683 -0
- package/dist/data/designs/midnight-pro.md +256 -0
- package/dist/data/designs/minimal-brutalist.md +245 -0
- package/dist/data/designs/minimax.md +746 -0
- package/dist/data/designs/mintlify.md +852 -0
- package/dist/data/designs/miro.md +825 -0
- package/dist/data/designs/mistral.ai.md +773 -0
- package/dist/data/designs/mongodb.md +767 -0
- package/dist/data/designs/nike.md +575 -0
- package/dist/data/designs/nintendo-2001.md +649 -0
- package/dist/data/designs/notion.md +821 -0
- package/dist/data/designs/nova-mobile-design-md.md +235 -0
- package/dist/data/designs/nvidia.md +640 -0
- package/dist/data/designs/ollama.md +539 -0
- package/dist/data/designs/opencode.ai.md +521 -0
- package/dist/data/designs/pinterest.md +597 -0
- package/dist/data/designs/playful-color.md +253 -0
- package/dist/data/designs/playstation.md +661 -0
- package/dist/data/designs/posthog.md +690 -0
- package/dist/data/designs/raycast.md +669 -0
- package/dist/data/designs/renault.md +589 -0
- package/dist/data/designs/replicate.md +616 -0
- package/dist/data/designs/resend.md +585 -0
- package/dist/data/designs/revolut.md +636 -0
- package/dist/data/designs/runwayml.md +244 -0
- package/dist/data/designs/sanity.md +357 -0
- package/dist/data/designs/sentry.md +551 -0
- package/dist/data/designs/shopify.md +516 -0
- package/dist/data/designs/slack.md +482 -0
- package/dist/data/designs/soft-glass.md +258 -0
- package/dist/data/designs/spacex.md +363 -0
- package/dist/data/designs/spotify.md +246 -0
- package/dist/data/designs/starbucks.md +580 -0
- package/dist/data/designs/stripe.md +487 -0
- package/dist/data/designs/supabase.md +462 -0
- package/dist/data/designs/superhuman.md +448 -0
- package/dist/data/designs/tesla.md +286 -0
- package/dist/data/designs/theverge.md +339 -0
- package/dist/data/designs/together.ai.md +633 -0
- package/dist/data/designs/uber.md +636 -0
- package/dist/data/designs/vercel.md +736 -0
- package/dist/data/designs/vodafone.md +538 -0
- package/dist/data/designs/voltagent.md +521 -0
- package/dist/data/designs/warp.md +526 -0
- package/dist/data/designs/webflow.md +588 -0
- package/dist/data/designs/wired.md +497 -0
- package/dist/data/designs/wise.md +544 -0
- package/dist/data/designs/x.ai.md +465 -0
- package/dist/data/designs/zapier.md +537 -0
- package/dist/data/index.json +2600 -0
- package/dist/httpServer.js +83 -0
- package/dist/index.js +13 -0
- package/dist/server.js +32 -0
- package/dist/services/designStore.js +59 -0
- package/dist/services/linter.js +87 -0
- package/dist/services/sectionParser.js +154 -0
- package/dist/tools/authoring.js +131 -0
- package/dist/tools/browse.js +232 -0
- package/dist/tools/diff.js +88 -0
- package/dist/tools/getDesign.js +216 -0
- package/dist/tools/guardrails.js +87 -0
- package/dist/tools/lint.js +104 -0
- package/dist/types.js +1 -0
- package/package.json +65 -0
|
@@ -0,0 +1,601 @@
|
|
|
1
|
+
# Cash App (iOS) — Jetpack Compose Implementation Guide
|
|
2
|
+
|
|
3
|
+
Companion to [DESIGN.md](DESIGN.md) — the framework-neutral spec. This file ports Cash App's visual language to **Android with Jetpack Compose (Material 3)**: a color token object, a `Typography` set, paste-ready `@Composable`s, the signature $-amount keypad, the matte Cash Card, and the icon-only tab bar.
|
|
4
|
+
|
|
5
|
+
> Why a Compose guide for an iOS-referenced app? The DESIGN.md tokens are platform-neutral. This file keeps the *visual* identity (Cash App's pure-black matte canvas, the single violently-saturated Cash Green, the giant Cash Sans Mono keypad, black-on-green Pay button, icon-only tabs) while making everything idiomatic Android — a `Box`-grid keypad instead of `_onButtonGesture`, `AnimatedContent` for the numeric digit shrink, `NavigationBar` with hidden labels, `sp`/`dp` instead of `pt`. Cash App is flat — no `shadow`, depth is surface-color contrast only.
|
|
6
|
+
|
|
7
|
+
Assumes Compose BOM `2024.09+`, Kotlin `2.0+`, `minSdk 24`, Material 3. No remote images in the core flows and no color extraction, so neither Coil nor `androidx.palette` is required (add Coil only if you render user-uploaded avatars).
|
|
8
|
+
|
|
9
|
+
## 1. Color Tokens
|
|
10
|
+
|
|
11
|
+
```kotlin
|
|
12
|
+
// ui/theme/CashColors.kt
|
|
13
|
+
import androidx.compose.ui.graphics.Color
|
|
14
|
+
|
|
15
|
+
object CashColors {
|
|
16
|
+
// Canvas & Surfaces — pure black, depth via fill contrast (no shadows)
|
|
17
|
+
val Canvas = Color(0xFF000000) // every screen
|
|
18
|
+
val Surface1 = Color(0xFF0F0F0F) // sheets, cards, row press
|
|
19
|
+
val Surface2 = Color(0xFF1A1A1A) // input fill, keypad press, Request button
|
|
20
|
+
val Divider = Color(0xFF1F1F1F) // hairline between rows
|
|
21
|
+
val Hairline = Color(0xFF2A2A2A) // sheet grabber, sparing dividers
|
|
22
|
+
|
|
23
|
+
// Text
|
|
24
|
+
val TextPrimary = Color(0xFFFFFFFF) // pure white — no off-white
|
|
25
|
+
val TextSecondary = Color(0xFF9E9E9E) // "Sent to", date stamps
|
|
26
|
+
val TextTertiary = Color(0xFF6E6E6E) // disabled, placeholder
|
|
27
|
+
val TextMutedGreen = Color(0xFF005C16) // faint "$0" ghost when empty
|
|
28
|
+
|
|
29
|
+
// Brand
|
|
30
|
+
val Green = Color(0xFF00D632) // THE accent — Pay CTA, valid amount, active tab
|
|
31
|
+
val GreenPressed = Color(0xFF00B829) // pressed Pay
|
|
32
|
+
val GreenDim = Color(0xFF008C20) // disabled Pay, secondary green
|
|
33
|
+
val BitcoinOrange = Color(0xFFF7931A) // Bitcoin tab + BTC line only
|
|
34
|
+
val BoostRed = Color(0xFFFF453A) // declines, Stocks down
|
|
35
|
+
|
|
36
|
+
// Semantic
|
|
37
|
+
val Success = Color(0xFF00D632) // == brand green
|
|
38
|
+
val Error = Color(0xFFFF453A)
|
|
39
|
+
val Warning = Color(0xFFFFA300) // pending Activity rows
|
|
40
|
+
|
|
41
|
+
// Light mode (accessibility-only — brand lives in the dark)
|
|
42
|
+
val LightCanvas = Color(0xFFFFFFFF)
|
|
43
|
+
val LightSurface1 = Color(0xFFF5F5F5)
|
|
44
|
+
val LightSurface2 = Color(0xFFEEEEEE)
|
|
45
|
+
val LightText = Color(0xFF000000)
|
|
46
|
+
val LightTextSec = Color(0xFF6E6E6E)
|
|
47
|
+
val GreenLight = Color(0xFF00B829) // darkened for AA on white
|
|
48
|
+
|
|
49
|
+
// Random saturated avatar background colors (no-photo fallback) — loud by design
|
|
50
|
+
val AvatarColors = listOf(
|
|
51
|
+
Color(0xFFFF6B9D), // pink
|
|
52
|
+
Color(0xFFFF953C), // orange
|
|
53
|
+
Color(0xFF619AFF), // blue
|
|
54
|
+
Color(0xFF5BD47B), // green
|
|
55
|
+
Color(0xFFAA77FF), // purple
|
|
56
|
+
Color(0xFFFFCA4C), // yellow
|
|
57
|
+
)
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Wire it into a Material 3 `darkColorScheme` — Cash App is dark-first; light mode is accessibility-only and reuses identical mono numerals.
|
|
62
|
+
|
|
63
|
+
```kotlin
|
|
64
|
+
// ui/theme/Theme.kt
|
|
65
|
+
import androidx.compose.material3.darkColorScheme
|
|
66
|
+
import androidx.compose.material3.MaterialTheme
|
|
67
|
+
|
|
68
|
+
private val CashScheme = darkColorScheme(
|
|
69
|
+
primary = CashColors.Green,
|
|
70
|
+
onPrimary = Color(0xFF000000), // intentional: BLACK text on green, not white
|
|
71
|
+
background = CashColors.Canvas,
|
|
72
|
+
onBackground = CashColors.TextPrimary,
|
|
73
|
+
surface = CashColors.Surface1,
|
|
74
|
+
onSurface = CashColors.TextPrimary,
|
|
75
|
+
surfaceVariant = CashColors.Surface2,
|
|
76
|
+
outline = CashColors.Divider,
|
|
77
|
+
error = CashColors.Error,
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
@Composable
|
|
81
|
+
fun CashTheme(content: @Composable () -> Unit) =
|
|
82
|
+
MaterialTheme(colorScheme = CashScheme, typography = CashTypography, content = content)
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## 2. Typography
|
|
86
|
+
|
|
87
|
+
Cash Sans and Cash Sans Mono are proprietary (drawn in-house for Block). Drop the TTFs in `res/font/` (lowercase, snake_case). Fall back to Roboto for the sans and a monospace family for amounts — Inter / JetBrains Mono are closer brand substitutes if you can bundle them. **Mono for money, sans for everything else** — non-negotiable.
|
|
88
|
+
|
|
89
|
+
```kotlin
|
|
90
|
+
// ui/theme/CashType.kt
|
|
91
|
+
import androidx.compose.material3.Typography
|
|
92
|
+
import androidx.compose.ui.text.TextStyle
|
|
93
|
+
import androidx.compose.ui.text.font.Font
|
|
94
|
+
import androidx.compose.ui.text.font.FontFamily
|
|
95
|
+
import androidx.compose.ui.text.font.FontWeight
|
|
96
|
+
import androidx.compose.ui.unit.sp
|
|
97
|
+
|
|
98
|
+
val CashSans = FontFamily(
|
|
99
|
+
Font(R.font.cash_sans_regular, FontWeight.Normal), // 400
|
|
100
|
+
Font(R.font.cash_sans_medium, FontWeight.Medium), // 500
|
|
101
|
+
Font(R.font.cash_sans_bold, FontWeight.Bold), // 700
|
|
102
|
+
Font(R.font.cash_sans_black, FontWeight.Black), // 900
|
|
103
|
+
)
|
|
104
|
+
val CashSansMono = FontFamily(
|
|
105
|
+
Font(R.font.cash_sans_mono_regular, FontWeight.Normal),
|
|
106
|
+
Font(R.font.cash_sans_mono_medium, FontWeight.Medium),
|
|
107
|
+
Font(R.font.cash_sans_mono_bold, FontWeight.Bold),
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
private const val TNUM = "tnum" // tabular numerals — every amount aligns vertically
|
|
111
|
+
|
|
112
|
+
// Named ramp — mirrors DESIGN.md §3 exactly (pt → sp 1:1, same weights/tracking)
|
|
113
|
+
object CashText {
|
|
114
|
+
val AmountHero = TextStyle(CashSansMono, fontWeight = FontWeight.Bold, fontSize = 96.sp, lineHeight = 96.sp, letterSpacing = (-2).sp, fontFeatureSettings = TNUM)
|
|
115
|
+
val AmountReceive = TextStyle(CashSansMono, fontWeight = FontWeight.Bold, fontSize = 64.sp, lineHeight = 64.sp, letterSpacing = (-1.5).sp, fontFeatureSettings = TNUM)
|
|
116
|
+
val Balance = TextStyle(CashSansMono, fontWeight = FontWeight.Bold, fontSize = 48.sp, lineHeight = 48.sp, letterSpacing = (-1).sp, fontFeatureSettings = TNUM)
|
|
117
|
+
val ScreenTitle = TextStyle(CashSans, fontWeight = FontWeight.Black, fontSize = 28.sp, lineHeight = 31.sp, letterSpacing = (-0.5).sp)
|
|
118
|
+
val SectionHeader = TextStyle(CashSans, fontWeight = FontWeight.Bold, fontSize = 22.sp, lineHeight = 25.sp, letterSpacing = (-0.3).sp)
|
|
119
|
+
val CashtagLarge = TextStyle(CashSansMono, fontWeight = FontWeight.Medium, fontSize = 22.sp, lineHeight = 26.sp, fontFeatureSettings = TNUM)
|
|
120
|
+
val CardLabel = TextStyle(CashSans, fontWeight = FontWeight.Medium, fontSize = 16.sp, lineHeight = 21.sp)
|
|
121
|
+
val Body = TextStyle(CashSans, fontWeight = FontWeight.Normal, fontSize = 15.sp, lineHeight = 21.sp)
|
|
122
|
+
val Meta = TextStyle(CashSans, fontWeight = FontWeight.Normal, fontSize = 13.sp, lineHeight = 17.sp)
|
|
123
|
+
val Button = TextStyle(CashSans, fontWeight = FontWeight.Bold, fontSize = 17.sp, lineHeight = 17.sp)
|
|
124
|
+
val ButtonSmall = TextStyle(CashSans, fontWeight = FontWeight.Medium, fontSize = 15.sp, lineHeight = 15.sp)
|
|
125
|
+
val AllCaps = TextStyle(CashSans, fontWeight = FontWeight.Bold, fontSize = 11.sp, lineHeight = 13.sp, letterSpacing = 1.5.sp)
|
|
126
|
+
val AmountRow = TextStyle(CashSansMono, fontWeight = FontWeight.Medium, fontSize = 17.sp, lineHeight = 17.sp, fontFeatureSettings = TNUM)
|
|
127
|
+
val CashtagInline = TextStyle(CashSansMono, fontWeight = FontWeight.Medium, fontSize = 15.sp, lineHeight = 20.sp, fontFeatureSettings = TNUM)
|
|
128
|
+
val KeypadDigit = TextStyle(CashSansMono, fontWeight = FontWeight.Normal, fontSize = 32.sp, lineHeight = 32.sp, fontFeatureSettings = TNUM)
|
|
129
|
+
val AvatarInit = TextStyle(CashSans, fontWeight = FontWeight.Bold, fontSize = 22.sp, lineHeight = 22.sp)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Map onto Material 3 slots so stock components inherit the brand
|
|
133
|
+
val CashTypography = Typography(
|
|
134
|
+
displayLarge = CashText.Balance,
|
|
135
|
+
headlineLarge = CashText.ScreenTitle,
|
|
136
|
+
titleLarge = CashText.SectionHeader,
|
|
137
|
+
titleMedium = CashText.CardLabel,
|
|
138
|
+
bodyMedium = CashText.Body,
|
|
139
|
+
labelSmall = CashText.AllCaps,
|
|
140
|
+
)
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
The `tnum` feature is baked into every monetary style so amounts align in a vertical list — non-negotiable for the Activity feed and keypad.
|
|
144
|
+
|
|
145
|
+
## 3. Signature Components
|
|
146
|
+
|
|
147
|
+
### The $-Amount Keypad (Pay screen — the hero)
|
|
148
|
+
|
|
149
|
+
This is the single most important screen. Giant `$` + amount fills the upper ~40%, auto-shrinking as digits add; a 3×4 keypad fills the lower half; Request (gray) + Pay (green, black text) sit below.
|
|
150
|
+
|
|
151
|
+
```kotlin
|
|
152
|
+
import androidx.compose.animation.AnimatedContent
|
|
153
|
+
import androidx.compose.animation.core.animateFloatAsState
|
|
154
|
+
import androidx.compose.animation.core.spring
|
|
155
|
+
import androidx.compose.animation.togetherWith
|
|
156
|
+
import androidx.compose.foundation.background
|
|
157
|
+
import androidx.compose.foundation.clickable
|
|
158
|
+
import androidx.compose.foundation.interaction.MutableInteractionSource
|
|
159
|
+
import androidx.compose.foundation.interaction.collectIsPressedAsState
|
|
160
|
+
import androidx.compose.foundation.layout.*
|
|
161
|
+
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
162
|
+
import androidx.compose.material.icons.Icons
|
|
163
|
+
import androidx.compose.material.icons.automirrored.filled.Backspace
|
|
164
|
+
import androidx.compose.material3.Icon
|
|
165
|
+
import androidx.compose.material3.Text
|
|
166
|
+
import androidx.compose.runtime.*
|
|
167
|
+
import androidx.compose.ui.Alignment
|
|
168
|
+
import androidx.compose.ui.Modifier
|
|
169
|
+
import androidx.compose.ui.draw.clip
|
|
170
|
+
import androidx.compose.ui.draw.scale
|
|
171
|
+
import androidx.compose.ui.graphics.Color
|
|
172
|
+
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
|
173
|
+
import androidx.compose.ui.platform.LocalHapticFeedback
|
|
174
|
+
import androidx.compose.ui.text.style.TextAlign
|
|
175
|
+
import androidx.compose.ui.unit.dp
|
|
176
|
+
import androidx.compose.ui.unit.sp
|
|
177
|
+
|
|
178
|
+
@Composable
|
|
179
|
+
fun AmountKeypad(
|
|
180
|
+
amount: String, // raw, e.g. "12.50"
|
|
181
|
+
onAmountChange: (String) -> Unit,
|
|
182
|
+
onPay: () -> Unit,
|
|
183
|
+
onRequest: () -> Unit,
|
|
184
|
+
modifier: Modifier = Modifier,
|
|
185
|
+
) {
|
|
186
|
+
val display = amount.ifEmpty { "0" }
|
|
187
|
+
// Auto-shrink as more digits appear (96 → 80 → 64 → 52)
|
|
188
|
+
val heroSize = when (display.length) {
|
|
189
|
+
in 0..3 -> 96.sp
|
|
190
|
+
4 -> 80.sp
|
|
191
|
+
5 -> 64.sp
|
|
192
|
+
else -> 52.sp
|
|
193
|
+
}
|
|
194
|
+
val valid = amount.isNotEmpty()
|
|
195
|
+
val haptics = LocalHapticFeedback.current
|
|
196
|
+
|
|
197
|
+
Column(modifier.fillMaxSize().background(CashColors.Canvas)) {
|
|
198
|
+
// Top: giant amount with numeric content transition
|
|
199
|
+
Row(
|
|
200
|
+
Modifier.fillMaxWidth().padding(top = 64.dp),
|
|
201
|
+
horizontalArrangement = Arrangement.Center,
|
|
202
|
+
verticalAlignment = Alignment.CenterVertically,
|
|
203
|
+
) {
|
|
204
|
+
Text("$",
|
|
205
|
+
style = CashText.AmountHero.copy(fontSize = heroSize * 0.67f),
|
|
206
|
+
color = CashColors.TextSecondary)
|
|
207
|
+
Spacer(Modifier.width(4.dp))
|
|
208
|
+
AnimatedContent(
|
|
209
|
+
targetState = display,
|
|
210
|
+
transitionSpec = { (fadeIn() + scaleIn(initialScale = 0.9f)) togetherWith fadeOut() },
|
|
211
|
+
label = "amount",
|
|
212
|
+
) { value ->
|
|
213
|
+
Text(value, style = CashText.AmountHero.copy(fontSize = heroSize),
|
|
214
|
+
color = CashColors.TextPrimary)
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
// Subtle Cash-Green "glow" when valid (Android has no text-shadow blur — emulate
|
|
218
|
+
// with a faint behind-text green halo via a blurred copy if exact parity is needed).
|
|
219
|
+
|
|
220
|
+
Spacer(Modifier.weight(1f))
|
|
221
|
+
|
|
222
|
+
// Keypad: 3 cols, "0" double-width on the last row
|
|
223
|
+
val rows = listOf(
|
|
224
|
+
listOf("1", "2", "3"),
|
|
225
|
+
listOf("4", "5", "6"),
|
|
226
|
+
listOf("7", "8", "9"),
|
|
227
|
+
)
|
|
228
|
+
Column(
|
|
229
|
+
Modifier.fillMaxWidth().padding(horizontal = 24.dp),
|
|
230
|
+
verticalArrangement = Arrangement.spacedBy(4.dp),
|
|
231
|
+
) {
|
|
232
|
+
rows.forEach { row ->
|
|
233
|
+
Row(horizontalArrangement = Arrangement.spacedBy(4.dp)) {
|
|
234
|
+
row.forEach { d ->
|
|
235
|
+
KeypadButton(d, Modifier.weight(1f)) { onAmountChange(amount + d) }
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
Row(horizontalArrangement = Arrangement.spacedBy(4.dp)) {
|
|
240
|
+
KeypadButton(".", Modifier.weight(1f)) { if (!amount.contains('.')) onAmountChange("$amount.") }
|
|
241
|
+
KeypadButton("0", Modifier.weight(2f)) { onAmountChange(amount + "0") } // double-width
|
|
242
|
+
KeypadButton(null, Modifier.weight(1f), icon = Icons.AutoMirrored.Filled.Backspace) {
|
|
243
|
+
if (amount.isNotEmpty()) onAmountChange(amount.dropLast(1))
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// Pay / Request
|
|
249
|
+
Row(
|
|
250
|
+
Modifier.fillMaxWidth().padding(horizontal = 24.dp, vertical = 0.dp)
|
|
251
|
+
.padding(top = 16.dp, bottom = 24.dp),
|
|
252
|
+
horizontalArrangement = Arrangement.spacedBy(12.dp),
|
|
253
|
+
) {
|
|
254
|
+
Box(
|
|
255
|
+
Modifier.weight(1f).height(60.dp).clip(RoundedCornerShape(30.dp))
|
|
256
|
+
.background(CashColors.Surface2).clickable { onRequest() },
|
|
257
|
+
contentAlignment = Alignment.Center,
|
|
258
|
+
) { Text("Request", style = CashText.Button, color = CashColors.TextPrimary) }
|
|
259
|
+
Box(
|
|
260
|
+
Modifier.weight(1f).height(60.dp).clip(RoundedCornerShape(30.dp))
|
|
261
|
+
.background(if (valid) CashColors.Green else CashColors.Surface2)
|
|
262
|
+
.clickable(enabled = valid) {
|
|
263
|
+
haptics.performHapticFeedback(HapticFeedbackType.LongPress) // ≈ .notification(.success)
|
|
264
|
+
onPay()
|
|
265
|
+
},
|
|
266
|
+
contentAlignment = Alignment.Center,
|
|
267
|
+
) {
|
|
268
|
+
Text("Pay", style = CashText.Button,
|
|
269
|
+
color = if (valid) Color.Black else CashColors.TextTertiary) // black on green
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
@Composable
|
|
276
|
+
private fun KeypadButton(
|
|
277
|
+
label: String?,
|
|
278
|
+
modifier: Modifier = Modifier,
|
|
279
|
+
icon: androidx.compose.ui.graphics.vector.ImageVector? = null,
|
|
280
|
+
onClick: () -> Unit,
|
|
281
|
+
) {
|
|
282
|
+
val interaction = remember { MutableInteractionSource() }
|
|
283
|
+
val pressed by interaction.collectIsPressedAsState()
|
|
284
|
+
val scale by animateFloatAsState(if (pressed) 0.96f else 1f, label = "keyScale")
|
|
285
|
+
val haptics = LocalHapticFeedback.current
|
|
286
|
+
Box(
|
|
287
|
+
modifier = modifier
|
|
288
|
+
.height(64.dp)
|
|
289
|
+
.scale(scale)
|
|
290
|
+
.clip(RoundedCornerShape(12.dp))
|
|
291
|
+
.background(if (pressed) CashColors.Surface2 else Color.Transparent)
|
|
292
|
+
.clickable(interaction, indication = null) {
|
|
293
|
+
haptics.performHapticFeedback(HapticFeedbackType.TextHandleMove) // ≈ .impact(.light)
|
|
294
|
+
onClick()
|
|
295
|
+
},
|
|
296
|
+
contentAlignment = Alignment.Center,
|
|
297
|
+
) {
|
|
298
|
+
when {
|
|
299
|
+
label != null -> Text(label, style = CashText.KeypadDigit, color = CashColors.TextPrimary,
|
|
300
|
+
textAlign = TextAlign.Center)
|
|
301
|
+
icon != null -> Icon(icon, "Backspace", tint = CashColors.TextPrimary,
|
|
302
|
+
modifier = Modifier.size(28.dp))
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
### Cash Card Render
|
|
309
|
+
|
|
310
|
+
1.586:1 matte-black card, hairline border, `$Cashtag` etched in the user's accent. **No shadow** — the card sits flat; the border is the only depth cue.
|
|
311
|
+
|
|
312
|
+
```kotlin
|
|
313
|
+
import androidx.compose.foundation.border
|
|
314
|
+
|
|
315
|
+
@Composable
|
|
316
|
+
fun CashCardView(
|
|
317
|
+
cashtag: String, // "$johndoe"
|
|
318
|
+
accent: Color = CashColors.Green,
|
|
319
|
+
modifier: Modifier = Modifier,
|
|
320
|
+
) {
|
|
321
|
+
Box(
|
|
322
|
+
modifier = modifier
|
|
323
|
+
.fillMaxWidth()
|
|
324
|
+
.aspectRatio(1.586f)
|
|
325
|
+
.clip(RoundedCornerShape(12.dp))
|
|
326
|
+
.background(CashColors.Canvas) // matte black, NO shadow
|
|
327
|
+
.border(1.dp, CashColors.Divider, RoundedCornerShape(12.dp)),
|
|
328
|
+
) {
|
|
329
|
+
Row(
|
|
330
|
+
Modifier.align(Alignment.BottomStart).fillMaxWidth().padding(24.dp),
|
|
331
|
+
verticalAlignment = Alignment.Bottom,
|
|
332
|
+
) {
|
|
333
|
+
Text(cashtag, style = CashText.CashtagLarge.copy(fontWeight = FontWeight.Bold, fontSize = 24.sp),
|
|
334
|
+
color = accent)
|
|
335
|
+
Spacer(Modifier.weight(1f))
|
|
336
|
+
Text("$", style = CashText.ScreenTitle.copy(fontSize = 32.sp), color = accent)
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
### Activity Row
|
|
343
|
+
|
|
344
|
+
```kotlin
|
|
345
|
+
enum class Direction { Sent, Received }
|
|
346
|
+
|
|
347
|
+
@Composable
|
|
348
|
+
fun ActivityRow(
|
|
349
|
+
name: String,
|
|
350
|
+
direction: Direction,
|
|
351
|
+
subtitle: String, // "Sent to John" / "From Sarah"
|
|
352
|
+
amount: String, // "20.00"
|
|
353
|
+
modifier: Modifier = Modifier,
|
|
354
|
+
avatarColor: Color = remember(name) { CashColors.AvatarColors.random() },
|
|
355
|
+
) {
|
|
356
|
+
val received = direction == Direction.Received
|
|
357
|
+
val interaction = remember { MutableInteractionSource() }
|
|
358
|
+
val pressed by interaction.collectIsPressedAsState()
|
|
359
|
+
Box(
|
|
360
|
+
modifier
|
|
361
|
+
.fillMaxWidth()
|
|
362
|
+
.height(64.dp)
|
|
363
|
+
.background(if (pressed) CashColors.Surface1 else CashColors.Canvas)
|
|
364
|
+
.clickable(interaction, indication = null) {},
|
|
365
|
+
) {
|
|
366
|
+
Row(
|
|
367
|
+
Modifier.fillMaxSize().padding(horizontal = 24.dp),
|
|
368
|
+
verticalAlignment = Alignment.CenterVertically,
|
|
369
|
+
horizontalArrangement = Arrangement.spacedBy(12.dp),
|
|
370
|
+
) {
|
|
371
|
+
Box(
|
|
372
|
+
Modifier.size(40.dp).clip(androidx.compose.foundation.shape.CircleShape).background(avatarColor),
|
|
373
|
+
contentAlignment = Alignment.Center,
|
|
374
|
+
) { Text(name.take(1), style = CashText.AvatarInit, color = Color.White) }
|
|
375
|
+
Column(Modifier.weight(1f), verticalArrangement = Arrangement.spacedBy(2.dp)) {
|
|
376
|
+
Text(name, style = CashText.CardLabel, color = CashColors.TextPrimary, maxLines = 1)
|
|
377
|
+
Text(subtitle, style = CashText.Meta, color = CashColors.TextSecondary, maxLines = 1)
|
|
378
|
+
}
|
|
379
|
+
Text(
|
|
380
|
+
(if (received) "+$" else "-$") + amount,
|
|
381
|
+
style = CashText.AmountRow,
|
|
382
|
+
color = if (received) CashColors.Green else CashColors.TextPrimary,
|
|
383
|
+
)
|
|
384
|
+
}
|
|
385
|
+
Box(
|
|
386
|
+
Modifier.align(Alignment.BottomCenter).fillMaxWidth().height(0.5.dp)
|
|
387
|
+
.background(CashColors.Divider)
|
|
388
|
+
)
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
### Balance Tile (Money tab top)
|
|
394
|
+
|
|
395
|
+
```kotlin
|
|
396
|
+
@Composable
|
|
397
|
+
fun BalanceTile(dollars: Int, cents: Int, modifier: Modifier = Modifier) {
|
|
398
|
+
Column(
|
|
399
|
+
modifier.fillMaxWidth().background(CashColors.Canvas)
|
|
400
|
+
.padding(horizontal = 24.dp, vertical = 24.dp),
|
|
401
|
+
verticalArrangement = Arrangement.spacedBy(8.dp),
|
|
402
|
+
) {
|
|
403
|
+
Text("CASH BALANCE", style = CashText.AllCaps, color = CashColors.TextSecondary)
|
|
404
|
+
Row(verticalAlignment = Alignment.Bottom) {
|
|
405
|
+
Text("$%,d".format(dollars), style = CashText.Balance, color = CashColors.TextPrimary)
|
|
406
|
+
Text(".%02d".format(cents),
|
|
407
|
+
style = CashText.Balance.copy(fontSize = 24.sp), color = CashColors.TextPrimary)
|
|
408
|
+
}
|
|
409
|
+
Row(horizontalArrangement = Arrangement.spacedBy(8.dp), modifier = Modifier.padding(top = 12.dp)) {
|
|
410
|
+
PillButton("Add Cash") {}
|
|
411
|
+
PillButton("Cash Out") {}
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
@Composable
|
|
417
|
+
private fun PillButton(label: String, onClick: () -> Unit) {
|
|
418
|
+
Box(
|
|
419
|
+
Modifier.clip(androidx.compose.foundation.shape.CircleShape).background(CashColors.Surface2)
|
|
420
|
+
.clickable { onClick() }.padding(horizontal = 18.dp, vertical = 10.dp),
|
|
421
|
+
) { Text(label, style = CashText.ButtonSmall, color = CashColors.TextPrimary) }
|
|
422
|
+
}
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
### Screen Title (Money / Card / Activity headers)
|
|
426
|
+
|
|
427
|
+
Cash App has no top nav bar — the title is a 28sp Black-weight word in the content area with a profile avatar trailing.
|
|
428
|
+
|
|
429
|
+
```kotlin
|
|
430
|
+
import androidx.compose.material.icons.filled.Person
|
|
431
|
+
|
|
432
|
+
@Composable
|
|
433
|
+
fun CashScreenTitle(title: String, modifier: Modifier = Modifier) {
|
|
434
|
+
Row(
|
|
435
|
+
modifier.fillMaxWidth().padding(horizontal = 24.dp, top = 16.dp),
|
|
436
|
+
verticalAlignment = Alignment.CenterVertically,
|
|
437
|
+
) {
|
|
438
|
+
Text(title, style = CashText.ScreenTitle, color = CashColors.TextPrimary)
|
|
439
|
+
Spacer(Modifier.weight(1f))
|
|
440
|
+
Box(
|
|
441
|
+
Modifier.size(36.dp).clip(androidx.compose.foundation.shape.CircleShape).background(CashColors.Surface2),
|
|
442
|
+
contentAlignment = Alignment.Center,
|
|
443
|
+
) { Icon(Icons.Filled.Person, "Profile", tint = CashColors.TextPrimary, modifier = Modifier.size(20.dp)) }
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
## 4. The $-Amount Entry System (the distinctive system)
|
|
449
|
+
|
|
450
|
+
Cash App has no color extraction; its defining dynamic system is the **keypad amount engine** — type a number, watch it auto-shrink and glow green when valid, then commit with a success flash. The amount-shrink + numeric transition is implemented above in `AmountKeypad`. Here is the **send-confirmation flash** that follows a valid Pay tap: the screen pulses Cash Green for ~300ms before the confirmation sheet slides up.
|
|
451
|
+
|
|
452
|
+
```kotlin
|
|
453
|
+
import androidx.compose.animation.core.Animatable
|
|
454
|
+
import androidx.compose.animation.core.tween
|
|
455
|
+
import androidx.compose.ui.draw.alpha
|
|
456
|
+
|
|
457
|
+
@Composable
|
|
458
|
+
fun PaySuccessFlash(triggerCount: Int, onComplete: () -> Unit) {
|
|
459
|
+
val flash = remember { Animatable(0f) }
|
|
460
|
+
val haptics = LocalHapticFeedback.current
|
|
461
|
+
LaunchedEffect(triggerCount) {
|
|
462
|
+
if (triggerCount > 0) {
|
|
463
|
+
haptics.performHapticFeedback(HapticFeedbackType.LongPress) // ≈ .notification(.success)
|
|
464
|
+
flash.animateTo(0.85f, tween(120))
|
|
465
|
+
flash.animateTo(0f, tween(180))
|
|
466
|
+
onComplete() // then present the confirmation ModalBottomSheet ($-amount in AmountReceive 64sp)
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
if (flash.value > 0f) {
|
|
470
|
+
Box(Modifier.fillMaxSize().alpha(flash.value).background(CashColors.Green))
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
The confirmation sheet itself is a Material 3 `ModalBottomSheet` (24dp top radius, `Surface1` container, `Hairline` grabber) showing the amount in `CashText.AmountReceive`. Keep the digit-shrink rule (`heroSize` ladder) identical anywhere an editable amount appears so the typographic behavior is consistent across the keypad and any inline amount editors.
|
|
476
|
+
|
|
477
|
+
## 5. Navigation
|
|
478
|
+
|
|
479
|
+
5 tabs — Money / Card / Pay / Activity / Bitcoin — **icons only, no labels, ever**. The Pay tab is the center anchor and renders larger (32dp vs 28dp). Active glyph fills Cash Green; inactive glyphs stay **full white** (Cash App does not dim inactive tabs). Use Material 3 `NavigationBar` with labels suppressed and the Material indicator pill removed.
|
|
480
|
+
|
|
481
|
+
```kotlin
|
|
482
|
+
import androidx.compose.material.icons.filled.AttachMoney
|
|
483
|
+
import androidx.compose.material.icons.filled.CreditCard
|
|
484
|
+
import androidx.compose.material.icons.filled.CurrencyBitcoin
|
|
485
|
+
import androidx.compose.material.icons.filled.History
|
|
486
|
+
import androidx.compose.material.icons.filled.Paid
|
|
487
|
+
import androidx.compose.material3.NavigationBar
|
|
488
|
+
import androidx.compose.material3.NavigationBarItem
|
|
489
|
+
import androidx.compose.material3.NavigationBarItemDefaults
|
|
490
|
+
|
|
491
|
+
@Composable
|
|
492
|
+
fun CashBottomBar(selected: Int, onSelect: (Int) -> Unit) {
|
|
493
|
+
NavigationBar(containerColor = CashColors.Canvas, tonalElevation = 0.dp) {
|
|
494
|
+
// Money, Card, Pay (center, larger), Activity, Bitcoin
|
|
495
|
+
val items = listOf(
|
|
496
|
+
Icons.Filled.Paid to 28.dp, // Money
|
|
497
|
+
Icons.Filled.CreditCard to 28.dp, // Card
|
|
498
|
+
Icons.Filled.AttachMoney to 32.dp, // Pay — larger anchor
|
|
499
|
+
Icons.Filled.History to 28.dp, // Activity
|
|
500
|
+
Icons.Filled.CurrencyBitcoin to 28.dp // Bitcoin
|
|
501
|
+
)
|
|
502
|
+
val labels = listOf("Money", "Card", "Pay", "Activity", "Bitcoin")
|
|
503
|
+
items.forEachIndexed { i, (icon, size) ->
|
|
504
|
+
NavigationBarItem(
|
|
505
|
+
selected = selected == i,
|
|
506
|
+
onClick = { onSelect(i) },
|
|
507
|
+
icon = {
|
|
508
|
+
Icon(
|
|
509
|
+
icon,
|
|
510
|
+
contentDescription = "${labels[i]} tab", // TalkBack only — no visible label
|
|
511
|
+
modifier = Modifier.size(size),
|
|
512
|
+
)
|
|
513
|
+
},
|
|
514
|
+
label = null, // NO LABELS — hard rule
|
|
515
|
+
alwaysShowLabel = false,
|
|
516
|
+
colors = NavigationBarItemDefaults.colors(
|
|
517
|
+
selectedIconColor = CashColors.Green,
|
|
518
|
+
unselectedIconColor = CashColors.TextPrimary, // full white, NOT dimmed
|
|
519
|
+
indicatorColor = Color.Transparent, // no Material pill — Cash App has none
|
|
520
|
+
),
|
|
521
|
+
)
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
```
|
|
526
|
+
|
|
527
|
+
Home screens have no `TopAppBar` — use `CashScreenTitle` in the content. Modal sheets slide up over an `rgba(0,0,0,0.85)` scrim as Material 3 `ModalBottomSheet` (24dp top radius). Android has no live blur, but Cash App uses a solid dim anyway, so there is nothing to approximate — use a plain `scrimColor`.
|
|
528
|
+
|
|
529
|
+
## 6. Motion
|
|
530
|
+
|
|
531
|
+
Cash App is flat and disciplined — no shadows, no bouncy mascots. Motion is the digit engine, the green flash, and the card flip.
|
|
532
|
+
|
|
533
|
+
| Moment | Compose recipe |
|
|
534
|
+
|--------|----------------|
|
|
535
|
+
| Keypad digit tap | digit drops via `AnimatedContent` (`fadeIn + scaleIn 0.9`); existing digits shift; `spring(dampingRatio = 0.7f, stiffness ≈ 500f)` (≈ response 0.3); `HapticFeedbackType.TextHandleMove` (.impact light) |
|
|
536
|
+
| Pay send | scale 1.0 → 0.97 → 1.0 250ms `spring`, then full-screen Green flash ~300ms; `HapticFeedbackType.LongPress` (.success) |
|
|
537
|
+
| Cash Card flip | `animateFloatAsState` `rotationY` 0 → 180 over 600ms `spring(dampingRatio = 0.65f)`; `graphicsLayer { rotationY = …; cameraDistance = 12 * density }` |
|
|
538
|
+
| Activity row press | background → `Surface1` over 150ms; no scale |
|
|
539
|
+
| Tab switch | glyph color tween to Green over 200ms; `HapticFeedbackType.TextHandleMove` (.selection) |
|
|
540
|
+
| Boost activation | `Animatable` scale 1.0 → 1.05 → 1.0 `spring` + particle burst; `HapticFeedbackType.LongPress` (.success) |
|
|
541
|
+
|
|
542
|
+
```kotlin
|
|
543
|
+
// Cash Card flip (tap to reveal card back)
|
|
544
|
+
@Composable
|
|
545
|
+
fun FlippableCashCard(cashtag: String, accent: Color) {
|
|
546
|
+
var flipped by remember { mutableStateOf(false) }
|
|
547
|
+
val rotation by animateFloatAsState(
|
|
548
|
+
targetValue = if (flipped) 180f else 0f,
|
|
549
|
+
animationSpec = spring(dampingRatio = 0.65f, stiffness = 300f),
|
|
550
|
+
label = "cardFlip",
|
|
551
|
+
)
|
|
552
|
+
Box(
|
|
553
|
+
Modifier
|
|
554
|
+
.fillMaxWidth()
|
|
555
|
+
.aspectRatio(1.586f)
|
|
556
|
+
.graphicsLayer {
|
|
557
|
+
rotationY = rotation
|
|
558
|
+
cameraDistance = 12f * density
|
|
559
|
+
}
|
|
560
|
+
.clickable { flipped = !flipped },
|
|
561
|
+
) {
|
|
562
|
+
if (rotation <= 90f) {
|
|
563
|
+
CashCardView(cashtag, accent, Modifier.fillMaxSize())
|
|
564
|
+
} else {
|
|
565
|
+
Box(
|
|
566
|
+
Modifier.fillMaxSize().graphicsLayer { rotationY = 180f }
|
|
567
|
+
.clip(RoundedCornerShape(12.dp)).background(CashColors.Canvas)
|
|
568
|
+
.border(1.dp, CashColors.Divider, RoundedCornerShape(12.dp)),
|
|
569
|
+
) { /* card back: card number, CVV, etc. */ }
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
Honor **Reduce Motion**: when `Settings.Global.ANIMATOR_DURATION_SCALE == 0f`, disable the amount-glow and digit-shrink animation (snap to a fixed size sized for the longest expected digit count) and skip the Pay flash — keep the success haptic. For richer haptics use `LocalView.current.performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK)` (API 30+) or a `Vibrator` `VibrationEffect.createOneShot(8, ...)` to approximate iOS's `.light` keypad tap.
|
|
576
|
+
|
|
577
|
+
## 7. Icons
|
|
578
|
+
|
|
579
|
+
Cash App's icons are mostly bespoke; the closest first-party set is `androidx.compose.material:material-icons-extended`. The **Boost glyphs are commissioned hand-drawn artwork** — never substitute Material icons; ship them as vector drawables and load via `ImageVector.vectorResource(R.drawable.…)`.
|
|
580
|
+
|
|
581
|
+
| Purpose | SF Symbol (iOS) | Material Icon (Compose) |
|
|
582
|
+
|---------|-----------------|--------------------------|
|
|
583
|
+
| Money tab | `dollarsign.circle` / `.fill` | `Icons.Filled.Paid` |
|
|
584
|
+
| Card tab | `creditcard` / `.fill` | `Icons.Filled.CreditCard` |
|
|
585
|
+
| Pay tab (center, larger) | `dollarsign` | `Icons.Filled.AttachMoney` (32dp) |
|
|
586
|
+
| Activity tab | `clock` / `.fill` | `Icons.Filled.History` |
|
|
587
|
+
| Bitcoin tab | `bitcoinsign.circle` / `.fill` | `Icons.Filled.CurrencyBitcoin` |
|
|
588
|
+
| Backspace (keypad) | `delete.left` | `Icons.AutoMirrored.Filled.Backspace` |
|
|
589
|
+
| Search | `magnifyingglass` | `Icons.Filled.Search` |
|
|
590
|
+
| Avatar fallback | `person.fill` | `Icons.Filled.Person` |
|
|
591
|
+
| Boost (Cash Card) | commissioned art | custom vector drawables — NOT Material icons |
|
|
592
|
+
|
|
593
|
+
## 8. Minimum SDK & Accessibility Notes
|
|
594
|
+
|
|
595
|
+
- **minSdk 24** (Compose floor is 21; modern motion comfortable at 24). `compileSdk 34+`, Compose BOM `2024.09+`, Kotlin `2.0+`.
|
|
596
|
+
- **Edge-to-edge**: call `enableEdgeToEdge()` in the `Activity`; the pure-black canvas wants `WindowCompat` light-content (white) system-bar icons. Use `Scaffold` insets so the keypad sits ~8dp above the tab bar and the tab bar clears the gesture-nav indicator. The screen title gets a 16dp inset below the status bar.
|
|
597
|
+
- **Font scaling**: `sp` honors the user's font scale automatically — keep it on titles, body, and Activity rows (clamp Activity amounts at 22sp). The **Pay-screen amount must NOT scale** — its size is driven by digit count, layout is critical: wrap the keypad amount in `CompositionLocalProvider(LocalDensity provides Density(density, fontScale = 1f))`. Tab glyphs are fixed dp.
|
|
598
|
+
- **TalkBack**: tab labels are invisible — every tab `Icon` must carry a `contentDescription` ("Money tab", "Pay tab", …) since there is no visible text. Announce the keypad as "Amount entry", read it back as "Sending $12.50 to John Doe", and set the Pay button's content description to include the amount ("Pay $12.50"). Merge Activity-row text with `Modifier.semantics(mergeDescendants = true)`.
|
|
599
|
+
- **Touch targets**: Material guidance is 48.dp minimum. The 64dp keypad keys and 60dp Pay/Request buttons clear it; the 28–32dp tab glyphs sit in `NavigationBar`'s 48dp+ item slots; the 36dp profile avatar should be wrapped in a 48dp hit area.
|
|
600
|
+
- **Contrast**: white on `#000000` exceeds WCAG AA at all sizes; `#9E9E9E` on black meets AA at 14sp+ — avoid `#6E6E6E` for body text (use it only for disabled/placeholder). Green `#00D632` as the Pay fill carries black text by design — that pairing passes AA.
|
|
601
|
+
- **Dynamic color**: do **not** enable Material You `dynamicColorScheme()` — Cash App's identity is the fixed pure-black canvas and the single Cash Green regardless of wallpaper. (Material You suits Google/Material-first apps; Cash App is a strong-brand exception.) Light mode is accessibility-only — swap canvas/surface/text and darken Green to `#00B829` for AA on white; the mono numerals and tabular figures stay identical.
|