add focus states and improve keyboard navigation

This commit is contained in:
saml33 2023-03-24 23:22:29 +11:00
parent 8caa115388
commit 7cd26e9da5
31 changed files with 406 additions and 464 deletions

View File

@ -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,6 +42,7 @@ 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
@ -234,26 +233,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 +249,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="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"
placeholder="0.00"
value={inputAmount}
onValueChange={handleInputChange}

View File

@ -1,13 +1,11 @@
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 +35,7 @@ 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 DepositFormProps {
onSuccess: () => void
@ -222,26 +221,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 +237,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="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"
placeholder="0.00"
value={inputAmount}
onValueChange={(e: NumberFormatValues) => {

View File

@ -1,14 +1,11 @@
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 +32,7 @@ import ConnectEmptyState from './shared/ConnectEmptyState'
import BankAmountWithValue from './shared/BankAmountWithValue'
import useBanksWithBalances from 'hooks/useBanksWithBalances'
import { isMangoError } from 'types'
import TokenListButton from './shared/TokenListButton'
interface RepayFormProps {
onSuccess: () => void
@ -233,23 +231,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 +247,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="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"
placeholder="0.00"
value={inputAmount}
onValueChange={(e: NumberFormatValues) => {

View File

@ -10,14 +10,13 @@ import {
Cog8ToothIcon,
ArrowsRightLeftIcon,
ArrowTrendingUpIcon,
XMarkIcon,
MagnifyingGlassIcon,
BanknotesIcon,
NewspaperIcon,
} 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'
@ -27,7 +26,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'
const SideNav = ({ collapsed }: { collapsed: boolean }) => {
const { t } = useTranslation(['common', 'search'])
@ -182,7 +180,6 @@ const SideNav = ({ collapsed }: { collapsed: boolean }) => {
size={32}
/>
}
isOpen
panelTitle={mangoAccount?.name ? mangoAccount.name : t('account')}
title={
<div className="w-24 text-left">
@ -200,7 +197,6 @@ const SideNav = ({ collapsed }: { collapsed: boolean }) => {
}
alignBottom
hideIconBg
showClose
>
<div className="px-4 py-2">
<MangoAccountSummary />
@ -293,8 +289,6 @@ export const ExpandableMenuItem = ({
hideIconBg,
icon,
panelTitle,
isOpen,
showClose,
title,
}: {
alignBottom?: boolean
@ -303,134 +297,114 @@ 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:text-th-active focus:ring-0'
} 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'
}
{({ open }) => (
<>
<div
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 focus:text-th-active focus:ring-0 md:hover:text-th-active`}
>
{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 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>
<ChevronDownIcon
className={`${
open ? 'rotate-180' : 'rotate-360'
} h-5 w-5 flex-shrink-0`}
/>
</Disclosure.Button>
</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>
<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>
)
}

View File

@ -2,13 +2,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 +37,7 @@ 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 WithdrawFormProps {
onSuccess: () => void
@ -211,26 +210,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 +226,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="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"
placeholder="0.00"
value={inputAmount}
onValueChange={(e: NumberFormatValues) =>

View File

@ -52,6 +52,7 @@ const ButtonGroup = <T extends Values>({
style={{
width: `${100 / values.length}%`,
}}
type="button"
>
{names ? (unit ? names[i] + unit : names[i]) : unit ? v + unit : v}
</button>

View File

@ -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"
/>

View File

@ -44,7 +44,7 @@ const Input = forwardRef<HTMLInputElement, InputProps>((props, ref) => {
className={`${className} default-transition h-12 w-full flex-1 rounded-md border bg-th-input-bkg px-3 text-base
text-th-fgd-1 ${
error ? 'border-th-down' : 'border-th-input-border'
} focus:outline-none
} focus:border-th-fgd-4 focus:outline-none
md:hover:border-th-input-border-hover
${
disabled

View File

@ -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:border-th-fgd-4 focus:outline-none 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>
)}

View File

@ -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 focus:ring-0 ${
disabled ? 'opacity-60' : ''
}`}
role="switch"
aria-checked={checked}
onClick={handleClick}

View File

@ -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'])

View File

@ -418,7 +418,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="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"
placeholder="0.00"
value={depositAmount}
onValueChange={(e: NumberFormatValues) => {

View File

@ -88,9 +88,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>
@ -117,9 +115,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>

View File

@ -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,7 +33,7 @@ const Button: FunctionComponent<ButtonCombinedProps> = ({
disabled={disabled}
className={`rounded-md ${
secondary
? 'border border-th-button md:hover:border-th-button-hover'
? 'border border-th-button focus:border-th-fgd-2 focus:ring-0 md:hover:border-th-button-hover'
: 'bg-th-button md:hover:bg-th-button-hover'
} ${
size === 'medium'
@ -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 focus:ring-0`}
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 focus:ring-0 disabled:cursor-not-allowed disabled:opacity-50 md:hover:no-underline ${className}`}
{...props}
type="button"
>

View File

@ -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 focus:ring-0 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 focus:ring-0 md:hover:text-th-active"
onClick={() => addToFavorites(market.name)}
>
<StarIcon className="h-5 w-5" />

View File

@ -46,7 +46,7 @@ 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 focus:border-th-fgd-2 focus:ring-0 md:hover:border-th-button-hover md:hover:text-th-fgd-1 ${
disabled ? 'cursor-not-allowed opacity-60' : ''
}`}
disabled={disabled}

View File

@ -24,7 +24,7 @@ const MaxAmountButton = ({
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>

View File

@ -48,7 +48,7 @@ const TabUnderline = <T extends Values>({
<button
onClick={() => onChange(value)}
className={`default-transition relative flex h-10 w-1/2
cursor-pointer items-center justify-center whitespace-nowrap rounded py-1 md:h-auto md:rounded-none md:hover:opacity-100 ${
cursor-pointer items-center justify-center whitespace-nowrap rounded py-1 focus:text-th-fgd-1 focus:ring-0 md:h-auto md:rounded-none md:hover:opacity-100 ${
small ? 'text-sm' : 'text-sm lg:text-base'
}
${

View File

@ -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 focus:ring-0"
>
<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

View File

@ -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 =
'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:border-th-fgd-4 focus:outline-none lg:text-lg xl:text-xl'
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}
@ -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}

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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 focus:ring-0"
>
<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>
)
}

View File

@ -60,6 +60,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 AdvancedTradeForm = () => {
const { t } = useTranslation(['common', 'trade'])
const { mangoAccount } = useMangoAccount()
@ -400,9 +406,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>
) : (
@ -418,14 +424,12 @@ const AdvancedTradeForm = () => {
decimalScale={6}
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 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}
@ -435,11 +439,24 @@ const AdvancedTradeForm = () => {
useMargin={useMargin}
/>
<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 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`}
@ -450,26 +467,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>
) : (
@ -485,14 +489,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 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>

View File

@ -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>
)
})}

View File

@ -45,10 +45,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 flex h-12 items-center justify-between px-2 hover:text-th-active">
<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">
@ -74,24 +74,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>
<FavoriteMarketButton market={m} />
</div>
@ -114,24 +105,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>
<FavoriteMarketButton market={m} />
</div>

View File

@ -25,37 +25,35 @@ 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 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>

View File

@ -1,4 +1,4 @@
import { Menu, Transition } from '@headlessui/react'
import { Popover, Transition } from '@headlessui/react'
import {
ArrowRightOnRectangleIcon,
CurrencyDollarIcon,
@ -74,103 +74,91 @@ 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: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>
</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="flex w-full flex-row items-center rounded-none py-0.5 font-normal hover:cursor-pointer hover:text-th-active focus:outline-none"
</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 focus:ring-0 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 focus:ring-0"
onClick={() => setShowMangoAccountsModal(true)}
>
<CurrencyDollarIcon className="h-4 w-4" />
<div className="pl-2 text-left">{t('accounts')}</div>
</button>
) : null}
{/* <button
className="flex w-full flex-row items-center rounded-none py-0.5 font-normal hover:cursor-pointer hover:text-th-active focus:outline-none focus:ring-0 focus:text-th-active"
onClick={() => setShowProfileImageModal(true)}
>
<ProfileIcon className="h-4 w-4" />
<div className="pl-2 text-left">
{t('edit-profile-image')}
</div>
</button>
</Menu.Item> */}
<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}
</button> */}
<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 focus:ring-0 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>
</Menu.Items>
</Transition>
</div>
)}
</Menu>
) : null}
</div>
</button>
</Popover.Panel>
</Transition>
</div>
</Popover>
{showEditProfileModal ? (
<EditProfileModal
isOpen={showEditProfileModal}

View File

@ -13,7 +13,7 @@ const WalletSelect = () => {
{({ 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`}
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 focus:ring-0 disabled:opacity-25`}
disabled={!group}
>
<ChevronDownIcon

View File

@ -401,7 +401,7 @@ body {
}
button {
@apply tracking-wider focus:outline-none;
@apply tracking-wider focus:outline-none focus:ring-1 focus:ring-inset focus:ring-th-fgd-4;
}
svg {