Merge pull request #104 from blockworks-foundation/focus-states
add focus states and improve keyboard navigation
This commit is contained in:
commit
489a057acb
|
@ -25,7 +25,7 @@ const AccountsButton = () => {
|
|||
return (
|
||||
<>
|
||||
<button
|
||||
className="hidden h-16 border-l border-th-bkg-3 px-4 md:block"
|
||||
className="hidden h-16 border-l border-th-bkg-3 px-4 focus:bg-th-bkg-3 md:block"
|
||||
id="account-step-two"
|
||||
onClick={handleShowAccounts}
|
||||
>
|
||||
|
|
|
@ -3,13 +3,11 @@ import {
|
|||
ArrowLeftIcon,
|
||||
ArrowUpLeftIcon,
|
||||
ArrowUpTrayIcon,
|
||||
ChevronDownIcon,
|
||||
ExclamationCircleIcon,
|
||||
LinkIcon,
|
||||
} from '@heroicons/react/20/solid'
|
||||
import Decimal from 'decimal.js'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import Image from 'next/legacy/image'
|
||||
import React, { useCallback, useMemo, useState } from 'react'
|
||||
import NumberFormat, {
|
||||
NumberFormatValues,
|
||||
|
@ -44,12 +42,16 @@ import { floorToDecimal } from 'utils/numbers'
|
|||
import BankAmountWithValue from './shared/BankAmountWithValue'
|
||||
import useBanksWithBalances from 'hooks/useBanksWithBalances'
|
||||
import { isMangoError } from 'types'
|
||||
import TokenListButton from './shared/TokenListButton'
|
||||
|
||||
interface BorrowFormProps {
|
||||
onSuccess: () => void
|
||||
token?: string
|
||||
}
|
||||
|
||||
export const ACCOUNT_ACTIONS_NUMBER_FORMAT_CLASSES =
|
||||
'default-transition w-full rounded-lg rounded-l-none border border-th-input-border bg-th-input-bkg p-3 text-right font-mono text-xl text-th-fgd-1 focus:border-th-fgd-4 focus:outline-none md:hover:border-th-input-border-hover md:hover:focus:border-th-fgd-4'
|
||||
|
||||
function BorrowForm({ onSuccess, token }: BorrowFormProps) {
|
||||
const { t } = useTranslation('common')
|
||||
const { group } = useMangoGroup()
|
||||
|
@ -181,12 +183,7 @@ function BorrowForm({ onSuccess, token }: BorrowFormProps) {
|
|||
className="absolute bottom-0 left-0 z-20 h-full w-full overflow-auto rounded-lg bg-th-bkg-1 p-6"
|
||||
show={showTokenList}
|
||||
>
|
||||
<button
|
||||
onClick={() => setShowTokenList(false)}
|
||||
className={`absolute left-4 top-4 z-40 w-6 text-th-fgd-4 focus:outline-none md:right-2 md:top-2 md:hover:text-th-active`}
|
||||
>
|
||||
<ArrowLeftIcon className={`h-6 w-6`} />
|
||||
</button>
|
||||
<BackButton onClick={() => setShowTokenList(false)} />
|
||||
<h2 className="mb-4 text-center text-lg">{t('select-borrow-token')}</h2>
|
||||
<div className="flex items-center px-4 pb-2">
|
||||
<div className="w-1/4">
|
||||
|
@ -234,26 +231,12 @@ function BorrowForm({ onSuccess, token }: BorrowFormProps) {
|
|||
/>
|
||||
) : null}
|
||||
</div>
|
||||
<div className="col-span-1 rounded-lg rounded-r-none border border-r-0 border-th-input-border bg-th-input-bkg">
|
||||
<button
|
||||
onClick={() => setShowTokenList(true)}
|
||||
className="default-transition flex h-full w-full items-center rounded-lg rounded-r-none py-2 px-3 text-th-fgd-2 hover:cursor-pointer hover:bg-th-bkg-2 hover:text-th-fgd-1"
|
||||
>
|
||||
<div className="mr-2.5 flex min-w-[24px] items-center">
|
||||
<Image
|
||||
alt=""
|
||||
width="24"
|
||||
height="24"
|
||||
src={
|
||||
logoUri || `/icons/${selectedToken.toLowerCase()}.svg`
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex w-full items-center justify-between">
|
||||
<div className="text-xl font-bold">{selectedToken}</div>
|
||||
<ChevronDownIcon className="h-6 w-6" />
|
||||
</div>
|
||||
</button>
|
||||
<div className="col-span-1">
|
||||
<TokenListButton
|
||||
token={selectedToken}
|
||||
logoUri={logoUri}
|
||||
setShowList={setShowTokenList}
|
||||
/>
|
||||
</div>
|
||||
<div className="col-span-1">
|
||||
<NumberFormat
|
||||
|
@ -264,7 +247,7 @@ function BorrowForm({ onSuccess, token }: BorrowFormProps) {
|
|||
allowNegative={false}
|
||||
isNumericString={true}
|
||||
decimalScale={bank?.mintDecimals || 6}
|
||||
className="w-full rounded-lg rounded-l-none border border-th-input-border bg-th-input-bkg p-3 text-right font-mono text-xl text-th-fgd-1 focus:border-th-input-border-hover focus:outline-none md:hover:border-th-input-border-hover"
|
||||
className={ACCOUNT_ACTIONS_NUMBER_FORMAT_CLASSES}
|
||||
placeholder="0.00"
|
||||
value={inputAmount}
|
||||
onValueChange={handleInputChange}
|
||||
|
@ -395,3 +378,14 @@ function BorrowForm({ onSuccess, token }: BorrowFormProps) {
|
|||
}
|
||||
|
||||
export default BorrowForm
|
||||
|
||||
export const BackButton = ({ onClick }: { onClick: (x: boolean) => void }) => {
|
||||
return (
|
||||
<button
|
||||
onClick={() => onClick(false)}
|
||||
className="absolute left-4 top-4 z-40 w-6 text-th-fgd-4 focus:text-th-active focus:outline-none md:right-2 md:top-2 md:hover:text-th-active"
|
||||
>
|
||||
<ArrowLeftIcon className={`h-6 w-6`} />
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
import {
|
||||
ArrowDownTrayIcon,
|
||||
ArrowLeftIcon,
|
||||
ChevronDownIcon,
|
||||
ExclamationCircleIcon,
|
||||
LinkIcon,
|
||||
} from '@heroicons/react/20/solid'
|
||||
import { useWallet } from '@solana/wallet-adapter-react'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import Image from 'next/legacy/image'
|
||||
import React, { useCallback, useMemo, useState } from 'react'
|
||||
import NumberFormat, { NumberFormatValues } from 'react-number-format'
|
||||
import mangoStore from '@store/mangoStore'
|
||||
|
@ -37,6 +34,8 @@ import { floorToDecimal } from 'utils/numbers'
|
|||
import BankAmountWithValue from './shared/BankAmountWithValue'
|
||||
import useBanksWithBalances from 'hooks/useBanksWithBalances'
|
||||
import { isMangoError } from 'types'
|
||||
import TokenListButton from './shared/TokenListButton'
|
||||
import { ACCOUNT_ACTIONS_NUMBER_FORMAT_CLASSES, BackButton } from './BorrowForm'
|
||||
|
||||
interface DepositFormProps {
|
||||
onSuccess: () => void
|
||||
|
@ -172,12 +171,7 @@ function DepositForm({ onSuccess, token }: DepositFormProps) {
|
|||
className="absolute bottom-0 left-0 z-20 h-full w-full overflow-auto rounded-lg bg-th-bkg-1 p-6"
|
||||
show={showTokenList}
|
||||
>
|
||||
<button
|
||||
onClick={() => setShowTokenList(false)}
|
||||
className={`absolute left-4 top-4 z-40 w-6 text-th-fgd-4 focus:outline-none md:right-2 md:top-2 md:hover:text-th-active`}
|
||||
>
|
||||
<ArrowLeftIcon className={`h-6 w-6`} />
|
||||
</button>
|
||||
<BackButton onClick={() => setShowTokenList(false)} />
|
||||
<h2 className="mb-4 text-center text-lg">
|
||||
{t('select-deposit-token')}
|
||||
</h2>
|
||||
|
@ -222,26 +216,12 @@ function DepositForm({ onSuccess, token }: DepositFormProps) {
|
|||
value={tokenMax.maxAmount}
|
||||
/>
|
||||
</div>
|
||||
<div className="col-span-1 rounded-lg rounded-r-none border border-r-0 border-th-input-border bg-th-input-bkg">
|
||||
<button
|
||||
onClick={() => setShowTokenList(true)}
|
||||
className="default-transition flex h-full w-full items-center rounded-lg rounded-r-none py-2 px-3 text-th-fgd-2 hover:cursor-pointer hover:bg-th-bkg-2 hover:text-th-fgd-1"
|
||||
>
|
||||
<div className="mr-2.5 flex min-w-[24px] items-center">
|
||||
<Image
|
||||
alt=""
|
||||
width="24"
|
||||
height="24"
|
||||
src={
|
||||
logoUri || `/icons/${selectedToken.toLowerCase()}.svg`
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex w-full items-center justify-between">
|
||||
<div className="text-xl font-bold">{selectedToken}</div>
|
||||
<ChevronDownIcon className="h-6 w-6" />
|
||||
</div>
|
||||
</button>
|
||||
<div className="col-span-1">
|
||||
<TokenListButton
|
||||
token={selectedToken}
|
||||
logoUri={logoUri}
|
||||
setShowList={setShowTokenList}
|
||||
/>
|
||||
</div>
|
||||
<div className="col-span-1">
|
||||
<NumberFormat
|
||||
|
@ -252,7 +232,7 @@ function DepositForm({ onSuccess, token }: DepositFormProps) {
|
|||
allowNegative={false}
|
||||
isNumericString={true}
|
||||
decimalScale={bank?.mintDecimals || 6}
|
||||
className="w-full rounded-lg rounded-l-none border border-th-input-border bg-th-input-bkg p-3 text-right font-mono text-xl text-th-fgd-1 focus:border-th-input-border-hover focus:outline-none md:hover:border-th-input-border-hover"
|
||||
className={ACCOUNT_ACTIONS_NUMBER_FORMAT_CLASSES}
|
||||
placeholder="0.00"
|
||||
value={inputAmount}
|
||||
onValueChange={(e: NumberFormatValues) => {
|
||||
|
|
|
@ -90,7 +90,7 @@ const Layout = ({ children }: { children: ReactNode }) => {
|
|||
|
||||
<div className="fixed z-20 hidden h-screen md:block">
|
||||
<button
|
||||
className="default-transition absolute right-0 top-1/2 z-20 hidden h-8 w-3 -translate-y-1/2 rounded-none rounded-l bg-th-bkg-4 hover:bg-th-bkg-4 focus:outline-none lg:block"
|
||||
className="default-transition absolute right-0 top-1/2 z-20 hidden h-8 w-3 -translate-y-1/2 rounded-none rounded-l bg-th-bkg-3 hover:bg-th-bkg-4 focus:bg-th-bkg-4 focus:outline-none lg:block"
|
||||
onClick={handleToggleSidebar}
|
||||
>
|
||||
<ChevronRightIcon
|
||||
|
|
|
@ -1,14 +1,10 @@
|
|||
import {
|
||||
ArrowDownRightIcon,
|
||||
ArrowLeftIcon,
|
||||
ChevronDownIcon,
|
||||
ExclamationCircleIcon,
|
||||
QuestionMarkCircleIcon,
|
||||
} from '@heroicons/react/20/solid'
|
||||
import { useWallet } from '@solana/wallet-adapter-react'
|
||||
import Decimal from 'decimal.js'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import Image from 'next/legacy/image'
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react'
|
||||
import NumberFormat, { NumberFormatValues } from 'react-number-format'
|
||||
import mangoStore from '@store/mangoStore'
|
||||
|
@ -35,6 +31,8 @@ import ConnectEmptyState from './shared/ConnectEmptyState'
|
|||
import BankAmountWithValue from './shared/BankAmountWithValue'
|
||||
import useBanksWithBalances from 'hooks/useBanksWithBalances'
|
||||
import { isMangoError } from 'types'
|
||||
import TokenListButton from './shared/TokenListButton'
|
||||
import { ACCOUNT_ACTIONS_NUMBER_FORMAT_CLASSES, BackButton } from './BorrowForm'
|
||||
|
||||
interface RepayFormProps {
|
||||
onSuccess: () => void
|
||||
|
@ -187,12 +185,7 @@ function RepayForm({ onSuccess, token }: RepayFormProps) {
|
|||
className="absolute bottom-0 left-0 z-20 h-full w-full overflow-auto rounded-lg bg-th-bkg-1 p-6"
|
||||
show={showTokenList}
|
||||
>
|
||||
<button
|
||||
onClick={() => setShowTokenList(false)}
|
||||
className={`absolute left-4 top-4 z-40 w-6 text-th-fgd-4 focus:outline-none md:right-2 md:top-2 md:hover:text-th-active`}
|
||||
>
|
||||
<ArrowLeftIcon className={`h-6 w-6`} />
|
||||
</button>
|
||||
<BackButton onClick={() => setShowTokenList(false)} />
|
||||
<h2 className="mb-4 text-center text-lg">{t('select-repay-token')}</h2>
|
||||
<div className="flex items-center px-4 pb-2">
|
||||
<div className="w-1/2 text-left">
|
||||
|
@ -233,23 +226,12 @@ function RepayForm({ onSuccess, token }: RepayFormProps) {
|
|||
/>
|
||||
) : null}
|
||||
</div>
|
||||
<div className="col-span-1 rounded-lg rounded-r-none border border-r-0 border-th-input-border bg-th-input-bkg">
|
||||
<button
|
||||
onClick={() => setShowTokenList(true)}
|
||||
className="default-transition flex h-full w-full items-center rounded-lg rounded-r-none py-2 px-3 text-th-fgd-2 hover:cursor-pointer hover:bg-th-bkg-2 hover:text-th-fgd-1"
|
||||
>
|
||||
<div className="mr-2.5 flex min-w-[24px] items-center">
|
||||
{logoUri ? (
|
||||
<Image alt="" width="24" height="24" src={logoUri} />
|
||||
) : (
|
||||
<QuestionMarkCircleIcon className="h-6 w-6 text-th-fgd-3" />
|
||||
)}
|
||||
</div>
|
||||
<div className="flex w-full items-center justify-between">
|
||||
<div className="text-xl font-bold">{selectedToken}</div>
|
||||
<ChevronDownIcon className="h-6 w-6" />
|
||||
</div>
|
||||
</button>
|
||||
<div className="col-span-1">
|
||||
<TokenListButton
|
||||
token={selectedToken}
|
||||
logoUri={logoUri}
|
||||
setShowList={setShowTokenList}
|
||||
/>
|
||||
</div>
|
||||
<div className="col-span-1">
|
||||
<NumberFormat
|
||||
|
@ -260,7 +242,7 @@ function RepayForm({ onSuccess, token }: RepayFormProps) {
|
|||
allowNegative={false}
|
||||
isNumericString={true}
|
||||
decimalScale={bank?.mintDecimals || 6}
|
||||
className="w-full rounded-lg rounded-l-none border border-th-input-border bg-th-input-bkg p-3 text-right font-mono text-xl text-th-fgd-1 focus:border-th-input-border-hover focus:outline-none md:hover:border-th-input-border-hover"
|
||||
className={ACCOUNT_ACTIONS_NUMBER_FORMAT_CLASSES}
|
||||
placeholder="0.00"
|
||||
value={inputAmount}
|
||||
onValueChange={(e: NumberFormatValues) => {
|
||||
|
|
|
@ -10,7 +10,6 @@ import {
|
|||
Cog8ToothIcon,
|
||||
ArrowsRightLeftIcon,
|
||||
ArrowTrendingUpIcon,
|
||||
XMarkIcon,
|
||||
MagnifyingGlassIcon,
|
||||
BanknotesIcon,
|
||||
NewspaperIcon,
|
||||
|
@ -19,7 +18,7 @@ import {
|
|||
} from '@heroicons/react/20/solid'
|
||||
import { useRouter } from 'next/router'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import { Fragment, ReactNode, useState } from 'react'
|
||||
import { Fragment, ReactNode } from 'react'
|
||||
import { Disclosure, Popover, Transition } from '@headlessui/react'
|
||||
import MangoAccountSummary from './account/MangoAccountSummary'
|
||||
import Tooltip from './shared/Tooltip'
|
||||
|
@ -29,7 +28,6 @@ import mangoStore from '@store/mangoStore'
|
|||
import HealthHeart from './account/HealthHeart'
|
||||
import useMangoAccount from 'hooks/useMangoAccount'
|
||||
import { useTheme } from 'next-themes'
|
||||
import { IconButton } from './shared/Button'
|
||||
import LeaderboardIcon from './icons/LeaderboardIcon'
|
||||
|
||||
const SideNav = ({ collapsed }: { collapsed: boolean }) => {
|
||||
|
@ -204,7 +202,6 @@ const SideNav = ({ collapsed }: { collapsed: boolean }) => {
|
|||
size={32}
|
||||
/>
|
||||
}
|
||||
isOpen
|
||||
panelTitle={mangoAccount?.name ? mangoAccount.name : t('account')}
|
||||
title={
|
||||
<div className="w-24 text-left">
|
||||
|
@ -222,7 +219,6 @@ const SideNav = ({ collapsed }: { collapsed: boolean }) => {
|
|||
}
|
||||
alignBottom
|
||||
hideIconBg
|
||||
showClose
|
||||
>
|
||||
<div className="px-4 py-2">
|
||||
<MangoAccountSummary />
|
||||
|
@ -315,8 +311,6 @@ export const ExpandableMenuItem = ({
|
|||
hideIconBg,
|
||||
icon,
|
||||
panelTitle,
|
||||
isOpen,
|
||||
showClose,
|
||||
title,
|
||||
}: {
|
||||
alignBottom?: boolean
|
||||
|
@ -325,134 +319,112 @@ export const ExpandableMenuItem = ({
|
|||
hideIconBg?: boolean
|
||||
icon: ReactNode
|
||||
panelTitle?: string
|
||||
isOpen?: boolean
|
||||
showClose?: boolean
|
||||
title: string | ReactNode
|
||||
}) => {
|
||||
const [showMenu, setShowMenu] = useState(isOpen || false)
|
||||
const { theme } = useTheme()
|
||||
|
||||
const toggleMenu = () => {
|
||||
setShowMenu(!showMenu)
|
||||
}
|
||||
|
||||
return collapsed ? (
|
||||
<Popover>
|
||||
<div
|
||||
className={`relative z-30 ${alignBottom ? '' : 'py-2 pl-4'}`}
|
||||
role="button"
|
||||
<Popover className={`relative z-30 ${alignBottom ? '' : 'py-2 pl-4'}`}>
|
||||
<Popover.Button
|
||||
className={`${theme === 'Light' ? 'text-th-fgd-3' : 'text-th-fgd-2'} ${
|
||||
alignBottom ? 'focus:bg-th-bkg-3' : 'focus:text-th-active'
|
||||
} md:hover:text-th-active`}
|
||||
>
|
||||
<Popover.Button
|
||||
className={`${
|
||||
theme === 'Light' ? 'text-th-fgd-3' : 'text-th-fgd-2'
|
||||
} md:hover:text-th-active`}
|
||||
onClick={() => toggleMenu()}
|
||||
<div
|
||||
className={` ${
|
||||
hideIconBg
|
||||
? ''
|
||||
: `flex h-8 w-8 items-center justify-center rounded-full ${
|
||||
theme === 'Light' ? 'bg-th-bkg-2' : 'bg-th-bkg-3'
|
||||
}`
|
||||
} ${
|
||||
alignBottom
|
||||
? 'default-transition flex h-[64px] w-[64px] items-center justify-center hover:bg-th-bkg-2'
|
||||
: ''
|
||||
}`}
|
||||
>
|
||||
<div
|
||||
className={` ${
|
||||
hideIconBg
|
||||
? ''
|
||||
: `flex h-8 w-8 items-center justify-center rounded-full ${
|
||||
theme === 'Light' ? 'bg-th-bkg-2' : 'bg-th-bkg-3'
|
||||
}`
|
||||
} ${
|
||||
alignBottom
|
||||
? 'default-transition flex h-[64px] w-[64px] items-center justify-center hover:bg-th-bkg-2'
|
||||
: ''
|
||||
}`}
|
||||
>
|
||||
{icon}
|
||||
{icon}
|
||||
</div>
|
||||
</Popover.Button>
|
||||
<Popover.Panel
|
||||
className={`absolute left-[64px] z-20 w-56 rounded-md rounded-l-none bg-th-bkg-1 focus:outline-none ${
|
||||
alignBottom
|
||||
? 'bottom-0 rounded-b-none border-b-0 p-0'
|
||||
: 'top-1/2 -translate-y-1/2'
|
||||
}`}
|
||||
>
|
||||
<div
|
||||
className={`rounded-md rounded-l-none bg-th-bkg-2 ${
|
||||
alignBottom ? 'pt-4 pb-2' : 'py-2'
|
||||
}`}
|
||||
>
|
||||
<div className="flex items-center justify-between pl-4 pr-2">
|
||||
{panelTitle ? (
|
||||
<h3 className="text-sm font-bold">{panelTitle}</h3>
|
||||
) : null}
|
||||
</div>
|
||||
</Popover.Button>
|
||||
|
||||
{showMenu ? (
|
||||
<Popover.Panel
|
||||
static
|
||||
className={`absolute z-20 w-56 rounded-md rounded-l-none bg-th-bkg-1 ${
|
||||
alignBottom
|
||||
? 'bottom-0 left-[63px] rounded-b-none border-b-0 p-0'
|
||||
: 'top-1/2 left-[63px] -translate-y-1/2'
|
||||
}`}
|
||||
>
|
||||
<div className="rounded-md rounded-l-none bg-th-bkg-2 py-2">
|
||||
<div className="flex items-center justify-between pl-4 pr-2">
|
||||
{panelTitle ? (
|
||||
<h3 className="text-sm font-bold">{panelTitle}</h3>
|
||||
) : null}
|
||||
{showClose ? (
|
||||
<IconButton
|
||||
onClick={() => setShowMenu(false)}
|
||||
hideBg
|
||||
size="small"
|
||||
>
|
||||
<XMarkIcon className="h-5 w-5" />
|
||||
</IconButton>
|
||||
) : null}
|
||||
</div>
|
||||
{children}
|
||||
</div>
|
||||
</Popover.Panel>
|
||||
) : null}
|
||||
</div>
|
||||
{children}
|
||||
</div>
|
||||
</Popover.Panel>
|
||||
</Popover>
|
||||
) : (
|
||||
<Disclosure>
|
||||
<div
|
||||
onClick={() => setShowMenu(!showMenu)}
|
||||
role="button"
|
||||
className={`w-full px-4 py-2 ${
|
||||
alignBottom ? 'h-[64px] hover:bg-th-bkg-2' : ''
|
||||
}`}
|
||||
>
|
||||
<Disclosure.Button
|
||||
className={`flex h-full w-full items-center justify-between rounded-none md:hover:text-th-active`}
|
||||
>
|
||||
<div className="flex items-center">
|
||||
<div
|
||||
className={
|
||||
hideIconBg
|
||||
? ''
|
||||
: 'flex h-8 w-8 items-center justify-center rounded-full bg-th-bkg-3'
|
||||
}
|
||||
>
|
||||
{icon}
|
||||
{({ open }) => (
|
||||
<>
|
||||
<Disclosure.Button
|
||||
className={`default-transition flex h-full w-full items-center justify-between rounded-none px-4 py-2 focus:text-th-active md:hover:text-th-active ${
|
||||
alignBottom
|
||||
? 'h-[64px] focus:bg-th-bkg-3 md:hover:bg-th-bkg-2'
|
||||
: ''
|
||||
}`}
|
||||
>
|
||||
<div className="flex items-center">
|
||||
<div
|
||||
className={
|
||||
hideIconBg
|
||||
? ''
|
||||
: 'flex h-8 w-8 items-center justify-center rounded-full bg-th-bkg-3'
|
||||
}
|
||||
>
|
||||
{icon}
|
||||
</div>
|
||||
<Transition
|
||||
appear={true}
|
||||
show={!collapsed}
|
||||
as={Fragment}
|
||||
enter="transition ease-in duration-300"
|
||||
enterFrom="opacity-50"
|
||||
enterTo="opacity-100"
|
||||
leave="transition ease-out duration-300"
|
||||
leaveFrom="opacity-100"
|
||||
leaveTo="opacity-0"
|
||||
>
|
||||
<span className="ml-3 truncate xl:text-base">{title}</span>
|
||||
</Transition>
|
||||
</div>
|
||||
<Transition
|
||||
appear={true}
|
||||
show={!collapsed}
|
||||
as={Fragment}
|
||||
enter="transition ease-in duration-300"
|
||||
enterFrom="opacity-50"
|
||||
enterTo="opacity-100"
|
||||
leave="transition ease-out duration-300"
|
||||
leaveFrom="opacity-100"
|
||||
leaveTo="opacity-0"
|
||||
>
|
||||
<span className="ml-3 truncate xl:text-base">{title}</span>
|
||||
</Transition>
|
||||
</div>
|
||||
<ChevronDownIcon
|
||||
className={`${
|
||||
showMenu ? 'rotate-180' : 'rotate-360'
|
||||
} h-5 w-5 flex-shrink-0`}
|
||||
/>
|
||||
</Disclosure.Button>
|
||||
</div>
|
||||
<Transition
|
||||
appear={true}
|
||||
show={showMenu}
|
||||
as={Fragment}
|
||||
enter="transition-all ease-in duration-300"
|
||||
enterFrom="opacity-100 max-h-0"
|
||||
enterTo="opacity-100 max-h-80"
|
||||
leave="transition-all ease-out duration-300"
|
||||
leaveFrom="opacity-100 max-h-80"
|
||||
leaveTo="opacity-0 max-h-0"
|
||||
>
|
||||
<Disclosure.Panel className="w-full overflow-hidden">
|
||||
<div className={`${!alignBottom ? 'ml-1.5' : ''}`}>{children}</div>
|
||||
</Disclosure.Panel>
|
||||
</Transition>
|
||||
<ChevronDownIcon
|
||||
className={`${
|
||||
open ? 'rotate-180' : 'rotate-360'
|
||||
} h-5 w-5 flex-shrink-0`}
|
||||
/>
|
||||
</Disclosure.Button>
|
||||
<Transition
|
||||
as={Fragment}
|
||||
enter="transition-all ease-in duration-300"
|
||||
enterFrom="opacity-100 max-h-0"
|
||||
enterTo="opacity-100 max-h-80"
|
||||
leave="transition-all ease-out duration-300"
|
||||
leaveFrom="opacity-100 max-h-80"
|
||||
leaveTo="opacity-0 max-h-0"
|
||||
>
|
||||
<Disclosure.Panel className="w-full overflow-hidden">
|
||||
<div className={`${!alignBottom ? 'ml-1.5' : ''}`}>
|
||||
{children}
|
||||
</div>
|
||||
</Disclosure.Panel>
|
||||
</Transition>
|
||||
</>
|
||||
)}
|
||||
</Disclosure>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,14 +1,11 @@
|
|||
import { HealthType } from '@blockworks-foundation/mango-v4'
|
||||
import {
|
||||
ArrowLeftIcon,
|
||||
ArrowUpTrayIcon,
|
||||
ChevronDownIcon,
|
||||
ExclamationCircleIcon,
|
||||
LinkIcon,
|
||||
} from '@heroicons/react/20/solid'
|
||||
import Decimal from 'decimal.js'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import Image from 'next/legacy/image'
|
||||
import { useCallback, useMemo, useState } from 'react'
|
||||
import NumberFormat, { NumberFormatValues } from 'react-number-format'
|
||||
|
||||
|
@ -39,6 +36,8 @@ import { floorToDecimal } from 'utils/numbers'
|
|||
import BankAmountWithValue from './shared/BankAmountWithValue'
|
||||
import useBanksWithBalances from 'hooks/useBanksWithBalances'
|
||||
import { isMangoError } from 'types'
|
||||
import TokenListButton from './shared/TokenListButton'
|
||||
import { ACCOUNT_ACTIONS_NUMBER_FORMAT_CLASSES, BackButton } from './BorrowForm'
|
||||
|
||||
interface WithdrawFormProps {
|
||||
onSuccess: () => void
|
||||
|
@ -160,12 +159,7 @@ function WithdrawForm({ onSuccess, token }: WithdrawFormProps) {
|
|||
className="absolute bottom-0 left-0 z-20 h-full w-full overflow-auto rounded-lg bg-th-bkg-1 p-6"
|
||||
show={showTokenList}
|
||||
>
|
||||
<button
|
||||
onClick={() => setShowTokenList(false)}
|
||||
className={`absolute left-4 top-4 z-40 w-6 text-th-fgd-4 focus:outline-none md:right-2 md:top-2 md:hover:text-th-active`}
|
||||
>
|
||||
<ArrowLeftIcon className={`h-6 w-6`} />
|
||||
</button>
|
||||
<BackButton onClick={() => setShowTokenList(false)} />
|
||||
<h2 className="mb-4 text-center text-lg">
|
||||
{t('select-withdraw-token')}
|
||||
</h2>
|
||||
|
@ -211,26 +205,12 @@ function WithdrawForm({ onSuccess, token }: WithdrawFormProps) {
|
|||
/>
|
||||
) : null}
|
||||
</div>
|
||||
<div className="col-span-1 rounded-lg rounded-r-none border border-r-0 border-th-input-border bg-th-input-bkg">
|
||||
<button
|
||||
onClick={() => setShowTokenList(true)}
|
||||
className="default-transition flex h-full w-full items-center rounded-lg rounded-r-none py-2 px-3 text-th-fgd-2 hover:cursor-pointer hover:bg-th-bkg-2 hover:text-th-fgd-1"
|
||||
>
|
||||
<div className="mr-2.5 flex min-w-[24px] items-center">
|
||||
<Image
|
||||
alt=""
|
||||
width="24"
|
||||
height="24"
|
||||
src={
|
||||
logoUri || `/icons/${selectedToken.toLowerCase()}.svg`
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex w-full items-center justify-between">
|
||||
<div className="text-xl font-bold">{selectedToken}</div>
|
||||
<ChevronDownIcon className="h-6 w-6" />
|
||||
</div>
|
||||
</button>
|
||||
<div className="col-span-1">
|
||||
<TokenListButton
|
||||
token={selectedToken}
|
||||
logoUri={logoUri}
|
||||
setShowList={setShowTokenList}
|
||||
/>
|
||||
</div>
|
||||
<div className="col-span-1">
|
||||
<NumberFormat
|
||||
|
@ -241,7 +221,7 @@ function WithdrawForm({ onSuccess, token }: WithdrawFormProps) {
|
|||
allowNegative={false}
|
||||
isNumericString={true}
|
||||
decimalScale={bank?.mintDecimals || 6}
|
||||
className="w-full rounded-lg rounded-l-none border border-th-input-border bg-th-input-bkg p-3 text-right font-mono text-xl text-th-fgd-1 focus:border-th-input-border-hover focus:outline-none md:hover:border-th-input-border-hover"
|
||||
className={ACCOUNT_ACTIONS_NUMBER_FORMAT_CLASSES}
|
||||
placeholder="0.00"
|
||||
value={inputAmount}
|
||||
onValueChange={(e: NumberFormatValues) =>
|
||||
|
|
|
@ -296,10 +296,10 @@ const AccountPage = () => {
|
|||
<div className="hide-scroll flex justify-center space-x-2 md:justify-start">
|
||||
{TABS.map((tab) => (
|
||||
<button
|
||||
className={`default-transition rounded-md py-1.5 px-2.5 text-sm font-medium md:hover:text-th-fgd-2 ${
|
||||
className={`default-transition rounded-md py-1.5 px-2.5 text-sm font-medium focus:bg-th-bkg-3 md:hover:text-th-fgd-2 ${
|
||||
activeTab === tab
|
||||
? 'bg-th-bkg-3 text-th-active'
|
||||
: 'text-th-fgd-3'
|
||||
? 'bg-th-bkg-3 text-th-active focus:text-th-active'
|
||||
: 'text-th-fgd-3 focus:text-th-fgd-1'
|
||||
}`}
|
||||
onClick={() => setActiveTab(tab)}
|
||||
key={tab}
|
||||
|
|
|
@ -32,7 +32,7 @@ const ActionTokenItem = ({
|
|||
|
||||
return (
|
||||
<button
|
||||
className="default-transition flex w-full items-center rounded-md border border-th-bkg-4 bg-th-bkg-1 px-4 py-3 disabled:cursor-not-allowed disabled:opacity-30 md:hover:border-th-fgd-4 md:disabled:hover:border-th-bkg-4"
|
||||
className="default-transition flex w-full items-center rounded-md border border-th-bkg-4 bg-th-bkg-1 px-4 py-3 focus:border-th-fgd-4 disabled:cursor-not-allowed disabled:opacity-30 md:hover:border-th-fgd-4 md:disabled:hover:border-th-bkg-4"
|
||||
onClick={() => onSelect(name)}
|
||||
disabled={customValue <= 0}
|
||||
>
|
||||
|
|
|
@ -140,12 +140,14 @@ const ActivityFilters = () => {
|
|||
</IconButton>
|
||||
</Tooltip>
|
||||
) : null}
|
||||
<div
|
||||
<button
|
||||
onClick={() => setShowFilters(!showFilters)}
|
||||
role="button"
|
||||
className={`default-transition mr-4 ml-3 rounded-md border border-th-button px-2 py-1.5 md:mr-6 md:hover:border-th-button-hover`}
|
||||
className={`default-transition mr-4 ml-3 rounded-md border border-th-button px-2 py-1.5 focus:border-th-fgd-4 md:mr-6 md:hover:border-th-button-hover`}
|
||||
>
|
||||
<Disclosure.Button className="flex h-full w-full items-center justify-between">
|
||||
<Disclosure.Button
|
||||
as="div"
|
||||
className="flex h-full w-full items-center justify-between"
|
||||
>
|
||||
<div className="flex items-center space-x-2">
|
||||
<AdjustmentsVerticalIcon className="hidden h-5 w-5 text-th-fgd-4 sm:block" />
|
||||
<span className="text-sm font-medium text-th-fgd-1">
|
||||
|
@ -158,7 +160,7 @@ const ActivityFilters = () => {
|
|||
} ml-1.5 h-5 w-5 flex-shrink-0`}
|
||||
/>
|
||||
</Disclosure.Button>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
{showFilters ? (
|
||||
<Disclosure.Panel
|
||||
|
|
|
@ -27,10 +27,10 @@ const HistoryTabs = () => {
|
|||
<div className="hide-scroll flex space-x-2 pl-4 md:pl-6">
|
||||
{TABS.map((tab) => (
|
||||
<button
|
||||
className={`default-transition rounded-md py-1.5 px-2.5 text-sm font-medium md:hover:bg-th-bkg-4 ${
|
||||
className={`default-transition rounded-md py-1.5 px-2.5 text-sm font-medium focus:bg-th-bkg-4 md:hover:bg-th-bkg-4 ${
|
||||
activeTab === tab
|
||||
? 'bg-th-bkg-4 text-th-active'
|
||||
: 'bg-th-bkg-3 text-th-fgd-3'
|
||||
? 'bg-th-bkg-4 text-th-active focus:text-th-active'
|
||||
: 'text-th-fgd-3 focus:text-th-fgd-1'
|
||||
}`}
|
||||
onClick={() => setActiveTab(tab)}
|
||||
key={tab}
|
||||
|
|
|
@ -37,13 +37,13 @@ const ButtonGroup = <T extends Values>({
|
|||
) : null}
|
||||
{values.map((v, i) => (
|
||||
<button
|
||||
className={`${className} default-transition relative w-1/2 cursor-pointer rounded-md px-3 text-center disabled:cursor-not-allowed ${
|
||||
className={`${className} default-transition relative w-1/2 cursor-pointer rounded-md px-3 text-center focus:bg-th-bkg-3 disabled:cursor-not-allowed ${
|
||||
large ? 'h-12 text-sm' : 'h-10 text-xs'
|
||||
} font-normal
|
||||
${
|
||||
v === activeValue
|
||||
? `text-th-active`
|
||||
: `text-th-fgd-2 md:hover:text-th-active`
|
||||
? `text-th-active focus:text-th-active`
|
||||
: `text-th-fgd-2 focus:text-th-fgd-1 md:hover:text-th-fgd-1`
|
||||
}
|
||||
`}
|
||||
disabled={disabled}
|
||||
|
|
|
@ -34,7 +34,7 @@ const MangoDateRangePicker = ({
|
|||
<div className="w-full">
|
||||
<Label text={t('date-from')} />
|
||||
<input
|
||||
className="default-transition h-12 w-full rounded-md border border-th-input-border bg-th-input-bkg px-3 text-th-fgd-1 focus:border-th-input-border-hover focus:outline-none md:hover:border-th-input-border-hover"
|
||||
className="default-transition h-12 w-full rounded-md border border-th-input-border bg-th-input-bkg px-3 text-th-fgd-1 focus:border-th-fgd-4 focus:outline-none md:hover:border-th-input-border-hover"
|
||||
{...startDateInputProps}
|
||||
placeholder="Start Date"
|
||||
/>
|
||||
|
@ -45,7 +45,7 @@ const MangoDateRangePicker = ({
|
|||
<div className="w-full">
|
||||
<Label text={t('date-to')} />
|
||||
<input
|
||||
className="default-transition h-12 w-full rounded-md border border-th-input-border bg-th-input-bkg px-3 text-th-fgd-1 focus:border-th-input-border-hover focus:outline-none md:hover:border-th-input-border-hover"
|
||||
className="default-transition h-12 w-full rounded-md border border-th-input-border bg-th-input-bkg px-3 text-th-fgd-1 focus:border-th-fgd-4 focus:outline-none md:hover:border-th-input-border-hover"
|
||||
{...endDateInputProps}
|
||||
placeholder="End Date"
|
||||
/>
|
||||
|
|
|
@ -21,7 +21,7 @@ const MultiSelectDropdown = ({
|
|||
{({ open }) => (
|
||||
<div className="flex flex-col">
|
||||
<Popover.Button
|
||||
className={`default-transition h-12 rounded-md bg-th-input-bkg px-3 text-th-fgd-1 ring-1 ring-inset ring-th-input-border md:hover:ring-th-input-border-hover ${
|
||||
className={`default-transition h-12 rounded-md bg-th-input-bkg px-3 text-th-fgd-1 ring-1 ring-inset ring-th-input-border focus:ring-th-fgd-4 md:hover:ring-th-input-border-hover ${
|
||||
open ? 'ring-th-input-border-hover' : 'ring-th-input-border'
|
||||
}`}
|
||||
>
|
||||
|
@ -47,8 +47,6 @@ const MultiSelectDropdown = ({
|
|||
</div>
|
||||
</Popover.Button>
|
||||
<Transition
|
||||
appear={true}
|
||||
show={open}
|
||||
as={Fragment}
|
||||
enter="transition-all ease-in duration-200"
|
||||
enterFrom="opacity-0 transform scale-75"
|
||||
|
|
|
@ -27,7 +27,7 @@ const Select = ({
|
|||
{({ open }) => (
|
||||
<>
|
||||
<Listbox.Button
|
||||
className={`default-transition h-full w-full rounded-md bg-th-input-bkg py-2.5 font-normal ring-1 ring-inset ring-th-input-border focus:border-th-input-border-hover focus:outline-none md:hover:ring-th-input-border-hover`}
|
||||
className={`default-transition h-full w-full rounded-md bg-th-input-bkg py-2.5 font-normal ring-1 ring-inset ring-th-input-border focus:outline-none focus:ring-th-fgd-4 md:hover:ring-th-input-border-hover`}
|
||||
>
|
||||
<div
|
||||
className={`flex items-center justify-between space-x-2 px-3 text-th-fgd-1`}
|
||||
|
@ -38,20 +38,17 @@ const Select = ({
|
|||
<span className="text-th-fgd-3">{placeholder}</span>
|
||||
)}
|
||||
<ChevronDownIcon
|
||||
className={`default-transition h-5 w-5 flex-shrink-0 text-th-fgd-1 ${
|
||||
className={`default-transition h-5 w-5 flex-shrink-0 text-th-fgd-3 ${
|
||||
open ? 'rotate-180' : 'rotate-360'
|
||||
}`}
|
||||
/>
|
||||
</div>
|
||||
</Listbox.Button>
|
||||
{open ? (
|
||||
<Listbox.Options
|
||||
static
|
||||
className={`thin-scroll absolute left-0 z-20 mt-1 max-h-60 w-full origin-top-left space-y-2 overflow-auto rounded-md bg-th-bkg-2 p-4 text-th-fgd-1 outline-none ${dropdownPanelClassName}`}
|
||||
>
|
||||
{children}
|
||||
</Listbox.Options>
|
||||
) : null}
|
||||
<Listbox.Options
|
||||
className={`thin-scroll absolute left-0 z-20 mt-1 max-h-60 w-full origin-top-left space-y-2 overflow-auto rounded-md bg-th-bkg-2 p-4 outline-none ${dropdownPanelClassName}`}
|
||||
>
|
||||
{children}
|
||||
</Listbox.Options>
|
||||
</>
|
||||
)}
|
||||
</Listbox>
|
||||
|
@ -67,13 +64,12 @@ interface OptionProps {
|
|||
|
||||
const Option = ({ value, children, className }: OptionProps) => {
|
||||
return (
|
||||
<Listbox.Option className="mb-0" value={value}>
|
||||
<Listbox.Option
|
||||
className="default-transition mb-0 text-th-fgd-2 hover:cursor-pointer focus:text-th-active md:hover:text-th-fgd-1"
|
||||
value={value}
|
||||
>
|
||||
{({ selected }) => (
|
||||
<div
|
||||
className={`default-transition rounded text-th-fgd-2 hover:cursor-pointer md:hover:text-th-fgd-1 ${
|
||||
selected ? 'text-th-active' : ''
|
||||
} ${className}`}
|
||||
>
|
||||
<div className={` ${selected ? 'text-th-active' : ''} ${className}`}>
|
||||
{children}
|
||||
</div>
|
||||
)}
|
||||
|
|
|
@ -27,8 +27,9 @@ const Switch: FunctionComponent<SwitchProps> = ({
|
|||
className={`${
|
||||
checked ? 'bg-th-success' : 'bg-th-bkg-4'
|
||||
} relative inline-flex h-5 w-10 flex-shrink-0 cursor-pointer rounded-full
|
||||
border-2 border-transparent transition-colors duration-200 ease-in-out
|
||||
focus:outline-none ${disabled ? 'opacity-60' : ''}`}
|
||||
border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-1 focus:outline-offset-2 focus:outline-th-fgd-4 ${
|
||||
disabled ? 'opacity-60' : ''
|
||||
}`}
|
||||
role="switch"
|
||||
aria-checked={checked}
|
||||
onClick={handleClick}
|
||||
|
|
|
@ -128,7 +128,7 @@ const MangoAccountsListModal = ({
|
|||
>
|
||||
<button
|
||||
onClick={() => handleSelectMangoAccount(acc)}
|
||||
className="default-transition flex h-full w-full items-center justify-between rounded-md rounded-r-none bg-th-bkg-2 px-4 text-th-fgd-1 hover:bg-th-bkg-3"
|
||||
className="default-transition flex h-full w-full items-center justify-between rounded-md rounded-r-none border border-th-bkg-4 px-4 text-th-fgd-1 focus:border-th-fgd-4 md:hover:border-th-fgd-4"
|
||||
>
|
||||
<div className="flex w-full items-center justify-between">
|
||||
<div className="flex items-center space-x-2.5">
|
||||
|
@ -190,7 +190,7 @@ const MangoAccountsListModal = ({
|
|||
</div>
|
||||
</div>
|
||||
</button>
|
||||
<div className="flex h-full items-center justify-center rounded-md rounded-l-none bg-th-bkg-3">
|
||||
<div className="flex h-full items-center justify-center rounded-md rounded-l-none border border-l-0 border-th-bkg-4">
|
||||
<Tooltip
|
||||
className="hidden md:block"
|
||||
content={t('copy-address')}
|
||||
|
|
|
@ -20,7 +20,7 @@ const volumeAlertSound = new Howl({
|
|||
export const DEFAULT_VOLUME_ALERT_SETTINGS = { seconds: 30, value: 10000 }
|
||||
|
||||
const INPUT_CLASSES =
|
||||
'h-12 w-full rounded-md border border-th-input-border bg-th-input-bkg px-3 font-mono text-base text-th-fgd-1 focus:border-th-input-border-hover focus:outline-none md:hover:border-th-input-border-hover'
|
||||
'h-12 w-full rounded-md border border-th-input-border bg-th-input-bkg px-3 font-mono text-base text-th-fgd-1 focus:border-th-fgd-4 focus:outline-none md:hover:border-th-input-border-hover'
|
||||
|
||||
const TradeVolumeAlertModal = ({ isOpen, onClose }: ModalProps) => {
|
||||
const { t } = useTranslation(['common', 'trade'])
|
||||
|
|
|
@ -45,6 +45,7 @@ import { isMangoError } from 'types'
|
|||
import ColorBlur from '@components/ColorBlur'
|
||||
import useLocalStorageState from 'hooks/useLocalStorageState'
|
||||
import { ACCEPT_TERMS_KEY } from 'utils/constants'
|
||||
import { ACCOUNT_ACTIONS_NUMBER_FORMAT_CLASSES } from '@components/BorrowForm'
|
||||
|
||||
const UserSetupModal = ({
|
||||
isOpen,
|
||||
|
@ -429,7 +430,7 @@ const UserSetupModal = ({
|
|||
allowNegative={false}
|
||||
isNumericString={true}
|
||||
decimalScale={tokenMax.decimals || 6}
|
||||
className="w-full rounded-lg rounded-l-none border border-th-input-border bg-th-input-bkg p-3 text-right font-mono text-xl text-th-fgd-1 focus:border-th-input-border-hover focus:outline-none md:hover:border-th-input-border-hover"
|
||||
className={ACCOUNT_ACTIONS_NUMBER_FORMAT_CLASSES}
|
||||
placeholder="0.00"
|
||||
value={depositAmount}
|
||||
onValueChange={(e: NumberFormatValues) => {
|
||||
|
|
|
@ -5,6 +5,11 @@ import ChartMiddleOBRight from '@components/icons/ChartMiddleOBRight'
|
|||
import ChartOnLeft from '@components/icons/ChartOnLeft'
|
||||
import ChartOnRight from '@components/icons/ChartOnRight'
|
||||
import Tooltip from '@components/shared/Tooltip'
|
||||
import { TradeLayout } from '@components/trade/TradeAdvancedPage'
|
||||
// import dayjs from 'dayjs'
|
||||
import { ReactNode } from 'react'
|
||||
// import { useRouter } from 'next/router'
|
||||
// import { useCallback } from 'react'
|
||||
import dayjs from 'dayjs'
|
||||
import useLocalStorageState from 'hooks/useLocalStorageState'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
|
@ -74,10 +79,7 @@ const DisplaySettings = () => {
|
|||
TRADE_CHART_UI_KEY,
|
||||
'trading-view'
|
||||
)
|
||||
const [tradeLayout, setTradeLayout] = useLocalStorageState(
|
||||
TRADE_LAYOUT_KEY,
|
||||
'chartLeft'
|
||||
)
|
||||
const [, setTradeLayout] = useLocalStorageState(TRADE_LAYOUT_KEY, 'chartLeft')
|
||||
|
||||
const handleLangChange = useCallback(
|
||||
(l: string) => {
|
||||
|
@ -101,9 +103,7 @@ const DisplaySettings = () => {
|
|||
>
|
||||
{THEMES.map((theme) => (
|
||||
<Select.Option key={theme} value={t(`settings:${theme}`)}>
|
||||
<div className="flex w-full items-center justify-between">
|
||||
{t(`settings:${theme}`)}
|
||||
</div>
|
||||
{t(`settings:${theme}`)}
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
|
@ -111,7 +111,7 @@ const DisplaySettings = () => {
|
|||
</div>
|
||||
<div className="flex flex-col border-t border-th-bkg-3 py-4 md:flex-row md:items-center md:justify-between md:px-4">
|
||||
<p className="mb-2 md:mb-0">{t('settings:language')}</p>
|
||||
<div className="w-full min-w-[330px] md:w-[480px] md:pl-4">
|
||||
<div className="w-full min-w-[220px] md:w-auto md:pl-4">
|
||||
<ButtonGroup
|
||||
activeValue={savedLanguage}
|
||||
onChange={(l) => handleLangChange(l)}
|
||||
|
@ -130,9 +130,7 @@ const DisplaySettings = () => {
|
|||
>
|
||||
{NOTIFICATION_POSITIONS.map((val) => (
|
||||
<Select.Option key={val} value={t(`settings:${val}`)}>
|
||||
<div className="flex w-full items-center justify-between">
|
||||
{t(`settings:${val}`)}
|
||||
</div>
|
||||
{t(`settings:${val}`)}
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
|
@ -142,52 +140,32 @@ const DisplaySettings = () => {
|
|||
<p className="mb-2 md:mb-0">{t('settings:trade-layout')}</p>
|
||||
<div className="flex space-x-3">
|
||||
<Tooltip content={t('settings:chart-left')}>
|
||||
<button
|
||||
className={`flex h-max items-center justify-center rounded border ${
|
||||
tradeLayout === 'chartLeft'
|
||||
? 'border-th-active'
|
||||
: 'border-th-bkg-4 md:hover:border-th-fgd-4'
|
||||
} p-0.5 `}
|
||||
<ChartLayoutButton
|
||||
icon={<ChartOnLeft className="h-auto w-32" />}
|
||||
position="chartLeft"
|
||||
onClick={() => setTradeLayout('chartLeft')}
|
||||
>
|
||||
<ChartOnLeft className="h-auto w-32" />
|
||||
</button>
|
||||
/>
|
||||
</Tooltip>
|
||||
<Tooltip content={t('settings:chart-middle-ob-right')}>
|
||||
<button
|
||||
className={`flex h-max items-center justify-center rounded border ${
|
||||
tradeLayout === 'chartMiddleOBRight'
|
||||
? 'border-th-active'
|
||||
: 'border-th-bkg-4 md:hover:border-th-fgd-4'
|
||||
} p-0.5 `}
|
||||
<ChartLayoutButton
|
||||
icon={<ChartMiddleOBRight className="h-auto w-32" />}
|
||||
position="chartMiddleOBRight"
|
||||
onClick={() => setTradeLayout('chartMiddleOBRight')}
|
||||
>
|
||||
<ChartMiddleOBRight className="h-auto w-32" />
|
||||
</button>
|
||||
/>
|
||||
</Tooltip>
|
||||
<Tooltip content={t('settings:chart-middle-ob-left')}>
|
||||
<button
|
||||
className={`flex h-max items-center justify-center rounded border ${
|
||||
tradeLayout === 'chartMiddleOBLeft'
|
||||
? 'border-th-active'
|
||||
: 'border-th-bkg-4 md:hover:border-th-fgd-4'
|
||||
} p-0.5 `}
|
||||
<ChartLayoutButton
|
||||
icon={<ChartMiddleOBLeft className="h-auto w-32" />}
|
||||
position="chartMiddleOBLeft"
|
||||
onClick={() => setTradeLayout('chartMiddleOBLeft')}
|
||||
>
|
||||
<ChartMiddleOBLeft className="h-auto w-32" />
|
||||
</button>
|
||||
/>
|
||||
</Tooltip>
|
||||
<Tooltip content={t('settings:chart-right')}>
|
||||
<button
|
||||
className={`flex h-max items-center justify-center rounded border ${
|
||||
tradeLayout === 'chartRight'
|
||||
? 'border-th-active'
|
||||
: 'border-th-bkg-4 md:hover:border-th-fgd-4'
|
||||
} p-0.5 `}
|
||||
<ChartLayoutButton
|
||||
icon={<ChartOnRight className="h-auto w-32" />}
|
||||
position="chartRight"
|
||||
onClick={() => setTradeLayout('chartRight')}
|
||||
>
|
||||
<ChartOnRight className="h-auto w-32" />
|
||||
</button>
|
||||
/>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -218,3 +196,27 @@ const DisplaySettings = () => {
|
|||
}
|
||||
|
||||
export default DisplaySettings
|
||||
|
||||
const ChartLayoutButton = ({
|
||||
onClick,
|
||||
icon,
|
||||
position,
|
||||
}: {
|
||||
onClick: (l: TradeLayout) => void
|
||||
icon: ReactNode
|
||||
position: TradeLayout
|
||||
}) => {
|
||||
const [tradeLayout] = useLocalStorageState(TRADE_LAYOUT_KEY, 'chartLeft')
|
||||
return (
|
||||
<button
|
||||
className={`flex h-max items-center justify-center rounded border ${
|
||||
tradeLayout === position
|
||||
? 'border-th-active'
|
||||
: 'border-th-bkg-4 md:hover:border-th-fgd-4'
|
||||
} p-0.5 focus:border-th-fgd-4`}
|
||||
onClick={() => onClick(position)}
|
||||
>
|
||||
{icon}
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { useTheme } from 'next-themes'
|
||||
import { FunctionComponent, ReactNode } from 'react'
|
||||
import { forwardRef, FunctionComponent, ReactNode, Ref } from 'react'
|
||||
|
||||
interface AllButtonProps {
|
||||
onClick?: (e?: React.MouseEvent) => void
|
||||
|
@ -33,8 +33,8 @@ const Button: FunctionComponent<ButtonCombinedProps> = ({
|
|||
disabled={disabled}
|
||||
className={`rounded-md ${
|
||||
secondary
|
||||
? 'border border-th-button md:hover:border-th-button-hover'
|
||||
: 'bg-th-button md:hover:bg-th-button-hover'
|
||||
? 'border border-th-button focus:border-th-fgd-4 md:hover:border-th-button-hover'
|
||||
: 'bg-th-button focus:border focus:border-th-fgd-4 md:hover:bg-th-button-hover'
|
||||
} ${
|
||||
size === 'medium'
|
||||
? 'h-10 px-4'
|
||||
|
@ -45,7 +45,7 @@ const Button: FunctionComponent<ButtonCombinedProps> = ({
|
|||
theme === 'High Contrast' && !secondary
|
||||
? 'text-th-bkg-1'
|
||||
: 'text-th-fgd-1'
|
||||
} disabled:cursor-not-allowed disabled:opacity-60 disabled:hover:brightness-100 ${className}`}
|
||||
} disabled:cursor-not-allowed disabled:opacity-60 ${className}`}
|
||||
type={type}
|
||||
{...props}
|
||||
>
|
||||
|
@ -57,19 +57,16 @@ const Button: FunctionComponent<ButtonCombinedProps> = ({
|
|||
interface IconButtonProps {
|
||||
hideBg?: boolean
|
||||
size?: 'small' | 'medium' | 'large'
|
||||
ref?: Ref<HTMLButtonElement>
|
||||
}
|
||||
|
||||
type IconButtonCombinedProps = AllButtonProps & IconButtonProps
|
||||
|
||||
export const IconButton: FunctionComponent<IconButtonCombinedProps> = ({
|
||||
children,
|
||||
onClick,
|
||||
disabled = false,
|
||||
className,
|
||||
hideBg,
|
||||
size,
|
||||
...props
|
||||
}) => {
|
||||
export const IconButton = forwardRef<
|
||||
HTMLButtonElement,
|
||||
IconButtonCombinedProps
|
||||
>((props, ref) => {
|
||||
const { children, onClick, disabled = false, className, hideBg, size } = props
|
||||
return (
|
||||
<button
|
||||
onClick={onClick}
|
||||
|
@ -85,15 +82,17 @@ export const IconButton: FunctionComponent<IconButtonCombinedProps> = ({
|
|||
} default-transition items-center justify-center rounded-full ${
|
||||
hideBg
|
||||
? 'md:hover:text-th-active'
|
||||
: 'border border-th-button md:hover:border-th-button-hover'
|
||||
: 'border border-th-button focus:border-th-fgd-3 md:hover:border-th-button-hover'
|
||||
} text-th-fgd-1 focus:outline-none disabled:cursor-not-allowed disabled:bg-th-bkg-4
|
||||
disabled:text-th-fgd-4 md:disabled:hover:text-th-fgd-4 ${className}`}
|
||||
{...props}
|
||||
disabled:text-th-fgd-4 md:disabled:hover:text-th-fgd-4 ${className} focus:text-th-active`}
|
||||
ref={ref}
|
||||
>
|
||||
{children}
|
||||
</button>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
IconButton.displayName = 'IconButton'
|
||||
|
||||
interface LinkButtonProps {
|
||||
icon?: ReactNode
|
||||
|
@ -115,7 +114,7 @@ export const LinkButton: FunctionComponent<LinkButtonCombinedProps> = ({
|
|||
disabled={disabled}
|
||||
className={`default-transition flex items-center border-0 font-bold ${
|
||||
secondary ? 'text-th-active' : 'text-th-fgd-2'
|
||||
} underline focus:outline-none disabled:cursor-not-allowed disabled:opacity-50 md:hover:no-underline ${className}`}
|
||||
} rounded-sm underline focus:text-th-active focus:no-underline disabled:cursor-not-allowed disabled:opacity-50 md:hover:no-underline ${className}`}
|
||||
{...props}
|
||||
type="button"
|
||||
>
|
||||
|
|
|
@ -19,7 +19,7 @@ const ChartRangeButtons: FunctionComponent<ChartRangeButtonsProps> = ({
|
|||
<div className="relative flex">
|
||||
{activeValue && values.includes(activeValue) ? (
|
||||
<div
|
||||
className={`default-transition absolute left-0 top-0 h-full transform rounded-md bg-th-bkg-3`}
|
||||
className="default-transition absolute left-0 top-0 h-full transform rounded-md bg-th-bkg-3"
|
||||
style={{
|
||||
transform: `translateX(${
|
||||
values.findIndex((v) => v === activeValue) * 100
|
||||
|
@ -30,7 +30,7 @@ const ChartRangeButtons: FunctionComponent<ChartRangeButtonsProps> = ({
|
|||
) : null}
|
||||
{values.map((v, i) => (
|
||||
<button
|
||||
className={`${className} default-transition relative h-6 cursor-pointer rounded-md px-3 text-center text-xs
|
||||
className={`${className} default-transition relative h-6 cursor-pointer rounded-md px-3 text-center text-xs focus:bg-th-bkg-3 focus:text-th-fgd-1
|
||||
${
|
||||
v === activeValue
|
||||
? `text-th-active`
|
||||
|
|
|
@ -27,14 +27,14 @@ const FavoriteMarketButton = ({
|
|||
(marketName: string) => marketName === market.name
|
||||
) ? (
|
||||
<button
|
||||
className="default-transition flex items-center justify-center text-th-active md:hover:text-th-fgd-3"
|
||||
className="default-transition flex items-center justify-center text-th-active focus:text-th-fgd-4 md:hover:text-th-fgd-3"
|
||||
onClick={() => removeFromFavorites(market.name)}
|
||||
>
|
||||
<FilledStarIcon className="h-5 w-5" />
|
||||
</button>
|
||||
) : (
|
||||
<button
|
||||
className="default-transition flex items-center justify-center text-th-fgd-4 md:hover:text-th-active"
|
||||
className="default-transition flex items-center justify-center text-th-fgd-4 focus:text-th-active md:hover:text-th-active"
|
||||
onClick={() => addToFavorites(market.name)}
|
||||
>
|
||||
<StarIcon className="h-5 w-5" />
|
||||
|
|
|
@ -46,7 +46,9 @@ const IconDropMenu = ({
|
|||
: size === 'medium'
|
||||
? 'h-10 w-10'
|
||||
: 'h-8 w-8'
|
||||
} default-transition items-center justify-center rounded-full border border-th-button text-th-fgd-1 md:hover:border-th-button-hover md:hover:text-th-fgd-1 ${
|
||||
} default-transition items-center justify-center rounded-full border border-th-button text-th-fgd-1 ${
|
||||
!open ? 'focus:border-th-fgd-2' : ''
|
||||
} md:hover:border-th-button-hover md:hover:text-th-fgd-1 ${
|
||||
disabled ? 'cursor-not-allowed opacity-60' : ''
|
||||
}`}
|
||||
disabled={disabled}
|
||||
|
|
|
@ -57,7 +57,7 @@ const LeverageSlider = ({
|
|||
min="0"
|
||||
max={leverageMax}
|
||||
step={step}
|
||||
className="w-full"
|
||||
className="w-full focus:outline-none"
|
||||
onChange={handleSliderChange}
|
||||
value={value}
|
||||
></input>
|
||||
|
|
|
@ -19,12 +19,12 @@ const MaxAmountButton = ({
|
|||
}) => {
|
||||
return (
|
||||
<LinkButton
|
||||
className={`font-normal no-underline ${className}`}
|
||||
className={`font-normal no-underline ${className} md:hover:text-th-fgd-3`}
|
||||
disabled={disabled}
|
||||
onClick={onClick}
|
||||
>
|
||||
<p className="mr-1 text-th-fgd-4">{label}:</p>
|
||||
<span className="font-mono text-th-fgd-2 underline">
|
||||
<span className="font-mono">
|
||||
<FormatNumericValue value={value} decimals={decimals} />
|
||||
</span>
|
||||
</LinkButton>
|
||||
|
|
|
@ -47,15 +47,15 @@ function Modal({
|
|||
: 'p-4 pt-6 sm:h-auto sm:max-w-md sm:rounded-lg sm:border sm:border-th-bkg-3 sm:p-6'
|
||||
} relative `}
|
||||
>
|
||||
<div>{children}</div>
|
||||
{!hideClose ? (
|
||||
<button
|
||||
onClick={onClose}
|
||||
className={`absolute right-4 top-4 z-40 text-th-fgd-4 focus:outline-none sm:right-2 sm:top-2 md:hover:text-th-active`}
|
||||
className={`absolute right-4 top-4 z-40 text-th-fgd-4 focus:text-th-active focus:outline-none sm:right-2 sm:top-2 md:hover:text-th-active`}
|
||||
>
|
||||
<XMarkIcon className={`h-6 w-6`} />
|
||||
</button>
|
||||
) : null}
|
||||
<div>{children}</div>
|
||||
</Dialog.Panel>
|
||||
</div>
|
||||
</Dialog>
|
||||
|
|
|
@ -25,7 +25,7 @@ const TabButtons = <T extends Values>({
|
|||
{values.map(([label, count], i) => (
|
||||
<div className={fillWidth ? 'flex-1' : ''} key={`${label}` + i}>
|
||||
<button
|
||||
className={`default-transition flex h-12 w-full items-center justify-center px-4 font-normal md:px-6 ${
|
||||
className={`default-transition flex h-12 w-full items-center justify-center px-4 font-normal focus:bg-th-bkg-2 md:px-6 ${
|
||||
rounded ? 'rounded-md' : 'rounded-none'
|
||||
} ${
|
||||
showBorders
|
||||
|
@ -39,8 +39,8 @@ const TabButtons = <T extends Values>({
|
|||
? 'bg-th-up-dark font-display text-th-fgd-1'
|
||||
: label === 'sell'
|
||||
? 'bg-th-down-dark font-display text-th-fgd-1'
|
||||
: 'bg-th-bkg-2 text-th-active'
|
||||
: 'hover:cursor-pointer hover:text-th-fgd-2'
|
||||
: 'bg-th-bkg-2 text-th-active focus:text-th-active'
|
||||
: 'hover:cursor-pointer hover:text-th-fgd-2 focus:text-th-fgd-1'
|
||||
}`}
|
||||
key={`${label}${i}`}
|
||||
onClick={() => onChange(label)}
|
||||
|
|
|
@ -54,11 +54,11 @@ const TabUnderline = <T extends Values>({
|
|||
${
|
||||
activeValue === value
|
||||
? activeValue === 'buy'
|
||||
? 'text-th-up'
|
||||
? 'text-th-up focus:text-th-up'
|
||||
: activeValue === 'sell'
|
||||
? 'text-th-down'
|
||||
: 'text-th-active'
|
||||
: 'text-th-fgd-4 hover:text-th-fgd-3'
|
||||
? 'text-th-down focus:text-th-down'
|
||||
: 'text-th-active focus:text-th-active'
|
||||
: 'text-th-fgd-4 focus:text-th-fgd-1 md:hover:text-th-fgd-3'
|
||||
}
|
||||
`}
|
||||
key={`${value}` + i}
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
import { ChevronDownIcon } from '@heroicons/react/20/solid'
|
||||
import Image from 'next/image'
|
||||
|
||||
const TokenListButton = ({
|
||||
logoUri,
|
||||
token,
|
||||
setShowList,
|
||||
}: {
|
||||
logoUri: string | undefined
|
||||
token: string
|
||||
setShowList: (x: boolean) => void
|
||||
}) => {
|
||||
return (
|
||||
<button
|
||||
onClick={() => setShowList(true)}
|
||||
className="default-transition flex h-full w-full items-center rounded-lg rounded-r-none border border-th-input-border bg-th-input-bkg py-2 px-3 text-th-fgd-2 hover:cursor-pointer hover:bg-th-bkg-2 hover:text-th-fgd-1 focus:border-th-fgd-4"
|
||||
>
|
||||
<div className="mr-2.5 flex min-w-[24px] items-center">
|
||||
<Image
|
||||
alt=""
|
||||
width="24"
|
||||
height="24"
|
||||
src={logoUri || `/icons/${token.toLowerCase()}.svg`}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex w-full items-center justify-between">
|
||||
<div className="text-xl font-bold">{token}</div>
|
||||
<ChevronDownIcon className="h-6 w-6" />
|
||||
</div>
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
||||
export default TokenListButton
|
|
@ -24,7 +24,6 @@ import Button, { IconButton } from '../shared/Button'
|
|||
import Loading from '../shared/Loading'
|
||||
import { EnterBottomExitBottom } from '../shared/Transitions'
|
||||
import useQuoteRoutes from './useQuoteRoutes'
|
||||
import SheenLoader from '../shared/SheenLoader'
|
||||
import { HealthType } from '@blockworks-foundation/mango-v4'
|
||||
import {
|
||||
INPUT_TOKEN_DEFAULT,
|
||||
|
@ -57,6 +56,9 @@ export const withValueLimit = (values: NumberFormatValues): boolean => {
|
|||
: true
|
||||
}
|
||||
|
||||
const NUMBER_FORMAT_CLASSNAMES =
|
||||
'default-transition w-full rounded-lg rounded-l-none border border-th-input-border bg-th-input-bkg p-3 text-right font-mono text-xl text-th-fgd-1 focus:border-th-fgd-4 focus:outline-none md:hover:border-th-input-border-hover md:hover:focus:border-th-fgd-4'
|
||||
|
||||
const set = mangoStore.getState().set
|
||||
|
||||
const SwapForm = () => {
|
||||
|
@ -338,7 +340,7 @@ const SwapForm = () => {
|
|||
) : null}
|
||||
</div>
|
||||
<div className="mb-3 grid grid-cols-2" id="swap-step-two">
|
||||
<div className="col-span-1 rounded-lg rounded-r-none border border-r-0 border-th-input-border bg-th-input-bkg">
|
||||
<div className="col-span-1">
|
||||
<TokenSelect
|
||||
bank={
|
||||
inputBank ||
|
||||
|
@ -357,7 +359,7 @@ const SwapForm = () => {
|
|||
decimalScale={inputBank?.mintDecimals || 6}
|
||||
name="amountIn"
|
||||
id="amountIn"
|
||||
className="w-full rounded-l-none rounded-r-lg border border-th-input-border bg-th-input-bkg p-3 text-right font-mono text-base font-bold text-th-fgd-1 focus:outline-none lg:text-lg xl:text-xl"
|
||||
className={NUMBER_FORMAT_CLASSNAMES}
|
||||
placeholder="0.00"
|
||||
value={amountInFormValue}
|
||||
onValueChange={handleAmountInChange}
|
||||
|
@ -367,7 +369,7 @@ const SwapForm = () => {
|
|||
</div>
|
||||
<div className="-mb-2 flex justify-center">
|
||||
<button
|
||||
className="rounded-full border border-th-bkg-4 p-1.5 text-th-fgd-3 md:hover:text-th-active"
|
||||
className="rounded-full border border-th-bkg-4 p-1.5 text-th-fgd-3 focus:border-th-fgd-4 md:hover:text-th-active"
|
||||
onClick={handleSwitchTokens}
|
||||
>
|
||||
<ArrowDownIcon
|
||||
|
@ -382,7 +384,7 @@ const SwapForm = () => {
|
|||
</div>
|
||||
<p className="mb-2 text-th-fgd-2 lg:text-base">{t('swap:receive')}</p>
|
||||
<div id="swap-step-three" className="mb-3 grid grid-cols-2">
|
||||
<div className="col-span-1 rounded-lg rounded-r-none border border-r-0 border-th-input-border bg-th-input-bkg">
|
||||
<div className="col-span-1">
|
||||
<TokenSelect
|
||||
bank={
|
||||
outputBank ||
|
||||
|
@ -392,12 +394,10 @@ const SwapForm = () => {
|
|||
type="output"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex h-[54px] w-full items-center justify-end rounded-r-lg border border-th-input-border text-right text-lg font-bold text-th-fgd-3 xl:text-xl">
|
||||
<div className="col-span-1 flex h-[54px]">
|
||||
{loadingSwapDetails ? (
|
||||
<div className="w-full">
|
||||
<SheenLoader className="flex flex-1 rounded-l-none">
|
||||
<div className="h-[52px] w-full rounded-r-lg bg-th-bkg-4" />
|
||||
</SheenLoader>
|
||||
<div className="flex w-full items-center justify-center rounded-l-none rounded-r-lg border border-th-input-border bg-th-bkg-2">
|
||||
<Loading />
|
||||
</div>
|
||||
) : (
|
||||
<NumberFormat
|
||||
|
@ -408,7 +408,7 @@ const SwapForm = () => {
|
|||
decimalScale={outputBank?.mintDecimals || 6}
|
||||
name="amountOut"
|
||||
id="amountOut"
|
||||
className="w-full rounded-l-none rounded-r-lg bg-th-input-bkg p-3 text-right font-mono text-base font-bold text-th-fgd-1 focus:outline-none lg:text-lg xl:text-xl"
|
||||
className={NUMBER_FORMAT_CLASSNAMES}
|
||||
placeholder="0.00"
|
||||
value={amountOutFormValue}
|
||||
onValueChange={handleAmountOutChange}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { memo, useMemo, useEffect } from 'react'
|
||||
import { memo, useMemo, useEffect, useRef } from 'react'
|
||||
import { Token } from '../../types/jupiter'
|
||||
import mangoStore from '@store/mangoStore'
|
||||
import { IconButton } from '../shared/Button'
|
||||
|
@ -133,6 +133,7 @@ const SwapFormTokenList = ({
|
|||
const outputBank = mangoStore((s) => s.swap.outputBank)
|
||||
const { group } = useMangoGroup()
|
||||
const { mangoAccount } = useMangoAccount()
|
||||
const focusRef = useRef<HTMLButtonElement>(null)
|
||||
|
||||
// const popularTokens = useMemo(() => {
|
||||
// return tokens.filter((token) => {
|
||||
|
@ -202,6 +203,12 @@ const SwapFormTokenList = ({
|
|||
// const sortedTokens = search ? startSearch(tokenInfos, search) : tokenInfos
|
||||
const sortedTokens = tokenInfos
|
||||
|
||||
useEffect(() => {
|
||||
if (focusRef?.current) {
|
||||
focusRef.current.focus()
|
||||
}
|
||||
}, [focusRef])
|
||||
|
||||
return (
|
||||
<>
|
||||
<p className="mb-3">
|
||||
|
@ -215,6 +222,7 @@ const SwapFormTokenList = ({
|
|||
className="absolute top-2 right-2 text-th-fgd-3 hover:text-th-fgd-2"
|
||||
onClick={onClose}
|
||||
hideBg
|
||||
ref={focusRef}
|
||||
>
|
||||
<XMarkIcon className="h-6 w-6" />
|
||||
</IconButton>
|
||||
|
|
|
@ -4,6 +4,7 @@ import React, {
|
|||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react'
|
||||
import {
|
||||
|
@ -199,6 +200,7 @@ const SwapReviewRouteInfo = ({
|
|||
SOUND_SETTINGS_KEY,
|
||||
INITIAL_SOUND_SETTINGS
|
||||
)
|
||||
const focusRef = useRef<HTMLButtonElement>(null)
|
||||
|
||||
const inputTokenIconUri = useMemo(() => {
|
||||
return inputTokenInfo ? inputTokenInfo.logoURI : ''
|
||||
|
@ -211,6 +213,12 @@ const SwapReviewRouteInfo = ({
|
|||
)
|
||||
}, [selectedRoute, outputTokenInfo])
|
||||
|
||||
useEffect(() => {
|
||||
if (focusRef?.current) {
|
||||
focusRef.current.focus()
|
||||
}
|
||||
}, [focusRef])
|
||||
|
||||
useEffect(() => {
|
||||
setCoingeckoPrices(EMPTY_COINGECKO_PRICES)
|
||||
const fetchTokenPrices = async () => {
|
||||
|
@ -354,6 +362,7 @@ const SwapReviewRouteInfo = ({
|
|||
className="absolute top-4 left-4 mr-3 text-th-fgd-2"
|
||||
onClick={onClose}
|
||||
size="small"
|
||||
ref={focusRef}
|
||||
>
|
||||
<ArrowLeftIcon className="h-5 w-5" />
|
||||
</IconButton>
|
||||
|
@ -570,7 +579,11 @@ const SwapReviewRouteInfo = ({
|
|||
<Disclosure>
|
||||
{({ open }) => (
|
||||
<>
|
||||
<Disclosure.Button className="default-transition flex w-full items-center justify-between rounded-md p-3">
|
||||
<Disclosure.Button
|
||||
className={`default-transition flex w-full items-center justify-between rounded-md p-3 focus:bg-th-bkg-3 ${
|
||||
open ? 'mb-2 rounded-b-none' : ''
|
||||
}`}
|
||||
>
|
||||
<p>{open ? t('swap:hide-fees') : t('swap:show-fees')}</p>
|
||||
<ChevronDownIcon
|
||||
className={`${
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { XMarkIcon } from '@heroicons/react/20/solid'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import mangoStore from '@store/mangoStore'
|
||||
import ButtonGroup from '../forms/ButtonGroup'
|
||||
import Input from '../forms/Input'
|
||||
|
@ -14,6 +14,7 @@ const SwapSettings = ({ onClose }: { onClose: () => void }) => {
|
|||
const margin = mangoStore((s) => s.swap.margin)
|
||||
const slippage = mangoStore((s) => s.swap.slippage)
|
||||
const set = mangoStore((s) => s.set)
|
||||
const focusRef = useRef<HTMLButtonElement>(null)
|
||||
|
||||
const [showCustomSlippageForm, setShowCustomSlippageForm] = useState(false)
|
||||
const [inputValue, setInputValue] = useState(slippage.toString())
|
||||
|
@ -36,10 +37,21 @@ const SwapSettings = ({ onClose }: { onClose: () => void }) => {
|
|||
})
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (focusRef?.current) {
|
||||
focusRef.current.focus()
|
||||
}
|
||||
}, [focusRef])
|
||||
|
||||
return (
|
||||
<>
|
||||
<h3 className="mb-3">{t('settings')}</h3>
|
||||
<IconButton className="absolute top-2 right-2" onClick={onClose} hideBg>
|
||||
<IconButton
|
||||
className="absolute top-2 right-2"
|
||||
onClick={onClose}
|
||||
hideBg
|
||||
ref={focusRef}
|
||||
>
|
||||
<XMarkIcon className="h-6 w-6" />
|
||||
</IconButton>
|
||||
|
||||
|
|
|
@ -28,10 +28,9 @@ const TokenSelect = ({ bank, showTokenList, type }: TokenSelectProps) => {
|
|||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
<button
|
||||
onClick={() => showTokenList(type)}
|
||||
className="default-transition flex h-full items-center rounded-lg rounded-r-none p-3 text-th-fgd-2 hover:cursor-pointer hover:bg-th-bkg-2 hover:text-th-fgd-1"
|
||||
role="button"
|
||||
className="default-transition flex h-full w-full items-center rounded-lg rounded-r-none border border-th-input-border bg-th-input-bkg py-2 px-3 text-th-fgd-2 hover:cursor-pointer hover:bg-th-bkg-2 hover:text-th-fgd-1 focus:border-th-fgd-4"
|
||||
>
|
||||
<div className="mr-2.5 flex min-w-[24px] items-center">
|
||||
{logoURI ? (
|
||||
|
@ -44,7 +43,7 @@ const TokenSelect = ({ bank, showTokenList, type }: TokenSelectProps) => {
|
|||
<div className="text-xl font-bold text-th-fgd-1">{bank?.name}</div>
|
||||
<ChevronDownIcon className="h-6 w-6" />
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -64,6 +64,12 @@ const successSound = new Howl({
|
|||
volume: 0.5,
|
||||
})
|
||||
|
||||
const INPUT_SUFFIX_CLASSNAMES =
|
||||
'absolute right-[1px] top-1/2 flex h-[calc(100%-2px)] -translate-y-1/2 items-center rounded-r-md bg-th-input-bkg px-2 text-xs font-normal text-th-fgd-4'
|
||||
|
||||
const INPUT_PREFIX_CLASSNAMES =
|
||||
'absolute left-2 top-1/2 h-5 w-5 flex-shrink-0 -translate-y-1/2'
|
||||
|
||||
const DEFAULT_CHECKBOX_SETTINGS = {
|
||||
ioc: false,
|
||||
post: false,
|
||||
|
@ -498,9 +504,9 @@ const AdvancedTradeForm = () => {
|
|||
{t('trade:limit-price')}
|
||||
</p>
|
||||
</div>
|
||||
<div className="default-transition flex items-center rounded-md border border-th-input-border bg-th-input-bkg p-2 text-sm font-bold text-th-fgd-1 md:hover:border-th-input-border-hover lg:text-base">
|
||||
<div className="relative">
|
||||
{quoteLogoURI ? (
|
||||
<div className="h-5 w-5 flex-shrink-0">
|
||||
<div className={INPUT_PREFIX_CLASSNAMES}>
|
||||
<Image alt="" width="20" height="20" src={quoteLogoURI} />
|
||||
</div>
|
||||
) : (
|
||||
|
@ -516,14 +522,12 @@ const AdvancedTradeForm = () => {
|
|||
decimalScale={tickDecimals}
|
||||
name="price"
|
||||
id="price"
|
||||
className="ml-2 w-full bg-transparent font-mono focus:outline-none"
|
||||
className="default-transition flex w-full items-center rounded-md border border-th-input-border bg-th-input-bkg p-2 pl-9 font-mono text-sm font-bold text-th-fgd-1 focus:border-th-fgd-4 focus:outline-none md:hover:border-th-input-border-hover md:hover:focus:border-th-fgd-4 lg:text-base"
|
||||
placeholder="0.00"
|
||||
value={tradeForm.price}
|
||||
onValueChange={handlePriceChange}
|
||||
/>
|
||||
<div className="text-xs font-normal text-th-fgd-4">
|
||||
{quoteSymbol}
|
||||
</div>
|
||||
<div className={INPUT_SUFFIX_CLASSNAMES}>{quoteSymbol}</div>
|
||||
</div>
|
||||
</>
|
||||
) : null}
|
||||
|
@ -533,11 +537,24 @@ const AdvancedTradeForm = () => {
|
|||
useMargin={savedCheckboxSettings.margin}
|
||||
/>
|
||||
<div className="flex flex-col">
|
||||
<div className="default-transition flex items-center rounded-md rounded-b-none border border-th-input-border bg-th-input-bkg p-2 text-sm font-bold text-th-fgd-1 md:hover:z-10 md:hover:border-th-input-border-hover lg:text-base">
|
||||
<div className="h-5 w-5 flex-shrink-0">
|
||||
<div className="relative">
|
||||
<NumberFormat
|
||||
inputMode="decimal"
|
||||
thousandSeparator=","
|
||||
allowNegative={false}
|
||||
isNumericString={true}
|
||||
decimalScale={minOrderDecimals}
|
||||
name="base"
|
||||
id="base"
|
||||
className="default-transition relative flex w-full items-center rounded-md rounded-b-none border border-th-input-border bg-th-input-bkg p-2 pl-9 font-mono text-sm font-bold text-th-fgd-1 focus:z-10 focus:border-th-fgd-4 focus:outline-none md:hover:z-10 md:hover:border-th-input-border-hover md:hover:focus:border-th-fgd-4 lg:text-base"
|
||||
placeholder="0.00"
|
||||
value={tradeForm.baseSize}
|
||||
onValueChange={handleBaseSizeChange}
|
||||
/>
|
||||
<div className={`z-10 ${INPUT_PREFIX_CLASSNAMES}`}>
|
||||
<LogoWithFallback
|
||||
alt=""
|
||||
className="z-10 drop-shadow-md"
|
||||
className="drop-shadow-md"
|
||||
width={'24'}
|
||||
height={'24'}
|
||||
src={baseLogoURI || `/icons/${baseSymbol?.toLowerCase()}.svg`}
|
||||
|
@ -548,26 +565,13 @@ const AdvancedTradeForm = () => {
|
|||
}
|
||||
/>
|
||||
</div>
|
||||
<NumberFormat
|
||||
inputMode="decimal"
|
||||
thousandSeparator=","
|
||||
allowNegative={false}
|
||||
isNumericString={true}
|
||||
decimalScale={minOrderDecimals}
|
||||
name="base"
|
||||
id="base"
|
||||
className="ml-2 w-full bg-transparent font-mono focus:outline-none"
|
||||
placeholder="0.00"
|
||||
value={tradeForm.baseSize}
|
||||
onValueChange={handleBaseSizeChange}
|
||||
/>
|
||||
<div className="text-xs font-normal text-th-fgd-4">
|
||||
<div className={`z-10 ${INPUT_SUFFIX_CLASSNAMES}`}>
|
||||
{baseSymbol}
|
||||
</div>
|
||||
</div>
|
||||
<div className="default-transition -mt-[1px] flex items-center rounded-md rounded-t-none border border-th-input-border bg-th-input-bkg p-2 text-sm font-bold text-th-fgd-1 md:hover:border-th-input-border-hover lg:text-base">
|
||||
<div className="relative">
|
||||
{quoteLogoURI ? (
|
||||
<div className="h-5 w-5 flex-shrink-0">
|
||||
<div className={INPUT_PREFIX_CLASSNAMES}>
|
||||
<Image alt="" width="20" height="20" src={quoteLogoURI} />
|
||||
</div>
|
||||
) : (
|
||||
|
@ -583,14 +587,12 @@ const AdvancedTradeForm = () => {
|
|||
decimalScale={tickDecimals}
|
||||
name="quote"
|
||||
id="quote"
|
||||
className="ml-2 w-full bg-transparent font-mono focus:outline-none"
|
||||
className="default-transition -mt-[1px] flex w-full items-center rounded-md rounded-t-none border border-th-input-border bg-th-input-bkg p-2 pl-9 font-mono text-sm font-bold text-th-fgd-1 focus:border-th-fgd-4 focus:outline-none md:hover:border-th-input-border-hover md:hover:focus:border-th-fgd-4 lg:text-base"
|
||||
placeholder="0.00"
|
||||
value={tradeForm.quoteSize}
|
||||
onValueChange={handleQuoteSizeChange}
|
||||
/>
|
||||
<div className="text-xs font-normal text-th-fgd-4">
|
||||
{quoteSymbol}
|
||||
</div>
|
||||
<div className={INPUT_SUFFIX_CLASSNAMES}>{quoteSymbol}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -704,8 +706,8 @@ const AdvancedTradeForm = () => {
|
|||
!connected
|
||||
? ''
|
||||
: tradeForm.side === 'buy'
|
||||
? 'bg-th-up-dark text-white md:hover:bg-th-up'
|
||||
: 'bg-th-down-dark text-white md:hover:bg-th-down'
|
||||
? 'bg-th-up-dark text-white md:hover:bg-th-up-dark md:hover:brightness-90'
|
||||
: 'bg-th-down text-white md:hover:bg-th-down md:hover:brightness-90'
|
||||
}`}
|
||||
disabled={connected && (!tradeForm.baseSize || !tradeForm.price)}
|
||||
size="large"
|
||||
|
|
|
@ -34,17 +34,19 @@ const FavoriteMarketsBar = () => {
|
|||
market = group?.getSerum3MarketByName(mkt)
|
||||
}
|
||||
return (
|
||||
<Link href={`/trade?name=${mkt}`} key={mkt} shallow={true}>
|
||||
<div
|
||||
className={`default-transition flex items-center whitespace-nowrap py-1 text-xs hover:text-th-active hover:opacity-100 ${
|
||||
selectedMarket && selectedMarket.name === mkt
|
||||
? 'text-th-active'
|
||||
: 'text-th-fgd-1 opacity-60'
|
||||
}`}
|
||||
>
|
||||
{market ? <MarketLogos market={market} size="small" /> : null}
|
||||
<span className="mb-0 mr-1.5 text-xs">{mkt}</span>
|
||||
{/* {change24h ? (
|
||||
<Link
|
||||
className={`default-transition flex items-center whitespace-nowrap py-1 text-xs hover:text-th-active hover:opacity-100 focus:text-th-fgd-1 focus:opacity-100 focus:outline-none ${
|
||||
selectedMarket && selectedMarket.name === mkt
|
||||
? 'text-th-active'
|
||||
: 'text-th-fgd-1 opacity-60'
|
||||
}`}
|
||||
href={`/trade?name=${mkt}`}
|
||||
key={mkt}
|
||||
shallow={true}
|
||||
>
|
||||
{market ? <MarketLogos market={market} size="small" /> : null}
|
||||
<span className="mb-0 mr-1.5 text-xs">{mkt}</span>
|
||||
{/* {change24h ? (
|
||||
<div
|
||||
className={`text-xs ${
|
||||
change24h
|
||||
|
@ -57,7 +59,6 @@ const FavoriteMarketsBar = () => {
|
|||
{`${(change24h * 100).toFixed(1)}%`}
|
||||
</div>
|
||||
) : null} */}
|
||||
</div>
|
||||
</Link>
|
||||
)
|
||||
})}
|
||||
|
|
|
@ -30,7 +30,7 @@ const GroupSize = ({
|
|||
{({ open }) => (
|
||||
<>
|
||||
<Listbox.Button
|
||||
className={`default-transition flex h-6 items-center rounded bg-th-bkg-1 py-1 font-normal text-th-fgd-2 hover:text-th-active focus:border-th-bkg-4 focus:outline-none`}
|
||||
className={`default-transition flex h-6 items-center rounded bg-th-bkg-1 py-1 pl-1.5 font-normal text-th-fgd-2 hover:text-th-active focus:border-th-bkg-4 focus:bg-th-bkg-3 focus:outline-none`}
|
||||
>
|
||||
<div
|
||||
className={`flex items-center justify-between font-mono text-xs leading-none`}
|
||||
|
|
|
@ -55,10 +55,10 @@ const MarketSelectDropdown = () => {
|
|||
<Popover>
|
||||
{({ open, close }) => (
|
||||
<div
|
||||
className="relative flex flex-col overflow-visible"
|
||||
className="relative -ml-2 flex flex-col overflow-visible"
|
||||
id="trade-step-one"
|
||||
>
|
||||
<Popover.Button className="default-transition flex h-12 items-center justify-between hover:text-th-active">
|
||||
<Popover.Button className="default-transition -ml-4 flex h-12 items-center justify-between px-4 hover:text-th-active focus:bg-th-bkg-3">
|
||||
<div className="flex items-center">
|
||||
{selectedMarket ? <MarketLogos market={selectedMarket} /> : null}
|
||||
<div className="whitespace-nowrap text-xl font-bold text-th-fgd-1 md:text-base">
|
||||
|
@ -91,24 +91,15 @@ const MarketSelectDropdown = () => {
|
|||
}}
|
||||
>
|
||||
<Link
|
||||
className="default-transition flex items-center hover:cursor-pointer focus:text-th-active focus:outline-none md:hover:text-th-fgd-3"
|
||||
href={{
|
||||
pathname: '/trade',
|
||||
query: { name: m.name },
|
||||
}}
|
||||
shallow={true}
|
||||
>
|
||||
<div className="default-transition flex items-center hover:cursor-pointer md:hover:text-th-fgd-3">
|
||||
<MarketLogos market={m} />
|
||||
<span
|
||||
className={
|
||||
m.name === selectedMarket?.name
|
||||
? 'text-th-active'
|
||||
: ''
|
||||
}
|
||||
>
|
||||
{m.name}
|
||||
</span>
|
||||
</div>
|
||||
<MarketLogos market={m} />
|
||||
<span>{m.name}</span>
|
||||
</Link>
|
||||
<div className="flex items-center space-x-3">
|
||||
{!loadingPerpStats ? (
|
||||
|
@ -155,24 +146,15 @@ const MarketSelectDropdown = () => {
|
|||
}}
|
||||
>
|
||||
<Link
|
||||
className="default-transition flex items-center hover:cursor-pointer focus:text-th-active focus:outline-none md:hover:text-th-fgd-3"
|
||||
href={{
|
||||
pathname: '/trade',
|
||||
query: { name: m.name },
|
||||
}}
|
||||
shallow={true}
|
||||
>
|
||||
<div className="default-transition flex items-center hover:cursor-pointer md:hover:text-th-fgd-3">
|
||||
<MarketLogos market={m} />
|
||||
<span
|
||||
className={
|
||||
m.name === selectedMarket?.name
|
||||
? 'text-th-active'
|
||||
: ''
|
||||
}
|
||||
>
|
||||
{m.name}
|
||||
</span>
|
||||
</div>
|
||||
<MarketLogos market={m} />
|
||||
<span>{m.name}</span>
|
||||
</Link>
|
||||
<div className="flex items-center space-x-3">
|
||||
{!loadingPrices ? (
|
||||
|
|
|
@ -497,7 +497,7 @@ const Orderbook = () => {
|
|||
<button
|
||||
className={`rounded ${
|
||||
showAsks ? 'bg-th-bkg-3' : 'bg-th-bkg-2'
|
||||
} default-transition flex h-6 w-6 items-center justify-center hover:border-th-fgd-4 focus:outline-none disabled:cursor-not-allowed`}
|
||||
} default-transition flex h-6 w-6 items-center justify-center hover:border-th-fgd-4 focus:bg-th-bkg-4 focus:outline-none disabled:cursor-not-allowed`}
|
||||
onClick={() => toggleSides('bids')}
|
||||
>
|
||||
<OrderbookIcon className="h-4 w-4" side="buy" />
|
||||
|
@ -511,7 +511,7 @@ const Orderbook = () => {
|
|||
<button
|
||||
className={`rounded ${
|
||||
showBids ? 'bg-th-bkg-3' : 'bg-th-bkg-2'
|
||||
} default-transition flex h-6 w-6 items-center justify-center hover:border-th-fgd-4 focus:outline-none disabled:cursor-not-allowed`}
|
||||
} default-transition flex h-6 w-6 items-center justify-center hover:border-th-fgd-4 focus:bg-th-bkg-4 focus:outline-none disabled:cursor-not-allowed`}
|
||||
onClick={() => toggleSides('asks')}
|
||||
>
|
||||
<OrderbookIcon className="h-4 w-4" side="sell" />
|
||||
|
@ -523,7 +523,7 @@ const Orderbook = () => {
|
|||
placement="bottom"
|
||||
>
|
||||
<button
|
||||
className="default-transition flex h-6 w-6 items-center justify-center rounded bg-th-bkg-3 hover:border-th-fgd-4 focus:outline-none disabled:cursor-not-allowed"
|
||||
className="default-transition flex h-6 w-6 items-center justify-center rounded bg-th-bkg-3 hover:border-th-fgd-4 focus:bg-th-bkg-4 focus:outline-none disabled:cursor-not-allowed"
|
||||
onClick={resetOrderbook}
|
||||
>
|
||||
<ArrowPathIcon className="h-4 w-4" />
|
||||
|
|
|
@ -17,7 +17,7 @@ import FavoriteMarketsBar from './FavoriteMarketsBar'
|
|||
import useLocalStorageState from 'hooks/useLocalStorageState'
|
||||
import { TRADE_LAYOUT_KEY } from 'utils/constants'
|
||||
|
||||
type TradeLayout =
|
||||
export type TradeLayout =
|
||||
| 'chartLeft'
|
||||
| 'chartMiddleOBRight'
|
||||
| 'chartMiddleOBLeft'
|
||||
|
|
|
@ -25,42 +25,40 @@ export const ConnectWalletButton: React.FC = () => {
|
|||
<button
|
||||
onClick={handleConnect}
|
||||
disabled={!groupLoaded}
|
||||
className={` text-white focus:outline-none disabled:cursor-wait disabled:opacity-25`}
|
||||
className="relative flex h-16 w-44 bg-th-bkg-3 py-2 text-white before:absolute before:inset-0 before:bg-gradient-to-r before:from-transparent before:via-th-bkg-4 before:to-transparent before:opacity-0 hover:overflow-hidden hover:before:-translate-x-full hover:before:animate-[shimmer_0.75s_normal] hover:before:opacity-100 focus:bg-th-bkg-4 disabled:cursor-wait disabled:opacity-25"
|
||||
>
|
||||
<div className="relative flex h-16 w-44 bg-th-bkg-3 py-2 before:absolute before:inset-0 before:bg-gradient-to-r before:from-transparent before:via-th-bkg-4 before:to-transparent before:opacity-0 hover:overflow-hidden hover:before:-translate-x-full hover:before:animate-[shimmer_0.75s_normal] hover:before:opacity-100">
|
||||
<div className="default-transition relative z-10 flex h-full items-center justify-center space-x-3 px-4">
|
||||
{connecting ? (
|
||||
<Loading className="h-[28px] w-[28px]" />
|
||||
) : (
|
||||
<div
|
||||
className={`flex h-[28px] w-[28px] items-center justify-center rounded-full ${
|
||||
wallet?.adapter.name === 'Solflare' ? 'bg-black' : ''
|
||||
}`}
|
||||
>
|
||||
<img
|
||||
src={wallet?.adapter.icon || selectedWallet?.adapter.icon}
|
||||
className={
|
||||
wallet?.adapter.name === 'Solflare'
|
||||
? 'h-auto w-[20px]'
|
||||
: 'h-auto w-[28px]'
|
||||
}
|
||||
alt={`${wallet?.adapter.name} icon`}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div className="text-left">
|
||||
<div className="mb-1.5 flex font-display text-base leading-none text-th-fgd-1">
|
||||
{t('connect')}
|
||||
</div>
|
||||
<div className="default-transition relative z-10 flex h-full items-center justify-center space-x-3 px-4">
|
||||
{connecting ? (
|
||||
<Loading className="h-[28px] w-[28px]" />
|
||||
) : (
|
||||
<div
|
||||
className={`flex h-[28px] w-[28px] items-center justify-center rounded-full ${
|
||||
wallet?.adapter.name === 'Solflare' ? 'bg-black' : ''
|
||||
}`}
|
||||
>
|
||||
<img
|
||||
src={wallet?.adapter.icon || selectedWallet?.adapter.icon}
|
||||
className={
|
||||
wallet?.adapter.name === 'Solflare'
|
||||
? 'h-auto w-[20px]'
|
||||
: 'h-auto w-[28px]'
|
||||
}
|
||||
alt={`${wallet?.adapter.name} icon`}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div className="text-left">
|
||||
<div className="mb-1.5 flex font-display text-base leading-none text-th-fgd-1">
|
||||
{t('connect')}
|
||||
</div>
|
||||
|
||||
<div className="text-xxs font-normal leading-3 text-th-fgd-3">
|
||||
{preselectedWalletName}
|
||||
</div>
|
||||
<div className="text-xxs font-normal leading-3 text-th-fgd-3">
|
||||
{preselectedWalletName}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
<div className="absolute top-1/2 right-0 z-20 h-full -translate-y-1/2">
|
||||
<div className="absolute right-0 top-0 z-20 flex h-full">
|
||||
<WalletSelect />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Menu, Transition } from '@headlessui/react'
|
||||
import { Popover, Transition } from '@headlessui/react'
|
||||
import {
|
||||
ArrowRightOnRectangleIcon,
|
||||
CurrencyDollarIcon,
|
||||
|
@ -73,92 +73,82 @@ const ConnectedMenu = () => {
|
|||
|
||||
return (
|
||||
<>
|
||||
<Menu>
|
||||
{({ open }) => (
|
||||
<div className="relative">
|
||||
<Menu.Button
|
||||
className={`default-transition h-16 ${
|
||||
!isMobile ? 'w-48 border-l border-th-bkg-3 px-4' : ''
|
||||
} hover:bg-th-bkg-2 focus:outline-none`}
|
||||
>
|
||||
<div className="flex items-center" id="account-step-one">
|
||||
<ProfileImage
|
||||
imageSize="40"
|
||||
placeholderSize="24"
|
||||
isOwnerProfile
|
||||
/>
|
||||
{!loadProfileDetails && !isMobile ? (
|
||||
<div className="ml-2.5 overflow-hidden text-left">
|
||||
<p className="text-xs text-th-fgd-3">
|
||||
{wallet?.adapter.name}
|
||||
</p>
|
||||
<p className="truncate pr-2 text-sm font-bold text-th-fgd-1">
|
||||
{publicKey ? abbreviateAddress(publicKey) : ''}
|
||||
</p>
|
||||
{/* <p className="truncate pr-2 text-sm font-bold capitalize text-th-fgd-1">
|
||||
<Popover>
|
||||
<div className="relative">
|
||||
<Popover.Button
|
||||
className={`default-transition h-16 ${
|
||||
!isMobile ? 'w-48 border-l border-th-bkg-3 px-4' : ''
|
||||
} hover:bg-th-bkg-2 focus:bg-th-bkg-3 focus:outline-none`}
|
||||
>
|
||||
<div className="flex items-center" id="account-step-one">
|
||||
<ProfileImage
|
||||
imageSize="40"
|
||||
placeholderSize="24"
|
||||
isOwnerProfile
|
||||
/>
|
||||
{!loadProfileDetails && !isMobile ? (
|
||||
<div className="ml-2.5 overflow-hidden text-left">
|
||||
<p className="text-xs text-th-fgd-3">
|
||||
{wallet?.adapter.name}
|
||||
</p>
|
||||
<p className="truncate pr-2 text-sm font-bold text-th-fgd-1">
|
||||
{publicKey ? abbreviateAddress(publicKey) : ''}
|
||||
</p>
|
||||
{/* <p className="truncate pr-2 text-sm font-bold capitalize text-th-fgd-1">
|
||||
{profileDetails?.profile_name
|
||||
? profileDetails.profile_name
|
||||
: 'Profile Unavailabe'}
|
||||
</p> */}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
</Menu.Button>
|
||||
<Transition
|
||||
appear={true}
|
||||
show={open}
|
||||
as={Fragment}
|
||||
enter="transition ease-in duration-200"
|
||||
enterFrom="opacity-0 scale-75"
|
||||
enterTo="opacity-100 scale-100"
|
||||
leave="transition ease-out duration-200"
|
||||
leaveFrom="opacity-100"
|
||||
leaveTo="opacity-0"
|
||||
>
|
||||
<Menu.Items className="absolute right-0 top-[61px] z-20 mt-1 w-48 space-y-1.5 rounded-md rounded-t-none bg-th-bkg-2 px-4 py-2.5 md:rounded-r-none">
|
||||
<Menu.Item>
|
||||
<button
|
||||
className="default-transition flex w-full flex-row items-center rounded-none py-0.5 font-normal focus:outline-none md:hover:cursor-pointer md:hover:text-th-fgd-1"
|
||||
onClick={() => setShowEditProfileModal(true)}
|
||||
>
|
||||
<UserCircleIcon className="h-4 w-4" />
|
||||
<div className="pl-2 text-left">
|
||||
{t('profile:edit-profile-pic')}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
</Popover.Button>
|
||||
<Transition
|
||||
as={Fragment}
|
||||
enter="transition ease-in duration-200"
|
||||
enterFrom="opacity-0 scale-75"
|
||||
enterTo="opacity-100 scale-100"
|
||||
leave="transition ease-out duration-200"
|
||||
leaveFrom="opacity-100"
|
||||
leaveTo="opacity-0"
|
||||
>
|
||||
<Popover.Panel className="absolute right-0 top-[61px] z-20 mt-1 w-48 space-y-1.5 rounded-md rounded-t-none bg-th-bkg-2 px-4 py-2.5 focus:outline-none md:rounded-r-none">
|
||||
<button
|
||||
className="default-transition flex w-full flex-row items-center rounded-none py-0.5 font-normal focus:text-th-active focus:outline-none md:hover:cursor-pointer md:hover:text-th-fgd-1"
|
||||
onClick={() => setShowEditProfileModal(true)}
|
||||
>
|
||||
<UserCircleIcon className="h-4 w-4" />
|
||||
<div className="pl-2 text-left">
|
||||
{t('profile:edit-profile-pic')}
|
||||
</div>
|
||||
</button>
|
||||
{isMobile ? (
|
||||
<button
|
||||
className="default-transition flex w-full flex-row items-center rounded-none py-0.5 font-normal focus:text-th-active focus:outline-none"
|
||||
onClick={() => setShowMangoAccountsModal(true)}
|
||||
>
|
||||
<CurrencyDollarIcon className="h-4 w-4" />
|
||||
<div className="pl-2 text-left">{t('accounts')}</div>
|
||||
</button>
|
||||
) : null}
|
||||
<button
|
||||
className="default-transition flex w-full flex-row items-center rounded-none py-0.5 font-normal focus:text-th-active focus:outline-none md:hover:cursor-pointer md:hover:text-th-fgd-1"
|
||||
onClick={handleDisconnect}
|
||||
>
|
||||
<ArrowRightOnRectangleIcon className="h-4 w-4" />
|
||||
<div className="pl-2 text-left">
|
||||
<div className="pb-0.5">{t('disconnect')}</div>
|
||||
{publicKey ? (
|
||||
<div className="font-mono text-xs text-th-fgd-4">
|
||||
{abbreviateAddress(publicKey)}
|
||||
</div>
|
||||
</button>
|
||||
</Menu.Item>
|
||||
{isMobile ? (
|
||||
<Menu.Item>
|
||||
<button
|
||||
className="default-transition flex w-full flex-row items-center rounded-none py-0.5 font-normal focus:outline-none"
|
||||
onClick={() => setShowMangoAccountsModal(true)}
|
||||
>
|
||||
<CurrencyDollarIcon className="h-4 w-4" />
|
||||
<div className="pl-2 text-left">{t('accounts')}</div>
|
||||
</button>
|
||||
</Menu.Item>
|
||||
) : null}
|
||||
<Menu.Item>
|
||||
<button
|
||||
className="default-transition flex w-full flex-row items-center rounded-none py-0.5 font-normal focus:outline-none md:hover:cursor-pointer md:hover:text-th-fgd-1"
|
||||
onClick={handleDisconnect}
|
||||
>
|
||||
<ArrowRightOnRectangleIcon className="h-4 w-4" />
|
||||
<div className="pl-2 text-left">
|
||||
<div className="pb-0.5">{t('disconnect')}</div>
|
||||
{publicKey ? (
|
||||
<div className="font-mono text-xs text-th-fgd-4">
|
||||
{abbreviateAddress(publicKey)}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
</button>
|
||||
</Menu.Item>
|
||||
</Menu.Items>
|
||||
</Transition>
|
||||
</div>
|
||||
)}
|
||||
</Menu>
|
||||
) : null}
|
||||
</div>
|
||||
</button>
|
||||
</Popover.Panel>
|
||||
</Transition>
|
||||
</div>
|
||||
</Popover>
|
||||
{showEditProfileModal ? (
|
||||
<EditProfileModal
|
||||
isOpen={showEditProfileModal}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React, { Fragment } from 'react'
|
||||
import { ChevronDownIcon } from '@heroicons/react/20/solid'
|
||||
import { Menu, Transition } from '@headlessui/react'
|
||||
import { Popover, Transition } from '@headlessui/react'
|
||||
import { useEnhancedWallet } from './EnhancedWalletProvider'
|
||||
import useMangoGroup from 'hooks/useMangoGroup'
|
||||
|
||||
|
@ -9,11 +9,11 @@ const WalletSelect = () => {
|
|||
const { group } = useMangoGroup()
|
||||
|
||||
return (
|
||||
<Menu>
|
||||
<Popover>
|
||||
{({ open }) => (
|
||||
<>
|
||||
<Menu.Button
|
||||
className={`flex h-full w-12 cursor-pointer items-center justify-center rounded-none bg-transparent text-th-fgd-3 hover:brightness-[1.1] focus:outline-none disabled:opacity-25`}
|
||||
<Popover.Button
|
||||
className={`flex h-full w-12 cursor-pointer items-center justify-center rounded-none bg-transparent text-th-fgd-3 hover:brightness-[1.1] focus:text-th-active focus:outline-none disabled:opacity-25`}
|
||||
disabled={!group}
|
||||
>
|
||||
<ChevronDownIcon
|
||||
|
@ -21,10 +21,8 @@ const WalletSelect = () => {
|
|||
open ? 'rotate-180' : 'rotate-360'
|
||||
}`}
|
||||
/>
|
||||
</Menu.Button>
|
||||
</Popover.Button>
|
||||
<Transition
|
||||
appear={true}
|
||||
show={open}
|
||||
as={Fragment}
|
||||
enter="transition ease-in duration-200"
|
||||
enterFrom="opacity-0 scale-75"
|
||||
|
@ -33,31 +31,30 @@ const WalletSelect = () => {
|
|||
leaveFrom="opacity-100"
|
||||
leaveTo="opacity-0"
|
||||
>
|
||||
<Menu.Items className="absolute top-16 right-0 z-20 w-44 rounded-md rounded-t-none bg-th-bkg-2 px-4 py-2.5 outline-none">
|
||||
<Popover.Panel className="absolute top-16 right-0 z-20 w-44 rounded-md rounded-t-none bg-th-bkg-2 px-4 py-2.5 outline-none">
|
||||
{displayedWallets?.map((wallet, index) => (
|
||||
<Menu.Item key={index}>
|
||||
<button
|
||||
className="flex w-full flex-row items-center justify-between rounded-none py-1.5 font-normal focus:outline-none md:hover:cursor-pointer md:hover:text-th-active"
|
||||
onClick={() => {
|
||||
handleSelect(wallet.adapter.name)
|
||||
}}
|
||||
>
|
||||
<div className="flex items-center">
|
||||
<img
|
||||
src={wallet.adapter.icon}
|
||||
className="mr-2 h-5 w-5"
|
||||
alt={`${wallet.adapter.name} icon`}
|
||||
/>
|
||||
{wallet.adapter.name}
|
||||
</div>
|
||||
</button>
|
||||
</Menu.Item>
|
||||
<button
|
||||
className="flex w-full flex-row items-center justify-between rounded-none py-1.5 font-normal focus:text-th-active focus:outline-none md:hover:cursor-pointer md:hover:text-th-active"
|
||||
onClick={() => {
|
||||
handleSelect(wallet.adapter.name)
|
||||
}}
|
||||
key={wallet.adapter.name + index}
|
||||
>
|
||||
<div className="flex items-center">
|
||||
<img
|
||||
src={wallet.adapter.icon}
|
||||
className="mr-2 h-5 w-5"
|
||||
alt={`${wallet.adapter.name} icon`}
|
||||
/>
|
||||
{wallet.adapter.name}
|
||||
</div>
|
||||
</button>
|
||||
))}
|
||||
</Menu.Items>
|
||||
</Popover.Panel>
|
||||
</Transition>
|
||||
</>
|
||||
)}
|
||||
</Menu>
|
||||
</Popover>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -401,7 +401,7 @@ body {
|
|||
}
|
||||
|
||||
button {
|
||||
@apply default-transition tracking-wider focus:outline-none;
|
||||
@apply tracking-wider focus:outline-none;
|
||||
}
|
||||
|
||||
svg {
|
||||
|
@ -543,7 +543,7 @@ table p {
|
|||
/* slider */
|
||||
|
||||
input[type='range'] {
|
||||
@apply h-1.5 appearance-none rounded bg-th-bkg-3 bg-gradient-to-r from-th-active to-th-active bg-no-repeat;
|
||||
@apply default-transition h-1.5 appearance-none rounded bg-th-bkg-3 bg-gradient-to-r from-th-active to-th-active bg-no-repeat focus:bg-th-bkg-4;
|
||||
}
|
||||
|
||||
input[type='range']::-webkit-slider-thumb {
|
||||
|
|
Loading…
Reference in New Issue