fix(bag): review asset buttons (#5182)
* fix(bag): review asset buttons * clean up * pr feedback
This commit is contained in:
parent
ce79774de9
commit
2970f9f1cb
@ -1,7 +1,7 @@
|
|||||||
import { darken } from 'polished'
|
import { darken } from 'polished'
|
||||||
import { Check, ChevronDown } from 'react-feather'
|
import { Check, ChevronDown } from 'react-feather'
|
||||||
import { Button as RebassButton, ButtonProps as ButtonPropsOriginal } from 'rebass/styled-components'
|
import { Button as RebassButton, ButtonProps as ButtonPropsOriginal } from 'rebass/styled-components'
|
||||||
import styled, { useTheme } from 'styled-components/macro'
|
import styled, { DefaultTheme, useTheme } from 'styled-components/macro'
|
||||||
|
|
||||||
import { RowBetween } from '../Row'
|
import { RowBetween } from '../Row'
|
||||||
|
|
||||||
@ -366,12 +366,82 @@ export function ButtonRadioChecked({ active = false, children, ...rest }: { acti
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const MediumButton = styled.button`
|
const ButtonOverlay = styled.div`
|
||||||
|
background-color: transparent;
|
||||||
|
bottom: 0;
|
||||||
|
border-radius: 16px;
|
||||||
|
height: 100%;
|
||||||
|
left: 0;
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
transition: 150ms ease background-color;
|
||||||
|
width: 100%;
|
||||||
|
`
|
||||||
|
export enum ButtonSize {
|
||||||
|
small,
|
||||||
|
medium,
|
||||||
|
large,
|
||||||
|
}
|
||||||
|
export enum ButtonEmphasis {
|
||||||
|
high,
|
||||||
|
promotional,
|
||||||
|
highSoft,
|
||||||
|
medium,
|
||||||
|
low,
|
||||||
|
warning,
|
||||||
|
destructive,
|
||||||
|
}
|
||||||
|
interface BaseButtonProps {
|
||||||
|
size: ButtonSize
|
||||||
|
emphasis: ButtonEmphasis
|
||||||
|
}
|
||||||
|
|
||||||
|
function pickThemeButtonBackgroundColor({ theme, emphasis }: { theme: DefaultTheme; emphasis: ButtonEmphasis }) {
|
||||||
|
switch (emphasis) {
|
||||||
|
case ButtonEmphasis.high:
|
||||||
|
return theme.accentAction
|
||||||
|
case ButtonEmphasis.promotional:
|
||||||
|
return theme.accentTextLightPrimary
|
||||||
|
case ButtonEmphasis.highSoft:
|
||||||
|
return theme.accentActionSoft
|
||||||
|
case ButtonEmphasis.low:
|
||||||
|
return 'transparent'
|
||||||
|
case ButtonEmphasis.warning:
|
||||||
|
return theme.accentWarningSoft
|
||||||
|
case ButtonEmphasis.destructive:
|
||||||
|
return theme.accentCritical
|
||||||
|
case ButtonEmphasis.medium:
|
||||||
|
default:
|
||||||
|
return theme.backgroundInteractive
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function pickThemeButtonTextColor({ theme, emphasis }: { theme: DefaultTheme; emphasis: ButtonEmphasis }) {
|
||||||
|
switch (emphasis) {
|
||||||
|
case ButtonEmphasis.high:
|
||||||
|
case ButtonEmphasis.promotional:
|
||||||
|
return theme.accentTextLightPrimary
|
||||||
|
case ButtonEmphasis.highSoft:
|
||||||
|
return theme.accentAction
|
||||||
|
case ButtonEmphasis.low:
|
||||||
|
return theme.textSecondary
|
||||||
|
case ButtonEmphasis.warning:
|
||||||
|
return theme.accentWarning
|
||||||
|
case ButtonEmphasis.destructive:
|
||||||
|
return theme.accentTextDarkPrimary
|
||||||
|
case ButtonEmphasis.medium:
|
||||||
|
default:
|
||||||
|
return theme.textPrimary
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const BaseThemeButton = styled.button<BaseButtonProps>`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background-color: ${({ theme }) => theme.backgroundInteractive};
|
background-color: ${pickThemeButtonBackgroundColor};
|
||||||
border-radius: 16px;
|
border-radius: 16px;
|
||||||
border: 0;
|
border: 0;
|
||||||
color: ${({ theme }) => theme.textPrimary};
|
color: ${pickThemeButtonTextColor};
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
@ -379,20 +449,37 @@ export const MediumButton = styled.button`
|
|||||||
gap: 12px;
|
gap: 12px;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
transition: 150ms ease background-color opacity;
|
position: relative;
|
||||||
|
transition: 150ms ease opacity;
|
||||||
|
|
||||||
|
:active {
|
||||||
|
${ButtonOverlay} {
|
||||||
|
background-color: ${({ theme }) => theme.stateOverlayPressed};
|
||||||
|
}
|
||||||
|
}
|
||||||
:disabled {
|
:disabled {
|
||||||
background-color: ${({ theme }) => theme.backgroundInteractive};
|
|
||||||
cursor: default;
|
cursor: default;
|
||||||
opacity: 0.6;
|
opacity: 0.6;
|
||||||
}
|
}
|
||||||
|
:focus {
|
||||||
|
${ButtonOverlay} {
|
||||||
|
background-color: ${({ theme }) => theme.stateOverlayPressed};
|
||||||
|
}
|
||||||
|
}
|
||||||
:hover {
|
:hover {
|
||||||
|
${ButtonOverlay} {
|
||||||
background-color: ${({ theme }) => theme.stateOverlayHover};
|
background-color: ${({ theme }) => theme.stateOverlayHover};
|
||||||
}
|
}
|
||||||
:active {
|
|
||||||
background-color: ${({ theme }) => theme.stateOverlayPressed};
|
|
||||||
}
|
|
||||||
:focus {
|
|
||||||
background-color: ${({ theme }) => theme.stateOverlayPressed};
|
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
interface ThemeButtonProps extends React.ComponentPropsWithoutRef<'button'>, BaseButtonProps {}
|
||||||
|
|
||||||
|
export const ThemeButton = ({ children, ...rest }: ThemeButtonProps) => {
|
||||||
|
return (
|
||||||
|
<BaseThemeButton {...rest}>
|
||||||
|
<ButtonOverlay />
|
||||||
|
{children}
|
||||||
|
</BaseThemeButton>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { BigNumber } from '@ethersproject/bignumber'
|
import { BigNumber } from '@ethersproject/bignumber'
|
||||||
import { formatEther } from '@ethersproject/units'
|
import { formatEther } from '@ethersproject/units'
|
||||||
import clsx from 'clsx'
|
import clsx from 'clsx'
|
||||||
import { MediumButton } from 'components/Button'
|
import { ButtonEmphasis, ButtonSize, ThemeButton } from 'components/Button'
|
||||||
import { TimedLoader } from 'nft/components/bag/TimedLoader'
|
import { TimedLoader } from 'nft/components/bag/TimedLoader'
|
||||||
import { Box } from 'nft/components/Box'
|
import { Box } from 'nft/components/Box'
|
||||||
import { Column, Row } from 'nft/components/Flex'
|
import { Column, Row } from 'nft/components/Flex'
|
||||||
@ -24,13 +24,20 @@ import styled from 'styled-components/macro'
|
|||||||
|
|
||||||
import * as styles from './BagRow.css'
|
import * as styles from './BagRow.css'
|
||||||
|
|
||||||
const RemoveButton = styled(MediumButton)`
|
const RemoveButton = styled(ThemeButton)`
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
line-height: 16px;
|
line-height: 16px;
|
||||||
margin-left: 16px;
|
margin-left: 16px;
|
||||||
padding: 12px 14px;
|
padding: 12px 14px;
|
||||||
`
|
`
|
||||||
|
const ReviewButton = styled(ThemeButton)`
|
||||||
|
border-radius: 12px;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
font-size: 14px;
|
||||||
|
padding: 8px;
|
||||||
|
width: 50%;
|
||||||
|
`
|
||||||
|
|
||||||
const NoContentContainer = () => (
|
const NoContentContainer = () => (
|
||||||
<Box position="relative" background="loadingBackground" className={styles.bagRowImage}>
|
<Box position="relative" background="loadingBackground" className={styles.bagRowImage}>
|
||||||
@ -127,7 +134,11 @@ export const BagRow = ({ asset, usdPrice, removeAsset, showRemove, grayscale, is
|
|||||||
{asset.collectionIsVerified && <VerifiedIcon className={styles.icon} />}
|
{asset.collectionIsVerified && <VerifiedIcon className={styles.icon} />}
|
||||||
</Row>
|
</Row>
|
||||||
</Column>
|
</Column>
|
||||||
{showRemoveButton && <RemoveButton onClick={handleRemoveClick}>Remove</RemoveButton>}
|
{showRemoveButton && (
|
||||||
|
<RemoveButton onClick={handleRemoveClick} emphasis={ButtonEmphasis.medium} size={ButtonSize.medium}>
|
||||||
|
Remove
|
||||||
|
</RemoveButton>
|
||||||
|
)}
|
||||||
{(!showRemoveButton || isMobile) && (
|
{(!showRemoveButton || isMobile) && (
|
||||||
<Column flexShrink="0" alignItems="flex-end">
|
<Column flexShrink="0" alignItems="flex-end">
|
||||||
<Box className={styles.bagRowPrice}>
|
<Box className={styles.bagRowPrice}>
|
||||||
@ -152,6 +163,24 @@ interface PriceChangeBagRowProps {
|
|||||||
|
|
||||||
export const PriceChangeBagRow = ({ asset, usdPrice, markAssetAsReviewed, top, isMobile }: PriceChangeBagRowProps) => {
|
export const PriceChangeBagRow = ({ asset, usdPrice, markAssetAsReviewed, top, isMobile }: PriceChangeBagRowProps) => {
|
||||||
const isPriceIncrease = BigNumber.from(asset.updatedPriceInfo?.ETHPrice).gt(BigNumber.from(asset.priceInfo.ETHPrice))
|
const isPriceIncrease = BigNumber.from(asset.updatedPriceInfo?.ETHPrice).gt(BigNumber.from(asset.priceInfo.ETHPrice))
|
||||||
|
const handleRemove = useCallback(
|
||||||
|
(e: MouseEvent<HTMLButtonElement>) => {
|
||||||
|
e.preventDefault()
|
||||||
|
e.stopPropagation()
|
||||||
|
const toKeep = false
|
||||||
|
markAssetAsReviewed(asset, toKeep)
|
||||||
|
},
|
||||||
|
[asset, markAssetAsReviewed]
|
||||||
|
)
|
||||||
|
const handleKeep = useCallback(
|
||||||
|
(e: MouseEvent<HTMLButtonElement>) => {
|
||||||
|
e.preventDefault()
|
||||||
|
e.stopPropagation()
|
||||||
|
const toKeep = true
|
||||||
|
markAssetAsReviewed(asset, toKeep)
|
||||||
|
},
|
||||||
|
[asset, markAssetAsReviewed]
|
||||||
|
)
|
||||||
return (
|
return (
|
||||||
<Column className={styles.priceChangeColumn} borderTopColor={top ? 'backgroundOutline' : 'transparent'}>
|
<Column className={styles.priceChangeColumn} borderTopColor={top ? 'backgroundOutline' : 'transparent'}>
|
||||||
<Row className={styles.priceChangeRow}>
|
<Row className={styles.priceChangeRow}>
|
||||||
@ -163,27 +192,13 @@ export const PriceChangeBagRow = ({ asset, usdPrice, markAssetAsReviewed, top, i
|
|||||||
<Box style={{ marginLeft: '-8px', marginRight: '-8px' }}>
|
<Box style={{ marginLeft: '-8px', marginRight: '-8px' }}>
|
||||||
<BagRow asset={asset} usdPrice={usdPrice} removeAsset={() => undefined} isMobile={isMobile} />
|
<BagRow asset={asset} usdPrice={usdPrice} removeAsset={() => undefined} isMobile={isMobile} />
|
||||||
</Box>
|
</Box>
|
||||||
<Row gap="12" justifyContent="space-between">
|
<Row gap="8" justifyContent="space-between">
|
||||||
<Box
|
<ReviewButton onClick={handleRemove} emphasis={ButtonEmphasis.medium} size={ButtonSize.small}>
|
||||||
className={styles.removeButton}
|
|
||||||
onClick={(e: MouseEvent) => {
|
|
||||||
e.preventDefault()
|
|
||||||
e.stopPropagation()
|
|
||||||
markAssetAsReviewed(asset, false)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Remove
|
Remove
|
||||||
</Box>
|
</ReviewButton>
|
||||||
<Box
|
<ReviewButton onClick={handleKeep} emphasis={ButtonEmphasis.high} size={ButtonSize.small}>
|
||||||
className={styles.keepButton}
|
|
||||||
onClick={(e: MouseEvent) => {
|
|
||||||
e.preventDefault()
|
|
||||||
e.stopPropagation()
|
|
||||||
markAssetAsReviewed(asset, true)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Keep
|
Keep
|
||||||
</Box>
|
</ReviewButton>
|
||||||
</Row>
|
</Row>
|
||||||
</Column>
|
</Column>
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user