diff --git a/public/easter-eggs/antarctica.png b/public/easter-eggs/antarctica.png new file mode 100644 index 000000000..4512ff345 Binary files /dev/null and b/public/easter-eggs/antarctica.png differ diff --git a/public/easter-eggs/bouvet.png b/public/easter-eggs/bouvet.png new file mode 100644 index 000000000..5952188dc Binary files /dev/null and b/public/easter-eggs/bouvet.png differ diff --git a/public/easter-eggs/christmas.png b/public/easter-eggs/christmas.png new file mode 100644 index 000000000..28c1a664d Binary files /dev/null and b/public/easter-eggs/christmas.png differ diff --git a/public/easter-eggs/cocos.png b/public/easter-eggs/cocos.png new file mode 100644 index 000000000..45abe6c80 Binary files /dev/null and b/public/easter-eggs/cocos.png differ diff --git a/public/easter-eggs/heard.png b/public/easter-eggs/heard.png new file mode 100644 index 000000000..3327267a7 Binary files /dev/null and b/public/easter-eggs/heard.png differ diff --git a/public/easter-eggs/pitcairn.png b/public/easter-eggs/pitcairn.png new file mode 100644 index 000000000..2fc3969c4 Binary files /dev/null and b/public/easter-eggs/pitcairn.png differ diff --git a/public/easter-eggs/southgeorgia.png b/public/easter-eggs/southgeorgia.png new file mode 100644 index 000000000..65170b6ef Binary files /dev/null and b/public/easter-eggs/southgeorgia.png differ diff --git a/public/easter-eggs/tokelau.png b/public/easter-eggs/tokelau.png new file mode 100644 index 000000000..a438c4d1f Binary files /dev/null and b/public/easter-eggs/tokelau.png differ diff --git a/src/app/(mobile-ui)/dev/ds/patterns/modal/page.tsx b/src/app/(mobile-ui)/dev/ds/patterns/modal/page.tsx index e16c79855..d2598a969 100644 --- a/src/app/(mobile-ui)/dev/ds/patterns/modal/page.tsx +++ b/src/app/(mobile-ui)/dev/ds/patterns/modal/page.tsx @@ -11,9 +11,11 @@ import { DocSection } from '../../_components/DocSection' import { SectionDivider } from '../../_components/SectionDivider' import { DocPage } from '../../_components/DocPage' import { CodeBlock } from '../../_components/CodeBlock' +import EasterEggModal from '@/components/Global/EasterEggModal' export default function ModalPage() { const [showModal, setShowModal] = useState(false) + const [showEasterEgg, setShowEasterEgg] = useState(false) const [showActionModal, setShowActionModal] = useState(false) const [actionCheckbox, setActionCheckbox] = useState(false) @@ -322,6 +324,43 @@ export default function ModalPage() { + + + + {/* Easter Egg Modal */} + + +

+ Fun modal shown when users tap uninhabited/weird countries (Antarctica, Bouvet Island, etc.) in + the country selector. Uses base Modal with an image and humorous caption. +

+ +
+ + setShowEasterEgg(false)} + countryCode="AQ" + /> +
+
+ + + setShowEasterEgg(false)} + countryCode="AQ" +/>`} + /> + +
) } diff --git a/src/components/Common/CountryList.tsx b/src/components/Common/CountryList.tsx index cdb2c06d2..a97292872 100644 --- a/src/components/Common/CountryList.tsx +++ b/src/components/Common/CountryList.tsx @@ -13,6 +13,7 @@ import { getCardPosition } from '../Global/Card/card.utils' import { useGeoLocation } from '@/hooks/useGeoLocation' import { CountryListSkeleton } from './CountryListSkeleton' import AvatarWithBadge from '../Profile/AvatarWithBadge' +import EasterEggModal, { EASTER_EGG_COUNTRIES } from '@/components/Global/EasterEggModal' import StatusBadge from '../Global/Badges/StatusBadge' import Loading from '../Global/Loading' import { useSearchParams } from 'next/navigation' @@ -69,6 +70,9 @@ export const CountryList = ({ const [clickedCountryId, setClickedCountryId] = useState(null) const { isBridgeSupportedCountry: isBridgeSupportedCountryHook } = useIdentityVerification() + // easter egg modal state + const [easterEggCountry, setEasterEggCountry] = useState(null) + const supportedCountries = countryData.filter((country) => country.type === 'country') // sort countries based on user's geo location, fallback to alphabetical order @@ -179,18 +183,26 @@ export const CountryList = ({ customRight ?? (showLoadingState && clickedCountryId === country.id ? ( - ) : !isSupported ? ( + ) : !isSupported && !EASTER_EGG_COUNTRIES[country.id] ? ( ) : undefined) } description={country.currency} onClick={() => { + // check for easter egg countries first + if (EASTER_EGG_COUNTRIES[country.id]) { + setEasterEggCountry(country.id) + return + } // set loading state immediately for visual feedback setClickedCountryId(country.id) onCountryClick(country) }} position={position} - isDisabled={!isSupported || clickedCountryId === country.id} + isDisabled={ + (!isSupported && !EASTER_EGG_COUNTRIES[country.id]) || + clickedCountryId === country.id + } leftIcon={
)} + + {/* Easter egg modal for weird/uninhabited countries */} + setEasterEggCountry(null)} + countryCode={easterEggCountry ?? ''} + />
) } diff --git a/src/components/Global/EasterEggModal/index.tsx b/src/components/Global/EasterEggModal/index.tsx new file mode 100644 index 000000000..835dd30eb --- /dev/null +++ b/src/components/Global/EasterEggModal/index.tsx @@ -0,0 +1,98 @@ +'use client' + +import ActionModal from '@/components/Global/ActionModal' +import Image from 'next/image' + +export interface EasterEggCountryConfig { + image: string + caption: string + subtitle: string +} + +/** + * Easter egg countries — these places have no banking infrastructure, + * so we show a fun modal instead of the normal flow. + */ +export const EASTER_EGG_COUNTRIES: Record = { + AQ: { + image: '/easter-eggs/antarctica.png', + caption: '🐧 No banks here, only penguins!', + subtitle: "Antarctica isn't a real country... yet", + }, + BV: { + image: '/easter-eggs/bouvet.png', + caption: '🧊 Population: 0. Banks: also 0.', + subtitle: 'An uninhabited Norwegian glacier in the South Atlantic', + }, + CX: { + image: '/easter-eggs/christmas.png', + caption: "šŸ¦€ Red crabs don't need bank accounts", + subtitle: '45 million crabs, zero ATMs', + }, + CC: { + image: '/easter-eggs/cocos.png', + caption: '🄄 Coconuts accepted, wire transfers not so much', + subtitle: 'Population: 544. Financial infrastructure: vibes', + }, + GS: { + image: '/easter-eggs/southgeorgia.png', + caption: '🐧 More penguins than people', + subtitle: 'South Georgia: 30 researchers, 3 million penguins, 0 banks', + }, + HM: { + image: '/easter-eggs/heard.png', + caption: 'šŸŒ‹ Active volcano, inactive banking sector', + subtitle: 'Heard Island: uninhabited, unless you count the seals', + }, + PN: { + image: '/easter-eggs/pitcairn.png', + caption: 'šŸ“\u200dā˜ ļø 47 people. 0 ATMs. All vibes.', + subtitle: "The world's least populated jurisdiction with a .pn domain", + }, + TK: { + image: '/easter-eggs/tokelau.png', + caption: '🌊 No roads, no banks, no problem', + subtitle: 'Three atolls, 1,500 people, and the .tk domain empire', + }, +} + +interface EasterEggModalProps { + visible: boolean + onClose: () => void + countryCode: string +} + +const EasterEggModal = ({ visible, onClose, countryCode }: EasterEggModalProps) => { + const config = EASTER_EGG_COUNTRIES[countryCode] + if (!config) return null + + return ( + + } + iconContainerClassName="size-auto rounded-none bg-transparent w-full" + ctas={[ + { + text: 'Got it', + variant: 'stroke', + shadowSize: '4', + onClick: onClose, + }, + ]} + /> + ) +} + +export default EasterEggModal