Web UI advancements

This commit is contained in:
Raphaël Thériault 2019-10-24 23:26:19 -04:00
parent 1b2c1b1199
commit e60e3d625f
4 changed files with 332 additions and 21 deletions

View File

@ -1,18 +0,0 @@
{
"printWidth": 80,
"tabWidth": 4,
"useTabs": false,
"semi": true,
"singleQuote": false,
"quoteProps": "consistent",
"jsxSingleQuote": false,
"trailingComma": "es5",
"bracketSpacing": true,
"jsxBracketSameLine": false,
"arrowParens": "always",
"requirePragma": false,
"insertPragma": false,
"proseWrap": "never",
"htmlWhitespaceSensitivity": "css",
"endOfLine": "lf"
}

View File

@ -1,11 +1,79 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<style>
{{ css }}
</style>
<title>filite</title>
</head>
<body>
Hello world!
<nav>
<div id="files-tab" role="tab"><span>Files</span></div>
<div id="links-tab" class="active" role="tab">
<span>Links</span>
</div>
<div id="texts-tab" role="tab"><span>Texts</span></div>
</nav>
<main>
<div id="files-form">
<label for="files-url">URL</label>
<input
id="files-url"
class="mb1"
type="text"
placeholder="a1b2c3"
required
/>
<label for="files-file">File</label>
<input id="files-file" type="file" hidden />
<div class="mb2">
<button id="files-browse">Browse</button
><input id="files-value" type="text" required />
</div>
<button id="files-submit" disabled>Submit</button>
</div>
<div id="links-form" class="active">
<label for="links-url">URL</label>
<input
id="links-url"
class="mb1"
type="text"
placeholder="a1b2c3"
required
/>
<label for="links-forward">Forward</label>
<input
id="links-forward"
class="mb2"
type="url"
placeholder="http://example.com/"
required
/>
<button id="links-submit" disabled>Submit</button>
</div>
<div id="texts-form">
<label for="texts-url">URL</label>
<input
id="texts-url"
class="mb1"
type="text"
placeholder="a1b2c3"
required
/>
<label for="texts-contents">Contents</label>
<textarea
id="texts-contents"
class="mb2"
placeholder="Hello, World!"
required
></textarea>
<button id="texts-submit" disabled>Submit</button>
</div>
</main>
<script>
{{ js }}
</script>
</body>
</html>

View File

@ -0,0 +1,95 @@
const tabs = {
files: [
document.querySelector("#files-tab"),
document.querySelector("#files-form"),
],
links: [
document.querySelector("#links-tab"),
document.querySelector("#links-form"),
],
texts: [
document.querySelector("#texts-tab"),
document.querySelector("#texts-form"),
],
};
const inputs = {
files: [
document.querySelector("#files-url"),
document.querySelector("#files-file"),
document.querySelector("#files-submit"),
],
links: [
document.querySelector("#links-url"),
document.querySelector("#links-forward"),
document.querySelector("#links-submit"),
],
texts: [
document.querySelector("#texts-url"),
document.querySelector("#texts-contents"),
document.querySelector("#texts-submit"),
],
};
for (const group in tabs) {
tabs[group][0].onclick = () => {
const active = document.querySelectorAll(".active");
for (const el of active) {
el.classList.remove("active");
}
for (const el of tabs[group]) {
el.classList.add("active");
}
};
}
for (const group in inputs) {
const checkValidity = () => {
const submitButton = inputs[group][inputs[group].length - 1];
submitButton.disabled = inputs[group].some(
(input) => input.validity != undefined && !input.validity.valid
);
};
const urlInput = inputs[group][0];
urlInput.addEventListener("input", () => {
urlInput.value = urlInput.value
.replace(/[^0-9A-Za-z]/g, "")
.toLowerCase();
if (parseInt(urlInput.value, 36) > 2147483647) {
urlInput.setCustomValidity(
"Base 36 integer below or equal to zik0zj"
);
} else {
urlInput.setCustomValidity("");
}
});
for (const input of inputs[group].filter(
(input) =>
input instanceof HTMLInputElement ||
input instanceof HTMLTextAreaElement
)) {
input.addEventListener("input", () => checkValidity());
input.addEventListener("change", () => checkValidity());
}
if (group === "files") {
const filesFileInput = inputs.files[1];
const filesBrowseButton = document.querySelector("#files-browse");
const filesValueInput = document.querySelector("#files-value");
filesFileInput.addEventListener("change", () => {
filesValueInput.value = filesFileInput.files[0].name || "";
});
filesBrowseButton.onclick = () => {
filesFileInput.click();
};
filesValueInput.onfocus = (e) => {
e.preventDefault();
filesValueInput.blur();
return false;
};
} else if (group === "links") {
} else if (group === "texts") {
}
}

View File

@ -0,0 +1,166 @@
html,
body {
margin: 0px;
padding: 0px;
width: 100vw;
height: 100vh;
}
html {
font-family: sans-serif;
font-size: 200%;
}
body {
display: grid;
grid-template:
[r1s] "nav" 2rem [r1e]
[r2s] "main" auto [r2e]
/ auto;
background-color: #002b36;
color: #839496;
}
::placeholder {
color: #586e75;
}
nav {
display: flex;
justify-content: space-evenly;
grid-area: nav;
background-color: #073642;
}
nav div {
display: flex;
justify-content: center;
align-items: center;
flex-grow: 1;
font-size: 1rem;
border-bottom: 0.0625rem solid #586e75;
}
nav div:hover {
background-color: #002b36;
color: #93a1a1;
cursor: pointer;
}
nav div.active {
background-color: #002b36;
color: #93a1a1;
border-top: 0.0625rem solid #586e75;
border-right: 0.0625rem solid #586e75;
border-left: 0.0625rem solid #586e75;
border-bottom: none;
}
main {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
grid-area: main;
}
main div {
display: none;
}
main div.active {
display: block;
}
main div label {
display: block;
margin-bottom: 0.5rem;
padding-left: 1rem;
font-size: 1rem;
}
main div input[type="text"],
main div input[type="url"] {
display: block;
padding: 0.5rem 1rem;
width: calc(75vw - 2rem);
background-color: #073642;
color: #839496;
font-size: 1rem;
border: none;
}
main div textarea {
display: block;
padding: 0.5rem 1rem;
width: calc(75vw - 2rem);
height: 25vh;
background-color: #073642;
color: #839496;
font-family: monospace;
font-size: 0.5rem;
border: none;
}
main div input[type="text"]:invalid,
main div input[type="url"]:invalid,
main div textarea:invalid {
border: 0.0625rem solid #dc322f;
}
main div button {
display: block;
padding: 0.5rem 1rem;
width: 75vw;
background-color: #073642;
color: #839496;
font-size: 1rem;
border: 0.0625rem solid #586e75;
}
main div button:hover,
main div button:focus {
background-color: #002b36;
color: #93a1a1;
cursor: pointer;
}
main div button:disabled {
background-color: #073642;
color: #586e75;
border: none;
cursor: default;
}
main div div {
display: flex;
width: 75vw;
}
main div div button {
width: auto;
}
main div div input {
flex: 1;
padding: 0.5rem 1rem;
background-color: #073642;
}
.mb1 {
margin-bottom: 2rem;
}
.mb2 {
margin-bottom: 4rem;
}
@media screen and (max-height: 720px) {
.mb1 {
margin-bottom: 1rem;
}
.mb2 {
margin-bottom: 2rem;
}
}