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

41
package-lock.json generated
View file

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

View file

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

View file

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

View file

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

View file

@ -7,7 +7,10 @@ export default (props: Props) => {
<input
type="text"
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 ..."
/>
</div>
@ -16,5 +19,5 @@ export default (props: Props) => {
type Props = {
value: string;
handleOnChange: Function;
handleOnChange(filterValue: string): void;
};

View file

@ -2,26 +2,49 @@ import React from "react";
import { Album } from "../interfaces";
export default (props: Props) => {
const handleKeyPress = (e: KeyboardEvent, callback: Function) => {
console.log(e.charCode);
callback();
const handleKeyPress = (
keyPressed: string,
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;
if (id === undefined) {
return "";
}
// const imagePath = `assets/covers/${img}`;
const imagePath = `./covers/${img}`;
const song = songs.join(", ");
document.onkeyup = (e: KeyboardEvent) =>
handleKeyPress(e.key, album.id, close /*goto*/);
return (
<div
className="selected-album"
className="selected-album blurred"
tabIndex={0}
onClick={() => handleOnClick()}
onKeyPress={e => handleKeyPress(e, handleOnClick)}
onClick={() => close()}
>
<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">
#{id + 1}: {artist} - {song}, från "{title}" ({year})
<br />
@ -38,5 +61,6 @@ export default (props: Props) => {
type Props = {
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) => {
const { value, handleOnChange } = props;
return (
<div hidden>
<label htmlFor="sortBy">Sortera efter</label>
<div>
<label htmlFor="sortBy" className="visuallyhidden">
Sortera efter
</label>
<select
id="sortBy"
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="artist">Artist</option>
@ -20,5 +25,5 @@ export default (props: Props) => {
type Props = {
value: string;
handleOnChange: Function;
handleOnChange(sortKey: string): void;
};

View file

@ -6,17 +6,20 @@ import { Album, State } from "../interfaces";
const atos = (o: Album) =>
[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) {
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) => ({
albums: getAlbums(state.albums, state.visibilityFilter),
blurred: "id" in state.selectedAlbum
albums: getAlbums(state.albums, state.visibilityFilter, state.sortKey),
blurred: "id" in state.selectedAlbum,
sortKey: state.sortKey
});
const mapDispatchToProps = (dispatch: Function) => ({

View file

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