Compare commits

...

169 Commits

Author SHA1 Message Date
Jordan Frankfurt
3bc7f015ee fix: add two more analytics events for m parity (#5748)
* fix: add two more analytics events for m parity

* pr feedback
2022-12-22 11:26:34 -06:00
lynn
802714377c fix: display warning / reload prompt modal when metamask erroneously disconnects (#5722)
* init

* hook up modal to error detection

* zzmp comments

* zzmp fixes
2022-12-21 18:32:34 -05:00
Mike Grabowski
352daf959e feat: enable Sentry (#5758) 2022-12-22 02:44:04 +04:00
Mike Grabowski
92c21c2811 feat: better UX when Sentry disabled (#5695)
* feat: disable sentry

* chore: update error page

* chore: use continue on error instead

* chore: wrap in trans

* flip check
2022-12-22 00:39:29 +04:00
lynn
e70723aaf3 fix: add missing amplitude sell events (#5530)
* in progress

* add events

* remove debug

* update analytics pkg

* removed signatures requested

Co-authored-by: Charles Bachmeier <charlie@genie.xyz>
2022-12-21 11:19:38 -08:00
Mike Grabowski
1802f50163 chore: use @uniswap eslint preset (#5556)
* feat: replace eslint with preset

* chore: update

* add empty line

* Revert changes

* chore: replace colors

* chore: tweaks

* Revert "chore: replace colors"

This reverts commit 3462420ecb.

* bring lint back

* chore: tweaks

* chore: add note

* chore: fix yarn lock

* chore: fix yarn.lock 2

* chore: use ESLint from npm

* Chore: update lockfile

* tweaks

* chore: initial take fixing some lint issues

* tweaks

* chore: another take

* chore: further tweaks

* chore: fix further

* feat: ignore Jest for cypress

* revert change

* chore: update to latest preset

* tmp lets see if this works

* chore: turn error into warning

* chore: remove warnings

* chore: deduplicate yarn lock

* feat: add recommended ESLint extension in case someone has Prettier instead

* upgrade to latest uniswap config

* chore: update todo

* remove patch

* find to some

* name

* chore: tweak yarn lock

* update

* cleanup

* update name for filter

* nl

* no unsafe finally

* chore: update doc

* fix

* fix

* one more fix

* one more file

* chore: Fix two last build issues

* add generated back

* fix lint after merge

* chore: fix tests

* remove

* one more
2022-12-21 03:08:20 +04:00
Charles Bachmeier
2aa1b18d14 chore: Migrate from Relay to Apollo (#5754)
* feat: initial apollo configutation (#5565)

* initial apollo configutation

* add new files

* check in types-and-hooks

* config unused export

* deduplicate

* ignore checked in schema for linting

* remove prettier ignore

* test unchecking types and hooks file

* undo

* rename codegen, respond to comments

Co-authored-by: Charles Bachmeier <charlie@genie.xyz>

* Remove maybe value from codegen

* add babel gql codegen

* correct ts graphql-tag

* remove plugin from craco

* chore: migrate Assets Query to Apollo (#5665)

* chore: migrate Assets Query to Apollo

* delete comment

* move length check back to collectionAssets

* remove uneeded check

* respond to comments

* working switching and filters

* change sweep fetch policy

Co-authored-by: Charles Bachmeier <charlie@genie.xyz>

* chore: migrate collection query to apollo (#5647)

* migrate collection query to apollo

* remove page level suspense

* undo removing page level suspense

* rename query and hook

* guard returns

* add return type prop

* cleanup nullables

* memoizing

* use gql from apollo

* use babel gql and move empty trait

* add fetch policy

Co-authored-by: Charles Bachmeier <charlie@genie.xyz>

* chore: migrate NFT details query to apollo (#5648)

* chore: migrate NFT details query to apollo

* update todo

* update imports

* remove no longer used hook

* rename query

* use babel gql and nonnullable type

* working page

* add fetchpolicy

* respond to comments

Co-authored-by: Charles Bachmeier <charlie@genie.xyz>

* chore: migrate NftBalanceQuery (#5653)

* chore: migrate NftBalanceQuery

* cleanup

* update pagination

* better undefined handling

* move brake listing for invalid asset higher

* better handle loading

* memoize and cleanup

Co-authored-by: Charles Bachmeier <charlie@genie.xyz>

* remove named gql query consts

* set default fetchPolicy

* null suspense

* chore: Migrate The Graph queries (#5727)

* migrate TheGraph queries to Apollo

* add new files

* ignore thegraph generated types

* use standard fetchPolicy

* update apollo codegen commands

Co-authored-by: Charles Bachmeier <charlie@genie.xyz>

* chore: migrate token queries to Apollo (#5682)

* migrate utils to types-and-hooks

* too many TokenTable re-renders

* working token queries

* fixed sparkline for native asset

* onChangeTimePeriod

* define inline

* use query instead of data in naming

* sparklineQuery instead of sparklineData

* rename to usePriceHistory

* multiline if else

* remove optional

* remove unneeded eslint ignore

* rename tokenQueryLoading

* rename OnChangeTimePeriod

* token address fallback

* just address

Co-authored-by: Charles Bachmeier <charlie@genie.xyz>

* chore: deprecate Relay (#5747)

* chore: deprecate Relay

* remove graph:ql generate step

* add new files

* apollo to graphql centric naming

* add new files

Co-authored-by: Charles Bachmeier <charlie@genie.xyz>

* remove no longer needed config exclusions

Co-authored-by: Charles Bachmeier <charlie@genie.xyz>
2022-12-20 13:42:52 -08:00
Vignesh Mohankumar
a286e5b114 test: disable fiat announcement on cypress tests (#5751)
* test: disable fiat announcement on cypress tests

* Revert "test: skip tests due to fiat on-ramp change (#5742)"

This reverts commit 283479f76e.

* dismissed
2022-12-20 15:36:57 -05:00
Vignesh Mohankumar
62361647e0 fix: use localStorage for Fiat announcement (#5750)
* fix: use localStorage for Fiat announcement

* move to redux

* rm locally

* lint

* add change to hook

* fixes
2022-12-20 15:21:52 -05:00
Vignesh Mohankumar
deee278439 chore: remove unused isOpen state in Landing (#5732)
Co-authored-by: eddie <66155195+just-toby@users.noreply.github.com>
2022-12-20 14:55:18 -05:00
Vignesh Mohankumar
6340deb201 chore: remove unused NFT redux user reducer state (#5753) 2022-12-20 14:55:08 -05:00
Vignesh Mohankumar
28b154ebe8 chore: remove landing redirect flag (#5736)
* test: add tests for landing redirect

* test: add tests for landing page (#5737)

* test: add tests for landing page

* lint

* intro=true

* rm downloads?

* fix: use second config option for no wallet in cypress

Co-authored-by: Eddie Dugan <eddie.dugan@uniswap.org>

Co-authored-by: Eddie Dugan <eddie.dugan@uniswap.org>
2022-12-20 14:54:56 -05:00
aballerr
3bde2165f4 fix: modal was removed, updating test to accommodate (#5749)
nft modal was removed, updating cypress to accommodate
2022-12-20 14:47:15 -05:00
Jack Short
78c8fd2359 style: updating cards to use appropriate aspect ratio (#5681)
* style: updating cards to use appropriate aspect ratio

* loading card height

* audio and video cards

* change loading height rendering

* respond to self serving comments

Co-authored-by: Charles Bachmeier <charlie@genie.xyz>
2022-12-20 11:10:54 -08:00
eddie
c378752910 feat: fiat on ramp tile for about page (#5746)
* feat: move about content into landing page

* fix: delete unused image files

* fix: remove unused components

* fix: pointer events on title and subtitle

* feat: add about footer to landing page

* fix: simplify css in Landing Page

* feat(moonpay): moonpay ip checks to determine if the user can access the fiat onramp (#10)

* feat(moonpay): useFiatOnrampAvailable

* feat(moonpay): ip check with moonpay for buy crypto availability

* add error state and clear up some of the sequence of logic

* add button-specific spinner, put the ... menu button behind the feature flag

* hide ... menu option if onramp is unavailable

* add live publishable moonpay key

* add initial FoR hype border flash to announcement acknowledgment

* remove ... menu access to FoR feature

* add tooltip and external link to info icon

* nicer error display

* add stale market to ack

* pr feedback from zzmp

* fix really weird react bug

* ts fix and clear timeout

* pairing staleness handler w/ zzmp

* add back feature flag

* feat: fiat on ramp tile for about page

Co-authored-by: Jordan Frankfurt <jordanwfrankfurt@gmail.com>
2022-12-20 13:23:29 -05:00
eddie
0bf7b92013 feat: move about content into landing page (#5734)
* feat: move about content into landing page

* fix: delete unused image files

* fix: remove unused components

* fix: pointer events on title and subtitle

* feat: add about footer to landing page

* fix: simplify css in Landing Page

* feat(moonpay): moonpay ip checks to determine if the user can access the fiat onramp (#10)

* feat(moonpay): useFiatOnrampAvailable

* feat(moonpay): ip check with moonpay for buy crypto availability

* add error state and clear up some of the sequence of logic

* add button-specific spinner, put the ... menu button behind the feature flag

* hide ... menu option if onramp is unavailable

* add live publishable moonpay key

* add initial FoR hype border flash to announcement acknowledgment

* remove ... menu access to FoR feature

* add tooltip and external link to info icon

* nicer error display

* add stale market to ack

* pr feedback from zzmp

* fix really weird react bug

* ts fix and clear timeout

* pairing staleness handler w/ zzmp

* add back feature flag

Co-authored-by: Jordan Frankfurt <jordanwfrankfurt@gmail.com>
2022-12-20 13:07:46 -05:00
Jordan Frankfurt
283479f76e test: skip tests due to fiat on-ramp change (#5742)
skip tests
2022-12-20 12:31:11 -05:00
Vignesh Mohankumar
d3c30e2f6b docs: update buying crypto helpcenter link (#5744)
* docs: update buying crypto helpcenter link

* new link

* new link
2022-12-20 12:30:32 -05:00
Jordan Frankfurt
32d226f78e feat: enable FoR flag (#5741) 2022-12-20 11:50:00 -05:00
Jordan Frankfurt
96744505c0 Merge pull request #5740 from Uniswap/FoR-publish
feat: FoR publish
2022-12-20 10:40:36 -06:00
Jordan Frankfurt
97236033d4 conditional access of .renderCount 2022-12-20 10:27:52 -06:00
Jordan Frankfurt
86e62dc4b9 add back feature flag 2022-12-20 09:56:15 -06:00
Vignesh Mohankumar
e584a5fa36 chore: removes unused Liquidity Mining code (#5451)
* feat: remove unused liquidity mining pages

* some changes

* rm more
2022-12-19 20:06:59 -05:00
Vignesh Mohankumar
332ef6e6c8 chore: remove /#/claim (#5445)
rm claim
2022-12-19 19:46:36 -05:00
Jordan Frankfurt
8cbd111e65 Merge pull request #8 from Uniswap/merge-upstream
chore: Merge upstream
2022-12-19 15:25:10 -06:00
Jordan Frankfurt
55ffcbd465 Merge remote-tracking branch 'upstream/main' into merge-upstream 2022-12-19 15:12:16 -06:00
Jordan Frankfurt
404775e86d Merge pull request #7 from Uniswap/analytics-account-dropdown-click
chore: analytics account dropdown click
2022-12-19 15:10:15 -06:00
Vignesh Mohankumar
0ae9fe28a2 feat: force landing page to show based on landing query param (#5730)
* feat: force landing page to show based on `landing` query param

* flag

* use intro

* lint
2022-12-19 15:49:42 -05:00
Vignesh Mohankumar
89c0caae43 feat: push nav icon to /?intro=true (#5731)
* feat: push nav icon to /?intro=true

* search
2022-12-19 15:48:53 -05:00
Vignesh Mohankumar
c8086e3c76 fix: wait to render Landing content until checking wallet cache (#5729)
* fix: wait to render Landing content until checking wallet cache

* use state
2022-12-19 15:22:13 -05:00
Jordan Frankfurt
1c2842e5a0 chore: analytics account dropdown click 2022-12-19 14:21:50 -06:00
Vignesh Mohankumar
a2c6d3f475 feat: navigate to /swap if user has a wallet cached (#5728)
* feat: navigate to /swap if user has a wallet cached

* flag it
2022-12-19 14:55:51 -05:00
Jordan Frankfurt
841ea7f8a1 Merge pull request #6 from Uniswap/fix-menu-z-index
fix: landing page overlay occlusion of Z_INDEX.dropdown
2022-12-19 13:49:10 -06:00
aballerr
804692b114 fix: adding fixed header (#5712)
*  adding fixed header
2022-12-19 14:26:07 -05:00
Vignesh Mohankumar
6282298d13 chore: add landing page redirect flag (#5724)
* chore: add landing page redirect flag

* unused

* fix
2022-12-19 13:38:03 -05:00
eddie
7a5b855097 chore: bump version of @uniswap/analytics-events (#5726) 2022-12-19 13:36:42 -05:00
Jordan Frankfurt
c9908748cf make under-dropdown 990 2022-12-19 12:24:43 -06:00
Jordan Frankfurt
79b77deee1 fix: bump conedison (#5725) 2022-12-19 12:15:16 -06:00
Jordan Frankfurt
a554af6670 pr feedback 2022-12-19 11:39:29 -06:00
lynn
1843f214b1 fix: hover button states (#5553)
* init but this looks wrong based on figma

* init

* fix props

* add back children
2022-12-19 12:18:25 -05:00
Jordan Frankfurt
3e0788092e Merge pull request #5 from Uniswap/geocheck-analytics
feat: add analytics for moonpay ip check
2022-12-19 11:13:30 -06:00
Jordan Frankfurt
d14c49df0d fix: landing page overlay occlusion of Z_INDEX.dropdown 2022-12-19 11:03:03 -06:00
eddie
c098ad1ffe fix: correct font size for the trade rate to on safari (#5714)
* fix: correct font size for the trade rate to on safari

* fix: use themedText.BodySmall for this label
2022-12-19 09:27:43 -05:00
Jordan Frankfurt
48114ef51d feat: add analytics for moonpay ip check 2022-12-18 09:48:38 -06:00
aballerr
4529e3cc88 fix: failing cypress test (#5715)
* fix failing cypress test for 404 page
2022-12-16 16:49:23 -05:00
Jordan Frankfurt
cb7132ee17 Merge pull request #3 from Uniswap/FoR-main
feat: FoR commits from mgtm repo
2022-12-16 11:10:30 -06:00
Mike Grabowski
4d47470f33 feat: not found page (#5708)
* chore: save

* save

* chore: finish

* chore: Fix link

* chore: remove div

* chore: tweaaks

* chore: tweaks
2022-12-16 11:21:29 -05:00
eddie
aedc020646 fix: use render function for SearchBar placeholder translation (#5710)
* fix: use render function for SearchBar placeholder translation

* fix: use render function for SearchBar placeholder translation

* fix: correct clsx usage
2022-12-16 11:07:42 -05:00
Jordan Frankfurt
0fa4859a09 6a47ac3c231a42a00ffee40677c46bf612e14187 2022-12-15 17:39:38 -06:00
Jordan Frankfurt
f8bb5046f0 73ad9987e4b337987f8e3cb2ef861bf03c42cc67 2022-12-15 17:37:58 -06:00
Jordan Frankfurt
7d1589d1df fixing from cherry-pick process 2022-12-15 17:05:06 -06:00
Jordan Frankfurt
26b603cc2e fix: update moonpay supported currencies list (#57)
lint
2022-12-15 16:34:05 -06:00
Jordan Frankfurt
ece68a0ec7 fix: close wallet modal on connection (#53)
fix: hide celo on uniswap wallet connections (#48)

* fix: hide celo on uniswap wallet connections

* add disabled UI instead of removing network from list

Revert "fix: hide celo on uniswap wallet connections (#48)"

This reverts commit b22d82545fef6812b22fe1adc3f281588642c9cd.
2022-12-15 15:32:21 -06:00
Jordan Frankfurt
fd212477ce fix: json.stringify addresses (#52) 2022-12-15 15:32:20 -06:00
Jordan Frankfurt
a16d2387cc fix: FoR polish (#47)
* fix: remove currencyCode config property from moonpay url

* add 8px padding to moonpay iframe

* don't switch button text when loading

* update tooltip text

* update announcement text

* remove FoR announcement on iOS mobile

* improve fiat quote format in account dropdown

fix: typo (#51)
2022-12-15 15:32:20 -06:00
Jordan Frankfurt
cae56ec385 feat: add supported currency list to moonpay config (#45) 2022-12-15 15:32:20 -06:00
Jordan Frankfurt
d16b3473e0 fix: remove currencyCode config property from moonpay url (#40) 2022-12-15 15:32:20 -06:00
Jordan Frankfurt
f66f249dba fix: fiat onramp polish (#36)
* fix: fiat onramp polish

* add 3 session render cap on FoR announcement
2022-12-15 15:32:20 -06:00
Jordan Frankfurt
08afd888d0 fix(moonpay): add ?platform=web to moonpay env vars (#35) 2022-12-15 15:32:20 -06:00
Jordan Frankfurt
b427be2673 feat(moonpay): moonpay ip checks to determine if the user can access the fiat onramp (#10)
* feat(moonpay): useFiatOnrampAvailable

* feat(moonpay): ip check with moonpay for buy crypto availability

* add error state and clear up some of the sequence of logic

* add button-specific spinner, put the ... menu button behind the feature flag

* hide ... menu option if onramp is unavailable

* add live publishable moonpay key

* add initial FoR hype border flash to announcement acknowledgment

* remove ... menu access to FoR feature

* add tooltip and external link to info icon

* nicer error display

* add stale market to ack

* pr feedback from zzmp

* fix really weird react bug

* ts fix and clear timeout

* pairing staleness handler w/ zzmp
2022-12-15 15:32:20 -06:00
Jordan Frankfurt
f753a5e325 feat(moonpay): add iframe (#9)
* feat(moonpay): add iframe

* add prod url

* polish iframe styles and supply the firebase fn with the new platform query param

* pr feedback

* pr feedback - .production env key distinction

feat(moonpay): add iframe (#9)

* feat(moonpay): add iframe

* add prod url

* polish iframe styles and supply the firebase fn with the new platform query param

* pr feedback

* pr feedback - .production env key distinction
2022-12-15 15:32:19 -06:00
Jordan Frankfurt
46d9d8e3df feat(fiat): announcement
cleanup

cleanup

fix close button

cleanup
2022-12-15 15:32:19 -06:00
Jordan Frankfurt
680d3a3f26 feat(fiat): add overflow menu cta 2022-12-15 15:32:19 -06:00
Jordan Frankfurt
e4c625ee71 feat(onramp): cta 2022-12-15 15:32:19 -06:00
Zach Pomerantz
fd8085722e fix: mark permit not syncing if not permitted (#5706)
* fix: mark permit not syncing if not permitted

* fix: clarify naming

* fix: show approval when loading
2022-12-15 13:09:39 -08:00
Mike Grabowski
a60a85db54 fix: layout padding/margin & overflow (#5707)
* chore: fix

* chore: tweaks
2022-12-15 15:34:39 -05:00
eddie
ad2472eac6 fix: correct color for selected token in CurrencySearchModal (#5705)
Co-authored-by: Eddie Dugan <eddie.dugan@UniswapdieDugan.localdomain>
2022-12-15 15:14:16 -05:00
eddie
f4d4acacae fix: constrain width on token details back button (#5703)
Co-authored-by: Eddie Dugan <eddie.dugan@UniswapdieDugan.localdomain>
2022-12-15 14:46:04 -05:00
lynn
a5d7af192c fix: Web 1610 token details another funky state chart re prices (#5685)
* initial commit

* fixes

* move msg loc depending on display price avail

* fred copywriting + jordan comments changes

* fix build errors

Co-authored-by: cartcrom <cartergcromer@gmail.com>
2022-12-15 14:23:03 -05:00
Zach Pomerantz
21a2863ae3 build: default flags but maintain togglability (#5702)
fix: default flags but maintain togglability
2022-12-15 10:56:06 -08:00
Zach Pomerantz
1f871d4e73 build: upgrade widget to 2.22.11 (#5701) 2022-12-15 10:49:31 -08:00
Vignesh Mohankumar
3690936aff chore: remove landing page flag (#5673) 2022-12-15 13:48:50 -05:00
Vignesh Mohankumar
e95e2321b4 fix: used sticky position for landing page content (#5699)
* fix: update padding to 80px on mobile landing

* try 100

* try 120

* 140

* try sticky
2022-12-15 13:29:55 -05:00
Zach Pomerantz
8b1bf09ff1 fix: await syncing allowance to update permit state (#5689)
* fix: await syncing allowance to update permit state

* fix: clarify isSyncing on Permit2

* fix: further clarify isApprovalSyncing
2022-12-15 09:48:18 -08:00
aballerr
6383e9e4bf fix: reverting some changes to wallet dropdown (#5694)
reverting some changes to wallet dropdown cypress tests
2022-12-15 12:15:44 -05:00
Vignesh Mohankumar
515ce9253d fix: add more padding-bottom on mobile landing page (#5696) 2022-12-15 11:06:17 -05:00
Vignesh Mohankumar
23ed384802 fix: Revert "fix: allow landing page scroll" (#5697)
Revert "fix: allow landing page scroll (#5692)"

This reverts commit 642c489240.
2022-12-15 11:05:53 -05:00
Mike Grabowski
9ae31aa26e build: update name for revert github action (#5693)
chore: update name for revert github action
2022-12-15 07:50:46 -08:00
Vignesh Mohankumar
642c489240 fix: allow landing page scroll (#5692) 2022-12-15 10:32:13 -05:00
aballerr
778ea8ee42 test: adding in some basic token tests (#5686)
* adding in some basic token tests
2022-12-15 10:16:15 -05:00
Vignesh Mohankumar
36900fe6c6 test: skip wallet dropdown tests (#5691) 2022-12-15 09:55:55 -05:00
Vignesh Mohankumar
40eb28f1e1 build: change cypress timeout to 24s (#5690) 2022-12-15 09:29:47 -05:00
Mike Grabowski
7c3ee78715 chore: replace deprecated colors with correct theme values [part 1] (#5563)
* chore: replace colors

* add missing line

* chore: fix lint after replacing colors

Co-authored-by: Vignesh Mohankumar <vignesh@vigneshmohankumar.com>
2022-12-14 16:46:56 -05:00
Vignesh Mohankumar
ccac51ec1f chore: turn landing page flag on (#5684)
Revert "chore: turn landing page flag off (#5679)"

This reverts commit 0176c74430.
2022-12-14 16:19:47 -05:00
Jack Short
77747f9f6f style: updating bag (#5539)
* style: updating bag

* desktop bag

* initial setup

* bag animations

* mobile stylings

* removing vanilla extract components

* background position

* design comments

* screen sizing

* closing filters and bag on appropriate screen sizes

* move screen size to main hooks

* prettier

* bag margins

* footer outline

* correct scrolling indicator width

* collection stats truncation

* merged with main

* collection stats on screen
2022-12-14 13:27:41 -05:00
Vignesh Mohankumar
0622ff30f6 fix: remove learn more link on landing page (#5683)
* fix: remove learn more link on landing page

* lowercase
2022-12-14 12:09:14 -05:00
aballerr
982c99b07f chore: Nft cypress tests 2 (#5658)
* adding in final set of nft cypress tests
2022-12-14 10:09:55 -05:00
aballerr
484a7d49f6 fix: allow empty states on days in listing (#5675)
allow empty states on days
2022-12-14 09:23:36 -05:00
lynn
082591d5dd fix: jumpy nav on safari mweb (#5668)
* test

* swap page nav bar on mobile looks weird without this change

* fixes
2022-12-14 08:56:36 -05:00
Zach Pomerantz
aa03f97890 build: add a revert workflow (#5680) 2022-12-13 17:29:02 -05:00
Zach Pomerantz
fd12a0d6e7 fix: display impact before severity (#5678) 2022-12-13 16:43:06 -05:00
Vignesh Mohankumar
0176c74430 chore: turn landing page flag off (#5679) 2022-12-13 16:39:35 -05:00
Vignesh Mohankumar
35613cc979 feat: amplitude analytics for landing and about (#5606)
* add events - no names yet

* lint fix

* events

* link

* more into card

* fix

* switch
2022-12-13 15:54:21 -05:00
Jack Short
b0d71f10e9 chore: adding useScreenSize hook (#5669)
* feat: adding useScreenSize hook

* updating isTablet

* adding comments
2022-12-13 14:22:24 -05:00
Vignesh Mohankumar
1cfb3d8034 feat: release new landing page (#5596)
* feat: release new landing page

* fix wallet dropdown integration tests

* remove problematic/not useful tests

Co-authored-by: Jordan Frankfurt <jordanwfrankfurt@gmail.com>
2022-12-13 13:40:56 -05:00
Zach Pomerantz
a650807c96 fix: correctly center navbar els (#5676) 2022-12-13 13:17:48 -05:00
Vignesh Mohankumar
6efd7ca779 build: re-start scheduled builds (#5674)
Revert "build: pause scheduled releases (#5615)"

This reverts commit 185c1f6772.
2022-12-13 12:32:43 -05:00
aballerr
d658720505 chore: initial set of cypress tests for nft (#5590)
* initial set of cypress tests for nft
2022-12-13 11:43:02 -05:00
Zach Pomerantz
bba40846e1 build: upgrade widget to 2.22.10 (#5666) 2022-12-12 15:54:40 -05:00
pp-hh-ii-ll
8fa6c87015 fix: responsive styles for steps (#5651)
* feat: styled footer links

* grid

* center

* Update bottom links and full bleed image

* Mobile spacing and font size adjustments

Decrease spacing in mobile and swap the sizing of fonts between mobile and desktop sizes

* Add responsive behavior to steps

Changes font size and margins in mobile view

Co-authored-by: Vignesh Mohankumar <me@vig.xyz>
Co-authored-by: Callil Capuozzo <callil.capuozzo@gmail.com>
2022-12-12 15:35:06 -05:00
pp-hh-ii-ll
933d02b275 fix: responsive styling for info buttons (#5652)
Responsive styling for info buttons

Reduces margins and font size in mobile view
Adds some margin to the side of the external-link arrow

Co-authored-by: Vignesh Mohankumar <vignesh@vigneshmohankumar.com>
2022-12-12 14:59:23 -05:00
Zach Pomerantz
7738a6b9e0 fix: vertically center-align navbar items (#5664) 2022-12-12 14:50:21 -05:00
Vignesh Mohankumar
2db4b1da3d fix: remove period on landing page title (#5663) 2022-12-12 14:22:25 -05:00
Zach Pomerantz
06c85b744f fix: show error when present (not approval) (#5662) 2022-12-12 13:51:38 -05:00
Callil Capuozzo
aa29ea80a9 fix: tweak landing page buttons (#5661)
* Tweak landing details

* flex

Co-authored-by: Vignesh Mohankumar <me@vig.xyz>
2022-12-12 13:45:28 -05:00
pp-hh-ii-ll
3613dc2d4a style: add transition to button and move gradient up (#5660)
Add transition to button and move gradient up

Moves gradient up to obscure more of the swap box
2022-12-12 13:33:22 -05:00
pp-hh-ii-ll
e22554b4c4 fix: responsive styling for info button (#5659)
Responsive styling for info button

Decreases gap and font size and adds margin to external link arrow icon
2022-12-12 12:55:25 -05:00
pp-hh-ii-ll
5f1625f5dc fix: update outline button to use non-deprecated colors (#5657)
Update outline button to use non-deprecated colors

Quick fix for about page – full refactor to come later
2022-12-12 11:48:01 -05:00
pp-hh-ii-ll
c1e6dd7335 fix: Add hover state to footer link (#5656)
* Add hover state to footer link

* Update hover outline to textTertiary

Don't use deprecated color
2022-12-12 11:45:46 -05:00
pp-hh-ii-ll
45419c2739 fix: responsive behavior for info cards (#5655)
Responsive behavior for info cards

Decreases margin, font size, card height, and grid gap in mobile
2022-12-12 11:40:09 -05:00
Mike Grabowski
c2342a86d6 fix: pointer events on Swap (#5654)
* feat: decouple landing from swap

* implement pointer events
2022-12-12 11:23:55 -05:00
Zach Pomerantz
504cd5b848 build: bump widgets/universal-router-sdk (#5582)
* build(deps): bump @uniswap/widgets from 2.22.0 to 2.22.2

Bumps [@uniswap/widgets](https://github.com/Uniswap/widgets) from 2.22.0 to 2.22.2.
- [Release notes](https://github.com/Uniswap/widgets/releases)
- [Changelog](https://github.com/Uniswap/widgets/blob/main/.releaserc.json)
- [Commits](https://github.com/Uniswap/widgets/compare/v2.22.0...v2.22.2)

---
updated-dependencies:
- dependency-name: "@uniswap/widgets"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* build(deps): bump @uniswap/widgets to 2.22.5

* fix(snyk): ack oz vulns

* build(deps): bump @uniswap/widgets to 2.22.9

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-12 11:21:22 -05:00
Vignesh Mohankumar
1faf13639c feat: styled footer links (#5644)
* feat: styled footer links

* grid

* center

* Update bottom links and full bleed image

* Mobile spacing and font size adjustments

Decrease spacing in mobile and swap the sizing of fonts between mobile and desktop sizes

Co-authored-by: Callil Capuozzo <callil.capuozzo@gmail.com>
Co-authored-by: pp-hh-ii-ll <111304124+pp-hh-ii-ll@users.noreply.github.com>
2022-12-12 11:18:58 -05:00
Vignesh Mohankumar
69c084ebe7 fix: full bleed about banner (#5650)
* fix: full bleed about banner

* add px
2022-12-12 11:12:59 -05:00
Zach Pomerantz
e5ac7e77da fix: observe submitted allowance immediately (#5620)
Fixes a bug where a user could submit a transaction, but would be required to re-sign a permit for a subsequent transaction, because the prior transaction's modification of allowance was not detected.
2022-12-12 11:02:12 -05:00
Vignesh Mohankumar
0614358a5e feat: close landing page when wallet connected (#5639) 2022-12-12 10:39:38 -05:00
pp-hh-ii-ll
42784e6121 fix: update card images (#5649)
update card images

Update card images to improve legibility
2022-12-12 10:37:58 -05:00
Vignesh Mohankumar
830500dc3b fix: use background-size cover for about banner (#5641) 2022-12-12 10:36:41 -05:00
Vignesh Mohankumar
5af32592aa fix: about button copy change (#5638) 2022-12-12 09:36:02 -05:00
Vignesh Mohankumar
0f36a99e98 fix: remove period in about copy (#5643) 2022-12-12 09:29:01 -05:00
Callil Capuozzo
5fe9f3f6e8 fix: add light mode images and gradient mask (#5640)
* add light mode image and gradient mask

* fix-image-bleed

* clean up

* rm todo
2022-12-11 21:21:04 -05:00
Vignesh Mohankumar
167fff16a0 fix: remove period in landing page copy (#5637) 2022-12-11 18:33:36 -05:00
Vignesh Mohankumar
a6eff7823a fix: make background header a background-image (#5635)
* fix: make background header a background-image

* fit differently
2022-12-11 17:37:50 -05:00
Mike Grabowski
1aba4fbcd7 feat: add glow to landing page (#5636)
* chore: adjust z-index on the linear gradient

* feat: add blur

* fix: heights and paddings

* chore: abstract values into sep variable

* chore: remove bg

* chore: tweaks
2022-12-11 17:30:58 -05:00
Vignesh Mohankumar
714d215cda feat: add about card backgrounds (#5634)
* fix: update landing page paddings

* feat: add about card backgrounds

* fix
2022-12-11 17:30:45 -05:00
Vignesh Mohankumar
0f32ed34f7 fix: update landing page paddings (#5633) 2022-12-11 14:49:16 -05:00
Vignesh Mohankumar
3703e843f8 fix: improve mobile spacing/ordering on /about (#5632) 2022-12-11 14:42:32 -05:00
Vignesh Mohankumar
3c3158f443 fix: update landing page paddings (#5630)
* fix: update landing page paddings

* button gap
2022-12-11 14:33:41 -05:00
Vignesh Mohankumar
f933e538e6 feat: add background image to /about (#5623)
* feat: add background image to /about

* 100% height
2022-12-11 14:33:09 -05:00
Vignesh Mohankumar
02b678b4a9 fix: centers /about Panels (#5631)
fix: centers about Panels
2022-12-11 14:30:36 -05:00
Vignesh Mohankumar
c25a2cfc00 fix: show swap hover state on landing page (#5629)
* fix: body, #root, AppWrapper and BodyWrapper height: 100%

* fix: show swap hover state on landing page

* pointer events fix

* revert gradient change

* pointer events auto

* pointer events auto
2022-12-11 14:29:23 -05:00
Vignesh Mohankumar
a5d75cad5b fix: body, #root, AppWrapper and BodyWrapper height: 100% (#5628) 2022-12-11 14:27:00 -05:00
Vignesh Mohankumar
40784963a5 fix: copy changes for /about (#5626) 2022-12-11 14:26:46 -05:00
Vignesh Mohankumar
6ca8e4f664 fix: remove Earn and Build dApps links (#5625) 2022-12-11 14:26:32 -05:00
Vignesh Mohankumar
91c0580825 feat: add initial footer to /about (#5624) 2022-12-11 14:26:22 -05:00
Ian Lapham
c518501e7b fix: update unsupported list (#5622)
Add GOLD1 to unsupported list
2022-12-10 15:51:19 -05:00
Zach Pomerantz
d59e4f334e fix: hexlify tx value from SwapRouter (#5621)
Hexlifies the value returned from universal-router-sdk, which is required for ethers to accept it as input.
Fixes an error thrown by ethers (RE: un-hexlified data).
See Uniswap/universal-router-sdk#92 (fixed in Uniswap/universal-router-sdk#93 but not yet released).
2022-12-09 20:05:52 -05:00
pp-hh-ii-ll
4c3528a03d style: update steps (#5619)
* update steps

Add Transfer crypto step to the steps and change Swap copy

* Fix transfer tokens image

Remove shadows from transfer token image
2022-12-09 17:24:47 -05:00
pp-hh-ii-ll
ed82f9ff8a fix: color updates (#5617)
Fixed colors for cards and text
2022-12-09 17:24:41 -05:00
lynn
dd5a22ce83 feat: add inline preview of pending txn in wallet dropdown (#5616)
* it looks good

* sort by latest timestamp and show latest only

* jordan comment
2022-12-09 15:34:55 -05:00
Zach Pomerantz
185c1f6772 build: pause scheduled releases (#5615) 2022-12-09 14:18:21 -05:00
lynn
93e6b65cb3 fix: swap quote loading spinner (#5569)
* init TEMP

* it's working now but the loading spinner is being redesigned by fred

* working with fred new design

* undo unnecesary changes

* undo unnecessary change

* rspond to jordan

* more fixes

* remove %
2022-12-09 13:28:44 -05:00
lynn
965a745d5e fix: token details chart x axis and time selector style tweaks (#5613)
init
2022-12-09 12:23:29 -05:00
pp-hh-ii-ll
6d97590c0f fix: adjustments to /about font size (#5614)
* Adjustments to font size

Changes font weights and sizes of text elements in the about page

* fixes

* fixes

Co-authored-by: Vignesh Mohankumar <me@vig.xyz>
2022-12-09 11:32:37 -05:00
Vignesh Mohankumar
8e7ab6f8c3 fix: copy changes about (#5611)
* fix: make cards smaller and update font-sizes

* breakpoints

* fix: update copy/images on About
2022-12-09 11:19:33 -05:00
Vignesh Mohankumar
61729610c2 fix: update /about cards and step sizings (#5610)
* fix: make cards smaller and update font-sizes

* breakpoints
2022-12-09 10:58:48 -05:00
Vignesh Mohankumar
53860dd8e4 fix: update about preview on hover (#5607) 2022-12-09 10:30:46 -05:00
Vignesh Mohankumar
19028c1d82 fix: update About sizings (#5609) 2022-12-09 10:30:34 -05:00
Vignesh Mohankumar
6676d80707 fix: landing page font-size changes (#5608) 2022-12-09 10:27:45 -05:00
Vignesh Mohankumar
f9f804c381 feat: add page view traces for / and /about (#5594)
* feat: add page view traces for / and /about

* update analytics

* page name

* import
2022-12-08 22:56:14 -05:00
Vignesh Mohankumar
0a0b56b13d fix: center the subtext by using a container (#5599) 2022-12-08 22:29:41 -05:00
Vignesh Mohankumar
480f3f29f3 fix: handle light mode image in About step (#5601) 2022-12-08 22:29:35 -05:00
Vignesh Mohankumar
5f2072f449 fix: makes sure padding-bottom isn't overriden in Landing (#5603) 2022-12-08 22:29:23 -05:00
Vignesh Mohankumar
4e144c7fb5 chore: remove unused wallet icons (#5604) 2022-12-08 22:29:17 -05:00
Vignesh Mohankumar
cfbb6a7129 fix: light mode cards for /about (#5605)
* fix: light mode cards for /about

* transparent
2022-12-08 22:00:09 -05:00
Vignesh Mohankumar
61f03af20a fix: switch to scrollHeight and add less padding (#5600)
* fix: add less padding-top to about

* switch to scroll height

* add-200
2022-12-08 21:23:11 -05:00
Vignesh Mohankumar
5eb1274f97 feat: dynamically add padding-top on /about (#5597) 2022-12-08 20:33:17 -05:00
Vignesh Mohankumar
9eb7d45aea fix: prevent scroll on landing page (#5595)
use hook
2022-12-08 20:21:43 -05:00
Vignesh Mohankumar
2e1d4fdda1 fix: update links in /about cards (#5593) 2022-12-08 17:17:05 -05:00
Vignesh Mohankumar
e85b6e4cc6 fix: update links in /about info buttons (#5592) 2022-12-08 17:13:09 -05:00
Vignesh Mohankumar
9c334bc865 fix: tablet responsiveness on /about (#5591) 2022-12-08 16:46:39 -05:00
Vignesh Mohankumar
6a833fc740 fix: CTAButton should use white text always (#5589)
different colors
2022-12-08 16:20:10 -05:00
Vignesh Mohankumar
80ed8eb6c2 feat: /about mobile responsive (#5587)
* fix gap

* order

* update gap
2022-12-08 16:19:59 -05:00
Vignesh Mohankumar
a14d2df8e6 feat: add thumbnails to /about (#5586)
* remove these icons

* destructure

* move to constants

* update thumbnails
2022-12-08 15:21:00 -05:00
Vignesh Mohankumar
09511b06f2 feat: add selected state for about steps (#5584)
* refactor: move steps and cards into config

* selected state

* css only
2022-12-08 14:26:19 -05:00
Vignesh Mohankumar
9def686344 fix: add max-width to landing page subtext (#5585) 2022-12-08 12:59:02 -05:00
lynn
a88c083758 fix: token details loading state fixes (#5567)
* init

* no export

* respond to jordan
2022-12-08 12:55:10 -05:00
Vignesh Mohankumar
1a6cad4a8f fix: update swap description in about, remove transfer (#5583)
* fix: update swap description in about, remove transfer

* fix
2022-12-08 12:29:28 -05:00
Vignesh Mohankumar
505b3f2a20 feat: new /about page (#5578)
* update card

* copy changes

* change

* add descriptions

* move folder

* move card

* template

* powered by

* more

* wallet icons

* add initial buttons

* gap

* external

* size

* Title

* button changes

* undo

* other icons

* color

* rm border

* new icons

* font weight

* naming and gaps

* naming

* get started

* StepList

* move out step

* move title

* eslint

* import

* transition stuff

* rgb

* rm rem
2022-12-08 12:06:39 -05:00
312 changed files with 12857 additions and 4996 deletions

7
.env
View File

@@ -1,7 +1,12 @@
REACT_APP_INFURA_KEY="4bf032f2d38a4ed6bb975b80d6340847"
# These API keys are intentionally public. Please do not report them - thank you for your concern.
REACT_APP_AMPLITUDE_PROXY_URL="https://api.uniswap.org/v1/amplitude-proxy"
REACT_APP_AWS_API_REGION="us-east-2"
REACT_APP_AWS_API_ENDPOINT="https://beta.api.uniswap.org/v1/graphql"
REACT_APP_TEMP_API_URL="https://temp.api.uniswap.org/v1"
REACT_APP_SENTRY_DSN="https://a3c62e400b8748b5a8d007150e2f38b7@o1037921.ingest.sentry.io/4504255148851200"
REACT_APP_SENTRY_ENABLED=false
ESLINT_NO_DEV_ERRORS=true
REACT_APP_INFURA_KEY="4bf032f2d38a4ed6bb975b80d6340847"
REACT_APP_MOONPAY_API="https://api.moonpay.com"
REACT_APP_MOONPAY_LINK="https://us-central1-uniswap-mobile.cloudfunctions.net/signMoonpayLinkStaging?platform=web"
REACT_APP_MOONPAY_PUBLISHABLE_KEY="pk_test_DycfESRid31UaSxhI5yWKe1r5E5kKSz"

View File

@@ -1,7 +1,11 @@
REACT_APP_AMPLITUDE_PROXY_URL="https://api.uniswap.org/v1/amplitude-proxy"
REACT_APP_INFURA_KEY="099fc58e0de9451d80b18d7c74caa7c1"
REACT_APP_AWS_API_ENDPOINT="https://api.uniswap.org/v1/graphql"
REACT_APP_FORTMATIC_KEY="pk_live_F937DF033A1666BF"
REACT_APP_GOOGLE_ANALYTICS_ID="G-KDP9B6W4H8"
REACT_APP_INFURA_KEY="099fc58e0de9451d80b18d7c74caa7c1"
REACT_APP_MOONPAY_API="https://api.moonpay.com"
REACT_APP_MOONPAY_LINK="https://us-central1-uniswap-mobile.cloudfunctions.net/signMoonpayLink?platform=web"
REACT_APP_MOONPAY_PUBLISHABLE_KEY="pk_live_uQG4BJC4w3cxnqpcSqAfohdBFDTsY6E"
REACT_APP_FIREBASE_KEY="AIzaSyBcZWwTcTJHj_R6ipZcrJkXdq05PuX0Rs0"
REACT_APP_AWS_API_ENDPOINT="https://api.uniswap.org/v1/graphql"
THE_GRAPH_SCHEMA_ENDPOINT="https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v3"
REACT_APP_SENTRY_ENABLED=true

View File

@@ -1,2 +1,5 @@
*.config.ts
*.d.ts
/src/graphql/data/__generated__/types-and-hooks.ts
/src/graphql/thegraph/__generated__/types-and-hooks.ts
/src/schema/schema.graphql

7
.eslintrc.js Normal file
View File

@@ -0,0 +1,7 @@
/* eslint-env node */
require('@uniswap/eslint-config/load')
module.exports = {
extends: '@uniswap/eslint-config/react',
}

View File

@@ -1,109 +0,0 @@
{
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 2020,
"sourceType": "module",
"ecmaFeatures": {
// Allows for the parsing of JSX
"jsx": true
}
},
"settings": {
"react": {
"version": "detect"
},
"import/parsers": {
"@typescript-eslint/parser": [".ts", ".tsx"]
},
"import/resolver": {
"typescript": {
"alwaysTryTypes": true
}
}
},
"ignorePatterns": [
"src/types/v3",
"src/abis/types",
"src/locales/**/*.js",
"src/locales/**/en-US.po",
"node_modules",
"coverage",
"build",
"dist",
".DS_Store",
".env.local",
".env.development.local",
".env.test.local",
".env.production.local",
".idea/",
".vscode/",
"package-lock.json",
"yarn.lock"
],
"extends": [
"react-app",
"plugin:react/recommended",
"plugin:@typescript-eslint/recommended",
"plugin:react-hooks/recommended",
"prettier/@typescript-eslint",
"plugin:prettier/recommended",
"plugin:import/typescript"
],
"plugins": ["import", "simple-import-sort", "unused-imports"],
"rules": {
"import/no-unused-modules": [2, { "unusedExports": true }],
"unused-imports/no-unused-imports": "error",
"simple-import-sort/imports": "error",
"simple-import-sort/exports": "error",
"@typescript-eslint/explicit-function-return-type": "off",
"prettier/prettier": "error",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/ban-ts-ignore": "off",
"@typescript-eslint/explicit-module-boundary-types": "off",
"react/react-in-jsx-scope": "off",
"react/jsx-curly-brace-presence": ["error", { "props": "never", "children": "never" }],
"object-shorthand": ["error", "always"],
"no-restricted-imports": [
"error",
{
"paths": [
{
"name": "ethers",
"message": "Please import from '@ethersproject/module' directly to support tree-shaking."
},
{
"name": "styled-components",
"message": "Please import from styled-components/macro."
},
{
"name": "@lingui/macro",
"importNames": ["t"],
"message": "Please use <Trans> instead of t."
}
],
"patterns": [
{
"group": ["**/dist"],
"message": "Do not import from dist/ - this is an implementation detail, and breaks tree-shaking."
},
{
"group": ["!styled-components/macro"]
}
]
}
],
"@typescript-eslint/no-restricted-imports": [
"error",
{
"paths": [
{
"name": "@ethersproject/providers",
"message": "Please only use Providers instantiated in constants/providers to improve traceability.",
"allowTypeImports": true
}
]
}
]
}
}

View File

@@ -112,7 +112,8 @@ jobs:
githubToken: ${{ secrets.GITHUB_TOKEN }}
- name: Upload source maps to Sentry
uses: getsentry/action-release@bd5f874fcda966ba48139b0140fb3ec0cb3aabdd
uses: getsentry/action-release@bd5f874fcda966ba48139b0140fb3ec0cb3aabdd
continue-on-error: true
env:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
@@ -120,4 +121,4 @@ jobs:
with:
environment: production
sourcemaps: './build/static/js'
url_prefix: '/static/js'
url_prefix: '/static/js'

27
.github/workflows/revert.yaml vendored Normal file
View File

@@ -0,0 +1,27 @@
name: Revert
on:
# manual trigger
workflow_dispatch:
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: ./.github/actions/setup
- run: yarn prepare
- run: yarn build
- name: Setup node@16 (required by Cloudflare Pages)
uses: actions/setup-node@v3
with:
node-version: 16
- name: Update Cloudflare Pages deployment
uses: cloudflare/pages-action@364c7ca09a4b57837c5967871d64a2c31adb8c0d
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
projectName: ${{ secrets.CLOUDFLARE_PROJECT_NAME }}
directory: build
githubToken: ${{ secrets.GITHUB_TOKEN }}

1
.gitignore vendored
View File

@@ -9,7 +9,6 @@
/src/locales/**/pseudo.po
# generated graphql types
__generated__/
schema.graphql
# dependencies

View File

@@ -1 +0,0 @@
/src/schema/schema.graphql

View File

@@ -1,5 +0,0 @@
{
"semi": false,
"singleQuote": true,
"printWidth": 120
}

25
.snyk Normal file
View File

@@ -0,0 +1,25 @@
# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities.
version: v1.25.0
# ignores vulnerabilities until expiry date; change duration by modifying expiry date
ignore:
SNYK-JS-OPENZEPPELINCONTRACTS-2964946:
- '*':
reason: None Given
expires: 2099-01-01T00:00:00.000Z
created: 2022-12-08T16:25:57.347Z
SNYK-JS-OPENZEPPELINCONTRACTS-2958047:
- '*':
reason: None Given
expires: 2099-01-01T00:00:00.000Z
created: 2022-12-08T16:26:09.720Z
SNYK-JS-OPENZEPPELINCONTRACTS-2958050:
- '*':
reason: None Given
expires: 2099-01-01T00:00:00.000Z
created: 2022-12-08T16:26:17.702Z
SNYK-JS-OPENZEPPELINCONTRACTS-2965580:
- '*':
reason: None Given
expires: 2099-01-01T00:00:00.000Z
created: 2022-12-08T16:26:34.283Z
patch: {}

6
.vscode/extensions.json vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"recommendations": [
"dbaeumer.vscode-eslint"
],
"unwantedRecommendations": []
}

View File

@@ -5,15 +5,12 @@
"editor.formatOnSaveMode": "file",
"editor.tabCompletion": "on",
"editor.tabSize": 2,
"editor.formatOnSave": true,
"editor.formatOnSave": false,
"editor.inlineSuggest.enabled": true,
"editor.codeActionsOnSave": {
"source.fixAll": true
},
"files.eol": "\n",
"eslint.enable": true,
"eslint.debug": true,
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
"eslint.debug": true
}

25
apollo-codegen.ts Normal file
View File

@@ -0,0 +1,25 @@
/* eslint-env node */
import type { CodegenConfig } from '@graphql-codegen/cli'
// Generates TS objects from the schemas returned by graphql queries
// To learn more: https://www.apollographql.com/docs/react/development-testing/static-typing/#setting-up-your-project
const config: CodegenConfig = {
overwrite: true,
schema: './src/graphql/data/schema.graphql',
documents: ['./src/graphql/data/**', '!./src/graphql/data/__generated__/**', '!**/thegraph/**'],
generates: {
'src/graphql/data/__generated__/types-and-hooks.ts': {
plugins: ['typescript', 'typescript-operations', 'typescript-react-apollo'],
config: {
withHooks: true,
// This avoid all generated schemas being wrapped in Maybe https://the-guild.dev/graphql/codegen/plugins/typescript/typescript#maybevalue-string-default-value-t--null
maybeValue: 'T',
},
},
},
}
// This is used in package.json when generating apollo schemas however the linter stills flags this as unused
// eslint-disable-next-line import/no-unused-modules
export default config

View File

@@ -0,0 +1,25 @@
/* eslint-env node */
import type { CodegenConfig } from '@graphql-codegen/cli'
// Generates TS objects from the schemas returned by graphql queries
// To learn more: https://www.apollographql.com/docs/react/development-testing/static-typing/#setting-up-your-project
const config: CodegenConfig = {
overwrite: true,
schema: './src/graphql/thegraph/schema.graphql',
documents: ['!./src/graphql/data/**', '!./src/graphql/thegraph/__generated__/**', './src/graphql/thegraph/**'],
generates: {
'src/graphql/thegraph/__generated__/types-and-hooks.ts': {
plugins: ['typescript', 'typescript-operations', 'typescript-react-apollo'],
config: {
withHooks: true,
// This avoid all generated schemas being wrapped in Maybe https://the-guild.dev/graphql/codegen/plugins/typescript/typescript#maybevalue-string-default-value-t--null
maybeValue: 'T',
},
},
},
}
// This is used in package.json when generating apollo schemas however the linter stills flags this as unused
// eslint-disable-next-line import/no-unused-modules
export default config

View File

@@ -1,3 +1,5 @@
/* eslint-env node */
const isDev = process.env.NODE_ENV === 'development'
module.exports = {

View File

@@ -1,12 +1,27 @@
import { getTestSelector } from '../utils'
describe('Landing Page', () => {
beforeEach(() => cy.visit('/'))
it('loads swap page', () => {
cy.get('#swap-page')
it('shows landing page when no selectedWallet', () => {
cy.visit('/', { noWallet: true })
cy.get(getTestSelector('landing-page'))
cy.screenshot()
})
it('redirects to url /swap', () => {
it('redirects to swap page when selectedWallet is INJECTED', () => {
cy.visit('/', { selectedWallet: 'INJECTED' })
cy.get('#swap-page')
cy.url().should('include', '/swap')
cy.screenshot()
})
it('shows landing page when selectedWallet is INJECTED and ?intro=true is in query', () => {
cy.visit('/?intro=true', { selectedWallet: 'INJECTED' })
cy.get(getTestSelector('landing-page'))
})
it('shows landing page when the unicorn icon in nav is selected', () => {
cy.get(getTestSelector('uniswap-logo')).click()
cy.get(getTestSelector('landing-page'))
})
it('allows navigation to pool', () => {

63
cypress/e2e/nfts.test.ts Normal file
View File

@@ -0,0 +1,63 @@
import { getTestSelector } from '../utils'
const COLLECTION_ADDRESS = '0xbd3531da5cf5857e7cfaa92426877b022e612cf8'
describe('Testing nfts', () => {
before(() => {
cy.visit('/')
})
it('should load nft leaderboard', () => {
cy.get(getTestSelector('nft-nav')).first().click()
cy.get(getTestSelector('nft-nav')).first().should('exist')
cy.get(getTestSelector('nft-nav')).first().click()
cy.get(getTestSelector('nft-trending-collection')).its('length').should('be.gte', 25)
})
it('should load pudgy penguin collection page', () => {
cy.visit(`/#/nfts/collection/${COLLECTION_ADDRESS}`)
cy.get(getTestSelector('nft-collection-asset')).should('exist')
cy.get(getTestSelector('nft-collection-filter-buy-now')).should('not.exist')
cy.get(getTestSelector('nft-filter')).first().click()
cy.get(getTestSelector('nft-collection-filter-buy-now')).should('exist')
})
it('should be able to open bag and open sweep', () => {
cy.get(getTestSelector('nft-sweep-button')).first().click()
cy.get(getTestSelector('nft-empty-bag')).should('exist')
cy.get(getTestSelector('nft-sweep-slider')).should('exist')
})
it('should be able to navigate to activity', () => {
cy.get(getTestSelector('nft-activity')).first().click()
cy.get(getTestSelector('nft-activity-row')).should('exist')
})
it('should go to the details page', () => {
cy.visit(`/#/nfts/collection/${COLLECTION_ADDRESS}`)
cy.get(getTestSelector('nft-filter')).first().click()
cy.get(getTestSelector('nft-collection-filter-buy-now')).click()
cy.get(getTestSelector('nft-details-link')).first().click()
cy.get(getTestSelector('nft-details-traits')).should('exist')
cy.get(getTestSelector('nft-details-activity')).should('exist')
cy.get(getTestSelector('nft-details-description')).should('exist')
cy.get(getTestSelector('nft-details-asset-details')).should('exist')
})
it('should toggle buy now on details page', () => {
cy.get(getTestSelector('nft-details-description-text')).should('exist')
cy.get(getTestSelector('nft-details-description')).click()
cy.get(getTestSelector('nft-details-description-text')).should('not.exist')
cy.get(getTestSelector('nft-details-toggle-bag')).eq(1).click()
cy.get(getTestSelector('nft-bag')).should('exist')
})
it('should go view my nfts', () => {
cy.get(getTestSelector('web3-status-connected')).click()
cy.get(getTestSelector('nft-view-self-nfts')).click()
cy.get(getTestSelector('nft-explore-nfts-button')).should('exist')
cy.get(getTestSelector('nft-no-nfts-selected')).should('exist')
cy.get(getTestSelector('nft-bag-close-icon')).click()
cy.get(getTestSelector('nft-explore-nfts-button')).click()
})
})

View File

@@ -3,8 +3,8 @@ describe('Redirect', () => {
cy.visit('/create-proposal')
cy.url().should('match', /\/vote\/create-proposal/)
})
it('should redirect to /swap when visiting nonexist url', () => {
it('should redirect to /not-found when visiting nonexist url', () => {
cy.visit('/none-exist-url')
cy.url().should('match', /\/swap/)
cy.url().should('match', /\/not-found/)
})
})

View File

@@ -22,10 +22,4 @@ describe('Remove Liquidity', () => {
cy.get('#remove-liquidity-tokena-symbol').should('contain.text', 'WETH')
cy.get('#remove-liquidity-tokenb-symbol').should('contain.text', 'WETH')
})
it.skip('token not in storage is loaded', () => {
cy.visit('/remove/v2/0xb290b2f9f8f108d03ff2af3ac5c8de6de31cdf6d/0xF9bA5210F91D0474bd1e1DcDAeC4C58E359AaD85')
cy.get('#remove-liquidity-tokena-symbol').should('contain.text', 'SKL')
cy.get('#remove-liquidity-tokenb-symbol').should('contain.text', 'MKR')
})
})

20
cypress/e2e/token.test.ts Normal file
View File

@@ -0,0 +1,20 @@
import { getTestSelector, getTestSelectorStartsWith } from '../utils'
describe('Testing tokens on uniswap page', () => {
before(() => {
cy.visit('/')
})
it('should load token leaderboard', () => {
cy.visit('/tokens/ethereum')
cy.get(getTestSelectorStartsWith('token-table')).its('length').should('be.gte', 25)
})
it('should load go to ethereum token and return to token list page', () => {
cy.visit('/tokens/ethereum')
cy.get(getTestSelector('token-table-row-Ether')).click()
cy.get(getTestSelector('token-details-stats')).should('exist')
cy.get(getTestSelector('token-details-return-button')).click()
cy.get(getTestSelectorStartsWith('token-table')).its('length').should('be.gte', 25)
})
})

View File

@@ -2,7 +2,7 @@ import { getTestSelector } from '../utils'
describe('Wallet Dropdown', () => {
before(() => {
cy.visit('/')
cy.visit('/pool')
})
it('should change the theme', () => {
@@ -30,6 +30,8 @@ describe('Wallet Dropdown', () => {
cy.get(getTestSelector('wallet-disconnect')).click()
cy.get(getTestSelector('wallet-select-theme')).click()
cy.get(getTestSelector('wallet-select-theme')).contains('Dark theme').should('exist')
cy.get(getTestSelector('wallet-select-theme')).click()
cy.get(getTestSelector('wallet-select-theme')).contains('Light theme').should('exist')
})
it('should select a language when not connected', () => {

View File

@@ -8,7 +8,8 @@ describe(
},
() => {
it('loads swap page', () => {
// We *must* wait in order to space out the retry attempts.
// TODO: We *must* wait in order to space out the retry attempts. Find a better way to do this.
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy.wait(ONE_MINUTE)
.visit('/', {
retryOnStatusCodeFailure: true,

View File

@@ -20,6 +20,8 @@ declare global {
interface VisitOptions {
serviceWorker?: true
featureFlags?: Array<FeatureFlag>
selectedWallet?: string
noWallet?: boolean
}
}
}
@@ -38,7 +40,12 @@ Cypress.Commands.overwrite(
onBeforeLoad(win) {
options?.onBeforeLoad?.(win)
win.localStorage.clear()
win.localStorage.setItem('redux_localstorage_simple_user', '{"selectedWallet":"INJECTED"}')
const userState = {
selectedWallet: options?.noWallet !== true ? options?.selectedWallet || 'INJECTED' : undefined,
fiatOnrampDismissed: true,
}
win.localStorage.setItem('redux_localstorage_simple_user', JSON.stringify(userState))
if (options?.featureFlags) {
const featureFlags = options.featureFlags.reduce(
@@ -65,10 +72,20 @@ beforeEach(() => {
res.headers['origin'] = 'http://localhost:3000'
res.continue()
})
// Graphql security policies are based on Origin headers.
// These are stripped by cypress because chromeWebSecurity === false; this adds them back in.
cy.intercept('https://api.uniswap.org/v1/graphql', (res) => {
res.headers['origin'] = 'https://app.uniswap.org'
res.continue()
})
cy.intercept('https://beta.api.uniswap.org/v1/graphql', (res) => {
res.headers['origin'] = 'https://app.uniswap.org'
res.continue()
})
})
Cypress.on('uncaught:exception', (_err, _runnable) => {
// returning false here prevents Cypress from
// failing the test
Cypress.on('uncaught:exception', () => {
// returning false here prevents Cypress from failing the test
return false
})

View File

@@ -1,7 +1,7 @@
// Utility to match GraphQL mutation based on the query name
export const hasQuery = (req: any, queryName: string) => {
const { body } = req
return body.hasOwnProperty('query') && body.query.includes(queryName)
return Object.prototype.hasOwnProperty.call(body, 'query') && body.query.includes(queryName)
}
// Alias query if queryName matches

View File

@@ -1 +1,3 @@
export const getTestSelector = (selectorId: string) => `[data-testid=${selectorId}]`
export const getTestSelectorStartsWith = (selectorId: string) => `[data-testid^=${selectorId}]`

View File

@@ -1,9 +1,10 @@
/* eslint-disable */
/* eslint-env node */
require('dotenv').config({ path: '.env.production' })
const { exec } = require('child_process')
const dataConfig = require('./relay.config')
const thegraphConfig = require('./relay_thegraph.config')
/* eslint-enable */
const dataConfig = require('./graphql.config')
const thegraphConfig = require('./graphql_thegraph.config')
function fetchSchema(url, outputFile) {
exec(

View File

@@ -1,3 +1,5 @@
/* eslint-env node */
module.exports = {
src: './src',
language: 'typescript',

View File

@@ -1,5 +1,6 @@
// eslint-disable-next-line @typescript-eslint/no-var-requires
const defaultConfig = require('./relay.config')
/* eslint-env node */
const defaultConfig = require('./graphql.config')
module.exports = {
src: defaultConfig.src,

View File

@@ -8,10 +8,10 @@
"contracts:compile:abi": "typechain --target ethers-v5 --out-dir src/abis/types \"./src/abis/**/*.json\"",
"contracts:compile:v3": "typechain --target ethers-v5 --out-dir src/types/v3 \"./node_modules/@uniswap/**/artifacts/contracts/**/*[!dbg].json\"",
"contracts:compile": "yarn contracts:compile:abi && yarn contracts:compile:v3",
"relay": "relay-compiler relay.config.js",
"relay-thegraph": "relay-compiler relay_thegraph.config.js",
"graphql:fetch": "node fetch-schema.js",
"graphql:generate": "yarn relay && yarn relay-thegraph",
"graphql:generate:data": "graphql-codegen --config apollo-codegen.ts",
"graphql:generate:thegraph": "graphql-codegen --config apollo-codegen_thegraph.ts",
"graphql:generate": "yarn graphql:generate:data && yarn graphql:generate:thegraph",
"prei18n:extract": "node prei18n-extract.js",
"i18n:extract": "lingui extract --locale en-US",
"i18n:compile": "yarn i18n:extract && lingui compile",
@@ -90,39 +90,35 @@
"@types/ua-parser-js": "^0.7.35",
"@types/uuid": "^8.3.4",
"@types/wcag-contrast": "^3.0.0",
"@typescript-eslint/eslint-plugin": "^4",
"@typescript-eslint/parser": "^4",
"@uniswap/eslint-config": "^1.1.1",
"@vanilla-extract/babel-plugin": "^1.1.7",
"@vanilla-extract/webpack-plugin": "^2.1.11",
"babel-plugin-relay": "^14.1.0",
"cypress": "^10.3.1",
"env-cmd": "^10.1.0",
"eslint": "^7.11.0",
"eslint-config-prettier": "^6.11.0",
"eslint-import-resolver-typescript": "^3.5.2",
"eslint-plugin-better-styled-components": "^1.1.2",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-prettier": "^3.1.3",
"eslint-plugin-react": "^7.21.5",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-simple-import-sort": "^7.0.0",
"eslint-plugin-unused-imports": "^2.0.0",
"jest-styled-components": "^7.0.8",
"ms.macro": "^2.0.0",
"patch-package": "^6.4.7",
"postinstall-postinstall": "^2.1.0",
"prettier": "^2.7.1",
"react-scripts": "^4.0.3",
"relay-compiler": "^14.1.0",
"serve": "^11.3.2",
"ts-transform-graphql-tag": "^0.2.1",
"typechain": "^5.0.0",
"typescript": "^4.4.3",
"yarn-deduplicate": "^6.0.0"
},
"dependencies": {
"@apollo/client": "^3.7.2",
"@coinbase/wallet-sdk": "^3.3.0",
"@fontsource/ibm-plex-mono": "^4.5.1",
"@fontsource/inter": "^4.5.1",
"@graphql-codegen/cli": "^2.15.0",
"@graphql-codegen/client-preset": "^1.2.1",
"@graphql-codegen/typescript": "^2.8.3",
"@graphql-codegen/typescript-operations": "^2.5.8",
"@graphql-codegen/typescript-react-apollo": "^3.3.7",
"@graphql-codegen/typescript-resolvers": "^2.7.8",
"@lingui/core": "^3.14.0",
"@lingui/macro": "^3.14.0",
"@lingui/react": "^3.14.0",
@@ -135,11 +131,10 @@
"@react-hook/window-scroll": "^1.3.0",
"@reduxjs/toolkit": "^1.6.1",
"@sentry/react": "7.20.1",
"@types/react-relay": "^13.0.2",
"@types/react-window-infinite-loader": "^1.0.6",
"@uniswap/analytics": "1.2.0",
"@uniswap/analytics-events": "1.1.0",
"@uniswap/conedison": "^1.1.0",
"@uniswap/analytics-events": "^1.5.0",
"@uniswap/conedison": "^1.1.1",
"@uniswap/governance": "^1.0.2",
"@uniswap/liquidity-staker": "^1.0.2",
"@uniswap/merkle-distributor": "1.0.1",
@@ -149,14 +144,14 @@
"@uniswap/sdk-core": "^3.0.1",
"@uniswap/smart-order-router": "^2.10.0",
"@uniswap/token-lists": "^1.0.0-beta.30",
"@uniswap/universal-router-sdk": "1.2.2",
"@uniswap/universal-router-sdk": "1.3.0",
"@uniswap/v2-core": "1.0.0",
"@uniswap/v2-periphery": "^1.1.0-beta.0",
"@uniswap/v2-sdk": "^3.0.1",
"@uniswap/v3-core": "1.0.0",
"@uniswap/v3-periphery": "^1.1.1",
"@uniswap/v3-sdk": "^3.9.0",
"@uniswap/widgets": "2.22.0",
"@uniswap/widgets": "2.22.11",
"@vanilla-extract/css": "^1.7.2",
"@vanilla-extract/css-utils": "^0.1.2",
"@vanilla-extract/dynamic": "^2.0.2",
@@ -215,8 +210,6 @@
"react-popper": "^2.2.3",
"react-query": "^3.39.1",
"react-redux": "^8.0.2",
"react-relay": "^14.1.0",
"react-relay-network-modern": "^6.2.1",
"react-router-dom": "^6.3.0",
"react-spring": "^9.5.5",
"react-table": "^7.8.0",

View File

@@ -1,4 +1,5 @@
// eslint-disable-next-line @typescript-eslint/no-var-requires
/* eslint-env node */
const { exec } = require('child_process')
const isWindows = process.platform === 'win32' || /^(msys|cygwin)$/.test(process.env.OSTYPE)

View File

@@ -89,7 +89,9 @@
z-index: -1;
}
html {
html,
body,
#root {
min-height: 100%;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 3.5 MiB

View File

@@ -0,0 +1,89 @@
import { TraceEvent } from '@uniswap/analytics'
import { BrowserEvent, ElementName, EventName } from '@uniswap/analytics-events'
import { BookOpen, Globe, Heart, Twitter } from 'react-feather'
import styled from 'styled-components/macro'
import { BREAKPOINTS } from 'theme'
const Footer = styled.div`
display: flex;
flex-direction: column;
width: 100%;
gap: 48px;
max-width: 1440px;
`
const FooterLinks = styled.div`
display: grid;
grid-template-columns: 1fr;
gap: 12px;
@media screen and (min-width: ${BREAKPOINTS.sm}px) {
grid-template-columns: 1fr 1fr;
gap: 24px;
}
@media screen and (min-width: ${BREAKPOINTS.lg}px) {
grid-template-columns: 1fr 1fr 1fr 1fr;
}
`
const FooterLink = styled.a`
display: flex;
align-items: center;
gap: 16px;
padding: 16px;
color: ${({ theme }) => theme.textPrimary};
border: 1px solid ${({ theme }) => theme.backgroundOutline};
font-size: 16px;
line-height: 20px;
font-weight: 600;
border-radius: 8px;
cursor: pointer;
text-decoration: none;
svg {
color: ${({ theme }) => theme.textSecondary};
stroke-width: 1.5;
}
transition: ${({ theme }) => `${theme.transition.duration.medium} ${theme.transition.timing.ease} border`};
&:hover {
border: 1px solid ${({ theme }) => theme.textTertiary};
}
@media screen and (min-width: ${BREAKPOINTS.md}px) {
font-size: 20px;
line-height: 24px;
}
`
const Copyright = styled.span`
font-size: 16px;
line-height: 20px;
color: ${({ theme }) => theme.textTertiary};
`
export const AboutFooter = () => {
return (
<Footer>
<FooterLinks>
<TraceEvent events={[BrowserEvent.onClick]} name={EventName.ELEMENT_CLICKED} element={ElementName.SUPPORT_LINK}>
<FooterLink rel="noopener noreferrer" target="_blank" href="https://support.uniswap.org">
<Globe /> Support
</FooterLink>
</TraceEvent>
<TraceEvent events={[BrowserEvent.onClick]} name={EventName.ELEMENT_CLICKED} element={ElementName.TWITTER_LINK}>
<FooterLink rel="noopener noreferrer" target="_blank" href="https://twitter.com/uniswap">
<Twitter /> Twitter
</FooterLink>
</TraceEvent>
<TraceEvent events={[BrowserEvent.onClick]} name={EventName.ELEMENT_CLICKED} element={ElementName.BLOG_LINK}>
<FooterLink rel="noopener noreferrer" target="_blank" href="https://uniswap.org/blog">
<BookOpen /> Blog
</FooterLink>
</TraceEvent>
<TraceEvent events={[BrowserEvent.onClick]} name={EventName.ELEMENT_CLICKED} element={ElementName.CAREERS_LINK}>
<FooterLink rel="noopener noreferrer" target="_blank" href="https://boards.greenhouse.io/uniswaplabs">
<Heart /> Careers
</FooterLink>
</TraceEvent>
</FooterLinks>
<Copyright>© {new Date().getFullYear()} Uniswap Labs</Copyright>
</Footer>
)
}

View File

@@ -0,0 +1,150 @@
import { TraceEvent } from '@uniswap/analytics'
import { BrowserEvent, EventName } from '@uniswap/analytics-events'
import { Link } from 'react-router-dom'
import { useIsDarkMode } from 'state/user/hooks'
import styled, { DefaultTheme } from 'styled-components/macro'
import { BREAKPOINTS } from 'theme'
export enum CardType {
Primary = 'Primary',
Secondary = 'Secondary',
}
const StyledCard = styled.div<{ isDarkMode: boolean; backgroundImgSrc?: string; type: CardType }>`
display: flex;
background: ${({ isDarkMode, backgroundImgSrc, type, theme }) =>
isDarkMode
? `${type === CardType.Primary ? theme.backgroundModule : theme.backgroundSurface} ${
backgroundImgSrc ? ` url(${backgroundImgSrc})` : ''
}`
: `${type === CardType.Primary ? 'white' : theme.backgroundModule} url(${backgroundImgSrc})`};
background-size: auto 100%;
background-position: right;
background-repeat: no-repeat;
background-origin: border-box;
flex-direction: column;
justify-content: space-between;
text-decoration: none;
color: ${({ theme }) => theme.textPrimary};
padding: 24px;
height: 212px;
border-radius: 24px;
border: 1px solid ${({ theme, type }) => (type === CardType.Primary ? 'transparent' : theme.backgroundOutline)};
box-shadow: 0px 10px 24px 0px rgba(51, 53, 72, 0.04);
transition: ${({ theme }) => `${theme.transition.duration.medium} ${theme.transition.timing.ease} border`};
&:hover {
border: 1px solid ${({ theme, isDarkMode }) => (isDarkMode ? theme.backgroundInteractive : theme.textTertiary)};
}
@media screen and (min-width: ${BREAKPOINTS.sm}px) {
height: ${({ backgroundImgSrc }) => (backgroundImgSrc ? 360 : 260)}px;
}
@media screen and (min-width: ${BREAKPOINTS.xl}px) {
padding: 32px;
}
`
const TitleRow = styled.div`
display: flex;
align-items: center;
justify-content: space-between;
`
const CardTitle = styled.div`
font-size: 20px;
line-height: 28px;
font-weight: 600;
@media screen and (min-width: ${BREAKPOINTS.lg}px) {
font-size: 28px;
line-height: 36px;
}
`
const getCardDescriptionColor = (type: CardType, theme: DefaultTheme) => {
switch (type) {
case CardType.Secondary:
return theme.textSecondary
default:
return theme.textPrimary
}
}
const CardDescription = styled.div<{ type: CardType }>`
display: flex;
flex-direction: column;
font-size: 16px;
line-height: 20px;
color: ${({ theme, type }) => getCardDescriptionColor(type, theme)};
padding: 0 40px 0 0;
max-width: 480px;
@media screen and (min-width: ${BREAKPOINTS.xl}px) {
font-size: 20px;
line-height: 28px;
max-width: 480px;
}
`
const CardCTA = styled(CardDescription)`
color: ${({ theme }) => theme.accentAction};
font-weight: 500;
margin: 24px 0 0;
cursor: pointer;
transition: ${({ theme }) => `${theme.transition.duration.medium} ${theme.transition.timing.ease} opacity`};
&:hover {
opacity: 0.6;
}
`
const Card = ({
type = CardType.Primary,
title,
description,
cta,
to,
external,
backgroundImgSrc,
icon,
elementName,
}: {
type?: CardType
title: string
description: string
cta?: string
to: string
external?: boolean
backgroundImgSrc?: string
icon?: React.ReactNode
elementName?: string
}) => {
const isDarkMode = useIsDarkMode()
return (
<TraceEvent events={[BrowserEvent.onClick]} name={EventName.ELEMENT_CLICKED} element={elementName}>
<StyledCard
type={type}
as={external ? 'a' : Link}
to={external ? undefined : to}
href={external ? to : undefined}
target={external ? '_blank' : undefined}
rel={external ? 'noopenener noreferrer' : undefined}
isDarkMode={isDarkMode}
backgroundImgSrc={backgroundImgSrc}
>
<TitleRow>
<CardTitle>{title}</CardTitle>
{icon}
</TitleRow>
<CardDescription type={type}>
{description}
<CardCTA type={type}>{cta}</CardCTA>
</CardDescription>
</StyledCard>
</TraceEvent>
)
}
export default Card

View File

@@ -0,0 +1,106 @@
import { ButtonEmpty } from 'components/Button'
import { useIsDarkMode } from 'state/user/hooks'
import styled from 'styled-components/macro'
import { BREAKPOINTS } from 'theme'
import meshSrc from './images/Mesh.png'
const DARK_MODE_GRADIENT = 'radial-gradient(101.8% 4091.31% at 0% 0%, #4673FA 0%, #9646FA 100%)'
const Banner = styled.div<{ isDarkMode: boolean }>`
height: 340px;
width: 100%;
border-radius: 32px;
max-width: 1440px;
margin: 80px 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
padding: 32px 48px;
box-shadow: 0px 10px 24px rgba(51, 53, 72, 0.04);
background: ${({ isDarkMode }) =>
isDarkMode
? `url(${meshSrc}), ${DARK_MODE_GRADIENT}`
: `url(${meshSrc}), linear-gradient(93.06deg, #FF00C7 2.66%, #FF9FFB 98.99%);`};
@media screen and (min-width: ${BREAKPOINTS.lg}px) {
height: 140px;
flex-direction: row;
}
`
const TextContainer = styled.div`
color: white;
display: flex;
flex: 1;
flex-direction: column;
`
const HeaderText = styled.div`
font-weight: 700;
font-size: 28px;
line-height: 36px;
@media screen and (min-width: ${BREAKPOINTS.xl}px) {
font-size: 28px;
line-height: 36px;
}
`
const DescriptionText = styled.div`
margin: 10px 10px 0 0;
font-weight: 500;
font-size: 16px;
line-height: 20px;
@media screen and (min-width: ${BREAKPOINTS.xl}px) {
font-size: 20px;
line-height: 28px;
}
`
const BannerButtonContainer = styled.div`
width: 100%;
display: flex;
align-items: center;
transition: ${({ theme }) => `${theme.transition.duration.medium} ${theme.transition.timing.ease} opacity`};
&:hover {
opacity: 0.6;
}
@media screen and (min-width: ${BREAKPOINTS.lg}px) {
width: auto;
}
`
const BannerButton = styled(ButtonEmpty)`
color: white;
border: 1px solid white;
`
const ProtocolBanner = () => {
const isDarkMode = useIsDarkMode()
return (
<Banner isDarkMode={isDarkMode}>
<TextContainer>
<HeaderText>Powered by the Uniswap Protocol</HeaderText>
<DescriptionText>
The leading decentralized crypto trading protocol, governed by a global community.
</DescriptionText>
</TextContainer>
<BannerButtonContainer>
<BannerButton width="200px" as="a" href="https://uniswap.org" rel="noopener noreferrer" target="_blank">
Learn more
</BannerButton>
</BannerButtonContainer>
</Banner>
)
}
export default ProtocolBanner

View File

@@ -0,0 +1,71 @@
import { ElementName } from '@uniswap/analytics-events'
import { DollarSign, Terminal } from 'react-feather'
import styled from 'styled-components/macro'
import { lightTheme } from 'theme/colors'
import darkArrowImgSrc from './images/aboutArrowDark.png'
import lightArrowImgSrc from './images/aboutArrowLight.png'
import darkDollarImgSrc from './images/aboutDollarDark.png'
import darkTerminalImgSrc from './images/aboutTerminalDark.png'
import nftCardImgSrc from './images/nftCard.png'
import swapCardImgSrc from './images/swapCard.png'
export const MAIN_CARDS = [
{
to: '/swap',
title: 'Swap tokens',
description: 'Buy, sell, and explore tokens on Ethereum, Polygon, Optimism, and more.',
cta: 'Trade Tokens',
darkBackgroundImgSrc: swapCardImgSrc,
lightBackgroundImgSrc: swapCardImgSrc,
elementName: ElementName.ABOUT_PAGE_SWAP_CARD,
},
{
to: '/nfts',
title: 'Trade NFTs',
description: 'Buy and sell NFTs across marketplaces to find more listings at better prices.',
cta: 'Explore NFTs',
darkBackgroundImgSrc: nftCardImgSrc,
lightBackgroundImgSrc: nftCardImgSrc,
elementName: ElementName.ABOUT_PAGE_NFTS_CARD,
},
]
const StyledCardLogo = styled.img`
min-width: 20px;
min-height: 20px;
max-height: 48px;
max-width: 48px;
`
export const MORE_CARDS = [
{
to: 'https://support.uniswap.org/hc/en-us/articles/11306574799117-How-to-use-Moon-Pay-on-the-Uniswap-web-app-',
external: true,
title: 'Buy crypto',
description: 'Buy crypto with your credit card or bank account at the best rates.',
lightIcon: <DollarSign color={lightTheme.textTertiary} size={48} />,
darkIcon: <StyledCardLogo src={darkDollarImgSrc} alt="Earn" />,
cta: 'Buy now',
elementName: ElementName.ABOUT_PAGE_BUY_CRYPTO_CARD,
},
{
to: '/pool',
title: 'Earn',
description: 'Provide liquidity to pools on Uniswap and earn fees on swaps.',
lightIcon: <StyledCardLogo src={lightArrowImgSrc} alt="Analytics" />,
darkIcon: <StyledCardLogo src={darkArrowImgSrc} alt="Analytics" />,
cta: 'Provide liquidity',
elementName: ElementName.ABOUT_PAGE_EARN_CARD,
},
{
to: 'https://docs.uniswap.org',
external: true,
title: 'Build dApps',
description: 'Build apps and tools on the largest DeFi protocol on Ethereum.',
lightIcon: <Terminal color={lightTheme.textTertiary} size={48} />,
darkIcon: <StyledCardLogo src={darkTerminalImgSrc} alt="Developers" />,
cta: 'Developer docs',
elementName: ElementName.ABOUT_PAGE_DEV_DOCS_CARD,
},
]

Binary file not shown.

After

Width:  |  Height:  |  Size: 327 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 379 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 532 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View File

@@ -27,12 +27,12 @@ const TransactionState = styled(ExternalLink)<{ pending: boolean; success?: bool
padding: 0.25rem 0rem;
font-weight: 500;
font-size: 0.825rem;
color: ${({ theme }) => theme.deprecated_primary1};
color: ${({ theme }) => theme.accentAction};
`
const IconWrapper = styled.div<{ pending: boolean; success?: boolean }>`
color: ${({ pending, success, theme }) =>
pending ? theme.deprecated_primary1 : success ? theme.deprecated_green1 : theme.deprecated_red1};
pending ? theme.accentAction : success ? theme.accentSuccess : theme.accentFailure};
`
export default function Transaction({ hash }: { hash: string }) {

View File

@@ -14,18 +14,15 @@ import {
CollectFeesTransactionInfo,
CreateV3PoolTransactionInfo,
DelegateTransactionInfo,
DepositLiquidityStakingTransactionInfo,
ExactInputSwapTransactionInfo,
ExactOutputSwapTransactionInfo,
ExecuteTransactionInfo,
MigrateV2LiquidityToV3TransactionInfo,
QueueTransactionInfo,
RemoveLiquidityV3TransactionInfo,
SubmitProposalTransactionInfo,
TransactionInfo,
TransactionType,
VoteTransactionInfo,
WithdrawLiquidityStakingTransactionInfo,
WrapTransactionInfo,
} from '../../state/transactions/types'
@@ -83,7 +80,7 @@ function ClaimSummary({ info: { recipient, uniAmountRaw } }: { info: ClaimTransa
)
}
function SubmitProposalTransactionSummary(_: { info: SubmitProposalTransactionInfo }) {
function SubmitProposalTransactionSummary() {
return <Trans>Submit new proposal</Trans>
}
@@ -175,13 +172,13 @@ function WrapSummary({ info: { chainId, currencyAmountRaw, unwrapped } }: { info
}
}
function DepositLiquidityStakingSummary(_: { info: DepositLiquidityStakingTransactionInfo }) {
function DepositLiquidityStakingSummary() {
// not worth rendering the tokens since you can should no longer deposit liquidity in the staking contracts
// todo: deprecate and delete the code paths that allow this, show user more information
return <Trans>Deposit liquidity</Trans>
}
function WithdrawLiquidityStakingSummary(_: { info: WithdrawLiquidityStakingTransactionInfo }) {
function WithdrawLiquidityStakingSummary() {
return <Trans>Withdraw deposited liquidity</Trans>
}
@@ -319,10 +316,10 @@ export function TransactionSummary({ info }: { info: TransactionInfo }) {
return <ClaimSummary info={info} />
case TransactionType.DEPOSIT_LIQUIDITY_STAKING:
return <DepositLiquidityStakingSummary info={info} />
return <DepositLiquidityStakingSummary />
case TransactionType.WITHDRAW_LIQUIDITY_STAKING:
return <WithdrawLiquidityStakingSummary info={info} />
return <WithdrawLiquidityStakingSummary />
case TransactionType.SWAP:
return <SwapSummary info={info} />
@@ -358,6 +355,6 @@ export function TransactionSummary({ info }: { info: TransactionInfo }) {
return <ExecuteSummary info={info} />
case TransactionType.SUBMIT_PROPOSAL:
return <SubmitProposalTransactionSummary info={info} />
return <SubmitProposalTransactionSummary />
}
}

View File

@@ -24,7 +24,7 @@ const HeaderRow = styled.div`
${flexRowNoWrap};
padding: 1rem 1rem;
font-weight: 500;
color: ${(props) => (props.color === 'blue' ? ({ theme }) => theme.deprecated_primary1 : 'inherit')};
color: ${(props) => (props.color === 'blue' ? ({ theme }) => theme.accentAction : 'inherit')};
${({ theme }) => theme.deprecated_mediaWidth.deprecated_upToMedium`
padding: 1rem;
`};
@@ -65,7 +65,7 @@ const AccountGroupingRow = styled.div`
justify-content: space-between;
align-items: center;
font-weight: 400;
color: ${({ theme }) => theme.deprecated_text1};
color: ${({ theme }) => theme.textPrimary};
div {
${flexColumnNoWrap};
@@ -95,14 +95,14 @@ const LowerSection = styled.div`
padding: 1.5rem;
flex-grow: 1;
overflow: auto;
background-color: ${({ theme }) => theme.deprecated_bg2};
background-color: ${({ theme }) => theme.backgroundInteractive};
border-bottom-left-radius: 20px;
border-bottom-right-radius: 20px;
h5 {
margin: 0;
font-weight: 400;
color: ${({ theme }) => theme.deprecated_text3};
color: ${({ theme }) => theme.textTertiary};
}
`
@@ -129,14 +129,14 @@ const AccountControl = styled.div`
`
const AddressLink = styled(ExternalLink)`
color: ${({ theme }) => theme.deprecated_text3};
color: ${({ theme }) => theme.textTertiary};
margin-left: 1rem;
font-size: 0.825rem;
display: flex;
gap: 6px;
text-decoration: none !important;
:hover {
color: ${({ theme }) => theme.deprecated_text2};
color: ${({ theme }) => theme.textSecondary};
}
`
@@ -160,7 +160,7 @@ const WalletName = styled.div`
width: initial;
font-size: 0.825rem;
font-weight: 500;
color: ${({ theme }) => theme.deprecated_text3};
color: ${({ theme }) => theme.textTertiary};
`
const TransactionListWrapper = styled.div`
@@ -316,7 +316,7 @@ export default function AccountDetails({
</LowerSection>
) : (
<LowerSection>
<ThemedText.DeprecatedBody color={theme.deprecated_text1}>
<ThemedText.DeprecatedBody color={theme.textPrimary}>
<Trans>Your transactions will appear here...</Trans>
</ThemedText.DeprecatedBody>
</LowerSection>

View File

@@ -39,26 +39,32 @@ const getCurrency = ({ info, chainId }: { info: TransactionInfo; chainId: number
switch (info.type) {
case TransactionType.ADD_LIQUIDITY_V3_POOL:
case TransactionType.REMOVE_LIQUIDITY_V3:
case TransactionType.CREATE_V3_POOL:
case TransactionType.CREATE_V3_POOL: {
const { baseCurrencyId, quoteCurrencyId } = info
return { currencyId0: baseCurrencyId, currencyId1: quoteCurrencyId }
case TransactionType.SWAP:
}
case TransactionType.SWAP: {
const { inputCurrencyId, outputCurrencyId } = info
return { currencyId0: inputCurrencyId, currencyId1: outputCurrencyId }
case TransactionType.WRAP:
}
case TransactionType.WRAP: {
const { unwrapped } = info
const native = info.chainId ? nativeOnChain(info.chainId) : undefined
const base = 'ETH'
const wrappedCurrency = native?.wrapped.address ?? 'WETH'
return { currencyId0: unwrapped ? wrappedCurrency : base, currencyId1: unwrapped ? base : wrappedCurrency }
case TransactionType.COLLECT_FEES:
}
case TransactionType.COLLECT_FEES: {
const { currencyId0, currencyId1 } = info
return { currencyId0, currencyId1 }
case TransactionType.APPROVAL:
}
case TransactionType.APPROVAL: {
return { currencyId0: info.tokenAddress, currencyId1: undefined }
case TransactionType.CLAIM:
}
case TransactionType.CLAIM: {
const uniAddress = chainId ? UNI_ADDRESS[chainId] : undefined
return { currencyId0: uniAddress, currencyId1: undefined }
}
default:
return { currencyId0: undefined, currencyId1: undefined }
}

View File

@@ -26,7 +26,7 @@ const ContainerRow = styled.div<{ error: boolean }>`
justify-content: center;
align-items: center;
border-radius: 1.25rem;
border: 1px solid ${({ error, theme }) => (error ? theme.deprecated_red1 : theme.deprecated_bg2)};
border: 1px solid ${({ error, theme }) => (error ? theme.accentFailure : theme.backgroundInteractive)};
transition: border-color 300ms ${({ error }) => (error ? 'step-end' : 'step-start')},
color 500ms ${({ error }) => (error ? 'step-end' : 'step-start')};
background-color: ${({ theme }) => theme.deprecated_bg1};
@@ -45,7 +45,7 @@ const Input = styled.input<{ error?: boolean }>`
width: 0;
background-color: ${({ theme }) => theme.deprecated_bg1};
transition: color 300ms ${({ error }) => (error ? 'step-end' : 'step-start')};
color: ${({ error, theme }) => (error ? theme.deprecated_red1 : theme.deprecated_text1)};
color: ${({ error, theme }) => (error ? theme.accentFailure : theme.textPrimary)};
overflow: hidden;
text-overflow: ellipsis;
font-weight: 500;
@@ -109,7 +109,7 @@ export default function AddressInputPanel({
<InputContainer>
<AutoColumn gap="md">
<RowBetween>
<ThemedText.DeprecatedBlack color={theme.deprecated_text2} fontWeight={500} fontSize={14}>
<ThemedText.DeprecatedBlack color={theme.textSecondary} fontWeight={500} fontSize={14}>
{label ?? <Trans>Recipient</Trans>}
</ThemedText.DeprecatedBlack>
{address && chainId && (

View File

@@ -17,7 +17,7 @@ const BadgeText = styled.div`
`
const ActiveDot = styled.span`
background-color: ${({ theme }) => theme.deprecated_success};
background-color: ${({ theme }) => theme.accentSuccess};
border-radius: 50%;
height: 8px;
width: 8px;

View File

@@ -19,24 +19,24 @@ interface BadgeProps {
function pickBackgroundColor(variant: BadgeVariant | undefined, theme: DefaultTheme): string {
switch (variant) {
case BadgeVariant.NEGATIVE:
return theme.deprecated_error
return theme.accentFailure
case BadgeVariant.POSITIVE:
return theme.deprecated_success
return theme.accentSuccess
case BadgeVariant.PRIMARY:
return theme.deprecated_primary1
return theme.accentAction
case BadgeVariant.WARNING:
return theme.deprecated_warning
return theme.accentWarning
case BadgeVariant.WARNING_OUTLINE:
return 'transparent'
default:
return theme.deprecated_bg2
return theme.backgroundInteractive
}
}
function pickBorder(variant: BadgeVariant | undefined, theme: DefaultTheme): string {
switch (variant) {
case BadgeVariant.WARNING_OUTLINE:
return `1px solid ${theme.deprecated_warning}`
return `1px solid ${theme.accentWarning}`
default:
return 'unset'
}
@@ -45,15 +45,15 @@ function pickBorder(variant: BadgeVariant | undefined, theme: DefaultTheme): str
function pickFontColor(variant: BadgeVariant | undefined, theme: DefaultTheme): string {
switch (variant) {
case BadgeVariant.NEGATIVE:
return readableColor(theme.deprecated_error)
return readableColor(theme.accentFailure)
case BadgeVariant.POSITIVE:
return readableColor(theme.deprecated_success)
return readableColor(theme.accentSuccess)
case BadgeVariant.WARNING:
return readableColor(theme.deprecated_warning)
return readableColor(theme.accentWarning)
case BadgeVariant.WARNING_OUTLINE:
return theme.deprecated_warning
return theme.accentWarning
default:
return readableColor(theme.deprecated_bg2)
return readableColor(theme.backgroundInteractive)
}
}

View File

@@ -0,0 +1,13 @@
import { SpinnerSVG } from 'theme'
const ButtonLoadingSpinner = (props: React.ComponentPropsWithoutRef<'svg'>) => (
<SpinnerSVG width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" {...props}>
<path
opacity="0.1"
d="M18.8334 10.0003C18.8334 14.6027 15.1025 18.3337 10.5001 18.3337C5.89771 18.3337 2.16675 14.6027 2.16675 10.0003C2.16675 5.39795 5.89771 1.66699 10.5001 1.66699C15.1025 1.66699 18.8334 5.39795 18.8334 10.0003ZM4.66675 10.0003C4.66675 13.222 7.27842 15.8337 10.5001 15.8337C13.7217 15.8337 16.3334 13.222 16.3334 10.0003C16.3334 6.77867 13.7217 4.16699 10.5001 4.16699C7.27842 4.16699 4.66675 6.77867 4.66675 10.0003Z"
/>
<path d="M17.5834 10.0003C18.2738 10.0003 18.843 9.4376 18.7398 8.755C18.6392 8.0891 18.458 7.43633 18.1991 6.8113C17.7803 5.80025 17.1665 4.88159 16.3926 4.10777C15.6188 3.33395 14.7002 2.72012 13.6891 2.30133C13.0641 2.04243 12.4113 1.86121 11.7454 1.76057C11.0628 1.6574 10.5001 2.22664 10.5001 2.91699C10.5001 3.60735 11.066 4.15361 11.7405 4.30041C12.0789 4.37406 12.4109 4.47786 12.7324 4.61103C13.4401 4.90418 14.0832 5.33386 14.6249 5.87554C15.1665 6.41721 15.5962 7.06027 15.8894 7.76801C16.0225 8.08949 16.1264 8.42147 16.2 8.75986C16.3468 9.43443 16.8931 10.0003 17.5834 10.0003Z" />
</SpinnerSVG>
)
export default ButtonLoadingSpinner

View File

@@ -5,16 +5,31 @@ import styled, { DefaultTheme, useTheme } from 'styled-components/macro'
import { RowBetween } from '../Row'
export { default as LoadingButtonSpinner } from './LoadingButtonSpinner'
type ButtonProps = Omit<ButtonPropsOriginal, 'css'>
export const BaseButton = styled(RebassButton)<
{
padding?: string
width?: string
$borderRadius?: string
altDisabledStyle?: boolean
} & ButtonProps
>`
const ButtonOverlay = styled.div`
background-color: transparent;
bottom: 0;
border-radius: inherit;
height: 100%;
left: 0;
position: absolute;
right: 0;
top: 0;
transition: 150ms ease background-color;
width: 100%;
`
type BaseButtonProps = {
padding?: string
width?: string
$borderRadius?: string
altDisabledStyle?: boolean
} & ButtonProps
export const BaseButton = styled(RebassButton)<BaseButtonProps>`
padding: ${({ padding }) => padding ?? '16px'};
width: ${({ width }) => width ?? '100%'};
font-weight: 500;
@@ -22,7 +37,7 @@ export const BaseButton = styled(RebassButton)<
border-radius: ${({ $borderRadius }) => $borderRadius ?? '20px'};
outline: none;
border: 1px solid transparent;
color: ${({ theme }) => theme.deprecated_text1};
color: ${({ theme }) => theme.textPrimary};
text-decoration: none;
display: flex;
justify-content: center;
@@ -57,21 +72,21 @@ export const ButtonPrimary = styled(BaseButton)`
padding: 16px;
color: ${({ theme }) => theme.accentTextLightPrimary};
&:focus {
box-shadow: 0 0 0 1pt ${({ theme }) => darken(0.05, theme.deprecated_primary1)};
background-color: ${({ theme }) => darken(0.05, theme.deprecated_primary1)};
box-shadow: 0 0 0 1pt ${({ theme }) => darken(0.05, theme.accentAction)};
background-color: ${({ theme }) => darken(0.05, theme.accentAction)};
}
&:hover {
background-color: ${({ theme }) => darken(0.05, theme.deprecated_primary1)};
background-color: ${({ theme }) => darken(0.05, theme.accentAction)};
}
&:active {
box-shadow: 0 0 0 1pt ${({ theme }) => darken(0.1, theme.deprecated_primary1)};
background-color: ${({ theme }) => darken(0.1, theme.deprecated_primary1)};
box-shadow: 0 0 0 1pt ${({ theme }) => darken(0.1, theme.accentAction)};
background-color: ${({ theme }) => darken(0.1, theme.accentAction)};
}
&:disabled {
background-color: ${({ theme, altDisabledStyle, disabled }) =>
altDisabledStyle ? (disabled ? theme.deprecated_primary1 : theme.deprecated_bg2) : theme.deprecated_bg2};
altDisabledStyle ? (disabled ? theme.accentAction : theme.backgroundInteractive) : theme.backgroundInteractive};
color: ${({ altDisabledStyle, disabled, theme }) =>
altDisabledStyle ? (disabled ? theme.deprecated_white : theme.deprecated_text2) : theme.deprecated_text2};
altDisabledStyle ? (disabled ? theme.white : theme.textSecondary) : theme.textSecondary};
cursor: auto;
box-shadow: none;
border: 1px solid transparent;
@@ -79,7 +94,14 @@ export const ButtonPrimary = styled(BaseButton)`
}
`
export const ButtonLight = styled(BaseButton)`
export const SmallButtonPrimary = styled(ButtonPrimary)`
width: auto;
font-size: 16px;
padding: 10px 16px;
border-radius: 12px;
`
const BaseButtonLight = styled(BaseButton)`
background-color: ${({ theme }) => theme.accentActionSoft};
color: ${({ theme }) => theme.accentAction};
font-size: 20px;
@@ -96,6 +118,19 @@ export const ButtonLight = styled(BaseButton)`
box-shadow: 0 0 0 1pt ${({ theme, disabled }) => !disabled && theme.accentActionSoft};
background-color: ${({ theme, disabled }) => !disabled && theme.accentActionSoft};
}
:hover {
${ButtonOverlay} {
background-color: ${({ theme }) => theme.stateOverlayHover};
}
}
:active {
${ButtonOverlay} {
background-color: ${({ theme }) => theme.stateOverlayPressed};
}
}
:disabled {
opacity: 0.4;
:hover {
@@ -110,21 +145,21 @@ export const ButtonLight = styled(BaseButton)`
export const ButtonGray = styled(BaseButton)`
background-color: ${({ theme }) => theme.deprecated_bg1};
color: ${({ theme }) => theme.deprecated_text2};
color: ${({ theme }) => theme.textSecondary};
font-size: 16px;
font-weight: 500;
&:hover {
background-color: ${({ theme, disabled }) => !disabled && darken(0.05, theme.deprecated_bg2)};
background-color: ${({ theme, disabled }) => !disabled && darken(0.05, theme.backgroundInteractive)};
}
&:active {
background-color: ${({ theme, disabled }) => !disabled && darken(0.1, theme.deprecated_bg2)};
background-color: ${({ theme, disabled }) => !disabled && darken(0.1, theme.backgroundInteractive)};
}
`
export const ButtonSecondary = styled(BaseButton)`
border: 1px solid ${({ theme }) => theme.deprecated_primary4};
color: ${({ theme }) => theme.deprecated_primary1};
color: ${({ theme }) => theme.accentAction};
background-color: transparent;
font-size: 16px;
border-radius: 12px;
@@ -151,14 +186,14 @@ export const ButtonSecondary = styled(BaseButton)`
`
export const ButtonOutlined = styled(BaseButton)`
border: 1px solid ${({ theme }) => theme.deprecated_bg2};
border: 1px solid ${({ theme }) => theme.backgroundOutline};
background-color: transparent;
color: ${({ theme }) => theme.deprecated_text1};
color: ${({ theme }) => theme.textPrimary};
&:focus {
box-shadow: 0 0 0 1px ${({ theme }) => theme.deprecated_bg4};
}
&:hover {
box-shadow: 0 0 0 1px ${({ theme }) => theme.deprecated_bg4};
box-shadow: 0 0 0 1px ${({ theme }) => theme.textTertiary};
}
&:active {
box-shadow: 0 0 0 1px ${({ theme }) => theme.deprecated_bg4};
@@ -191,7 +226,7 @@ export const ButtonYellow = styled(BaseButton)`
export const ButtonEmpty = styled(BaseButton)`
background-color: transparent;
color: ${({ theme }) => theme.deprecated_primary1};
color: ${({ theme }) => theme.accentAction};
display: flex;
justify-content: center;
align-items: center;
@@ -233,38 +268,38 @@ export const ButtonText = styled(BaseButton)`
const ButtonConfirmedStyle = styled(BaseButton)`
background-color: ${({ theme }) => theme.deprecated_bg3};
color: ${({ theme }) => theme.deprecated_text1};
/* border: 1px solid ${({ theme }) => theme.deprecated_green1}; */
color: ${({ theme }) => theme.textPrimary};
/* border: 1px solid ${({ theme }) => theme.accentSuccess}; */
&:disabled {
opacity: 50%;
background-color: ${({ theme }) => theme.deprecated_bg2};
color: ${({ theme }) => theme.deprecated_text2};
background-color: ${({ theme }) => theme.backgroundInteractive};
color: ${({ theme }) => theme.textSecondary};
cursor: auto;
}
`
const ButtonErrorStyle = styled(BaseButton)`
background-color: ${({ theme }) => theme.deprecated_red1};
border: 1px solid ${({ theme }) => theme.deprecated_red1};
background-color: ${({ theme }) => theme.accentFailure};
border: 1px solid ${({ theme }) => theme.accentFailure};
&:focus {
box-shadow: 0 0 0 1pt ${({ theme }) => darken(0.05, theme.deprecated_red1)};
background-color: ${({ theme }) => darken(0.05, theme.deprecated_red1)};
box-shadow: 0 0 0 1pt ${({ theme }) => darken(0.05, theme.accentFailure)};
background-color: ${({ theme }) => darken(0.05, theme.accentFailure)};
}
&:hover {
background-color: ${({ theme }) => darken(0.05, theme.deprecated_red1)};
background-color: ${({ theme }) => darken(0.05, theme.accentFailure)};
}
&:active {
box-shadow: 0 0 0 1pt ${({ theme }) => darken(0.1, theme.deprecated_red1)};
background-color: ${({ theme }) => darken(0.1, theme.deprecated_red1)};
box-shadow: 0 0 0 1pt ${({ theme }) => darken(0.1, theme.accentFailure)};
background-color: ${({ theme }) => darken(0.1, theme.accentFailure)};
}
&:disabled {
opacity: 50%;
cursor: auto;
box-shadow: none;
background-color: ${({ theme }) => theme.deprecated_red1};
border: 1px solid ${({ theme }) => theme.deprecated_red1};
background-color: ${({ theme }) => theme.accentFailure};
border: 1px solid ${({ theme }) => theme.accentFailure};
}
`
@@ -312,14 +347,14 @@ export function ButtonDropdownLight({ disabled = false, children, ...rest }: { d
const ActiveOutlined = styled(ButtonOutlined)`
border: 1px solid;
border-color: ${({ theme }) => theme.deprecated_primary1};
border-color: ${({ theme }) => theme.accentAction};
`
const Circle = styled.div`
height: 17px;
width: 17px;
border-radius: 50%;
background-color: ${({ theme }) => theme.deprecated_primary1};
background-color: ${({ theme }) => theme.accentAction};
display: flex;
align-items: center;
justify-content: center;
@@ -353,7 +388,7 @@ export function ButtonRadioChecked({ active = false, children, ...rest }: { acti
{children}
<CheckboxWrapper>
<Circle>
<ResponsiveCheck size={13} stroke={theme.deprecated_white} />
<ResponsiveCheck size={13} stroke={theme.white} />
</Circle>
</CheckboxWrapper>
</RowBetween>
@@ -362,18 +397,6 @@ export function ButtonRadioChecked({ active = false, children, ...rest }: { acti
}
}
const ButtonOverlay = styled.div`
background-color: transparent;
bottom: 0;
border-radius: 16px;
height: 100%;
left: 0;
position: absolute;
right: 0;
top: 0;
transition: 150ms ease background-color;
width: 100%;
`
export enum ButtonSize {
small,
medium,
@@ -388,7 +411,7 @@ export enum ButtonEmphasis {
warning,
destructive,
}
interface BaseButtonProps {
interface BaseThemeButtonProps {
size: ButtonSize
emphasis: ButtonEmphasis
}
@@ -467,7 +490,7 @@ function pickThemeButtonTextColor({ theme, emphasis }: { theme: DefaultTheme; em
}
}
const BaseThemeButton = styled.button<BaseButtonProps>`
const BaseThemeButton = styled.button<BaseThemeButtonProps>`
align-items: center;
background-color: ${pickThemeButtonBackgroundColor};
border-radius: 16px;
@@ -484,16 +507,13 @@ const BaseThemeButton = styled.button<BaseButtonProps>`
padding: ${pickThemeButtonPadding};
position: relative;
transition: 150ms ease opacity;
user-select: none;
:active {
${ButtonOverlay} {
background-color: ${({ theme }) => theme.stateOverlayPressed};
}
}
:disabled {
cursor: default;
opacity: 0.6;
}
:focus {
${ButtonOverlay} {
background-color: ${({ theme }) => theme.stateOverlayPressed};
@@ -504,9 +524,20 @@ const BaseThemeButton = styled.button<BaseButtonProps>`
background-color: ${({ theme }) => theme.stateOverlayHover};
}
}
:disabled {
cursor: default;
opacity: 0.6;
}
:disabled:active,
:disabled:focus,
:disabled:hover {
${ButtonOverlay} {
background-color: transparent;
}
}
`
interface ThemeButtonProps extends React.ComponentPropsWithoutRef<'button'>, BaseButtonProps {}
interface ThemeButtonProps extends React.ComponentPropsWithoutRef<'button'>, BaseThemeButtonProps {}
export const ThemeButton = ({ children, ...rest }: ThemeButtonProps) => {
return (
@@ -516,3 +547,12 @@ export const ThemeButton = ({ children, ...rest }: ThemeButtonProps) => {
</BaseThemeButton>
)
}
export const ButtonLight = ({ children, ...rest }: BaseButtonProps) => {
return (
<BaseButtonLight {...rest}>
<ButtonOverlay />
{children}
</BaseButtonLight>
)
}

View File

@@ -10,7 +10,7 @@ const Card = styled(Box)<{ width?: string; padding?: string; border?: string; $b
export default Card
export const LightCard = styled(Card)`
border: 1px solid ${({ theme }) => theme.deprecated_bg2};
border: 1px solid ${({ theme }) => theme.backgroundInteractive};
background-color: ${({ theme }) => theme.deprecated_bg1};
`
@@ -19,11 +19,11 @@ export const GrayCard = styled(Card)`
`
export const DarkGrayCard = styled(Card)`
background-color: ${({ theme }) => theme.deprecated_bg2};
background-color: ${({ theme }) => theme.backgroundInteractive};
`
export const DarkCard = styled(Card)`
background-color: ${({ theme }) => theme.deprecated_bg0};
background-color: ${({ theme }) => theme.backgroundSurface};
`
export const OutlineCard = styled(Card)`
@@ -38,6 +38,6 @@ export const YellowCard = styled(Card)`
export const BlueCard = styled(Card)`
background-color: ${({ theme }) => theme.deprecated_primary5};
color: ${({ theme }) => theme.deprecated_blue2};
color: ${({ theme }) => theme.accentAction};
border-radius: 12px;
`

View File

@@ -1,6 +1,7 @@
import { Group } from '@visx/group'
import { LinePath } from '@visx/shape'
import { easeCubicInOut } from 'd3'
import { easeSinOut } from 'd3'
import ms from 'ms.macro'
import React from 'react'
import { useEffect, useRef, useState } from 'react'
import { animated, useSpring } from 'react-spring'
@@ -11,8 +12,8 @@ import { LineChartProps } from './LineChart'
type AnimatedInLineChartProps<T> = Omit<LineChartProps<T>, 'height' | 'width' | 'children'>
const config = {
duration: 800,
easing: easeCubicInOut,
duration: ms`0.8s`,
easing: easeSinOut,
}
// code reference: https://airbnb.io/visx/lineradial
@@ -91,4 +92,4 @@ function AnimatedInLineChart<T>({
)
}
export default AnimatedInLineChart
export default React.memo(AnimatedInLineChart) as typeof AnimatedInLineChart

View File

@@ -0,0 +1,86 @@
import { Group } from '@visx/group'
import { LinePath } from '@visx/shape'
import { easeCubicInOut } from 'd3'
import React from 'react'
import { useEffect, useRef, useState } from 'react'
import { animated, useSpring } from 'react-spring'
import { useTheme } from 'styled-components/macro'
import { LineChartProps } from './LineChart'
type FadedInLineChartProps<T> = Omit<LineChartProps<T>, 'height' | 'width' | 'children'> & { dashed?: boolean }
const config = {
duration: 3000,
easing: easeCubicInOut,
}
// code reference: https://airbnb.io/visx/lineradial
function FadedInLineChart<T>({
data,
getX,
getY,
marginTop,
curve,
color,
strokeWidth,
dashed,
}: FadedInLineChartProps<T>) {
const lineRef = useRef<SVGPathElement>(null)
const [lineLength, setLineLength] = useState(0)
const [shouldAnimate, setShouldAnimate] = useState(false)
const [hasAnimatedIn, setHasAnimatedIn] = useState(false)
const spring = useSpring({
frame: shouldAnimate ? 0 : 1,
config,
onRest: () => {
setShouldAnimate(false)
setHasAnimatedIn(true)
},
})
// We need to check to see after the "invisble" line has been drawn
// what the length is to be able to animate in the line for the first time
// This will run on each render to see if there is a new line length
// eslint-disable-next-line react-hooks/exhaustive-deps
useEffect(() => {
if (lineRef.current) {
const length = lineRef.current.getTotalLength()
if (length !== lineLength) {
setLineLength(length)
}
if (length > 0 && !shouldAnimate && !hasAnimatedIn) {
setShouldAnimate(true)
}
}
})
const theme = useTheme()
const lineColor = color ?? theme.accentAction
return (
<Group top={marginTop}>
<LinePath curve={curve} x={getX} y={getY}>
{({ path }) => {
const d = path(data) || ''
return (
<>
<animated.path
d={d}
ref={lineRef}
strokeWidth={strokeWidth}
strokeOpacity={hasAnimatedIn ? 1 : spring.frame.to((v) => 1 - v)}
fill="none"
stroke={lineColor}
strokeDasharray={dashed ? '4,4' : undefined}
/>
</>
)
}}
</LinePath>
</Group>
)
}
export default React.memo(FadedInLineChart) as typeof FadedInLineChart

View File

@@ -2,7 +2,6 @@ import { SparkLineLoadingBubble } from 'components/Tokens/TokenTable/TokenRow'
import { curveCardinal, scaleLinear } from 'd3'
import { SparklineMap, TopToken } from 'graphql/data/TopTokens'
import { PricePoint } from 'graphql/data/util'
import { TimePeriod } from 'graphql/data/util'
import { memo } from 'react'
import styled, { useTheme } from 'styled-components/macro'
@@ -21,18 +20,10 @@ interface SparklineChartProps {
height: number
tokenData: TopToken
pricePercentChange: number | undefined | null
timePeriod: TimePeriod
sparklineMap: SparklineMap
}
function _SparklineChart({
width,
height,
tokenData,
pricePercentChange,
timePeriod,
sparklineMap,
}: SparklineChartProps) {
function _SparklineChart({ width, height, tokenData, pricePercentChange, sparklineMap }: SparklineChartProps) {
const theme = useTheme()
// for sparkline
const pricePoints = tokenData?.address ? sparklineMap[tokenData.address] : null

View File

@@ -49,7 +49,7 @@ export default function ConnectedAccountBlocked(props: ConnectedAccountBlockedPr
fontSize={14}
iconSize={16}
gap={6}
color={theme.deprecated_primary1}
color={theme.accentAction}
iconPosition="right"
>
compliance@uniswap.org

View File

@@ -1,45 +1,72 @@
import { Trans } from '@lingui/macro'
// eslint-disable-next-line no-restricted-imports
import { t } from '@lingui/macro'
import { formatCurrencyAmount, formatPriceImpact, NumberType } from '@uniswap/conedison/format'
import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core'
import { useMemo } from 'react'
import { useTheme } from 'styled-components/macro'
import { LoadingBubble } from 'components/Tokens/loading'
import { MouseoverTooltip } from 'components/Tooltip'
import { useEffect, useMemo, useState } from 'react'
import styled, { useTheme } from 'styled-components/macro'
import { ThemedText } from '../../theme'
import { warningSeverity } from '../../utils/prices'
import { MouseoverTooltip } from '../Tooltip'
const FiatLoadingBubble = styled(LoadingBubble)`
border-radius: 4px;
width: 4rem;
height: 1rem;
`
export function FiatValue({
fiatValue,
priceImpact,
isLoading = false,
}: {
fiatValue: CurrencyAmount<Currency> | null | undefined
priceImpact?: Percent
isLoading?: boolean
}) {
const theme = useTheme()
const [showLoadingPlaceholder, setShowLoadingPlaceholder] = useState(false)
const priceImpactColor = useMemo(() => {
if (!priceImpact) return undefined
if (priceImpact.lessThan('0')) return theme.deprecated_green1
if (priceImpact.lessThan('0')) return theme.accentSuccess
const severity = warningSeverity(priceImpact)
if (severity < 1) return theme.deprecated_text3
if (severity < 1) return theme.textTertiary
if (severity < 3) return theme.deprecated_yellow1
return theme.deprecated_red1
}, [priceImpact, theme.deprecated_green1, theme.deprecated_red1, theme.deprecated_text3, theme.deprecated_yellow1])
return theme.accentFailure
}, [priceImpact, theme.accentSuccess, theme.accentFailure, theme.textTertiary, theme.deprecated_yellow1])
const p = Number(fiatValue?.toFixed())
const visibleDecimalPlaces = p < 1.05 ? 4 : 2
useEffect(() => {
const stale = false
let timeoutId = 0
if (isLoading && !fiatValue) {
timeoutId = setTimeout(() => {
if (!stale) setShowLoadingPlaceholder(true)
}, 200) as unknown as number
} else {
setShowLoadingPlaceholder(false)
}
return () => clearTimeout(timeoutId)
}, [isLoading, fiatValue])
return (
<ThemedText.DeprecatedBody fontSize={14} color={theme.textSecondary}>
{fiatValue && <>${fiatValue?.toFixed(visibleDecimalPlaces, { groupSeparator: ',' })}</>}
{priceImpact ? (
<span style={{ color: priceImpactColor }}>
{' '}
<MouseoverTooltip text={t`The estimated difference between the USD values of input and output amounts.`}>
(<Trans>{priceImpact.multiply(-1).toSignificant(3)}%</Trans>)
</MouseoverTooltip>
</span>
) : null}
{showLoadingPlaceholder ? (
<FiatLoadingBubble />
) : (
<div>
{fiatValue && <>{formatCurrencyAmount(fiatValue, NumberType.FiatTokenPrice)}</>}
{priceImpact && (
<span style={{ color: priceImpactColor }}>
{' '}
<MouseoverTooltip text={t`The estimated difference between the USD values of input and output amounts.`}>
(<Trans>{formatPriceImpact(priceImpact)}</Trans>)
</MouseoverTooltip>
</span>
)}
</div>
)}
</ThemedText.DeprecatedBody>
)
}

View File

@@ -9,7 +9,7 @@ import { LoadingOpacityContainer, loadingOpacityMixin } from 'components/Loader/
import CurrencyLogo from 'components/Logo/CurrencyLogo'
import { isSupportedChain } from 'constants/chains'
import { darken } from 'polished'
import { ReactNode, useCallback, useState } from 'react'
import { ReactNode, useCallback, useEffect, useState } from 'react'
import { Lock } from 'react-feather'
import styled, { useTheme } from 'styled-components/macro'
import { flexColumnNoWrap, flexRowNoWrap } from 'theme/styles'
@@ -62,7 +62,7 @@ const CurrencySelect = styled(ButtonGray)<{
background-color: ${({ selected, theme }) => (selected ? theme.backgroundInteractive : theme.accentAction)};
opacity: ${({ disabled }) => (!disabled ? 1 : 0.4)};
box-shadow: ${({ selected }) => (selected ? 'none' : '0px 6px 10px rgba(0, 0, 0, 0.075)')};
color: ${({ selected, theme }) => (selected ? theme.deprecated_text1 : theme.deprecated_white)};
color: ${({ selected, theme }) => (selected ? theme.textPrimary : theme.white)};
cursor: pointer;
height: unset;
border-radius: 16px;
@@ -121,7 +121,7 @@ const LabelRow = styled.div`
span:hover {
cursor: pointer;
color: ${({ theme }) => darken(0.2, theme.deprecated_text2)};
color: ${({ theme }) => darken(0.2, theme.textSecondary)};
}
`
@@ -144,7 +144,7 @@ const StyledDropDown = styled(DropDown)<{ selected: boolean }>`
margin-left: 8px;
path {
stroke: ${({ selected, theme }) => (selected ? theme.deprecated_text1 : theme.deprecated_white)};
stroke: ${({ selected, theme }) => (selected ? theme.textPrimary : theme.white)};
stroke-width: 2px;
}
`
@@ -229,6 +229,7 @@ export default function SwapCurrencyInputPanel({
...rest
}: SwapCurrencyInputPanelProps) {
const [modalOpen, setModalOpen] = useState(false)
const [fiatValueIsLoading, setFiatValueIsLoading] = useState(false)
const { account, chainId } = useWeb3React()
const selectedCurrencyBalance = useCurrencyBalance(account ?? undefined, currency ?? undefined)
const theme = useTheme()
@@ -239,6 +240,10 @@ export default function SwapCurrencyInputPanel({
const chainAllowed = isSupportedChain(chainId)
useEffect(() => {
!!value && !fiatValue ? setFiatValueIsLoading(true) : setFiatValueIsLoading(false)
}, [fiatValueIsLoading, value, fiatValue])
return (
<InputPanel id={id} hideInput={hideInput} {...rest}>
{locked && (
@@ -306,7 +311,7 @@ export default function SwapCurrencyInputPanel({
<FiatRow>
<RowBetween>
<LoadingOpacityContainer $loading={loading}>
<FiatValue fiatValue={fiatValue} priceImpact={priceImpact} />
<FiatValue fiatValue={fiatValue} priceImpact={priceImpact} isLoading={fiatValueIsLoading} />
</LoadingOpacityContainer>
{account ? (
<RowFixed style={{ height: '17px' }}>

View File

@@ -29,7 +29,7 @@ const InputPanel = styled.div<{ hideInput?: boolean }>`
${flexColumnNoWrap};
position: relative;
border-radius: ${({ hideInput }) => (hideInput ? '16px' : '20px')};
background-color: ${({ theme, hideInput }) => (hideInput ? 'transparent' : theme.deprecated_bg2)};
background-color: ${({ theme, hideInput }) => (hideInput ? 'transparent' : theme.backgroundInteractive)};
z-index: 1;
width: ${({ hideInput }) => (hideInput ? '100%' : 'initial')};
transition: height 1s ease;
@@ -41,7 +41,7 @@ const FixedContainer = styled.div`
height: 100%;
position: absolute;
border-radius: 20px;
background-color: ${({ theme }) => theme.deprecated_bg2};
background-color: ${({ theme }) => theme.backgroundInteractive};
display: flex;
align-items: center;
justify-content: center;
@@ -50,7 +50,7 @@ const FixedContainer = styled.div`
const Container = styled.div<{ hideInput: boolean; disabled: boolean }>`
border-radius: ${({ hideInput }) => (hideInput ? '16px' : '20px')};
border: 1px solid ${({ theme }) => theme.deprecated_bg0};
border: 1px solid ${({ theme }) => theme.backgroundSurface};
background-color: ${({ theme }) => theme.deprecated_bg1};
width: ${({ hideInput }) => (hideInput ? '100%' : 'initial')};
${({ theme, hideInput, disabled }) =>
@@ -70,11 +70,11 @@ const CurrencySelect = styled(ButtonGray)<{
disabled?: boolean
}>`
align-items: center;
background-color: ${({ selected, theme }) => (selected ? theme.deprecated_bg2 : theme.deprecated_primary1)};
background-color: ${({ selected, theme }) => (selected ? theme.backgroundInteractive : theme.accentAction)};
opacity: ${({ disabled }) => (!disabled ? 1 : 0.4)};
box-shadow: ${({ selected }) => (selected ? 'none' : '0px 6px 10px rgba(0, 0, 0, 0.075)')};
box-shadow: 0px 6px 10px rgba(0, 0, 0, 0.075);
color: ${({ selected, theme }) => (selected ? theme.deprecated_text1 : theme.deprecated_white)};
color: ${({ selected, theme }) => (selected ? theme.textPrimary : theme.white)};
cursor: pointer;
border-radius: 16px;
outline: none;
@@ -89,8 +89,7 @@ const CurrencySelect = styled(ButtonGray)<{
margin-left: ${({ hideInput }) => (hideInput ? '0' : '12px')};
:focus,
:hover {
background-color: ${({ selected, theme }) =>
selected ? theme.deprecated_bg3 : darken(0.05, theme.deprecated_primary1)};
background-color: ${({ selected, theme }) => (selected ? theme.deprecated_bg3 : darken(0.05, theme.accentAction))};
}
visibility: ${({ visible }) => (visible ? 'visible' : 'hidden')};
`
@@ -105,13 +104,13 @@ const InputRow = styled.div<{ selected: boolean }>`
const LabelRow = styled.div`
${flexRowNoWrap};
align-items: center;
color: ${({ theme }) => theme.deprecated_text1};
color: ${({ theme }) => theme.textPrimary};
font-size: 0.75rem;
line-height: 1rem;
padding: 0 1rem 1rem;
span:hover {
cursor: pointer;
color: ${({ theme }) => darken(0.2, theme.deprecated_text2)};
color: ${({ theme }) => darken(0.2, theme.textSecondary)};
}
`
@@ -133,7 +132,7 @@ const StyledDropDown = styled(DropDown)<{ selected: boolean }>`
height: 35%;
path {
stroke: ${({ selected, theme }) => (selected ? theme.deprecated_text1 : theme.deprecated_white)};
stroke: ${({ selected, theme }) => (selected ? theme.textPrimary : theme.white)};
stroke-width: 1.5px;
}
`
@@ -148,7 +147,7 @@ const StyledBalanceMax = styled.button<{ disabled?: boolean }>`
background-color: ${({ theme }) => theme.deprecated_primary5};
border: none;
border-radius: 12px;
color: ${({ theme }) => theme.deprecated_primary1};
color: ${({ theme }) => theme.accentAction};
cursor: pointer;
font-size: 11px;
font-weight: 500;
@@ -300,7 +299,7 @@ export default function CurrencyInputPanel({
<RowFixed style={{ height: '17px' }}>
<ThemedText.DeprecatedBody
onClick={onMax}
color={theme.deprecated_text3}
color={theme.textTertiary}
fontWeight={500}
fontSize={14}
style={{ display: 'inline', cursor: 'pointer' }}

View File

@@ -1,11 +1,12 @@
import { Trans } from '@lingui/macro'
import * as Sentry from '@sentry/react'
import { ButtonLight, ButtonPrimary } from 'components/Button'
import { ButtonLight, SmallButtonPrimary } from 'components/Button'
import { ChevronUpIcon } from 'nft/components/icons'
import { useIsMobile } from 'nft/hooks'
import React, { PropsWithChildren, useState } from 'react'
import { Copy } from 'react-feather'
import styled from 'styled-components/macro'
import { isSentryEnabled } from 'utils/env'
import { CopyToClipboard, ExternalLink, ThemedText } from '../../theme'
import { Column } from '../Column'
@@ -23,13 +24,6 @@ const BodyWrapper = styled.div<{ margin?: string }>`
padding: 1rem;
`
const SmallButtonPrimary = styled(ButtonPrimary)`
width: auto;
font-size: 16px;
padding: 10px 16px;
border-radius: 12px;
`
const SmallButtonLight = styled(ButtonLight)`
font-size: 16px;
padding: 10px 16px;
@@ -92,6 +86,7 @@ const CodeTitle = styled.div`
display: flex;
gap: 14px;
align-items: center;
justify-content: space-between;
word-break: break-word;
`
@@ -99,49 +94,87 @@ const Fallback = ({ error, eventId }: { error: Error; eventId: string | null })
const [isExpanded, setExpanded] = useState(false)
const isMobile = useIsMobile()
const errorId = eventId || 'unknown-error'
// @todo: ThemedText components should be responsive by default
const [Title, Description] = isMobile
? [ThemedText.HeadlineSmall, ThemedText.BodySmall]
: [ThemedText.HeadlineLarge, ThemedText.BodySecondary]
const showErrorId = isSentryEnabled() && eventId
const showMoreButton = (
<ShowMoreButton onClick={() => setExpanded((s) => !s)}>
<ThemedText.Link color="textSecondary">
<Trans>{isExpanded ? 'Show less' : 'Show more'}</Trans>
</ThemedText.Link>
<ShowMoreIcon $isExpanded={isExpanded} secondaryWidth="20" secondaryHeight="20" />
</ShowMoreButton>
)
const errorDetails = error.stack || error.message
return (
<FallbackWrapper>
<BodyWrapper>
<Column gap="xl">
<Column gap="sm">
<Title textAlign="center">
<Trans>Something went wrong</Trans>
</Title>
<Description textAlign="center" color="textSecondary">
<Trans>
Sorry, an error occured while processing your request. If you request support, be sure to provide your
error ID.
</Trans>
</Description>
</Column>
<CodeBlockWrapper>
<CodeTitle>
<ThemedText.SubHeader fontWeight={500}>Error ID: {errorId}</ThemedText.SubHeader>
<CopyToClipboard toCopy={errorId}>
<CopyIcon />
</CopyToClipboard>
</CodeTitle>
<Separator />
{isExpanded && (
<>
<Code>{error.stack}</Code>
{showErrorId ? (
<>
<Column gap="sm">
<Title textAlign="center">
<Trans>Something went wrong</Trans>
</Title>
<Description textAlign="center" color="textSecondary">
<Trans>
Sorry, an error occured while processing your request. If you request support, be sure to provide
your error ID.
</Trans>
</Description>
</Column>
<CodeBlockWrapper>
<CodeTitle>
<ThemedText.SubHeader fontWeight={500}>
<Trans>Error ID: {eventId}</Trans>
</ThemedText.SubHeader>
<CopyToClipboard toCopy={eventId}>
<CopyIcon />
</CopyToClipboard>
</CodeTitle>
<Separator />
</>
)}
<ShowMoreButton onClick={() => setExpanded((s) => !s)}>
<ThemedText.Link color="textSecondary">
<Trans>{isExpanded ? 'Show less' : 'Show more'}</Trans>
</ThemedText.Link>
<ShowMoreIcon $isExpanded={isExpanded} secondaryWidth="20" secondaryHeight="20" />
</ShowMoreButton>
</CodeBlockWrapper>
{isExpanded && (
<>
<Code>{errorDetails}</Code>
<Separator />
</>
)}
{showMoreButton}
</CodeBlockWrapper>
</>
) : (
<>
<Column gap="sm">
<Title textAlign="center">
<Trans>Something went wrong</Trans>
</Title>
<Description textAlign="center" color="textSecondary">
<Trans>
Sorry, an error occured while processing your request. If you request support, be sure to copy the
details of this error.
</Trans>
</Description>
</Column>
<CodeBlockWrapper>
<CodeTitle>
<ThemedText.SubHeader fontWeight={500}>Error details</ThemedText.SubHeader>
<CopyToClipboard toCopy={errorDetails}>
<CopyIcon />
</CopyToClipboard>
</CodeTitle>
<Separator />
<Code>{errorDetails.split('\n').slice(0, isExpanded ? undefined : 4)}</Code>
<Separator />
{showMoreButton}
</CodeBlockWrapper>
</>
)}
<StretchedRow>
<SmallButtonPrimary onClick={() => window.location.reload()}>
<Trans>Reload the app</Trans>

View File

@@ -1,5 +1,5 @@
import { BaseVariant, FeatureFlag, featureFlagSettings, useUpdateFlag } from 'featureFlags'
import { LandingPageVariant, useLandingPageFlag } from 'featureFlags/flags/landingPage'
import { useFiatOnrampFlag } from 'featureFlags/flags/fiatOnramp'
import { Permit2Variant, usePermit2Flag } from 'featureFlags/flags/permit2'
import { TraceJsonRpcVariant, useTraceJsonRpcFlag } from 'featureFlags/flags/traceJsonRpc'
import { useAtomValue, useUpdateAtom } from 'jotai/utils'
@@ -164,7 +164,7 @@ function FeatureFlagGroup({ name, children }: PropsWithChildren<{ name: string }
)
}
function FeatureFlagOption({ variant, featureFlag, value, label }: FeatureFlagProps) {
function FeatureFlagOption({ variant, featureFlag, label }: FeatureFlagProps) {
const updateFlag = useUpdateFlag()
const [count, setCount] = useState(0)
const featureFlags = useAtomValue(featureFlagSettings)
@@ -203,18 +203,18 @@ export default function FeatureFlagModal() {
<X size={24} />
</CloseButton>
</Header>
<FeatureFlagOption
variant={LandingPageVariant}
value={useLandingPageFlag()}
featureFlag={FeatureFlag.landingPage}
label="Landing page"
/>
<FeatureFlagOption
variant={Permit2Variant}
value={usePermit2Flag()}
featureFlag={FeatureFlag.permit2}
label="Permit 2 / Universal Router"
/>
<FeatureFlagOption
variant={BaseVariant}
value={useFiatOnrampFlag()}
featureFlag={FeatureFlag.fiatOnramp}
label="Fiat on-ramp"
/>
<FeatureFlagGroup name="Debug">
<FeatureFlagOption
variant={TraceJsonRpcVariant}

View File

@@ -34,8 +34,8 @@ const pulse = (color: string) => keyframes`
}
`
const FocusedOutlineCard = styled(Card)<{ pulsing: boolean }>`
border: 1px solid ${({ theme }) => theme.deprecated_bg2};
animation: ${({ pulsing, theme }) => pulsing && pulse(theme.deprecated_primary1)} 0.6s linear;
border: 1px solid ${({ theme }) => theme.backgroundInteractive};
animation: ${({ pulsing, theme }) => pulsing && pulse(theme.accentAction)} 0.6s linear;
align-self: center;
`

View File

@@ -0,0 +1,149 @@
import { Trans } from '@lingui/macro'
import { sendAnalyticsEvent } from '@uniswap/analytics'
import { useWeb3React } from '@web3-react/core'
import fiatMaskUrl from 'assets/svg/fiat_mask.svg'
import { BaseVariant } from 'featureFlags'
import { useFiatOnrampFlag } from 'featureFlags/flags/fiatOnramp'
import { useCallback, useEffect } from 'react'
import { X } from 'react-feather'
import { useDispatch } from 'react-redux'
import { useToggleWalletDropdown } from 'state/application/hooks'
import { useAppSelector } from 'state/hooks'
import { useFiatOnrampAck } from 'state/user/hooks'
import { dismissFiatOnramp } from 'state/user/reducer'
import styled from 'styled-components/macro'
import { ThemedText } from 'theme'
import { isMobile } from 'utils/userAgent'
const Arrow = styled.div`
top: -4px;
height: 16px;
position: absolute;
right: 16px;
width: 16px;
::before {
background: hsl(315.75, 93%, 83%);
border-top: none;
border-left: none;
box-sizing: border-box;
content: '';
height: 16px;
position: absolute;
transform: rotate(45deg);
width: 16px;
}
`
const ArrowWrapper = styled.div`
position: absolute;
right: 16px;
top: 90%;
width: 100%;
max-width: 320px;
min-height: 92px;
@media screen and (min-width: ${({ theme }) => theme.breakpoint.lg}px) {
right: 36px;
}
`
const CloseIcon = styled(X)`
color: white;
cursor: pointer;
position: absolute;
top: 8px;
right: 8px;
z-index: 1;
`
const Wrapper = styled.button`
background: radial-gradient(105% 250% at 100% 5%, hsla(318, 95%, 85%) 1%, hsla(331, 80%, 75%, 0.1) 84%),
linear-gradient(180deg, hsla(296, 92%, 67%, 0.5) 0%, hsla(313, 96%, 60%, 0.5) 130%);
background-color: hsla(297, 93%, 68%, 1);
border-radius: 12px;
border: none;
cursor: pointer;
outline: none;
overflow: hidden;
position: relative;
text-align: start;
max-width: 320px;
min-height: 92px;
width: 100%;
:before {
background-image: url(${fiatMaskUrl});
background-repeat: no-repeat;
content: '';
height: 100%;
position: absolute;
right: -154px; // roughly width of fiat mask image
top: 0;
width: 100%;
}
`
const Header = styled(ThemedText.SubHeader)`
color: white;
margin: 0;
padding: 12px 12px 4px;
position: relative;
`
const Body = styled(ThemedText.BodySmall)`
color: white;
margin: 0 12px 12px 12px !important;
position: relative;
`
const MAX_RENDER_COUNT = 3
export function FiatOnrampAnnouncement() {
const { account } = useWeb3React()
const [acks, acknowledge] = useFiatOnrampAck()
const fiatOnrampDismissed = useAppSelector((state) => state.user.fiatOnrampDismissed)
useEffect(() => {
acknowledge({ renderCount: acks?.renderCount + 1 })
// The dependency list is empty so this is only run once on mount
}, []) // eslint-disable-line react-hooks/exhaustive-deps
const dispatch = useDispatch()
const handleClose = useCallback(() => {
dispatch(dismissFiatOnramp())
}, [dispatch])
const toggleWalletDropdown = useToggleWalletDropdown()
const handleClick = useCallback(() => {
sendAnalyticsEvent('FOR Banner Click')
toggleWalletDropdown()
acknowledge({ user: true })
}, [acknowledge, toggleWalletDropdown])
const fiatOnrampFlag = useFiatOnrampFlag()
const openModal = useAppSelector((state) => state.application.openModal)
if (
!account ||
acks?.user ||
fiatOnrampFlag === BaseVariant.Control ||
fiatOnrampDismissed ||
acks?.renderCount >= MAX_RENDER_COUNT ||
isMobile ||
openModal !== null
) {
return null
}
return (
<ArrowWrapper>
<Arrow />
<CloseIcon onClick={handleClose} />
<Wrapper onClick={handleClick}>
<Header>
<Trans>Buy crypto</Trans>
</Header>
<Body>
<Trans>Get tokens at the best prices in web3 on Uniswap, powered by Moonpay.</Trans>
</Body>
</Wrapper>
</ArrowWrapper>
)
}

View File

@@ -0,0 +1,143 @@
import { Trans } from '@lingui/macro'
import { useWeb3React } from '@web3-react/core'
import { useCallback, useEffect, useState } from 'react'
import { useCloseModal, useModalIsOpen } from 'state/application/hooks'
import { ApplicationModal } from 'state/application/reducer'
import styled, { useTheme } from 'styled-components/macro'
import { CustomLightSpinner, ThemedText } from 'theme'
import Circle from '../../assets/images/blue-loader.svg'
import Modal from '../Modal'
const Wrapper = styled.div`
background-color: ${({ theme }) => theme.white};
border-radius: 20px;
box-shadow: ${({ theme }) => theme.deepShadow};
display: flex;
flex-flow: column nowrap;
margin: 0;
min-height: 720px;
min-width: 375px;
position: relative;
width: 100%;
`
const ErrorText = styled(ThemedText.BodyPrimary)`
color: ${({ theme }) => theme.accentFailure};
margin: auto !important;
text-align: center;
width: 90%;
`
const StyledIframe = styled.iframe`
background-color: ${({ theme }) => theme.white};
border-radius: 12px;
bottom: 0;
left: 0;
height: calc(100% - 16px);
margin: 8px;
padding: 0;
position: absolute;
right: 0;
top: 0;
width: calc(100% - 16px);
`
const StyledSpinner = styled(CustomLightSpinner)`
bottom: 0;
left: 0;
margin: auto;
position: absolute;
right: 0;
top: 0;
`
const MOONPAY_SUPPORTED_CURRENCY_CODES = [
'eth',
'eth_arbitrum',
'eth_optimism',
'eth_polygon',
'weth',
'wbtc',
'matic_polygon',
'polygon',
'usdc_arbitrum',
'usdc_optimism',
'usdc_polygon',
]
export default function FiatOnrampModal() {
const { account } = useWeb3React()
const theme = useTheme()
const closeModal = useCloseModal()
const fiatOnrampModalOpen = useModalIsOpen(ApplicationModal.FIAT_ONRAMP)
const [signedIframeUrl, setSignedIframeUrl] = useState<string | null>(null)
const [error, setError] = useState<string | null>(null)
const [loading, setLoading] = useState(false)
const fetchSignedIframeUrl = useCallback(async () => {
if (!account) {
setError('Please connect an account before making a purchase.')
return
}
setLoading(true)
setError(null)
try {
const signedIframeUrlFetchEndpoint = process.env.REACT_APP_MOONPAY_LINK as string
const res = await fetch(signedIframeUrlFetchEndpoint, {
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
method: 'POST',
body: JSON.stringify({
colorCode: theme.accentAction,
defaultCurrencyCode: 'eth',
redirectUrl: 'https://app.uniswap.org/#/swap',
walletAddresses: JSON.stringify(
MOONPAY_SUPPORTED_CURRENCY_CODES.reduce(
(acc, currencyCode) => ({
...acc,
[currencyCode]: account,
}),
{}
)
),
}),
})
const { url } = await res.json()
setSignedIframeUrl(url)
} catch (e) {
console.log('there was an error fetching the link', e)
setError(e.toString())
} finally {
setLoading(false)
}
}, [account, theme.accentAction])
useEffect(() => {
fetchSignedIframeUrl()
}, [fetchSignedIframeUrl])
return (
<Modal isOpen={fiatOnrampModalOpen} onDismiss={closeModal} maxHeight={720}>
<Wrapper data-testid="fiat-onramp-modal">
{error ? (
<>
<ThemedText.MediumHeader>
<Trans>Moonpay Fiat On-ramp iframe</Trans>
</ThemedText.MediumHeader>
<ErrorText>
<Trans>something went wrong!</Trans>
<br />
{error}
</ErrorText>
</>
) : loading ? (
<StyledSpinner src={Circle} alt="loading spinner" size="90px" />
) : (
<StyledIframe src={signedIframeUrl ?? ''} frameBorder="0" title="fiat-onramp-iframe" />
)}
</Wrapper>
</Modal>
)
}

View File

@@ -36,9 +36,9 @@ const SmallButton = styled(ButtonGray)`
`
const FocusedOutlineCard = styled(OutlineCard)<{ active?: boolean; pulsing?: boolean }>`
border-color: ${({ active, theme }) => active && theme.deprecated_blue1};
border-color: ${({ active, theme }) => active && theme.accentAction};
padding: 12px;
animation: ${({ pulsing, theme }) => pulsing && pulse(theme.deprecated_blue1)} 0.8s linear;
animation: ${({ pulsing, theme }) => pulsing && pulse(theme.accentAction)} 0.8s linear;
`
const StyledInput = styled(NumericalInput)<{ usePercent?: boolean }>`
@@ -58,13 +58,13 @@ const StyledInput = styled(NumericalInput)<{ usePercent?: boolean }>`
`
const InputTitle = styled(ThemedText.DeprecatedSmall)`
color: ${({ theme }) => theme.deprecated_text2};
color: ${({ theme }) => theme.textSecondary};
font-size: 12px;
font-weight: 500;
`
const ButtonLabel = styled(ThemedText.DeprecatedWhite)<{ disabled: boolean }>`
color: ${({ theme, disabled }) => (disabled ? theme.deprecated_text2 : theme.deprecated_text1)} !important;
color: ${({ theme, disabled }) => (disabled ? theme.textSecondary : theme.textPrimary)} !important;
`
interface StepCounterProps {

View File

@@ -6,8 +6,8 @@ import { ChartEntry } from './types'
const Path = styled.path<{ fill: string | undefined }>`
opacity: 0.5;
stroke: ${({ fill, theme }) => fill ?? theme.deprecated_blue2};
fill: ${({ fill, theme }) => fill ?? theme.deprecated_blue2};
stroke: ${({ fill, theme }) => fill ?? theme.accentAction};
fill: ${({ fill, theme }) => fill ?? theme.accentAction};
`
export const Area = ({

View File

@@ -8,7 +8,7 @@ const StyledGroup = styled.g`
}
text {
color: ${({ theme }) => theme.deprecated_text2};
color: ${({ theme }) => theme.textSecondary};
transform: translateY(5px);
}
`

View File

@@ -18,7 +18,7 @@ const HandleAccent = styled.path`
pointer-events: none;
stroke-width: 1.5;
stroke: ${({ theme }) => theme.deprecated_white};
stroke: ${({ theme }) => theme.white};
opacity: ${({ theme }) => theme.opacity.hover};
`
@@ -28,13 +28,13 @@ const LabelGroup = styled.g<{ visible: boolean }>`
`
const TooltipBackground = styled.rect`
fill: ${({ theme }) => theme.deprecated_bg2};
fill: ${({ theme }) => theme.backgroundInteractive};
`
const Tooltip = styled.text`
text-anchor: middle;
font-size: 13px;
fill: ${({ theme }) => theme.deprecated_text1};
fill: ${({ theme }) => theme.textPrimary};
`
// flips the handles draggers when close to the container edges

View File

@@ -5,7 +5,7 @@ import styled from 'styled-components/macro'
const StyledLine = styled.line`
opacity: 0.5;
stroke-width: 2;
stroke: ${({ theme }) => theme.deprecated_text1};
stroke: ${({ theme }) => theme.textPrimary};
fill: none;
`

View File

@@ -18,8 +18,8 @@ const Wrapper = styled.div<{ count: number }>`
const Button = styled(ButtonGray)`
&:hover {
background-color: ${({ theme }) => theme.deprecated_bg2};
color: ${({ theme }) => theme.deprecated_text1};
background-color: ${({ theme }) => theme.backgroundInteractive};
color: ${({ theme }) => theme.textPrimary};
}
width: 32px;

View File

@@ -167,7 +167,7 @@ export default function LiquidityChartRangeInput({
{isUninitialized ? (
<InfoBox
message={<Trans>Your position will appear here.</Trans>}
icon={<Inbox size={56} stroke={theme.deprecated_text1} />}
icon={<Inbox size={56} stroke={theme.textPrimary} />}
/>
) : isLoading ? (
<InfoBox icon={<Loader size="40px" stroke={theme.deprecated_text4} />} />
@@ -189,12 +189,12 @@ export default function LiquidityChartRangeInput({
margins={{ top: 10, right: 2, bottom: 20, left: 0 }}
styles={{
area: {
selection: theme.deprecated_blue1,
selection: theme.accentAction,
},
brush: {
handle: {
west: saturate(0.1, tokenAColor) ?? theme.deprecated_red1,
east: saturate(0.1, tokenBColor) ?? theme.deprecated_blue1,
west: saturate(0.1, tokenAColor) ?? theme.accentFailure,
east: saturate(0.1, tokenBColor) ?? theme.accentAction,
},
},
}}

View File

@@ -18,7 +18,7 @@ export const LoadingRows = styled.div`
background: linear-gradient(
to left,
${({ theme }) => theme.deprecated_bg1} 25%,
${({ theme }) => theme.deprecated_bg2} 50%,
${({ theme }) => theme.backgroundInteractive} 50%,
${({ theme }) => theme.deprecated_bg1} 75%
);
background-size: 400%;

View File

@@ -15,7 +15,7 @@ export enum FlyoutAlignment {
const StyledMenuIcon = styled(MenuIcon)`
path {
stroke: ${({ theme }) => theme.deprecated_text1};
stroke: ${({ theme }) => theme.textPrimary};
}
`
@@ -35,7 +35,7 @@ const MenuFlyout = styled.span<{ flyoutAlignment?: FlyoutAlignment }>`
background-color: ${({ theme }) => theme.deprecated_bg1};
box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.01), 0px 4px 8px rgba(0, 0, 0, 0.04), 0px 16px 24px rgba(0, 0, 0, 0.04),
0px 24px 32px rgba(0, 0, 0, 0.01);
border: 1px solid ${({ theme }) => theme.deprecated_bg0};
border: 1px solid ${({ theme }) => theme.backgroundSurface};
border-radius: 12px;
padding: 0.5rem;
display: flex;
@@ -67,9 +67,9 @@ const MenuItem = styled(ExternalLink)`
align-items: center;
padding: 0.5rem 0.5rem;
justify-content: space-between;
color: ${({ theme }) => theme.deprecated_text2};
color: ${({ theme }) => theme.textSecondary};
:hover {
color: ${({ theme }) => theme.deprecated_text1};
color: ${({ theme }) => theme.textPrimary};
cursor: pointer;
text-decoration: none;
}
@@ -78,11 +78,11 @@ const MenuItem = styled(ExternalLink)`
const InternalMenuItem = styled(Link)`
flex: 1;
padding: 0.5rem 0.5rem;
color: ${({ theme }) => theme.deprecated_text2};
color: ${({ theme }) => theme.textSecondary};
width: max-content;
text-decoration: none;
:hover {
color: ${({ theme }) => theme.deprecated_text1};
color: ${({ theme }) => theme.textPrimary};
cursor: pointer;
text-decoration: none;
}

View File

@@ -9,7 +9,7 @@ import { isMobile } from '../../utils/userAgent'
const AnimatedDialogOverlay = animated(DialogOverlay)
const StyledDialogOverlay = styled(AnimatedDialogOverlay)<{ scrollOverlay?: boolean }>`
const StyledDialogOverlay = styled(AnimatedDialogOverlay)<{ $scrollOverlay?: boolean }>`
&[data-reach-dialog-overlay] {
z-index: ${Z_INDEX.modalBackdrop};
background-color: transparent;
@@ -17,7 +17,7 @@ const StyledDialogOverlay = styled(AnimatedDialogOverlay)<{ scrollOverlay?: bool
display: flex;
align-items: center;
overflow-y: ${({ scrollOverlay }) => scrollOverlay && 'scroll'};
overflow-y: ${({ $scrollOverlay }) => $scrollOverlay && 'scroll'};
justify-content: center;
background-color: ${({ theme }) => theme.backgroundScrim};
@@ -39,7 +39,7 @@ const StyledDialogContent = styled(AnimatedDialogContent)<StyledDialogProps>`
&[data-reach-dialog-content] {
margin: auto;
background-color: ${({ theme }) => theme.deprecated_bg0};
background-color: ${({ theme }) => theme.backgroundSurface};
border: ${({ theme, $hideBorder }) => !$hideBorder && `1px solid ${theme.deprecated_bg1}`};
box-shadow: ${({ theme }) => theme.deepShadow};
padding: 0px;
@@ -89,7 +89,7 @@ interface ModalProps {
maxWidth?: number
initialFocusRef?: React.RefObject<any>
children?: React.ReactNode
scrollOverlay?: boolean
$scrollOverlay?: boolean
hideBorder?: boolean
isBottomSheet?: boolean
}
@@ -103,7 +103,7 @@ export default function Modal({
initialFocusRef,
children,
onSwipe = onDismiss,
scrollOverlay,
$scrollOverlay,
isBottomSheet = isMobile,
hideBorder = false,
}: ModalProps) {
@@ -136,7 +136,7 @@ export default function Modal({
onDismiss={onDismiss}
initialFocusRef={initialFocusRef}
unstable_lockFocusAcrossFrames={false}
scrollOverlay={scrollOverlay}
$scrollOverlay={$scrollOverlay}
>
<StyledDialogContent
{...(isMobile
@@ -149,7 +149,7 @@ export default function Modal({
$minHeight={minHeight}
$maxHeight={maxHeight}
$isBottomSheet={isBottomSheet}
$scrollOverlay={scrollOverlay}
$scrollOverlay={$scrollOverlay}
$hideBorder={hideBorder}
$maxWidth={maxWidth}
>

View File

@@ -58,7 +58,7 @@ export function SubmittedView({
<CloseIcon onClick={onDismiss} />
</RowBetween>
<ConfirmedIcon>
<ArrowUpCircle strokeWidth={0.5} size={90} color={theme.deprecated_primary1} />
<ArrowUpCircle strokeWidth={0.5} size={90} color={theme.accentAction} />
</ConfirmedIcon>
<AutoColumn gap="100px" justify="center">
{children}

View File

@@ -16,6 +16,7 @@ import { body, bodySmall } from 'nft/css/common.css'
import { themeVars } from 'nft/css/sprinkles.css'
import { ReactNode, useReducer, useRef } from 'react'
import { NavLink, NavLinkProps } from 'react-router-dom'
import styled from 'styled-components/macro'
import { isDevelopmentEnv, isStagingEnv } from 'utils/env'
import { useToggleModal } from '../../state/application/hooks'
@@ -50,8 +51,13 @@ const PrimaryMenuRow = ({
)
}
const StyledBox = styled(Box)`
align-items: center;
display: flex;
justify-content: center;
`
const PrimaryMenuRowText = ({ children }: { children: ReactNode }) => {
return <Box className={`${styles.PrimaryText} ${body}`}>{children}</Box>
return <StyledBox className={`${styles.PrimaryText} ${body}`}>{children}</StyledBox>
}
PrimaryMenuRow.Text = PrimaryMenuRowText
@@ -115,7 +121,6 @@ export const MenuDropdown = () => {
const [isOpen, toggleOpen] = useReducer((s) => !s, false)
const togglePrivacyPolicy = useToggleModal(ApplicationModal.PRIVACY_POLICY)
const openFeatureFlagsModal = useToggleModal(ApplicationModal.FEATURE_FLAGS)
const ref = useRef<HTMLDivElement>(null)
useOnClickOutside(ref, isOpen ? toggleOpen : undefined)

View File

@@ -10,7 +10,6 @@ const baseNavDropdown = style([
borderWidth: '1px',
paddingBottom: '8',
paddingTop: '8',
zIndex: '2',
}),
{
boxShadow: '0px 4px 12px 0px #00000026',

View File

@@ -1,12 +1,20 @@
import { Box, BoxProps } from 'nft/components/Box'
import { useIsMobile } from 'nft/hooks'
import { ForwardedRef, forwardRef } from 'react'
import { Z_INDEX } from 'theme/zIndex'
import * as styles from './NavDropdown.css'
export const NavDropdown = forwardRef((props: BoxProps, ref: ForwardedRef<HTMLElement>) => {
const isMobile = useIsMobile()
return <Box ref={ref} className={isMobile ? styles.mobileNavDropdown : styles.NavDropdown} {...props} />
return (
<Box
ref={ref}
style={{ zIndex: Z_INDEX.modal }}
className={isMobile ? styles.mobileNavDropdown : styles.NavDropdown}
{...props}
/>
)
})
NavDropdown.displayName = 'NavDropdown'

View File

@@ -1,5 +1,5 @@
// eslint-disable-next-line no-restricted-imports
import { t } from '@lingui/macro'
import { t, Trans } from '@lingui/macro'
import { sendAnalyticsEvent, Trace, TraceEvent, useTrace } from '@uniswap/analytics'
import { BrowserEvent, ElementName, EventName, SectionName } from '@uniswap/analytics-events'
import clsx from 'clsx'
@@ -156,9 +156,9 @@ export const SearchBar = () => {
>
<Row
className={clsx(
` ${styles.nftSearchBar} ${!isOpen && !isMobile && magicalGradientOnHover} ${
isMobileOrTablet && (isOpen ? styles.visible : styles.hidden)
} `
styles.nftSearchBar,
!isOpen && !isMobile && magicalGradientOnHover,
isMobileOrTablet && (isOpen ? styles.visible : styles.hidden)
)}
borderRadius={isOpen || isMobileOrTablet ? undefined : '12'}
borderTopRightRadius={isOpen && !isMobile ? '12' : undefined}
@@ -182,18 +182,23 @@ export const SearchBar = () => {
element={ElementName.NAVBAR_SEARCH_INPUT}
properties={{ ...trace }}
>
<Box
as="input"
placeholder={placeholderText}
onChange={(event: ChangeEvent<HTMLInputElement>) => {
!isOpen && toggleOpen()
setSearchValue(event.target.value)
}}
onBlur={() => sendAnalyticsEvent(EventName.NAVBAR_SEARCH_EXITED, navbarSearchEventProperties)}
className={`${styles.searchBarInput} ${styles.searchContentLeftAlign}`}
value={searchValue}
ref={inputRef}
width="full"
<Trans
id={placeholderText}
render={({ translation }) => (
<Box
as="input"
placeholder={translation as string}
onChange={(event: ChangeEvent<HTMLInputElement>) => {
!isOpen && toggleOpen()
setSearchValue(event.target.value)
}}
onBlur={() => sendAnalyticsEvent(EventName.NAVBAR_SEARCH_EXITED, navbarSearchEventProperties)}
className={`${styles.searchBarInput} ${styles.searchContentLeftAlign}`}
value={searchValue}
ref={inputRef}
width="full"
/>
)}
/>
</TraceEvent>
{!isOpen && <KeyShortCut>/</KeyShortCut>}

View File

@@ -16,21 +16,11 @@ import { MenuDropdown } from './MenuDropdown'
import { SearchBar } from './SearchBar'
import * as styles from './style.css'
const MobileBottomBar = styled.div`
position: fixed;
display: flex;
bottom: 0;
right: 0;
left: 0;
justify-content: space-between;
padding: 4px 8px;
height: 56px;
background: ${({ theme }) => theme.backgroundSurface};
border-top: 1px solid ${({ theme }) => theme.backgroundOutline};
@media screen and (min-width: ${({ theme }) => theme.breakpoint.md}px) {
display: none;
}
const Nav = styled.nav`
padding: 20px 12px;
width: 100%;
height: ${({ theme }) => theme.navHeight}px;
z-index: 2;
`
interface MenuItemProps {
@@ -38,22 +28,24 @@ interface MenuItemProps {
id?: NavLinkProps['id']
isActive?: boolean
children: ReactNode
dataTestId?: string
}
const MenuItem = ({ href, id, isActive, children }: MenuItemProps) => {
const MenuItem = ({ href, dataTestId, id, isActive, children }: MenuItemProps) => {
return (
<NavLink
to={href}
className={isActive ? styles.activeMenuItem : styles.menuItem}
id={id}
style={{ textDecoration: 'none' }}
data-testid={dataTestId}
>
{children}
</NavLink>
)
}
const PageTabs = () => {
export const PageTabs = () => {
const { pathname } = useLocation()
const { chainId: connectedChainId } = useWeb3React()
const chainName = chainIdToBackendName(connectedChainId)
@@ -75,7 +67,7 @@ const PageTabs = () => {
<MenuItem href={`/tokens/${chainName.toLowerCase()}`} isActive={pathname.startsWith('/tokens')}>
<Trans>Tokens</Trans>
</MenuItem>
<MenuItem href="/nfts" isActive={isNftPage}>
<MenuItem dataTestId="nft-nav" href="/nfts" isActive={isNftPage}>
<Trans>NFTs</Trans>
</MenuItem>
<MenuItem href="/pool" id="pool-nav-link" isActive={isPoolActive}>
@@ -91,16 +83,20 @@ const Navbar = () => {
return (
<>
<nav className={styles.nav}>
<Box display="flex" height="full" flexWrap="nowrap" alignItems="stretch">
<Nav>
<Box display="flex" height="full" flexWrap="nowrap">
<Box className={styles.leftSideContainer}>
<Box className={styles.logoContainer}>
<UniIcon
width="48"
height="48"
data-testid="uniswap-logo"
className={styles.logo}
onClick={() => {
navigate('/')
navigate({
pathname: '/',
search: '?intro=true',
})
}}
/>
</Box>
@@ -113,7 +109,7 @@ const Navbar = () => {
<PageTabs />
</Row>
</Box>
<Box className={styles.middleContainer} alignItems="flex-start">
<Box className={styles.searchContainer}>
<SearchBar />
</Box>
<Box className={styles.rightSideContainer}>
@@ -135,13 +131,7 @@ const Navbar = () => {
</Row>
</Box>
</Box>
</nav>
<MobileBottomBar>
<PageTabs />
<Box marginY="4">
<MenuDropdown />
</Box>
</MobileBottomBar>
</Nav>
</>
)
}

View File

@@ -3,25 +3,10 @@ import { style } from '@vanilla-extract/css'
import { subhead } from '../../nft/css/common.css'
import { sprinkles, vars } from '../../nft/css/sprinkles.css'
export const nav = style([
sprinkles({
paddingX: '20',
paddingY: '12',
width: 'full',
height: '72',
zIndex: '2',
background: 'backgroundFloating',
}),
{
backdropFilter: 'blur(24px)',
},
])
export const logoContainer = style([
sprinkles({
display: 'flex',
marginRight: { sm: '12', xxl: '20' },
alignItems: 'center',
cursor: 'pointer',
}),
])
@@ -45,16 +30,19 @@ export const baseSideContainer = style([
export const leftSideContainer = style([
baseSideContainer,
sprinkles({
alignItems: 'center',
justifyContent: 'flex-start',
}),
])
export const middleContainer = style([
export const searchContainer = style([
sprinkles({
flex: '1',
flexShrink: '1',
justifyContent: { lg: 'flex-end', xl: 'center' },
display: { sm: 'none', xl: 'flex' },
alignSelf: 'center',
height: '48',
alignItems: 'flex-start',
}),
])
@@ -62,6 +50,7 @@ export const middleContainer = style([
export const rightSideContainer = style([
baseSideContainer,
sprinkles({
alignItems: 'center',
justifyContent: 'flex-end',
}),
])

View File

@@ -36,7 +36,7 @@ const ActiveText = styled.div`
`
const StyledArrowLeft = styled(ArrowLeft)`
color: ${({ theme }) => theme.deprecated_text1};
color: ${({ theme }) => theme.textPrimary};
`
export function FindPoolTabs({ origin }: { origin: string }) {
@@ -76,7 +76,7 @@ export function AddRemoveTabs({
// detect if back should redirect to v3 or v2 pool page
const poolLink = location.pathname.includes('add/v2')
? '/pool/v2'
: '/pool' + (!!positionID ? `/${positionID.toString()}` : '')
: '/pool' + (positionID ? `/${positionID.toString()}` : '')
return (
<Tabs>
@@ -92,7 +92,7 @@ export function AddRemoveTabs({
}}
flex={children ? '1' : undefined}
>
<StyledArrowLeft stroke={theme.deprecated_text2} />
<StyledArrowLeft stroke={theme.textSecondary} />
</StyledHistoryLink>
<ThemedText.DeprecatedMediumHeader
fontWeight={500}

View File

@@ -4,7 +4,7 @@ import styled from 'styled-components/macro'
import { escapeRegExp } from '../../utils'
const StyledInput = styled.input<{ error?: boolean; fontSize?: string; align?: string }>`
color: ${({ error, theme }) => (error ? theme.deprecated_red1 : theme.deprecated_text1)};
color: ${({ error, theme }) => (error ? theme.accentFailure : theme.textPrimary)};
width: 0;
position: relative;
font-weight: 400;

View File

@@ -17,7 +17,7 @@ const CautionTriangle = styled(AlertTriangle)`
color: ${({ theme }) => theme.accentWarning};
`
const Link = styled(ExternalLink)`
color: ${({ theme }) => theme.deprecated_black};
color: ${({ theme }) => theme.black};
text-decoration: underline;
`
const TitleRow = styled.div`

View File

@@ -4,6 +4,7 @@ import { RowFixed } from 'components/Row'
import { getChainInfo } from 'constants/chainInfo'
import useCurrentBlockTimestamp from 'hooks/useCurrentBlockTimestamp'
import useGasPrice from 'hooks/useGasPrice'
import { useIsLandingPage } from 'hooks/useIsLandingPage'
import { useIsNftPage } from 'hooks/useIsNftPage'
import useMachineTimeMs from 'hooks/useMachineTime'
import JSBI from 'jsbi'
@@ -44,7 +45,7 @@ const StyledPollingBlockNumber = styled(ThemedText.DeprecatedSmall)<{
hovering: boolean
warning: boolean
}>`
color: ${({ theme, warning }) => (warning ? theme.deprecated_yellow3 : theme.deprecated_green1)};
color: ${({ theme, warning }) => (warning ? theme.deprecated_yellow3 : theme.accentSuccess)};
transition: opacity 0.25s ease;
opacity: ${({ breathe, hovering }) => (hovering ? 0.7 : breathe ? 1 : 0.5)};
:hover {
@@ -66,12 +67,12 @@ const StyledPollingDot = styled.div<{ warning: boolean }>`
min-width: 8px;
border-radius: 50%;
position: relative;
background-color: ${({ theme, warning }) => (warning ? theme.deprecated_yellow3 : theme.deprecated_green1)};
background-color: ${({ theme, warning }) => (warning ? theme.deprecated_yellow3 : theme.accentSuccess)};
transition: 250ms ease background-color;
`
const StyledGasDot = styled.div`
background-color: ${({ theme }) => theme.deprecated_text3};
background-color: ${({ theme }) => theme.textTertiary};
border-radius: 50%;
height: 4px;
min-height: 4px;
@@ -97,7 +98,7 @@ const Spinner = styled.div<{ warning: boolean }>`
border-top: 1px solid transparent;
border-right: 1px solid transparent;
border-bottom: 1px solid transparent;
border-left: 2px solid ${({ theme, warning }) => (warning ? theme.deprecated_yellow3 : theme.deprecated_green1)};
border-left: 2px solid ${({ theme, warning }) => (warning ? theme.deprecated_yellow3 : theme.accentSuccess)};
background: transparent;
width: 14px;
height: 14px;
@@ -120,6 +121,7 @@ export default function Polling() {
const machineTime = useMachineTimeMs(NETWORK_HEALTH_CHECK_MS)
const blockTime = useCurrentBlockTimestamp()
const isNftPage = useIsNftPage()
const isLandingPage = useIsLandingPage()
const ethGasPrice = useGasPrice()
const priceGwei = ethGasPrice ? JSBI.divide(ethGasPrice, JSBI.BigInt(1000000000)) : undefined
@@ -154,7 +156,7 @@ export default function Polling() {
return getExplorerLink(chainId, blockNumber.toString(), ExplorerDataType.BLOCK)
}, [blockNumber, chainId])
if (isNftPage) {
if (isNftPage || isLandingPage) {
return null
}

View File

@@ -12,7 +12,7 @@ const PopoverContainer = styled.div<{ show: boolean }>`
visibility: ${(props) => (props.show ? 'visible' : 'hidden')};
opacity: ${(props) => (props.show ? 1 : 0)};
transition: visibility 150ms linear, opacity 150ms linear;
color: ${({ theme }) => theme.deprecated_text2};
color: ${({ theme }) => theme.textSecondary};
`
const ReferenceElement = styled.div`
@@ -33,9 +33,9 @@ const Arrow = styled.div`
z-index: 9998;
content: '';
border: 1px solid ${({ theme }) => theme.deprecated_bg2};
border: 1px solid ${({ theme }) => theme.backgroundInteractive};
transform: rotate(45deg);
background: ${({ theme }) => theme.deprecated_bg0};
background: ${({ theme }) => theme.backgroundSurface};
}
&.arrow-top {

View File

@@ -21,7 +21,7 @@ const Popup = styled.div`
display: inline-block;
width: 100%;
padding: 1em;
background-color: ${({ theme }) => theme.deprecated_bg0};
background-color: ${({ theme }) => theme.backgroundSurface};
position: relative;
border-radius: 10px;
padding: 20px;

View File

@@ -9,14 +9,12 @@ import { AutoColumn } from '../Column'
import ClaimPopup from './ClaimPopup'
import PopupItem from './PopupItem'
const MobilePopupWrapper = styled.div<{ height: string | number }>`
const MobilePopupWrapper = styled.div`
position: relative;
max-width: 100%;
height: ${({ height }) => height};
margin: ${({ height }) => (height ? '0 auto;' : 0)};
margin-bottom: ${({ height }) => (height ? '20px' : 0)};
margin: 0 auto;
display: none;
${({ theme }) => theme.deprecated_mediaWidth.deprecated_upToSmall`
display: block;
padding-top: 20px;
@@ -74,16 +72,18 @@ export default function Popups() {
<PopupItem key={item.key} content={item.content} popKey={item.key} removeAfterMs={item.removeAfterMs} />
))}
</FixedPopupColumn>
<MobilePopupWrapper height={activePopups?.length > 0 ? 'fit-content' : 0}>
<MobilePopupInner>
{activePopups // reverse so new items up front
.slice(0)
.reverse()
.map((item) => (
<PopupItem key={item.key} content={item.content} popKey={item.key} removeAfterMs={item.removeAfterMs} />
))}
</MobilePopupInner>
</MobilePopupWrapper>
{activePopups?.length > 0 && (
<MobilePopupWrapper>
<MobilePopupInner>
{activePopups // reverse so new items up front
.slice(0)
.reverse()
.map((item) => (
<PopupItem key={item.key} content={item.content} popKey={item.key} removeAfterMs={item.removeAfterMs} />
))}
</MobilePopupInner>
</MobilePopupWrapper>
)}
</>
)
}

View File

@@ -29,7 +29,7 @@ const LinkRow = styled(Link)`
display: flex;
flex-direction: column;
justify-content: space-between;
color: ${({ theme }) => theme.deprecated_text1};
color: ${({ theme }) => theme.textPrimary};
padding: 16px;
text-decoration: none;
font-weight: 500;
@@ -73,7 +73,7 @@ const RangeLineItem = styled(DataLineItem)`
const DoubleArrow = styled.span`
margin: 0 2px;
color: ${({ theme }) => theme.deprecated_text3};
color: ${({ theme }) => theme.textTertiary};
`
const RangeText = styled.span`
@@ -82,7 +82,7 @@ const RangeText = styled.span`
`
const ExtentsText = styled.span`
color: ${({ theme }) => theme.deprecated_text3};
color: ${({ theme }) => theme.textTertiary};
font-size: 14px;
margin-right: 4px;
${({ theme }) => theme.deprecated_mediaWidth.deprecated_upToSmall`

View File

@@ -135,11 +135,7 @@ export const PositionPreview = ({
{quoteCurrency.symbol} per {baseCurrency.symbol}
</Trans>
</ThemedText.DeprecatedMain>
<ThemedText.DeprecatedSmall
textAlign="center"
color={theme.deprecated_text3}
style={{ marginTop: '4px' }}
>
<ThemedText.DeprecatedSmall textAlign="center" color={theme.textTertiary} style={{ marginTop: '4px' }}>
<Trans>Your position will be 100% composed of {baseCurrency?.symbol} at this price</Trans>
</ThemedText.DeprecatedSmall>
</AutoColumn>
@@ -160,11 +156,7 @@ export const PositionPreview = ({
{quoteCurrency.symbol} per {baseCurrency.symbol}
</Trans>
</ThemedText.DeprecatedMain>
<ThemedText.DeprecatedSmall
textAlign="center"
color={theme.deprecated_text3}
style={{ marginTop: '4px' }}
>
<ThemedText.DeprecatedSmall textAlign="center" color={theme.textTertiary} style={{ marginTop: '4px' }}>
<Trans>Your position will be 100% composed of {quoteCurrency?.symbol} at this price</Trans>
</ThemedText.DeprecatedSmall>
</AutoColumn>

View File

@@ -33,7 +33,7 @@ const StyledExternalCard = styled(Card)`
const HoverText = styled.div`
text-decoration: none;
color: ${({ theme }) => theme.deprecated_text1};
color: ${({ theme }) => theme.textPrimary};
display: flex;
align-items: center;
@@ -128,7 +128,7 @@ function PrivacyPolicy() {
<RowBetween>
<AutoRow gap="4px">
<Info size={20} />
<ThemedText.DeprecatedMain fontSize={14} color="deprecated_primaryText1">
<ThemedText.DeprecatedMain fontSize={14} color="accentAction">
<Trans>Uniswap Labs&apos; Terms of Service</Trans>
</ThemedText.DeprecatedMain>
</AutoRow>
@@ -141,7 +141,7 @@ function PrivacyPolicy() {
<RowBetween>
<AutoRow gap="4px">
<Info size={20} />
<ThemedText.DeprecatedMain fontSize={14} color="deprecated_primaryText1">
<ThemedText.DeprecatedMain fontSize={14} color="accentAction">
<Trans>Privacy Policy</Trans>
</ThemedText.DeprecatedMain>
</AutoRow>
@@ -159,7 +159,7 @@ function PrivacyPolicy() {
<AutoColumn gap="sm">
<AutoRow gap="4px">
<Info size={18} />
<ThemedText.DeprecatedMain fontSize={14} color="deprecated_text1">
<ThemedText.DeprecatedMain fontSize={14} color="textPrimary">
{name}
</ThemedText.DeprecatedMain>
</AutoRow>

Some files were not shown because too many files have changed in this diff Show More