Commit 92b7ca8f authored by Zach Pomerantz's avatar Zach Pomerantz Committed by GitHub

feat: hide balance on blur (#3285)

* feat: hide balance when blurred

* refactor: express focused through props

* refactor: share Input/Output code
parent c5ea01ce
...@@ -17,10 +17,15 @@ import Row from '../Row' ...@@ -17,10 +17,15 @@ import Row from '../Row'
import TokenImg from '../TokenImg' import TokenImg from '../TokenImg'
import TokenInput from './TokenInput' import TokenInput from './TokenInput'
const LoadingSpan = styled.span<{ $loading: boolean }>` export const LoadingSpan = styled.span<{ $loading: boolean }>`
${loadingOpacityCss}; ${loadingOpacityCss};
` `
export const Balance = styled(ThemedText.Body2)<{ focused: boolean }>`
opacity: ${({ focused }) => (focused ? 1 : 0)};
transition: opacity 0.25s ${({ focused }) => (focused ? 'ease-in' : 'ease-out')};
`
const InputColumn = styled(Column)<{ approved?: boolean }>` const InputColumn = styled(Column)<{ approved?: boolean }>`
margin: 0.75em; margin: 0.75em;
position: relative; position: relative;
...@@ -31,11 +36,12 @@ const InputColumn = styled(Column)<{ approved?: boolean }>` ...@@ -31,11 +36,12 @@ const InputColumn = styled(Column)<{ approved?: boolean }>`
} }
` `
interface InputProps { export interface InputProps {
disabled?: boolean disabled: boolean
focused: boolean
} }
export default function Input({ disabled }: InputProps) { export default function Input({ disabled, focused }: InputProps) {
const { i18n } = useLingui() const { i18n } = useLingui()
const { const {
trade: { state: tradeState }, trade: { state: tradeState },
...@@ -90,9 +96,9 @@ export default function Input({ disabled }: InputProps) { ...@@ -90,9 +96,9 @@ export default function Input({ disabled }: InputProps) {
<Row> <Row>
<LoadingSpan $loading={isLoading}>{inputUSDC ? `$${inputUSDC.toFixed(2)}` : '-'}</LoadingSpan> <LoadingSpan $loading={isLoading}>{inputUSDC ? `$${inputUSDC.toFixed(2)}` : '-'}</LoadingSpan>
{balance && ( {balance && (
<ThemedText.Body2 color={inputCurrencyAmount?.greaterThan(balance) ? 'error' : undefined}> <Balance color={inputCurrencyAmount?.greaterThan(balance) ? 'error' : undefined} focused={focused}>
Balance: <span style={{ userSelect: 'text' }}>{formatCurrencyAmount(balance, 4, i18n.locale)}</span> Balance: <span style={{ userSelect: 'text' }}>{formatCurrencyAmount(balance, 4, i18n.locale)}</span>
</ThemedText.Body2> </Balance>
)} )}
</Row> </Row>
</ThemedText.Body2> </ThemedText.Body2>
......
...@@ -4,26 +4,22 @@ import { useUSDCValue } from 'hooks/useUSDCPrice' ...@@ -4,26 +4,22 @@ import { useUSDCValue } from 'hooks/useUSDCPrice'
import { atom } from 'jotai' import { atom } from 'jotai'
import { useAtomValue } from 'jotai/utils' import { useAtomValue } from 'jotai/utils'
import BrandedFooter from 'lib/components/BrandedFooter' import BrandedFooter from 'lib/components/BrandedFooter'
import { loadingOpacityCss } from 'lib/css/loading'
import { useSwapAmount, useSwapCurrency, useSwapInfo } from 'lib/hooks/swap' import { useSwapAmount, useSwapCurrency, useSwapInfo } from 'lib/hooks/swap'
import useCurrencyColor from 'lib/hooks/useCurrencyColor' import useCurrencyColor from 'lib/hooks/useCurrencyColor'
import { Field, independentFieldAtom } from 'lib/state/swap' import { Field, independentFieldAtom } from 'lib/state/swap'
import styled, { DynamicThemeProvider, ThemedText } from 'lib/theme' import styled, { DynamicThemeProvider, ThemedText } from 'lib/theme'
import { ReactNode, useMemo } from 'react' import { PropsWithChildren, useMemo } from 'react'
import { TradeState } from 'state/routing/types' import { TradeState } from 'state/routing/types'
import { computeFiatValuePriceImpact } from 'utils/computeFiatValuePriceImpact' import { computeFiatValuePriceImpact } from 'utils/computeFiatValuePriceImpact'
import { formatCurrencyAmount } from 'utils/formatCurrencyAmount' import { formatCurrencyAmount } from 'utils/formatCurrencyAmount'
import Column from '../Column' import Column from '../Column'
import Row from '../Row' import Row from '../Row'
import { Balance, InputProps, LoadingSpan } from './Input'
import TokenInput from './TokenInput' import TokenInput from './TokenInput'
export const colorAtom = atom<string | undefined>(undefined) export const colorAtom = atom<string | undefined>(undefined)
const LoadingSpan = styled.span<{ $loading: boolean }>`
${loadingOpacityCss};
`
const OutputColumn = styled(Column)<{ hasColor: boolean | null }>` const OutputColumn = styled(Column)<{ hasColor: boolean | null }>`
background-color: ${({ theme }) => theme.module}; background-color: ${({ theme }) => theme.module};
border-radius: ${({ theme }) => theme.borderRadius - 0.25}em; border-radius: ${({ theme }) => theme.borderRadius - 0.25}em;
...@@ -40,12 +36,7 @@ const OutputColumn = styled(Column)<{ hasColor: boolean | null }>` ...@@ -40,12 +36,7 @@ const OutputColumn = styled(Column)<{ hasColor: boolean | null }>`
} }
` `
interface OutputProps { export default function Output({ disabled, focused, children }: PropsWithChildren<InputProps>) {
disabled?: boolean
children: ReactNode
}
export default function Output({ disabled, children }: OutputProps) {
const { i18n } = useLingui() const { i18n } = useLingui()
const { const {
...@@ -108,9 +99,9 @@ export default function Output({ disabled, children }: OutputProps) { ...@@ -108,9 +99,9 @@ export default function Output({ disabled, children }: OutputProps) {
<Row> <Row>
<LoadingSpan $loading={isLoading}>{usdc}</LoadingSpan> <LoadingSpan $loading={isLoading}>{usdc}</LoadingSpan>
{balance && ( {balance && (
<span> <Balance focused={focused}>
Balance: <span style={{ userSelect: 'text' }}>{formatCurrencyAmount(balance, 4, i18n.locale)}</span> Balance: <span style={{ userSelect: 'text' }}>{formatCurrencyAmount(balance, 4, i18n.locale)}</span>
</span> </Balance>
)} )}
</Row> </Row>
</ThemedText.Body2> </ThemedText.Body2>
......
...@@ -65,6 +65,8 @@ export default function Swap(props: SwapProps) { ...@@ -65,6 +65,8 @@ export default function Swap(props: SwapProps) {
[chainId, list] [chainId, list]
) )
const [focused, setFocused] = useState(false)
return ( return (
<SwapPropValidator {...props}> <SwapPropValidator {...props}>
{onSupportedChain && <SwapInfoUpdater />} {onSupportedChain && <SwapInfoUpdater />}
...@@ -72,11 +74,11 @@ export default function Swap(props: SwapProps) { ...@@ -72,11 +74,11 @@ export default function Swap(props: SwapProps) {
{active && <Wallet disabled={!account} onClick={props.onConnectWallet} />} {active && <Wallet disabled={!account} onClick={props.onConnectWallet} />}
<Settings disabled={!active} /> <Settings disabled={!active} />
</Header> </Header>
<div ref={setBoundary}> <div onFocus={() => setFocused(true)} onBlur={() => setFocused(false)} ref={setBoundary}>
<BoundaryProvider value={boundary}> <BoundaryProvider value={boundary}>
<Input disabled={!active} /> <Input disabled={!active} focused={focused} />
<ReverseButton disabled={!active} /> <ReverseButton disabled={!active} />
<Output disabled={!active}> <Output disabled={!active} focused={focused}>
<Toolbar disabled={!active} /> <Toolbar disabled={!active} />
<SwapButton disabled={!account} /> <SwapButton disabled={!account} />
</Output> </Output>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment