add Menu modal

This commit is contained in:
[poww10s]
2020-11-24 15:10:41 -05:00
parent 9363f7932e
commit 5865400d5b
5 changed files with 192 additions and 28 deletions
+2 -1
View File
@@ -11,7 +11,8 @@ Alapatch currently only supports loading and saving patch files in the .SYSEX fo
- [x] finish one timbre as an example - [x] finish one timbre as an example
- [x] update state and components to handle multiple timbres - [x] update state and components to handle multiple timbres
- [x] implement switching between currently viewed timbre - [x] implement switching between currently viewed timbre
- [ ] make a home screen! - [x] make a home screen!
- [ ] implement popup to confirm new patch if a patch is currently being worked on.
- [ ] style components - [ ] style components
- [ ] merge with main branch - [ ] merge with main branch
-1
View File
@@ -1,6 +1,5 @@
.App { .App {
text-align: center; text-align: center;
} }
.App-logo { .App-logo {
+106 -7
View File
@@ -1,21 +1,23 @@
.menu, .menu,
.menu-true, .menu-true,
.menu-false { .menu-false {
position: absolute; position: fixed;
background: white; background: white;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
z-index: 9999; z-index: 99;
top: 0; top: 0;
left: 0; left: 0;
bottom: 0;
right: 0;
min-height: 100vh; min-height: 100vh;
min-width: 100vw; min-width: 100vw;
} }
.menu-false { .menu-false {
left: -100vw; display: none;
} }
.menu-true-animation { .menu-true-animation {
@@ -83,16 +85,28 @@
.menu-logo { .menu-logo {
height: 40vmin; height: 40vmin;
pointer-events: none; pointer-events: none;
padding: 0.5em;
} }
.menu-title { .menu-title {
color: #1c1d21; color: #1c1d21;
font-family: 'Lato', sans-serif; font-family: 'Lato', sans-serif;
font-weight: 700;
line-height: 1em; line-height: 1em;
font-size: calc(10px + 10vmin);
margin: 0 0 0.5em 0; margin: 0 0 0.5em 0;
} }
h1 {
margin: 0.25em;
font-weight: 700;
line-height: 0.85em;
font-size: 2.5em;
}
h2 {
margin: 0.25em;
font-weight: 500;
line-height: 1em;
font-size: 1em;
}
.menu-button, .menu-button,
.menu-open-button { .menu-open-button {
@@ -109,6 +123,12 @@
text-align: center; text-align: center;
outline: none; outline: none;
transition: all 0.2s ease-in-out; transition: all 0.2s ease-in-out;
-webkit-touch-callout: none; /* iOS Safari */
-webkit-user-select: none; /* Safari */
-khtml-user-select: none; /* Konqueror HTML */
-moz-user-select: none; /* Old versions of Firefox */
-ms-user-select: none; /* Internet Explorer/Edge */
user-select: none;
} }
.menu-button:hover { .menu-button:hover {
color: white; color: white;
@@ -121,10 +141,11 @@
} }
.menu-open-button { .menu-open-button {
height: 1.5em; z-index: 100;
height: 1.495em;
line-height: 0.9em; line-height: 0.9em;
position: absolute; position: absolute;
padding: 0.13em 0.3em; padding: 0em 0.3em;
color: #ef476f; color: #ef476f;
border: 0.09em solid #ef476f; border: 0.09em solid #ef476f;
margin: 0; margin: 0;
@@ -137,3 +158,81 @@
.menu-open-button::before { .menu-open-button::before {
content: '\2630'; content: '\2630';
} }
.modal {
margin: auto;
height: 8em;
width: 14em;
position: fixed;
z-index: 100;
top: 0;
left: 0;
bottom: 0;
right: 0;
}
.modal-hide {
display: none;
}
.modal-display {
display: block;
}
.modal-main {
background: white;
padding: 0.75em 0 1em;
border: solid 1pt slategrey;
border-radius: 6px;
display: flex;
flex-wrap: wrap;
justify-content: center;
}
.modal-header {
font-size: 0.75em;
line-height: 1.25em;
text-align: left;
margin: 0em 9em 0 0;
}
.modal-text {
flex-grow: 3;
margin: 0.5em 0em 1em 1.85em;
text-align: left;
line-height: 1.5em;
font-size: 0.65em;
font-weight: 300;
}
.button-save,
.button-no-save,
.button-cancel {
width: 25%;
font-size: 0.5em;
margin: 0 0.5em;
border-radius: 0.2em;
padding: 0.35em 0;
}
.button-save {
color: mediumseagreen;
border-color: mediumseagreen;
}
.button-save:hover {
background: mediumseagreen;
}
.button-no-save {
color: crimson;
border-color: crimson;
}
.button-no-save:hover {
background: crimson;
}
.button-cancel {
color: slategray;
border-color: grey;
}
.button-cancel:hover {
background: slategray;
}
+67 -9
View File
@@ -1,16 +1,56 @@
import React, { useState } from 'react'; import React, { useState, useCallback } from 'react';
import { useDispatch } from 'react-redux'; // probably temporarily here import { useDispatch, useSelector } from 'react-redux'; // probably temporarily here
import { parameterRefreshAll } from '../timbre/parameters/parameterSlice'; // probably temporarily here import {
parameterRefreshAll,
parameterFlipUnsaved,
} from '../timbre/parameters/parameterSlice'; // probably temporarily here
import logo from '../../1f3b9.svg'; import logo from '../../1f3b9.svg';
import './Menu.css'; import './Menu.css';
export default function MainMenu(props) { // for things such as (do you want to save? or do you want to reset things?)
const Modal = ({ show, handleSave, handleNoSave, handleClose }) => {
const modalDisplay = show ? 'modal modal-display' : 'modal modal-hide';
const dispatch = useDispatch();
return (
<div className={modalDisplay}>
<div className="modal-main">
<span className="modal-header">Save Changes</span>
<span className="modal-text">
Do you want to save your changes?
</span>
<button
className="menu-button button-save"
onClick={handleSave}>
Save Changes
</button>
<button
className="menu-button button-no-save"
onClick={handleNoSave}>
Don't Save
</button>
<button
className="menu-button button-cancel"
onClick={handleClose}>
Cancel
</button>
</div>
</div>
);
};
export default function MainMenu() {
const unsaved = useSelector((state) => state.parameters.unsaved);
const [open, setOpen] = useState({ const [open, setOpen] = useState({
className: '', className: '',
openState: true, openState: true,
}); });
const [showModal, setShowModal] = useState(false);
const dispatch = useDispatch(); const dispatch = useDispatch();
const unSavedUpdate = useCallback(() => dispatch(parameterFlipUnsaved), [
dispatch,
]);
const HandleClick = () => { const HandleClick = () => {
setOpen({ setOpen({
className: open.openState className: open.openState
@@ -27,28 +67,46 @@ export default function MainMenu(props) {
}); });
}; };
const modalState = () => {
setShowModal(!showModal);
};
return ( return (
<div> <div>
<Modal
show={showModal}
handleClose={modalState}
handleSave={() => {
modalState();
HandleClick(); // temporary while I implement the binary parsing stuff
}}
handleNoSave={() => {
dispatch(parameterRefreshAll());
modalState();
HandleClick();
}}
/>
<div <div
className={`menu ${open.className}`} className={`menu ${open.className}`}
onAnimationEnd={AnimationEnd}> onAnimationEnd={AnimationEnd}>
<img src={logo} className="menu-logo" alt="logo" /> <img src={logo} className="menu-logo" alt="logo" />
<header className="menu-title">Alapatch</header> <header className="menu-title">
<h1>Alapatch</h1>
<h2>A microKORG Patch Editor</h2>
</header>
<div className="menu-button-container"> <div className="menu-button-container">
<button <button
className="menu-button" className="menu-button"
onClick={() => { onClick={() => {
HandleClick(); !unsaved ? HandleClick() : modalState();
dispatch(parameterRefreshAll());
}}> }}>
New Patch New Patch
</button> </button>
<button className="menu-button">Load Patch</button> <button className="menu-button">Load Patch</button>
</div> </div>
</div> </div>
{!open.openState && (
<button className="menu-open-button" onClick={HandleClick} /> <button className="menu-open-button" onClick={HandleClick} />
)}
</div> </div>
); );
} }
@@ -372,6 +372,7 @@ const defaultState = {
target: 'Both', target: 'Both',
}, },
}, },
unsaved: false,
}; };
const parametersAdapter = createEntityAdapter({}); const parametersAdapter = createEntityAdapter({});
@@ -380,9 +381,14 @@ const parametersSlice = createSlice({
name: 'parameters', name: 'parameters',
initialState: parametersAdapter.getInitialState(defaultState), initialState: parametersAdapter.getInitialState(defaultState),
reducers: { reducers: {
parameterAdded: parametersAdapter.addOne, parameterUpdated(state, action) {
parameterUpdated: parametersAdapter.updateOne, parametersAdapter.updateOne(state, action.payload);
state.unsaved = true;
},
parameterRefreshAll: () => defaultState, parameterRefreshAll: () => defaultState,
parameterFlipUnsaved(state) {
state.unsaved = !state.unsaved;
},
}, },
}); });
@@ -397,6 +403,7 @@ export const {
parameterAdded, parameterAdded,
parameterUpdated, parameterUpdated,
parameterRefreshAll, parameterRefreshAll,
parameterFlipUnsaved,
} = parametersSlice.actions; } = parametersSlice.actions;
export default parametersSlice.reducer; export default parametersSlice.reducer;