fix(bag): review asset buttons (#5182)

* fix(bag): review asset buttons

* clean up

* pr feedback
This commit is contained in:
Jordan Frankfurt 2022-11-14 18:34:49 -06:00 committed by GitHub
parent ce79774de9
commit 2970f9f1cb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 137 additions and 35 deletions

@ -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;
} }
:hover {
background-color: ${({ theme }) => theme.stateOverlayHover};
}
:active {
background-color: ${({ theme }) => theme.stateOverlayPressed};
}
:focus { :focus {
background-color: ${({ theme }) => theme.stateOverlayPressed}; ${ButtonOverlay} {
background-color: ${({ theme }) => theme.stateOverlayPressed};
}
}
:hover {
${ButtonOverlay} {
background-color: ${({ theme }) => theme.stateOverlayHover};
}
} }
` `
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>
) )