css modules, basic flexbox layout

This commit is contained in:
Jeff Colombo 2019-01-20 23:38:24 -05:00
parent 2ad47c55d0
commit c6c92db92a
20 changed files with 199 additions and 82 deletions

View File

@ -2,8 +2,8 @@
<html>
<head>
<title>PVP, ok? E-Mon.</title>
<style src="dist/global.css"></style>
<style src="dist/app.css"></style>
<link rel="stylesheet" href="dist/global.css" />
<link rel="stylesheet" href="dist/app.css" />
</head>
<body>
<div id="pokemon-mount"></div>

View File

@ -29,6 +29,7 @@
"babel-loader": "^8.0.4",
"babel-plugin-transform-builtin-extend": "^1.1.2",
"css-loader": "^2.1.0",
"css-modules-typescript-loader": "^1.1.1",
"fs": "^0.0.1-security",
"glob": "^7.1.3",
"mini-css-extract-plugin": "^0.5.0",

2
src/scss/Variables.scss Normal file
View File

@ -0,0 +1,2 @@
$background-color: #fff;
$border-color: #000;

View File

@ -1,3 +1,8 @@
@import './Variables.scss';
html,
body {
background: red;
height: 100vh;
margin: 0;
background: $background-color;
}

3
src/scss/index.scss.d.ts vendored Normal file
View File

@ -0,0 +1,3 @@
// This file is automatically generated.
// Please do not change this file!

View File

@ -12,6 +12,8 @@ import { IndividualValueKey } from './components/PokemonExplorer/types';
import { PokemonExplorer } from './components/PokemonExplorer/PokemonExplorer';
import { PokemonSelectList } from './components/PokemonSelectList/PokemonSelectList';
import * as styles from './styles/PokemonApp.scss';
type PokemonAppProps = ReturnType<typeof appReducers>;
interface IConnectedPokemonAppProps extends PokemonAppProps {
@ -39,7 +41,7 @@ class PokemonApp extends React.Component<IConnectedPokemonAppProps> {
} = this.props.pokemonExplorerState;
return (
<div>
<div className={ styles.wrapper }>
<PokemonSelectList
isLoading={ this.props.pokemonSelectListState.isLoading }
activePokemonIndex={ activePokemonIndex }

View File

@ -7,6 +7,8 @@ import classNames from 'classnames';
import { Grade, IStats } from 'app/models/Pokemon';
import { IIndividualValues } from './types';
import * as styles from './styles/LeagueStatsList.scss';
export interface ILeagueStatsListProps {
activeIndividualValues : IIndividualValues;
leagueStatsList : Array<IStats>;
@ -90,14 +92,14 @@ export class LeagueStatsList extends React.Component<ILeagueStatsListProps, ISta
};
return (
<div id="league-pokemon-select-list" style={ { height: '400px' } }>
<div className={ styles.selectList }>
<Measure
bounds={ true }
onResize={ onResize }
>
{
({ measureRef }) => (
<div ref={ measureRef } style={ { height: '100%' } }>
<div ref={ measureRef }>
<FixedSizeList
ref={ this.listRef }
height={ height }

View File

@ -7,6 +7,8 @@ import { IIndividualValues, IndividualValueKey } from './types';
import { LeagueStatsList } from './LeagueStatsList';
import * as styles from './styles/PokemonExplorer.scss';
export interface IPokemonExplorerProps {
isLoading : boolean;
leaguePokemon : ILeaguePokemon;
@ -116,79 +118,81 @@ export class PokemonExplorer extends React.Component<IPokemonExplorerProps, ISta
const rankedDef = rankedPokemon !== null ? rankedPokemon.def : '-';
return (
<div id="pokemon-explorer">
<h2 className="pokemon-info">
<span>{ this.formatDexNumber(leaguePokemon.dex) }</span>
{ leaguePokemon.name }
</h2>
<div className="pokemon-base-stats">
<div>Base Stats</div>
<div className="pokemon-type type-1">{ leaguePokemon.types.type1 }</div>
<div className="pokemon-type type-2">{ leaguePokemon.types.type2 }</div>
<div>{ leaguePokemon.stats.baseStamina }</div>
<div>{ leaguePokemon.stats.baseAttack }</div>
<div>{ leaguePokemon.stats.baseDefense }</div>
</div>
<div className="pokemon-individual-stats">
<div>
<h5>Level</h5>
<input
name="level"
type="number"
min={ this.MIN_LEVEL }
max={ this.MAX_LEVEL }
step={ 0.5 }
onChange={ this.handleChangeLevel }
value={ individualValueLevel !== null ? individualValueLevel : '' }
placeholder={ placeholderLevel }
/>
<div className={ styles.wrapper }>
<div>
<h2 className={ styles.pokemonInfo }>
<span>{ this.formatDexNumber(leaguePokemon.dex) }</span>
{ leaguePokemon.name }
</h2>
<div className={ styles.pokemonBaseStats }>
<div>Base Stats</div>
<div className="pokemon-type type-1">{ leaguePokemon.types.type1 }</div>
<div className="pokemon-type type-2">{ leaguePokemon.types.type2 }</div>
<div>{ leaguePokemon.stats.baseStamina }</div>
<div>{ leaguePokemon.stats.baseAttack }</div>
<div>{ leaguePokemon.stats.baseDefense }</div>
</div>
<div>
<h5>IVs</h5>
<label>
<div className={ styles.popkemonIndividualStats }>
<div>
<h5>Level</h5>
<input
name="hp"
name="level"
type="number"
min={ this.MIN_IV }
max={ this.MAX_IV }
maxLength={ 2 }
onChange={ this.handleChangeHp }
value={ individualValues.hp !== null ? individualValues.hp : '' }
placeholder={ placeholderHp }
/> HP
</label>
<label>
<input
name="atk"
type="number"
min={ this.MIN_IV }
max={ this.MAX_IV }
maxLength={ 2 }
onChange={ this.handleChangeAtk }
value={ individualValues.atk !== null ? individualValues.atk : '' }
placeholder={ placeholderAtk }
/> ATK
</label>
<label>
<input
name="def"
type="number"
min={ this.MIN_IV }
max={ this.MAX_IV }
maxLength={ 2 }
onChange={ this.handleChangeDef }
value={ individualValues.def !== null ? individualValues.def : '' }
placeholder={ placeholderDef }
/> DEF
</label>
min={ this.MIN_LEVEL }
max={ this.MAX_LEVEL }
step={ 0.5 }
onChange={ this.handleChangeLevel }
value={ individualValueLevel !== null ? individualValueLevel : '' }
placeholder={ placeholderLevel }
/>
</div>
<div>
<h5>IVs</h5>
<label>
<input
name="hp"
type="number"
min={ this.MIN_IV }
max={ this.MAX_IV }
maxLength={ 2 }
onChange={ this.handleChangeHp }
value={ individualValues.hp !== null ? individualValues.hp : '' }
placeholder={ placeholderHp }
/> HP
</label>
<label>
<input
name="atk"
type="number"
min={ this.MIN_IV }
max={ this.MAX_IV }
maxLength={ 2 }
onChange={ this.handleChangeAtk }
value={ individualValues.atk !== null ? individualValues.atk : '' }
placeholder={ placeholderAtk }
/> ATK
</label>
<label>
<input
name="def"
type="number"
min={ this.MIN_IV }
max={ this.MAX_IV }
maxLength={ 2 }
onChange={ this.handleChangeDef }
value={ individualValues.def !== null ? individualValues.def : '' }
placeholder={ placeholderDef }
/> DEF
</label>
</div>
</div>
<div className={ styles.leaguePokemonRank }>
<div className="league-pokemon-stat pokemon-rank"><span>{ rankedGrade }</span> Rank</div>
<div className="league-pokemon-stat pokemon-cp">CP <span>{ rankedCp }</span></div>
<div className="league-pokemon-stat"><span>{ rankedHp }</span> HP</div>
<div className="league-pokemon-stat"><span>{ rankedAtk }</span> ATK</div>
<div className="league-pokemon-stat"><span>{ rankedDef }</span> DEF</div>
</div>
</div>
<div className="league-pokemon-rank">
<div className="league-pokemon-stat pokemon-rank"><span>{ rankedGrade }</span> Rank</div>
<div className="league-pokemon-stat pokemon-cp">CP <span>{ rankedCp }</span></div>
<div className="league-pokemon-stat"><span>{ rankedHp }</span> HP</div>
<div className="league-pokemon-stat"><span>{ rankedAtk }</span> ATK</div>
<div className="league-pokemon-stat"><span>{ rankedDef }</span> DEF</div>
</div>
<LeagueStatsList
activeIndividualValues={ individualValues }

View File

@ -0,0 +1,12 @@
@import 'styles/Variables.scss';
.selectList {
flex: 1;
display: flex;
overflow: hidden;
& > * {
flex: 1;
overflow: auto;
}
}

View File

@ -0,0 +1,3 @@
// This file is automatically generated.
// Please do not change this file!
export const selectList: string;

View File

@ -0,0 +1,23 @@
@import 'styles/Variables.scss';
.wrapper {
display: flex;
flex-flow: column nowrap;
height: 100vh;
}
.pokemonInfo {
display: block;
}
.pokemonBaseStats {
display: block;
}
.popkemonIndividualStats {
display: block;
}
.leaguePokemonRank {
display: block;
}

View File

@ -0,0 +1,7 @@
// This file is automatically generated.
// Please do not change this file!
export const leaguePokemonRank: string;
export const pokemonBaseStats: string;
export const pokemonInfo: string;
export const popkemonIndividualStats: string;
export const wrapper: string;

View File

@ -6,6 +6,8 @@ import classNames from 'classnames';
import { IPokemon } from 'app/models/Pokemon';
import * as styles from './styles/PokemonSelectList.scss';
export interface IPokemonSelectListProps {
isLoading : boolean;
activePokemonIndex : number | null;
@ -48,17 +50,18 @@ export class PokemonSelectList extends React.Component<IPokemonSelectListProps,
};
const classes = classNames({
loading: this.props.isLoading,
[styles.leftPanel]: true,
});
return (
<div id="pokemon-select-list" className={ classes } style={ { height: '400px' } }>
<div id="pokemon-select-list" className={ classes }>
<Measure
bounds={ true }
onResize={ onResize }
>
{
({ measureRef }) => (
<div ref={ measureRef } style={ { height: '100%' } }>
<div ref={ measureRef }>
<FixedSizeList
height={ height }
itemCount={ this.props.pokemonList.length }

View File

@ -0,0 +1,11 @@
@import 'styles/Variables.scss';
.leftPanel {
height: 100vh;
border: 1px solid $border-color;
width: 20em;
& > * {
height: 100%;
}
}

View File

@ -0,0 +1,3 @@
// This file is automatically generated.
// Please do not change this file!
export const leftPanel: string;

View File

@ -13,8 +13,6 @@ import { PokemonSelectListReducers } from './components/PokemonSelectList/reduce
import { ConnectedPokemonApp } from './PokemonApp';
import 'styles/index.scss';
export const appReducers = Redux.combineReducers({
pokemonSelectListState: PokemonSelectListReducers,
pokemonExplorerState: PokemonExplorerReducers,

View File

@ -0,0 +1,12 @@
@import 'styles/Variables.scss';
.wrapper {
display: flex;
flex-flow: row nowrap;
align-items: stretch;
height: 100vh;
& > * {
flex: 1 auto;
}
}

View File

@ -0,0 +1,3 @@
// This file is automatically generated.
// Please do not change this file!
export const wrapper: string;

View File

@ -1,7 +1,7 @@
const path = require('path');
const options = require('./webpack.config.options');
const StyleLintPlugin = require('stylelint-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const typescriptResolve = {
alias: {
@ -111,10 +111,12 @@ module.exports = function (env) {
// publicPath: '../'
}
},
{ loader: 'css-modules-typescript-loader' },
{
loader: 'css-loader',
options: {
sourceMap: !!env.CSS_SOURCEMAPS
sourceMap: !!env.CSS_SOURCEMAPS,
modules: true,
}
},
{
@ -130,10 +132,12 @@ module.exports = function (env) {
exclude: /node_modules/,
use: [
{ loader: 'style-loader' },
{ loader: 'css-modules-typescript-loader' },
{
loader: 'css-loader',
options: {
sourceMap: !!env.CSS_SOURCEMAPS
sourceMap: !!env.CSS_SOURCEMAPS,
modules: true,
}
}
],

View File

@ -1903,6 +1903,13 @@ css-loader@^2.1.0:
postcss-value-parser "^3.3.0"
schema-utils "^1.0.0"
css-modules-typescript-loader@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/css-modules-typescript-loader/-/css-modules-typescript-loader-1.1.1.tgz#fe03e2f02ed620c5c6825958f6945395ddf1d0df"
integrity sha512-eAQ6o7ATdO+9UYhe6BPEOg8e5zTfaAjNqyqwzrUm4yex48n2dYgBejWVkjpvOQ2CjsV1pHLadwwDUFYU9F6Akg==
dependencies:
line-diff "^2.0.1"
css-selector-tokenizer@^0.7.0:
version "0.7.1"
resolved "https://registry.yarnpkg.com/css-selector-tokenizer/-/css-selector-tokenizer-0.7.1.tgz#a177271a8bca5019172f4f891fc6eed9cbf68d5d"
@ -3452,11 +3459,23 @@ left-pad@^1.3.0:
resolved "https://registry.yarnpkg.com/left-pad/-/left-pad-1.3.0.tgz#5b8a3a7765dfe001261dde915589e782f8c94d1e"
integrity sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA==
levdist@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/levdist/-/levdist-1.0.0.tgz#91d7a3044964f2ccc421a0477cac827fe75c5718"
integrity sha1-kdejBElk8szEIaBHfKyCf+dcVxg=
leven@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580"
integrity sha1-wuep93IJTe6dNCAq6KzORoeHVYA=
line-diff@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/line-diff/-/line-diff-2.0.1.tgz#d893ae8d81914cd65974fd57e714e730ce1e96a8"
integrity sha512-l+tt/aYyO+uyVyk5mzLgvoNYOkGR2iiFw5w2rWfFerfM7va0pje7n8LWdGk7Gl+Fkzw/bPZ0X9bvCBuTVLv8RA==
dependencies:
levdist "^1.0.0"
load-json-file@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0"