Make modal great again
This commit is contained in:
parent
755cf14828
commit
9bcf0ecc56
10 changed files with 145 additions and 53 deletions
|
|
@ -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
41
package-lock.json
generated
|
|
@ -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
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -20,6 +20,6 @@ export default (props: Props) => {
|
|||
|
||||
type Props = {
|
||||
albums: Array<interfaces.Album>;
|
||||
handleOnClick: Function;
|
||||
handleOnClick(album: interfaces.Album): void;
|
||||
blurred: boolean;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -40,5 +40,5 @@ export default (props: Props) => {
|
|||
type Props = {
|
||||
key: number;
|
||||
album: Album;
|
||||
handleOnClick: Function;
|
||||
handleOnClick(album: Album): void;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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 />
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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) => ({
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ const mapStateToProps = (state: State) => ({
|
|||
});
|
||||
|
||||
const mapDispatchToProps = (dispatch: Function) => ({
|
||||
handleOnClick: () => dispatch(unselectAlbum())
|
||||
close: () => dispatch(unselectAlbum())
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(Modal);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue