Skip to content

Commit

Permalink
feat: Add new rarity badge (#529)
Browse files Browse the repository at this point in the history
* feat: Add new rarity badge

* fix: Wrap the badge with a background
  • Loading branch information
LautaroPetaccio authored Apr 5, 2024
1 parent edbae59 commit e7808e1
Show file tree
Hide file tree
Showing 15 changed files with 255 additions and 62 deletions.
10 changes: 0 additions & 10 deletions src/components/CatalogCard/CatalogCard.css
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,6 @@
}

.CatalogCard .badge {
display: inline-flex;
align-items: center;
text-transform: uppercase;
border-radius: 5px;
cursor: pointer;
padding: 3px 6px;
height: 24px;
font-size: 13px;
color: white;
width: fit-content;
margin-top: 10px;
}

Expand Down
14 changes: 13 additions & 1 deletion src/components/CatalogCard/CatalogCard.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,17 @@ import { HeaderMenu } from '../HeaderMenu/HeaderMenu'
import { CatalogCard, CatalogCardProps } from './CatalogCard'
import { Rarity, Network } from '@dcl/schemas'

const i18n = {
rarities: Rarity.getRarities().reduce((acc, rarity) => {
acc[rarity as string] = rarity
return acc
}, {}) as unknown as Record<Rarity, string>,
rarities_description: Rarity.getRarities().reduce((acc, rarity) => {
acc[rarity as string] = `This is the ${rarity} rarity`
return acc
}, {}) as unknown as Record<Rarity, string>
}

const props: CatalogCardProps = {
asset: {
id: '0x10cd9f15bb7d58ac0c8f4ec5e1b77c0f5df0b652-0',
Expand All @@ -22,7 +33,8 @@ const props: CatalogCardProps = {
extraInformation: <span>1 listing</span>,
notForSale: false,
price: '10',
owners: '3 owners'
owners: '3 owners',
i18n
}

storiesOf('CatalogCard', module).add('Catalog', () => (
Expand Down
23 changes: 11 additions & 12 deletions src/components/CatalogCard/CatalogCard.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import React from 'react'
import classNames from 'classnames'
import { Network, Rarity, Item } from '@dcl/schemas'
import { Network, Item } from '@dcl/schemas'
import { Mana } from '../Mana/Mana'
import { Card } from '../Card/Card'
import { Profile } from '../Profile/Profile'
import './CatalogCard.css'
import { AssetImage } from '../AssetImage/AssetImage'
import { RarityBadge, RarityBadgeProps } from '../RarityBadge'
import './CatalogCard.css'

export type CatalogCardProps = {
asset: Pick<Item, 'id' | 'url' | 'name' | 'rarity' | 'network' | 'creator'>
Expand All @@ -16,11 +17,12 @@ export type CatalogCardProps = {
notForSale: boolean
price?: string
owners?: string
}
} & Pick<RarityBadgeProps, 'i18n'>

export const CatalogCard = (props: CatalogCardProps) => {
const {
action,
i18n,
actionIcon,
asset,
extraInformation,
Expand Down Expand Up @@ -79,15 +81,12 @@ export const CatalogCard = (props: CatalogCardProps) => {
<span className={'extraInformation'}>{extraInformation}</span>
)}
</div>
<div
className={'badge'}
style={{
backgroundColor: Rarity.getColor(asset.rarity)
}}
title={asset.rarity}
>
<span className={'text'}>{asset.rarity}</span>
</div>
<RarityBadge
i18n={i18n}
rarity={asset.rarity}
withTooltip={false}
className="badge"
/>
</Card.Content>
</>
) : null}
Expand Down
2 changes: 1 addition & 1 deletion src/components/NFTCard/NFTCard.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ Emote.args = {
bodyShapes: ['BaseMale', 'BaseFemale'],
category: 'greetings',
description: '',
rarity: 'common',
rarity: 'unique',
loop: false,
hasSound: true,
hasGeometry: true
Expand Down
80 changes: 44 additions & 36 deletions src/components/NFTCard/NFTCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,47 @@ import { getBadges, getSubtitle } from './utils'
import { Badge, Props } from './NFTCard.types'
import './NFTCard.css'

const Badge = ({ badge }: { badge: Badge }) => {
if (badge.icon && badge.hideLabel) {
return (
<Popup
key={badge.label}
content={badge.label}
trigger={
<span
className="dui-nft-card__badge--only-icon"
style={{
background: badge.color,
color: badge.textColor ?? 'var(--text)'
}}
>
<i
className={classNames('dui-nft-card__badge-icon', badge.icon)}
aria-label={badge.label}
/>
</span>
}
/>
)
}

return (
<span
className="dui-nft-card__badge"
style={{
background: badge.color,
color: badge.textColor ?? 'var(--text)'
}}
key={badge.label}
>
{badge.icon && (
<i className={classNames('dui-nft-card__badge-icon', badge.icon)} />
)}
{badge.label}
</span>
)
}

export const NFTCard = (props: Props) => {
const {
nft,
Expand Down Expand Up @@ -47,41 +88,6 @@ export const NFTCard = (props: Props) => {
return subtitle
}, [subtitle])

const renderBadge = useCallback((badge: Badge) => {
if (badge.icon && badge.hideLabel) {
return (
<Popup
key={badge.label}
content={badge.label}
trigger={
<span
className="dui-nft-card__badge--only-icon"
style={{ background: badge.color }}
>
<i
className={classNames('dui-nft-card__badge-icon', badge.icon)}
aria-label={badge.label}
/>
</span>
}
/>
)
}

return (
<span
className="dui-nft-card__badge"
style={{ background: badge.color }}
key={badge.label}
>
{badge.icon && (
<i className={classNames('dui-nft-card__badge-icon', badge.icon)} />
)}
{badge.label}
</span>
)
}, [])

const renderBadges = useCallback(() => {
if (badges) {
return badges
Expand All @@ -94,7 +100,9 @@ export const NFTCard = (props: Props) => {

return (
<div className="dui-nft-card__badges">
{nftBadges.map((badge) => renderBadge(badge))}
{nftBadges.map((badge) => (
<Badge key={badge.label} badge={badge} />
))}
</div>
)
}, [])
Expand Down
1 change: 1 addition & 0 deletions src/components/NFTCard/NFTCard.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { StrictCardProps } from '../Card/Card'
export type Badge = {
label: string
color: string
textColor?: string
icon?: string
hideLabel?: boolean
}
Expand Down
17 changes: 15 additions & 2 deletions src/components/NFTCard/utils.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
import React from 'react'
import { BodyShape, NFT, NFTCategory, Rarity } from '@dcl/schemas'
import { hex2rgb } from '../../lib/colors'
import { Profile } from '../Profile/Profile'
import { Badge, NFTCardI18N } from './NFTCard.types'

const DEFAULT_BADGE_COLOR = '#37333d'

function _getEmoteBadges(emote: NFT['data']['emote'], i18n: NFTCardI18N) {
const [lightColor, regularColor] = Rarity.getGradient(emote.rarity)
const hexColor = hex2rgb(regularColor)
return [
{ color: Rarity.getColor(emote.rarity), label: emote.rarity },
{
color: `rgb(${hexColor.r} ${hexColor.g} ${hexColor.b} / 20%)`,
label: emote.rarity,
textColor: lightColor
},
{
color: DEFAULT_BADGE_COLOR,
label: emote.loop ? i18n.playMode.loop : i18n.playMode.once,
Expand Down Expand Up @@ -39,8 +46,14 @@ function _getWearableBadges(
: wearable.bodyShapes[0] === BodyShape.MALE
? 'male'
: 'female'
const [lightColor, regularColor] = Rarity.getGradient(wearable.rarity)
const hexColor = hex2rgb(regularColor)
return [
{ color: Rarity.getColor(wearable.rarity), label: wearable.rarity },
{
color: `rgb(${hexColor.r} ${hexColor.g} ${hexColor.b} / 20%)`,
label: wearable.rarity,
textColor: lightColor
},
{
color: DEFAULT_BADGE_COLOR,
label: i18n.category[wearable.category],
Expand Down
27 changes: 27 additions & 0 deletions src/components/RarityBadge/RarityBadge.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
.dui-rarity-badge {
display: inline-flex;
align-items: center;
text-transform: uppercase;
border-radius: 5px;
width: fit-content;
background-color: var(--background);
}

.dui-rarity-badge .wrapper {
border-radius: 5px;
}

.dui-rarity-badge .wrapper.medium {
padding: 4px 12px;
}
.dui-rarity-badge .wrapper.medium .text {
font-size: 15px;
}

.dui-rarity-badge .wrapper.small {
padding: 3px 6px;
height: 24px;
}
.dui-rarity-badge .wrapper.small .text {
font-size: 13px;
}
5 changes: 5 additions & 0 deletions src/components/RarityBadge/RarityBadge.stories.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.dui-rarity-badge-story-wrapper {
display: flex;
flex-direction: column;
gap: 10px;
}
47 changes: 47 additions & 0 deletions src/components/RarityBadge/RarityBadge.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import React from 'react'
import { Rarity } from '@dcl/schemas'
import { storiesOf } from '@storybook/react'
import RarityBadge from './RarityBadge'
import './RarityBadge.stories.css'

const i18n = {
rarities: Rarity.getRarities().reduce((acc, rarity) => {
acc[rarity as string] = rarity
return acc
}, {}) as unknown as Record<Rarity, string>,
rarities_description: Rarity.getRarities().reduce((acc, rarity) => {
acc[rarity as string] = `This is the ${rarity} rarity`
return acc
}, {}) as unknown as Record<Rarity, string>
}

storiesOf('RarityBadge', module)
.add('Small size badges', () => {
return (
<div className="dui-rarity-badge-story-wrapper">
{Rarity.getRarities().map((rarity) => (
<RarityBadge
key={rarity}
i18n={i18n}
rarity={rarity}
size="small"
onClick={() => alert(`Clicked ${rarity}!`)}
/>
))}
</div>
)
})
.add('Medium size badges', () => {
return (
<div className="dui-rarity-badge-story-wrapper">
{Rarity.getRarities().map((rarity) => (
<RarityBadge
key={rarity}
i18n={i18n}
rarity={rarity}
onClick={() => alert(`Clicked ${rarity}!`)}
/>
))}
</div>
)
})
58 changes: 58 additions & 0 deletions src/components/RarityBadge/RarityBadge.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import React from 'react'
import classnames from 'classnames'
import { Rarity } from '@dcl/schemas'
import { hex2rgb } from '../../lib/colors'
import { Popup } from '../Popup/Popup'
import { RarityBadgeProps } from './RarityBadge.types'
import './RarityBadge.css'

const RarityBadge = ({
rarity,
className,
size,
withTooltip,
i18n,
onClick
}: RarityBadgeProps) => {
const [lightColor, regularColor] = Rarity.getGradient(rarity)
const hexColor = hex2rgb(regularColor)

const trigger = (
<div
className={classnames('dui-rarity-badge', className)}
style={{
cursor: onClick ? 'pointer' : 'default'
}}
title={!withTooltip ? i18n.rarities_description[rarity] : ''}
onClick={onClick}
>
<div
className={classnames('wrapper', size)}
style={{
backgroundColor: `rgb(${hexColor.r} ${hexColor.g} ${hexColor.b} / 20%)`
}}
>
<span className="text" style={{ color: lightColor }}>
{i18n.rarities[rarity]}
</span>
</div>
</div>
)

return withTooltip ? (
<Popup
position="top center"
content={i18n.rarities_description[rarity]}
trigger={trigger}
/>
) : (
trigger
)
}

RarityBadge.defaultProps = {
size: 'medium',
withTooltip: true
}

export default React.memo(RarityBadge)
Loading

0 comments on commit e7808e1

Please sign in to comment.