diff --git a/src/components/CatalogCard/CatalogCard.css b/src/components/CatalogCard/CatalogCard.css index 9649cea2..37bdd7cf 100644 --- a/src/components/CatalogCard/CatalogCard.css +++ b/src/components/CatalogCard/CatalogCard.css @@ -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; } diff --git a/src/components/CatalogCard/CatalogCard.stories.tsx b/src/components/CatalogCard/CatalogCard.stories.tsx index f53fb9ea..11e88c97 100644 --- a/src/components/CatalogCard/CatalogCard.stories.tsx +++ b/src/components/CatalogCard/CatalogCard.stories.tsx @@ -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, + rarities_description: Rarity.getRarities().reduce((acc, rarity) => { + acc[rarity as string] = `This is the ${rarity} rarity` + return acc + }, {}) as unknown as Record +} + const props: CatalogCardProps = { asset: { id: '0x10cd9f15bb7d58ac0c8f4ec5e1b77c0f5df0b652-0', @@ -22,7 +33,8 @@ const props: CatalogCardProps = { extraInformation: 1 listing, notForSale: false, price: '10', - owners: '3 owners' + owners: '3 owners', + i18n } storiesOf('CatalogCard', module).add('Catalog', () => ( diff --git a/src/components/CatalogCard/CatalogCard.tsx b/src/components/CatalogCard/CatalogCard.tsx index 630aaad5..d3f47a3e 100644 --- a/src/components/CatalogCard/CatalogCard.tsx +++ b/src/components/CatalogCard/CatalogCard.tsx @@ -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 @@ -16,11 +17,12 @@ export type CatalogCardProps = { notForSale: boolean price?: string owners?: string -} +} & Pick export const CatalogCard = (props: CatalogCardProps) => { const { action, + i18n, actionIcon, asset, extraInformation, @@ -79,15 +81,12 @@ export const CatalogCard = (props: CatalogCardProps) => { {extraInformation} )} -
- {asset.rarity} -
+ ) : null} diff --git a/src/components/NFTCard/NFTCard.stories.tsx b/src/components/NFTCard/NFTCard.stories.tsx index 9438fca1..7932e46f 100644 --- a/src/components/NFTCard/NFTCard.stories.tsx +++ b/src/components/NFTCard/NFTCard.stories.tsx @@ -66,7 +66,7 @@ Emote.args = { bodyShapes: ['BaseMale', 'BaseFemale'], category: 'greetings', description: '', - rarity: 'common', + rarity: 'unique', loop: false, hasSound: true, hasGeometry: true diff --git a/src/components/NFTCard/NFTCard.tsx b/src/components/NFTCard/NFTCard.tsx index dde97855..03cf139c 100644 --- a/src/components/NFTCard/NFTCard.tsx +++ b/src/components/NFTCard/NFTCard.tsx @@ -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 ( + + + + } + /> + ) + } + + return ( + + {badge.icon && ( + + )} + {badge.label} + + ) +} + export const NFTCard = (props: Props) => { const { nft, @@ -47,41 +88,6 @@ export const NFTCard = (props: Props) => { return subtitle }, [subtitle]) - const renderBadge = useCallback((badge: Badge) => { - if (badge.icon && badge.hideLabel) { - return ( - - - - } - /> - ) - } - - return ( - - {badge.icon && ( - - )} - {badge.label} - - ) - }, []) - const renderBadges = useCallback(() => { if (badges) { return badges @@ -94,7 +100,9 @@ export const NFTCard = (props: Props) => { return (
- {nftBadges.map((badge) => renderBadge(badge))} + {nftBadges.map((badge) => ( + + ))}
) }, []) diff --git a/src/components/NFTCard/NFTCard.types.ts b/src/components/NFTCard/NFTCard.types.ts index 0faf3a16..ad6759b8 100644 --- a/src/components/NFTCard/NFTCard.types.ts +++ b/src/components/NFTCard/NFTCard.types.ts @@ -4,6 +4,7 @@ import { StrictCardProps } from '../Card/Card' export type Badge = { label: string color: string + textColor?: string icon?: string hideLabel?: boolean } diff --git a/src/components/NFTCard/utils.tsx b/src/components/NFTCard/utils.tsx index fc69762f..8e1c86b0 100644 --- a/src/components/NFTCard/utils.tsx +++ b/src/components/NFTCard/utils.tsx @@ -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, @@ -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], diff --git a/src/components/RarityBadge/RarityBadge.css b/src/components/RarityBadge/RarityBadge.css new file mode 100644 index 00000000..31f710de --- /dev/null +++ b/src/components/RarityBadge/RarityBadge.css @@ -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; +} diff --git a/src/components/RarityBadge/RarityBadge.stories.css b/src/components/RarityBadge/RarityBadge.stories.css new file mode 100644 index 00000000..db1904c6 --- /dev/null +++ b/src/components/RarityBadge/RarityBadge.stories.css @@ -0,0 +1,5 @@ +.dui-rarity-badge-story-wrapper { + display: flex; + flex-direction: column; + gap: 10px; +} diff --git a/src/components/RarityBadge/RarityBadge.stories.tsx b/src/components/RarityBadge/RarityBadge.stories.tsx new file mode 100644 index 00000000..0d0562f6 --- /dev/null +++ b/src/components/RarityBadge/RarityBadge.stories.tsx @@ -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, + rarities_description: Rarity.getRarities().reduce((acc, rarity) => { + acc[rarity as string] = `This is the ${rarity} rarity` + return acc + }, {}) as unknown as Record +} + +storiesOf('RarityBadge', module) + .add('Small size badges', () => { + return ( +
+ {Rarity.getRarities().map((rarity) => ( + alert(`Clicked ${rarity}!`)} + /> + ))} +
+ ) + }) + .add('Medium size badges', () => { + return ( +
+ {Rarity.getRarities().map((rarity) => ( + alert(`Clicked ${rarity}!`)} + /> + ))} +
+ ) + }) diff --git a/src/components/RarityBadge/RarityBadge.tsx b/src/components/RarityBadge/RarityBadge.tsx new file mode 100644 index 00000000..0201b877 --- /dev/null +++ b/src/components/RarityBadge/RarityBadge.tsx @@ -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 = ( +
+
+ + {i18n.rarities[rarity]} + +
+
+ ) + + return withTooltip ? ( + + ) : ( + trigger + ) +} + +RarityBadge.defaultProps = { + size: 'medium', + withTooltip: true +} + +export default React.memo(RarityBadge) diff --git a/src/components/RarityBadge/RarityBadge.types.ts b/src/components/RarityBadge/RarityBadge.types.ts new file mode 100644 index 00000000..369ffb6b --- /dev/null +++ b/src/components/RarityBadge/RarityBadge.types.ts @@ -0,0 +1,18 @@ +import { MouseEventHandler } from 'react' +import { Rarity } from '@dcl/schemas' + +export type RarityBadgeProps = { + rarity: Rarity + size: 'medium' | 'small' + withTooltip: boolean + className?: string + onClick?: MouseEventHandler + i18n: { + rarities: { + [keyof in Rarity]: string + } + rarities_description: { + [keyof in Rarity]: string + } + } +} diff --git a/src/components/RarityBadge/index.ts b/src/components/RarityBadge/index.ts new file mode 100644 index 00000000..21c20e0f --- /dev/null +++ b/src/components/RarityBadge/index.ts @@ -0,0 +1,4 @@ +import RarityBadge from './RarityBadge' + +export * from './RarityBadge.types' +export { RarityBadge } diff --git a/src/index.ts b/src/index.ts index fbeed62a..e2468d60 100644 --- a/src/index.ts +++ b/src/index.ts @@ -100,6 +100,7 @@ export * from './components/SmartIcon' export * from './components/CommunityBubble' export * from './components/AddressField' export * from './components/Loader/LoadingText' +export * from './components/RarityBadge' // Semantic components /* eslint-disable no-restricted-imports */ export * from 'semantic-ui-react' diff --git a/src/lib/colors.ts b/src/lib/colors.ts new file mode 100644 index 00000000..03413300 --- /dev/null +++ b/src/lib/colors.ts @@ -0,0 +1,10 @@ +/** + * Converts an hexadecimal color into a RGB one. + * @param hex - A color represented as a 8 digits hexadecimal color. + */ +export const hex2rgb = (hex: string): { r: number; g: number; b: number } => { + const r = parseInt(hex.slice(1, 3), 16) + const g = parseInt(hex.slice(3, 5), 16) + const b = parseInt(hex.slice(5, 7), 16) + return { r, g, b } +}