ui for swap limit orders

This commit is contained in:
saml33 2023-06-15 14:42:34 +10:00
parent 2e4852e965
commit b548e7f61e
9 changed files with 128 additions and 22 deletions

View File

@ -7,6 +7,7 @@ interface SelectProps {
onChange: (x: string) => void
children: ReactNode
className?: string
buttonClassName?: string
dropdownPanelClassName?: string
placeholder?: string
disabled?: boolean
@ -17,6 +18,7 @@ const Select = ({
onChange,
children,
className,
buttonClassName,
dropdownPanelClassName,
placeholder = 'Select',
disabled = false,
@ -27,7 +29,7 @@ const Select = ({
{({ open }) => (
<>
<Listbox.Button
className={`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-visible:ring-th-fgd-4 md:hover:ring-th-input-border-hover`}
className={`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-visible:ring-th-fgd-4 md:hover:ring-th-input-border-hover ${buttonClassName}`}
>
<div
className={`flex items-center justify-between space-x-2 px-3 text-th-fgd-1`}

View File

@ -48,6 +48,8 @@ import SwapSettings from './SwapSettings'
import InlineNotification from '@components/shared/InlineNotification'
import useUnownedAccount from 'hooks/useUnownedAccount'
import Tooltip from '@components/shared/Tooltip'
import TabUnderline from '@components/shared/TabUnderline'
import Select from '@components/forms/Select'
const MAX_DIGITS = 11
export const withValueLimit = (values: NumberFormatValues): boolean => {
@ -57,10 +59,16 @@ export const withValueLimit = (values: NumberFormatValues): boolean => {
}
const NUMBER_FORMAT_CLASSNAMES =
'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-visible:border-th-fgd-4'
'w-full rounded-lg rounded-l-none h-[54px] border-l border-th-bkg-2 bg-th-input-bkg p-3 text-right font-mono text-xl text-th-fgd-1 focus:outline-none md:hover:border-th-input-border-hover focus-visible:bg-th-bkg-3'
const set = mangoStore.getState().set
export const ORDER_TYPES = [
'trade:limit',
'trade:stop-market',
'trade:stop-limit',
]
const SwapForm = () => {
const { t } = useTranslation(['common', 'swap', 'trade'])
//initial state is undefined null is returned on error
@ -69,6 +77,8 @@ const SwapForm = () => {
const [showTokenSelect, setShowTokenSelect] = useState<'input' | 'output'>()
const [showSettings, setShowSettings] = useState(false)
const [showConfirm, setShowConfirm] = useState(false)
const [orderType, setOrderType] = useState(ORDER_TYPES[0])
const [activeTab, setActiveTab] = useState('swap')
const { group } = useMangoGroup()
const [swapFormSizeUi] = useLocalStorageState(SIZE_INPUT_UI_KEY, 'slider')
const { ipAllowed, ipCountry } = useIpAddress()
@ -277,7 +287,7 @@ const SwapForm = () => {
return (
<ContentBox
hidePadding
className="relative overflow-hidden border-x-0 md:border-l md:border-r-0 md:border-t-0 md:border-b-0"
className="relative overflow-hidden border-x-0 bg-th-bkg-1 md:border-l md:border-r-0 md:border-t-0 md:border-b-0"
>
<div>
<Transition
@ -320,7 +330,14 @@ const SwapForm = () => {
>
<SwapSettings onClose={() => setShowSettings(false)} />
</EnterBottomExitBottom>
<div className="relative p-6 pt-10">
<div className="relative p-6">
<div className="mb-6">
<TabUnderline
activeValue={activeTab}
values={['swap', 'trade:limit']}
onChange={(v) => setActiveTab(v)}
/>
</div>
<div className="absolute right-4 top-4">
<IconButton
className="text-th-fgd-3"
@ -330,16 +347,21 @@ const SwapForm = () => {
<Cog8ToothIcon className="h-5 w-5" />
</IconButton>
</div>
<div className="mb-2 flex items-end justify-between">
<p className="text-th-fgd-2 lg:text-base">{t('swap:pay')}</p>
{!isUnownedAccount ? (
<MaxSwapAmount
useMargin={useMargin}
setAmountIn={(v) => setAmountInFormValue(v, true)}
/>
) : null}
</div>
<div className="mb-3 grid grid-cols-2" id="swap-step-two">
<div
className={`grid grid-cols-2 ${
activeTab === 'trade:limit' ? 'rounded-t-xl' : 'rounded-xl'
} bg-th-bkg-2 p-3`}
id="swap-step-two"
>
<div className="col-span-2 mb-2 flex items-center justify-between">
<p className="text-th-fgd-2">{t('sell')}</p>
{!isUnownedAccount ? (
<MaxSwapAmount
useMargin={useMargin}
setAmountIn={(v) => setAmountInFormValue(v, true)}
/>
) : null}
</div>
<div className="col-span-1">
<TokenSelect
bank={
@ -350,7 +372,7 @@ const SwapForm = () => {
type="input"
/>
</div>
<div className="col-span-1 flex h-[54px]">
<div className="col-span-1">
<NumberFormat
inputMode="decimal"
thousandSeparator=","
@ -367,9 +389,73 @@ const SwapForm = () => {
/>
</div>
</div>
<div className="-mb-2 flex justify-center">
{activeTab === 'trade:limit' ? (
<div
className={`grid ${
orderType === 'trade:stop-limit' ? 'grid-cols-3' : 'grid-cols-2'
} gap-2 rounded-b-xl bg-th-bkg-2 p-3 pt-1`}
id="swap-step-two"
>
<div className="col-span-1">
<p className="mb-2 text-th-fgd-2">{t('trade:order-type')}</p>
<Select
value={t(orderType)}
onChange={(type) => setOrderType(type)}
className="w-full"
buttonClassName="ring-0 rounded-t-lg rounded-b-lg"
>
{ORDER_TYPES.map((type) => (
<Select.Option key={type} value={type}>
{t(type)}
</Select.Option>
))}
</Select>
</div>
<div className="col-span-1">
<p className="mb-2 text-th-fgd-2">
{orderType === 'trade:limit'
? t('trade:limit-price')
: t('trade:trigger-price')}
</p>
<NumberFormat
inputMode="decimal"
thousandSeparator=","
allowNegative={false}
isNumericString={true}
decimalScale={inputBank?.mintDecimals || 6}
name="amountIn"
id="amountIn"
className="h-10 w-full rounded-lg bg-th-input-bkg p-3 text-right font-mono text-sm text-th-fgd-1 focus:border-th-fgd-4 focus:outline-none md:hover:border-th-input-border-hover md:hover:focus-visible:bg-th-bkg-3"
placeholder="0.00"
value={amountInFormValue}
onValueChange={handleAmountInChange}
isAllowed={withValueLimit}
/>
</div>
{orderType === 'trade:stop-limit' ? (
<div className="col-span-1">
<p className="mb-2 text-th-fgd-2">{t('trade:limit-price')}</p>
<NumberFormat
inputMode="decimal"
thousandSeparator=","
allowNegative={false}
isNumericString={true}
decimalScale={inputBank?.mintDecimals || 6}
name="amountIn"
id="amountIn"
className="h-10 w-full rounded-lg bg-th-input-bkg p-3 text-right font-mono text-sm text-th-fgd-1 focus:border-th-fgd-4 focus:outline-none md:hover:border-th-input-border-hover md:hover:focus-visible:bg-th-bkg-3"
placeholder="0.00"
value={amountInFormValue}
onValueChange={handleAmountInChange}
isAllowed={withValueLimit}
/>
</div>
) : null}
</div>
) : null}
<div className="my-2 flex justify-center">
<button
className="rounded-full border border-th-bkg-4 p-1.5 text-th-fgd-3 focus-visible:border-th-fgd-4 md:hover:text-th-active"
className="rounded-full border border-th-fgd-4 p-1.5 text-th-fgd-3 focus-visible:border-th-active md:hover:border-th-active md:hover:text-th-active"
onClick={handleSwitchTokens}
>
<ArrowDownIcon
@ -382,8 +468,11 @@ const SwapForm = () => {
/>
</button>
</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
id="swap-step-three"
className="mb-3 grid grid-cols-2 rounded-xl bg-th-bkg-2 p-3"
>
<p className="col-span-2 mb-2 text-th-fgd-2">{t('buy')}</p>
<div className="col-span-1">
<TokenSelect
bank={
@ -394,7 +483,7 @@ const SwapForm = () => {
type="output"
/>
</div>
<div className="col-span-1 flex h-[54px]">
<div className="col-span-1">
{loadingSwapDetails ? (
<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 />

View File

@ -390,7 +390,7 @@ const SwapTokenChart = () => {
)}
</div>
</div>
<div className="mt-2 h-40 w-auto md:h-72">
<div className="mt-2 h-40 w-auto md:h-96">
<div className="absolute top-[2px] right-0 -mb-2 flex items-center justify-end space-x-4">
<Tooltip
content={

View File

@ -31,7 +31,7 @@ const TokenSelect = ({ bank, showTokenList, type }: TokenSelectProps) => {
return (
<button
onClick={() => showTokenList(type)}
className="flex h-full w-full items-center rounded-lg rounded-r-none border border-r-0 border-th-input-border bg-th-input-bkg py-2 px-3 text-th-fgd-2 focus-visible:bg-th-bkg-2 md:hover:cursor-pointer md:hover:bg-th-bkg-2 md:hover:text-th-fgd-1"
className="flex h-[54px] w-full items-center rounded-lg rounded-r-none bg-th-input-bkg py-2 px-3 text-th-fgd-2 focus-visible:bg-th-bkg-3 md:hover:cursor-pointer md:hover:bg-th-bkg-1 md:hover:text-th-fgd-1"
>
<div className="mr-2.5 flex min-w-[24px] items-center">
{logoURI ? (

View File

@ -74,6 +74,8 @@
"size": "Size",
"spread": "Spread",
"stable-price": "Stable Price",
"stop-limit": "Stop Limit",
"stop-market": "Stop Market",
"taker": "Taker",
"taker-fee": "Taker Fee",
"tick-size": "Tick Size",
@ -88,6 +90,7 @@
"tooltip-stable-price": "Stable price is used in a safety mechanism that limits a user's ability to enter risky positions when the oracle price is changing rapidly",
"trade-sounds-tooltip": "Play a sound alert for every new trade",
"trades": "Trades",
"trigger-price": "Trigger Price",
"tweet-position": "Share to Twitter",
"unsettled": "Unsettled",
"volume-alert": "Volume Alert",

View File

@ -74,6 +74,8 @@
"size": "Size",
"spread": "Spread",
"stable-price": "Stable Price",
"stop-limit": "Stop Limit",
"stop-market": "Stop Market",
"taker": "Taker",
"taker-fee": "Taker Fee",
"tick-size": "Tick Size",
@ -88,6 +90,7 @@
"tooltip-stable-price": "Stable price is used in a safety mechanism that limits a user's ability to enter risky positions when the oracle price is changing rapidly",
"trade-sounds-tooltip": "Play a sound alert for every new trade",
"trades": "Trades",
"trigger-price": "Trigger Price",
"tweet-position": "Share to Twitter",
"unsettled": "Unsettled",
"volume-alert": "Volume Alert",

View File

@ -74,6 +74,8 @@
"size": "Size",
"spread": "Spread",
"stable-price": "Stable Price",
"stop-limit": "Stop Limit",
"stop-market": "Stop Market",
"taker": "Taker",
"taker-fee": "Taker Fee",
"tick-size": "Tick Size",
@ -88,6 +90,7 @@
"tooltip-stable-price": "Stable price is used in a safety mechanism that limits a user's ability to enter risky positions when the oracle price is changing rapidly",
"trade-sounds-tooltip": "Play a sound alert for every new trade",
"trades": "Trades",
"trigger-price": "Trigger Price",
"tweet-position": "Share to Twitter",
"unsettled": "Unsettled",
"volume-alert": "Volume Alert",

View File

@ -73,6 +73,8 @@
"size": "數量",
"spread": "差價",
"stable-price": "穩定價格",
"stop-limit": "Stop Limit",
"stop-market": "Stop Market",
"taker": "吃單者",
"tick-size": "波動單位",
"tooltip-borrow-balance": "You'll use your {{balance}} {{token}} balance and borrow {{borrowAmount}} {{token}} to execute this trade. The current {{token}} variable borrow rate is {{rate}}%",
@ -87,6 +89,7 @@
"trade-sounds-tooltip": "為每筆新交易播放警報聲音",
"trades": "交易",
"tweet-position": "分享至Twitter",
"trigger-price": "Trigger Price",
"unsettled": "未結清",
"volume-alert": "交易量警報",
"volume-alert-desc": "交易量超過警報設定時播放聲音"

View File

@ -74,6 +74,8 @@
"size": "數量",
"spread": "差價",
"stable-price": "穩定價格",
"stop-limit": "Stop Limit",
"stop-market": "Stop Market",
"taker": "吃單者",
"taker-fee": "吃單者 Fee",
"tick-size": "波動單位",
@ -88,6 +90,7 @@
"tooltip-volume-alert": "交易量警報設定",
"trade-sounds-tooltip": "為每筆新交易播放警報聲音",
"trades": "交易",
"trigger-price": "Trigger Price",
"tweet-position": "分享至Twitter",
"unsettled": "未結清",
"volume-alert": "交易量警報",