From e021dea1abcb0aebf55b873c17d71355da482706 Mon Sep 17 00:00:00 2001 From: Melvin Valster Date: Wed, 24 Jul 2019 23:27:23 +0200 Subject: [PATCH] Refactor, tweaks, clean-up, improve --- TODO.md | 1 + src/App.scss | 56 ++++++++--------- src/App.tsx | 12 +++- src/components/Calculator.tsx | 12 ++-- src/components/ClassPicker.scss | 31 ++++++++++ src/components/ClassPicker.tsx | 4 +- src/components/Icon.scss | 14 +++-- src/components/Icon.tsx | 31 +++++++--- src/components/IndexRoute.tsx | 6 +- src/components/Playground.scss | 9 +++ src/components/Playground.tsx | 99 ++++++++++++++++++++++++++++++ src/components/PlaygroundRoute.tsx | 71 --------------------- src/components/Tooltip.scss | 12 ++++ src/components/Tooltip.tsx | 2 +- src/lib/tree.ts | 2 +- src/sass/_config.scss | 26 ++++++-- 16 files changed, 258 insertions(+), 130 deletions(-) create mode 100644 src/components/ClassPicker.scss create mode 100644 src/components/Playground.scss create mode 100644 src/components/Playground.tsx delete mode 100644 src/components/PlaygroundRoute.tsx diff --git a/TODO.md b/TODO.md index cfa6319..1463f47 100644 --- a/TODO.md +++ b/TODO.md @@ -1,5 +1,6 @@ # TODO +- [ ] SCSS: Normalize - [ ] General: Add redux - [ ] General: Talent tooltips - [ ] General: Responsive on mobile diff --git a/src/App.scss b/src/App.scss index b35cda8..c009a84 100644 --- a/src/App.scss +++ b/src/App.scss @@ -4,6 +4,12 @@ body { color: white; background-color: #111; font-family: Verdana; + margin: 0; +} + +// Normalize etc. +ul { + margin: 0; } a { @@ -28,6 +34,17 @@ a { } } +.yellow { color: $color-yellow; } +.green { color: $quality-2; } + +.tight { + margin-bottom: 0; + + & + p { + margin-top: 0; + } +} + .calculator { &__points { color: white; @@ -69,35 +86,16 @@ a { } } -.class-picker { - display: flex; - list-style: none; - padding: 0; +.index { + min-height: 85vh; +} + +.index__class-picker { margin: 2em 0; +} - &--center { - justify-content: center; - } - - &__class { - margin-right: 1em; - opacity: 1; - transition: all .1s ease-out; - - &:hover { - opacity: 1; - } - - &--active { - opacity: 1; - } - - &--inactive { - opacity: .4; - - &:hover { - opacity: .5; - } - } - } +footer { + padding: 2em; + font-size: 12px; + text-align: center; } \ No newline at end of file diff --git a/src/App.tsx b/src/App.tsx index aaf4595..550e91a 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,8 +1,8 @@ import React from 'react' import './App.scss' import { IndexRoute } from './components/IndexRoute' -import { PlaygroundRoute } from './components/PlaygroundRoute' -import { BrowserRouter as Router, Route, Switch } from 'react-router-dom' +import { Playground } from './components/Playground' +import { BrowserRouter as Router, Route, Switch, Link } from 'react-router-dom' const App: React.FC = () => { return ( @@ -10,9 +10,15 @@ const App: React.FC = () => { {/* */}
- + + +
+ Home + {' - '} + Components +
); diff --git a/src/components/Calculator.tsx b/src/components/Calculator.tsx index 463b76d..3a98ab8 100644 --- a/src/components/Calculator.tsx +++ b/src/components/Calculator.tsx @@ -5,13 +5,12 @@ import { modifyTalentPoint, calcAvailablePoints, encodeKnownTalents, - SORT_TALENTS_BY_SPEC } from '../lib/tree' -import { talentsBySpec, talentsById } from '../data/talents' +import { talentsBySpec } from '../data/talents' import { classByName } from '../data/classes' import { History } from 'history' -import { spells } from '../data/spells' import { debugPrintKnown } from '../lib/debug' +import { Link } from 'react-router-dom'; interface Props { selectedClass: string @@ -96,10 +95,11 @@ export class Calculator extends React.PureComponent { Points: {availablePoints} +

Quick links

) diff --git a/src/components/ClassPicker.scss b/src/components/ClassPicker.scss new file mode 100644 index 0000000..89c7ba4 --- /dev/null +++ b/src/components/ClassPicker.scss @@ -0,0 +1,31 @@ +.class-picker { + display: flex; + list-style: none; + padding: 0; + + &--center { + justify-content: center; + } + + &__class { + margin-right: 1em; + opacity: 1; + transition: all .1s ease-out; + + &:hover { + opacity: 1; + } + + &--active { + opacity: 1; + } + + &--inactive { + opacity: .4; + + &:hover { + opacity: .5; + } + } + } +} \ No newline at end of file diff --git a/src/components/ClassPicker.tsx b/src/components/ClassPicker.tsx index d773c33..fdc8c93 100644 --- a/src/components/ClassPicker.tsx +++ b/src/components/ClassPicker.tsx @@ -1,3 +1,4 @@ +import './ClassPicker.scss' import React from 'react' import { Link } from 'react-router-dom' import { classByName } from '../data/classes' @@ -8,6 +9,7 @@ interface Props { /** Name of the selected class, lowercase */ selected?: string center?: boolean + className?: string } const classNameForItem = (c: ClassData, selected: string) => classNames('class-picker__class', { @@ -24,7 +26,7 @@ export class ClassPicker extends React.PureComponent { const cn = classNames('class-picker', { 'class-picker--has-selection': !!selected, 'class-picker--center': center, - }) + }, this.props.className) return (
    diff --git a/src/components/Icon.scss b/src/components/Icon.scss index 9bfd333..d17e190 100644 --- a/src/components/Icon.scss +++ b/src/components/Icon.scss @@ -60,17 +60,20 @@ } } - &--loading { + &--loaded { .icon__bg { - opacity: 0; + opacity: 1; + } + + &.icon--fade-in .icon__bg { + animation: fadeIn .1s forwards; } } &__bg { position: absolute; background-size: cover; - opacity: 1; - transition: all 100ms ease-out; + opacity: 0; } &__frame { @@ -79,4 +82,5 @@ background-repeat: no-repeat; background-size: contain; } -} \ No newline at end of file +} + diff --git a/src/components/Icon.tsx b/src/components/Icon.tsx index bd6bdaa..7b33739 100644 --- a/src/components/Icon.tsx +++ b/src/components/Icon.tsx @@ -3,31 +3,48 @@ import classNames from 'classnames' import './Icon.scss' interface Props { - name: string + name?: string size?: 'small' | 'medium' | 'large' golden?: boolean } -export const Icon: FC = ({ name, size = 'medium', golden = false, children }) => { - const [hasLoadedImage, setHasLoadedImage] = useState(false) +const NOT_FOUND_ICON = 'inv_misc_questionmark' + +export const Icon: FC = ({ name: defaultName, size = 'medium', golden = false, children }) => { + const [hasLoadedImage, setLoadedImage] = useState(false) + const [fadeIn, setFadeIn] = useState(false) + const [name, setName] = useState(defaultName) const bgSize = size !== 'small' ? 'large' : 'medium' const url = `https://wow.zamimg.com/images/wow/icons/${bgSize}/${name}.jpg` + const start = Date.now() + useEffect(() => { + if (!name) return const img = new Image() - img.onload = () => setHasLoadedImage(true) + img.onload = () => { + const loadTime = Date.now() - start + if (loadTime >= 300) { + setFadeIn(true) + } + setLoadedImage(true) + } + img.onerror = () => setName(NOT_FOUND_ICON) img.src = url - }, []) + }, [name, url]) const className = classNames('icon', `icon--${size}`, { 'icon--golden': golden, - 'icon--loading': !hasLoadedImage + 'icon--loaded': hasLoadedImage, + 'icon--fade-in': fadeIn, }) return (
    -
    + {name && +
    + }
    {children}
    diff --git a/src/components/IndexRoute.tsx b/src/components/IndexRoute.tsx index 8c5002f..71eea34 100644 --- a/src/components/IndexRoute.tsx +++ b/src/components/IndexRoute.tsx @@ -33,7 +33,11 @@ export class IndexRoute extends React.PureComponent { return (
    - + {selectedClass && +

    Rank 1/3

    +

    Your critical strikes cause the opponent to bleed, dealing 20% of your melee weapon's average damage over 12 sec.

    + +

    Next rank:

    +

    Your critical strikes cause the opponent to bleed, dealing 40% of your melee weapon's average damage over 12 sec.

    + +

    Click to learn

    + + +const Section: FC = (props) => { + return
    +
    +

    {props.title}

    + + {props.children} +
    +
    +} + +export class Playground extends React.PureComponent { + static whyDidYouRender = true + + render() { + return ( +
    +
    + +
    + +
    +

    Small Icons

    +
    + {iconNames.map((n) => )} +
    + +

    Medium Icons

    +
    + {iconNames.map((n) => )} +
    + +

    Large Icons

    +
    + {iconNames.map((n) => )} +
    +
    + +
    +

    No params

    + + +

    Simple text content

    + + +

    Using HTML inside

    + + I can use normal HTML in here +
    + And even link to exciting places! +
    + +

    Fixed width

    + {DEEP_WOUNDS} + +

    Overriding fixed width

    + {React.cloneElement(DEEP_WOUNDS, { + width: '500px' + })} + +

    No fixed

    + {React.cloneElement(DEEP_WOUNDS, { + fixed: false + })} +
    +
    + ) + } +} \ No newline at end of file diff --git a/src/components/PlaygroundRoute.tsx b/src/components/PlaygroundRoute.tsx deleted file mode 100644 index 9a250d9..0000000 --- a/src/components/PlaygroundRoute.tsx +++ /dev/null @@ -1,71 +0,0 @@ -import React from 'react' -import { ClassPicker } from './ClassPicker' -import { match } from 'react-router-dom' -import { RouteComponentProps } from 'react-router' -import { Icon } from './Icon'; -import { Tooltip } from './Tooltip'; - -interface Props extends RouteComponentProps { - match: match<{ - selectedClass: string - pointString: string - }> -} - -const iconNames = [ - 'foo', - 'spell_holy_prayerofhealing', - 'ability_sap', - 'class_shaman', - 'inv_ammo_firetar', - 'spell_shadow_requiem', -] - -export class PlaygroundRoute extends React.PureComponent { - static whyDidYouRender = true - - render() { - const { match, history } = this.props - - - - return ( -
    -

    Class Picker

    - - -

    Icons

    - -

    Small Icons

    -
    - {iconNames.map((n) => )} -
    - -

    Medium Icons

    -
    - {iconNames.map((n) => )} -
    - -

    Large Icons

    -
    - {iconNames.map((n) => )} -
    - -

    Tooltip

    - - - - I can use normal HTML in here -
    - And even link to exciting places! -
    - - - - - - -
    - ) - } -} \ No newline at end of file diff --git a/src/components/Tooltip.scss b/src/components/Tooltip.scss index ed15b66..68f18da 100644 --- a/src/components/Tooltip.scss +++ b/src/components/Tooltip.scss @@ -66,4 +66,16 @@ flex: 1; } } + + &__title { + font-size: 14px; + line-height: 1.3; + // margin-bottom: 1px; + } + + &__body { + p:last-child { + margin-bottom: 2px; + } + } } \ No newline at end of file diff --git a/src/components/Tooltip.tsx b/src/components/Tooltip.tsx index 0a55789..7a9d882 100644 --- a/src/components/Tooltip.tsx +++ b/src/components/Tooltip.tsx @@ -28,7 +28,7 @@ export const Tooltip: FC = (props) => {
    - {title} + {title &&
    {title}
    } {children}
    diff --git a/src/lib/tree.ts b/src/lib/tree.ts index 91de613..0786b8b 100644 --- a/src/lib/tree.ts +++ b/src/lib/tree.ts @@ -1,4 +1,4 @@ -import { List, Map, fromJS } from 'immutable' +import { Map } from 'immutable' import { talentsBySpec, talentToSpec, diff --git a/src/sass/_config.scss b/src/sass/_config.scss index 0eb1beb..5edc458 100644 --- a/src/sass/_config.scss +++ b/src/sass/_config.scss @@ -7,11 +7,13 @@ $col-offset: 44px; $col-gutter: 16px; $col-distance: $icon-size + $col-gutter; -$color-yellow: #ffd100; -$color-green: #1eff00; -$color-dark-green: #40bf40; -$color-subtle: #9d9d9d; -$color-icon-overlay: #6396d6; +// Item quality colours +$quality-0: #9d9d9d; +$quality-1: #fff; +$quality-2: #1eff00; +$quality-3: #0070dd; +$quality-4: #a335ee; +$quality-5: #ff8000; // Class colours $color-warrior: #c69b6d; @@ -23,3 +25,17 @@ $color-shaman: #2359ff; $color-mage: #68ccef; $color-warlock: #9382c9; $color-druid: #ff7c0a; + +// Colours used in app +$color-yellow: #ffd100; +$color-green: $quality-2; +$color-dark-green: #40bf40; +$color-subtle: $quality-0; +$color-icon-overlay: #6396d6; + +$color-description: $color-yellow; + +@keyframes fadeIn { + 0% { opacity: 0; } + 100% { opacity: 1; } +} \ No newline at end of file