added vertical mode and optimised layout for mobile

This commit is contained in:
Daniel Ledda
2021-10-19 18:57:36 +02:00
parent 342e65345d
commit f3851f32cd
20 changed files with 280 additions and 8593 deletions

8622
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -28,5 +28,8 @@
"webpack": "^5.51.1", "webpack": "^5.51.1",
"webpack-cli": "^4.8.0", "webpack-cli": "^4.8.0",
"webpack-dev-server": "^4.0.0" "webpack-dev-server": "^4.0.0"
},
"dependencies": {
"file-loader": "^6.2.0"
} }
} }

View File

View File

@@ -1,6 +1,6 @@
import "./main.css";
import BeatGroup from "./BeatGroup"; import BeatGroup from "./BeatGroup";
import RootView from "./ui/Root/RootView"; import RootView from "./ui/Root/RootView";
import "./ui/global.css";
const defaultSettings = { const defaultSettings = {
barCount: 2, barCount: 2,

View File

@@ -3,26 +3,54 @@
padding-left: 1em; padding-left: 1em;
} }
.vertical-mode .beat > * {
padding-right: 0;
padding-left: 0;
}
.beat-unit-block { .beat-unit-block {
height: 2em; height: 2em;
} }
.vertical-mode .beat-unit-block {
height: auto;
width: 2em;
}
.beat-title { .beat-title {
width: 3em; width: 3em;
line-height: 32px; line-height: 32px;
margin: 0; margin: 0;
} }
.vertical-mode .beat-title {
display: block;
width: auto;
text-align: center;
}
.beat-spacer { .beat-spacer {
display: inline-block; display: inline-block;
width: 1em; width: 1em;
height: 2em; height: 2em;
} }
.vertical-mode .beat-spacer {
display: block;
width: 2em;
height: 1em;
}
.beat-main { .beat-main {
display: inline-flex; display: inline-flex;
} }
.vertical-mode .beat-main {
width: 2em;
margin-right: 4px;
display: block;
}
.beat-settings-container { .beat-settings-container {
display: flex; display: flex;
} }
@@ -30,4 +58,8 @@
.beat { .beat {
width: max-content; width: max-content;
margin-bottom: 4px; margin-bottom: 4px;
}
.vertical-mode .beat {
display: inline-block;
} }

View File

@@ -11,6 +11,11 @@
cursor: pointer; cursor: pointer;
} }
.vertical-mode .beat-unit {
margin-bottom: 4px;
display: block;
}
.beat-unit:hover { .beat-unit:hover {
border-color: var(--color-ui-neutral-dark-hover); border-color: var(--color-ui-neutral-dark-hover);
background-color: var(--color-ui-neutral-dark-hover); background-color: var(--color-ui-neutral-dark-hover);

View File

@@ -1,4 +1,15 @@
.beat-group { .beat-group {
padding: 1em; padding: 1em;
overflow-x: scroll; overflow-x: scroll;
} overflow-y: hidden;
display: flex;
width: inherit;
flex-direction: column;
}
.vertical-mode .beat-group {
height: inherit;
overflow-x: hidden;
overflow-y: scroll;
display: block;
}

View File

@@ -1,4 +1,3 @@
import BeatLikeLoopSettingsView from "../BeatLikeLoopSettings/BeatLikeLoopSettingsView";
import "./BeatGroupSettings.css"; import "./BeatGroupSettings.css";
import UINode, {UINodeOptions} from "../UINode"; import UINode, {UINodeOptions} from "../UINode";
import NumberInputView from "../Widgets/NumberInput/NumberInputView"; import NumberInputView from "../Widgets/NumberInput/NumberInputView";
@@ -30,6 +29,7 @@ export default class BeatGroupSettingsView extends UINode implements ISubscriber
BeatEvents.DisplayTypeChanged, BeatEvents.DisplayTypeChanged,
BeatGroupEvents.BeatListChanged, BeatGroupEvents.BeatListChanged,
BeatGroupEvents.LockingChanged, BeatGroupEvents.LockingChanged,
BeatGroupEvents.AutoBeatSettingsChanged,
]); ]);
} }
@@ -46,6 +46,8 @@ export default class BeatGroupSettingsView extends UINode implements ISubscriber
} else { } else {
this.barCountInput.enable(); this.barCountInput.enable();
} }
} else if (event === BeatGroupEvents.AutoBeatSettingsChanged) {
this.autoBeatLengthCheckbox.setValue(this.beatGroup.autoBeatLengthOn());
} }
} }

View File

@@ -13,19 +13,32 @@
} }
.root { .root {
position: relative;
overflow: hidden; overflow: hidden;
color: var(--color-p-light); color: var(--color-p-light);
background-color: var(--color-bg-dark); background-color: var(--color-bg-dark);
height: 100vh; height: 100vh;
display: flex;
align-content: center; align-content: center;
} }
.root-settings { .root-sidebar {
background-color: var(--color-bg-light); position: absolute;
height: 100%; left: -28em;
width: 30em; width: 30em;
padding: 0 2em 0 2em; height: 100vh;
display: flex;
transition: left 400ms;
}
.sidebar-visible .root-sidebar {
left: 0;
}
.root-settings {
z-index: 1;
width: 28em;
padding: 0 0 0 2em;
background-color: var(--color-bg-light);
overflow: scroll; overflow: scroll;
display: inline-block; display: inline-block;
} }
@@ -35,19 +48,86 @@
text-align: center; text-align: center;
} }
.root-sidebar-toggle {
z-index: 1;
height: 100vh;
min-width: 2em;
background-color: var(--color-bg-light);
left: 0;
}
.root-hamburger {
right: 0;
width: 2em;
height: 2em;
cursor: pointer;
mask-image: url(./drawing.svg);
mask-size: 2em;
background-color: var(--color-ui-neutral-dark);
}
.root-switch-mode {
right: 0;
width: 2em;
height: 2em;
cursor: pointer;
mask-image: url(./rotate.svg);
mask-size: 2em;
background-color: var(--color-ui-neutral-dark);
}
.root-beat-stage-container { .root-beat-stage-container {
flex: 1; position: absolute;
height: 100%; height: 100%;
width: calc(100vw - 30em); left: 0;
width: 100vw;
display: flex; display: flex;
justify-content: center;
flex-direction: column; flex-direction: column;
transition: left 400ms, width 400ms;
}
.sidebar-visible .root-beat-stage-container {
left: 30em;
width: calc(100vw - 30em);
} }
.root-beat-stage { .root-beat-stage {
max-width: calc(100vw - 30em); padding: 2em;
overflow: hidden; max-height: 100vh;
margin: auto; margin: auto;
max-width: 100vw;
transition: max-width 400ms;
}
.vertical-mode .root-beat-stage {
height: 100vh;
}
.sidebar-visible .root-beat-stage {
max-width: calc(100vw - 30em);
}
@media screen and (max-width: 900px) {
.sidebar-visible .root-sidebar {
left: 0;
width: 100vw;
}
.root-sidebar {
left: calc(-100vw + 2em);
width: 100vw;
}
.root-settings {
width: calc(100vw - 2em);
}
.sidebar-visible .root-beat-stage-container {
left: 100vw;
}
.root-beat-stage-container {
left: 0;
}
.sidebar-visible .root-beat-stage {
max-width: 100vw;
}
} }
* { * {

View File

@@ -14,6 +14,7 @@ export default class RootView extends UINode {
private beatGroupView: BeatGroupView; private beatGroupView: BeatGroupView;
private mainBeatGroup: BeatGroup; private mainBeatGroup: BeatGroup;
private beatGroupSettingsView!: BeatGroupSettingsView; private beatGroupSettingsView!: BeatGroupSettingsView;
private sidebar!: HTMLDivElement;
constructor(options: RootUINodeOptions) { constructor(options: RootUINodeOptions) {
@@ -23,18 +24,47 @@ export default class RootView extends UINode {
this.title = options.title; this.title = options.title;
} }
rebuild(): HTMLDivElement { toggleSidebar(): void {
this.node!.classList.toggle("sidebar-visible");
}
toggleOrientation(): void {
this.node!.classList.toggle("vertical-mode");
}
rebuild(): HTMLElement {
this.beatGroupSettingsView = new BeatGroupSettingsView({beatGroup: this.mainBeatGroup}); this.beatGroupSettingsView = new BeatGroupSettingsView({beatGroup: this.mainBeatGroup});
return UINode.make("div", { const sidebarMain = UINode.make("div", {
classes: ["root"], classes: ["root-settings"],
subs: [
UINode.make("h1", {innerText: this.title, classes: ["root-title"]}),
this.beatGroupSettingsView.render(),
]
});
const sidebarToggle = UINode.make("div", {
classes: ["root-sidebar-toggle"],
subs: [ subs: [
UINode.make("div", { UINode.make("div", {
classes: ["root-settings"], classes: ["root-hamburger"],
subs: [ onclick: () => this.toggleSidebar(),
UINode.make("h1", {innerText: this.title, classes: ["root-title"]}),
this.beatGroupSettingsView.render(),
]
}), }),
UINode.make("div", {
classes: ["root-switch-mode"],
onclick: () => this.toggleOrientation(),
})
]
});
this.sidebar = UINode.make("div", {
classes: ["root-sidebar"],
subs: [
sidebarMain,
sidebarToggle,
]
});
this.node = UINode.make("div", {
classes: ["root", "sidebar-visible"],
subs: [
this.sidebar,
UINode.make("div", { UINode.make("div", {
classes: ["root-beat-stage-container"], classes: ["root-beat-stage-container"],
subs: [ subs: [
@@ -48,5 +78,6 @@ export default class RootView extends UINode {
}) })
], ],
}); });
return this.node;
} }
} }

View File

@@ -2,11 +2,13 @@
height: 1.1em; height: 1.1em;
margin: 0.5em; margin: 0.5em;
line-height: 1em; line-height: 1em;
cursor: pointer;
} }
.bool-box-label { .bool-box-label {
display: inline-block; display: inline-block;
margin-right: 0.5em; margin-right: 0.5em;
cursor: pointer;
} }
input.bool-box-checkbox[type="checkbox"] { input.bool-box-checkbox[type="checkbox"] {
@@ -20,6 +22,7 @@ input.bool-box-checkbox[type="checkbox"] {
-webkit-appearance: none; -webkit-appearance: none;
-moz-appearance: none; -moz-appearance: none;
appearance: none; appearance: none;
cursor: pointer;
} }
input.bool-box-checkbox[type="checkbox"]::before { input.bool-box-checkbox[type="checkbox"]::before {

View File

@@ -39,6 +39,9 @@ export default class BoolBoxView extends UINode {
this.labelElement = UINode.make("label", { this.labelElement = UINode.make("label", {
classes: ["bool-box-label"], classes: ["bool-box-label"],
innerText: this.label ?? "", innerText: this.label ?? "",
onclick: () => {
this.onInput(!this.checkboxElement.checked);
},
}); });
if (this.label !== null) { if (this.label !== null) {
this.labelElement.classList.add("visible"); this.labelElement.classList.add("visible");
@@ -46,7 +49,9 @@ export default class BoolBoxView extends UINode {
this.checkboxElement = UINode.make("input", { this.checkboxElement = UINode.make("input", {
type: "checkbox", type: "checkbox",
classes: ["bool-box-checkbox"], classes: ["bool-box-checkbox"],
oninput: (event: Event) => this.onInput((event.target as HTMLInputElement).checked), onclick: (event: Event) => {
this.onInput((event.target as HTMLInputElement).checked);
},
}); });
return UINode.make("div", { return UINode.make("div", {
classes: ["bool-box"], classes: ["bool-box"],

View File

@@ -64,34 +64,38 @@ button:focus {
::-webkit-scrollbar { ::-webkit-scrollbar {
background-color: transparent; background-color: transparent;
} }
body {
scrollbar-width: thin;
scrollbar-color: var(--color-ui-neutral-dark) transparent;
}
::-webkit-scrollbar-thumb { ::-webkit-scrollbar-thumb {
background-color: rgba(0,0,0); background-color: rgba(0,0,0,0);
} }
@font-face { @font-face {
font-family: 'DMSans'; font-family: 'DMSans';
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
src: url(/static/DMSans-Regular.ttf) format('woff2'); src: url(./DMSans-Regular.ttf) format('woff2');
} }
@font-face { @font-face {
font-family: 'DMSans'; font-family: 'DMSans';
font-style: normal; font-style: normal;
font-weight: 600; font-weight: 600;
src: url(/static/DMSans-Bold.ttf) format('woff2'); src: url(./DMSans-Bold.ttf) format('woff2');
} }
@font-face { @font-face {
font-family: 'DMSans'; font-family: 'DMSans';
font-style: italic; font-style: italic;
font-weight: 400; font-weight: 400;
src: url(/static/DMSans-Italic.ttf) format('woff2'); src: url(./DMSans-Italic.ttf) format('woff2');
} }
@font-face { @font-face {
font-family: 'DMSans'; font-family: 'DMSans';
font-style: italic; font-style: italic;
font-weight: 600; font-weight: 600;
src: url(/static/DMSans-BoldItalic.ttf) format('woff2'); src: url(./DMSans-BoldItalic.ttf) format('woff2');
} }

View File

@@ -25,18 +25,20 @@ const webpackConfig = {
}, { }, {
loader: "css-loader", loader: "css-loader",
options: { options: {
url: true,
sourceMap: true sourceMap: true
} }
}] }]
}, },
{ // {
test: /\.(png|jpe?g|gif|ttf|woff2?|eot|svg)$/i, // test: /\.(png|jpe?g|gif|ttf|woff2?|eot|svg)$/i,
use: [ // use: [
{ // {
loader: "file-loader", // loader: "file-loader",
}, // },
], // ],
}] // }
]
}, },
resolve: { resolve: {
@@ -45,13 +47,14 @@ const webpackConfig = {
output: { output: {
filename: "bundle.js", filename: "bundle.js",
publicPath: "/static", publicPath: "/static/",
path: path.resolve(__dirname, "./public/static/"), path: path.resolve(__dirname, "./public/static/"),
}, },
devServer: { devServer: {
static: { static: {
directory: path.join(__dirname, "./public"), directory: path.join(__dirname, "./public"),
publicPath: "/",
}, },
hot: true, hot: true,
compress: true, compress: true,