Add icon support to tooltip and add SpellTooltip component
This commit is contained in:
@@ -6,22 +6,24 @@ interface Props {
|
|||||||
name?: string
|
name?: string
|
||||||
size?: 'small' | 'medium' | 'large'
|
size?: 'small' | 'medium' | 'large'
|
||||||
golden?: boolean
|
golden?: boolean
|
||||||
|
className?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const NOT_FOUND_ICON = 'inv_misc_questionmark'
|
const NOT_FOUND_ICON = 'inv_misc_questionmark'
|
||||||
|
|
||||||
export const Icon: FC<Props> = ({ name: defaultName, size = 'medium', golden = false, children }) => {
|
export const Icon: FC<Props> = (props) => {
|
||||||
|
const { name: defaultName, size = 'medium', golden = false, children } = props
|
||||||
const [hasLoadedImage, setLoadedImage] = useState(false)
|
const [hasLoadedImage, setLoadedImage] = useState(false)
|
||||||
const [fadeIn, setFadeIn] = useState(false)
|
const [fadeIn, setFadeIn] = useState(false)
|
||||||
const [name, setName] = useState(defaultName)
|
const [name, setName] = useState(defaultName)
|
||||||
|
|
||||||
const bgSize = size !== 'small' ? 'large' : 'medium'
|
const bgSize = size !== 'small' ? 'large' : 'medium'
|
||||||
const url = `https://wow.zamimg.com/images/wow/icons/${bgSize}/${name}.jpg`
|
const url = name && `https://wow.zamimg.com/images/wow/icons/${bgSize}/${name}.jpg`
|
||||||
|
|
||||||
const start = Date.now()
|
const start = Date.now()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!name) return
|
if (!url) return
|
||||||
const img = new Image()
|
const img = new Image()
|
||||||
img.onload = () => {
|
img.onload = () => {
|
||||||
const loadTime = Date.now() - start
|
const loadTime = Date.now() - start
|
||||||
@@ -32,9 +34,9 @@ export const Icon: FC<Props> = ({ name: defaultName, size = 'medium', golden = f
|
|||||||
}
|
}
|
||||||
img.onerror = () => setName(NOT_FOUND_ICON)
|
img.onerror = () => setName(NOT_FOUND_ICON)
|
||||||
img.src = url
|
img.src = url
|
||||||
}, [name, url, start])
|
}, [url, start])
|
||||||
|
|
||||||
const className = classNames('icon', `icon--${size}`, {
|
const className = classNames('icon', `icon--${size}`, props.className, {
|
||||||
'icon--golden': golden,
|
'icon--golden': golden,
|
||||||
'icon--loaded': hasLoadedImage,
|
'icon--loaded': hasLoadedImage,
|
||||||
'icon--fade-in': fadeIn,
|
'icon--fade-in': fadeIn,
|
||||||
@@ -42,7 +44,7 @@ export const Icon: FC<Props> = ({ name: defaultName, size = 'medium', golden = f
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={className}>
|
<div className={className}>
|
||||||
{name &&
|
{url &&
|
||||||
<div className="icon__bg" style={{ backgroundImage: `url(${url})` }} />
|
<div className="icon__bg" style={{ backgroundImage: `url(${url})` }} />
|
||||||
}
|
}
|
||||||
<div className="icon__frame" />
|
<div className="icon__frame" />
|
||||||
|
|||||||
@@ -7,3 +7,9 @@
|
|||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.playground-section__spelltooltip {
|
||||||
|
.tooltip {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,6 +7,8 @@ import { Tooltip } from './Tooltip'
|
|||||||
import { Talent } from './Talent'
|
import { Talent } from './Talent'
|
||||||
import { talentsById } from '../data/talents'
|
import { talentsById } from '../data/talents'
|
||||||
import { Map } from 'immutable'
|
import { Map } from 'immutable'
|
||||||
|
import { SpellTooltip } from './SpellTooltip';
|
||||||
|
import classNames from 'classnames'
|
||||||
|
|
||||||
interface Props extends RouteComponentProps {
|
interface Props extends RouteComponentProps {
|
||||||
//
|
//
|
||||||
@@ -38,7 +40,7 @@ const DEEP_WOUNDS = <Tooltip title="Deep Wounds" fixed>
|
|||||||
|
|
||||||
const Section: FC<any> = (props) => {
|
const Section: FC<any> = (props) => {
|
||||||
return <div className="playground-section">
|
return <div className="playground-section">
|
||||||
<div className="container">
|
<div className={classNames('container', `playground-section__${props.title.toLowerCase()}`)}>
|
||||||
<h2>{props.title}</h2>
|
<h2>{props.title}</h2>
|
||||||
|
|
||||||
{props.children}
|
{props.children}
|
||||||
@@ -152,6 +154,11 @@ export class Playground extends React.PureComponent<Props> {
|
|||||||
And even <a href="/warrior">link</a> to exciting places!
|
And even <a href="/warrior">link</a> to exciting places!
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
||||||
|
<h3>With title and icon</h3>
|
||||||
|
<Tooltip title="Strongest Class in the World" icon="inv_pet_babymurlocs_blue">
|
||||||
|
<p className="yellow">And some description text here</p>
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
<h3>Fixed width</h3>
|
<h3>Fixed width</h3>
|
||||||
{DEEP_WOUNDS}
|
{DEEP_WOUNDS}
|
||||||
|
|
||||||
@@ -165,6 +172,12 @@ export class Playground extends React.PureComponent<Props> {
|
|||||||
fixed: false
|
fixed: false
|
||||||
})}
|
})}
|
||||||
</Section>
|
</Section>
|
||||||
|
|
||||||
|
<Section title="SpellTooltip">
|
||||||
|
<SpellTooltip id={29086} />
|
||||||
|
<SpellTooltip id={20501} />
|
||||||
|
<SpellTooltip id={17793} />
|
||||||
|
</Section>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
import React, { FC } from 'react'
|
||||||
|
import { Tooltip } from './Tooltip'
|
||||||
|
import spells from '../data/spells.json'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
id: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export const SpellTooltip: FC<Props> = ({ id }) => {
|
||||||
|
const spell: SpellData = spells[id.toString()]
|
||||||
|
if (!spell) {
|
||||||
|
return <Tooltip fixed>Spell not found :(</Tooltip>
|
||||||
|
}
|
||||||
|
|
||||||
|
return <Tooltip fixed title={spell.name} icon={spell.icon}>
|
||||||
|
{spell.rank &&
|
||||||
|
<p className="tight">Rank {spell.rank}</p>
|
||||||
|
}
|
||||||
|
<p className="yellow">{spell.description}</p>
|
||||||
|
</Tooltip>
|
||||||
|
}
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
height: 40px;
|
height: 40px;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
transition: filter .1s linear;
|
transition: filter .1s linear;
|
||||||
box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, .75);
|
box-shadow: 0px 1px 3px 0px rgba(0, 0, 0, .75);
|
||||||
filter: none;
|
filter: none;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ import './TalentTree.scss'
|
|||||||
import React, { useCallback } from 'react'
|
import React, { useCallback } from 'react'
|
||||||
import { Map } from 'immutable'
|
import { Map } from 'immutable'
|
||||||
import { Talent } from './Talent';
|
import { Talent } from './Talent';
|
||||||
import { getPointsInSpec, canLearnTalent, calcMeetsRequirements, SORT_TALENTS_DESC } from '../lib/tree';
|
import { getPointsInSpec, canLearnTalent, SORT_TALENTS_DESC } from '../lib/tree';
|
||||||
import { talentsBySpec, specNames, talentsById, talentToSpec } from '../data/talents'
|
import { talentsBySpec, specNames, talentsById } from '../data/talents'
|
||||||
import { Arrow } from './Arrow'
|
import { Arrow } from './Arrow'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@@ -36,9 +36,8 @@ export const TalentTree: React.FC<Props> = ({ specId, knownTalents, availablePoi
|
|||||||
const points = knownTalents.get(talent.id, 0)
|
const points = knownTalents.get(talent.id, 0)
|
||||||
const canLearn = canLearnTalent(knownTalents, talent)
|
const canLearn = canLearnTalent(knownTalents, talent)
|
||||||
|
|
||||||
return <React.Fragment>
|
return <React.Fragment key={talent.id}>
|
||||||
<Talent
|
<Talent
|
||||||
key={talent.id}
|
|
||||||
talent={talent}
|
talent={talent}
|
||||||
points={points}
|
points={points}
|
||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
@@ -48,7 +47,6 @@ export const TalentTree: React.FC<Props> = ({ specId, knownTalents, availablePoi
|
|||||||
|
|
||||||
{!!talent.requires.length &&
|
{!!talent.requires.length &&
|
||||||
<Arrow
|
<Arrow
|
||||||
key={`arrow-${talent.id}`}
|
|
||||||
from={talentsById[talent.requires[0].id]}
|
from={talentsById[talent.requires[0].id]}
|
||||||
to={talent}
|
to={talent}
|
||||||
active={points > 0 || canLearn}
|
active={points > 0 || canLearn}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
&__body {
|
&__body {
|
||||||
min-height: 2px;
|
min-height: 2px;
|
||||||
padding: 8px 4px 2px 10px;
|
padding: 8px 3px 2px 9px;
|
||||||
background: url('../images/tooltip-background.png');
|
background: url('../images/tooltip-background.png');
|
||||||
background-position: top left;
|
background-position: top left;
|
||||||
}
|
}
|
||||||
@@ -50,16 +50,17 @@
|
|||||||
|
|
||||||
.tooltip {
|
.tooltip {
|
||||||
@include tooltip-base;
|
@include tooltip-base;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
&--inline {
|
&--inline {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
&--fixed {
|
&--fixed {
|
||||||
width: 320px;
|
|
||||||
|
|
||||||
.tooltip__inner {
|
.tooltip__inner {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
width: 320px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tooltip__body {
|
.tooltip__body {
|
||||||
@@ -67,10 +68,14 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__icon {
|
||||||
|
margin-right: .25em;
|
||||||
|
transform: translateY(2px);
|
||||||
|
}
|
||||||
|
|
||||||
&__title {
|
&__title {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
line-height: 1.3;
|
line-height: 1.3;
|
||||||
// margin-bottom: 1px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&__body {
|
&__body {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import './Tooltip.scss'
|
import './Tooltip.scss'
|
||||||
import React, { FC } from 'react'
|
import React, { FC } from 'react'
|
||||||
import classNames from 'classnames'
|
import classNames from 'classnames'
|
||||||
|
import { Icon } from './Icon'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
title?: string
|
title?: string
|
||||||
@@ -10,6 +11,8 @@ interface Props {
|
|||||||
fixed?: boolean
|
fixed?: boolean
|
||||||
/** Display tooltip inline */
|
/** Display tooltip inline */
|
||||||
inline?: boolean
|
inline?: boolean
|
||||||
|
/** Icon to show next to tooltip */
|
||||||
|
icon?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Tooltip: FC<Props> = (props) => {
|
export const Tooltip: FC<Props> = (props) => {
|
||||||
@@ -24,8 +27,11 @@ export const Tooltip: FC<Props> = (props) => {
|
|||||||
width: props.width
|
width: props.width
|
||||||
}
|
}
|
||||||
|
|
||||||
return <div className={cn} style={style}>
|
return <div className={cn}>
|
||||||
<div className="tooltip__inner">
|
{props.icon &&
|
||||||
|
<Icon className="tooltip__icon" name={props.icon} />
|
||||||
|
}
|
||||||
|
<div className="tooltip__inner" style={style}>
|
||||||
<div className="tooltip__top">
|
<div className="tooltip__top">
|
||||||
<div className="tooltip__body">
|
<div className="tooltip__body">
|
||||||
{title && <div className="tooltip__title tight">{title}</div>}
|
{title && <div className="tooltip__title tight">{title}</div>}
|
||||||
|
|||||||
Reference in New Issue
Block a user