diff --git a/App.css b/App.css index 281ad899..8c99444b 100644 --- a/App.css +++ b/App.css @@ -14,14 +14,43 @@ div[data-rk] { box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); } -@tailwind base; -@tailwind components; -@tailwind utilities; - +@import 'tailwindcss'; +@plugin "daisyui"; + +:root { + --color-primary: #0f4dc0; + --color-primary-content: #fff; + --color-secondary: #f4f5f6; + --color-secondary-content: #58667e; + --color-accent: #1de7df; + --color-accent-content: #000; + --color-neutral: #eff2f5; + --color-neutral-content: #58667e; + --color-base-100: #f5f9fa; + --color-base-200: #fff; + --color-base-300: #f7f7f7; + --color-base-content: #58667e; + + --radius-field: 9px; + --border: 1px; + + --text: #111; + --bg-modal: #fff; + --modal-border: #e5e5e5; + --rounded-btn: 9px; + --btn-text-case: none; +} :root:has(:is(.modal-open, .modal:target, .modal-toggle:checked + .modal, .modal[open])) { scrollbar-gutter: unset; } +.modal-box { + border-bottom-right-radius: 1.25rem; + border-bottom-left-radius: 1.25rem; + border-top-left-radius: 1.25rem; + border-top-right-radius: 1.25rem; +} + .input-disabled { cursor: not-allowed; color: rgb(229 231 235 / var(--tw-text-opacity)); @@ -29,6 +58,17 @@ div[data-rk] { background-color: var(--fallback-b2, oklch(var(--b2) / var(--tw-bg-opacity))); } +.input { + &:has(> input[disabled]), + &:is(:disabled, [disabled]) { + background-color: transparent; + } +} + +.input-vortex-primary:focus-within { + outline: 2px solid var(--color-primary); +} + .fadein-button-animation::before { content: ''; position: absolute; @@ -53,115 +93,132 @@ div[data-rk] { transform: scaleX(1); } -.click-animation:active:hover, -.click-animation:active:focus { - animation: button-pop 0.2s ease-out; - transform: scale(var(1, 0.97)); +.step-vortex { + min-height: 2.5rem !important; +} +.step-vortex::before { + @apply bg-blue-700; + width: 2px !important; +} +.step-vortex::after { + @apply text-blue-700; +} +.step-primary.step-vortex::after { + @apply text-white; } -@keyframes click { - 50% { - transform: scale(1.25); - } - 100% { - transform: scale(1); - } +.collapse-title, +:where(.collapse > input[type='checkbox']), +:where(.collapse > input[type='radio']) { + min-height: 0rem !important; } -/** Vortex customisations of DaisyUI components */ -@layer components { - .step-vortex { - min-height: 2.5rem !important; - } - .step-vortex::before { - @apply bg-blue-700 !important; - width: 2px !important; - } - .step-vortex::after { - @apply text-blue-700 !important; - } - .step-primary.step-vortex::after { - @apply text-white !important; - } +.collapse-title::after { + @apply text-blue-700; + @apply w-3; + @apply h-3; + top: 1.4rem !important; +} - .collapse-title, - :where(.collapse > input[type='checkbox']), - :where(.collapse > input[type='radio']) { - min-height: 0rem !important; - } +.input-ghost[aria-readonly='true']:focus, +.input-ghost[aria-readonly='true']:focus-within { + background-color: transparent !important; + color: var(--color-base-content); + border-color: #0000; + box-shadow: none; +} - .collapse-title::after { - @apply text-blue-700; - @apply w-3 !important; - @apply h-3 !important; - top: 1.4rem !important; - } - .btn-vortex-primary { - @apply bg-blue-700; - @apply text-white; - @apply rounded-xl; - @apply border; - @apply border-blue-700; - } +.input { + height: unset; +} - .btn-vortex-primary:hover { - @apply bg-white; - @apply text-blue-700; - @apply border-blue-700; - } +.btn { + height: 3rem; +} - .btn-vortex-primary:disabled { - @apply bg-blue-700; - @apply text-white; - @apply border-blue-700; - @apply opacity-40; - } +.btn-vortex-primary { + @apply bg-blue-700; + @apply text-white; + @apply rounded-xl; + @apply border; + @apply border-blue-700; + @apply shadow-none; +} - .btn-vortex-primary:active, - .btn-vortex-primary:focus { - @apply bg-blue-200; - @apply text-blue-700; - @apply border-blue-700; - } +.btn-vortex-primary:hover { + @apply bg-white; + @apply text-blue-700; + @apply border-blue-700; +} - .btn-vortex-primary-inverse { - @apply bg-white; - @apply text-blue-700; - @apply rounded-xl; - @apply border; - @apply border-blue-700; - } +.btn-vortex-primary:disabled { + @apply bg-blue-700; + @apply text-white; + @apply border-blue-700; + @apply opacity-40; +} - .btn-vortex-primary-inverse:hover { - @apply bg-blue-700; - @apply text-white; - @apply border-blue-700; - } +.btn-vortex-primary:active, +.btn-vortex-primary:focus { + @apply bg-blue-200; + @apply text-blue-700; + @apply border-blue-700; +} - .btn-vortex-primary-inverse:disabled { - @apply bg-white; - @apply text-blue-700; - @apply border-blue-700; - @apply opacity-40; - } +.btn-vortex-primary-inverse { + @apply bg-white; + @apply text-blue-700; + @apply rounded-xl; + @apply border; + @apply border-blue-700; +} - .btn-vortex-primary-inverse:active, - .btn-vortex-primary-inverse:focus { - @apply bg-blue-200; - @apply text-blue-700; - @apply border-blue-700; - } +.btn-vortex-primary-inverse:hover { + @apply bg-blue-700; + @apply text-white; + @apply border-blue-700; +} + +.btn-vortex-primary-inverse:disabled { + @apply bg-white; + @apply text-blue-700; + @apply border-blue-700; + @apply opacity-40; +} + +.btn-vortex-primary-inverse:active, +.btn-vortex-primary-inverse:focus { + @apply bg-blue-200; + @apply text-blue-700; + @apply border-blue-700; +} + +.btn-vortex-secondary { + @apply text-white; + @apply bg-pink-600; + @apply border-pink-600; + @apply shadow-none; +} + +.btn-vortex-secondary:hover { + @apply bg-pink-100; + @apply text-pink-600; + @apply border; + @apply border-pink-600; +} + +.btn-vortex-primary { + background-color: var(--color-blue-700); + color: white; + border-radius: var(--radius-field); + border: var(--border) solid var(--color-blue-700); - .btn-vortex-secondary { - @apply text-white; - @apply bg-pink-600; - @apply border-pink-600; + &:hover { + background-color: white; + color: var(--color-blue-700); } - .btn-vortex-secondary:hover { - @apply bg-pink-100; - @apply text-pink-600; - @apply border; - @apply border-pink-600; + &:disabled { + opacity: 0.4; } } diff --git a/package.json b/package.json index a24e0cc3..7d3d19a6 100644 --- a/package.json +++ b/package.json @@ -39,28 +39,24 @@ "@sentry/react": "^8.36.0", "@sentry/vite-plugin": "^2.22.6", "@slack/web-api": "^7.7.0", + "@tailwindcss/vite": "^4.0.3", "@talismn/connect-components": "^1.1.9", "@talismn/connect-wallets": "^1.2.5", "@tanstack/react-query": "^5.64.2", "@vitejs/plugin-react": "^4.3.4", "@walletconnect/modal": "^2.6.2", "@walletconnect/universal-provider": "^2.12.2", - "autoprefixer": "^10.4.19", "big.js": "^6.2.1", "bn.js": "^5.2.1", "buffer": "^6.0.3", - "daisyui": "^4.11.1", "motion": "^12.0.3", - "postcss": "^8.4.38", "react": "^19.0.0", - "react-daisyui": "^5.0.5", "react-dom": "^19.0.0", "react-hook-form": "^7.51.5", "react-toastify": "^10.0.6", "stellar-base": "^11.0.1", "stellar-sdk": "^11.3.0", - "tailwind": "^4.0.0", - "tailwindcss": "^3.4.3", + "tailwindcss": "^4.0.3", "viem": "^2.22.13", "wagmi": "^2.14.9", "web3": "^4.10.0", @@ -85,6 +81,7 @@ "@typescript-eslint/eslint-plugin": "^5.53.0", "@typescript-eslint/parser": "^5.53.0", "babel-preset-vite": "^1.1.3", + "daisyui": "^5.0.0-beta.6", "eslint": "^8.34.0", "eslint-plugin-react": "^7.32.2", "eslint-plugin-react-hooks": "^4.6.0", diff --git a/postcss.config.js b/postcss.config.js deleted file mode 100644 index feab3515..00000000 --- a/postcss.config.js +++ /dev/null @@ -1,8 +0,0 @@ -export default { - plugins: { - 'postcss-import': {}, - 'tailwindcss/nesting': {}, - tailwindcss: {}, - autoprefixer: {}, - }, -}; diff --git a/src/assets/planet.svg b/src/assets/planet.svg new file mode 100644 index 00000000..5f40f3ab --- /dev/null +++ b/src/assets/planet.svg @@ -0,0 +1,2346 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/trusted-by/coindesk.svg b/src/assets/trusted-by/coindesk.svg new file mode 100644 index 00000000..ca4bf41f --- /dev/null +++ b/src/assets/trusted-by/coindesk.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/trusted-by/ethereum.svg b/src/assets/trusted-by/ethereum.svg new file mode 100644 index 00000000..11989de2 --- /dev/null +++ b/src/assets/trusted-by/ethereum.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/trusted-by/metamask.svg b/src/assets/trusted-by/metamask.svg new file mode 100644 index 00000000..64c4f0ee --- /dev/null +++ b/src/assets/trusted-by/metamask.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/trustedby/moonbeam.svg b/src/assets/trusted-by/moonbeam.svg similarity index 100% rename from src/assets/trustedby/moonbeam.svg rename to src/assets/trusted-by/moonbeam.svg diff --git a/src/assets/trustedby/nabla.svg b/src/assets/trusted-by/nabla.svg similarity index 100% rename from src/assets/trustedby/nabla.svg rename to src/assets/trusted-by/nabla.svg diff --git a/src/assets/trusted-by/plugnplay.png b/src/assets/trusted-by/plugnplay.png new file mode 100644 index 00000000..f3fc2140 Binary files /dev/null and b/src/assets/trusted-by/plugnplay.png differ diff --git a/src/assets/trustedby/polkadot.svg b/src/assets/trusted-by/polkadot.svg similarity index 100% rename from src/assets/trustedby/polkadot.svg rename to src/assets/trusted-by/polkadot.svg diff --git a/src/assets/trustedby/stellar.svg b/src/assets/trusted-by/stellar.svg similarity index 100% rename from src/assets/trustedby/stellar.svg rename to src/assets/trusted-by/stellar.svg diff --git a/src/assets/trusted-by/web3.svg b/src/assets/trusted-by/web3.svg new file mode 100644 index 00000000..7300837b --- /dev/null +++ b/src/assets/trusted-by/web3.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/trustedby/web3.svg b/src/assets/trustedby/web3.svg deleted file mode 100644 index 6c55d436..00000000 --- a/src/assets/trustedby/web3.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/src/assets/why-vortex/coffee.svg b/src/assets/why-vortex/coffee.svg new file mode 100644 index 00000000..ab58842e --- /dev/null +++ b/src/assets/why-vortex/coffee.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/assets/why-vortex/dollar.png b/src/assets/why-vortex/dollar.png deleted file mode 100644 index f2f3a7e8..00000000 Binary files a/src/assets/why-vortex/dollar.png and /dev/null differ diff --git a/src/assets/why-vortex/lock.svg b/src/assets/why-vortex/lock.svg new file mode 100644 index 00000000..0a676ddd --- /dev/null +++ b/src/assets/why-vortex/lock.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/why-vortex/padlock.png b/src/assets/why-vortex/padlock.png deleted file mode 100644 index 43919500..00000000 Binary files a/src/assets/why-vortex/padlock.png and /dev/null differ diff --git a/src/assets/why-vortex/percent.svg b/src/assets/why-vortex/percent.svg new file mode 100644 index 00000000..437a3896 --- /dev/null +++ b/src/assets/why-vortex/percent.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/why-vortex/thumb.png b/src/assets/why-vortex/thumb.png deleted file mode 100644 index d818a203..00000000 Binary files a/src/assets/why-vortex/thumb.png and /dev/null differ diff --git a/src/assets/why-vortex/user-check.svg b/src/assets/why-vortex/user-check.svg new file mode 100644 index 00000000..9795a671 --- /dev/null +++ b/src/assets/why-vortex/user-check.svg @@ -0,0 +1,2 @@ + \ No newline at end of file diff --git a/src/components/Accordion/index.tsx b/src/components/Accordion/index.tsx new file mode 100644 index 00000000..b71aaf69 --- /dev/null +++ b/src/components/Accordion/index.tsx @@ -0,0 +1,142 @@ +import { FC, JSX } from 'react'; +import { create } from 'zustand'; +import { motion, AnimatePresence } from 'motion/react'; + +interface AccordionProps { + children: React.ReactNode | React.ReactNode[]; + className?: string; + defaultValue?: string[]; +} + +interface AccordionItemProps { + children: React.ReactNode | React.ReactNode[]; + className?: string; + value: string; +} + +interface AccordionTriggerProps { + children: React.ReactNode | React.ReactNode[]; + className?: string; + value: string; +} + +interface AccordionContentProps { + children: React.ReactNode | React.ReactNode[]; + className?: string; + value: string; +} + +interface AccordionStore { + value: string[]; + setValue: (value: string[]) => void; + toggleValue: (itemValue: string) => void; +} + +const useAccordionStore = create((set) => ({ + value: [], + setValue: (value) => set({ value }), + toggleValue: (itemValue) => + set((state) => ({ + value: state.value.includes(itemValue) ? state.value.filter((v) => v !== itemValue) : [...state.value, itemValue], + })), +})); + +const Accordion: FC = ({ children, className = '', defaultValue = [] }) => { + const setValue = useAccordionStore((state) => state.setValue); + + if (defaultValue.length > 0) { + setValue(defaultValue); + } + + return ( + + {children} + + ); +}; + +const AccordionItem: FC = ({ children, className = '', value }) => { + const isOpen = useAccordionStore((state) => state.value.includes(value)); + + return ( + + + {children} + + + ); +}; + +const AccordionTrigger: FC = ({ children, className = '', value }) => { + const toggleValue = useAccordionStore((state) => state.toggleValue); + const isOpen = useAccordionStore((state) => state.value.includes(value)); + + return ( + + toggleValue(value)} + className={`w-full text-left px-6 py-4 text-base md:text-lg font-medium text-gray-900 hover:text-blue-700 focus:outline-none transition-all duration-200 ${className}`} + > +
+ {children} + + + +
+
+
+ ); +}; + +const AccordionContent: FC = ({ children, className = '', value }) => { + const isOpen = useAccordionStore((state) => state.value.includes(value)); + + return ( + + {isOpen && ( + + + {children} + + + )} + + ); +}; + +export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }; diff --git a/src/components/AssetNumericInput/index.tsx b/src/components/AssetNumericInput/index.tsx index 861b1b58..7a8f1613 100644 --- a/src/components/AssetNumericInput/index.tsx +++ b/src/components/AssetNumericInput/index.tsx @@ -24,20 +24,20 @@ export const AssetNumericInput: FC = ({ ...rest }) => (
-
- +
+
diff --git a/src/components/Dialog/index.tsx b/src/components/Dialog/index.tsx index c577a489..8c676141 100644 --- a/src/components/Dialog/index.tsx +++ b/src/components/Dialog/index.tsx @@ -1,4 +1,3 @@ -import { Modal } from 'react-daisyui'; import { FC, useCallback, useEffect, useRef, useState, FormEvent, JSX } from 'react'; import { createPortal } from 'react-dom'; @@ -104,29 +103,28 @@ export const Dialog: FC = ({ const modalBody = ( <> - {content} - {actions} +
{content}
+
{actions}
); return createPortal( - - - {headerText} {hideCloseButton ? <> : } - - {form ? ( -
- {modalBody} -
- ) : ( - modalBody - )} -
, + +
+
+ {headerText} {hideCloseButton ? <> : } +
+ {form ? ( +
+ {modalBody} +
+ ) : ( + modalBody + )} +
+
, container, ); }; diff --git a/src/components/FeeComparison/index.tsx b/src/components/FeeComparison/index.tsx index 6a02dd62..91537d64 100644 --- a/src/components/FeeComparison/index.tsx +++ b/src/components/FeeComparison/index.tsx @@ -125,7 +125,7 @@ function FeeComparisonTable(props: BaseComparisonProps) { const { amount, sourceAssetSymbol, network, targetAssetSymbol, vortexPrice } = props; return ( -
+
@@ -174,19 +174,24 @@ export const FeeComparison = forwardRef(f })); return ( -
-
-

Save on exchange rate markups

-

- The cost of your transfer comes from the fee and the exchange rate. Many providers offer “no fee”, while - hiding a markup in the exchange rate, making you pay more. -

-

At Vortex, we’ll never do that and show our fees upfront.

+
+
+

+ Save on exchange rate markups +

+

+ The cost of your transfer comes from the fee and the exchange rate. Many providers offer{' '} + “no fee”, while hiding a markup in the exchange rate, making + you pay more. +

+

At Vortex, we’ll never do that and show our fees upfront.

+
+
- -
+ ); }); diff --git a/src/components/Footer/index.tsx b/src/components/Footer/index.tsx index 61ba92a0..5e16ac4c 100644 --- a/src/components/Footer/index.tsx +++ b/src/components/Footer/index.tsx @@ -2,6 +2,8 @@ import { ComponentType } from 'react'; import { Telegram } from '../../assets/SocialsTelegram'; import { Github } from '../../assets/SocialsGithub'; import { X } from '../../assets/SocialsX'; +import VORTEX_LOGO from '../../assets/logo/blue.svg'; +import SATOSHIPAY_LOGO from '../../assets/logo/satoshipay.svg'; interface SocialLink { name: string; @@ -33,24 +35,40 @@ const SocialIcon = ({ social }: { social: SocialLink }) => ( ); -const Copyright = () => ( -
-

Copyright © {new Date().getFullYear()}, Vortex.

-

All rights reserved.

+const Copyright = () =>

Copyright © {new Date().getFullYear()}, Vortex. All rights reserved.

; + +const PoweredBySatoshipay = () => ( +
+

Powered by

+ + Satoshipay +
); export function Footer() { return ( -