diff --git a/functions/_middleware.ts b/functions/_middleware.ts index 7672f8665..5bc0fc30d 100644 --- a/functions/_middleware.ts +++ b/functions/_middleware.ts @@ -1,4 +1,5 @@ /* eslint max-classes-per-file: "off" */ +import { cspOnlyFrameAncestors, cspWithFrameAncestors } from '@app/utils/createCsp' class ContentModifier { private newContent: string @@ -57,20 +58,14 @@ const firefoxRewrite: PagesFunction = async ({ request, next }) => { // firefox CSP exception + metamask script if (userAgent?.includes('gecko/20100101') && userAgent.includes('firefox/')) { - response.headers.set( - 'Content-Security-Policy', - "frame-ancestors 'self' https://app.safe.global;", - ) + response.headers.set('Content-Security-Policy', cspOnlyFrameAncestors) return new HTMLRewriter() .on('head', new ScriptWriter('/_next/static/chunks/initialise-metamask.js')) .transform(response) } // default headers - response.headers.set( - 'Content-Security-Policy', - "worker-src 'self'; script-src 'self' 'sha256-UyYcl+sKCF/ROFZPHBlozJrndwfNiC5KT5ZZfup/pPc=' plausible.io static.cloudflareinsights.com *.ens-app-v3.pages.dev https://app.intercom.io https://widget.intercom.io https://js.intercomcdn.com 'wasm-unsafe-eval'; frame-ancestors 'self' https://app.safe.global;", - ) + response.headers.set('Content-Security-Policy', cspWithFrameAncestors) return response } diff --git a/functions/tsconfig.json b/functions/tsconfig.json index 1680095d9..17ac1f51a 100644 --- a/functions/tsconfig.json +++ b/functions/tsconfig.json @@ -1,5 +1,5 @@ { - "include": ["../src/utils/gradient.ts", "./**/*"], + "include": ["../src/utils/createCsp.ts", "./**/*"], "compilerOptions": { "noEmit": true, "target": "ESNext", diff --git a/package.json b/package.json index 924500452..feb91e4b6 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,7 @@ "@ensdomains/content-hash": "^3.0.0-beta.5", "@ensdomains/ens-contracts": "1.2.0-beta.0", "@ensdomains/ensjs": "4.0.2", - "@ensdomains/thorin": "0.6.50", + "@ensdomains/thorin": "1.0.0-beta.16", "@metamask/post-message-stream": "^6.1.2", "@metamask/providers": "^14.0.2", "@noble/hashes": "^1.3.2", @@ -123,7 +123,7 @@ "@types/node": "^18.7.13", "@types/pako": "^2.0.0", "@types/prettier": "^2.7.0", - "@types/react": "18.2.21", + "@types/react": "18.3.12", "@types/react-dom": "^18.2.7", "@types/styled-components": "5.1.23", "@types/ws": "^8.5.10", diff --git a/playwright.config.ts b/playwright.config.ts index 059e39758..35965d6a9 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -1,4 +1,3 @@ -/* eslint-disable import/no-extraneous-dependencies */ import { defineConfig, devices } from '@playwright/test' export default defineConfig({ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f5bc20d3f..5874df4f2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -128,8 +128,8 @@ importers: specifier: 4.0.2 version: 4.0.2(encoding@0.1.13)(typescript@5.4.5)(viem@2.19.4(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8) '@ensdomains/thorin': - specifier: 0.6.50 - version: 0.6.50(react-dom@18.3.1(react@18.3.1))(react-transition-state@1.1.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(styled-components@5.3.11(@babel/core@7.24.6)(react-dom@18.3.1(react@18.3.1))(react-is@18.3.1)(react@18.3.1)) + specifier: 1.0.0-beta.16 + version: 1.0.0-beta.16(@vanilla-extract/css@1.14.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@metamask/post-message-stream': specifier: ^6.1.2 version: 6.2.0 @@ -141,7 +141,7 @@ importers: version: 1.4.0 '@rainbow-me/rainbowkit': specifier: 2.1.2 - version: 2.1.2(@tanstack/react-query@5.22.2(react@18.3.1))(@types/react@18.2.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(viem@2.19.4(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(wagmi@2.12.4(@tanstack/query-core@5.22.2)(@tanstack/react-query@5.22.2(react@18.3.1))(@types/react@18.2.21)(bufferutil@4.0.8)(encoding@0.1.13)(immer@9.0.21)(react-dom@18.3.1(react@18.3.1))(react-native@0.74.1(@babel/core@7.24.6)(@babel/preset-env@7.24.6(@babel/core@7.24.6))(@types/react@18.2.21)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(rollup@2.78.0)(typescript@5.4.5)(utf-8-validate@5.0.10)(viem@2.19.4(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8)) + version: 2.1.2(@tanstack/react-query@5.22.2(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(viem@2.19.4(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(wagmi@2.12.4(@tanstack/query-core@5.22.2)(@tanstack/react-query@5.22.2(react@18.3.1))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(immer@9.0.21)(react-dom@18.3.1(react@18.3.1))(react-native@0.74.1(@babel/core@7.24.6)(@babel/preset-env@7.24.6(@babel/core@7.24.6))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(rollup@2.78.0)(typescript@5.4.5)(utf-8-validate@5.0.10)(viem@2.19.4(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8)) '@sentry/nextjs': specifier: 7.43.x version: 7.43.0(encoding@0.1.13)(next@13.5.6(@babel/core@7.24.6)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(webpack@5.91.0(esbuild@0.17.19)) @@ -168,7 +168,7 @@ importers: version: 5.22.2(@tanstack/react-query@5.22.2(react@18.3.1))(react@18.3.1) '@wagmi/core': specifier: 2.13.3 - version: 2.13.3(@tanstack/query-core@5.22.2)(@types/react@18.2.21)(immer@9.0.21)(react@18.3.1)(typescript@5.4.5)(viem@2.19.4(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8)) + version: 2.13.3(@tanstack/query-core@5.22.2)(@types/react@18.3.12)(immer@9.0.21)(react@18.3.1)(typescript@5.4.5)(viem@2.19.4(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8)) calendar-link: specifier: ^2.2.0 version: 2.6.0 @@ -225,7 +225,7 @@ importers: version: 7.51.0(react@18.3.1) react-i18next: specifier: ^11.18.5 - version: 11.18.6(i18next@21.10.0)(react-dom@18.3.1(react@18.3.1))(react-native@0.74.1(@babel/core@7.24.6)(@babel/preset-env@7.24.6(@babel/core@7.24.6))(@types/react@18.2.21)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1) + version: 11.18.6(i18next@21.10.0)(react-dom@18.3.1(react@18.3.1))(react-native@0.74.1(@babel/core@7.24.6)(@babel/preset-env@7.24.6(@babel/core@7.24.6))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1) react-transition-state: specifier: ^1.1.5 version: 1.1.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -255,7 +255,7 @@ importers: version: 2.19.4(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8) wagmi: specifier: 2.12.4 - version: 2.12.4(@tanstack/query-core@5.22.2)(@tanstack/react-query@5.22.2(react@18.3.1))(@types/react@18.2.21)(bufferutil@4.0.8)(encoding@0.1.13)(immer@9.0.21)(react-dom@18.3.1(react@18.3.1))(react-native@0.74.1(@babel/core@7.24.6)(@babel/preset-env@7.24.6(@babel/core@7.24.6))(@types/react@18.2.21)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(rollup@2.78.0)(typescript@5.4.5)(utf-8-validate@5.0.10)(viem@2.19.4(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8) + version: 2.12.4(@tanstack/query-core@5.22.2)(@tanstack/react-query@5.22.2(react@18.3.1))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(immer@9.0.21)(react-dom@18.3.1(react@18.3.1))(react-native@0.74.1(@babel/core@7.24.6)(@babel/preset-env@7.24.6(@babel/core@7.24.6))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(rollup@2.78.0)(typescript@5.4.5)(utf-8-validate@5.0.10)(viem@2.19.4(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8) devDependencies: '@cloudflare/workers-types': specifier: ^3.14.1 @@ -295,7 +295,7 @@ importers: version: 14.3.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@testing-library/react-hooks': specifier: ^8.0.1 - version: 8.0.1(@types/react@18.2.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 8.0.1(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@testing-library/user-event': specifier: ^14.5.2 version: 14.5.2(@testing-library/dom@9.3.4) @@ -312,8 +312,8 @@ importers: specifier: ^2.7.0 version: 2.7.3 '@types/react': - specifier: 18.2.21 - version: 18.2.21 + specifier: 18.3.12 + version: 18.3.12 '@types/react-dom': specifier: ^18.2.7 version: 18.3.0 @@ -1648,13 +1648,12 @@ packages: '@ensdomains/solsha1@0.0.3': resolution: {integrity: sha512-uhuG5LzRt/UJC0Ux83cE2rCKwSleRePoYdQVcqPN1wyf3/ekMzT/KZUF9+v7/AG5w9jlMLCQkUM50vfjr0Yu9Q==} - '@ensdomains/thorin@0.6.50': - resolution: {integrity: sha512-UA1Blyz1h/Yy9e2h8ykNwyIfFMa85+fM5viS1Jra7Ms/EbgLhiP/BEMNr1/oZvwLHE54UM/rZGij1GaxurrOoQ==} + '@ensdomains/thorin@1.0.0-beta.16': + resolution: {integrity: sha512-4iUyTL/UdwkRxXOW9y/bkcDmJUZkY3uYE03kdeQTCIRdJBlOvluZOS+pQpmQhgAoEhNqd/kYMmO+sz/g71PjyQ==} + engines: {node: '>=20'} peerDependencies: react: ^18.2.0 react-dom: ^18.2.0 - react-transition-state: ^1.1.4 - styled-components: ^5.3.3 '@esbuild-plugins/node-globals-polyfill@0.2.3': resolution: {integrity: sha512-r3MIryXDeXDOZh7ih1l/yE9ZLORCd5e8vWg02azWRGj5SPTuoh69A2AIyn0Z31V/kHBfZ4HgWJ+OK3GTTwLmnw==} @@ -3655,8 +3654,8 @@ packages: '@types/react-dom@18.3.0': resolution: {integrity: sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==} - '@types/react@18.2.21': - resolution: {integrity: sha512-neFKG/sBAwGxHgXiIxnbm3/AAVQ/cMRS93hvBpg8xYRbeQSPVABp9U2bRnPf0iI4+Ucdv3plSxKK+3CW2ENJxA==} + '@types/react@18.3.12': + resolution: {integrity: sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==} '@types/responselike@1.0.3': resolution: {integrity: sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==} @@ -3664,9 +3663,6 @@ packages: '@types/sax@1.2.7': resolution: {integrity: sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==} - '@types/scheduler@0.23.0': - resolution: {integrity: sha512-YIoDCTH3Af6XM5VuwGG/QL/CJqga1Zm3NkU3HZ4ZHK2fRMPYP1VczsTUqtsf43PH/iJNVlPHAo2oWX7BSdB2Hw==} - '@types/secp256k1@4.0.6': resolution: {integrity: sha512-hHxJU6PAEUn0TP4S/ZOzuTUvJWuZ6eIKeNKb5RBpODvSl6hp1Wrw4s7ATY50rklRCScUDpHzVA/DQdSjJ3UoYQ==} @@ -3823,6 +3819,11 @@ packages: peerDependencies: '@vanilla-extract/css': ^1.0.0 + '@vanilla-extract/sprinkles@1.6.3': + resolution: {integrity: sha512-oCHlQeYOBIJIA2yWy2GnY5wE2A7hGHDyJplJo4lb+KEIBcJWRnDJDg8ywDwQS5VfWJrBBO3drzYZPFpWQjAMiQ==} + peerDependencies: + '@vanilla-extract/css': ^1.0.0 + '@vitejs/plugin-react@4.3.1': resolution: {integrity: sha512-m/V2syj5CuVnaxcUJOQRel/Wr31FFXRFlnOoq1TVtkCxsY5veGMTEmpWHndrhB2U8ScHtCQB1e+4hWYExQc6Lg==} engines: {node: ^14.18.0 || >=16.0.0} @@ -4695,6 +4696,10 @@ packages: resolution: {integrity: sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg==} engines: {node: '>=6'} + clsx@2.1.1: + resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} + engines: {node: '>=6'} + code-point-at@1.1.0: resolution: {integrity: sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==} engines: {node: '>=0.10.0'} @@ -5805,9 +5810,6 @@ packages: fmix@0.1.0: resolution: {integrity: sha512-Y6hyofImk9JdzU8k5INtTXX1cu8LDlePWDFU5sftm9H+zKCr5SGrVjdhkvsim646cw5zD0nADj8oHyXMZmCZ9w==} - focus-visible@5.2.1: - resolution: {integrity: sha512-8Bx950VD1bWTQJEH/AM6SpEk+SU55aVnp4Ujhuuxy3eMEBCRwBnTBnVXr9YAPvZL3/CNjCa8u4IWfNmEO53whA==} - follow-redirects@1.15.6: resolution: {integrity: sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==} engines: {node: '>=4.0'} @@ -8119,6 +8121,12 @@ packages: react: ^18.2.0 react-dom: ^18.2.0 + react-transition-state@2.2.0: + resolution: {integrity: sha512-D3EyLku1Sdxrxq26Fo4Jh0q1BLEFQfDOxKKiSuyqWH84+hM6y0Guc0hcW2IXMXY5l5gQCgkOQ9y90xx6mNoj5w==} + peerDependencies: + react: ^18.2.0 + react-dom: ^18.2.0 + react-universal-interface@0.6.2: resolution: {integrity: sha512-dg8yXdcQmvgR13RIlZbTRQOoUrDciFVoSBZILwjE2LFISxZZ8loVJKAkuzswl5js8BHda79bIb2b84ehU8IjXw==} peerDependencies: @@ -11592,16 +11600,16 @@ snapshots: dependencies: hash-test-vectors: 1.3.2 - '@ensdomains/thorin@0.6.50(react-dom@18.3.1(react@18.3.1))(react-transition-state@1.1.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(styled-components@5.3.11(@babel/core@7.24.6)(react-dom@18.3.1(react@18.3.1))(react-is@18.3.1)(react@18.3.1))': + '@ensdomains/thorin@1.0.0-beta.16(@vanilla-extract/css@1.14.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - clsx: 1.2.1 - focus-visible: 5.2.1 - lodash: 4.17.21 + '@vanilla-extract/sprinkles': 1.6.3(@vanilla-extract/css@1.14.0) + clsx: 2.1.1 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - react-transition-state: 1.1.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - styled-components: 5.3.11(@babel/core@7.24.6)(react-dom@18.3.1(react@18.3.1))(react-is@18.3.1)(react@18.3.1) - ts-pattern: 4.3.0 + react-transition-state: 2.2.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + ts-pattern: 5.5.0 + transitivePeerDependencies: + - '@vanilla-extract/css' '@esbuild-plugins/node-globals-polyfill@0.2.3(esbuild@0.17.19)': dependencies: @@ -12343,21 +12351,21 @@ snapshots: transitivePeerDependencies: - supports-color - '@metamask/sdk-install-modal-web@0.26.5(i18next@23.11.5)(react-dom@18.3.1(react@18.3.1))(react-native@0.74.1(@babel/core@7.24.6)(@babel/preset-env@7.24.6(@babel/core@7.24.6))(@types/react@18.2.21)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)': + '@metamask/sdk-install-modal-web@0.26.5(i18next@23.11.5)(react-dom@18.3.1(react@18.3.1))(react-native@0.74.1(@babel/core@7.24.6)(@babel/preset-env@7.24.6(@babel/core@7.24.6))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)': dependencies: i18next: 23.11.5 qr-code-styling: 1.6.0-rc.1 optionalDependencies: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - react-native: 0.74.1(@babel/core@7.24.6)(@babel/preset-env@7.24.6(@babel/core@7.24.6))(@types/react@18.2.21)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10) + react-native: 0.74.1(@babel/core@7.24.6)(@babel/preset-env@7.24.6(@babel/core@7.24.6))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10) - '@metamask/sdk@0.27.0(bufferutil@4.0.8)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react-native@0.74.1(@babel/core@7.24.6)(@babel/preset-env@7.24.6(@babel/core@7.24.6))(@types/react@18.2.21)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(rollup@2.78.0)(utf-8-validate@5.0.10)': + '@metamask/sdk@0.27.0(bufferutil@4.0.8)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react-native@0.74.1(@babel/core@7.24.6)(@babel/preset-env@7.24.6(@babel/core@7.24.6))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(rollup@2.78.0)(utf-8-validate@5.0.10)': dependencies: '@metamask/onboarding': 1.0.1 '@metamask/providers': 16.1.0 '@metamask/sdk-communication-layer': 0.27.0(cross-fetch@4.0.0(encoding@0.1.13))(eciesjs@0.3.18)(eventemitter2@6.4.9)(readable-stream@3.6.2)(socket.io-client@4.7.5(bufferutil@4.0.8)(utf-8-validate@5.0.10)) - '@metamask/sdk-install-modal-web': 0.26.5(i18next@23.11.5)(react-dom@18.3.1(react@18.3.1))(react-native@0.74.1(@babel/core@7.24.6)(@babel/preset-env@7.24.6(@babel/core@7.24.6))(@types/react@18.2.21)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1) + '@metamask/sdk-install-modal-web': 0.26.5(i18next@23.11.5)(react-dom@18.3.1(react@18.3.1))(react-native@0.74.1(@babel/core@7.24.6)(@babel/preset-env@7.24.6(@babel/core@7.24.6))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1) '@types/dom-screen-wake-lock': 1.0.3 bowser: 2.11.0 cross-fetch: 4.0.0(encoding@0.1.13) @@ -12370,7 +12378,7 @@ snapshots: obj-multiplex: 1.0.0 pump: 3.0.0 qrcode-terminal-nooctal: 0.12.1 - react-native-webview: 11.26.1(react-native@0.74.1(@babel/core@7.24.6)(@babel/preset-env@7.24.6(@babel/core@7.24.6))(@types/react@18.2.21)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1) + react-native-webview: 11.26.1(react-native@0.74.1(@babel/core@7.24.6)(@babel/preset-env@7.24.6(@babel/core@7.24.6))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1) readable-stream: 3.6.2 rollup-plugin-visualizer: 5.12.0(rollup@2.78.0) socket.io-client: 4.7.5(bufferutil@4.0.8)(utf-8-validate@5.0.10) @@ -12756,7 +12764,7 @@ snapshots: '@polka/url@1.0.0-next.25': {} - '@rainbow-me/rainbowkit@2.1.2(@tanstack/react-query@5.22.2(react@18.3.1))(@types/react@18.2.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(viem@2.19.4(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(wagmi@2.12.4(@tanstack/query-core@5.22.2)(@tanstack/react-query@5.22.2(react@18.3.1))(@types/react@18.2.21)(bufferutil@4.0.8)(encoding@0.1.13)(immer@9.0.21)(react-dom@18.3.1(react@18.3.1))(react-native@0.74.1(@babel/core@7.24.6)(@babel/preset-env@7.24.6(@babel/core@7.24.6))(@types/react@18.2.21)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(rollup@2.78.0)(typescript@5.4.5)(utf-8-validate@5.0.10)(viem@2.19.4(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8))': + '@rainbow-me/rainbowkit@2.1.2(@tanstack/react-query@5.22.2(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(viem@2.19.4(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(wagmi@2.12.4(@tanstack/query-core@5.22.2)(@tanstack/react-query@5.22.2(react@18.3.1))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(immer@9.0.21)(react-dom@18.3.1(react@18.3.1))(react-native@0.74.1(@babel/core@7.24.6)(@babel/preset-env@7.24.6(@babel/core@7.24.6))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(rollup@2.78.0)(typescript@5.4.5)(utf-8-validate@5.0.10)(viem@2.19.4(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8))': dependencies: '@tanstack/react-query': 5.22.2(react@18.3.1) '@vanilla-extract/css': 1.14.0 @@ -12766,10 +12774,10 @@ snapshots: qrcode: 1.5.3 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - react-remove-scroll: 2.5.7(@types/react@18.2.21)(react@18.3.1) + react-remove-scroll: 2.5.7(@types/react@18.3.12)(react@18.3.1) ua-parser-js: 1.0.37 viem: 2.19.4(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8) - wagmi: 2.12.4(@tanstack/query-core@5.22.2)(@tanstack/react-query@5.22.2(react@18.3.1))(@types/react@18.2.21)(bufferutil@4.0.8)(encoding@0.1.13)(immer@9.0.21)(react-dom@18.3.1(react@18.3.1))(react-native@0.74.1(@babel/core@7.24.6)(@babel/preset-env@7.24.6(@babel/core@7.24.6))(@types/react@18.2.21)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(rollup@2.78.0)(typescript@5.4.5)(utf-8-validate@5.0.10)(viem@2.19.4(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8) + wagmi: 2.12.4(@tanstack/query-core@5.22.2)(@tanstack/react-query@5.22.2(react@18.3.1))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(immer@9.0.21)(react-dom@18.3.1(react@18.3.1))(react-native@0.74.1(@babel/core@7.24.6)(@babel/preset-env@7.24.6(@babel/core@7.24.6))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(rollup@2.78.0)(typescript@5.4.5)(utf-8-validate@5.0.10)(viem@2.19.4(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8) transitivePeerDependencies: - '@types/react' @@ -13052,14 +13060,14 @@ snapshots: '@react-native/normalize-colors@0.74.83': {} - '@react-native/virtualized-lists@0.74.83(@types/react@18.2.21)(react-native@0.74.1(@babel/core@7.24.6)(@babel/preset-env@7.24.6(@babel/core@7.24.6))(@types/react@18.2.21)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)': + '@react-native/virtualized-lists@0.74.83(@types/react@18.3.12)(react-native@0.74.1(@babel/core@7.24.6)(@babel/preset-env@7.24.6(@babel/core@7.24.6))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)': dependencies: invariant: 2.2.4 nullthrows: 1.1.1 react: 18.3.1 - react-native: 0.74.1(@babel/core@7.24.6)(@babel/preset-env@7.24.6(@babel/core@7.24.6))(@types/react@18.2.21)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10) + react-native: 0.74.1(@babel/core@7.24.6)(@babel/preset-env@7.24.6(@babel/core@7.24.6))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10) optionalDependencies: - '@types/react': 18.2.21 + '@types/react': 18.3.12 '@rnx-kit/chromium-edge-launcher@1.0.0': dependencies: @@ -13741,13 +13749,13 @@ snapshots: '@types/jest': 29.5.12 vitest: 2.0.5(@types/node@18.19.33)(jsdom@24.1.0(bufferutil@4.0.8)(canvas@2.11.2(encoding@0.1.13))(utf-8-validate@5.0.10))(terser@5.31.5) - '@testing-library/react-hooks@8.0.1(@types/react@18.2.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@testing-library/react-hooks@8.0.1(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.24.6 react: 18.3.1 react-error-boundary: 3.1.4(react@18.3.1) optionalDependencies: - '@types/react': 18.2.21 + '@types/react': 18.3.12 react-dom: 18.3.1(react@18.3.1) '@testing-library/react@14.3.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': @@ -13924,7 +13932,7 @@ snapshots: '@types/hoist-non-react-statics@3.3.5': dependencies: - '@types/react': 18.2.21 + '@types/react': 18.3.12 hoist-non-react-statics: 3.3.2 '@types/http-cache-semantics@4.0.4': {} @@ -13999,12 +14007,11 @@ snapshots: '@types/react-dom@18.3.0': dependencies: - '@types/react': 18.2.21 + '@types/react': 18.3.12 - '@types/react@18.2.21': + '@types/react@18.3.12': dependencies: '@types/prop-types': 15.7.12 - '@types/scheduler': 0.23.0 csstype: 3.1.3 '@types/responselike@1.0.3': @@ -14015,8 +14022,6 @@ snapshots: dependencies: '@types/node': 18.19.33 - '@types/scheduler@0.23.0': {} - '@types/secp256k1@4.0.6': dependencies: '@types/node': 18.19.44 @@ -14032,7 +14037,7 @@ snapshots: '@types/styled-components@5.1.23': dependencies: '@types/hoist-non-react-statics': 3.3.5 - '@types/react': 18.2.21 + '@types/react': 18.3.12 csstype: 3.1.3 '@types/trusted-types@2.0.7': {} @@ -14240,6 +14245,10 @@ snapshots: dependencies: '@vanilla-extract/css': 1.14.0 + '@vanilla-extract/sprinkles@1.6.3(@vanilla-extract/css@1.14.0)': + dependencies: + '@vanilla-extract/css': 1.14.0 + '@vitejs/plugin-react@4.3.1(vite@5.2.11(@types/node@18.19.33)(terser@5.31.5))': dependencies: '@babel/core': 7.24.6 @@ -14302,15 +14311,15 @@ snapshots: loupe: 3.1.1 tinyrainbow: 1.2.0 - '@wagmi/connectors@5.1.4(@types/react@18.2.21)(@wagmi/core@2.13.3(@tanstack/query-core@5.22.2)(@types/react@18.2.21)(immer@9.0.21)(react@18.3.1)(typescript@5.4.5)(viem@2.19.4(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8)))(bufferutil@4.0.8)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react-native@0.74.1(@babel/core@7.24.6)(@babel/preset-env@7.24.6(@babel/core@7.24.6))(@types/react@18.2.21)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(rollup@2.78.0)(typescript@5.4.5)(utf-8-validate@5.0.10)(viem@2.19.4(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8)': + '@wagmi/connectors@5.1.4(@types/react@18.3.12)(@wagmi/core@2.13.3(@tanstack/query-core@5.22.2)(@types/react@18.3.12)(immer@9.0.21)(react@18.3.1)(typescript@5.4.5)(viem@2.19.4(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8)))(bufferutil@4.0.8)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react-native@0.74.1(@babel/core@7.24.6)(@babel/preset-env@7.24.6(@babel/core@7.24.6))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(rollup@2.78.0)(typescript@5.4.5)(utf-8-validate@5.0.10)(viem@2.19.4(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8)': dependencies: '@coinbase/wallet-sdk': 4.0.4 - '@metamask/sdk': 0.27.0(bufferutil@4.0.8)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react-native@0.74.1(@babel/core@7.24.6)(@babel/preset-env@7.24.6(@babel/core@7.24.6))(@types/react@18.2.21)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(rollup@2.78.0)(utf-8-validate@5.0.10) + '@metamask/sdk': 0.27.0(bufferutil@4.0.8)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react-native@0.74.1(@babel/core@7.24.6)(@babel/preset-env@7.24.6(@babel/core@7.24.6))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(rollup@2.78.0)(utf-8-validate@5.0.10) '@safe-global/safe-apps-provider': 0.18.3(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8) '@safe-global/safe-apps-sdk': 9.1.0(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8) - '@wagmi/core': 2.13.3(@tanstack/query-core@5.22.2)(@types/react@18.2.21)(immer@9.0.21)(react@18.3.1)(typescript@5.4.5)(viem@2.19.4(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8)) - '@walletconnect/ethereum-provider': 2.11.1(@types/react@18.2.21)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10) - '@walletconnect/modal': 2.6.2(@types/react@18.2.21)(react@18.3.1) + '@wagmi/core': 2.13.3(@tanstack/query-core@5.22.2)(@types/react@18.3.12)(immer@9.0.21)(react@18.3.1)(typescript@5.4.5)(viem@2.19.4(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8)) + '@walletconnect/ethereum-provider': 2.11.1(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10) + '@walletconnect/modal': 2.6.2(@types/react@18.3.12)(react@18.3.1) cbw-sdk: '@coinbase/wallet-sdk@3.9.3' viem: 2.19.4(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8) optionalDependencies: @@ -14341,12 +14350,12 @@ snapshots: - utf-8-validate - zod - '@wagmi/core@2.13.3(@tanstack/query-core@5.22.2)(@types/react@18.2.21)(immer@9.0.21)(react@18.3.1)(typescript@5.4.5)(viem@2.19.4(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))': + '@wagmi/core@2.13.3(@tanstack/query-core@5.22.2)(@types/react@18.3.12)(immer@9.0.21)(react@18.3.1)(typescript@5.4.5)(viem@2.19.4(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))': dependencies: eventemitter3: 5.0.1 mipd: 0.0.7(typescript@5.4.5) viem: 2.19.4(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8) - zustand: 4.4.1(@types/react@18.2.21)(immer@9.0.21)(react@18.3.1) + zustand: 4.4.1(@types/react@18.3.12)(immer@9.0.21)(react@18.3.1) optionalDependencies: '@tanstack/query-core': 5.22.2 typescript: 5.4.5 @@ -14397,13 +14406,13 @@ snapshots: dependencies: tslib: 1.14.1 - '@walletconnect/ethereum-provider@2.11.1(@types/react@18.2.21)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10)': + '@walletconnect/ethereum-provider@2.11.1(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10)': dependencies: '@walletconnect/jsonrpc-http-connection': 1.0.8(encoding@0.1.13) '@walletconnect/jsonrpc-provider': 1.0.14 '@walletconnect/jsonrpc-types': 1.0.4 '@walletconnect/jsonrpc-utils': 1.0.8 - '@walletconnect/modal': 2.6.2(@types/react@18.2.21)(react@18.3.1) + '@walletconnect/modal': 2.6.2(@types/react@18.3.12)(react@18.3.1) '@walletconnect/sign-client': 2.11.1(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@5.0.10) '@walletconnect/types': 2.11.1 '@walletconnect/universal-provider': 2.11.1(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@5.0.10) @@ -14513,16 +14522,16 @@ snapshots: '@walletconnect/safe-json': 1.0.2 pino: 7.11.0 - '@walletconnect/modal-core@2.6.2(@types/react@18.2.21)(react@18.3.1)': + '@walletconnect/modal-core@2.6.2(@types/react@18.3.12)(react@18.3.1)': dependencies: - valtio: 1.11.2(@types/react@18.2.21)(react@18.3.1) + valtio: 1.11.2(@types/react@18.3.12)(react@18.3.1) transitivePeerDependencies: - '@types/react' - react - '@walletconnect/modal-ui@2.6.2(@types/react@18.2.21)(react@18.3.1)': + '@walletconnect/modal-ui@2.6.2(@types/react@18.3.12)(react@18.3.1)': dependencies: - '@walletconnect/modal-core': 2.6.2(@types/react@18.2.21)(react@18.3.1) + '@walletconnect/modal-core': 2.6.2(@types/react@18.3.12)(react@18.3.1) lit: 2.8.0 motion: 10.16.2 qrcode: 1.5.3 @@ -14530,10 +14539,10 @@ snapshots: - '@types/react' - react - '@walletconnect/modal@2.6.2(@types/react@18.2.21)(react@18.3.1)': + '@walletconnect/modal@2.6.2(@types/react@18.3.12)(react@18.3.1)': dependencies: - '@walletconnect/modal-core': 2.6.2(@types/react@18.2.21)(react@18.3.1) - '@walletconnect/modal-ui': 2.6.2(@types/react@18.2.21)(react@18.3.1) + '@walletconnect/modal-core': 2.6.2(@types/react@18.3.12)(react@18.3.1) + '@walletconnect/modal-ui': 2.6.2(@types/react@18.3.12)(react@18.3.1) transitivePeerDependencies: - '@types/react' - react @@ -15499,6 +15508,8 @@ snapshots: clsx@2.1.0: {} + clsx@2.1.1: {} + code-point-at@1.1.0: {} color-convert@1.9.3: @@ -16893,8 +16904,6 @@ snapshots: dependencies: imul: 1.0.1 - focus-visible@5.2.1: {} - follow-redirects@1.15.6(debug@4.3.4): optionalDependencies: debug: 4.3.4(supports-color@8.1.1) @@ -19446,7 +19455,7 @@ snapshots: dependencies: react: 18.3.1 - react-i18next@11.18.6(i18next@21.10.0)(react-dom@18.3.1(react@18.3.1))(react-native@0.74.1(@babel/core@7.24.6)(@babel/preset-env@7.24.6(@babel/core@7.24.6))(@types/react@18.2.21)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1): + react-i18next@11.18.6(i18next@21.10.0)(react-dom@18.3.1(react@18.3.1))(react-native@0.74.1(@babel/core@7.24.6)(@babel/preset-env@7.24.6(@babel/core@7.24.6))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1): dependencies: '@babel/runtime': 7.24.6 html-parse-stringify: 3.0.1 @@ -19454,7 +19463,7 @@ snapshots: react: 18.3.1 optionalDependencies: react-dom: 18.3.1(react@18.3.1) - react-native: 0.74.1(@babel/core@7.24.6)(@babel/preset-env@7.24.6(@babel/core@7.24.6))(@types/react@18.2.21)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10) + react-native: 0.74.1(@babel/core@7.24.6)(@babel/preset-env@7.24.6(@babel/core@7.24.6))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10) react-is@16.13.1: {} @@ -19462,14 +19471,14 @@ snapshots: react-is@18.3.1: {} - react-native-webview@11.26.1(react-native@0.74.1(@babel/core@7.24.6)(@babel/preset-env@7.24.6(@babel/core@7.24.6))(@types/react@18.2.21)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1): + react-native-webview@11.26.1(react-native@0.74.1(@babel/core@7.24.6)(@babel/preset-env@7.24.6(@babel/core@7.24.6))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1): dependencies: escape-string-regexp: 2.0.0 invariant: 2.2.4 react: 18.3.1 - react-native: 0.74.1(@babel/core@7.24.6)(@babel/preset-env@7.24.6(@babel/core@7.24.6))(@types/react@18.2.21)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10) + react-native: 0.74.1(@babel/core@7.24.6)(@babel/preset-env@7.24.6(@babel/core@7.24.6))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10) - react-native@0.74.1(@babel/core@7.24.6)(@babel/preset-env@7.24.6(@babel/core@7.24.6))(@types/react@18.2.21)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10): + react-native@0.74.1(@babel/core@7.24.6)(@babel/preset-env@7.24.6(@babel/core@7.24.6))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10): dependencies: '@jest/create-cache-key-function': 29.7.0 '@react-native-community/cli': 13.6.6(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@5.0.10) @@ -19481,7 +19490,7 @@ snapshots: '@react-native/gradle-plugin': 0.74.83 '@react-native/js-polyfills': 0.74.83 '@react-native/normalize-colors': 0.74.83 - '@react-native/virtualized-lists': 0.74.83(@types/react@18.2.21)(react-native@0.74.1(@babel/core@7.24.6)(@babel/preset-env@7.24.6(@babel/core@7.24.6))(@types/react@18.2.21)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1) + '@react-native/virtualized-lists': 0.74.83(@types/react@18.3.12)(react-native@0.74.1(@babel/core@7.24.6)(@babel/preset-env@7.24.6(@babel/core@7.24.6))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1) abort-controller: 3.0.0 anser: 1.4.10 ansi-regex: 5.0.1 @@ -19510,7 +19519,7 @@ snapshots: ws: 6.2.3(bufferutil@4.0.8)(utf-8-validate@5.0.10) yargs: 17.7.2 optionalDependencies: - '@types/react': 18.2.21 + '@types/react': 18.3.12 transitivePeerDependencies: - '@babel/core' - '@babel/preset-env' @@ -19521,24 +19530,24 @@ snapshots: react-refresh@0.14.2: {} - react-remove-scroll-bar@2.3.6(@types/react@18.2.21)(react@18.3.1): + react-remove-scroll-bar@2.3.6(@types/react@18.3.12)(react@18.3.1): dependencies: react: 18.3.1 - react-style-singleton: 2.2.1(@types/react@18.2.21)(react@18.3.1) + react-style-singleton: 2.2.1(@types/react@18.3.12)(react@18.3.1) tslib: 2.6.2 optionalDependencies: - '@types/react': 18.2.21 + '@types/react': 18.3.12 - react-remove-scroll@2.5.7(@types/react@18.2.21)(react@18.3.1): + react-remove-scroll@2.5.7(@types/react@18.3.12)(react@18.3.1): dependencies: react: 18.3.1 - react-remove-scroll-bar: 2.3.6(@types/react@18.2.21)(react@18.3.1) - react-style-singleton: 2.2.1(@types/react@18.2.21)(react@18.3.1) + react-remove-scroll-bar: 2.3.6(@types/react@18.3.12)(react@18.3.1) + react-style-singleton: 2.2.1(@types/react@18.3.12)(react@18.3.1) tslib: 2.6.2 - use-callback-ref: 1.3.2(@types/react@18.2.21)(react@18.3.1) - use-sidecar: 1.1.2(@types/react@18.2.21)(react@18.3.1) + use-callback-ref: 1.3.2(@types/react@18.3.12)(react@18.3.1) + use-sidecar: 1.1.2(@types/react@18.3.12)(react@18.3.1) optionalDependencies: - '@types/react': 18.2.21 + '@types/react': 18.3.12 react-shallow-renderer@16.15.0(react@18.3.1): dependencies: @@ -19546,20 +19555,25 @@ snapshots: react: 18.3.1 react-is: 18.3.1 - react-style-singleton@2.2.1(@types/react@18.2.21)(react@18.3.1): + react-style-singleton@2.2.1(@types/react@18.3.12)(react@18.3.1): dependencies: get-nonce: 1.0.1 invariant: 2.2.4 react: 18.3.1 tslib: 2.6.2 optionalDependencies: - '@types/react': 18.2.21 + '@types/react': 18.3.12 react-transition-state@1.1.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + react-transition-state@2.2.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + react-universal-interface@0.6.2(react@18.3.1)(tslib@2.6.2): dependencies: react: 18.3.1 @@ -20882,25 +20896,25 @@ snapshots: url-set-query@1.0.0: {} - use-callback-ref@1.3.2(@types/react@18.2.21)(react@18.3.1): + use-callback-ref@1.3.2(@types/react@18.3.12)(react@18.3.1): dependencies: react: 18.3.1 tslib: 2.6.2 optionalDependencies: - '@types/react': 18.2.21 + '@types/react': 18.3.12 use-immer@0.7.0(immer@9.0.21)(react@18.3.1): dependencies: immer: 9.0.21 react: 18.3.1 - use-sidecar@1.1.2(@types/react@18.2.21)(react@18.3.1): + use-sidecar@1.1.2(@types/react@18.3.12)(react@18.3.1): dependencies: detect-node-es: 1.1.0 react: 18.3.1 tslib: 2.6.2 optionalDependencies: - '@types/react': 18.2.21 + '@types/react': 18.3.12 use-sync-external-store@1.2.0(react@18.3.1): dependencies: @@ -20941,12 +20955,12 @@ snapshots: spdx-correct: 3.2.0 spdx-expression-parse: 3.0.1 - valtio@1.11.2(@types/react@18.2.21)(react@18.3.1): + valtio@1.11.2(@types/react@18.3.12)(react@18.3.1): dependencies: proxy-compare: 2.5.1 use-sync-external-store: 1.2.0(react@18.3.1) optionalDependencies: - '@types/react': 18.2.21 + '@types/react': 18.3.12 react: 18.3.1 varint@5.0.2: {} @@ -21101,11 +21115,11 @@ snapshots: dependencies: xml-name-validator: 5.0.0 - wagmi@2.12.4(@tanstack/query-core@5.22.2)(@tanstack/react-query@5.22.2(react@18.3.1))(@types/react@18.2.21)(bufferutil@4.0.8)(encoding@0.1.13)(immer@9.0.21)(react-dom@18.3.1(react@18.3.1))(react-native@0.74.1(@babel/core@7.24.6)(@babel/preset-env@7.24.6(@babel/core@7.24.6))(@types/react@18.2.21)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(rollup@2.78.0)(typescript@5.4.5)(utf-8-validate@5.0.10)(viem@2.19.4(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8): + wagmi@2.12.4(@tanstack/query-core@5.22.2)(@tanstack/react-query@5.22.2(react@18.3.1))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(immer@9.0.21)(react-dom@18.3.1(react@18.3.1))(react-native@0.74.1(@babel/core@7.24.6)(@babel/preset-env@7.24.6(@babel/core@7.24.6))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(rollup@2.78.0)(typescript@5.4.5)(utf-8-validate@5.0.10)(viem@2.19.4(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8): dependencies: '@tanstack/react-query': 5.22.2(react@18.3.1) - '@wagmi/connectors': 5.1.4(@types/react@18.2.21)(@wagmi/core@2.13.3(@tanstack/query-core@5.22.2)(@types/react@18.2.21)(immer@9.0.21)(react@18.3.1)(typescript@5.4.5)(viem@2.19.4(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8)))(bufferutil@4.0.8)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react-native@0.74.1(@babel/core@7.24.6)(@babel/preset-env@7.24.6(@babel/core@7.24.6))(@types/react@18.2.21)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(rollup@2.78.0)(typescript@5.4.5)(utf-8-validate@5.0.10)(viem@2.19.4(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8) - '@wagmi/core': 2.13.3(@tanstack/query-core@5.22.2)(@types/react@18.2.21)(immer@9.0.21)(react@18.3.1)(typescript@5.4.5)(viem@2.19.4(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8)) + '@wagmi/connectors': 5.1.4(@types/react@18.3.12)(@wagmi/core@2.13.3(@tanstack/query-core@5.22.2)(@types/react@18.3.12)(immer@9.0.21)(react@18.3.1)(typescript@5.4.5)(viem@2.19.4(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8)))(bufferutil@4.0.8)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react-native@0.74.1(@babel/core@7.24.6)(@babel/preset-env@7.24.6(@babel/core@7.24.6))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(rollup@2.78.0)(typescript@5.4.5)(utf-8-validate@5.0.10)(viem@2.19.4(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8) + '@wagmi/core': 2.13.3(@tanstack/query-core@5.22.2)(@types/react@18.3.12)(immer@9.0.21)(react@18.3.1)(typescript@5.4.5)(viem@2.19.4(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8)) react: 18.3.1 use-sync-external-store: 1.2.0(react@18.3.1) viem: 2.19.4(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8) @@ -21995,10 +22009,10 @@ snapshots: zod@3.23.8: {} - zustand@4.4.1(@types/react@18.2.21)(immer@9.0.21)(react@18.3.1): + zustand@4.4.1(@types/react@18.3.12)(immer@9.0.21)(react@18.3.1): dependencies: use-sync-external-store: 1.2.0(react@18.3.1) optionalDependencies: - '@types/react': 18.2.21 + '@types/react': 18.3.12 immer: 9.0.21 react: 18.3.1 diff --git a/src/assets/CircleTick.svg b/src/assets/CircleTick.svg index 0f7a7e6cb..992ee47b8 100644 --- a/src/assets/CircleTick.svg +++ b/src/assets/CircleTick.svg @@ -1,5 +1,5 @@ - - + \ No newline at end of file diff --git a/src/components/@atoms/Calendar/Calendar.test.tsx b/src/components/@atoms/Calendar/Calendar.test.tsx index 96fe2ef0c..d37bee72e 100644 --- a/src/components/@atoms/Calendar/Calendar.test.tsx +++ b/src/components/@atoms/Calendar/Calendar.test.tsx @@ -3,11 +3,11 @@ import { fireEvent, mockFunction, render, screen } from '@app/test-utils' import { InputHTMLAttributes, useState } from 'react' import { describe, expect, it, vi } from 'vitest' +import { useBreakpoint } from '@app/utils/BreakpointProvider' import { secondsToDate, secondsToDateInput } from '@app/utils/date' import { formatExpiry } from '@app/utils/utils' import { Calendar } from './Calendar' -import { useBreakpoint } from '@app/utils/BreakpointProvider' vi.mock('@app/utils/BreakpointProvider') @@ -44,27 +44,26 @@ describe('Calendar', () => { it('should handle timezone offset correctly', async () => { const OnChange = vi.fn() // Render the Calendar component - const currentDate = new Date(); - const currentDateSeconds = Math.floor(currentDate.getTime() / 1000); - render(); + const currentDate = new Date() + const currentDateSeconds = Math.floor(currentDate.getTime() / 1000) + render() // Find the input element - const calendarInput = screen.getByTestId('calendar'); + const calendarInput = screen.getByTestId('calendar') // Prepare new date and format it - currentDate.setDate(currentDate.getDate() + 2); // Change to the next day - const newDateSeconds = Math.floor(currentDate.getTime() / 1000); - const newFormattedDate = secondsToDateInput(newDateSeconds); + currentDate.setDate(currentDate.getDate() + 2) // Change to the next day + const newDateSeconds = Math.floor(currentDate.getTime() / 1000) + const newFormattedDate = secondsToDateInput(newDateSeconds) - fireEvent.change(calendarInput, { target: { value: newFormattedDate }}) + fireEvent.change(calendarInput, { target: { value: newFormattedDate } }) // Assert the onChange handler was called - expect(OnChange).toHaveBeenCalledTimes(1); + expect(OnChange).toHaveBeenCalledTimes(1) - const receivedDate = OnChange.mock.calls[0][0].currentTarget.valueAsDate; + const receivedDate = OnChange.mock.calls[0][0].currentTarget.valueAsDate const receivedFormattedDate = receivedDate.toISOString().split('T')[0] - - expect(receivedFormattedDate).toEqual(newFormattedDate); - }); + expect(receivedFormattedDate).toEqual(newFormattedDate) + }) }) diff --git a/src/components/@atoms/CheckButton/CheckButton.tsx b/src/components/@atoms/CheckButton/CheckButton.tsx index d04a81ec7..450a8e55b 100644 --- a/src/components/@atoms/CheckButton/CheckButton.tsx +++ b/src/components/@atoms/CheckButton/CheckButton.tsx @@ -1,27 +1,26 @@ import styled, { css } from 'styled-components' -import CircleTick from '@app/assets/CircleTick.svg' - const Container = styled.button<{ $active: boolean }>( ({ theme, $active }) => css` cursor: pointer; flex: 0 0 ${theme.space['9']}; width: ${theme.space['9']}; height: ${theme.space['9']}; + color: ${$active ? theme.colors.accent : theme.colors.grey}; svg { path, rect { transition: all 0.15s ease-in-out; - stroke: ${$active ? theme.colors.accent : theme.colors.textTertiary}; + stroke-width: 1px; } } &:hover { + color: ${theme.colors.accent}; svg { path, rect { - stroke: ${theme.colors.accent}; stroke-width: 1.5px; } } @@ -42,7 +41,26 @@ export const CheckButton = ({ active = false, onChange }: Props) => { onClick={() => onChange?.(!active)} data-testid="check-button" > - + + + + ) } diff --git a/src/components/@atoms/ExpiryComponents/ExpiryComponents.tsx b/src/components/@atoms/ExpiryComponents/ExpiryComponents.tsx index 4fff61e51..416edfc40 100644 --- a/src/components/@atoms/ExpiryComponents/ExpiryComponents.tsx +++ b/src/components/@atoms/ExpiryComponents/ExpiryComponents.tsx @@ -140,7 +140,7 @@ export const ReadableExpiry = ({ expiry }: { expiry: Date }) => { day: 'numeric', })}, ${expiry.getFullYear()}`} - + {`at ${expiry.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit', diff --git a/src/components/@atoms/GasDisplay.tsx b/src/components/@atoms/GasDisplay.tsx index 59ea5b317..29dc54379 100644 --- a/src/components/@atoms/GasDisplay.tsx +++ b/src/components/@atoms/GasDisplay.tsx @@ -14,7 +14,7 @@ const Container = styled.div( gap: ${theme.space['1']}; font-size: ${theme.fontSizes.small}; - color: ${theme.colors.textTertiary}; + color: ${theme.colors.grey}; font-weight: bold; padding: 0 ${theme.space['4']}; diff --git a/src/components/@atoms/InnerDialog.tsx b/src/components/@atoms/InnerDialog.tsx index 1a6d5ef1e..518e38ae1 100644 --- a/src/components/@atoms/InnerDialog.tsx +++ b/src/components/@atoms/InnerDialog.tsx @@ -1,7 +1,5 @@ import styled, { css } from 'styled-components' -import { mq } from '@ensdomains/thorin' - export const InnerDialog = styled.div( ({ theme }) => css` display: flex; @@ -12,9 +10,9 @@ export const InnerDialog = styled.div( gap: ${theme.space['4']}; max-height: 60vh; max-width: 100vw; - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { width: calc(80vw - 2 * ${theme.space['6']}); max-width: ${theme.space['128']}; - `)} + } `, ) diff --git a/src/components/@atoms/Invoice/Invoice.tsx b/src/components/@atoms/Invoice/Invoice.tsx index 54286f564..ed954d386 100644 --- a/src/components/@atoms/Invoice/Invoice.tsx +++ b/src/components/@atoms/Invoice/Invoice.tsx @@ -23,7 +23,7 @@ const LineItem = styled.div<{ $color?: Colors }>( display: flex; justify-content: space-between; line-height: ${theme.space['5']}; - color: ${$color ? theme.colors[$color] : theme.colors.textTertiary}; + color: ${$color ? theme.colors[$color] : theme.colors.grey}; `, ) diff --git a/src/components/@atoms/MobileFullWidth.tsx b/src/components/@atoms/MobileFullWidth.tsx index b8711fe62..3e88ae063 100644 --- a/src/components/@atoms/MobileFullWidth.tsx +++ b/src/components/@atoms/MobileFullWidth.tsx @@ -1,18 +1,16 @@ import styled, { css } from 'styled-components' -import { mq } from '@ensdomains/thorin' - const MobileFullWidth = styled.div( ({ theme }) => css` & > div, & { width: ${theme.space.full}; max-width: ${theme.space.full}; - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { min-width: ${theme.space['40']}; width: fit-content; max-width: max-content; - `)} + } } `, ) diff --git a/src/components/@atoms/NameDetailItem/NameDetailItem.tsx b/src/components/@atoms/NameDetailItem/NameDetailItem.tsx index 52c1b2776..8e525589a 100644 --- a/src/components/@atoms/NameDetailItem/NameDetailItem.tsx +++ b/src/components/@atoms/NameDetailItem/NameDetailItem.tsx @@ -2,7 +2,7 @@ import { ReactNode } from 'react' import styled, { css } from 'styled-components' import { useEnsAvatar } from 'wagmi' -import { Avatar, mq } from '@ensdomains/thorin' +import { Avatar } from '@ensdomains/thorin' import CircleTick from '@app/assets/CircleTick.svg' import { useZorb } from '@app/hooks/useZorb' @@ -39,10 +39,10 @@ const NameItemWrapper = styled.div<{ $highlight: boolean; $disabled: boolean }>( &:last-of-type { border: none; } - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { padding: ${theme.space['3']} ${theme.space['4.5']}; gap: ${theme.space['4']}; - `)} + } `, ) diff --git a/src/components/@atoms/NameDetailItem/TaggedNameItem.tsx b/src/components/@atoms/NameDetailItem/TaggedNameItem.tsx index a4ed26f78..5299360e0 100644 --- a/src/components/@atoms/NameDetailItem/TaggedNameItem.tsx +++ b/src/components/@atoms/NameDetailItem/TaggedNameItem.tsx @@ -2,7 +2,7 @@ import { useTranslation } from 'react-i18next' import styled, { css } from 'styled-components' import { NameWithRelation } from '@ensdomains/ensjs/subgraph' -import { mq, Tag } from '@ensdomains/thorin' +import { Tag } from '@ensdomains/thorin' import { validateExpiry } from '@app/utils/utils' @@ -16,11 +16,11 @@ const OtherItemsContainer = styled.div( justify-content: center; gap: ${theme.space['2']}; flex-gap: ${theme.space['2']}; - ${mq.md.min(css` + @media (min-width: 768px) { flex-direction: row; gap: ${theme.space['4']}; flex-gap: ${theme.space['4']}; - `)} + } `, ) diff --git a/src/components/@atoms/PseudoActionButton/PseudoActionButton.test.tsx b/src/components/@atoms/PseudoActionButton/PseudoActionButton.test.tsx index ba3a0aad8..0525474fd 100644 --- a/src/components/@atoms/PseudoActionButton/PseudoActionButton.test.tsx +++ b/src/components/@atoms/PseudoActionButton/PseudoActionButton.test.tsx @@ -14,7 +14,7 @@ afterAll(() => { describe('PseudoActionButton', () => { it('should show loading state when clicked and reset after timeout has been run', async () => { - const testIcon = + const testIcon = () => render( Test @@ -35,7 +35,7 @@ describe('PseudoActionButton', () => { }) it('should maintain loading state if loading is set to true', async () => { - const testIcon = + const testIcon = () => render( Test diff --git a/src/components/@atoms/RegistrationTimeComparisonBanner/RegistrationTimeComparisonBanner.tsx b/src/components/@atoms/RegistrationTimeComparisonBanner/RegistrationTimeComparisonBanner.tsx index 5e34e36d0..d6699d4b3 100644 --- a/src/components/@atoms/RegistrationTimeComparisonBanner/RegistrationTimeComparisonBanner.tsx +++ b/src/components/@atoms/RegistrationTimeComparisonBanner/RegistrationTimeComparisonBanner.tsx @@ -1,7 +1,7 @@ import { useTranslation } from 'react-i18next' import styled, { css } from 'styled-components' -import { Helper, mq } from '@ensdomains/thorin' +import { Helper } from '@ensdomains/thorin' const InnerContainer = styled.div( ({ theme }) => css` @@ -75,10 +75,10 @@ const Marker = styled.div<{ $percent: number }>( white-space: nowrap; } - ${mq.xs.min(css` + @media (min-width: 360px) { width: ${theme.space['18']}; font-size: ${theme.fontSizes.small}; - `)} + } &::before { content: ''; @@ -133,7 +133,7 @@ export const RegistrationTimeComparisonBanner = ({ message, yearlyFee, transacti const twentyRounded = calcPercent(twenty.gas, 3) return ( - + {message} diff --git a/src/components/@atoms/StyledName/StyledName.tsx b/src/components/@atoms/StyledName/StyledName.tsx index ad3642747..7cc8a1b22 100644 --- a/src/components/@atoms/StyledName/StyledName.tsx +++ b/src/components/@atoms/StyledName/StyledName.tsx @@ -14,7 +14,7 @@ const Container = styled.div( const Name = styled.span<{ $disabled?: boolean }>( ({ theme, $disabled }) => css` - color: ${$disabled ? theme.colors.textTertiary : theme.colors.text}; + color: ${$disabled ? theme.colors.grey : theme.colors.text}; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; @@ -24,13 +24,13 @@ const Name = styled.span<{ $disabled?: boolean }>( const Dot = styled.span( ({ theme }) => css` - color: ${theme.colors.textTertiary}; + color: ${theme.colors.grey}; `, ) const Tld = styled.span( ({ theme }) => css` - color: ${theme.colors.textTertiary}; + color: ${theme.colors.grey}; white-space: nowrap; `, ) diff --git a/src/components/@molecules/AddRecordButton/AddRecordButton.tsx b/src/components/@molecules/AddRecordButton/AddRecordButton.tsx index 2ed6e8e60..eae2384a2 100644 --- a/src/components/@molecules/AddRecordButton/AddRecordButton.tsx +++ b/src/components/@molecules/AddRecordButton/AddRecordButton.tsx @@ -239,7 +239,7 @@ const NoOptionsContainer = styled.div<{ $inline: boolean }>( padding: 0 ${theme.space['3']} ${theme.space['0.75']} ${theme.space['3']}; display: flex; align-items: center; - color: ${theme.colors.textTertiary}; + color: ${theme.colors.text}; font-style: italic; margin-bottom: ${theme.space['0.75']}; `, @@ -280,6 +280,12 @@ type Props = { onAddRecord?: (value: string) => void } +const WrappedPlusSVG = () => ( + + + +) + export const AddRecordButton = ({ autocomplete, createable, @@ -429,11 +435,7 @@ export const AddRecordButton = ({ - - - } + prefix={WrappedPlusSVG} colorStyle="transparent" onClick={handleButtonClick} size="medium" diff --git a/src/components/@molecules/AdvancedEditor/AddRecord.tsx b/src/components/@molecules/AdvancedEditor/AddRecord.tsx index 2a6c0c835..825d37135 100644 --- a/src/components/@molecules/AdvancedEditor/AddRecord.tsx +++ b/src/components/@molecules/AdvancedEditor/AddRecord.tsx @@ -1,8 +1,6 @@ import { useWatch } from 'react-hook-form' import styled, { css } from 'styled-components' -import { mq } from '@ensdomains/thorin' - import { AddRecordButton } from '@app/components/@molecules/AddRecordButton/AddRecordButton' import useAdvancedEditor, { AdvancedEditorType } from '@app/hooks/useAdvancedEditor' @@ -11,9 +9,9 @@ import { convertFormSafeKey } from '../../../utils/editor' const AddRecordContainer = styled.div( ({ theme }) => css` width: ${theme.space.full}; - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { margin-top: -${theme.space['2']}; - `)} + } `, ) diff --git a/src/components/@molecules/AdvancedEditor/AdvancedEditorTabs.tsx b/src/components/@molecules/AdvancedEditor/AdvancedEditorTabs.tsx index 30ad15b7f..0113b1fb7 100644 --- a/src/components/@molecules/AdvancedEditor/AdvancedEditorTabs.tsx +++ b/src/components/@molecules/AdvancedEditor/AdvancedEditorTabs.tsx @@ -2,23 +2,21 @@ import { useTranslation } from 'react-i18next' import styled, { css } from 'styled-components' import { Theme } from 'typings-custom/styled-components' -import { mq } from '@ensdomains/thorin' - import useAdvancedEditor from '@app/hooks/useAdvancedEditor' -const TabButtonsContainer = styled.div(({ theme }) => [ - css` +const TabButtonsContainer = styled.div( + ({ theme }) => css` display: flex; flex-wrap: wrap; gap: ${theme.space['1.25']} ${theme.space['3']}; padding: 0 ${theme.space['4']} 0 ${theme.space['2']}; width: ${theme.space.full}; + @media (min-width: ${theme.breakpoints.sm}px) { + padding: 0 ${theme.space['2']}; + margin: -${theme.space['1.5']} 0 -${theme.space['2']}; + } `, - mq.sm.min(css` - padding: 0 ${theme.space['2']}; - margin: -${theme.space['1.5']} 0 -${theme.space['2']}; - `), -]) +) const getIndicatorStyle = ( theme: Theme, @@ -61,7 +59,7 @@ const TabButton = styled.button<{ padding: 0; margin: 0; background: none; - color: ${$selected ? theme.colors.accent : theme.colors.textTertiary}; + color: ${$selected ? theme.colors.accent : theme.colors.grey}; font-size: 1.25rem; transition: all 0.15s ease-in-out; cursor: pointer; diff --git a/src/components/@molecules/BurnFuses/BurnFusesContent.tsx b/src/components/@molecules/BurnFuses/BurnFusesContent.tsx index 895934566..0c4b4ee74 100644 --- a/src/components/@molecules/BurnFuses/BurnFusesContent.tsx +++ b/src/components/@molecules/BurnFuses/BurnFusesContent.tsx @@ -4,7 +4,7 @@ import { useTranslation } from 'react-i18next' import styled, { css } from 'styled-components' import { ChildFuseKeys, ChildFuseReferenceType } from '@ensdomains/ensjs/utils' -import { Button, FlameSVG, Helper, mq, Typography } from '@ensdomains/thorin' +import { Button, FlameSVG, Helper, Typography } from '@ensdomains/thorin' import { Spacer } from '@app/components/@atoms/Spacer' import { CurrentChildFuses } from '@app/types' @@ -13,15 +13,15 @@ export const childFuseObj = Object.fromEntries( ChildFuseKeys.map((key) => [key, false]), ) as CurrentChildFuses -const FusesContainer = styled.div(({ theme }) => [ - css` +const FusesContainer = styled.div( + ({ theme }) => css` width: 100%; padding: ${theme.space['1.25']} ${theme.space['4']}; + @media (min-width: ${theme.breakpoints.sm}px) { + min-width: ${theme.space['112']}; + } `, - mq.sm.min(css` - min-width: ${theme.space['112']}; - `), -]) +) const BurnButtonsContainer = styled.div( ({ theme }) => css` @@ -81,6 +81,12 @@ const StyledButton = styled(Button)( `, ) +const SelectedBurnButton = (permission: string) => () => ( + +) + +const UnselectedBurnButton = () => + const BurnButton = ({ permission, isBurned, @@ -100,13 +106,7 @@ const BurnButton = ({ disabled={isBurned} colorStyle={isSelected ? 'redSecondary' : 'greySecondary'} size="small" - suffix={ - isSelected ? ( - - ) : ( - - ) - } + suffix={isSelected ? SelectedBurnButton(permission) : UnselectedBurnButton} > {t(`permissions.${permission}`)} @@ -218,7 +218,7 @@ const BurnFusesContent = ({ {!_fuseData.CANNOT_UNWRAP && !fuseSelected.CANNOT_UNWRAP ? ( <> - + {t('fuses.info')} > diff --git a/src/components/@molecules/ConfirmationDialogView/ConfirmationDialogView.test.tsx b/src/components/@molecules/ConfirmationDialogView/ConfirmationDialogView.test.tsx index 7372836b3..573a572e7 100644 --- a/src/components/@molecules/ConfirmationDialogView/ConfirmationDialogView.test.tsx +++ b/src/components/@molecules/ConfirmationDialogView/ConfirmationDialogView.test.tsx @@ -2,8 +2,8 @@ import { render, screen, userEvent } from '@app/test-utils' import { describe, expect, it, vi } from 'vitest' -import { ConfirmationDialogView } from './ConfirmationDialogView' import { makeMockIntersectionObserver } from '../../../../test/mock/makeMockIntersectionObserver' +import { ConfirmationDialogView } from './ConfirmationDialogView' const mockOnConfirm = vi.fn() const mockOnDecline = vi.fn() diff --git a/src/components/@molecules/DateSelection/DateSelection.test.tsx b/src/components/@molecules/DateSelection/DateSelection.test.tsx index 2ddad8ce2..efd867b8b 100644 --- a/src/components/@molecules/DateSelection/DateSelection.test.tsx +++ b/src/components/@molecules/DateSelection/DateSelection.test.tsx @@ -3,11 +3,11 @@ import { act, mockFunction, render, renderHook, screen, userEvent, waitFor } fro import { useState } from 'react' import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' +import { useBreakpoint } from '@app/utils/BreakpointProvider' import { secondsFromDateDiff } from '@app/utils/date' import { ONE_DAY, ONE_YEAR } from '@app/utils/time' import { DateSelection } from './DateSelection' -import { useBreakpoint } from '@app/utils/BreakpointProvider' vi.mock('@app/utils/BreakpointProvider') diff --git a/src/components/@molecules/DialogComponentVariants/DialogFooterWithBorder.tsx b/src/components/@molecules/DialogComponentVariants/DialogFooterWithBorder.tsx index c7b2b7c15..83e3a72eb 100644 --- a/src/components/@molecules/DialogComponentVariants/DialogFooterWithBorder.tsx +++ b/src/components/@molecules/DialogComponentVariants/DialogFooterWithBorder.tsx @@ -1,7 +1,7 @@ import { ComponentProps } from 'react' import styled, { css } from 'styled-components' -import { Dialog, mq } from '@ensdomains/thorin' +import { Dialog } from '@ensdomains/thorin' const Wrapper = styled.div<{ $fullWidth?: boolean }>( ({ theme, $fullWidth }) => css` @@ -14,16 +14,13 @@ const Wrapper = styled.div<{ $fullWidth?: boolean }>( width: calc(100% + 2 * ${theme.space['4']}); margin: -${theme.space['4']} -${theme.space['4']} 0 -${theme.space['4']}; padding: ${theme.space['4']} ${theme.space['4']} 0 ${theme.space['4']}; - `} - ${mq.sm.min(css` - ${$fullWidth && - css` + @media (min-width: ${theme.breakpoints.sm}px) { width: calc(100% + 2 * ${theme.space['6']}); margin: -${theme.space['6']} -${theme.space['6']} 0 -${theme.space['6']}; padding: ${theme.space['4']} ${theme.space['4']} 0 ${theme.space['4']}; - `} - `)} + } + `} `, ) diff --git a/src/components/@molecules/DialogComponentVariants/DialogHeadinWithBorder.tsx b/src/components/@molecules/DialogComponentVariants/DialogHeadinWithBorder.tsx index ef4a0f784..f68f666a3 100644 --- a/src/components/@molecules/DialogComponentVariants/DialogHeadinWithBorder.tsx +++ b/src/components/@molecules/DialogComponentVariants/DialogHeadinWithBorder.tsx @@ -1,7 +1,7 @@ import { ComponentProps } from 'react' import styled, { css } from 'styled-components' -import { Dialog, mq } from '@ensdomains/thorin' +import { Dialog } from '@ensdomains/thorin' const Wrapper = styled.div<{ $fullWidth?: boolean }>( ({ theme, $fullWidth }) => css` @@ -14,16 +14,13 @@ const Wrapper = styled.div<{ $fullWidth?: boolean }>( width: calc(100% + 2 * ${theme.space['4']}); margin: -${theme.space['4']}; padding: ${theme.space['4']}; - `} - ${mq.sm.min(css` - ${$fullWidth && - css` + @media (min-width: ${theme.breakpoints.sm}px) { width: calc(100% + 2 * ${theme.space['6']}); margin: 0 -${theme.space['6']} -${theme.space['6']} -${theme.space['6']}; padding: 0 ${theme.space['6']} ${theme.space['4']} ${theme.space['6']}; - `} - `)} + } + `} `, ) diff --git a/src/components/@molecules/DialogComponentVariants/DialogInput.tsx b/src/components/@molecules/DialogComponentVariants/DialogInput.tsx index ac3e325ad..5017333e9 100644 --- a/src/components/@molecules/DialogComponentVariants/DialogInput.tsx +++ b/src/components/@molecules/DialogComponentVariants/DialogInput.tsx @@ -1,15 +1,15 @@ import { ComponentProps, forwardRef } from 'react' import styled, { css } from 'styled-components' -import { Input, mq } from '@ensdomains/thorin' +import { Input } from '@ensdomains/thorin' const Wrapper = styled.div( ({ theme }) => css` width: ${theme.space.full}; margin-bottom: -${theme.space['4']}; - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { margin-bottom: -${theme.space['6']}; - `)} + } `, ) diff --git a/src/components/@molecules/DisabledButtonWithTooltip.tsx b/src/components/@molecules/DisabledButtonWithTooltip.tsx index 897dfe690..66b2e7004 100644 --- a/src/components/@molecules/DisabledButtonWithTooltip.tsx +++ b/src/components/@molecules/DisabledButtonWithTooltip.tsx @@ -1,8 +1,6 @@ import { ComponentProps } from 'react' -import { Button, Tooltip } from '@ensdomains/thorin' -import { ButtonProps } from '@ensdomains/thorin/dist/types/components/atoms/Button' -import { ReactNodeNoStrings } from '@ensdomains/thorin/dist/types/types/index' +import { AsProp, Button, ButtonProps, Tooltip } from '@ensdomains/thorin' import { useTooltipSeenManager } from '@app/hooks/useTooltipSeenManager' @@ -33,7 +31,7 @@ export const DisabledButtonWithTooltip = ({ mobileWidth?: number buttonWidth?: ButtonProps['width'] colorStyle?: ButtonProps['colorStyle'] - prefix?: ReactNodeNoStrings + prefix?: AsProp loading?: boolean }) => { const { shouldShowTooltipIndicator, onSeen } = useTooltipSeenManager(buttonId) diff --git a/src/components/@molecules/FaucetBanner.tsx b/src/components/@molecules/FaucetBanner.tsx index f6f9a3646..1de27c068 100644 --- a/src/components/@molecules/FaucetBanner.tsx +++ b/src/components/@molecules/FaucetBanner.tsx @@ -78,8 +78,8 @@ const FaucetBanner = () => { const BannerComponent = ( } - icon={} + actionIcon={RightArrowSVG} + icon={EthSVG} onClick={openDialog} alert="info" title={`You have unclaimed ${chainName} ETH!`} @@ -112,7 +112,7 @@ const FaucetBanner = () => { { label: 'Address', value: address || '', type: 'address', useRawLabel: true }, ]} /> - {isError && {(error as Error).message}} + {isError && {(error as Error).message}} css` @@ -16,19 +16,19 @@ const Container = styled.div( padding: ${theme.space['4']}; gap: ${theme.space['4']}; - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { flex-direction: column; padding: 0; gap: 0; - `)} + } `, ) const HeadingWrapper = styled.div( ({ theme }) => css` - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { border-bottom: 1px solid ${theme.colors.border}; - `)} + } `, ) @@ -55,7 +55,7 @@ const Heading = styled.div( color: ${theme.colors.grey}; } - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { justify-content: flex-start; padding: ${theme.space['4']} ${theme.space['6']}; margin: ${theme.space['2']}; @@ -67,7 +67,7 @@ const Heading = styled.div( & > div > svg { display: none; } - `)} + } `, ) @@ -88,11 +88,11 @@ const LanguagesContainer = styled.div( align-items: stretch; justify-content: flex-start; gap: ${theme.space['2']}; - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { flex-direction: column; padding: ${theme.space['2']}; gap: 0; - `)} + } `, ) @@ -125,10 +125,9 @@ const LanguageItem = styled.div( color: ${theme.colors.green}; } } - - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { border: none; - `)} + } `, ) diff --git a/src/components/@molecules/Hamburger/MainMenu.tsx b/src/components/@molecules/Hamburger/MainMenu.tsx index 06ee8e264..ed2e34b44 100644 --- a/src/components/@molecules/Hamburger/MainMenu.tsx +++ b/src/components/@molecules/Hamburger/MainMenu.tsx @@ -5,10 +5,11 @@ import styled, { css } from 'styled-components' import { CurrencyToggle, LanguageSVG, - mq, RightChevronSVG, Spinner, + ThemeToggle, Typography, + useTheme, WalletSVG, } from '@ensdomains/thorin' @@ -36,12 +37,12 @@ const Container = styled.div( flex-direction: column; align-items: stretch; justify-content: flex-start; - background-color: ${theme.colors.background}; + background-color: ${theme.colors.backgroundPrimary}; padding: ${theme.space['4']}; gap: ${theme.space['2']}; - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { padding: 0; gap: 0; & > div { @@ -51,7 +52,7 @@ const Container = styled.div( & > div:last-child { border-bottom: none; } - `)} + } `, ) @@ -66,11 +67,11 @@ const SettingsSection = styled.div( margin-bottom: ${theme.space['2']}; gap: ${theme.space['2']}; - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { padding: ${theme.space['2']}; margin: 0; gap: 0; - `)} + } `, ) @@ -99,9 +100,9 @@ const SettingsItem = styled.div( } } - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { border: none; - `)} + } `, ) @@ -135,10 +136,10 @@ const miscSectionStyle = css( background-color: ${theme.colors.greySurface}; border-radius: ${theme.radii.large}; - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { background-color: transparent; border-radius: none; - `)} + } `, ) @@ -164,9 +165,9 @@ const RouteItem = styled.a( background-color: ${theme.colors.greySurface}; } - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { padding: ${theme.space['2']} ${theme.space['4']}; - `)} + } `, ) @@ -196,9 +197,9 @@ const NetworkSectionContainer = styled.div( text-transform: capitalize; } - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { padding: ${theme.space['4']} ${theme.space['6']}; - `)} + } `, miscSectionStyle, ) @@ -214,6 +215,18 @@ const NetworkSectionRow = styled.div( `, ) +const DarkModeItem = styled.div( + ({ theme }) => css` + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + gap: ${theme.space['2']}; + + padding: ${theme.space['4']} ${theme.space['6']}; + `, +) + const NetworkSection = () => { const { t } = useTranslation('common') const graphOutOfSync = useGraphOutOfSync() @@ -254,20 +267,21 @@ const MainMenu = ({ setCurrentView }: { setCurrentView: (view: 'main' | 'languag const { t, i18n } = useTranslation('common') const language = i18n.resolvedLanguage || 'en' const { userConfig, setCurrency } = useUserConfig() + const { setMode, mode } = useTheme() return ( setCurrentView('language')}> - + {t('navigation.language')} {ISO6391.getNativeName(language)} ({language.toLocaleUpperCase()}) - + @@ -284,6 +298,19 @@ const MainMenu = ({ setCurrentView }: { setCurrentView: (view: 'main' | 'languag /> + + Theme + { + const newValue = e.target.checked ? 'light' : 'dark' + if (newValue !== mode) { + setMode(newValue) + } + }} + /> + {disconnectedRoutes.map((route) => ( diff --git a/src/components/@molecules/LegacyDropdown/LegacyDropdown.tsx b/src/components/@molecules/LegacyDropdown/LegacyDropdown.tsx index 8850bc7db..a7ebb50b3 100644 --- a/src/components/@molecules/LegacyDropdown/LegacyDropdown.tsx +++ b/src/components/@molecules/LegacyDropdown/LegacyDropdown.tsx @@ -11,7 +11,7 @@ import { } from 'react' import styled, { css } from 'styled-components' -import { Button, Colors, DownChevronSVG } from '@ensdomains/thorin' +import { AsProp, Button, Colors, DownChevronSVG } from '@ensdomains/thorin' import { getTestId } from '@app/utils/utils' @@ -34,7 +34,7 @@ type DropdownItemObject = { onClick?: (value?: string) => void wrapper?: (children: React.ReactNode, key: React.Key) => JSX.Element as?: 'button' | 'a' - icon?: React.ReactNode + icon?: AsProp value?: string color?: Colors disabled?: boolean @@ -186,7 +186,7 @@ const MenuButton = styled.button( } ${disabled && css` - color: ${theme.colors.textTertiary}; + color: ${theme.colors.grey}; cursor: not-allowed; `} @@ -374,7 +374,7 @@ const InnerMenuButton = styled.button( border-${$direction === 'down' ? 'bottom' : 'top'}-left-radius: none; border-${$direction === 'down' ? 'bottom' : 'top'}-right-radius: none; border-${$direction === 'down' ? 'bottom' : 'top'}-width: 0; - color: ${theme.colors.textTertiary}; + color: ${theme.colors.grey}; transition: 0.35s all cubic-bezier(1, 0, 0.22, 1.6), 0.3s color ease-in-out, 0.2s border-radius ease-in-out, 0s border-width 0.1s, 0s padding linear; @@ -464,6 +464,10 @@ const ButtonWrapper = styled.div( `, ) +const ChevronSuffix = + ({ direction, isOpen }: { direction: Direction; isOpen?: boolean }) => + () => + export const LegacyDropdown = ({ children, buttonProps, @@ -527,7 +531,7 @@ export const LegacyDropdown = ({ } + suffix={chevron ? ChevronSuffix({ direction, isOpen }) : undefined} onClick={() => setIsOpen(!isOpen)} > {label} diff --git a/src/components/@molecules/NameListView/NameListView.tsx b/src/components/@molecules/NameListView/NameListView.tsx index 553686d2e..478f798c7 100644 --- a/src/components/@molecules/NameListView/NameListView.tsx +++ b/src/components/@molecules/NameListView/NameListView.tsx @@ -199,7 +199,7 @@ export const NameListView = ({ address, selfAddress, setError, setLoading }: Nam size="small" onClick={handleExtend} data-testid="extend-names-button" - prefix={} + prefix={FastForwardSVG} disabled={selectedNames.length === 0} > {t('action.extend', { ns: 'common' })} diff --git a/src/components/@molecules/NameTableHeader/NameTableHeader.tsx b/src/components/@molecules/NameTableHeader/NameTableHeader.tsx index 141416219..c2e2d9b92 100644 --- a/src/components/@molecules/NameTableHeader/NameTableHeader.tsx +++ b/src/components/@molecules/NameTableHeader/NameTableHeader.tsx @@ -1,9 +1,10 @@ +/* stylelint-disable declaration-block-no-redundant-longhand-properties */ import { PropsWithChildren } from 'react' import { useTranslation } from 'react-i18next' import styled, { css } from 'styled-components' import { GetNamesForAddressParameters } from '@ensdomains/ensjs/subgraph' -import { Input, MagnifyingGlassSimpleSVG, mq, Select } from '@ensdomains/thorin' +import { Input, MagnifyingGlassSimpleSVG, Select } from '@ensdomains/thorin' import DownDirectionSVG from '@app/assets/SortAscending.svg' import UpDirectionSVG from '@app/assets/SortDescending.svg' @@ -20,12 +21,12 @@ const TableHeader = styled.div<{ border-bottom: 1px solid ${theme.colors.border}; padding: ${theme.space['3']} ${theme.space['4']}; gap: ${theme.space['2']}; - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { flex-direction: row; align-items: center; padding: ${theme.space['3']} ${theme.space['4.5']}; gap: ${$desktopGap === 'medium' ? theme.space['6'] : theme.space['2']}; - `)} + } `, ) @@ -46,12 +47,13 @@ const TableHeaderLeadingLeft = styled.div<{ $isFullWidth: boolean }>( align-items: center; color: ${theme.colors.text}; ${$isFullWidth && `flex: 1;`} - ${mq.sm.min(css` + + @media (min-width: ${theme.breakpoints.sm}px) { gap: ${theme.space['4']}; flex-basis: auto; flex-grow: 0; flex-shrink: 0; - `)} + } `, ) @@ -80,10 +82,10 @@ const TableHeaderTrailing = styled.div<{ flex-direction: row; align-items: center; justify-content: center; - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { flex: ${$isDesktopFlexibleWidth ? '2' : `0 0 ${theme.space['32']}`}; width: ${theme.space['32']}; - `)} + } `, ) @@ -104,7 +106,7 @@ const DirectionButton = styled.button<{ $active: boolean }>( width: ${theme.space['3']}; height: ${theme.space['3']}; path { - fill: ${$active ? theme.colors.accent : theme.colors.textTertiary}; + fill: ${$active ? theme.colors.accent : theme.colors.grey}; } } &:hover { diff --git a/src/components/@molecules/ProfileEditor/Avatar/AvatarButton.tsx b/src/components/@molecules/ProfileEditor/Avatar/AvatarButton.tsx index 57993b51a..9613532d0 100644 --- a/src/components/@molecules/ProfileEditor/Avatar/AvatarButton.tsx +++ b/src/components/@molecules/ProfileEditor/Avatar/AvatarButton.tsx @@ -164,7 +164,7 @@ const AvatarButton = ({ {...dropdownProps} > - + {!validated && !error && ( diff --git a/src/components/@molecules/ProfileEditor/Avatar/AvatarCrop.tsx b/src/components/@molecules/ProfileEditor/Avatar/AvatarCrop.tsx index 0c1976e2c..f0e6fa459 100644 --- a/src/components/@molecules/ProfileEditor/Avatar/AvatarCrop.tsx +++ b/src/components/@molecules/ProfileEditor/Avatar/AvatarCrop.tsx @@ -3,7 +3,7 @@ import { useCallback, useEffect, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' import styled, { css } from 'styled-components' -import { Button, Dialog, mq, Slider } from '@ensdomains/thorin' +import { Button, Dialog, Slider } from '@ensdomains/thorin' import CropBorderSVG from '@app/assets/CropBorder.svg' import CropFrameSVG from '@app/assets/CropFrame.svg' @@ -91,10 +91,9 @@ const SliderContainer = styled.div( height: ${theme.space['6']}; opacity: 0.15; } - - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { padding: ${theme.space['2']} ${theme.space['8']}; - `)} + } `, ) diff --git a/src/components/@molecules/ProfileEditor/Avatar/AvatarNFT.test.tsx b/src/components/@molecules/ProfileEditor/Avatar/AvatarNFT.test.tsx index 33e58a23c..cddf28b12 100644 --- a/src/components/@molecules/ProfileEditor/Avatar/AvatarNFT.test.tsx +++ b/src/components/@molecules/ProfileEditor/Avatar/AvatarNFT.test.tsx @@ -5,12 +5,12 @@ import * as ReactQuery from '@tanstack/react-query' import { beforeEach, describe, expect, it, Mock, vi } from 'vitest' import { useAccount, useClient } from 'wagmi' -import * as ThorinComponents from '@ensdomains/thorin' import * as UseInfiniteQuery from '@app/utils/query/useInfiniteQuery' import { makeMockIntersectionObserver } from '../../../../../test/mock/makeMockIntersectionObserver' import { AvatarNFT } from './AvatarNFT' +import React from 'react' vi.mock('wagmi') vi.mock('@app/hooks/chain/useCurrentBlockTimestamp', () => ({ @@ -20,6 +20,8 @@ vi.mock('@app/hooks/chain/useChainName', () => ({ useChainName: () => 'mainnet', })) + + const mockUseClient = mockFunction(useClient) const mockUseAccount = mockFunction(useAccount) @@ -194,6 +196,8 @@ describe('', () => { }) it('show load more data on page load trigger', async () => { const useInfiniteQuerySpy = vi.spyOn(UseInfiniteQuery, 'useInfiniteQuery') + + mockFetch .mockImplementationOnce(() => Promise.resolve({ @@ -209,12 +213,16 @@ describe('', () => { pageKey: 'test456', }), ) - vi.spyOn(ThorinComponents, 'ScrollBox').mockImplementationOnce( - ({ children, onReachedBottom }) => { + vi.mock('@ensdomains/thorin', async (importActual) => ({ + ...(await importActual() as any), + ScrollBox: () => ({ children, onReachedBottom }: React.PropsWithChildren<{ + onReachedBottom?: () => void; + }>) => { onReachedBottom!() return {children} }, - ) + })) + render() await waitFor(() => expect(mockFetch).toHaveBeenCalled()) @@ -246,12 +254,15 @@ describe('', () => { }), ) - vi.spyOn(ThorinComponents, 'ScrollBox').mockImplementationOnce( - ({ children, onReachedBottom }) => { + vi.mock('@ensdomains/thorin', async (importActual) => ({ + ...(await importActual() as any), + ScrollBox: () => ({ children, onReachedBottom }: React.PropsWithChildren<{ + onReachedBottom?: () => void; + }>) => { onReachedBottom!() return {children} }, - ) + })) render() diff --git a/src/components/@molecules/ProfileEditor/Avatar/AvatarNFT.tsx b/src/components/@molecules/ProfileEditor/Avatar/AvatarNFT.tsx index 118034268..e34cd6b95 100644 --- a/src/components/@molecules/ProfileEditor/Avatar/AvatarNFT.tsx +++ b/src/components/@molecules/ProfileEditor/Avatar/AvatarNFT.tsx @@ -11,7 +11,6 @@ import { Dialog, Heading, MagnifyingGlassSVG, - mq, Typography, } from '@ensdomains/thorin' @@ -158,7 +157,7 @@ const NFTContainer = styled.div( &[aria-disabled='true'] { cursor: not-allowed; opacity: 1; - color: ${theme.colors.textTertiary}; + color: ${theme.colors.grey}; } `, ) @@ -209,11 +208,11 @@ const SelectedNFTContainer = styled.div(({ theme }) => [ font-size: ${theme.fontSizes.headingThree}; } } + @media (min-width: ${theme.breakpoints.sm}px) { + width: calc(80vw - 2 * ${theme.space['6']}); + max-width: ${theme.space['128']}; + } `, - mq.sm.min(css` - width: calc(80vw - 2 * ${theme.space['6']}); - max-width: ${theme.space['128']}; - `), ]) const SelectedNFTImageWrapper = styled.div( @@ -240,22 +239,22 @@ const FilterContainer = styled.div( gap: ${theme.space['4']}; margin-bottom: ${theme.space['4']}; - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { margin-bottom: ${theme.space['6']}; - `)} + } & > button { flex-basis: 100px; margin-bottom: -${theme.space['4']}; - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { margin-bottom: -${theme.space['6']}; - `)} + } } `, ) -const LoadingContainer = styled.div(({ theme }) => [ - css` +const LoadingContainer = styled.div( + ({ theme }) => css` width: ${theme.space.full}; min-height: ${theme.space['32']}; @@ -264,11 +263,11 @@ const LoadingContainer = styled.div(({ theme }) => [ justify-content: center; flex-direction: column; gap: ${theme.space['4']}; + @media (min-width: ${theme.breakpoints.sm}px) { + gap: ${theme.space['6']}; + } `, - mq.sm.min(css` - gap: ${theme.space['6']}; - `), -]) +) const LoadFailureContainer = styled.div( ({ theme }) => css` @@ -286,7 +285,7 @@ const LoadFailureContainer = styled.div( border-radius: ${theme.radii['2xLarge']}; background-color: ${theme.colors.greySurface}; - color: ${theme.colors.textTertiary}; + color: ${theme.colors.grey}; & > svg { width: ${theme.space['5']}; @@ -329,7 +328,7 @@ const NftItem = ({ ) : ( - + {t('input.profileEditor.tabs.avatar.nft.loadError')} diff --git a/src/components/@molecules/ProfileEditor/Avatar/AvatarUpload.test.tsx b/src/components/@molecules/ProfileEditor/Avatar/AvatarUpload.test.tsx index eb0e9613a..677223a97 100644 --- a/src/components/@molecules/ProfileEditor/Avatar/AvatarUpload.test.tsx +++ b/src/components/@molecules/ProfileEditor/Avatar/AvatarUpload.test.tsx @@ -5,8 +5,8 @@ import { useAccount, useSignTypedData } from 'wagmi' import { useChainName } from '@app/hooks/chain/useChainName' -import { AvatarUpload } from './AvatarUpload' import { makeMockIntersectionObserver } from '../../../../../test/mock/makeMockIntersectionObserver' +import { AvatarUpload } from './AvatarUpload' vi.mock('wagmi') diff --git a/src/components/@molecules/ProfileEditor/Avatar/AvatarUpload.tsx b/src/components/@molecules/ProfileEditor/Avatar/AvatarUpload.tsx index 6959e53e9..59efe914c 100644 --- a/src/components/@molecules/ProfileEditor/Avatar/AvatarUpload.tsx +++ b/src/components/@molecules/ProfileEditor/Avatar/AvatarUpload.tsx @@ -136,7 +136,7 @@ const UploadComponent = ({ {error && ( - + {error.message} )} diff --git a/src/components/@molecules/ProfileEditor/options/addressOptions.tsx b/src/components/@molecules/ProfileEditor/options/addressOptions.tsx index d05dc3fd8..d2b905474 100644 --- a/src/components/@molecules/ProfileEditor/options/addressOptions.tsx +++ b/src/components/@molecules/ProfileEditor/options/addressOptions.tsx @@ -25,7 +25,7 @@ const AddressWrapper = styled.div( const UnsupportedAddressWrapper = styled.div( ({ theme }) => css` - background-color: ${theme.colors.textTertiary}; + background-color: ${theme.colors.grey}; color: ${theme.colors.backgroundPrimary}; border-radius: ${theme.radii.large}; font-size: 1rem; diff --git a/src/components/@molecules/QuestionTooltip/QuestionTooltip.tsx b/src/components/@molecules/QuestionTooltip/QuestionTooltip.tsx index 615bbe769..58ca18220 100644 --- a/src/components/@molecules/QuestionTooltip/QuestionTooltip.tsx +++ b/src/components/@molecules/QuestionTooltip/QuestionTooltip.tsx @@ -53,7 +53,7 @@ export const QuestionTooltip = ({ content, link, ...props }: Props) => { const { t } = useTranslation('common') const _content = ( - + {content} {link && ( diff --git a/src/components/@molecules/RecordInput/RecordInput.tsx b/src/components/@molecules/RecordInput/RecordInput.tsx index b884cd7c8..9de6d7664 100644 --- a/src/components/@molecules/RecordInput/RecordInput.tsx +++ b/src/components/@molecules/RecordInput/RecordInput.tsx @@ -80,7 +80,7 @@ const LabelSecondary = styled.div( ({ theme }) => css` font-size: ${theme.space['3.5']}; line-height: 1.2; - color: ${theme.colors.textTertiary}; + color: ${theme.colors.grey}; `, ) diff --git a/src/components/@molecules/SearchInput/SearchInput.tsx b/src/components/@molecules/SearchInput/SearchInput.tsx index 0d091ee4c..0c3a97d9c 100644 --- a/src/components/@molecules/SearchInput/SearchInput.tsx +++ b/src/components/@molecules/SearchInput/SearchInput.tsx @@ -22,7 +22,7 @@ import { GetPriceReturnType, GetWrapperDataReturnType, } from '@ensdomains/ensjs/public' -import { BackdropSurface, mq, Portal, Typography } from '@ensdomains/thorin' +import { BackdropSurface, Portal, Typography } from '@ensdomains/thorin' import { SupportedChain } from '@app/constants/chains' import { @@ -53,14 +53,14 @@ import { getBoxNameStatus, SearchResult } from './SearchResult' import { HistoryItem, SearchHandler, SearchItem } from './types' const Container = styled.div<{ $size: 'medium' | 'extraLarge' }>( - ({ $size }) => css` + ({ $size, theme }) => css` width: 100%; position: relative; ${$size === 'extraLarge' && - mq.sm.min(css` - padding-left: 48px; + ` @media (min-width: ${theme.breakpoints.sm}px) { + padding-left: 48px; padding-right: 48px; - `)} + }`} `, ) @@ -73,7 +73,7 @@ const SearchResultsContainer = styled.div<{ height: min-content; top: calc(100% + ${theme.space['3']}); - background-color: #f7f7f7; + background-color: ${theme.colors.background}; box-shadow: 0 2px 12px ${theme.colors.border}; border-radius: ${theme.radii.extraLarge}; border: ${theme.borderWidths.px} ${theme.borderStyles.solid} ${theme.colors.border}; diff --git a/src/components/@molecules/SearchInput/SearchInputBox.tsx b/src/components/@molecules/SearchInput/SearchInputBox.tsx index 3dd3040a7..27daa0d91 100644 --- a/src/components/@molecules/SearchInput/SearchInputBox.tsx +++ b/src/components/@molecules/SearchInput/SearchInputBox.tsx @@ -33,30 +33,6 @@ const SearchInputWrapper = styled.div<{ $size: 'medium' | 'extraLarge' }>( `, ) -const StyledInputParent = (size: 'medium' | 'extraLarge') => - css( - ({ theme }) => css` - border-radius: ${theme.radii.full}; - background-color: ${theme.colors.backgroundSecondary}; - transition: background-color 0.35s ease-in-out; - ${size === 'medium' && - css` - & > div { - border-radius: ${theme.radii.full}; - input { - padding-left: ${theme.space['12']}; - } - } - `} - &:focus-within { - background-color: ${theme.colors.backgroundPrimary}; - & input::placeholder { - color: transparent; - } - } - `, - ) - const MagnifyingGlassIcon = styled.svg( ({ theme }) => css` width: ${theme.space['4']}; @@ -103,7 +79,6 @@ export const SearchInputBox = forwardRef( clearable autoComplete="off" autoCorrect="off" - parentStyles={StyledInputParent(size)} icon={size === 'medium' ? : undefined} spellCheck="false" data-testid="search-input-box" @@ -133,7 +108,6 @@ export const FakeSearchInputBox = forwardRef diff --git a/src/components/@molecules/SearchInput/SearchResult.tsx b/src/components/@molecules/SearchInput/SearchResult.tsx index f80186183..31cd2f74f 100644 --- a/src/components/@molecules/SearchInput/SearchResult.tsx +++ b/src/components/@molecules/SearchInput/SearchResult.tsx @@ -36,7 +36,7 @@ const SearchItemContainer = styled.div<{ gap: ${theme.space['2']}; height: ${theme.space['14']}; padding: 0 ${theme.space['4']}; - border-bottom: ${theme.borderWidths['0.375']} ${theme.borderStyles.solid} ${theme.colors.border}; + border-bottom: 0.0938rem ${theme.borderStyles.solid} ${theme.colors.border}; &:last-of-type { border-bottom: 0; } @@ -83,7 +83,7 @@ const SearchItemContainer = styled.div<{ const NoInputYetTypography = styled(Typography)( ({ theme }) => css` - color: ${theme.colors.textTertiary}; + color: ${theme.colors.grey}; `, ) @@ -158,7 +158,7 @@ const StyledTag = styled(Tag)( const AddressTag = styled(StyledTag)( ({ theme }) => css` - border: ${theme.borderWidths['0.375']} solid ${theme.colors.border}; + border: 0.0938rem solid ${theme.colors.border}; background-color: transparent; `, ) diff --git a/src/components/@molecules/TransactionDialogManager/DisplayItems.tsx b/src/components/@molecules/TransactionDialogManager/DisplayItems.tsx index a33e334ee..53e67cc75 100644 --- a/src/components/@molecules/TransactionDialogManager/DisplayItems.tsx +++ b/src/components/@molecules/TransactionDialogManager/DisplayItems.tsx @@ -252,7 +252,7 @@ const DurationValue = ({ value }: { value: string | undefined }) => { {value} - + {t('transaction.extendNames.newExpiry', { date: formatExpiry(date) })} diff --git a/src/components/@molecules/TransactionDialogManager/InputComponentWrapper.test.tsx b/src/components/@molecules/TransactionDialogManager/InputComponentWrapper.test.tsx index dfaa985ea..cb99ecd83 100644 --- a/src/components/@molecules/TransactionDialogManager/InputComponentWrapper.test.tsx +++ b/src/components/@molecules/TransactionDialogManager/InputComponentWrapper.test.tsx @@ -1,13 +1,12 @@ import { act, render, screen, waitFor } from '@app/test-utils' import { QueryClientProvider } from '@tanstack/react-query' -import { useQuery } from '@app/utils/query/useQuery' - import { ReactNode, useContext, useEffect } from 'react' import { beforeEach, describe, expect, it, vi } from 'vitest' import { WagmiProvider } from 'wagmi' import { queryClientWithRefetch as queryClient } from '@app/utils/query/reactQuery' +import { useQuery } from '@app/utils/query/useQuery' import { wagmiConfig } from '@app/utils/query/wagmi' import DynamicLoadingContext from './DynamicLoadingContext' diff --git a/src/components/@molecules/TransactionDialogManager/stage/TransactionStageModal.test.tsx b/src/components/@molecules/TransactionDialogManager/stage/TransactionStageModal.test.tsx index e1a30690b..a511fb560 100644 --- a/src/components/@molecules/TransactionDialogManager/stage/TransactionStageModal.test.tsx +++ b/src/components/@molecules/TransactionDialogManager/stage/TransactionStageModal.test.tsx @@ -16,10 +16,10 @@ import { useIsSafeApp } from '@app/hooks/useIsSafeApp' import { GenericTransaction } from '@app/transaction-flow/types' import { checkIsSafeApp } from '@app/utils/safe' +import { makeMockIntersectionObserver } from '../../../../../test/mock/makeMockIntersectionObserver' import { useMockedUseQueryOptions } from '../../../../../test/mock/useMockedUseQueryOptions' import { calculateGasLimit, transactionSuccessHandler } from './query' import { handleBackToInput, TransactionStageModal } from './TransactionStageModal' -import { makeMockIntersectionObserver } from '../../../../../test/mock/makeMockIntersectionObserver' vi.mock('@app/hooks/account/useAccountSafely') vi.mock('@app/hooks/chain/useChainName') @@ -308,7 +308,7 @@ describe('TransactionStageModal', () => { ) expect(mockDispatch).toBeCalledWith({ name: 'setTransactionHash', - payload: { hash: '0x123', key: 'test'}, + payload: { hash: '0x123', key: 'test' }, }) }) it('should add to recent transactions and run dispatch from success callback when isSafeTx', async () => { @@ -331,7 +331,7 @@ describe('TransactionStageModal', () => { ) expect(mockDispatch).toBeCalledWith({ name: 'setTransactionHash', - payload: { hash: '0x123', key: 'test'}, + payload: { hash: '0x123', key: 'test' }, }) }) }) @@ -449,7 +449,10 @@ describe('transactionSuccessHandler', () => { await waitFor(() => expect(mockDispatch).toBeCalledWith( - expect.objectContaining({ name: 'setTransactionHash', payload: { hash: '0xhash', key: 'txKey'} }), + expect.objectContaining({ + name: 'setTransactionHash', + payload: { hash: '0xhash', key: 'txKey' }, + }), ), ) }) diff --git a/src/components/@molecules/TransactionDialogManager/stage/TransactionStageModal.tsx b/src/components/@molecules/TransactionDialogManager/stage/TransactionStageModal.tsx index 435f3b759..ce173e88d 100644 --- a/src/components/@molecules/TransactionDialogManager/stage/TransactionStageModal.tsx +++ b/src/components/@molecules/TransactionDialogManager/stage/TransactionStageModal.tsx @@ -528,7 +528,7 @@ export const TransactionStageModal = ({ return ( } + suffix={() => } data-testid="transaction-modal-confirm-button" > {t('transaction.dialog.confirm.waitingForWallet')} diff --git a/src/components/AvatarWithZorb.tsx b/src/components/AvatarWithZorb.tsx index 7b7b353b4..30a033280 100644 --- a/src/components/AvatarWithZorb.tsx +++ b/src/components/AvatarWithZorb.tsx @@ -2,7 +2,7 @@ import { ComponentProps } from 'react' import styled, { css } from 'styled-components' import { useEnsAvatar } from 'wagmi' -import { Avatar, mq, Space } from '@ensdomains/thorin' +import { Avatar, Space } from '@ensdomains/thorin' import { useZorb } from '@app/hooks/useZorb' import { QuerySpace } from '@app/types' @@ -22,16 +22,30 @@ const Wrapper = styled.div<{ $size?: QuerySpace }>( height: ${$size ? theme.space[$size] : theme.space.full}; flex: 0 0 ${$size ? theme.space[$size] : theme.space.full}; ` - : Object.entries($size) - .filter(([key]) => key !== 'min') - .map(([key, value]) => - mq[key as keyof typeof mq].min(css` - width: ${theme.space[value as Space]}; - height: ${theme.space[value as Space]}; - flex: 0 0 ${theme.space[value as Space]}; - `), - )} - + : css` + @media (min-width: ${theme.breakpoints.xs}px) { + width: ${theme.space[$size.min]}; + height: ${theme.space[$size.min]}; + flex: 0 0 ${theme.space[$size.min]}; + } + ${Object.keys($size) + .filter((key) => key !== 'min' && key in theme.breakpoints) + .map((key) => { + const sizeValue = $size[key as keyof typeof $size] + return sizeValue + ? css` + @media (min-width: ${theme.breakpoints[ + key as keyof typeof theme.breakpoints + ]}px) { + width: ${theme.space[sizeValue]}; + height: ${theme.space[sizeValue]}; + flex: 0 0 ${theme.space[sizeValue]}; + } + ` + : null + })} + `} + img { display: block; } diff --git a/src/components/ConnectButton.tsx b/src/components/ConnectButton.tsx index 921891df9..a63447eb3 100644 --- a/src/components/ConnectButton.tsx +++ b/src/components/ConnectButton.tsx @@ -5,16 +5,7 @@ import styled, { css } from 'styled-components' import type { Address } from 'viem' import { useDisconnect, useEnsAvatar } from 'wagmi' -import { - Button, - CheckSVG, - CogSVG, - CopySVG, - ExitSVG, - mq, - PersonSVG, - Profile, -} from '@ensdomains/thorin' +import { Button, CheckSVG, CogSVG, CopySVG, ExitSVG, PersonSVG, Profile } from '@ensdomains/thorin' import { DropdownItem } from '@ensdomains/thorin/dist/types/components/molecules/Dropdown/Dropdown' import { useAccountSafely } from '@app/hooks/account/useAccountSafely' @@ -45,9 +36,9 @@ const StyledButtonWrapper = styled.div<{ $isTabBar?: boolean; $large?: boolean } height: ${theme.space['10']}; border-radius: ${theme.radii.full}; font-size: ${theme.fontSizes.body}; - ${mq.xs.min(css` + @media (min-width: ${theme.breakpoints.xs}px) { padding: 0 ${theme.space['8']}; - `)} + } } ` : css` @@ -162,7 +153,7 @@ const HeaderProfile = ({ address }: { address: Address }) => { ), as: 'a' as 'a', color: 'text', - icon: , + icon: PersonSVG, }, ] : []), @@ -175,7 +166,7 @@ const HeaderProfile = ({ address }: { address: Address }) => { ), as: 'a', - icon: , + icon: CogSVG, showIndicator: hasPendingTransactions, }, , @@ -183,13 +174,13 @@ const HeaderProfile = ({ address }: { address: Address }) => { label: shortenAddress(address), color: 'text', onClick: () => copy(address), - icon: copied ? : , + icon: copied ? CheckSVG : CopySVG, }, { label: t('wallet.disconnect'), color: 'red', onClick: () => disconnect(), - icon: , + icon: ExitSVG, }, ] as DropdownItem[] } @@ -197,12 +188,13 @@ const HeaderProfile = ({ address }: { address: Address }) => { src: avatar || zorb, decoding: 'sync', loading: 'eager', - noBorder: true, - overlay: avatar ? undefined : ( - - - - ), + icon: avatar + ? undefined + : () => ( + + + + ), }} size="medium" alignDropdown="left" diff --git a/src/components/Header.tsx b/src/components/Header.tsx index f915760b7..5b804d9fd 100644 --- a/src/components/Header.tsx +++ b/src/components/Header.tsx @@ -4,8 +4,6 @@ import useTransition, { TransitionState } from 'react-transition-state' import styled, { css, useTheme } from 'styled-components' import { useAccount } from 'wagmi' -import { mq } from '@ensdomains/thorin' - import { useRecentTransactions } from '@app/hooks/transactions/useRecentTransactions' import { useInitial } from '@app/hooks/useInitial' import { legacyFavouritesRoute, routes } from '@app/routes' @@ -24,9 +22,9 @@ const HeaderWrapper = styled.header( ({ theme }) => css` height: ${theme.space['12']}; - ${mq.sm.max(css` + @media (max-width: ${theme.breakpoints.sm}px) { display: none; - `)} + } `, ) @@ -56,10 +54,10 @@ const NavContainer = styled.div( gap: ${theme.space['3']}; height: ${theme.space['12']}; - ${mq.lg.min(css` + @media (min-width: ${theme.breakpoints.lg}px) { flex-gap: ${theme.space['6']}; gap: ${theme.space['6']}; - `)} + } `, ) @@ -81,11 +79,11 @@ const RouteContainer = styled.div<{ $state: TransitionState }>( transform: translateX(125%); opacity: 0; - ${mq.lg.min(css` + @media (min-width: ${theme.breakpoints.lg}px) { flex-gap: ${theme.space['6']}; gap: ${theme.space['6']}; position: relative; - `)} + } ${$state === 'entered' && css` @@ -107,9 +105,9 @@ const SearchWrapper = styled.div<{ $state: TransitionState }>( max-width: ${theme.space['80']}; & > div > div { max-width: ${theme.space.full}; - ${mq.lg.min(css` + @media (min-width: ${theme.breakpoints.lg}px) { max-width: ${theme.space['80']}; - `)} + } } transition: margin 0.15s ease-in-out; @@ -118,9 +116,9 @@ const SearchWrapper = styled.div<{ $state: TransitionState }>( css` margin-right: 0; `} - ${mq.lg.min(css` + @media (min-width: ${theme.breakpoints.lg}px) { margin-right: 0; - `)} + } `, ) diff --git a/src/components/IconCopyAnimated.tsx b/src/components/IconCopyAnimated.tsx index 049a77ec6..ab73c0a1c 100644 --- a/src/components/IconCopyAnimated.tsx +++ b/src/components/IconCopyAnimated.tsx @@ -66,7 +66,7 @@ type SVGProps = { export const IconCopyAnimated = memo( ({ copied = false, - checkStrokeWidth = '1', + checkStrokeWidth = '1x', size = '6', color, }: { diff --git a/src/components/LeadingHeading.tsx b/src/components/LeadingHeading.tsx index b04384386..bc54de7e5 100644 --- a/src/components/LeadingHeading.tsx +++ b/src/components/LeadingHeading.tsx @@ -1,7 +1,5 @@ import styled, { css } from 'styled-components' -import { mq } from '@ensdomains/thorin' - export const LeadingHeading = styled.div( ({ theme }) => css` width: calc(100% - calc(${theme.radii.large} * 2)); @@ -10,9 +8,9 @@ export const LeadingHeading = styled.div( flex-direction: row; align-items: center; justify-content: space-between; - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { width: calc(100% - calc(${theme.radii['2xLarge']} * 2)); margin-left: ${theme.radii['2xLarge']}; - `)} + } `, ) diff --git a/src/components/NFTWithPlaceholder.tsx b/src/components/NFTWithPlaceholder.tsx index 9f8356d05..ec7b67e46 100644 --- a/src/components/NFTWithPlaceholder.tsx +++ b/src/components/NFTWithPlaceholder.tsx @@ -8,7 +8,7 @@ import NFTTemplate from './@molecules/NFTTemplate/NFTTemplate' const StyledNftBox = styled.div( ({ theme }) => css` - width: 100%; + width: ${theme.space.full}; border-radius: ${theme.radii.large}; overflow: hidden; `, diff --git a/src/components/Outlink.tsx b/src/components/Outlink.tsx index 726155471..80f8e3aa9 100644 --- a/src/components/Outlink.tsx +++ b/src/components/Outlink.tsx @@ -4,8 +4,7 @@ import Link from 'next/link' import { ComponentProps } from 'react' import styled, { css } from 'styled-components' -import { Typography } from '@ensdomains/thorin' -import { FontVariant } from '@ensdomains/thorin/dist/types/types' +import { AsProp, Typography, type FontVariant } from '@ensdomains/thorin' import OutlinkSVG from '@app/assets/Outlink.svg' @@ -48,7 +47,7 @@ export const Outlink = ({ ComponentProps & { href: string | UrlObject fontVariant?: FontVariant - icon?: any + icon?: AsProp iconPosition?: 'before' | 'after' }) => { const InnerContent = ( diff --git a/src/components/ProfileSnippet.tsx b/src/components/ProfileSnippet.tsx index 503b7d28a..092d1ab2e 100644 --- a/src/components/ProfileSnippet.tsx +++ b/src/components/ProfileSnippet.tsx @@ -2,7 +2,7 @@ import { useMemo } from 'react' import { useTranslation } from 'react-i18next' import styled, { css } from 'styled-components' -import { Button, mq, NametagSVG, Tag, Typography } from '@ensdomains/thorin' +import { Button, NametagSVG, Tag, Typography } from '@ensdomains/thorin' import FastForwardSVG from '@app/assets/FastForward.svg' import VerifiedPersonSVG from '@app/assets/VerifiedPerson.svg' @@ -18,7 +18,7 @@ const Container = styled.div<{ $banner?: string }>( width: 100%; padding: ${theme.space['4']}; padding-top: ${theme.space['18']}; - background-image: ${$banner ? `url(${$banner})` : theme.colors.gradients.blue}; + background-image: ${$banner ? `url(${$banner})` : theme.colors.blueGradient}; background-repeat: no-repeat; background-attachment: scroll; background-size: 100% ${theme.space['28']}; @@ -33,10 +33,10 @@ const Container = styled.div<{ $banner?: string }>( gap: ${theme.space['4']}; flex-gap: ${theme.space['4']}; - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { padding: ${theme.space['6']}; padding-top: ${theme.space['12']}; - `)} + } `, ) @@ -209,7 +209,7 @@ export const ProfileSnippet = ({ } + prefix={FastForwardSVG} data-testid="extend-button" onClick={() => { showExtendNamesInput(`extend-names-${name}`, { diff --git a/src/components/TabBar.tsx b/src/components/TabBar.tsx index 3078a5284..5525617ad 100644 --- a/src/components/TabBar.tsx +++ b/src/components/TabBar.tsx @@ -4,7 +4,7 @@ import { Dispatch, SetStateAction, useEffect, useState } from 'react' import styled, { css } from 'styled-components' import { useEnsAvatar } from 'wagmi' -import { CrossSVG, LeftChevronSVG, mq, PersonSVG } from '@ensdomains/thorin' +import { CrossSVG, LeftChevronSVG, PersonSVG } from '@ensdomains/thorin' import { useAccountSafely } from '@app/hooks/account/useAccountSafely' import { usePrimaryName } from '@app/hooks/ensjs/public/usePrimaryName' @@ -72,9 +72,9 @@ const TabWrapper = styled.div( ${theme.colors.backgroundSecondary} 60% ); padding: ${theme.space['4']}; - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { display: none; - `)} + } `, ) diff --git a/src/components/pages/AnnouncementBanner.tsx b/src/components/pages/AnnouncementBanner.tsx index d9e0c2a4d..93f45f32b 100644 --- a/src/components/pages/AnnouncementBanner.tsx +++ b/src/components/pages/AnnouncementBanner.tsx @@ -24,7 +24,7 @@ const Container = styled.div( } } - @media (min-width: 640px) { + @media (min-width: ${theme.breakpoints.sm}px) { flex-direction: row; } `, diff --git a/src/components/pages/dotbox/[name]/DotBoxRegistration.tsx b/src/components/pages/dotbox/[name]/DotBoxRegistration.tsx index 1dbddb288..1e60fe4fe 100644 --- a/src/components/pages/dotbox/[name]/DotBoxRegistration.tsx +++ b/src/components/pages/dotbox/[name]/DotBoxRegistration.tsx @@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next' import styled, { css } from 'styled-components' import { match, P } from 'ts-pattern' -import { Button, CheckSVG, Helper, mq, Spinner, Tag, Typography } from '@ensdomains/thorin' +import { Button, CheckSVG, Helper, Spinner, Tag, Typography } from '@ensdomains/thorin' import CoreFeatureENS from '@app/assets/dotbox/CoreFeatureENS.svg' import CoreFeatureNFT from '@app/assets/dotbox/CoreFeatureNFT.svg' @@ -27,10 +27,10 @@ const DotBoxCard = styled(Card)( padding: ${theme.space['4']}; align-items: flex-start; - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { padding: ${theme.space['6']} ${theme.space['18']}; gap: ${theme.space['6']}; - `)} + } `, ) @@ -176,7 +176,7 @@ export const DotBoxRegistration = () => { )) .with({ isLoading: false, nameStatus: P._ }, () => ( <> - + Online registration for this domain is unavailable. Please contact the registry directly for further information. diff --git a/src/components/pages/import/[name]/shared.tsx b/src/components/pages/import/[name]/shared.tsx index 8c3a4e835..b39fc394a 100644 --- a/src/components/pages/import/[name]/shared.tsx +++ b/src/components/pages/import/[name]/shared.tsx @@ -1,7 +1,7 @@ import { ComponentProps, forwardRef } from 'react' import styled, { css } from 'styled-components' -import { Button, Heading, Helper, mq, Typography } from '@ensdomains/thorin' +import { Button, Heading, Helper, Typography } from '@ensdomains/thorin' import { Card } from '@app/components/Card' import { IconCopyAnimated } from '@app/components/IconCopyAnimated' @@ -15,10 +15,10 @@ export const DnsImportCard = styled(Card)( gap: ${theme.space['4']}; padding: ${theme.space['4']}; - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { padding: ${theme.space['6']} ${theme.space['18']}; gap: ${theme.space['6']}; - `)} + } `, ) @@ -47,20 +47,19 @@ export const DnsImportActionsContainer = styled.div( justify-content: stretch; width: 100%; gap: ${theme.space['2']}; - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { flex-direction: row; justify-content: center; - `)} + } `, ) export const DnsImportActionButton = styled(Button)( ({ theme }) => css` width: 100%; - - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { width: ${theme.space['40']}; - `)} + } `, ) diff --git a/src/components/pages/import/[name]/steps/CompleteImport.tsx b/src/components/pages/import/[name]/steps/CompleteImport.tsx index d0df23e01..d3daf07e8 100644 --- a/src/components/pages/import/[name]/steps/CompleteImport.tsx +++ b/src/components/pages/import/[name]/steps/CompleteImport.tsx @@ -3,7 +3,7 @@ import type ConfettiT from 'react-confetti' import { Trans, useTranslation } from 'react-i18next' import styled, { css } from 'styled-components' -import { Button, Helper, mq, Typography } from '@ensdomains/thorin' +import { Button, Helper, Typography } from '@ensdomains/thorin' import MobileFullWidth from '@app/components/@atoms/MobileFullWidth' import { Card } from '@app/components/Card' @@ -25,10 +25,10 @@ const StyledCard = styled(Card)( max-width: ${theme.space.full}; } - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { padding: ${theme.space['6']} ${theme.space['18']}; gap: ${theme.space['6']}; - `)} + } `, ) @@ -68,7 +68,7 @@ const SubtitleWithGradient = styled(Typography)( font-size: ${theme.fontSizes.headingThree}; font-weight: bold; - background: ${theme.colors.gradients.blue}; + background: ${theme.colors.blueGradient}; /* stylelint-disable property-no-vendor-prefix */ -webkit-background-clip: text; -moz-background-clip: text; diff --git a/src/components/pages/import/[name]/steps/VerifyOffchainOwnership.tsx b/src/components/pages/import/[name]/steps/VerifyOffchainOwnership.tsx index e72dbc4ad..37623b516 100644 --- a/src/components/pages/import/[name]/steps/VerifyOffchainOwnership.tsx +++ b/src/components/pages/import/[name]/steps/VerifyOffchainOwnership.tsx @@ -101,7 +101,7 @@ export const VerifyOffchainOwnership = ({ {t('title')} {(() => { - if (!isConnected) return {t('status.disconnected')} + if (!isConnected) return {t('status.disconnected')} if (dnsOffchainStatus?.address?.status === 'matching') return ( @@ -148,7 +148,7 @@ export const VerifyOffchainOwnership = ({ } statusHelperElement={ dnsOffchainStatus?.address?.status === 'mismatching' && ( - {t('status.mismatching.error.offchain')} + {t('status.mismatching.error.offchain')} ) } /> diff --git a/src/components/pages/import/[name]/steps/onchain/ImportTransaction.tsx b/src/components/pages/import/[name]/steps/onchain/ImportTransaction.tsx index 1e9cc13d2..b8bb372e9 100644 --- a/src/components/pages/import/[name]/steps/onchain/ImportTransaction.tsx +++ b/src/components/pages/import/[name]/steps/onchain/ImportTransaction.tsx @@ -249,7 +249,7 @@ export const ImportTransaction = ({ {dnsOwnerStatus === 'mismatching' && ( - + {tc('steps.verifyOwnership.status.mismatching.error.onchain', { ns: 'dnssec' })} )} diff --git a/src/components/pages/import/[name]/steps/onchain/VerifyOnchainOwnership.tsx b/src/components/pages/import/[name]/steps/onchain/VerifyOnchainOwnership.tsx index eea61570d..50a7651d2 100644 --- a/src/components/pages/import/[name]/steps/onchain/VerifyOnchainOwnership.tsx +++ b/src/components/pages/import/[name]/steps/onchain/VerifyOnchainOwnership.tsx @@ -105,7 +105,7 @@ export const VerifyOnchainOwnership = ({ {t('title')} {dnsOwnerStatus !== 'matching' && {t('status.mismatching.heading')}} {(() => { - if (!isConnected) return {t('status.disconnected')} + if (!isConnected) return {t('status.disconnected')} if (dnsOwnerStatus === 'matching') return ( @@ -147,7 +147,7 @@ export const VerifyOnchainOwnership = ({ } statusHelperElement={ dnsOwnerStatus === 'mismatching' && ( - {t('status.mismatching.error.onchain')} + {t('status.mismatching.error.onchain')} ) } /> diff --git a/src/components/pages/profile/NameSnippet.tsx b/src/components/pages/profile/NameSnippet.tsx index f3abc8ef9..97a2e4240 100644 --- a/src/components/pages/profile/NameSnippet.tsx +++ b/src/components/pages/profile/NameSnippet.tsx @@ -50,7 +50,7 @@ const OwnerWithEns = styled.div( flex-gap: ${theme.space['0.5']}; & div:last-of-type { - color: ${theme.colors.textTertiary}; + color: ${theme.colors.grey}; font-size: ${theme.fontSizes.small}; } `, @@ -123,7 +123,7 @@ const ButtonWrapper = styled.div( const LeftText = styled(Typography)( ({ theme }) => css` - color: ${theme.colors.textTertiary}; + color: ${theme.colors.grey}; `, ) diff --git a/src/components/pages/profile/ProfileButton.test.tsx b/src/components/pages/profile/ProfileButton.test.tsx index 393fea0a6..131cbf3fc 100644 --- a/src/components/pages/profile/ProfileButton.test.tsx +++ b/src/components/pages/profile/ProfileButton.test.tsx @@ -46,11 +46,11 @@ const mockUseCoinChain = mockFunction(useCoinChain) mockUseCoinChain.mockImplementation(({ coinName }) => { if (coinName !== 'eth') { return { - data: null + data: null, } } return { - data: { + data: { id: 1, name: 'Ethereum', blockExplorers: { @@ -60,7 +60,7 @@ mockUseCoinChain.mockImplementation(({ coinName }) => { apiUrl: 'https://api.etherscan.io/api', }, }, - }, + }, } }) diff --git a/src/components/pages/profile/ProfileButton.tsx b/src/components/pages/profile/ProfileButton.tsx index 5cac0e0b0..b30e5373d 100644 --- a/src/components/pages/profile/ProfileButton.tsx +++ b/src/components/pages/profile/ProfileButton.tsx @@ -66,12 +66,12 @@ export const SocialProfileButton = ({ tooltipContent={} > ( - } + )} size={breakpoints.sm ? 'large' : 'small'} inline data-testid={`social-profile-button-${iconKey}`} @@ -104,19 +104,19 @@ export const AddressProfileButton = ({ const items = [ iconKey === 'eth' ? { - icon: , + icon: UpRightArrowSVG, label: 'View address', href: getDestination(`/${address}`) as string, } : undefined, { - icon: , + icon: CopySVG, label: 'Copy address', onClick: () => copy(address), }, defaultBlockExplorer ? { - icon: , + icon: UpRightArrowSVG, label: `View on ${defaultBlockExplorer?.name}`, href: `${defaultBlockExplorer?.url}/address/${address}`, } @@ -128,7 +128,7 @@ export const AddressProfileButton = ({ } + icon={() => } value={address} size={breakpoints.sm ? 'large' : 'small'} inline @@ -324,14 +324,14 @@ export const OwnerProfileButton = ({ const items = [ link ? { - icon: , + icon: UpRightArrowSVG, label: 'View profile', href: link, } : undefined, primary.data?.name ? { - icon: , + icon: CopySVG, label: 'Copy name', onClick: () => copy(primary.data?.name!), } @@ -339,17 +339,17 @@ export const OwnerProfileButton = ({ ...(dataType === 'address' ? ([ { - icon: , + icon: UpRightArrowSVG, label: 'View address', href: getDestination(`/${addressOrNameOrDate}`) as string, }, { - icon: , + icon: CopySVG, label: 'Copy address', onClick: () => copy(addressOrNameOrDate), }, { - icon: , + icon: UpRightArrowSVG, label: 'View on Etherscan', href: makeEtherscanLink(addressOrNameOrDate, 'mainnet', 'address'), }, @@ -407,7 +407,7 @@ export const VerificationProfileButton = ({ tooltipContent={} > } + icon={() => } size={breakpoints.sm ? 'large' : 'small'} inline data-testid={`verification-profile-button-${iconKey}`} diff --git a/src/components/pages/profile/ProfileDetails.test.tsx b/src/components/pages/profile/ProfileDetails.test.tsx index 0b96fd8bd..6fdc40f41 100644 --- a/src/components/pages/profile/ProfileDetails.test.tsx +++ b/src/components/pages/profile/ProfileDetails.test.tsx @@ -117,7 +117,14 @@ describe('ProfileDetails', () => { name="test.eth" expiryDate={undefined} accountRecords={[]} - otherRecords={[{ iconKey: 'contenthash', key: 'contenthash', value: 'ipfs://QmXoypizjW3WknFiJnKLwHCnL72vedxjQkDDP1mXWo6uco', type: 'contenthash' }]} + otherRecords={[ + { + iconKey: 'contenthash', + key: 'contenthash', + value: 'ipfs://QmXoypizjW3WknFiJnKLwHCnL72vedxjQkDDP1mXWo6uco', + type: 'contenthash', + }, + ]} addresses={[]} pccExpired={false} owners={[]} diff --git a/src/components/pages/profile/ProfileDetails.tsx b/src/components/pages/profile/ProfileDetails.tsx index ba1206c73..748162507 100644 --- a/src/components/pages/profile/ProfileDetails.tsx +++ b/src/components/pages/profile/ProfileDetails.tsx @@ -1,7 +1,7 @@ import { useTranslation } from 'react-i18next' import styled, { css } from 'styled-components' -import { Button, Helper, mq, RightArrowSVG, Typography } from '@ensdomains/thorin' +import { Button, Helper, RightArrowSVG, Typography } from '@ensdomains/thorin' import { CacheableComponent } from '@app/components/@atoms/CacheableComponent' import { DisabledButtonWithTooltip } from '@app/components/@molecules/DisabledButtonWithTooltip' @@ -114,24 +114,24 @@ const RecordsStack = styled.div( gap: ${theme.space['4']}; padding: ${theme.space['4']}; - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { padding: ${theme.space['6']}; - `)} + } `, ) -const ActionsContainer = styled.div(({ theme }) => [ - css` +const ActionsContainer = styled.div( + ({ theme }) => css` border-top: ${theme.space.px} solid ${theme.colors.border}; padding: ${theme.space['4']}; display: flex; flex-direction: column; gap: ${theme.space['4']}; + @media (min-width: ${theme.breakpoints.sm}px) { + padding: ${theme.space['4']} ${theme.space['6']}; + } `, - mq.sm.min(css` - padding: ${theme.space['4']} ${theme.space['6']}; - `), -]) +) const Actions = styled.div( ({ theme }) => css` @@ -141,7 +141,7 @@ const Actions = styled.div( flex-flow: row wrap; gap: ${theme.space['2']}; - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { & > .leading { flex-grow: 1; order: -1; @@ -152,33 +152,33 @@ const Actions = styled.div( width: min-content; } } - `)} + } `, ) const ActionWrapper = styled.div<{ leading?: boolean fullMobileWidth?: boolean -}>(({ leading, fullMobileWidth }) => [ - css` +}>( + ({ leading, fullMobileWidth, theme }) => css` ${fullMobileWidth && css` width: 100%; `} + @media (min-width: ${theme.breakpoints.sm}px) { + width: initial; + ${leading && + css` + flex-grow: 1; + order: -1; + & > div, + button { + width: min-content; + } + `} + } `, - mq.sm.min(css` - width: initial; - ${leading && - css` - flex-grow: 1; - order: -1; - & > div, - button { - width: min-content; - } - `} - `), -]) +) type Action = NonNullable['profileActions']>[number] const getAction = (action: Action, is2LDEth: boolean) => { diff --git a/src/components/pages/profile/[name]/Profile.tsx b/src/components/pages/profile/[name]/Profile.tsx index 5f67940be..12438dd90 100644 --- a/src/components/pages/profile/[name]/Profile.tsx +++ b/src/components/pages/profile/[name]/Profile.tsx @@ -89,7 +89,7 @@ export const NameAvailableBanner = ({ } + icon={CheckCircleSVG} title={t('banner.available.title', { name: normalisedName })} > [ - css` +const StyledInnerDialog = styled(InnerDialog)( + ({ theme }) => css` height: 85vh; max-height: 85vh; margin: -${theme.space['4']}; @@ -70,17 +70,17 @@ const StyledInnerDialog = styled(InnerDialog)(({ theme }) => [ overflow: hidden; border-top-left-radius: ${theme.radii['3xLarge']}; border-top-right-radius: ${theme.radii['3xLarge']}; + @media (min-width: ${theme.breakpoints.sm}px) { + height: 90vh; + max-height: 720px; + width: calc(80vw - 2 * ${theme.space['6']}); + max-width: ${theme.space['128']}; + margin: -${theme.space['6']}; + border-bottom-left-radius: ${theme.radii['3xLarge']}; + border-bottom-right-radius: ${theme.radii['3xLarge']}; + } `, - mq.sm.min(css` - height: 90vh; - max-height: 720px; - width: calc(80vw - 2 * ${theme.space['6']}); - max-width: ${theme.space['128']}; - margin: -${theme.space['6']}; - border-bottom-left-radius: ${theme.radii['3xLarge']}; - border-bottom-right-radius: ${theme.radii['3xLarge']}; - `), -]) +) const MoonPayHeader = styled.div( ({ theme }) => css` @@ -297,7 +297,7 @@ const Registration = ({ nameDetails, isLoading }: Props) => { ), trailing: match([labelTooLong, step]) - .with([true, P._], () => {t('error.nameTooLong')}) + .with([true, P._], () => {t('error.nameTooLong')}) .with([false, 'pricing'], () => ( ( justify-content: space-between; gap: ${theme.space['1']}; line-height: ${theme.space['5']}; - color: ${$color ? theme.colors[$color] : theme.colors.textTertiary}; + color: ${$color ? theme.colors[$color] : theme.colors.grey}; &:not(:last-of-type) { padding-bottom: ${theme.space['4']}; border-bottom: 1px solid #e8e8e8; } - ${mq.sm.max(css` + @media (max-width: ${theme.breakpoints.sm}px) { &:not(:last-of-type) { border-bottom: none; - padding-bottom: 0px; + padding-bottom: 0; } &:first-of-type { @@ -64,7 +64,7 @@ const LineItem = styled.div<{ $color?: Colors }>( padding-top: ${theme.space['4']}; border-top: 1px solid #e8e8e8; } - `)} + } `, ) @@ -90,7 +90,7 @@ export const Invoice = ({ name, expiryTitle, expiryDate, items }: Props) => { {items.map(({ label, value, bufferPercentage }, inx) => ( - + {label} @@ -99,7 +99,7 @@ export const Invoice = ({ name, expiryTitle, expiryDate, items }: Props) => { @@ -109,7 +109,7 @@ export const Invoice = ({ name, expiryTitle, expiryDate, items }: Props) => { ))} - + {expiryTitle} diff --git a/src/components/pages/profile/[name]/registration/steps/Pricing/Pricing.tsx b/src/components/pages/profile/[name]/registration/steps/Pricing/Pricing.tsx index 2ca36cfad..d675ac1c2 100644 --- a/src/components/pages/profile/[name]/registration/steps/Pricing/Pricing.tsx +++ b/src/components/pages/profile/[name]/registration/steps/Pricing/Pricing.tsx @@ -13,7 +13,6 @@ import { Field, Heading, Helper, - mq, RadioButton, RadioButtonGroup, Toggle, @@ -52,10 +51,10 @@ const StyledCard = styled(Card)( gap: ${theme.space['4']}; padding: ${theme.space['4']}; - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { padding: ${theme.space['6']} ${theme.space['18']}; gap: ${theme.space['6']}; - `)} + } `, ) @@ -71,9 +70,9 @@ const OutlinedContainer = styled.div( border-radius: ${theme.radii.large}; background: ${theme.colors.backgroundSecondary}; - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { grid-template-areas: 'title checkbox' 'description checkbox'; - `)} + } `, ) @@ -144,10 +143,10 @@ const InfoItems = styled.div( justify-content: flex-start; gap: ${theme.space['4']}; - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { flex-direction: row; align-items: stretch; - `)} + } `, ) @@ -282,7 +281,7 @@ const PaymentChoice = ({ return ( - + {t('steps.info.paymentMethod')} @@ -302,7 +301,7 @@ const PaymentChoice = ({ {paymentMethodChoice === PaymentMethod.ethereum && !hasEnoughEth && ( <> - + {t('steps.info.notEnoughEth')} @@ -331,7 +330,7 @@ const PaymentChoice = ({ label={ {t('steps.info.creditOrDebit')} - + ({t('steps.info.additionalFee')}) @@ -353,7 +352,7 @@ const PaymentChoice = ({ {hasFailedMoonpayTransaction && ( - {t('steps.info.failedMoonpayTransaction')} + {t('steps.info.failedMoonpayTransaction')} )} diff --git a/src/components/pages/profile/[name]/registration/steps/Pricing/TemporaryPremium.tsx b/src/components/pages/profile/[name]/registration/steps/Pricing/TemporaryPremium.tsx index 73b69bd43..aec7333a5 100644 --- a/src/components/pages/profile/[name]/registration/steps/Pricing/TemporaryPremium.tsx +++ b/src/components/pages/profile/[name]/registration/steps/Pricing/TemporaryPremium.tsx @@ -12,7 +12,7 @@ import { import { useTranslation } from 'react-i18next' import styled, { css, DefaultTheme } from 'styled-components' -import { Button, Dropdown, Helper, Input, mq, Typography } from '@ensdomains/thorin' +import { Button, Dropdown, Helper, Input, Typography } from '@ensdomains/thorin' import CalendarSVG from '@app/assets/Calendar.svg' import MobileFullWidth from '@app/components/@atoms/MobileFullWidth' @@ -224,23 +224,23 @@ const InputContainer = styled.div( margin-bottom: -${theme.space['2']}; width: 100%; - ${mq.md.min(css` + @media (min-width: 768px) { flex-direction: row; - `)} + } `, ) -const inputStyle = ({ theme }: { theme: DefaultTheme }) => css` - background-color: ${theme.colors.background}; - border-radius: ${theme.radii.large}; - border-color: ${theme.colors.background}; - height: ${theme.space['11']}; -` +// const inputStyle = ({ theme }: { theme: DefaultTheme }) => css` +// background-color: ${theme.colors.background}; +// border-radius: ${theme.radii.large}; +// border-color: ${theme.colors.background}; +// height: ${theme.space['11']}; +// ` const TimezoneText = styled(Typography)( ({ theme }) => css` margin-top: -${theme.space['2']}; - color: ${theme.colors.textTertiary}; + color: ${theme.colors.grey}; `, ) @@ -553,7 +553,6 @@ const TemporaryPremium = ({ startDate, name }: Props) => { prefix="$" size="medium" clearable={false} - parentStyles={inputStyle as any} /> { onChange={handleDateInput} clearable={false} type="datetime-local" - parentStyles={inputStyle as any} /> @@ -598,7 +596,7 @@ const TemporaryPremium = ({ startDate, name }: Props) => { color: 'text', }))} > - }> + }> {t('action.remindMe', { ns: 'common' })} diff --git a/src/components/pages/profile/[name]/registration/steps/Profile/AddProfileRecordView.test.tsx b/src/components/pages/profile/[name]/registration/steps/Profile/AddProfileRecordView.test.tsx index 8311a3387..320b569d8 100644 --- a/src/components/pages/profile/[name]/registration/steps/Profile/AddProfileRecordView.test.tsx +++ b/src/components/pages/profile/[name]/registration/steps/Profile/AddProfileRecordView.test.tsx @@ -72,7 +72,7 @@ describe('AddProfileRecordView', () => { render() await userEvent.click(screen.getByTestId('profile-record-option-ipfs')) expect(screen.getByTestId('profile-record-option-ipfs')).toHaveStyle( - 'background-color: ButtonFace', + 'background-color: rgb(238, 245, 255)', ) expect(screen.getByTestId('profile-record-option-skynet')).toBeDisabled() expect(screen.getByTestId('profile-record-option-swarm')).toBeDisabled() diff --git a/src/components/pages/profile/[name]/registration/steps/Profile/AddProfileRecordView.tsx b/src/components/pages/profile/[name]/registration/steps/Profile/AddProfileRecordView.tsx index 08b89c3fe..e05916af0 100644 --- a/src/components/pages/profile/[name]/registration/steps/Profile/AddProfileRecordView.tsx +++ b/src/components/pages/profile/[name]/registration/steps/Profile/AddProfileRecordView.tsx @@ -3,7 +3,7 @@ import { Control, useWatch } from 'react-hook-form' import { useTranslation } from 'react-i18next' import styled, { css } from 'styled-components' -import { Button, Dialog, MagnifyingGlassSimpleSVG, mq, ScrollBox } from '@ensdomains/thorin' +import { Button, Dialog, MagnifyingGlassSimpleSVG, ScrollBox } from '@ensdomains/thorin' import DismissDialogButton from '@app/components/@atoms/DismissDialogButton/DismissDialogButton' import { Spacer } from '@app/components/@atoms/Spacer' @@ -28,10 +28,10 @@ const Content = styled.div( gap: ${theme.space[6]}; overflow: hidden; - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { width: 80vw; max-width: ${theme.space['128']}; - `)} + } `, ) diff --git a/src/components/pages/profile/[name]/registration/steps/Profile/CustomProfileRecordInput.tsx b/src/components/pages/profile/[name]/registration/steps/Profile/CustomProfileRecordInput.tsx index 799a1afb4..5075e49a5 100644 --- a/src/components/pages/profile/[name]/registration/steps/Profile/CustomProfileRecordInput.tsx +++ b/src/components/pages/profile/[name]/registration/steps/Profile/CustomProfileRecordInput.tsx @@ -1,8 +1,8 @@ import { UseFormRegister, UseFormTrigger } from 'react-hook-form' import { useTranslation } from 'react-i18next' -import styled, { css, useTheme } from 'styled-components' +import styled, { css } from 'styled-components' -import { CrossSVG, Input, mq } from '@ensdomains/thorin' +import { CrossSVG, Input } from '@ensdomains/thorin' import { ProfileEditorForm } from '@app/hooks/useProfileEditorForm' @@ -15,37 +15,37 @@ const Container = styled.div( `, ) -const InnerResponsiveContainer = styled.div(({ theme }) => [ - css` +const InnerResponsiveContainer = styled.div( + ({ theme }) => css` display: flex; flex-direction: column; gap: ${theme.space[2]}; + @media (min-width: ${theme.breakpoints.sm}px) { + flex-direction: row; + } `, - mq.sm.min(css` - flex-direction: row; - `), -]) +) -const LabelWrapper = styled.div(() => [ - css` +const LabelWrapper = styled.div( + ({ theme }) => css` width: 100%; + @media (min-width: ${theme.breakpoints.sm}px) { + flex: 0 0 25%; + } `, - mq.sm.min(css` - flex: 0 0 25%; - `), -]) +) -const ValueWrapper = styled.div(() => [ - css` +const ValueWrapper = styled.div( + ({ theme }) => css` width: 100%; + @media (min-width: ${theme.breakpoints.sm}px) { + flex: 1; + } `, - mq.sm.min(css` - flex: 1; - `), -]) +) -const ButtonContainer = styled.div(({ theme }) => [ - css` +const ButtonContainer = styled.div( + ({ theme }) => css` width: ${theme.space['11']}; margin-right: -${theme.space['1']}; display: flex; @@ -53,11 +53,11 @@ const ButtonContainer = styled.div(({ theme }) => [ justify-content: flex-start; padding-top: calc(${theme.space['8']} + ${theme.space['12']} + ${theme.space['2']}); margin-top: -1px; + @media (min-width: ${theme.breakpoints.sm}px) { + padding-top: ${theme.space['8']}; + } `, - mq.sm.min(css` - padding-top: ${theme.space['8']}; - `), -]) +) const DeleteButton = styled.button( ({ theme }) => css` @@ -112,7 +112,6 @@ export const CustomProfileRecordInput = ({ error, onDelete, }: Props) => { - const theme = useTheme() const { t } = useTranslation('register') return ( @@ -123,9 +122,6 @@ export const CustomProfileRecordInput = ({ label="" hideLabel error={!!error} - parentStyles={css` - height: ${theme.space[12]}; - `} placeholder={t('steps.profile.options.groups.custom.key')} {...register(`records.${index}.key`, { required: t('steps.profile.errors.labelRequired'), diff --git a/src/components/pages/profile/[name]/registration/steps/Profile/Field.tsx b/src/components/pages/profile/[name]/registration/steps/Profile/Field.tsx index 580fe30b6..8c4b75939 100644 --- a/src/components/pages/profile/[name]/registration/steps/Profile/Field.tsx +++ b/src/components/pages/profile/[name]/registration/steps/Profile/Field.tsx @@ -22,7 +22,7 @@ const LabelsContainer = styled.div( const Label = styled.div( ({ theme }) => css` - color: ${theme.colors.textTertiary}; + color: ${theme.colors.grey}; font-weight: ${theme.fontWeights.bold}; line-height: ${theme.space['5']}; `, @@ -30,7 +30,7 @@ const Label = styled.div( const SecondaryLabel = styled.div( ({ theme }) => css` - color: ${theme.colors.textTertiary}; + color: ${theme.colors.grey}; font-size: ${theme.space['3']}; `, ) diff --git a/src/components/pages/profile/[name]/registration/steps/Profile/Profile.tsx b/src/components/pages/profile/[name]/registration/steps/Profile/Profile.tsx index bbabfbad7..89d078eff 100644 --- a/src/components/pages/profile/[name]/registration/steps/Profile/Profile.tsx +++ b/src/components/pages/profile/[name]/registration/steps/Profile/Profile.tsx @@ -6,7 +6,7 @@ import styled, { css } from 'styled-components' import { match } from 'ts-pattern' import { useAccount } from 'wagmi' -import { Button, Dialog, mq, PlusSVG, Typography } from '@ensdomains/thorin' +import { Button, Dialog, PlusSVG, Typography } from '@ensdomains/thorin' import { ConfirmationDialogView } from '@app/components/@molecules/ConfirmationDialogView/ConfirmationDialogView' import { AvatarClickType } from '@app/components/@molecules/ProfileEditor/Avatar/AvatarButton' @@ -40,11 +40,12 @@ const StyledCard = styled.form(({ theme }) => [ align-items: center; justify-content: center; gap: ${theme.space['4']}; + + @media (min-width: ${theme.breakpoints.sm}px) { + padding: ${theme.space['6']}; + gap: ${theme.space['6']}; + } `, - mq.sm.min(css` - padding: ${theme.space['6']}; - gap: ${theme.space['6']}; - `), ]) const CenterAlignedTypography = styled(Typography)( @@ -64,10 +65,10 @@ const Divider = styled.div( const ButtonWrapper = styled.div(({ theme }) => [ css` width: ${theme.space.full}; + @media (min-width: 360px) { + width: initial; + } `, - mq.xs.min(css` - width: initial; - `), ]) const SubmitButton = ({ @@ -320,7 +321,7 @@ const Profile = ({ name, callback, registrationData, resolverExists }: Props) => size="medium" onClick={handleShowAddRecordModal} data-testid="show-add-profile-records-modal-button" - prefix={} + prefix={PlusSVG} > {t('steps.profile.addMore')} diff --git a/src/components/pages/profile/[name]/registration/steps/Profile/ProfileRecordInput.tsx b/src/components/pages/profile/[name]/registration/steps/Profile/ProfileRecordInput.tsx index 75803659e..d0f50e296 100644 --- a/src/components/pages/profile/[name]/registration/steps/Profile/ProfileRecordInput.tsx +++ b/src/components/pages/profile/[name]/registration/steps/Profile/ProfileRecordInput.tsx @@ -1,5 +1,5 @@ import { ComponentProps, FocusEvent, forwardRef, ReactNode, Ref, RefObject, useMemo } from 'react' -import styled, { css, useTheme } from 'styled-components' +import styled, { css } from 'styled-components' import { CrossSVG, Input } from '@ensdomains/thorin' @@ -125,8 +125,6 @@ export const ProfileRecordInput = forwardRef( }: Props, ref: Ref, ) => { - const theme = useTheme() - const prefix = useMemo(() => { if (!group) return null if (['address', 'website', 'social'].includes(group)) @@ -155,9 +153,6 @@ export const ProfileRecordInput = forwardRef( placeholder={placeholder} data-testid={`profile-record-input-input-${recordKey}`} validated={validated} - parentStyles={css` - height: ${theme.space['12']}; - `} iconWidth="5.5" disabled={disabled} onFocus={onFocus} diff --git a/src/components/pages/profile/[name]/registration/steps/Transactions.tsx b/src/components/pages/profile/[name]/registration/steps/Transactions.tsx index a02e00894..47b5b7753 100644 --- a/src/components/pages/profile/[name]/registration/steps/Transactions.tsx +++ b/src/components/pages/profile/[name]/registration/steps/Transactions.tsx @@ -5,7 +5,7 @@ import { match, P } from 'ts-pattern' import { useAccount } from 'wagmi' import { makeCommitment } from '@ensdomains/ensjs/utils' -import { Button, CountdownCircle, Dialog, Heading, mq, Spinner } from '@ensdomains/thorin' +import { Button, CountdownCircle, Dialog, Heading, Spinner } from '@ensdomains/thorin' import MobileFullWidth from '@app/components/@atoms/MobileFullWidth' import { StatusDots } from '@app/components/@atoms/StatusDots/StatusDots' @@ -88,10 +88,10 @@ const StyledCard = styled(Card)( gap: ${theme.space['4']}; padding: ${theme.space['4']}; - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { padding: ${theme.space['6']} ${theme.space['18']}; gap: ${theme.space['6']}; - `)} + } `, ) @@ -490,7 +490,11 @@ const Transactions = ({ registrationData, name, callback, onStart }: Props) => { <> {ResetBackButton} - }> + } + > {t('steps.transactions.wait')} diff --git a/src/components/pages/profile/[name]/tabs/MoreTab/Miscellaneous/EarnifiDialog.test.tsx b/src/components/pages/profile/[name]/tabs/MoreTab/Miscellaneous/EarnifiDialog.test.tsx index 859e58275..54bc69ee7 100644 --- a/src/components/pages/profile/[name]/tabs/MoreTab/Miscellaneous/EarnifiDialog.test.tsx +++ b/src/components/pages/profile/[name]/tabs/MoreTab/Miscellaneous/EarnifiDialog.test.tsx @@ -2,9 +2,9 @@ import { render, screen, userEvent, waitFor } from '@app/test-utils' import { beforeEach, describe, expect, it, Mock, vi } from 'vitest' +import { makeMockIntersectionObserver } from '../../../../../../../../test/mock/makeMockIntersectionObserver' import { EarnifiDialog } from './EarnifiDialog' import { useSubscribeToEarnifi } from './useSubscribeToEarnifi' -import { makeMockIntersectionObserver } from '../../../../../../../../test/mock/makeMockIntersectionObserver' vi.mock('./useSubscribeToEarnifi', () => ({ useSubscribeToEarnifi: vi.fn(), diff --git a/src/components/pages/profile/[name]/tabs/MoreTab/Miscellaneous/components/DateLayout.tsx b/src/components/pages/profile/[name]/tabs/MoreTab/Miscellaneous/components/DateLayout.tsx index d78ab23e2..1ac5a9338 100644 --- a/src/components/pages/profile/[name]/tabs/MoreTab/Miscellaneous/components/DateLayout.tsx +++ b/src/components/pages/profile/[name]/tabs/MoreTab/Miscellaneous/components/DateLayout.tsx @@ -10,7 +10,7 @@ export const DateLayout = styled.div( justify-content: center; & > div:first-of-type { - color: ${theme.colors.textTertiary}; + color: ${theme.colors.grey}; margin-bottom: ${theme.space['2']}; font-weight: ${theme.fontWeights.bold}; } @@ -21,7 +21,7 @@ export const DateLayout = styled.div( } & > div:nth-of-type(3) { - color: ${theme.colors.textTertiary}; + color: ${theme.colors.grey}; font-weight: ${theme.fontWeights.normal}; font-size: ${theme.fontSizes.small}; } diff --git a/src/components/pages/profile/[name]/tabs/MoreTab/NameWrapper.tsx b/src/components/pages/profile/[name]/tabs/MoreTab/NameWrapper.tsx index cdc89595f..ede638306 100644 --- a/src/components/pages/profile/[name]/tabs/MoreTab/NameWrapper.tsx +++ b/src/components/pages/profile/[name]/tabs/MoreTab/NameWrapper.tsx @@ -4,7 +4,7 @@ import { match, P } from 'ts-pattern' import { Address } from 'viem' import { GetOwnerReturnType, GetWrapperDataReturnType } from '@ensdomains/ensjs/public' -import { AlertSVG, CheckSVG, LockSVG, mq, Typography } from '@ensdomains/thorin' +import { AlertSVG, CheckSVG, LockSVG, Typography } from '@ensdomains/thorin' import { cacheableComponentStyles } from '@app/components/@atoms/CacheableComponent' import { DisabledButtonWithTooltip } from '@app/components/@molecules/DisabledButtonWithTooltip' @@ -38,9 +38,9 @@ const Container = styled(TabWrapper)( padding: ${theme.space['4']}; - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { padding: ${theme.space['6']}; - `)} + } `, ) @@ -59,6 +59,7 @@ const Record = styled.div( background: ${theme.colors.greenSurface}; border-radius: ${theme.radii.input}; width: ${theme.space.full}; + color: ${theme.colors.text}; font-weight: ${theme.fontWeights.bold}; display: flex; flex-direction: row; @@ -161,19 +162,21 @@ export const NameWrapper = ({ {t('tabs.more.token.status.wrapped')} {status === 'locked' ? ( - + ) : ( - + )} {isPCC ? ( <> - {t('tabs.more.token.pcc.not-controllable')} + {t('tabs.more.token.pcc.not-controllable')}{' '} + > ) : ( <> - {t('tabs.more.token.pcc.controllable')} + {t('tabs.more.token.pcc.controllable')}{' '} + > )} diff --git a/src/components/pages/profile/[name]/tabs/MoreTab/Ownership.tsx b/src/components/pages/profile/[name]/tabs/MoreTab/Ownership.tsx index ff1f8c2c0..a82d8d362 100644 --- a/src/components/pages/profile/[name]/tabs/MoreTab/Ownership.tsx +++ b/src/components/pages/profile/[name]/tabs/MoreTab/Ownership.tsx @@ -5,7 +5,7 @@ import styled, { css } from 'styled-components' import { useAccount } from 'wagmi' import { GetDnsOwnerReturnType } from '@ensdomains/ensjs/dns' -import { Button, Helper, mq, Tag, Typography } from '@ensdomains/thorin' +import { Button, Helper, Tag, Typography } from '@ensdomains/thorin' import AeroplaneSVG from '@app/assets/Aeroplane.svg' import { BaseLinkWithHistory } from '@app/components/@atoms/BaseLink' @@ -57,9 +57,9 @@ const HeadingContainer = styled.div( font-weight: ${theme.fontWeights.bold}; font-size: ${theme.fontSizes.headingFour}; - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { padding: ${theme.space['6']}; - `)} + } `, ) @@ -87,9 +87,9 @@ const OwnerContainer = styled.div( background-color: ${theme.colors.backgroundSecondary}; } - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { padding: ${theme.space['4']} ${theme.space['6']}; - `)} + } `, ) @@ -111,7 +111,7 @@ const TextContainer = styled.div( & > div:last-of-type { font-size: ${theme.fontSizes.small}; - color: ${theme.colors.textTertiary}; + color: ${theme.colors.grey}; } `, ) @@ -166,9 +166,9 @@ const DNSOwnerSectionContainer = styled.div( gap: ${theme.space['4']}; padding: ${theme.space['4']}; - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { padding: ${theme.space['6']}; - `)} + } `, ) @@ -262,7 +262,7 @@ const DNSOwnerSection = ({ return ( - + {t(`tabs.more.ownership.dnsOwnerWarning.${canSend ? 'isManager' : 'isDnsOwner'}`)} @@ -317,7 +317,7 @@ const Ownership = ({ {canSend && ( } + prefix={() => } onClick={handleSend} data-testid="send-name-button" > @@ -332,7 +332,7 @@ const Ownership = ({ buttonText: t('action.send', { ns: 'common' }), mobileWidth: 150, mobileButtonWidth: 'initial', - prefix: , + prefix: () => , }} /> )} diff --git a/src/components/pages/profile/[name]/tabs/MoreTab/Resolver.tsx b/src/components/pages/profile/[name]/tabs/MoreTab/Resolver.tsx index 881950839..e497de739 100644 --- a/src/components/pages/profile/[name]/tabs/MoreTab/Resolver.tsx +++ b/src/components/pages/profile/[name]/tabs/MoreTab/Resolver.tsx @@ -2,7 +2,7 @@ import { useTranslation } from 'react-i18next' import styled, { css } from 'styled-components' import { match, P } from 'ts-pattern' -import { Button, mq, Typography } from '@ensdomains/thorin' +import { Button, Typography } from '@ensdomains/thorin' import { cacheableComponentStyles } from '@app/components/@atoms/CacheableComponent' import { DisabledButtonWithTooltip } from '@app/components/@molecules/DisabledButtonWithTooltip' @@ -27,9 +27,9 @@ const Container = styled(TabWrapper)( padding: ${theme.space['4']}; - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { padding: ${theme.space['6']}; - `)} + } `, ) @@ -70,9 +70,9 @@ const ButtonStack = styled.div( justify-content: flex-end; gap: ${theme.space['4']}; - ${mq.md.max(css` + @media (max-width: 640px) { flex-direction: column; - `)} + } `, ) diff --git a/src/components/pages/profile/[name]/tabs/MoreTab/Token/BaseWrapButton.tsx b/src/components/pages/profile/[name]/tabs/MoreTab/Token/BaseWrapButton.tsx index b6afcd266..cd9cc547b 100644 --- a/src/components/pages/profile/[name]/tabs/MoreTab/Token/BaseWrapButton.tsx +++ b/src/components/pages/profile/[name]/tabs/MoreTab/Token/BaseWrapButton.tsx @@ -1,14 +1,14 @@ import { ComponentProps, forwardRef } from 'react' import styled, { css } from 'styled-components' -import { Button, mq } from '@ensdomains/thorin' +import { Button } from '@ensdomains/thorin' const StyledWrapButton = styled(Button)( ({ theme }) => css` width: 100%; - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { max-width: ${theme.space['36']}; - `)} + } `, ) diff --git a/src/components/pages/profile/[name]/tabs/MoreTab/Token/Token.test.tsx b/src/components/pages/profile/[name]/tabs/MoreTab/Token/Token.test.tsx index 814488630..c27b8f313 100644 --- a/src/components/pages/profile/[name]/tabs/MoreTab/Token/Token.test.tsx +++ b/src/components/pages/profile/[name]/tabs/MoreTab/Token/Token.test.tsx @@ -1,5 +1,6 @@ import { mockFunction, render, screen } from '@app/test-utils' +import { makeMockUseWrapperDataData } from '@root/test/mock/makeMockUseWrapperDataData.ts' import { labelhash, namehash } from 'viem' import { describe, expect, it, vi } from 'vitest' @@ -8,7 +9,6 @@ import { useContractAddress } from '@app/hooks/chain/useContractAddress' import { useParentBasicName } from '@app/hooks/useParentBasicName' import { useBreakpoint } from '@app/utils/BreakpointProvider' -import { makeMockUseWrapperDataData } from '@root/test/mock/makeMockUseWrapperDataData.ts' import Token from './Token' vi.mock('@app/hooks/useParentBasicName') diff --git a/src/components/pages/profile/[name]/tabs/MoreTab/Token/Token.tsx b/src/components/pages/profile/[name]/tabs/MoreTab/Token/Token.tsx index 95d72bf51..e60d2dd32 100644 --- a/src/components/pages/profile/[name]/tabs/MoreTab/Token/Token.tsx +++ b/src/components/pages/profile/[name]/tabs/MoreTab/Token/Token.tsx @@ -2,7 +2,7 @@ import { useTranslation } from 'react-i18next' import styled, { css } from 'styled-components' import { labelhash, namehash } from 'viem' -import { mq, Tag, Typography } from '@ensdomains/thorin' +import { Tag, Typography } from '@ensdomains/thorin' import { CacheableComponent } from '@app/components/@atoms/CacheableComponent' import { NFTWithPlaceholder } from '@app/components/NFTWithPlaceholder' @@ -36,7 +36,7 @@ const Container = styled(TabWrapper)( border-bottom: none; } - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { & > div { padding: ${theme.space['4']} ${theme.space['6']}; } @@ -44,7 +44,7 @@ const Container = styled(TabWrapper)( & > div:first-of-type { padding: ${theme.space['6']}; } - `)} + } `, ) @@ -69,10 +69,9 @@ const IdsContainer = styled.div( align-items: stretch; justify-content: center; gap: ${theme.space['4']}; - - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { gap: ${theme.space['2']}; - `)} + } `, ) @@ -86,9 +85,9 @@ const ItemsContainer = styled(CacheableComponent)( overflow: hidden; - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { flex-direction: row; - `)} + } `, ) @@ -97,10 +96,10 @@ const NftBox = styled(NFTWithPlaceholder)( max-width: 100%; aspect-ratio: 1; - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { max-width: ${theme.space['36']}; max-height: ${theme.space['36']}; - `)} + } `, ) diff --git a/src/components/pages/profile/[name]/tabs/MoreTab/Token/WrapButton.test.tsx b/src/components/pages/profile/[name]/tabs/MoreTab/Token/WrapButton.test.tsx index f6577caed..dfbf0359b 100644 --- a/src/components/pages/profile/[name]/tabs/MoreTab/Token/WrapButton.test.tsx +++ b/src/components/pages/profile/[name]/tabs/MoreTab/Token/WrapButton.test.tsx @@ -79,7 +79,10 @@ describe('WrapButton', () => { name="test123.eth" canBeWrapped={false} ownerData={{ owner: '0x123' } as any} - profile={{ resolverAddress: '0x456' } as any} isManager={false} isRegistrant={false} />, + profile={{ resolverAddress: '0x456' } as any} + isManager={false} + isRegistrant={false} + />, ) expect(screen.queryByTestId('wrap-name-btn')).toBeNull() }) @@ -90,7 +93,10 @@ describe('WrapButton', () => { name="test123.eth" canBeWrapped ownerData={{ owner: '0x123' } as any} - profile={{ resolverAddress: '0x456' } as any} isManager={false} isRegistrant={false} />, + profile={{ resolverAddress: '0x456' } as any} + isManager={false} + isRegistrant={false} + />, ) screen.getByTestId('wrap-name-btn').click() expect(mockCreateTransactionFlow).toHaveBeenCalled() @@ -104,19 +110,24 @@ describe('WrapButton', () => { name="test123.eth" canBeWrapped ownerData={{ owner: '0x123' } as any} - profile={{ - resolverAddress: '0x456', - records: { - coinTypes: [ - { - key: 'coin1', - }, - { - key: 'coin2', - }, - ], - }, - } as any} isManager={true} isRegistrant={false} />, + profile={ + { + resolverAddress: '0x456', + records: { + coinTypes: [ + { + key: 'coin1', + }, + { + key: 'coin2', + }, + ], + }, + } as any + } + isManager={true} + isRegistrant={false} + />, ) screen.getByTestId('wrap-name-btn').click() const args = mockCreateTransactionFlow.mock.lastCall! @@ -133,19 +144,24 @@ describe('WrapButton', () => { name="test123.eth" canBeWrapped ownerData={{ owner: '0x123' } as any} - profile={{ - resolverAddress: '0x231b0Ee14048e9dCcD1d247744d114a4EB5E8E63', - records: { - coinTypes: [ - { - key: 'coin1', - }, - { - key: 'coin2', - }, - ], - }, - } as any} isManager={false} isRegistrant={false} />, + profile={ + { + resolverAddress: '0x231b0Ee14048e9dCcD1d247744d114a4EB5E8E63', + records: { + coinTypes: [ + { + key: 'coin1', + }, + { + key: 'coin2', + }, + ], + }, + } as any + } + isManager={false} + isRegistrant={false} + />, ) screen.getByTestId('wrap-name-btn').click() const args = mockCreateTransactionFlow.mock.lastCall! @@ -161,10 +177,15 @@ describe('WrapButton', () => { name="test123.eth" canBeWrapped ownerData={{ owner: '0x123' } as any} - profile={{ - resolverAddress: '0x456', - records: {}, - } as any} isManager={false} isRegistrant={false} />, + profile={ + { + resolverAddress: '0x456', + records: {}, + } as any + } + isManager={false} + isRegistrant={false} + />, ) screen.getByTestId('wrap-name-btn').click() const args = mockCreateTransactionFlow.mock.lastCall! @@ -182,19 +203,24 @@ describe('WrapButton', () => { name="test123.eth" canBeWrapped ownerData={{ ownershipLevel: 'registrar', owner: '0x124', registrant: '0x123' }} - profile={{ - resolverAddress: '0x456', - records: { - coinTypes: [ - { - key: 'coin1', - }, - { - key: 'coin2', - }, - ], - }, - } as any} isManager={false} isRegistrant={true} />, + profile={ + { + resolverAddress: '0x456', + records: { + coinTypes: [ + { + key: 'coin1', + }, + { + key: 'coin2', + }, + ], + }, + } as any + } + isManager={false} + isRegistrant={true} + />, ) screen.getByTestId('wrap-name-btn').click() const args = mockCreateTransactionFlow.mock.lastCall! @@ -211,19 +237,24 @@ describe('WrapButton', () => { name="test123.eth" canBeWrapped ownerData={{ ownershipLevel: 'registrar', owner: '0x124', registrant: '0x123' }} - profile={{ - resolverAddress: '0x231b0Ee14048e9dCcD1d247744d114a4EB5E8E63', - records: { - coinTypes: [ - { - key: 'coin1', - }, - { - key: 'coin2', - }, - ], - }, - } as any} isManager={false} isRegistrant={false} />, + profile={ + { + resolverAddress: '0x231b0Ee14048e9dCcD1d247744d114a4EB5E8E63', + records: { + coinTypes: [ + { + key: 'coin1', + }, + { + key: 'coin2', + }, + ], + }, + } as any + } + isManager={false} + isRegistrant={false} + />, ) screen.getByTestId('wrap-name-btn').click() const args = mockCreateTransactionFlow.mock.lastCall! @@ -244,10 +275,15 @@ describe('WrapButton', () => { name="sub.test123.eth" canBeWrapped ownerData={{ owner: '0x123' } as any} - profile={{ - resolverAddress: '0x456', - records: {}, - } as any} isManager={true} isRegistrant={false} />, + profile={ + { + resolverAddress: '0x456', + records: {}, + } as any + } + isManager={true} + isRegistrant={false} + />, ) screen.getByTestId('wrap-name-btn').click() const args = mockCreateTransactionFlow.mock.lastCall! @@ -268,10 +304,15 @@ describe('WrapButton', () => { name="sub.test123.eth" canBeWrapped ownerData={{ owner: '0x123' } as any} - profile={{ - resolverAddress: '0x456', - records: {}, - } as any} isManager={false} isRegistrant={false} />, + profile={ + { + resolverAddress: '0x456', + records: {}, + } as any + } + isManager={false} + isRegistrant={false} + />, ) screen.getByTestId('wrap-name-btn').click() const args = mockCreateTransactionFlow.mock.lastCall! @@ -290,19 +331,24 @@ describe('WrapButton', () => { name="sub.test123.eth" canBeWrapped ownerData={{ owner: '0x123' } as any} - profile={{ - resolverAddress: '0x456', - records: { - coinTypes: [ - { - key: 'coin1', - }, - { - key: 'coin2', - }, - ], - }, - } as any} isManager={true} isRegistrant={false} />, + profile={ + { + resolverAddress: '0x456', + records: { + coinTypes: [ + { + key: 'coin1', + }, + { + key: 'coin2', + }, + ], + }, + } as any + } + isManager={true} + isRegistrant={false} + />, ) screen.getByTestId('wrap-name-btn').click() const args = mockCreateTransactionFlow.mock.lastCall! @@ -321,7 +367,10 @@ describe('WrapButton', () => { name="test123.eth" canBeWrapped ownerData={{ owner: '0x123' } as any} - profile={{ resolverAddress: '0x456' } as any} isManager={false} isRegistrant={false} />, + profile={{ resolverAddress: '0x456' } as any} + isManager={false} + isRegistrant={false} + />, ) screen.getByTestId('wrap-name-btn').click() expect(mockResumeTransactionFlow).toHaveBeenCalled() @@ -341,7 +390,10 @@ describe('WrapButton', () => { name="[b2fd3233fdc544d81e84c93822934ddd9b599f056b6a7f84f4de29378bf1cb15].test123.eth" canBeWrapped ownerData={{ owner: '0x123' } as any} - profile={{ resolverAddress: '0x456', records: {} } as any} isManager={true} isRegistrant={false} />, + profile={{ resolverAddress: '0x456', records: {} } as any} + isManager={true} + isRegistrant={false} + />, ) screen.getByTestId('wrap-name-btn').click() expect(mockCreateTransactionFlow).not.toHaveBeenCalled() @@ -374,7 +426,10 @@ describe('WrapButton', () => { name="sub.test123.eth" canBeWrapped ownerData={{ owner: '0x123', ownershipLevel: 'registrar', registrant: '0x123' } as any} - profile={{ resolverAddress: '0x456' } as any} isManager={false} isRegistrant={false} />, + profile={{ resolverAddress: '0x456' } as any} + isManager={false} + isRegistrant={false} + />, ) expect( mockUseWrapperApprovedForAll.mock.calls[mockUseWrapperApprovedForAll.mock.calls.length - 1], diff --git a/src/components/pages/profile/[name]/tabs/OwnershipTab/sections/ContractSection/ContractSection.tsx b/src/components/pages/profile/[name]/tabs/OwnershipTab/sections/ContractSection/ContractSection.tsx index 0e29aeca4..f83574e34 100644 --- a/src/components/pages/profile/[name]/tabs/OwnershipTab/sections/ContractSection/ContractSection.tsx +++ b/src/components/pages/profile/[name]/tabs/OwnershipTab/sections/ContractSection/ContractSection.tsx @@ -29,7 +29,7 @@ export const ContractSection = ({ details }: Props) => { {address} - + {t('tabs.ownership.sections.contract.warning')} diff --git a/src/components/pages/profile/[name]/tabs/OwnershipTab/sections/ExpirySection/ExpirySection.tsx b/src/components/pages/profile/[name]/tabs/OwnershipTab/sections/ExpirySection/ExpirySection.tsx index 21b3592d5..36121128d 100644 --- a/src/components/pages/profile/[name]/tabs/OwnershipTab/sections/ExpirySection/ExpirySection.tsx +++ b/src/components/pages/profile/[name]/tabs/OwnershipTab/sections/ExpirySection/ExpirySection.tsx @@ -2,7 +2,7 @@ import { useState } from 'react' import { useTranslation } from 'react-i18next' import styled, { css } from 'styled-components' -import { Button, Card, Dropdown, mq } from '@ensdomains/thorin' +import { Button, Card, Dropdown } from '@ensdomains/thorin' import { cacheableComponentStyles } from '@app/components/@atoms/CacheableComponent' import { useCalendarOptions } from '@app/hooks/useCalendarOptions' @@ -13,18 +13,18 @@ import { ExpiryPanel } from './components/ExpiryPanel' import { useExpiryActions } from './hooks/useExpiryActions' import { useExpiryDetails } from './hooks/useExpiryDetails' -const Header = styled.div(({ theme }) => [ - css` +const Header = styled.div( + ({ theme }) => css` padding: ${theme.space['4']}; border-bottom: 1px solid ${theme.colors.border}; + @media (min-width: ${theme.breakpoints.sm}px) { + padding: ${theme.space['6']}; + } `, - mq.sm.min(css` - padding: ${theme.space['6']}; - `), -]) +) -const PanelsContainer = styled.div(({ theme }) => [ - css` +const PanelsContainer = styled.div( + ({ theme }) => css` display: flex; flex-direction: column; justify-content: space-between; @@ -32,15 +32,15 @@ const PanelsContainer = styled.div(({ theme }) => [ > *:last-child { border-bottom: none; } - `, - mq.lg.min(css` - flex-direction: row; - margin: 0 -${theme.space['4']}; - > *:last-child { - border-right: none; + @media (min-width: ${theme.breakpoints.lg}px) { + flex-direction: row; + margin: 0 -${theme.space['4']}; + > *:last-child { + border-right: none; + } } - `), -]) + `, +) const Footer = styled.div( ({ theme }) => css` @@ -52,25 +52,25 @@ const Footer = styled.div( `, ) -const FooterWrapper = styled.div(({ theme }) => [ - css` +const FooterWrapper = styled.div( + ({ theme }) => css` padding: ${theme.space['4']}; + @media (min-width: ${theme.breakpoints.sm}px) { + padding: ${theme.space['4']} ${theme.space['6']} ${theme.space['6']}; + } `, - mq.sm.min(css` - padding: ${theme.space['4']} ${theme.space['6']} ${theme.space['6']}; - `), -]) +) -const Container = styled.div(({ theme }) => [ - css` +const Container = styled.div( + ({ theme }) => css` display: flex; flex-direction: column; margin: -${theme.space['4']}; + @media (min-width: ${theme.breakpoints.sm}px) { + margin: -${theme.space['6']}; + } `, - mq.sm.min(css` - margin: -${theme.space['6']}; - `), -]) +) const StyledCard = styled(Card)(cacheableComponentStyles) diff --git a/src/components/pages/profile/[name]/tabs/OwnershipTab/sections/ExpirySection/components/ExpiryPanel.tsx b/src/components/pages/profile/[name]/tabs/OwnershipTab/sections/ExpirySection/components/ExpiryPanel.tsx index 27d7562b2..258b2a0a0 100644 --- a/src/components/pages/profile/[name]/tabs/OwnershipTab/sections/ExpirySection/components/ExpiryPanel.tsx +++ b/src/components/pages/profile/[name]/tabs/OwnershipTab/sections/ExpirySection/components/ExpiryPanel.tsx @@ -1,7 +1,7 @@ import { useTranslation } from 'react-i18next' import styled, { css } from 'styled-components' -import { mq, OutlinkSVG, Typography } from '@ensdomains/thorin' +import { OutlinkSVG, Typography } from '@ensdomains/thorin' import { QuestionTooltip } from '@app/components/@molecules/QuestionTooltip/QuestionTooltip' import { safeDateObj } from '@app/utils/date' @@ -22,12 +22,12 @@ const Container = styled.div(({ theme }) => [ gap: ${theme.space[2]}; border-bottom: 1px solid ${theme.colors.border}; padding: ${theme.space['4']} 0; + @media (min-width: ${theme.breakpoints.lg}px) { + border-bottom: none; + border-right: 1px solid ${theme.colors.border}; + padding: 0 ${theme.space['1']} 0 ${theme.space['4']}; + } `, - mq.lg.min(css` - border-bottom: none; - border-right: 1px solid ${theme.colors.border}; - padding: 0 ${theme.space['1']} 0 ${theme.space['4']}; - `), ]) const Header = styled.div( diff --git a/src/components/pages/profile/[name]/tabs/OwnershipTab/sections/ExpirySection/hooks/useExpiryActions.tsx b/src/components/pages/profile/[name]/tabs/OwnershipTab/sections/ExpirySection/hooks/useExpiryActions.tsx index e18995637..c9314d71b 100644 --- a/src/components/pages/profile/[name]/tabs/OwnershipTab/sections/ExpirySection/hooks/useExpiryActions.tsx +++ b/src/components/pages/profile/[name]/tabs/OwnershipTab/sections/ExpirySection/hooks/useExpiryActions.tsx @@ -47,14 +47,14 @@ export const useExpiryActions = ({ { label: t('action.setReminder'), type: 'set-reminder', - icon: , + icon: CalendarSVG, primary: false, expiryDate, }, { label: t('action.extend'), type: 'extend', - icon: , + icon: FastForwardSVG, primary: true, onClick: () => { showExtendNamesInput(`extend-names-${name}`, { diff --git a/src/components/pages/profile/[name]/tabs/OwnershipTab/sections/RolesSection/RolesSection.tsx b/src/components/pages/profile/[name]/tabs/OwnershipTab/sections/RolesSection/RolesSection.tsx index 5f0d587bc..d1e8c10e4 100644 --- a/src/components/pages/profile/[name]/tabs/OwnershipTab/sections/RolesSection/RolesSection.tsx +++ b/src/components/pages/profile/[name]/tabs/OwnershipTab/sections/RolesSection/RolesSection.tsx @@ -1,7 +1,7 @@ import { useTranslation } from 'react-i18next' import styled, { css } from 'styled-components' -import { Button, Card } from '@ensdomains/thorin' +import { Button, Card, CardDivider } from '@ensdomains/thorin' import { cacheableComponentStyles } from '@app/components/@atoms/CacheableComponent' import { PseudoActionButton } from '@app/components/@atoms/PseudoActionButton/PseudoActionButton' @@ -39,7 +39,7 @@ export const RolesSection = ({ name, roles, details }: Props) => { return ( !!address).length || 0} /> - + {roles?.map((role) => ( window.open(makeEtherscanLink(address!, networkName, 'address'), '_blank'), - icon: , + icon: OutlinkSVG, } }, [primary.data?.name, isWrapped, t, address, networkName]) @@ -93,37 +93,37 @@ export const RoleRow = ({ name, address, roles, actions, isWrapped, isEmancipate const items: DropdownItem[] = [ ...(primary.data?.name - ? ([ + ? [ { label: t('wallet.viewProfile'), onClick: () => router.push(getDestination(`/profile/${primary.data!.name}`) as string), color: 'text', - icon: , + icon: UpRightArrowSVG, }, { label: t('name.copy'), onClick: () => copy(primary.data!.name!), color: 'text', - icon: , + icon: CopySVG, }, - ] as DropdownItem[]) + ] : []), { label: t('address.viewAddress'), onClick: () => router.push(getDestination(`/address/${address}`) as string), color: 'text', - icon: , + icon: UpRightArrowSVG, }, { label: t('address.copyAddress'), onClick: () => copy(address!), color: 'text', - icon: , + icon: CopySVG, }, ...(etherscanAction ? [etherscanAction] : []), ...(editRolesAction ? [editRolesAction] : []), ...(syncManagerAction ? [syncManagerAction] : []), - ] + ] as DropdownItem[] const { isLoading } = primary @@ -146,12 +146,12 @@ export const RoleRow = ({ name, address, roles, actions, isWrapped, isEmancipate colorStyle="accentSecondary" size="small" > - + - + > ) } diff --git a/src/components/pages/profile/[name]/tabs/OwnershipTab/sections/RolesSection/components/RoleTag.tsx b/src/components/pages/profile/[name]/tabs/OwnershipTab/sections/RolesSection/components/RoleTag.tsx index e95b41bb1..e0c6425eb 100644 --- a/src/components/pages/profile/[name]/tabs/OwnershipTab/sections/RolesSection/components/RoleTag.tsx +++ b/src/components/pages/profile/[name]/tabs/OwnershipTab/sections/RolesSection/components/RoleTag.tsx @@ -66,7 +66,7 @@ export const RoleTag = ({ - + {t(`tabs.ownership.tooltips.${_role}`, tOptions)} diff --git a/src/components/pages/profile/[name]/tabs/OwnershipTab/sections/RolesSection/hooks/useRoleActions.tsx b/src/components/pages/profile/[name]/tabs/OwnershipTab/sections/RolesSection/hooks/useRoleActions.tsx index 804434f7c..aae9f143d 100644 --- a/src/components/pages/profile/[name]/tabs/OwnershipTab/sections/RolesSection/hooks/useRoleActions.tsx +++ b/src/components/pages/profile/[name]/tabs/OwnershipTab/sections/RolesSection/hooks/useRoleActions.tsx @@ -4,12 +4,12 @@ import { useTranslation } from 'react-i18next' import { AeroplaneSVG, + AsProp, CounterClockwiseArrowSVG, HorizontalOutwardArrowsSVG, PersonSVG, } from '@ensdomains/thorin' import { DropdownItemObject } from '@ensdomains/thorin/dist/types/components/molecules/Dropdown/Dropdown' -import { ReactNodeNoStrings } from '@ensdomains/thorin/dist/types/types' import { useAbilities } from '@app/hooks/abilities/useAbilities' import { useAccountSafely } from '@app/hooks/account/useAccountSafely' @@ -23,7 +23,7 @@ import { useTransactionFlow } from '@app/transaction-flow/TransactionFlowProvide type Action = Omit & { primary?: boolean - icon: ReactNodeNoStrings + icon: AsProp type: string error?: string onClick?: () => void @@ -72,7 +72,7 @@ export const useRoleActions = ({ name, roles, details }: Props) => { showSendDNS ? { type: 'send-dns', - icon: , + icon: AeroplaneSVG, label: t('action.send'), error: canSendError, onClick: () => showSendNameInput(`send-name-${name}`, { name }), @@ -81,7 +81,7 @@ export const useRoleActions = ({ name, roles, details }: Props) => { canRefreshDNS ? { type: 'refresh-dns', - icon: , + icon: CounterClockwiseArrowSVG, label: t('dns.refresh'), onClick: () => queryClient.resetQueries({ exact: true, queryKey: ['getDNSOwner', name] }), @@ -90,7 +90,7 @@ export const useRoleActions = ({ name, roles, details }: Props) => { showSyncManager ? { type: 'sync-manager', - icon: , + icon: HorizontalOutwardArrowsSVG, label: t('transaction.description.syncManager'), onClick: () => showSyncManagerInput(`sync-manager-${name}`, { @@ -101,7 +101,7 @@ export const useRoleActions = ({ name, roles, details }: Props) => { showSendEth ? { type: 'send-name', - icon: , + icon: AeroplaneSVG, label: t('action.send'), error: canSendError, onClick: () => showSendNameInput(`send-name-${name}`, { name }), @@ -110,7 +110,7 @@ export const useRoleActions = ({ name, roles, details }: Props) => { canEditRoles ? { type: 'edit-roles', - icon: , + icon: PersonSVG, label: t('action.editRoles'), primary: true, onClick: () => showEditRolesInput(`edit-roles-${name}`, { name }), diff --git a/src/components/pages/profile/[name]/tabs/PermissionsTab/Section.tsx b/src/components/pages/profile/[name]/tabs/PermissionsTab/Section.tsx index 6c9d8b71c..ceea8663b 100644 --- a/src/components/pages/profile/[name]/tabs/PermissionsTab/Section.tsx +++ b/src/components/pages/profile/[name]/tabs/PermissionsTab/Section.tsx @@ -110,6 +110,7 @@ const SectionListContainer = styled.div( li { font-size: ${theme.fontSizes.small}; font-weight: ${theme.fontWeights.normal}; + color: ${theme.colors.text}; } li::before { diff --git a/src/components/pages/profile/[name]/tabs/ProfileTab.tsx b/src/components/pages/profile/[name]/tabs/ProfileTab.tsx index 67e98b23f..9090c3b6c 100644 --- a/src/components/pages/profile/[name]/tabs/ProfileTab.tsx +++ b/src/components/pages/profile/[name]/tabs/ProfileTab.tsx @@ -130,7 +130,7 @@ const ProfileTab = ({ nameDetails, name }: Props) => { )} {nameDetails.isNonASCII && ( - + { )} {isWrapped && !normalisedName.endsWith('.eth') && ( - + {t('tabs.profile.warnings.wrappedDNS')} )} diff --git a/src/components/pages/profile/[name]/tabs/RecordsTab.tsx b/src/components/pages/profile/[name]/tabs/RecordsTab.tsx index bc51cfa22..56d1c3071 100644 --- a/src/components/pages/profile/[name]/tabs/RecordsTab.tsx +++ b/src/components/pages/profile/[name]/tabs/RecordsTab.tsx @@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next' import styled, { css } from 'styled-components' import { useChainId } from 'wagmi' -import { Button, mq, Typography } from '@ensdomains/thorin' +import { Button, Typography } from '@ensdomains/thorin' import { cacheableComponentStyles } from '@app/components/@atoms/CacheableComponent' import { DisabledButtonWithTooltip } from '@app/components/@molecules/DisabledButtonWithTooltip' @@ -37,10 +37,10 @@ const AllRecords = styled.div( justify-content: flex-start; gap: ${theme.space['3']}; padding: ${theme.space['4.5']}; - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { padding: ${theme.space['6']}; gap: ${theme.space['6']}; - `)} + } `, ) @@ -85,7 +85,7 @@ const SectionTitle = styled(Typography)( const SectionSubtitle = styled(Typography)( ({ theme }) => css` - color: ${theme.colors.textTertiary}; + color: ${theme.colors.grey}; `, ) @@ -100,9 +100,9 @@ const Actions = styled.div( border-top: 1px solid ${theme.colors.border}; padding: ${theme.space['4']}; - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { padding: ${theme.space['4']} ${theme.space['6']}; - `)} + } `, ) diff --git a/src/components/pages/profile/[name]/tabs/SubnamesTab.tsx b/src/components/pages/profile/[name]/tabs/SubnamesTab.tsx index 4fd3f918d..054beee48 100644 --- a/src/components/pages/profile/[name]/tabs/SubnamesTab.tsx +++ b/src/components/pages/profile/[name]/tabs/SubnamesTab.tsx @@ -4,7 +4,7 @@ import styled, { css } from 'styled-components' import { useAccount } from 'wagmi' import { GetSubnamesParameters } from '@ensdomains/ensjs/subgraph' -import { Button, mq, PlusSVG, Spinner, Typography } from '@ensdomains/thorin' +import { Button, PlusSVG, Spinner, Typography } from '@ensdomains/thorin' import { DisabledButtonWithTooltip } from '@app/components/@molecules/DisabledButtonWithTooltip' import { @@ -55,6 +55,7 @@ const NoMoreResultsContainer = styled.div( align-items: center; justify-content: center; height: ${theme.space['15']}; + color: ${theme.colors.text}; `, ) @@ -68,14 +69,13 @@ const AddSubnamesCard = styled(Card)( & > button { width: 100%; } - - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { flex-direction: row; text-align: left; & > button { width: min-content; } - `)} + } `, ) @@ -217,7 +217,7 @@ export const SubnamesTab = ({ } + prefix={() => } > {t('details.tabs.subnames.addSubname.action')} @@ -230,7 +230,7 @@ export const SubnamesTab = ({ buttonText: t('details.tabs.subnames.addSubname.action'), mobileWidth: 200, mobilePlacement: 'top', - prefix: , + prefix: () => , }} /> )} diff --git a/src/components/pages/profile/settings/PrimarySection.tsx b/src/components/pages/profile/settings/PrimarySection.tsx index ff4adc7dd..8288fdfab 100644 --- a/src/components/pages/profile/settings/PrimarySection.tsx +++ b/src/components/pages/profile/settings/PrimarySection.tsx @@ -1,7 +1,7 @@ import { useTranslation } from 'react-i18next' import styled, { css } from 'styled-components' -import { Button, Card, CrossSVG, mq, PersonPlusSVG, Skeleton, Typography } from '@ensdomains/thorin' +import { Button, Card, CrossSVG, PersonPlusSVG, Skeleton, Typography } from '@ensdomains/thorin' import { AvatarWithLink } from '@app/components/@molecules/AvatarWithLink/AvatarWithLink' import { DisabledButtonWithTooltip } from '@app/components/@molecules/DisabledButtonWithTooltip' @@ -18,8 +18,8 @@ const SkeletonFiller = styled.div( `, ) -const NoNameContainer = styled.div(({ theme }) => [ - css` +const NoNameContainer = styled.div( + ({ theme }) => css` display: grid; grid: 'title title' auto @@ -27,43 +27,44 @@ const NoNameContainer = styled.div(({ theme }) => [ 'button button' auto / 1fr 1fr; grid-row-gap: ${theme.space['4']}; + + @media (min-width: ${theme.breakpoints.sm}px) { + grid: + 'title button' auto + 'description description' auto + / 1fr 1fr; + } `, - mq.sm.min(css` - grid: - 'title button' auto - 'description description' auto - / 1fr 1fr; - `), -]) +) -const NoNameTitle = styled(Typography)(({ theme }) => [ - css` +const NoNameTitle = styled(Typography)( + ({ theme }) => css` grid-area: title; + @media (min-width: ${theme.breakpoints.sm}px) { + line-height: ${theme.space['10']}; + } `, - mq.sm.min(css` - line-height: ${theme.space['10']}; - `), -]) +) -const NoNameButton = styled(Button)(() => [ - css` +const NoNameButton = styled(Button)( + ({ theme }) => css` grid-area: button; + @media (min-width: ${theme.breakpoints.sm}px) { + width: fit-content; + justify-self: end; + } `, - mq.sm.min(css` - width: fit-content; - justify-self: end; - `), -]) +) -const NoNameDisabledButtonContainer = styled.div(() => [ - css` +const NoNameDisabledButtonContainer = styled.div( + ({ theme }) => css` grid-area: button; + @media (min-width: ${theme.breakpoints.sm}px) { + width: fit-content; + justify-self: end; + } `, - mq.sm.min(css` - width: fit-content; - justify-self: end; - `), -]) +) const NoNameDescription = styled(Typography)( () => css` @@ -71,21 +72,21 @@ const NoNameDescription = styled(Typography)( `, ) -const PrimaryNameContainer = styled.div(({ theme }) => [ - css` +const PrimaryNameContainer = styled.div( + ({ theme }) => css` display: flex; flex-direction: column; align-items: center; gap: ${theme.space['4']}; + @media (min-width: ${theme.breakpoints.sm}px) { + flex-direction: row; + gap: ${theme.space['6']}; + } `, - mq.sm.min(css` - flex-direction: row; - gap: ${theme.space['6']}; - `), -]) +) -const PrimaryNameInfo = styled.div(() => [ - css` +const PrimaryNameInfo = styled.div( + ({ theme }) => css` display: flex; width: 100%; position: relative; @@ -97,37 +98,37 @@ const PrimaryNameInfo = styled.div(() => [ width: 100%; text-align: center; } - `, - mq.sm.min(css` - align-items: flex-start; - > div { - text-align: left; + @media (min-width: ${theme.breakpoints.sm}px) { + align-items: flex-start; + > div { + text-align: left; + } } - `), -]) + `, +) -const AvatarContainer = styled.div(({ theme }) => [ - css` +const AvatarContainer = styled.div( + ({ theme }) => css` width: ${theme.space['26']}; height: ${theme.space['26']}; + @media (min-width: ${theme.breakpoints.sm}px) { + order: -1; + } `, - mq.sm.min(css` - order: -1; - `), -]) +) -const ActionsContainer = styled.div(({ theme }) => [ - css` +const ActionsContainer = styled.div( + ({ theme }) => css` width: 100%; display: flex; flex-direction: row; gap: ${theme.space['2']}; + @media (min-width: ${theme.breakpoints.sm}px) { + flex-direction: column-reverse; + width: ${theme.space['40']}; + } `, - mq.sm.min(css` - flex-direction: column-reverse; - width: ${theme.space['40']}; - `), -]) +) export const PrimarySection = () => { const { t } = useTranslation('settings') @@ -185,7 +186,7 @@ export const PrimarySection = () => { buttonId="disabled-reset-primary-name-button" buttonText={t('action.remove', { ns: 'common' })} content={t('errors.networkError.blurb', { ns: 'common' })} - prefix={} + prefix={CrossSVG} size="medium" mobilePlacement="top" loading={hasGraphErrorLoading} @@ -194,7 +195,7 @@ export const PrimarySection = () => { buttonId="disabled-change-primary-name-button" buttonText={t('action.change', { ns: 'common' })} content={t('errors.networkError.blurb', { ns: 'common' })} - prefix={} + prefix={PersonPlusSVG} size="medium" mobilePlacement="top" loading={hasGraphErrorLoading} @@ -204,7 +205,7 @@ export const PrimarySection = () => { <> } + prefix={CrossSVG} colorStyle="redSecondary" disabled={hasGraphErrorLoading} loading={hasGraphErrorLoading} @@ -214,7 +215,7 @@ export const PrimarySection = () => { } + prefix={PersonPlusSVG} disabled={hasGraphErrorLoading} loading={hasGraphErrorLoading} onClick={changePrimary} @@ -235,7 +236,7 @@ export const PrimarySection = () => { buttonText={t('section.primary.choosePrimaryName')} size="small" content={t('errors.networkError.blurb', { ns: 'common' })} - prefix={} + prefix={PersonPlusSVG} mobilePlacement="top" loading={hasGraphErrorLoading} /> @@ -245,7 +246,7 @@ export const PrimarySection = () => { } + prefix={PersonPlusSVG} loading={hasGraphErrorLoading} disabled={hasGraphErrorLoading} onClick={changePrimary} diff --git a/src/components/pages/profile/settings/TransactionSection/TransactionSection.test.tsx b/src/components/pages/profile/settings/TransactionSection/TransactionSection.test.tsx index 93626bb1a..f01cbbf5c 100644 --- a/src/components/pages/profile/settings/TransactionSection/TransactionSection.test.tsx +++ b/src/components/pages/profile/settings/TransactionSection/TransactionSection.test.tsx @@ -8,8 +8,8 @@ import type { Transaction } from '@app/hooks/transactions/transactionStore' import { useClearRecentTransactions } from '@app/hooks/transactions/useClearRecentTransactions' import { useRecentTransactions } from '@app/hooks/transactions/useRecentTransactions' -import { TransactionSection } from './TransactionSection' import { makeMockIntersectionObserver } from '../../../../../../test/mock/makeMockIntersectionObserver' +import { TransactionSection } from './TransactionSection' vi.mock('@app/hooks/chain/useChainName') vi.mock('@app/hooks/transactions/useClearRecentTransactions') diff --git a/src/components/pages/profile/settings/TransactionSection/TransactionSection.tsx b/src/components/pages/profile/settings/TransactionSection/TransactionSection.tsx index 013aa29cf..2dfbbeeac 100644 --- a/src/components/pages/profile/settings/TransactionSection/TransactionSection.tsx +++ b/src/components/pages/profile/settings/TransactionSection/TransactionSection.tsx @@ -2,7 +2,7 @@ import { useEffect, useMemo, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' import styled, { css } from 'styled-components' -import { Button, mq, Spinner, Typography } from '@ensdomains/thorin' +import { Button, Spinner, Typography } from '@ensdomains/thorin' import { Card } from '@app/components/Card' import { Outlink } from '@app/components/Outlink' @@ -44,7 +44,7 @@ const RecentTransactionsMessage = styled(Typography)( ({ theme }) => css` display: flex; justify-content: center; - color: ${theme.colors.textTertiary}; + color: ${theme.colors.grey}; padding: ${theme.space['4']}; `, ) @@ -103,12 +103,12 @@ const ContinueContainer = styled.div(({ theme }) => [ button { padding: 0 ${theme.space['4']}; } - `, - mq.sm.min(css` - button { - padding: 0 ${theme.space['8']}; + @media (min-width: ${theme.breakpoints.sm}px) { + button { + padding: 0 ${theme.space['8']}; + } } - `), + `, ]) const ViewMoreInner = styled(Typography)( diff --git a/src/constants/blockExplorers/evm.json b/src/constants/blockExplorers/evm.json index c6119e574..ff4b77973 100644 --- a/src/constants/blockExplorers/evm.json +++ b/src/constants/blockExplorers/evm.json @@ -1 +1,188 @@ -{"matic":{"id":137,"name":"Polygon","nativeCurrency":{"name":"MATIC","symbol":"MATIC","decimals":18},"blockExplorers":{"default":{"name":"PolygonScan","url":"https://polygonscan.com","apiUrl":"https://api.polygonscan.com/api"}}},"celo":{"id":42220,"name":"Celo","nativeCurrency":{"decimals":18,"name":"CELO","symbol":"CELO"},"blockExplorers":{"default":{"name":"Celo Explorer","url":"https://celoscan.io","apiUrl":"https://api.celoscan.io/api"}}},"cro":{"id":25,"name":"Cronos Mainnet","nativeCurrency":{"decimals":18,"name":"Cronos","symbol":"CRO"},"blockExplorers":{"default":{"name":"Cronos Explorer","url":"https://explorer.cronos.org","apiUrl":"https://explorer-api.cronos.org/mainnet/api"}}},"etc":{"id":61,"name":"Ethereum Classic","nativeCurrency":{"decimals":18,"name":"ETC","symbol":"ETC"},"blockExplorers":{"default":{"name":"Blockscout","url":"https://blockscout.com/etc/mainnet"}}},"ftm":{"id":250,"name":"Fantom","nativeCurrency":{"decimals":18,"name":"Fantom","symbol":"FTM"},"blockExplorers":{"default":{"name":"FTMScan","url":"https://ftmscan.com","apiUrl":"https://api.ftmscan.com/api"}}},"gno":{"id":100,"name":"Gnosis","nativeCurrency":{"decimals":18,"name":"Gnosis","symbol":"xDAI"},"blockExplorers":{"default":{"name":"Gnosisscan","url":"https://gnosisscan.io","apiUrl":"https://api.gnosisscan.io/api"}}},"op":{"id":10,"name":"OP Mainnet","nativeCurrency":{"name":"Ether","symbol":"ETH","decimals":18},"blockExplorers":{"default":{"name":"Optimism Explorer","url":"https://optimistic.etherscan.io","apiUrl":"https://api-optimistic.etherscan.io/api"}}},"arb1":{"id":42161,"name":"Arbitrum One","nativeCurrency":{"name":"Ether","symbol":"ETH","decimals":18},"blockExplorers":{"default":{"name":"Arbiscan","url":"https://arbiscan.io","apiUrl":"https://api.arbiscan.io/api"}}},"base":{"id":8453,"name":"Base","nativeCurrency":{"name":"Ether","symbol":"ETH","decimals":18},"blockExplorers":{"default":{"name":"Basescan","url":"https://basescan.org","apiUrl":"https://api.basescan.org/api"}}},"linea":{"id":59144,"name":"Linea Mainnet","nativeCurrency":{"name":"Linea Ether","symbol":"ETH","decimals":18},"blockExplorers":{"default":{"name":"Etherscan","url":"https://lineascan.build","apiUrl":"https://api.lineascan.build/api"}}},"zora":{"id":7777777,"name":"Zora","nativeCurrency":{"decimals":18,"name":"Ether","symbol":"ETH"},"blockExplorers":{"default":{"name":"Explorer","url":"https://explorer.zora.energy","apiUrl":"https://explorer.zora.energy/api"}}},"zksync":{"id":324,"name":"ZKsync Era","nativeCurrency":{"decimals":18,"name":"Ether","symbol":"ETH"},"blockExplorers":{"default":{"name":"Etherscan","url":"https://era.zksync.network/","apiUrl":"https://api-era.zksync.network/api"},"native":{"name":"ZKsync Explorer","url":"https://explorer.zksync.io/","apiUrl":"https://block-explorer-api.mainnet.zksync.io/api"}}},"metis":{"id":1088,"name":"Metis","nativeCurrency":{"decimals":18,"name":"Metis","symbol":"METIS"},"blockExplorers":{"default":{"name":"Metis Explorer","url":"https://explorer.metis.io","apiUrl":"https://api.routescan.io/v2/network/mainnet/evm/43114/etherscan/api"},"blockscout":{"name":"Andromeda Explorer","url":"https://andromeda-explorer.metis.io","apiUrl":"https://andromeda-explorer.metis.io/api"}}},"avaxc":{"id":43114,"name":"Avalanche","nativeCurrency":{"decimals":18,"name":"Avalanche","symbol":"AVAX"},"blockExplorers":{"default":{"name":"SnowTrace","url":"https://snowtrace.io","apiUrl":"https://api.snowtrace.io"}}},"bsc":{"id":56,"name":"BNB Smart Chain","nativeCurrency":{"decimals":18,"name":"BNB","symbol":"BNB"},"blockExplorers":{"default":{"name":"BscScan","url":"https://bscscan.com","apiUrl":"https://api.bscscan.com/api"}}}} \ No newline at end of file +{ + "matic": { + "id": 137, + "name": "Polygon", + "nativeCurrency": { "name": "MATIC", "symbol": "MATIC", "decimals": 18 }, + "blockExplorers": { + "default": { + "name": "PolygonScan", + "url": "https://polygonscan.com", + "apiUrl": "https://api.polygonscan.com/api" + } + } + }, + "celo": { + "id": 42220, + "name": "Celo", + "nativeCurrency": { "decimals": 18, "name": "CELO", "symbol": "CELO" }, + "blockExplorers": { + "default": { + "name": "Celo Explorer", + "url": "https://celoscan.io", + "apiUrl": "https://api.celoscan.io/api" + } + } + }, + "cro": { + "id": 25, + "name": "Cronos Mainnet", + "nativeCurrency": { "decimals": 18, "name": "Cronos", "symbol": "CRO" }, + "blockExplorers": { + "default": { + "name": "Cronos Explorer", + "url": "https://explorer.cronos.org", + "apiUrl": "https://explorer-api.cronos.org/mainnet/api" + } + } + }, + "etc": { + "id": 61, + "name": "Ethereum Classic", + "nativeCurrency": { "decimals": 18, "name": "ETC", "symbol": "ETC" }, + "blockExplorers": { + "default": { "name": "Blockscout", "url": "https://blockscout.com/etc/mainnet" } + } + }, + "ftm": { + "id": 250, + "name": "Fantom", + "nativeCurrency": { "decimals": 18, "name": "Fantom", "symbol": "FTM" }, + "blockExplorers": { + "default": { + "name": "FTMScan", + "url": "https://ftmscan.com", + "apiUrl": "https://api.ftmscan.com/api" + } + } + }, + "gno": { + "id": 100, + "name": "Gnosis", + "nativeCurrency": { "decimals": 18, "name": "Gnosis", "symbol": "xDAI" }, + "blockExplorers": { + "default": { + "name": "Gnosisscan", + "url": "https://gnosisscan.io", + "apiUrl": "https://api.gnosisscan.io/api" + } + } + }, + "op": { + "id": 10, + "name": "OP Mainnet", + "nativeCurrency": { "name": "Ether", "symbol": "ETH", "decimals": 18 }, + "blockExplorers": { + "default": { + "name": "Optimism Explorer", + "url": "https://optimistic.etherscan.io", + "apiUrl": "https://api-optimistic.etherscan.io/api" + } + } + }, + "arb1": { + "id": 42161, + "name": "Arbitrum One", + "nativeCurrency": { "name": "Ether", "symbol": "ETH", "decimals": 18 }, + "blockExplorers": { + "default": { + "name": "Arbiscan", + "url": "https://arbiscan.io", + "apiUrl": "https://api.arbiscan.io/api" + } + } + }, + "base": { + "id": 8453, + "name": "Base", + "nativeCurrency": { "name": "Ether", "symbol": "ETH", "decimals": 18 }, + "blockExplorers": { + "default": { + "name": "Basescan", + "url": "https://basescan.org", + "apiUrl": "https://api.basescan.org/api" + } + } + }, + "linea": { + "id": 59144, + "name": "Linea Mainnet", + "nativeCurrency": { "name": "Linea Ether", "symbol": "ETH", "decimals": 18 }, + "blockExplorers": { + "default": { + "name": "Etherscan", + "url": "https://lineascan.build", + "apiUrl": "https://api.lineascan.build/api" + } + } + }, + "zora": { + "id": 7777777, + "name": "Zora", + "nativeCurrency": { "decimals": 18, "name": "Ether", "symbol": "ETH" }, + "blockExplorers": { + "default": { + "name": "Explorer", + "url": "https://explorer.zora.energy", + "apiUrl": "https://explorer.zora.energy/api" + } + } + }, + "zksync": { + "id": 324, + "name": "ZKsync Era", + "nativeCurrency": { "decimals": 18, "name": "Ether", "symbol": "ETH" }, + "blockExplorers": { + "default": { + "name": "Etherscan", + "url": "https://era.zksync.network/", + "apiUrl": "https://api-era.zksync.network/api" + }, + "native": { + "name": "ZKsync Explorer", + "url": "https://explorer.zksync.io/", + "apiUrl": "https://block-explorer-api.mainnet.zksync.io/api" + } + } + }, + "metis": { + "id": 1088, + "name": "Metis", + "nativeCurrency": { "decimals": 18, "name": "Metis", "symbol": "METIS" }, + "blockExplorers": { + "default": { + "name": "Metis Explorer", + "url": "https://explorer.metis.io", + "apiUrl": "https://api.routescan.io/v2/network/mainnet/evm/43114/etherscan/api" + }, + "blockscout": { + "name": "Andromeda Explorer", + "url": "https://andromeda-explorer.metis.io", + "apiUrl": "https://andromeda-explorer.metis.io/api" + } + } + }, + "avaxc": { + "id": 43114, + "name": "Avalanche", + "nativeCurrency": { "decimals": 18, "name": "Avalanche", "symbol": "AVAX" }, + "blockExplorers": { + "default": { + "name": "SnowTrace", + "url": "https://snowtrace.io", + "apiUrl": "https://api.snowtrace.io" + } + } + }, + "bsc": { + "id": 56, + "name": "BNB Smart Chain", + "nativeCurrency": { "decimals": 18, "name": "BNB", "symbol": "BNB" }, + "blockExplorers": { + "default": { + "name": "BscScan", + "url": "https://bscscan.com", + "apiUrl": "https://api.bscscan.com/api" + } + } + } +} diff --git a/src/constants/blockExplorers/other.json b/src/constants/blockExplorers/other.json index 9e26dfeeb..0967ef424 100644 --- a/src/constants/blockExplorers/other.json +++ b/src/constants/blockExplorers/other.json @@ -1 +1 @@ -{} \ No newline at end of file +{} diff --git a/src/constants/blockExplorers/supported.json b/src/constants/blockExplorers/supported.json index 602a9bd36..3d310104f 100644 --- a/src/constants/blockExplorers/supported.json +++ b/src/constants/blockExplorers/supported.json @@ -1 +1,86 @@ -{"eth":{"id":1,"name":"Ethereum","nativeCurrency":{"name":"Ether","symbol":"ETH","decimals":18},"blockExplorers":{"default":{"name":"Etherscan","url":"https://etherscan.io","apiUrl":"https://api.etherscan.io/api"}}},"btc":{"name":"Bitcoin","nativeCurrency":{"name":"Bitcoin","symbol":"BTC","decimals":8},"blockExplorers":{"default":{"name":"Blockchair","url":"https://blockchair.com/bitcoin"}}},"sol":{"name":"Solana","nativeCurrency":{"name":"Solana","symbol":"SOL","decimals":9},"blockExplorers":{"default":{"name":"Solana","url":"https://explorer.solana.com/"}}},"op":{"id":10,"name":"OP Mainnet","nativeCurrency":{"name":"Ether","symbol":"ETH","decimals":18},"blockExplorers":{"default":{"name":"Optimism Explorer","url":"https://optimistic.etherscan.io","apiUrl":"https://api-optimistic.etherscan.io/api"}}},"arb1":{"id":42161,"name":"Arbitrum One","nativeCurrency":{"name":"Ether","symbol":"ETH","decimals":18},"blockExplorers":{"default":{"name":"Arbiscan","url":"https://arbiscan.io","apiUrl":"https://api.arbiscan.io/api"}}},"base":{"id":8453,"name":"Base","nativeCurrency":{"name":"Ether","symbol":"ETH","decimals":18},"blockExplorers":{"default":{"name":"Basescan","url":"https://basescan.org","apiUrl":"https://api.basescan.org/api"}}},"matic":{"id":137,"name":"Polygon","nativeCurrency":{"name":"MATIC","symbol":"MATIC","decimals":18},"blockExplorers":{"default":{"name":"PolygonScan","url":"https://polygonscan.com","apiUrl":"https://api.polygonscan.com/api"}}},"linea":{"id":59144,"name":"Linea Mainnet","nativeCurrency":{"name":"Linea Ether","symbol":"ETH","decimals":18},"blockExplorers":{"default":{"name":"Etherscan","url":"https://lineascan.build","apiUrl":"https://api.lineascan.build/api"}}}} \ No newline at end of file +{ + "eth": { + "id": 1, + "name": "Ethereum", + "nativeCurrency": { "name": "Ether", "symbol": "ETH", "decimals": 18 }, + "blockExplorers": { + "default": { + "name": "Etherscan", + "url": "https://etherscan.io", + "apiUrl": "https://api.etherscan.io/api" + } + } + }, + "btc": { + "name": "Bitcoin", + "nativeCurrency": { "name": "Bitcoin", "symbol": "BTC", "decimals": 8 }, + "blockExplorers": { + "default": { "name": "Blockchair", "url": "https://blockchair.com/bitcoin" } + } + }, + "sol": { + "name": "Solana", + "nativeCurrency": { "name": "Solana", "symbol": "SOL", "decimals": 9 }, + "blockExplorers": { "default": { "name": "Solana", "url": "https://explorer.solana.com/" } } + }, + "op": { + "id": 10, + "name": "OP Mainnet", + "nativeCurrency": { "name": "Ether", "symbol": "ETH", "decimals": 18 }, + "blockExplorers": { + "default": { + "name": "Optimism Explorer", + "url": "https://optimistic.etherscan.io", + "apiUrl": "https://api-optimistic.etherscan.io/api" + } + } + }, + "arb1": { + "id": 42161, + "name": "Arbitrum One", + "nativeCurrency": { "name": "Ether", "symbol": "ETH", "decimals": 18 }, + "blockExplorers": { + "default": { + "name": "Arbiscan", + "url": "https://arbiscan.io", + "apiUrl": "https://api.arbiscan.io/api" + } + } + }, + "base": { + "id": 8453, + "name": "Base", + "nativeCurrency": { "name": "Ether", "symbol": "ETH", "decimals": 18 }, + "blockExplorers": { + "default": { + "name": "Basescan", + "url": "https://basescan.org", + "apiUrl": "https://api.basescan.org/api" + } + } + }, + "matic": { + "id": 137, + "name": "Polygon", + "nativeCurrency": { "name": "MATIC", "symbol": "MATIC", "decimals": 18 }, + "blockExplorers": { + "default": { + "name": "PolygonScan", + "url": "https://polygonscan.com", + "apiUrl": "https://api.polygonscan.com/api" + } + } + }, + "linea": { + "id": 59144, + "name": "Linea Mainnet", + "nativeCurrency": { "name": "Linea Ether", "symbol": "ETH", "decimals": 18 }, + "blockExplorers": { + "default": { + "name": "Etherscan", + "url": "https://lineascan.build", + "apiUrl": "https://api.lineascan.build/api" + } + } + } +} diff --git a/src/hooks/chain/useCoinChain.test.ts b/src/hooks/chain/useCoinChain.test.ts index 1f7191b5c..695886014 100644 --- a/src/hooks/chain/useCoinChain.test.ts +++ b/src/hooks/chain/useCoinChain.test.ts @@ -1,21 +1,25 @@ -import { supportedAddresses } from '@app/constants/supportedAddresses'; -import { describe, it, expect } from 'vitest'; -import { getCoinChainQueryFn } from './useCoinChain'; +import { describe, expect, it } from 'vitest' + +import { supportedAddresses } from '@app/constants/supportedAddresses' + +import { getCoinChainQueryFn } from './useCoinChain' describe('getCoinChainQueryFn', () => { - it.each(supportedAddresses)('should return data for supported coin: %s', async (coinName: any) => { - const result = await getCoinChainQueryFn({ queryKey: [{ coinName }] } as any); - expect(result).not.toBeNull(); - }) + it.each(supportedAddresses)( + 'should return data for supported coin: %s', + async (coinName: any) => { + const result = await getCoinChainQueryFn({ queryKey: [{ coinName }] } as any) + expect(result).not.toBeNull() + }, + ) - it.each(['bsc'])('should return data for evm coin: %s', async (coinName: any) => { - const result = await getCoinChainQueryFn({ queryKey: [{ coinName }] } as any); - expect(result).not.toBeNull(); + const result = await getCoinChainQueryFn({ queryKey: [{ coinName }] } as any) + expect(result).not.toBeNull() }) it('should return null for unsupported coin', async () => { - const result = await getCoinChainQueryFn({ queryKey: [{ coinName: 'unsupported' }] } as any); - expect(result).toBeNull(); + const result = await getCoinChainQueryFn({ queryKey: [{ coinName: 'unsupported' }] } as any) + expect(result).toBeNull() }) }) diff --git a/src/hooks/fuses/useFusesSetDates.test.ts b/src/hooks/fuses/useFusesSetDates.test.ts index 1de096986..f44293282 100644 --- a/src/hooks/fuses/useFusesSetDates.test.ts +++ b/src/hooks/fuses/useFusesSetDates.test.ts @@ -211,11 +211,7 @@ describe('generateGetBlockQueryArray', () => { describe('generateMatchedFuseBlockData', () => { it('returns undefined data and no loading or fetching blocks if no fuse set blocks are provided', () => { - const { - data, - hasPendingBlocks, - hasFetchingBlocks, - } = generateMatchedFuseBlockData({ + const { data, hasPendingBlocks, hasFetchingBlocks } = generateMatchedFuseBlockData({ fuseSetBlocks: [], blockDatas: [], queries: [], @@ -226,11 +222,7 @@ describe('generateMatchedFuseBlockData', () => { }) it('returns undefined data and no loading or fetching blocks if no block datas are provided', () => { - const { - data, - hasPendingBlocks, - hasFetchingBlocks, - } = generateMatchedFuseBlockData({ + const { data, hasPendingBlocks, hasFetchingBlocks } = generateMatchedFuseBlockData({ fuseSetBlocks: [['PARENT_CANNOT_CONTROL', 1234]], blockDatas: [], queries: [{ queryKey: [{ blockNumber: 1234n }] } as any], @@ -241,11 +233,7 @@ describe('generateMatchedFuseBlockData', () => { }) it('returns undefined data and no loading or fetching blocks if no block data is found for a fuse set block', () => { - const { - data, - hasPendingBlocks, - hasFetchingBlocks, - } = generateMatchedFuseBlockData({ + const { data, hasPendingBlocks, hasFetchingBlocks } = generateMatchedFuseBlockData({ fuseSetBlocks: [['PARENT_CANNOT_CONTROL', 1234]], blockDatas: [ { diff --git a/src/hooks/time/useDurationCountdown.test.ts b/src/hooks/time/useDurationCountdown.test.ts index 4124d1ef6..8c937ef7c 100644 --- a/src/hooks/time/useDurationCountdown.test.ts +++ b/src/hooks/time/useDurationCountdown.test.ts @@ -1,5 +1,6 @@ -import { describe, expect, it, vi } from "vitest"; -import { calculateTimeDiff, displayCountdown } from "./useDurationCountdown"; +import { describe, expect, it, vi } from 'vitest' + +import { calculateTimeDiff, displayCountdown } from './useDurationCountdown' const makeDiff = (str: string) => { const [years, months, days, hours, minutes] = str.split('-').map(Number) @@ -45,9 +46,11 @@ describe('displayCountdown', () => { ['1 unit.years', '1-1-1-1-1'], ])('should return %s for diff interval %s', (result, diffInterval) => { const diff = makeDiff(diffInterval) - expect(displayCountdown({ - diff, - t: ((x: string, opts: any) => `${opts.count} ${x}`) as any - })).toEqual(result) + expect( + displayCountdown({ + diff, + t: ((x: string, opts: any) => `${opts.count} ${x}`) as any, + }), + ).toEqual(result) }) -}) \ No newline at end of file +}) diff --git a/src/hooks/verification/useVerificationOAuthHandler/utils/createVerificationTransactionFlow.test.ts b/src/hooks/verification/useVerificationOAuthHandler/utils/createVerificationTransactionFlow.test.ts index 96fa43a68..fd9cf9966 100644 --- a/src/hooks/verification/useVerificationOAuthHandler/utils/createVerificationTransactionFlow.test.ts +++ b/src/hooks/verification/useVerificationOAuthHandler/utils/createVerificationTransactionFlow.test.ts @@ -1,6 +1,6 @@ -import { createVerificationTransactionFlow } from './createVerificationTransactionFlow'; +import { afterEach, describe, expect, it, vi } from 'vitest' -import { describe, it, expect, vi, afterEach } from 'vitest'; +import { createVerificationTransactionFlow } from './createVerificationTransactionFlow' const mockCreateTransaction = vi.fn() const mockRouter = { push: vi.fn() } @@ -25,23 +25,33 @@ describe('createVerificationTransactionFlow', () => { it('should return a transaction item', () => { createVerificationTransactionFlow(defaultProps) - expect(mockCreateTransaction).toBeCalledWith("update-verification-record-name.eth", { - "transactions": [ - { - "data":{ - "name": "name.eth", - "verifier": "dentity", - "resolverAddress": "0xresolver", - "verifiedPresentationUri": "https://verifiedPresentationUri", - }, - "name": "updateVerificationRecord", - }, - ]}) + expect(mockCreateTransaction).toBeCalledWith('update-verification-record-name.eth', { + transactions: [ + { + data: { + name: 'name.eth', + verifier: 'dentity', + resolverAddress: '0xresolver', + verifiedPresentationUri: 'https://verifiedPresentationUri', + }, + name: 'updateVerificationRecord', + }, + ], + }) }) - it.each(['verifier', 'name', 'createTransactionFlow', 'resolverAddress', 'verifiedPresentationUri'] as (keyof typeof defaultProps)[])('should return undefined if a parameter %s is missing', (key) => { - expect(createVerificationTransactionFlow(makePropsWithoutProp(key))).toBeUndefined() - expect(mockCreateTransaction).not.toBeCalled() - expect(mockRouter.push).not.toBeCalled() - }) -}) \ No newline at end of file + it.each([ + 'verifier', + 'name', + 'createTransactionFlow', + 'resolverAddress', + 'verifiedPresentationUri', + ] as (keyof typeof defaultProps)[])( + 'should return undefined if a parameter %s is missing', + (key) => { + expect(createVerificationTransactionFlow(makePropsWithoutProp(key))).toBeUndefined() + expect(mockCreateTransaction).not.toBeCalled() + expect(mockRouter.push).not.toBeCalled() + }, + ) +}) diff --git a/src/hooks/verification/useVerifiedRecords/useVerifiedRecords.test.ts b/src/hooks/verification/useVerifiedRecords/useVerifiedRecords.test.ts index e87264342..1fd0822b6 100644 --- a/src/hooks/verification/useVerifiedRecords/useVerifiedRecords.test.ts +++ b/src/hooks/verification/useVerifiedRecords/useVerifiedRecords.test.ts @@ -1,7 +1,8 @@ -import { match } from 'ts-pattern'; -import { getVerifiedRecords, parseVerificationRecord } from './useVerifiedRecords'; -import { describe, it, vi, expect } from 'vitest'; -import { makeMockVerifiablePresentationData } from '@root/test/mock/makeMockVerifiablePresentationData'; +import { makeMockVerifiablePresentationData } from '@root/test/mock/makeMockVerifiablePresentationData' +import { match } from 'ts-pattern' +import { describe, expect, it, vi } from 'vitest' + +import { getVerifiedRecords, parseVerificationRecord } from './useVerifiedRecords' describe('parseVerificationRecord', () => { it('should return empty array if undefined', () => { @@ -17,24 +18,34 @@ describe('parseVerificationRecord', () => { }) it('should return empty array of strings if json is array of strings', () => { - expect(parseVerificationRecord('["1", "2", "3"]')).toEqual(["1", "2", "3"]) + expect(parseVerificationRecord('["1", "2", "3"]')).toEqual(['1', '2', '3']) }) }) - - describe('getVerifiedRecords', () => { - const mockFetch = vi.fn().mockImplementation(async (uri) => match(uri).with('error', () => Promise.reject('error')).otherwise(() => Promise.resolve({ json: () => Promise.resolve(makeMockVerifiablePresentationData('openid'))}))) + const mockFetch = vi.fn().mockImplementation(async (uri) => + match(uri) + .with('error', () => Promise.reject('error')) + .otherwise(() => + Promise.resolve({ + json: () => Promise.resolve(makeMockVerifiablePresentationData('openid')), + }), + ), + ) vi.stubGlobal('fetch', mockFetch) - + it('should exclude fetches that error from results ', async () => { - const result = await getVerifiedRecords({ queryKey: [{ verificationsRecord: '["error", "regular", "error"]'}, '0x123']} as any) + const result = await getVerifiedRecords({ + queryKey: [{ verificationsRecord: '["error", "regular", "error"]' }, '0x123'], + } as any) expect(result).toHaveLength(7) }) it('should return a flat array of verified credentials', async () => { - const result = await getVerifiedRecords({ queryKey: [{ verificationsRecord: '["one", "two", "error", "three"]'}]} as any) + const result = await getVerifiedRecords({ + queryKey: [{ verificationsRecord: '["one", "two", "error", "three"]' }], + } as any) expect(result).toHaveLength(21) expect(result.every((item) => !Array.isArray(item))).toBe(true) }) -}) \ No newline at end of file +}) diff --git a/src/hooks/verification/useVerifiedRecords/utils/makeAppendVerificationProps.test.ts b/src/hooks/verification/useVerifiedRecords/utils/makeAppendVerificationProps.test.ts index 0fcc2cbe7..0db55a278 100644 --- a/src/hooks/verification/useVerifiedRecords/utils/makeAppendVerificationProps.test.ts +++ b/src/hooks/verification/useVerifiedRecords/utils/makeAppendVerificationProps.test.ts @@ -20,76 +20,82 @@ const RECORD_ITEM_KEY_VALUES = [ ] describe('makeAppendVerificationsProps', () => { - it.each(RECORD_ITEM_KEY_VALUES)('should return isVerified is true for key = %s and value = %s', (key, value) => { - const verifiedRecords: UseVerifiedRecordsReturnType = [ - { - issuer: 'dentity', - key: 'com.twitter', - value: '@testETH', - verified: true, - }, - { - issuer: 'dentity', - key: 'org.telegram', - value: 'testETH', - verified: true, - }, - { - issuer: 'dentity', - key: 'com.discord', - value: 'testETH', - verified: true, - }, - { - issuer: 'dentity', - key: 'com.github', - value: 'testETH', - verified: true, - } - ] - const appendVerificationProps = makeAppendVerificationProps(verifiedRecords) - const normalisedRecord = normaliseProfileAccountsRecord({ key, value }) + it.each(RECORD_ITEM_KEY_VALUES)( + 'should return isVerified is true for key = %s and value = %s', + (key, value) => { + const verifiedRecords: UseVerifiedRecordsReturnType = [ + { + issuer: 'dentity', + key: 'com.twitter', + value: '@testETH', + verified: true, + }, + { + issuer: 'dentity', + key: 'org.telegram', + value: 'testETH', + verified: true, + }, + { + issuer: 'dentity', + key: 'com.discord', + value: 'testETH', + verified: true, + }, + { + issuer: 'dentity', + key: 'com.github', + value: 'testETH', + verified: true, + }, + ] + const appendVerificationProps = makeAppendVerificationProps(verifiedRecords) + const normalisedRecord = normaliseProfileAccountsRecord({ key, value }) - expect(appendVerificationProps(normalisedRecord)).toEqual({ - ...normalisedRecord, - isVerified: true, - verifiers: ['dentity'], - }) - }) + expect(appendVerificationProps(normalisedRecord)).toEqual({ + ...normalisedRecord, + isVerified: true, + verifiers: ['dentity'], + }) + }, + ) - it.each(RECORD_ITEM_KEY_VALUES)('should return isVerified is false for key = %s and value = %s if verified is false', (key, value) => { - const verifiedRecords: UseVerifiedRecordsReturnType = [ - { - issuer: 'dentity', - key: 'com.twitter', - value: '@testETH', - verified: false, - }, - { - issuer: 'dentity', - key: 'org.telegram', - value: 'testETH', - verified: false, - }, - { - issuer: 'dentity', - key: 'com.discord', - value: 'testETH', - verified: false, - }, - { - issuer: 'dentity', - key: 'com.github', - value: 'testETH', - verified: false, - } - ] - const appendVerificationProps = makeAppendVerificationProps(verifiedRecords) - const normalisedRecord = normaliseProfileAccountsRecord({ key, value }) + it.each(RECORD_ITEM_KEY_VALUES)( + 'should return isVerified is false for key = %s and value = %s if verified is false', + (key, value) => { + const verifiedRecords: UseVerifiedRecordsReturnType = [ + { + issuer: 'dentity', + key: 'com.twitter', + value: '@testETH', + verified: false, + }, + { + issuer: 'dentity', + key: 'org.telegram', + value: 'testETH', + verified: false, + }, + { + issuer: 'dentity', + key: 'com.discord', + value: 'testETH', + verified: false, + }, + { + issuer: 'dentity', + key: 'com.github', + value: 'testETH', + verified: false, + }, + ] + const appendVerificationProps = makeAppendVerificationProps(verifiedRecords) + const normalisedRecord = normaliseProfileAccountsRecord({ key, value }) - expect(appendVerificationProps(normalisedRecord)).toEqual({ - ...normalisedRecord, - isVerified: false, - }) - }) + expect(appendVerificationProps(normalisedRecord)).toEqual({ + ...normalisedRecord, + isVerified: false, + }) + }, + ) }) diff --git a/src/hooks/verification/useVerifiedRecords/utils/parseVerificationData/utils/parseOpenIdVerifiablePresentation.test.ts b/src/hooks/verification/useVerifiedRecords/utils/parseVerificationData/utils/parseOpenIdVerifiablePresentation.test.ts index a199ba522..e7840ae50 100644 --- a/src/hooks/verification/useVerifiedRecords/utils/parseVerificationData/utils/parseOpenIdVerifiablePresentation.test.ts +++ b/src/hooks/verification/useVerifiedRecords/utils/parseVerificationData/utils/parseOpenIdVerifiablePresentation.test.ts @@ -1,16 +1,23 @@ -import { vi, describe, it, expect } from 'vitest'; -import { isOpenIdVerifiablePresentation, parseOpenIdVerifiablePresentation } from './parseOpenIdVerifiablePresentation'; -import { makeMockVerifiablePresentationData } from '@root/test/mock/makeMockVerifiablePresentationData'; -import { match } from 'ts-pattern'; +import { makeMockVerifiablePresentationData } from '@root/test/mock/makeMockVerifiablePresentationData' +import { match } from 'ts-pattern' +import { describe, expect, it, vi } from 'vitest' + +import { + isOpenIdVerifiablePresentation, + parseOpenIdVerifiablePresentation, +} from './parseOpenIdVerifiablePresentation' vi.mock('../../parseVerifiedCredential', () => ({ - parseVerifiableCredential: () => async (type: string) => match(type).with('error', () => null).with('twitter', () => ({ - issuer: 'dentity', - key: 'com.twitter', - value: 'name', - verified: true - })) - .otherwise(() => null) + parseVerifiableCredential: () => async (type: string) => + match(type) + .with('error', () => null) + .with('twitter', () => ({ + issuer: 'dentity', + key: 'com.twitter', + value: 'name', + verified: true, + })) + .otherwise(() => null), })) describe('isOpenIdVerifiablePresentation', () => { @@ -27,17 +34,23 @@ describe('isOpenIdVerifiablePresentation', () => { }) it('should return false if vp_token is not array of objects', () => { - expect(isOpenIdVerifiablePresentation({ vp_token: {"iamnot": "not verifiable credential"}})).toBe(false) + expect( + isOpenIdVerifiablePresentation({ vp_token: { iamnot: 'not verifiable credential' } }), + ).toBe(false) }) it('should return false if vp_token is not array of objects', () => { - expect(isOpenIdVerifiablePresentation({ vp_token: ["not verifiable credential"]})).toBe(false) + expect(isOpenIdVerifiablePresentation({ vp_token: ['not verifiable credential'] })).toBe(false) }) }) describe('parseOpenIdVerifiablePresentation', () => { it('should return an array of verified credentials an exclude any null values', async () => { - const result = await parseOpenIdVerifiablePresentation({ ownershipVerified: true })({ vp_token: ['twitter', 'error', 'other'] as any}) - expect(result).toEqual([{ issuer: 'dentity', key: 'com.twitter', value: 'name', verified: true}]) + const result = await parseOpenIdVerifiablePresentation({ ownershipVerified: true })({ + vp_token: ['twitter', 'error', 'other'] as any, + }) + expect(result).toEqual([ + { issuer: 'dentity', key: 'com.twitter', value: 'name', verified: true }, + ]) }) -}) \ No newline at end of file +}) diff --git a/src/layouts/Basic.tsx b/src/layouts/Basic.tsx index 4621ddf88..d6d6edcb8 100644 --- a/src/layouts/Basic.tsx +++ b/src/layouts/Basic.tsx @@ -4,8 +4,6 @@ import { useIntercom } from 'react-use-intercom' import styled, { css } from 'styled-components' import { useAccount, useSwitchChain } from 'wagmi' -import { mq } from '@ensdomains/thorin' - import ErrorScreen from '@app/components/@atoms/ErrorScreen' import { getSupportedChainById } from '@app/constants/chains' import { useRouterWithHistory } from '@app/hooks/useRouterWithHistory' @@ -29,11 +27,11 @@ const Container = styled.div( width: calc(100% - calc(var(--padding-size) * 2)); box-sizing: content-box; } - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { --padding-size: ${theme.space['8']}; gap: ${theme.space['6']}; flex-gap: ${theme.space['6']}; - `)} + } `, ) @@ -53,9 +51,9 @@ const ContentWrapper = styled.div( const BottomPlaceholder = styled.div( ({ theme }) => css` height: ${theme.space['14']}; - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { height: ${theme.space['12']}; - `)} + } `, ) diff --git a/src/layouts/Content.tsx b/src/layouts/Content.tsx index d311a64ae..77f81ce18 100644 --- a/src/layouts/Content.tsx +++ b/src/layouts/Content.tsx @@ -2,7 +2,7 @@ import Head from 'next/head' import { ComponentProps, ReactNode, useCallback, useEffect, useRef, useState } from 'react' import styled, { css } from 'styled-components' -import { Banner, Button, mq, Skeleton, Typography } from '@ensdomains/thorin' +import { Banner, Button, Skeleton, Typography } from '@ensdomains/thorin' import Hamburger from '@app/components/@molecules/Hamburger/Hamburger' import { IconCopyAnimated } from '@app/components/IconCopyAnimated' @@ -35,10 +35,10 @@ const HeadingItems = styled.div( align-self: center; align-items: center; min-height: ${theme.space['12']}; - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { min-height: ${theme.space['10']}; grid-column: span 2; - `)} + } `, ) @@ -61,24 +61,24 @@ const ContentContainer = styled.div( ) const ContentPlaceholder = styled.div( - () => css` + ({ theme }) => css` display: none; height: 0; width: 0; - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { display: block; - `)} + } `, ) const WarningWrapper = styled.div( - () => css` + ({ theme }) => css` width: 100%; grid-column: span 1; height: min-content; - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { grid-column: span 2; - `)} + } `, ) @@ -98,7 +98,7 @@ const TitleContainer = styled.div( ) const TitleWrapper = styled.div( - () => css` + ({ theme }) => css` width: 100%; display: flex; align-items: center; @@ -109,7 +109,7 @@ const TitleWrapper = styled.div( align-items: flex-start; } - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { justify-content: flex-start; width: max-content; @@ -117,7 +117,7 @@ const TitleWrapper = styled.div( text-align: left; align-items: flex-start; } - `)} + } `, ) @@ -128,10 +128,10 @@ const Title = styled(Typography)( white-space: nowrap; text-overflow: ellipsis; - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { font-size: ${theme.fontSizes.headingTwo}; line-height: ${theme.lineHeights.headingTwo}; - `)} + } `, ) diff --git a/src/pages/404.tsx b/src/pages/404.tsx index 006999453..bf62aa6fa 100644 --- a/src/pages/404.tsx +++ b/src/pages/404.tsx @@ -2,8 +2,6 @@ import Head from 'next/head' import { useTranslation } from 'react-i18next' import styled, { css } from 'styled-components' -import { mq } from '@ensdomains/thorin' - import ErrorScreen from '@app/components/@atoms/ErrorScreen' import Hamburger from '@app/components/@molecules/Hamburger/Hamburger' import { LeadingHeading } from '@app/components/LeadingHeading' @@ -28,10 +26,10 @@ const LogoAndLanguage = styled.div( ) const StyledLeadingHeading = styled(LeadingHeading)( - () => css` - ${mq.sm.min(css` + ({ theme }) => css` + @media (min-width: ${theme.breakpoints.sm}px) { display: none; - `)} + } `, ) diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index 294ed4587..aec873cae 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -1,6 +1,8 @@ -import { lightTheme, RainbowKitProvider, Theme } from '@rainbow-me/rainbowkit' +/* eslint-disable @typescript-eslint/naming-convention */ +import { darkTheme, lightTheme, RainbowKitProvider, Theme } from '@rainbow-me/rainbowkit' import '@rainbow-me/rainbowkit/styles.css' +import '@ensdomains/thorin/dist/style.css' import '@splidejs/react-splide/css' import { NextPage } from 'next' @@ -10,7 +12,13 @@ import { I18nextProvider } from 'react-i18next' import { IntercomProvider } from 'react-use-intercom' import { createGlobalStyle, keyframes, ThemeProvider } from 'styled-components' -import { ThorinGlobalStyles, lightTheme as thorinLightTheme } from '@ensdomains/thorin' +import { + Mode, + darkTheme as thorinDarkTheme, + lightTheme as thorinLightTheme, + ThemeProvider as ThorinThemeProvider, + useTheme, +} from '@ensdomains/thorin' import { Notifications } from '@app/components/Notifications' import { TestnetWarning } from '@app/components/TestnetWarning' @@ -29,16 +37,6 @@ import '../styles.css' const INTERCOM_ID = process.env.NEXT_PUBLIC_INTERCOM_ID || 'eotmigir' -const rainbowKitTheme: Theme = { - ...lightTheme({ - accentColor: thorinLightTheme.colors.accent, - borderRadius: 'medium', - }), - fonts: { - body: 'Satoshi, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif', - }, -} - const anim = keyframes` 0% { opacity: 1; @@ -91,6 +89,10 @@ const GlobalStyle = createGlobalStyle` } } + [data-theme="dark"] body { + background: rgb(20, 20, 22); + } + a { color: inherit; text-decoration: none; @@ -139,33 +141,66 @@ type AppPropsWithLayout = AppProps & { setupAnalytics() -function MyApp({ Component, pageProps }: AppPropsWithLayout) { +declare global { + interface Window { + __theme: Mode + __setPreferredTheme: (theme: Mode) => void + __onThemeChange: (theme: Mode) => void + } +} + +const AppWithThorin = ({ Component, pageProps }: Omit) => { const getLayout = Component.getLayout ?? ((page) => page) + const theme = useTheme() + + const baseRainbowKitTheme = theme.mode === 'dark' ? darkTheme : lightTheme + + const rainbowKitTheme: Theme = { + ...baseRainbowKitTheme({ + accentColor: thorinLightTheme.colors.accent, + borderRadius: 'medium', + }), + fonts: { + body: 'Satoshi, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif', + }, + } + + return ( + + + + + + + + + + + + {getLayout()} + + + + + + + + + ) +} + +function MyApp({ Component, pageProps }: AppPropsWithLayout) { + const defaultMode = typeof window !== 'undefined' ? window.__theme : 'light' return ( - - - - - - - - - - - - - {getLayout()} - - - - - - - - + window.__setPreferredTheme(mode)} + defaultMode={defaultMode} + > + + ) diff --git a/src/pages/_document.tsx b/src/pages/_document.tsx index 340bcf018..3c04a39ed 100644 --- a/src/pages/_document.tsx +++ b/src/pages/_document.tsx @@ -1,7 +1,10 @@ +/* eslint-disable react/no-danger */ import { AppPropsType, AppType } from 'next/dist/shared/lib/utils' import Document, { DocumentContext, Head, Html, Main, NextScript } from 'next/document' import { ServerStyleSheet, StyleSheetManager } from 'styled-components' +import { cspWithoutFrameAncestors } from '@app/utils/createCsp' + const ipfsPathScript = ` (function () { const { pathname } = window.location @@ -13,6 +16,7 @@ const ipfsPathScript = ` })(); ` +// sha256-UyYcl+sKCF/ROFZPHBlozJrndwfNiC5KT5ZZfup/pPc= const hiddenCheckScript = ` if (document.prerendering) { document.addEventListener('prerenderingchange', () => { @@ -33,6 +37,36 @@ const hiddenCheckScript = ` } ` +// sha256-84jekTLuMPFFzbBxEFpoUhJbu81z5uBinvhIKKkAPxg= +const themeSwitcherScript = ` + (function () { + function setTheme(newTheme) { + document.documentElement.setAttribute('data-theme', newTheme); + window.__theme = newTheme; + window.__onThemeChange(newTheme); + } + window.__onThemeChange = function () {}; + window.__setPreferredTheme = function (newTheme) { + setTheme(newTheme); + try { + localStorage.setItem("theme", JSON.stringify(window.__theme)); + } catch (err) {} + }; + + const darkQuery = window.matchMedia("(prefers-color-scheme: dark)"); + darkQuery.addListener(function (event) { + window.__setPreferredTheme(event.matches ? "dark" : "light"); + }); + + let preferredTheme; + try { + preferredTheme = JSON.parse(localStorage.getItem("theme")); + } catch (err) {} + + setTheme(preferredTheme || (darkQuery.matches ? "dark" : "light")); + })(); +` + const makeIPFSURL = (url: string) => { if (process.env.NEXT_PUBLIC_IPFS) { return `.${url}` @@ -72,16 +106,17 @@ export default class MyDocument extends Document { render() { return ( - + {process.env.NODE_ENV === 'production' && ( - + )} - {/* eslint-disable-next-line react/no-danger */} + {process.env.NEXT_PUBLIC_IPFS && ( <> {/* eslint-disable-next-line react/no-danger */} diff --git a/src/pages/ens-v2.tsx b/src/pages/ens-v2.tsx index 80e1d5a9f..91ce8e072 100644 --- a/src/pages/ens-v2.tsx +++ b/src/pages/ens-v2.tsx @@ -9,7 +9,6 @@ import { GasPumpSVG, // InfoCircleSVG, KeySVG, - mq, // QuestionBubbleSVG, // QuestionCircleSVG, // RightArrowSVG, @@ -21,17 +20,19 @@ import { // import DAOSVG from '../assets/DAO.svg' // import SocialX from '../assets/social/SocialX.svg' -const Title = styled.h1` - font-weight: 830; - text-align: center; +const Title = styled.h1( + ({ theme }) => css` + font-weight: 830; + text-align: center; - font-size: 36px; - line-height: 104%; + font-size: 36px; + line-height: 104%; - @media (min-width: 640px) { - font-size: 52px; - } -` + @media (min-width: ${theme.breakpoints.sm}px) { + font-size: 52px; + } + `, +) const Header = styled.header( ({ theme }) => css` @@ -74,7 +75,7 @@ const Main = styled.main( & > a:hover { color: ${theme.colors.green}; } - @media (min-width: 640px) { + @media (min-width: ${theme.breakpoints.sm}px) { border-radius: ${theme.radii['3xLarge']}; } `, @@ -164,7 +165,7 @@ const GridOneToThree = styled.div( gap: ${theme.space['4']}; text-align: center; grid-template-columns: 1fr; - @media (min-width: 640px) { + @media (min-width: ${theme.breakpoints.sm}px) { grid-template-columns: repeat(3, 1fr); } `, @@ -179,6 +180,11 @@ const CardHeader = styled.h3( font-weight: ${theme.fontWeights.bold}; gap: ${theme.space['2']}; align-items: center; + + svg { + width: 20px; + height: 20px; + } `, ) @@ -219,12 +225,8 @@ const AnnouncementContainer = styled.div( display: flex; align-items: center; justify-content: center; - flex-direction: column; gap: ${theme.space['4']}; - - ${mq.sm.min(css` - flex-direction: row; - `)} + flex-flow: row wrap; `, ) @@ -271,7 +273,7 @@ export default function ENSv2() { allowFullScreen /> - + {t('learn-more.title')} {t('learn-more.caption')} @@ -288,7 +290,7 @@ export default function ENSv2() { - + {t('accessible.title')} {t('accessible.caption')} @@ -326,7 +328,7 @@ export default function ENSv2() { - + {t('announcement.title')} {/* diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 2df5b1ac1..ab052d3ad 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -2,7 +2,7 @@ import Head from 'next/head' import { useTranslation } from 'react-i18next' import styled, { css } from 'styled-components' -import { mq, Typography } from '@ensdomains/thorin' +import { Typography } from '@ensdomains/thorin' import FaucetBanner from '@app/components/@molecules/FaucetBanner' import Hamburger from '@app/components/@molecules/Hamburger/Hamburger' @@ -19,7 +19,7 @@ const GradientTitle = styled.h1( font-size: ${theme.fontSizes.headingTwo}; text-align: center; font-weight: 800; - background-image: ${theme.colors.gradients.accent}; + background-image: ${theme.colors.blueGradient}; background-repeat: no-repeat; background-size: 110%; /* stylelint-disable-next-line property-no-vendor-prefix */ @@ -28,9 +28,9 @@ const GradientTitle = styled.h1( color: transparent; margin: 0; - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { font-size: ${theme.fontSizes.headingOne}; - `)} + } `, ) @@ -82,10 +82,10 @@ const LogoAndLanguage = styled.div( ) const StyledLeadingHeading = styled(LeadingHeading)( - () => css` - ${mq.sm.min(css` + ({ theme }) => css` + @media (min-width: ${theme.breakpoints.sm}px) { display: none; - `)} + } `, ) diff --git a/src/pages/legacyfavourites.tsx b/src/pages/legacyfavourites.tsx index aac73c9c0..b70d1bcb4 100644 --- a/src/pages/legacyfavourites.tsx +++ b/src/pages/legacyfavourites.tsx @@ -48,7 +48,7 @@ export default function Page() { {{ trailing: ( <> - + Your favourites have been carried over from{' '} @@ -78,7 +78,7 @@ export default function Page() { ) }) .otherwise(() => ( - No Favourites found + No Favourites found ))} > ), diff --git a/src/pages/my/names.tsx b/src/pages/my/names.tsx index 37e81cdef..609f79b4c 100644 --- a/src/pages/my/names.tsx +++ b/src/pages/my/names.tsx @@ -4,7 +4,7 @@ import { useTranslation } from 'react-i18next' import styled, { css } from 'styled-components' import { useAccount } from 'wagmi' -import { Banner, QuestionCircleSVG, UpRightArrowSVG } from '@ensdomains/thorin' +import { Banner, QuestionCircleSVG } from '@ensdomains/thorin' import { NameListView } from '@app/components/@molecules/NameListView/NameListView' import { useProtectedRoute } from '@app/hooks/useProtectedRoute' @@ -16,7 +16,10 @@ const ContentContainer = styled.div( display: flex; flex-direction: column; gap: ${theme.space[6]}; - color: ${theme.colors.indigoPrimary}; + + & > *:nth-child(2) svg { + color: var(--thorin-color-indigoPrimary); + } `, ) @@ -40,9 +43,8 @@ export default function Page() { target="_blank" rel="noopener noreferrer" href="https://support.ens.domains/en/articles/9375254-why-is-my-ens-name-not-in-my-names" - icon={} + icon={QuestionCircleSVG} title={t('offchainWarning.title')} - actionIcon={} > {t('offchainWarning.text')} diff --git a/src/pages/unsupportedNetwork.tsx b/src/pages/unsupportedNetwork.tsx index 8c941dbc0..081fe89d4 100644 --- a/src/pages/unsupportedNetwork.tsx +++ b/src/pages/unsupportedNetwork.tsx @@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next' import styled, { css } from 'styled-components' import { useAccount, useSwitchChain } from 'wagmi' -import { Button, Helper, mq } from '@ensdomains/thorin' +import { Button, Helper } from '@ensdomains/thorin' import { getSupportedChainById } from '@app/constants/chains' import { useRouterWithHistory } from '@app/hooks/useRouterWithHistory' @@ -22,10 +22,10 @@ const Card = styled.div( max-height: 75vh; overflow-y: auto; - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { width: initial; min-width: ${theme.space['128']}; - `)} + } `, ) @@ -57,7 +57,7 @@ export default function Page() { return ( - {t('unsupportedNetwork')} + {t('unsupportedNetwork')} {t('action.changeNetwork')} diff --git a/src/test-utils.tsx b/src/test-utils.tsx index 7f932c8f4..07dba94e1 100644 --- a/src/test-utils.tsx +++ b/src/test-utils.tsx @@ -9,7 +9,7 @@ import { beforeEach, expect, MockedFunction, vi } from 'vitest' import type { Register } from 'wagmi' import { hashFn } from 'wagmi/query' -import { lightTheme, ThorinGlobalStyles } from '@ensdomains/thorin' +import { lightTheme } from '@ensdomains/thorin' import { mainnetWithEns } from '@app/constants/chains' @@ -85,10 +85,7 @@ const AllTheProviders: FC<{ children: React.ReactNode }> = ({ children }) => { return ( - - - {children} - + {children} ) diff --git a/src/transaction-flow/TransactionLoader.tsx b/src/transaction-flow/TransactionLoader.tsx index 84e619933..5076fd5c3 100644 --- a/src/transaction-flow/TransactionLoader.tsx +++ b/src/transaction-flow/TransactionLoader.tsx @@ -1,6 +1,6 @@ import styled, { css } from 'styled-components' -import { mq, Spinner } from '@ensdomains/thorin' +import { Spinner } from '@ensdomains/thorin' const Container = styled.div( ({ theme }) => css` @@ -10,10 +10,10 @@ const Container = styled.div( padding: ${theme.space[4]}; width: 100%; - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { width: calc(80vw - 2 * ${theme.space['6']}); max-width: ${theme.space['128']}; - `)} + } `, ) diff --git a/src/transaction-flow/input/AdvancedEditor/AdvancedEditor-flow.tsx b/src/transaction-flow/input/AdvancedEditor/AdvancedEditor-flow.tsx index b7cbc4d59..2cb3ac187 100644 --- a/src/transaction-flow/input/AdvancedEditor/AdvancedEditor-flow.tsx +++ b/src/transaction-flow/input/AdvancedEditor/AdvancedEditor-flow.tsx @@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next' import styled, { css } from 'styled-components' import { RecordOptions } from '@ensdomains/ensjs/utils' -import { Button, Dialog, mq } from '@ensdomains/thorin' +import { Button, Dialog } from '@ensdomains/thorin' import AddRecord from '@app/components/@molecules/AdvancedEditor/AddRecord' import AdvancedEditorTabContent from '@app/components/@molecules/AdvancedEditor/AdvancedEditorTabContent' @@ -14,8 +14,8 @@ import { createTransactionItem, TransactionItem } from '@app/transaction-flow/tr import type { TransactionDialogPassthrough } from '@app/transaction-flow/types' import { Profile } from '@app/types' -const NameContainer = styled.div(({ theme }) => [ - css` +const NameContainer = styled.div( + ({ theme }) => css` display: block; width: 100%; padding-left: ${theme.space['2']}; @@ -33,11 +33,12 @@ const NameContainer = styled.div(({ theme }) => [ white-space: nowrap; text-overflow: ellipsis; overflow: hidden; + + @media (min-width: ${theme.breakpoints.sm}px) { + text-align: left; + } `, - mq.sm.min(css` - text-align: left; - `), -]) +) const FooterContainer = styled.div( ({ theme }) => css` @@ -46,9 +47,9 @@ const FooterContainer = styled.div( width: 100%; margin: 0 auto; - ${mq.sm.min(css` + @media (min-width: ${theme.breakpoints.sm}px) { margin-top: -${theme.space['2']}; - `)} + } `, ) diff --git a/src/transaction-flow/input/CreateSubname-flow.tsx b/src/transaction-flow/input/CreateSubname-flow.tsx index bcfca0e5c..67dfe8bcc 100644 --- a/src/transaction-flow/input/CreateSubname-flow.tsx +++ b/src/transaction-flow/input/CreateSubname-flow.tsx @@ -4,7 +4,7 @@ import styled, { css } from 'styled-components' import { match } from 'ts-pattern' import { validateName } from '@ensdomains/ensjs/utils' -import { Button, Dialog, Input, mq, PlusSVG } from '@ensdomains/thorin' +import { Button, Dialog, Input, PlusSVG } from '@ensdomains/thorin' import { AvatarClickType } from '@app/components/@molecules/ProfileEditor/Avatar/AvatarButton' import { AvatarViewManager } from '@app/components/@molecules/ProfileEditor/Avatar/AvatarViewManager' @@ -42,14 +42,14 @@ const ButtonContainer = styled.div( `, ) -const ButtonWrapper = styled.div(({ theme }) => [ - css` +const ButtonWrapper = styled.div( + ({ theme }) => css` width: ${theme.space.full}; + @media (min-width: ${theme.breakpoints.xs}px) { + width: ${theme.space.max}; + } `, - mq.xs.min(css` - width: max-content; - `), -]) +) const ParentLabel = styled.div( ({ theme }) => css` @@ -286,7 +286,7 @@ const CreateSubname = ({ data: { parent, isWrapped }, dispatch, onDismiss }: Pro size="medium" onClick={() => setView('add-record')} data-testid="show-add-profile-records-modal-button" - prefix={} + prefix={PlusSVG} > {registerT('steps.profile.addMore')} diff --git a/src/transaction-flow/input/DeleteEmancipatedSubnameWarning/DeleteEmancipatedSubnameWarning-flow.tsx b/src/transaction-flow/input/DeleteEmancipatedSubnameWarning/DeleteEmancipatedSubnameWarning-flow.tsx index a305a3c90..86b580f7e 100644 --- a/src/transaction-flow/input/DeleteEmancipatedSubnameWarning/DeleteEmancipatedSubnameWarning-flow.tsx +++ b/src/transaction-flow/input/DeleteEmancipatedSubnameWarning/DeleteEmancipatedSubnameWarning-flow.tsx @@ -1,7 +1,7 @@ import { useTranslation } from 'react-i18next' import styled, { css } from 'styled-components' -import { Button, Dialog, mq } from '@ensdomains/thorin' +import { Button, Dialog } from '@ensdomains/thorin' import { useWrapperData } from '@app/hooks/ensjs/public/useWrapperData' import { TransactionDialogPassthrough } from '@app/transaction-flow/types' @@ -9,15 +9,15 @@ import { TransactionDialogPassthrough } from '@app/transaction-flow/types' import { createTransactionItem } from '../../transaction/index' import { CenterAlignedTypography } from '../RevokePermissions/components/CenterAlignedTypography' -const MessageContainer = styled(CenterAlignedTypography)(({ theme }) => [ - css` +const MessageContainer = styled(CenterAlignedTypography)( + ({ theme }) => css` width: 100%; + @media (min-width: ${theme.breakpoints.sm}px) { + width: calc(80vw - 2 * ${theme.space['6']}); + max-width: ${theme.space['128']}; + } `, - mq.sm.min(css` - width: calc(80vw - 2 * ${theme.space['6']}); - max-width: ${theme.space['128']}; - `), -]) +) type Data = { name: string diff --git a/src/transaction-flow/input/EditRoles/views/EditRoleView/EditRoleView.tsx b/src/transaction-flow/input/EditRoles/views/EditRoleView/EditRoleView.tsx index a021149f6..ad9e0cef9 100644 --- a/src/transaction-flow/input/EditRoles/views/EditRoleView/EditRoleView.tsx +++ b/src/transaction-flow/input/EditRoles/views/EditRoleView/EditRoleView.tsx @@ -4,7 +4,7 @@ import { useTranslation } from 'react-i18next' import styled, { css } from 'styled-components' import { match, P } from 'ts-pattern' -import { Button, Dialog, Input, MagnifyingGlassSimpleSVG, mq } from '@ensdomains/thorin' +import { Button, Dialog, Input, MagnifyingGlassSimpleSVG } from '@ensdomains/thorin' import { DialogFooterWithBorder } from '@app/components/@molecules/DialogComponentVariants/DialogFooterWithBorder' import { SearchViewErrorView } from '@app/transaction-flow/input/SendName/views/SearchView/views/SearchViewErrorView' @@ -16,18 +16,18 @@ import { useSimpleSearch } from '../../hooks/useSimpleSearch' import { EditRoleIntroView } from './views/EditRoleIntroView' import { EditRoleResultsView } from './views/EditRoleResultsView' -const InputWrapper = styled.div(({ theme }) => [ - css` +const InputWrapper = styled.div( + ({ theme }) => css` flex: 0; width: 100%; display: flex; flex-direction: column; margin-bottom: -${theme.space['4']}; + @media (min-width: ${theme.breakpoints.sm}px) { + margin-bottom: -${theme.space['6']}; + } `, - mq.sm.min(css` - margin-bottom: -${theme.space['6']}; - `), -]) +) type Props = { index: number diff --git a/src/transaction-flow/input/EditRoles/views/EditRoleView/views/EditRoleIntroView.tsx b/src/transaction-flow/input/EditRoles/views/EditRoleView/views/EditRoleIntroView.tsx index 546b64a01..d4686c702 100644 --- a/src/transaction-flow/input/EditRoles/views/EditRoleView/views/EditRoleIntroView.tsx +++ b/src/transaction-flow/input/EditRoles/views/EditRoleView/views/EditRoleIntroView.tsx @@ -2,7 +2,7 @@ import { useTranslation } from 'react-i18next' import styled, { css } from 'styled-components' import { Address } from 'viem' -import { Button, mq } from '@ensdomains/thorin' +import { Button } from '@ensdomains/thorin' import { AvatarWithIdentifier } from '@app/components/@molecules/AvatarWithIdentifier/AvatarWithIdentifier' import { useAccountSafely } from '@app/hooks/account/useAccountSafely' @@ -30,10 +30,10 @@ const Row = styled.div(({ theme }) => [ > *:last-child { flex: 0 0 ${theme.space['24']}; } + @media (min-width: ${theme.breakpoints.sm}px) { + padding: ${theme.space['4']} ${theme.space['6']}; + } `, - mq.sm.min(css` - padding: ${theme.space['4']} ${theme.space['6']}; - `), ]) const Container = styled.div( diff --git a/src/transaction-flow/input/EditRoles/views/MainView/components/NoneSetAvatarWithIdentifier.tsx b/src/transaction-flow/input/EditRoles/views/MainView/components/NoneSetAvatarWithIdentifier.tsx index ed886b5dc..76457004b 100644 --- a/src/transaction-flow/input/EditRoles/views/MainView/components/NoneSetAvatarWithIdentifier.tsx +++ b/src/transaction-flow/input/EditRoles/views/MainView/components/NoneSetAvatarWithIdentifier.tsx @@ -1,7 +1,7 @@ import { useTranslation } from 'react-i18next' import styled, { css } from 'styled-components' -import { mq, Space, Typography } from '@ensdomains/thorin' +import { Typography } from '@ensdomains/thorin' import { QuerySpace } from '@app/types' @@ -19,15 +19,31 @@ const Wrapper = styled.div<{ $size?: QuerySpace; $dirty?: boolean }>( ? css` width: ${$size ? theme.space[$size] : theme.space.full}; height: ${$size ? theme.space[$size] : theme.space.full}; + flex: 0 0 ${$size ? theme.space[$size] : theme.space.full}; ` - : Object.entries($size) - .filter(([key]) => key !== 'min') - .map(([key, value]) => - mq[key as keyof typeof mq].min(css` - width: ${theme.space[value as Space]}; - height: ${theme.space[value as Space]}; - `), - )} + : css` + @media (min-width: ${theme.breakpoints.xs}px) { + width: ${theme.space[$size.min]}; + height: ${theme.space[$size.min]}; + flex: 0 0 ${theme.space[$size.min]}; + } + ${Object.keys($size) + .filter((key) => key !== 'min' && key in theme.breakpoints) + .map((key) => { + const sizeValue = $size[key as keyof typeof $size] + return sizeValue + ? css` + @media (min-width: ${theme.breakpoints[ + key as keyof typeof theme.breakpoints + ]}px) { + width: ${theme.space[sizeValue]}; + height: ${theme.space[sizeValue]}; + flex: 0 0 ${theme.space[sizeValue]}; + } + ` + : null + })} + `} `, ) diff --git a/src/transaction-flow/input/ExtendNames/ExtendNames-flow.tsx b/src/transaction-flow/input/ExtendNames/ExtendNames-flow.tsx index 97164798f..182e55fc2 100644 --- a/src/transaction-flow/input/ExtendNames/ExtendNames-flow.tsx +++ b/src/transaction-flow/input/ExtendNames/ExtendNames-flow.tsx @@ -93,7 +93,7 @@ const NamesListItemSubtitle = styled.div( font-weight: ${theme.fontWeights.normal}; font-size: ${theme.space['3.5']}; line-height: 1.43; - color: ${theme.colors.textTertiary}; + color: ${theme.colors.grey}; `, ) @@ -385,7 +385,7 @@ const ExtendNames = ({ (!!estimatedGasLimit && !!balance?.value && balance.value < estimatedGasLimit)) && ( - {t('input.extendNames.gasLimitError')} + {t('input.extendNames.gasLimitError')} )} > diff --git a/src/transaction-flow/input/ExtendNames/utils/validateExtendNamesDuration.test.ts b/src/transaction-flow/input/ExtendNames/utils/validateExtendNamesDuration.test.ts index a960f91d5..37aa29d26 100644 --- a/src/transaction-flow/input/ExtendNames/utils/validateExtendNamesDuration.test.ts +++ b/src/transaction-flow/input/ExtendNames/utils/validateExtendNamesDuration.test.ts @@ -1,41 +1,43 @@ -import { it, describe, expect } from "vitest"; -import { validateExtendNamesDuration } from "./validateExtendNamesDuration"; -import { ONE_DAY, ONE_YEAR } from "@app/utils/time"; +import { describe, expect, it } from 'vitest' + +import { ONE_DAY, ONE_YEAR } from '@app/utils/time' + +import { validateExtendNamesDuration } from './validateExtendNamesDuration' describe('validateExtendNamesDuration', () => { it('should return an integer', () => { - expect(validateExtendNamesDuration({ duration: '90000'})).toBe(90000) + expect(validateExtendNamesDuration({ duration: '90000' })).toBe(90000) }) it('should return an integer for a decimal', () => { - expect(validateExtendNamesDuration({duration: '90000.123'})).toBe(90000) + expect(validateExtendNamesDuration({ duration: '90000.123' })).toBe(90000) }) it('should return minimum duration for a number less than the minimum', () => { - expect(validateExtendNamesDuration({duration: '0'})).toBe(ONE_DAY) + expect(validateExtendNamesDuration({ duration: '0' })).toBe(ONE_DAY) }) it('should return null duration for null', () => { - expect(validateExtendNamesDuration({duration: null})).toBe(null) + expect(validateExtendNamesDuration({ duration: null })).toBe(null) }) it('should return default duration for undefined', () => { - expect(validateExtendNamesDuration({duration: undefined})).toBe(ONE_YEAR) + expect(validateExtendNamesDuration({ duration: undefined })).toBe(ONE_YEAR) }) it('should return default for a string', () => { - expect(validateExtendNamesDuration({duration: 'abc'})).toBe(ONE_YEAR) + expect(validateExtendNamesDuration({ duration: 'abc' })).toBe(ONE_YEAR) }) it('should return default for an empty string', () => { - expect(validateExtendNamesDuration({ duration: ''})).toBe(ONE_YEAR) + expect(validateExtendNamesDuration({ duration: '' })).toBe(ONE_YEAR) }) it('should return default for a negative number', () => { - expect(validateExtendNamesDuration({duration: '-123'})).toBe(ONE_YEAR) + expect(validateExtendNamesDuration({ duration: '-123' })).toBe(ONE_YEAR) }) it('should return default for an object ', () => { - expect(validateExtendNamesDuration({ duration: {}})).toBe(ONE_YEAR) + expect(validateExtendNamesDuration({ duration: {} })).toBe(ONE_YEAR) }) -}) \ No newline at end of file +}) diff --git a/src/transaction-flow/input/ProfileEditor/ProfileEditor-flow.tsx b/src/transaction-flow/input/ProfileEditor/ProfileEditor-flow.tsx index 8a8e72bc2..5639c660a 100644 --- a/src/transaction-flow/input/ProfileEditor/ProfileEditor-flow.tsx +++ b/src/transaction-flow/input/ProfileEditor/ProfileEditor-flow.tsx @@ -6,7 +6,7 @@ import styled, { css } from 'styled-components' import { match } from 'ts-pattern' import { useChainId } from 'wagmi' -import { Button, Dialog, mq, PlusSVG } from '@ensdomains/thorin' +import { Button, Dialog, PlusSVG } from '@ensdomains/thorin' import { DisabledButtonWithTooltip } from '@app/components/@molecules/DisabledButtonWithTooltip' import { AvatarViewManager } from '@app/components/@molecules/ProfileEditor/Avatar/AvatarViewManager' @@ -49,14 +49,14 @@ const ButtonContainer = styled.div( `, ) -const ButtonWrapper = styled.div(({ theme }) => [ - css` +const ButtonWrapper = styled.div( + ({ theme }) => css` width: ${theme.space.full}; + (min-width: 360px) { + width: max-content; + } `, - mq.xs.min(css` - width: max-content; - `), -]) +) type Data = { name?: string @@ -326,7 +326,7 @@ const ProfileEditor = ({ data = {}, transactions = [], dispatch, onDismiss }: Pr size="medium" onClick={handleShowAddRecordModal} data-testid="show-add-profile-records-modal-button" - prefix={} + prefix={PlusSVG} > {t('steps.profile.addMore')} diff --git a/src/transaction-flow/input/ProfileEditor/components/ProfileBlurb.tsx b/src/transaction-flow/input/ProfileEditor/components/ProfileBlurb.tsx index 787c9129d..c0984756a 100644 --- a/src/transaction-flow/input/ProfileEditor/components/ProfileBlurb.tsx +++ b/src/transaction-flow/input/ProfileEditor/components/ProfileBlurb.tsx @@ -61,7 +61,7 @@ export const ProfileBlurb = ({ name, resolverAddress }: Props) => { return ( - + {name} diff --git a/src/transaction-flow/input/ProfileReclaim-flow.tsx b/src/transaction-flow/input/ProfileReclaim-flow.tsx index 407a0727e..4fbc9278d 100644 --- a/src/transaction-flow/input/ProfileReclaim-flow.tsx +++ b/src/transaction-flow/input/ProfileReclaim-flow.tsx @@ -4,7 +4,7 @@ import { useTranslation } from 'react-i18next' import styled, { css } from 'styled-components' import { match } from 'ts-pattern' -import { Button, Dialog, mq, PlusSVG } from '@ensdomains/thorin' +import { Button, Dialog, PlusSVG } from '@ensdomains/thorin' import { AvatarClickType } from '@app/components/@molecules/ProfileEditor/Avatar/AvatarButton' import { AvatarViewManager } from '@app/components/@molecules/ProfileEditor/Avatar/AvatarViewManager' @@ -33,14 +33,14 @@ const ButtonContainer = styled.div( `, ) -const ButtonWrapper = styled.div(({ theme }) => [ - css` +const ButtonWrapper = styled.div( + ({ theme }) => css` width: ${theme.space.full}; + @media (min-width: ${theme.breakpoints.xs}px) { + width: ${theme.space.max}; + } `, - mq.xs.min(css` - width: max-content; - `), -]) +) type Data = { name: string @@ -190,7 +190,7 @@ const ProfileReclaim = ({ data: { name, label, parent }, dispatch, onDismiss }: size="medium" onClick={() => setView('add-record')} data-testid="show-add-profile-records-modal-button" - prefix={} + prefix={PlusSVG} > {registerT('steps.profile.addMore')} diff --git a/src/transaction-flow/input/RevokePermissions/RevokePermissions.test.tsx b/src/transaction-flow/input/RevokePermissions/RevokePermissions.test.tsx index 54103c074..90cccc769 100644 --- a/src/transaction-flow/input/RevokePermissions/RevokePermissions.test.tsx +++ b/src/transaction-flow/input/RevokePermissions/RevokePermissions.test.tsx @@ -6,8 +6,8 @@ import { usePrimaryName } from '@app/hooks/ensjs/public/usePrimaryName' import { createTransactionItem } from '@app/transaction-flow/transaction' import { DeepPartial } from '@app/types' -import RevokePermissions, { Props } from './RevokePermissions-flow' import { makeMockIntersectionObserver } from '../../../../test/mock/makeMockIntersectionObserver' +import RevokePermissions, { Props } from './RevokePermissions-flow' vi.mock('@app/hooks/ensjs/public/usePrimaryName') diff --git a/src/transaction-flow/input/RevokePermissions/views/NameConfirmationWarningView.test.tsx b/src/transaction-flow/input/RevokePermissions/views/NameConfirmationWarningView.test.tsx index c85dc341b..e5cd7afca 100644 --- a/src/transaction-flow/input/RevokePermissions/views/NameConfirmationWarningView.test.tsx +++ b/src/transaction-flow/input/RevokePermissions/views/NameConfirmationWarningView.test.tsx @@ -3,8 +3,8 @@ import { fireEvent, render, renderHook, screen } from '@app/test-utils' import { useState } from 'react' import { describe, expect, it } from 'vitest' -import { NameConfirmationWarningView } from './NameConfirmationWarningView' import { makeMockIntersectionObserver } from '../../../../../test/mock/makeMockIntersectionObserver' +import { NameConfirmationWarningView } from './NameConfirmationWarningView' makeMockIntersectionObserver() diff --git a/src/transaction-flow/input/SelectPrimaryName/SelectPrimaryName-flow.tsx b/src/transaction-flow/input/SelectPrimaryName/SelectPrimaryName-flow.tsx index 3eda7ea98..9ca47f6e7 100644 --- a/src/transaction-flow/input/SelectPrimaryName/SelectPrimaryName-flow.tsx +++ b/src/transaction-flow/input/SelectPrimaryName/SelectPrimaryName-flow.tsx @@ -8,7 +8,7 @@ import { useClient } from 'wagmi' import { getDecodedName, Name } from '@ensdomains/ensjs/subgraph' import { decodeLabelhash, isEncodedLabelhash, saveName } from '@ensdomains/ensjs/utils' -import { Button, Dialog, Heading, mq, Typography } from '@ensdomains/thorin' +import { Button, Dialog, Heading, Typography } from '@ensdomains/thorin' import { DialogFooterWithBorder } from '@app/components/@molecules/DialogComponentVariants/DialogFooterWithBorder' import { DialogHeadingWithBorder } from '@app/components/@molecules/DialogComponentVariants/DialogHeadinWithBorder' @@ -83,20 +83,20 @@ const LoadingContainer = styled.div( `, ) -const NameTableHeaderWrapper = styled.div(({ theme }) => [ - css` +const NameTableHeaderWrapper = styled.div( + ({ theme }) => css` width: calc(100% + 2 * ${theme.space['4']}); margin: 0 -${theme.space['4']} -${theme.space['4']}; border-bottom: 1px solid ${theme.colors.border}; > div { border-bottom: none; } + @media (min-width: ${theme.breakpoints.sm}px) { + width: calc(100% + 2 * ${theme.space['6']}); + margin: 0 -${theme.space['6']} -${theme.space['6']}; + } `, - mq.sm.min(css` - width: calc(100% + 2 * ${theme.space['6']}); - margin: 0 -${theme.space['6']} -${theme.space['6']}; - `), -]) +) const ErrorContainer = styled.div( ({ theme }) => css` diff --git a/src/transaction-flow/input/SendName/views/SearchView/components/SearchViewResult.tsx b/src/transaction-flow/input/SendName/views/SearchView/components/SearchViewResult.tsx index 0720e0ab0..82941d22c 100644 --- a/src/transaction-flow/input/SendName/views/SearchView/components/SearchViewResult.tsx +++ b/src/transaction-flow/input/SendName/views/SearchView/components/SearchViewResult.tsx @@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next' import styled, { css } from 'styled-components' import { Address } from 'viem' -import { mq, Tag } from '@ensdomains/thorin' +import { Tag } from '@ensdomains/thorin' import { AvatarWithIdentifier } from '@app/components/@molecules/AvatarWithIdentifier/AvatarWithIdentifier' import type { Role, RoleRecord } from '@app/hooks/ownership/useRoles/useRoles' @@ -27,8 +27,8 @@ const TagText = styled.span( `, ) -const Container = styled.button(({ theme }) => [ - css` +const Container = styled.button( + ({ theme }) => css` width: 100%; display: flex; align-items: center; @@ -48,11 +48,11 @@ const Container = styled.button(({ theme }) => [ opacity: 0.5; } } + @media (min-width: ${theme.breakpoints.sm}px) { + padding: ${theme.space[4]} ${theme.space[6]}; + } `, - mq.sm.min(css` - padding: ${theme.space[4]} ${theme.space[6]}; - `), -]) +) type Props = { name?: string diff --git a/src/transaction-flow/input/SyncManager/views/MainView.tsx b/src/transaction-flow/input/SyncManager/views/MainView.tsx index 0ee9dbb81..821d4830d 100644 --- a/src/transaction-flow/input/SyncManager/views/MainView.tsx +++ b/src/transaction-flow/input/SyncManager/views/MainView.tsx @@ -26,7 +26,7 @@ export const MainView = ({ manager, showWarning, onCancel, onConfirm }: Props) = - {showWarning && {t('input.syncManager.warning')}} + {showWarning && {t('input.syncManager.warning')}} { return ( <> - + {t('intro.migrateAndUpdateResolver.heading')} diff --git a/src/transaction-flow/intro/SyncManager.tsx b/src/transaction-flow/intro/SyncManager.tsx index efac7885c..5ada4a1f1 100644 --- a/src/transaction-flow/intro/SyncManager.tsx +++ b/src/transaction-flow/intro/SyncManager.tsx @@ -24,7 +24,7 @@ export const SyncManager = ({ manager, isWrapped }: { manager: string; isWrapped values={{ manager: shortenAddress(manager) }} /> - {isWrapped && {t('intro.syncManager.wrappedWarning')}} + {isWrapped && {t('intro.syncManager.wrappedWarning')}} > ) } diff --git a/src/utils/createCsp.ts b/src/utils/createCsp.ts new file mode 100644 index 000000000..8844e465b --- /dev/null +++ b/src/utils/createCsp.ts @@ -0,0 +1,49 @@ +let csp = '' + +// worker-src +csp += 'worker-src' +// only self worker/service worker +csp += " 'self'" +// end worker-src +csp += ';' + +// script-src +csp += ' script-src' +// allow self +csp += " 'self'" +// allow plausible script +csp += ' plausible.io' +// allow cloudflare analytics script +csp += ' static.cloudflareinsights.com' +// allow loading from the pages domain for this app +csp += ' *.ens-app-v3.pages.dev' +// allow intercom scripts +csp += ' https://app.intercom.io' +csp += ' https://widget.intercom.io' +csp += ' https://js.intercomcdn.com' +// allow inline wasm evaluation +csp += ' wasm-unsafe-eval' +// INLINE SCRIPT HASHES +// hiddenCheckScript +csp += " 'sha256-UyYcl+sKCF/ROFZPHBlozJrndwfNiC5KT5ZZfup/pPc='" +// themeSwitcherScript +csp += " 'sha256-84jekTLuMPFFzbBxEFpoUhJbu81z5uBinvhIKKkAPxg='" +// end script-src +csp += ';' + +// for use with csp meta tag +export const cspWithoutFrameAncestors = csp + +let frameAncestors = '' + +// frame-ancestors +frameAncestors += 'frame-ancestors' +// allow self +frameAncestors += " 'self'" +// allow safe wallet +frameAncestors += ' https://app.safe.global' +// end frame-ancestors +frameAncestors += ';' + +export const cspOnlyFrameAncestors = frameAncestors +export const cspWithFrameAncestors = `${csp} ${frameAncestors}` diff --git a/src/utils/date.test.ts b/src/utils/date.test.ts index eedcc6db9..957fb6c4a 100644 --- a/src/utils/date.test.ts +++ b/src/utils/date.test.ts @@ -155,21 +155,23 @@ describe('secondsFromDateDiff', () => { describe('calculateDateDiff', () => { it.each([ ['2024-01-10', '2025-01-10', '1-0-0'], - ['2024-01-10', '2024-02-10', '0-1-0' ], - ['2024-01-10', '2024-01-11', '0-0-1' ], + ['2024-01-10', '2024-02-10', '0-1-0'], + ['2024-01-10', '2024-01-11', '0-0-1'], ['2024-01-10', '2025-01-9', '0-11-30'], ['2024-03-10', '2025-03-9', '0-11-27'], ['2023-03-10', '2024-03-9', '0-11-28'], // leap year ['2024-04-10', '2025-04-9', '0-11-30'], - ['2024-04-10', '2025-04-10', '1-0-0' ], - ['2024-11-10', '2026-05-1', '1-5-21' ], + ['2024-04-10', '2025-04-10', '1-0-0'], + ['2024-11-10', '2026-05-1', '1-5-21'], ])(`should return correct diff from %s to %s`, (date1, date2, result) => { const startDate = new Date(date1) const endDate = new Date(date2) - const toUnit = (i: number) => i === 0 ? 'years' : i === 1 ? 'months' : 'days' - const dateDiff = Object.fromEntries(result.split('-').map((value, i) => [toUnit(i),parseInt(value)])) + const toUnit = (i: number) => (i === 0 ? 'years' : i === 1 ? 'months' : 'days') + const dateDiff = Object.fromEntries( + result.split('-').map((value, i) => [toUnit(i), parseInt(value)]), + ) - expect(calculateDatesDiff(startDate, endDate)).toEqual({ diff: dateDiff, isNegative: false}) + expect(calculateDatesDiff(startDate, endDate)).toEqual({ diff: dateDiff, isNegative: false }) }) -}) \ No newline at end of file +}) diff --git a/src/utils/query/reactQuery.test.tsx b/src/utils/query/reactQuery.test.tsx index 5ac7c41da..537454240 100644 --- a/src/utils/query/reactQuery.test.tsx +++ b/src/utils/query/reactQuery.test.tsx @@ -1,12 +1,12 @@ import { render, waitFor } from '@app/test-utils' import { QueryClientProvider } from '@tanstack/react-query' -import { useQuery } from './useQuery' import { PropsWithChildren, ReactNode } from 'react' import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import { WagmiProvider } from 'wagmi' import { queryClient } from './reactQuery' +import { useQuery } from './useQuery' import { wagmiConfig } from './wagmi' const mockFetchData = vi.fn().mockResolvedValue('Test data') @@ -64,7 +64,7 @@ describe('reactQuery', () => { it('should not refetch query on rerender', async () => { const { getByTestId, rerender } = render( - + , ) @@ -75,7 +75,7 @@ describe('reactQuery', () => { rerender( - + , ) @@ -88,7 +88,7 @@ describe('reactQuery', () => { it('should refetch query on mount', async () => { const { getByTestId, unmount } = render( - + , ) @@ -100,7 +100,7 @@ describe('reactQuery', () => { unmount() const { getByTestId: getByTestId2 } = render( - + , ) @@ -114,7 +114,7 @@ describe('reactQuery', () => { const { getByTestId, unmount } = render( - + , ) @@ -129,7 +129,7 @@ describe('reactQuery', () => { const { getByTestId: getByTestId2 } = render( - + , ) diff --git a/src/utils/records/categoriseProfileTextRecords.test.ts b/src/utils/records/categoriseProfileTextRecords.test.ts index 8aa6229c4..26a1ff170 100644 --- a/src/utils/records/categoriseProfileTextRecords.test.ts +++ b/src/utils/records/categoriseProfileTextRecords.test.ts @@ -1,13 +1,14 @@ -import { vi, describe, it, expect } from 'vitest' +import { describe, expect, it, vi } from 'vitest' + import { categoriseAndTransformTextRecords } from './categoriseProfileTextRecords' describe('categoriseProfileTextRecords', () => { it('should return text records correctly categorised', () => { const result = categoriseAndTransformTextRecords({ texts: [ - { key: 'com.twitter', value: 'name'}, - { key: 'other', value: 'value'}, - { key: 'description', value: 'description'}, + { key: 'com.twitter', value: 'name' }, + { key: 'other', value: 'value' }, + { key: 'description', value: 'description' }, ], contentHash: 'ipfs://contenthash', appendVerificationProps: (record: any) => ({ @@ -17,7 +18,7 @@ describe('categoriseProfileTextRecords', () => { }), }) expect(result).toEqual({ - general: [ { key: 'description', value: 'description' } ], + general: [{ key: 'description', value: 'description' }], accounts: [ { key: 'com.twitter', @@ -25,8 +26,8 @@ describe('categoriseProfileTextRecords', () => { value: '@name', isVerified: true, verifiers: ['dentity'], - iconKey: 'com.twitter' - } + iconKey: 'com.twitter', + }, ], other: [ { key: 'other', value: 'value', type: 'text', iconKey: 'other' }, @@ -34,18 +35,18 @@ describe('categoriseProfileTextRecords', () => { key: 'contenthash', value: 'ipfs://contenthash', type: 'contenthash', - iconKey: 'contenthash' - } - ] + iconKey: 'contenthash', + }, + ], }) }) it('should not return a contenthash record item if it is undefined', () => { const result = categoriseAndTransformTextRecords({ texts: [ - { key: 'com.twitter', value: 'name'}, - { key: 'other', value: 'value'}, - { key: 'description', value: 'description'}, + { key: 'com.twitter', value: 'name' }, + { key: 'other', value: 'value' }, + { key: 'description', value: 'description' }, ], contentHash: undefined, appendVerificationProps: (record: any) => ({ @@ -55,7 +56,7 @@ describe('categoriseProfileTextRecords', () => { }), }) expect(result).toEqual({ - general: [ { key: 'description', value: 'description' } ], + general: [{ key: 'description', value: 'description' }], accounts: [ { key: 'com.twitter', @@ -63,12 +64,10 @@ describe('categoriseProfileTextRecords', () => { value: '@name', isVerified: true, verifiers: ['dentity'], - iconKey: 'com.twitter' - } + iconKey: 'com.twitter', + }, ], - other: [ - { key: 'other', value: 'value', type: 'text', iconKey: 'other' }, - ] + other: [{ key: 'other', value: 'value', type: 'text', iconKey: 'other' }], }) }) }) diff --git a/src/utils/utils.test.ts b/src/utils/utils.test.ts index fd75a6388..a71515796 100644 --- a/src/utils/utils.test.ts +++ b/src/utils/utils.test.ts @@ -131,7 +131,7 @@ describe('formatDurationOfDates', () => { formatDurationOfDates({ startDate: new Date(), endDate: new Date(Date.now() + 123 * 1000), - t: (x, options: any) => x + options?.count, + t: (x, options: any) => x + options?.count, }), ).toEqual('unit.days0') }) diff --git a/src/utils/verification/isVerificationProtocol.test.ts b/src/utils/verification/isVerificationProtocol.test.ts index d04ebca23..3b77b0758 100644 --- a/src/utils/verification/isVerificationProtocol.test.ts +++ b/src/utils/verification/isVerificationProtocol.test.ts @@ -1,5 +1,6 @@ -import { isVerificationProtocol } from "./isVerificationProtocol"; -import { describe, it, expect } from "vitest"; +import { describe, expect, it } from 'vitest' + +import { isVerificationProtocol } from './isVerificationProtocol' describe('isVerificationProtocol', () => { it.each(['dentity'])('should return true for protocol: %s', (protocol) => { diff --git a/tsconfig.json b/tsconfig.json index f00fa1841..5782d836d 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -13,7 +13,7 @@ "plugins": [ { "name": "typescript-styled-plugin", - "tags": ["styled", "css", "mq"] + "tags": ["styled", "css"] } ] } @@ -40,12 +40,13 @@ "paths": { "@app/*": ["./src/*"], "@public/*": ["./public/*"], - "@root/*": ["./*"] + "@root/*": ["./*"], + "rainbow-sprinkles": ["./node_modules/rainbow-sprinkles/"] }, "plugins": [ { "name": "typescript-styled-plugin", - "tags": ["styled", "css", "mq"], + "tags": ["styled", "css"], "validate": false, "lint": { "validProperties": ["flex-gap"]