Make modal great again

This commit is contained in:
Anders Englöf Ytterström 2020-03-05 21:48:45 +01:00
parent 755cf14828
commit 9bcf0ecc56
10 changed files with 145 additions and 53 deletions

View file

@ -3,7 +3,8 @@ body {
background-color: #111; background-color: #111;
color: #aaa; color: #aaa;
font-size: large; font-size: large;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif; font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto,
Helvetica Neue, Arial, sans-serif;
padding: 0; padding: 0;
margin: 0 auto; margin: 0 auto;
max-width: 80em; max-width: 80em;
@ -18,7 +19,8 @@ a:visited {
text-decoration: line-through; text-decoration: line-through;
} }
a:hover, a:focus { a:hover,
a:focus {
color: #fff; color: #fff;
} }
@ -62,43 +64,55 @@ p:last-child {
margin-bottom: 0; margin-bottom: 0;
} }
input { /* === /Base === */
/* === Field === */
.field {
background-color: #333; background-color: #333;
color: #fff; color: #fff;
border-width: 0; border-width: 0;
border-radius: 5px; border-radius: 5px;
font-size: large; font-size: large;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif; font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto,
padding: .5rem 1rem; Helvetica Neue, Arial, sans-serif;
padding: 0.5rem 1rem;
display: block; display: block;
width: 100%; width: 100%;
box-sizing: border-box; box-sizing: border-box;
margin-top: 0.5em; margin-top: 0.5em;
} }
input:hover { .field:hover {
background-color: #444; background-color: #444;
} }
input:focus { .field:focus {
background-color: #fff; background-color: #fff;
color: #000; color: #000;
} }
@media (min-width: 500px) { @media (min-width: 500px) {
input { .field {
min-width: 17em;
margin-top: 0; margin-top: 0;
} }
input.field {
min-width: 17em;
}
} }
/* === /Base === */ /* === /Field === */
/* === Helpers === */ /* === Helpers === */
.blur { .blur {
filter: blur(25px); filter: blur(25px);
} }
.visuallyhidden {
position: absolute;
left: -9999em;
}
/* === /Helpers === */ /* === /Helpers === */
/* === Albums === */ /* === Albums === */
@ -136,6 +150,7 @@ input:focus {
@media (min-width: 500px) { @media (min-width: 500px) {
.album__cover { .album__cover {
margin: 0 0 0.5em; margin: 0 0 0.5em;
width: 100%;
padding-top: 0; padding-top: 0;
} }
} }
@ -143,6 +158,7 @@ input:focus {
@media (min-width: 1200px) { @media (min-width: 1200px) {
.album__cover { .album__cover {
margin: 0 1em 0 0; margin: 0 1em 0 0;
width: auto;
padding-top: 0; padding-top: 0;
} }
} }
@ -155,7 +171,7 @@ input:focus {
.album__cover__media:after { .album__cover__media:after {
position: absolute; position: absolute;
content: ''; content: "";
top: 0; top: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
@ -197,31 +213,51 @@ input:focus {
right: 0; right: 0;
bottom: 0; bottom: 0;
left: 0; left: 0;
display: flex;
align-items: center;
justify-content: center;
} }
.selected-album__inner { .selected-album__inner {
display: flex;
height: 100%;
overflow: auto; overflow: auto;
border: 3px solid #a83;
background: black;
padding: 2em;
max-height: 80%;
display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
justify-content: center;
} }
.selected-album__summary { .selected-album__summary {
text-transform: uppercase; text-transform: uppercase;
padding: 0.5em; padding: 0.5em;
background-color: #000;
margin-bottom: 0.5em; margin-bottom: 0.5em;
} }
.selected-album__description { .selected-album__description {
color: #fff; color: #fff;
padding: 0.5rem; padding: 0 0.5rem 2em;
overflow: auto; margin: 0 auto;
margin: 0;
max-width: 40em; max-width: 40em;
background-color: #000; }
.selected-album__cover {
display: none;
}
@media (min-width: 1200px) {
.selected-album__cover {
display: block;
width: 75vh;
max-width: 900px;
height: auto;
}
.selected-album__media {
width: 100%;
height: auto;
}
} }
/* === /Selected album === */ /* === /Selected album === */

41
package-lock.json generated
View file

@ -3659,7 +3659,8 @@
"ansi-regex": { "ansi-regex": {
"version": "2.1.1", "version": "2.1.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"aproba": { "aproba": {
"version": "1.2.0", "version": "1.2.0",
@ -3680,12 +3681,14 @@
"balanced-match": { "balanced-match": {
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"brace-expansion": { "brace-expansion": {
"version": "1.1.11", "version": "1.1.11",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"balanced-match": "^1.0.0", "balanced-match": "^1.0.0",
"concat-map": "0.0.1" "concat-map": "0.0.1"
@ -3700,17 +3703,20 @@
"code-point-at": { "code-point-at": {
"version": "1.1.0", "version": "1.1.0",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"concat-map": { "concat-map": {
"version": "0.0.1", "version": "0.0.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"console-control-strings": { "console-control-strings": {
"version": "1.1.0", "version": "1.1.0",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"core-util-is": { "core-util-is": {
"version": "1.0.2", "version": "1.0.2",
@ -3827,7 +3833,8 @@
"inherits": { "inherits": {
"version": "2.0.4", "version": "2.0.4",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"ini": { "ini": {
"version": "1.3.5", "version": "1.3.5",
@ -3839,6 +3846,7 @@
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"number-is-nan": "^1.0.0" "number-is-nan": "^1.0.0"
} }
@ -3853,6 +3861,7 @@
"version": "3.0.4", "version": "3.0.4",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"brace-expansion": "^1.1.7" "brace-expansion": "^1.1.7"
} }
@ -3860,12 +3869,14 @@
"minimist": { "minimist": {
"version": "0.0.8", "version": "0.0.8",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"minipass": { "minipass": {
"version": "2.9.0", "version": "2.9.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"safe-buffer": "^5.1.2", "safe-buffer": "^5.1.2",
"yallist": "^3.0.0" "yallist": "^3.0.0"
@ -3884,6 +3895,7 @@
"version": "0.5.1", "version": "0.5.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"minimist": "0.0.8" "minimist": "0.0.8"
} }
@ -3973,7 +3985,8 @@
"number-is-nan": { "number-is-nan": {
"version": "1.0.1", "version": "1.0.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"object-assign": { "object-assign": {
"version": "4.1.1", "version": "4.1.1",
@ -3985,6 +3998,7 @@
"version": "1.4.0", "version": "1.4.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"wrappy": "1" "wrappy": "1"
} }
@ -4070,7 +4084,8 @@
"safe-buffer": { "safe-buffer": {
"version": "5.1.2", "version": "5.1.2",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"safer-buffer": { "safer-buffer": {
"version": "2.1.2", "version": "2.1.2",
@ -4106,6 +4121,7 @@
"version": "1.0.2", "version": "1.0.2",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"code-point-at": "^1.0.0", "code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0", "is-fullwidth-code-point": "^1.0.0",
@ -4125,6 +4141,7 @@
"version": "3.0.1", "version": "3.0.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"ansi-regex": "^2.0.0" "ansi-regex": "^2.0.0"
} }
@ -4168,12 +4185,14 @@
"wrappy": { "wrappy": {
"version": "1.0.2", "version": "1.0.2",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"yallist": { "yallist": {
"version": "3.1.1", "version": "3.1.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
} }
} }
}, },

View file

@ -20,6 +20,6 @@ export default (props: Props) => {
type Props = { type Props = {
albums: Array<interfaces.Album>; albums: Array<interfaces.Album>;
handleOnClick: Function; handleOnClick(album: interfaces.Album): void;
blurred: boolean; blurred: boolean;
}; };

View file

@ -40,5 +40,5 @@ export default (props: Props) => {
type Props = { type Props = {
key: number; key: number;
album: Album; album: Album;
handleOnClick: Function; handleOnClick(album: Album): void;
}; };

View file

@ -1,12 +1,14 @@
import React from "react"; import React from "react";
import AlbumList from "../containers/album-list"; import AlbumList from "../containers/album-list";
import FilterInput from "../containers/filter-input"; import FilterInput from "../containers/filter-input";
import SortSelect from "../containers/sort-select";
import Modal from "../containers/modal"; import Modal from "../containers/modal";
export default () => ( export default () => (
<React.Fragment> <React.Fragment>
<header> <header>
<h1>Brütal Legend</h1> <h1>Brütal Legend</h1>
<SortSelect />
<FilterInput /> <FilterInput />
</header> </header>
<AlbumList /> <AlbumList />

View file

@ -7,7 +7,10 @@ export default (props: Props) => {
<input <input
type="text" type="text"
value={value} value={value}
onChange={evt => handleOnChange(evt.target.value)} className="field"
onChange={(evt: { target: HTMLInputElement }) =>
handleOnChange(evt.target.value)
}
placeholder="Filtrera på år, artist, låt, skivtitel ..." placeholder="Filtrera på år, artist, låt, skivtitel ..."
/> />
</div> </div>
@ -16,5 +19,5 @@ export default (props: Props) => {
type Props = { type Props = {
value: string; value: string;
handleOnChange: Function; handleOnChange(filterValue: string): void;
}; };

View file

@ -2,26 +2,49 @@ import React from "react";
import { Album } from "../interfaces"; import { Album } from "../interfaces";
export default (props: Props) => { export default (props: Props) => {
const handleKeyPress = (e: KeyboardEvent, callback: Function) => { const handleKeyPress = (
console.log(e.charCode); keyPressed: string,
callback(); albumId: number,
close: Function
//goto: Function
) => {
if (keyPressed === "Escape") {
close();
}
// } else if (keyPressed === "ArrowRight") {
// goto(albumId, 1);
// } else if (keyPressed === "ArrowLeft") {
// goto(albumId, -1);
// }
}; };
const { album, handleOnClick } = props; const { album, close /*goto*/ } = props;
const { id, artist, title, songs, year, img, description } = album; const { id, artist, title, songs, year, img, description } = album;
if (id === undefined) { if (id === undefined) {
return ""; return "";
} }
// const imagePath = `assets/covers/${img}`;
const imagePath = `./covers/${img}`;
const song = songs.join(", "); const song = songs.join(", ");
document.onkeyup = (e: KeyboardEvent) =>
handleKeyPress(e.key, album.id, close /*goto*/);
return ( return (
<div <div
className="selected-album" className="selected-album blurred"
tabIndex={0} tabIndex={0}
onClick={() => handleOnClick()} onClick={() => close()}
onKeyPress={e => handleKeyPress(e, handleOnClick)}
> >
<div className="selected-album__inner"> <div className="selected-album__inner">
<figure className="selected-album__cover">
<img
src={imagePath}
alt="cover"
className="selected-album__media"
/>
</figure>
<span className="selected-album__summary"> <span className="selected-album__summary">
#{id + 1}: {artist} - {song}, från "{title}" ({year}) #{id + 1}: {artist} - {song}, från "{title}" ({year})
<br /> <br />
@ -38,5 +61,6 @@ export default (props: Props) => {
type Props = { type Props = {
album: Album; album: Album;
handleOnClick(): void; close(): void;
// goto(albumId: number, direction: number): void;
}; };

View file

@ -3,12 +3,17 @@ import React from "react";
export default (props: Props) => { export default (props: Props) => {
const { value, handleOnChange } = props; const { value, handleOnChange } = props;
return ( return (
<div hidden> <div>
<label htmlFor="sortBy">Sortera efter</label> <label htmlFor="sortBy" className="visuallyhidden">
Sortera efter
</label>
<select <select
id="sortBy" id="sortBy"
value={value} value={value}
onChange={evt => handleOnChange(evt.target.value)} className="field"
onChange={(evt: { target: HTMLSelectElement }) =>
handleOnChange(evt.target.value)
}
> >
<option value="id">Inköpsdatum</option> <option value="id">Inköpsdatum</option>
<option value="artist">Artist</option> <option value="artist">Artist</option>
@ -20,5 +25,5 @@ export default (props: Props) => {
type Props = { type Props = {
value: string; value: string;
handleOnChange: Function; handleOnChange(sortKey: string): void;
}; };

View file

@ -6,17 +6,20 @@ import { Album, State } from "../interfaces";
const atos = (o: Album) => const atos = (o: Album) =>
[o.artist, o.title, o.songs.join(" "), o.year].join(" ").toLowerCase(); [o.artist, o.title, o.songs.join(" "), o.year].join(" ").toLowerCase();
const getAlbums = (albums: Array<Object>, filter: string) => { const getAlbums = (albums: Array<Object>, filter: string, sortKey: string) => {
if (filter) { if (filter) {
const term = filter.toLowerCase(); const term = filter.toLowerCase();
return albums.filter((album: Album) => atos(album).match(term)); albums = albums.filter((album: Album) => atos(album).match(term));
} }
return albums; return [...albums].sort((a: Album, b: Album) =>
a[sortKey] > b[sortKey] ? 1 : -1
);
}; };
const mapStateToProps = (state: State) => ({ const mapStateToProps = (state: State) => ({
albums: getAlbums(state.albums, state.visibilityFilter), albums: getAlbums(state.albums, state.visibilityFilter, state.sortKey),
blurred: "id" in state.selectedAlbum blurred: "id" in state.selectedAlbum,
sortKey: state.sortKey
}); });
const mapDispatchToProps = (dispatch: Function) => ({ const mapDispatchToProps = (dispatch: Function) => ({

View file

@ -8,7 +8,7 @@ const mapStateToProps = (state: State) => ({
}); });
const mapDispatchToProps = (dispatch: Function) => ({ const mapDispatchToProps = (dispatch: Function) => ({
handleOnClick: () => dispatch(unselectAlbum()) close: () => dispatch(unselectAlbum())
}); });
export default connect(mapStateToProps, mapDispatchToProps)(Modal); export default connect(mapStateToProps, mapDispatchToProps)(Modal);