From c1ce2fed3d0c9c9cee01a4da893d493238e63b38 Mon Sep 17 00:00:00 2001 From: hacki Date: Sun, 18 Feb 2024 23:58:32 +0100 Subject: [PATCH] A LOT of improvements to the UX/UI and new fonctionnalities --- front/_colors.scss | 5 + front/_inputs.scss | 0 front/_misc.scss | 23 ++++ front/_recents.scss | 65 +++++++++++ front/index.html | 64 +++++++++++ front/style.scss | 111 ++++++++++++++++++ static/app.js | 88 +++++++++++---- static/favicon.ico | Bin 0 -> 4286 bytes static/favicon.svg | 1 + static/style.css | 268 +++++++++++++++++++++++++++++--------------- 10 files changed, 508 insertions(+), 117 deletions(-) create mode 100644 front/_colors.scss create mode 100644 front/_inputs.scss create mode 100644 front/_misc.scss create mode 100644 front/_recents.scss create mode 100644 front/index.html create mode 100644 front/style.scss create mode 100644 static/favicon.ico create mode 100644 static/favicon.svg diff --git a/front/_colors.scss b/front/_colors.scss new file mode 100644 index 0000000..6a09684 --- /dev/null +++ b/front/_colors.scss @@ -0,0 +1,5 @@ +$accent: #d30f45; +$background: #09090b; +$border: #363636; +$text: #f2f2f7; +$placeholder: #888; \ No newline at end of file diff --git a/front/_inputs.scss b/front/_inputs.scss new file mode 100644 index 0000000..e69de29 diff --git a/front/_misc.scss b/front/_misc.scss new file mode 100644 index 0000000..5770e2c --- /dev/null +++ b/front/_misc.scss @@ -0,0 +1,23 @@ +@use 'colors' as *; + +::selection { + background-color: $accent; + color: $text; +} + +::-webkit-scrollbar { + width: 9px; +} + +::-webkit-scrollbar-track { + background-color: $background; +} + +::-webkit-scrollbar-thumb { + background-color: #444; + border-radius: 9px; +} + +::-webkit-scrollbar-thumb:hover { + background-color: $text; +} \ No newline at end of file diff --git a/front/_recents.scss b/front/_recents.scss new file mode 100644 index 0000000..70cabde --- /dev/null +++ b/front/_recents.scss @@ -0,0 +1,65 @@ +@use 'colors' as *; + +section#recent-plaks { + bottom: 1rem; + display: flex; + flex-flow: column wrap; + gap: 9px; + position: absolute; + right: 1rem; + transition: .15s ease-in-out; + user-select: none; + + .title { + align-items: center; + gap: 18px; + transition: .15s ease-in-out; + + &:hover { + border-color: #555; + } + } + + .recent-plak { + align-items: center; + border: 3px solid $border; + font-weight: 500; + justify-content: space-between; + outline: none; + padding: 8px 18px; + text-decoration: none; + transition: .15s ease-in-out; + width: 12rem; + + &:focus-visible { + border: 2px solid #bbb; + } + + svg { + border-radius: 15px; + cursor: pointer; + height: 22px; + padding: 5px; + stroke: $text; + stroke-width: 2.25; + width: 22px; + transition: .1s ease-in-out; + + &:hover { + background-color: $border; + } + } + } + + a { + color: inherit; + text-decoration: none; + } +} + +h3 { + font-size: 1.5rem; + margin: 0; + transition: .15s ease-in-out; + width: fit-content; +} \ No newline at end of file diff --git a/front/index.html b/front/index.html new file mode 100644 index 0000000..13413ad --- /dev/null +++ b/front/index.html @@ -0,0 +1,64 @@ + + + + + + + + + + + New paste + + + + + +
+
1
+ +
+ +
+
+

Recent plaks

+ + + +
+
+ + + \ No newline at end of file diff --git a/front/style.scss b/front/style.scss new file mode 100644 index 0000000..9397f15 --- /dev/null +++ b/front/style.scss @@ -0,0 +1,111 @@ +@use 'colors' as *; + +@use 'inputs'; +@use 'recents'; +@use 'misc'; + +@import url('https://fonts.googleapis.com/css2?family=Inter:wght@100..900&family=JetBrains+Mono&display=swap'); + +body { + background-color: $background; + color: $text; + font: 400 16px/2 "Inter", "system-ui", sans-serif; + margin: 0; + overflow-x: hidden; +} + +.fr { + display: flex; + flex-flow: row wrap; +} + +#line-numbers, +#content { + font: 400 15px/1.6 "JetBrains Mono", monospace; +} + +#line-numbers { + color: $placeholder; + padding: 16px 1px; + text-align: center; + white-space: pre; + width: 30px; +} + +#content { + color: $text; + height: 100%; + min-height: 90vh; + padding: 16px 16px 0 16px; + width: calc(100vw - 65px); +} + +.menu { + gap: 18px; + position: fixed; + right: 16px; + top: 16px; + + svg { + cursor: pointer; + height: 24px; + fill: none; + margin-bottom: -6px; + stroke: $text; + stroke-width: 2; + width: 24px; + } +} + +input, +select { + background-color: $background; + border: 2px solid $border; + color: $text; + font: 500 14px/2 "Inter", "system-ui", sans-serif; + outline: none; + padding: 3px 10px; + width: 150px; + transition: .15s ease; + + &::placeholder { + color: $placeholder; + } + + &:hover { + border-color: #555; + } + + &:focus-visible { + border: 2px solid #bbb; + } +} + +select { + padding: 8px 10px; +} + +select:focus { + background-color: $background; + transition: none; +} + +option { + background-color: $background; + color: $text; + + &:focus { + background-color: $accent; + color: $background; + } +} + +button, +textarea { + background-color: inherit; + border: none; + margin: 0; + outline: none; + resize: none; +} + diff --git a/static/app.js b/static/app.js index bef2c56..0e89f6a 100644 --- a/static/app.js +++ b/static/app.js @@ -1,31 +1,71 @@ -const codeEditor = document.getElementById('content'); -const lineCounter = document.getElementById('lines'); +const editor = document.getElementById('content'); +const filenameSelector = document.getElementById('filename'); +const recentPlaksDiv = document.getElementById('recent-plaks'); +const lineNumbersDiv = document.getElementById('line-numbers'); -let lineCountCache = 0; +function updateLn() { + const lines = editor.value.split('\n').length; + const lineNumbers = Array.from({ length: lines }, (_, i) => i + 1).join('\n'); -// Update line counter -function updateLineCounter() { - const lineCount = codeEditor.value.split('\n').length; - - if (lineCountCache !== lineCount) { - const outarr = Array.from({length: lineCount}, (_, index) => index + 1); - lineCounter.value = outarr.join('\n'); - } - - lineCountCache = lineCount; + lineNumbersDiv.textContent = lineNumbers; } -codeEditor.addEventListener('input', updateLineCounter); +function updateTitle() { + document.title = filenameSelector.value == '' ? 'New paste' : ` *${filenameSelector.value} - Plakken`; +} -codeEditor.addEventListener('keydown', (e) => { - if (e.key === 'Tab') { - e.preventDefault(); +function getRecentPlaksFromStorage() { + return new Set(JSON.parse(localStorage.getItem('recentPlaks')) || []); +} - const {value, selectionStart, selectionEnd} = codeEditor; - codeEditor.value = `${value.slice(0, selectionStart)}\t${value.slice(selectionEnd)}`; - codeEditor.setSelectionRange(selectionStart + 1, selectionStart + 1); - updateLineCounter(); - } -}); +function updateLocalStorage() { + localStorage.setItem('recentPlaks', JSON.stringify(Array.from(recentPlaks))); +} -updateLineCounter(); +function addRecentPlak(plakId) { + recentPlaks.add(plakId); + updateLocalStorage(); +} + +function deleteRecentPlak(plakId) { + const plak = document.querySelector(`[href="/${plakId}/"]`).parentElement; + + plak.style.transform = 'translateX(150%)'; + setTimeout(() => plak.remove(), 250); + + recentPlaks.delete(plakId); + updateLocalStorage(); +} + +function createRecentPlakComponent(plak) { + const div = document.createElement('div'); + div.classList.add('recent-plak', 'fr'); + + const a = document.createElement('a'); + a.href = `/${plak}/`; + a.textContent = plak; + + const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); + svg.innerHTML = ``; + svg.id = 'cross'; + svg.setAttribute('viewBox', '0 0 24 24'); + svg.onclick = () => deleteRecentPlak(plak); + + div.appendChild(a); + div.appendChild(svg); + + return div; +} + +filenameSelector.addEventListener('input', updateTitle); +editor.addEventListener('input', updateLn); + +let recentPlaks = getRecentPlaksFromStorage(); + +if (recentPlaks === null) { + recentPlaks = []; + localStorage.setItem('recentPlaks', JSON.stringify(recentPlaks)); +} else { + for (const plak of recentPlaks) + recentPlaksDiv.appendChild(createRecentPlakComponent(plak)); +} diff --git a/static/favicon.ico b/static/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..1f47bd4a96a611cc483aa1cecb1adde0cb610e26 GIT binary patch literal 4286 zcmd5=OHWfl6rM&{AR9G-$c{*wxG>d~F}{~3Zge3r_zTpyb?E{Z#-#zDQGCZHDhVqM zTCRvj#Q*_B5mO&UMNtrh@@T=&@7(Ea8feS3T)7@{I_mJ8JqyN)C0#}%pEcRJsbzF3;=t&fmOo2rFGdOU|p-` zrS&(!w3sJ%$yvb}AP@uwqVtAx>WC5G7GuBovF2eHG4|4s$>MO`U5J z?@6Ciu#cr3mEY~|f>lJVU2GxykR_yBCY4JpXHUemnSfE5E7RcxMjA7DDHoJnAp0bK3cqRP(%rbMafS3t4aN z=m1Xf-RR@KoMt48sXu!d^J|`Ip9R~*XCtEwCy9>--x8l^QNy~&3u$JoNu3`i=U#~9 Uq10Ta=k0}!ZelwB2k@%>3t(Q \ No newline at end of file diff --git a/static/style.css b/static/style.css index cf339b3..41531dd 100644 --- a/static/style.css +++ b/static/style.css @@ -1,98 +1,180 @@ -:root { - --accent: #be0560; - --background: #121212; - --border: #333; - --text: #e6e6e6; - --placeholder: #666; +@import url("https://fonts.googleapis.com/css2?family=Inter:wght@100..900&family=JetBrains+Mono&display=swap"); +section#recent-plaks { + bottom: 1rem; + display: flex; + flex-flow: column wrap; + gap: 9px; + position: absolute; + right: 1rem; + transition: 0.15s ease-in-out; + user-select: none; +} +section#recent-plaks .title { + align-items: center; + gap: 18px; + transition: 0.15s ease-in-out; +} +section#recent-plaks .title:hover { + border-color: #555; +} +section#recent-plaks .recent-plak { + align-items: center; + border: 3px solid #363636; + font-weight: 500; + justify-content: space-between; + outline: none; + padding: 8px 18px; + text-decoration: none; + transition: 0.15s ease-in-out; + width: 12rem; +} +section#recent-plaks .recent-plak:focus-visible { + border: 2px solid #bbb; +} +section#recent-plaks .recent-plak svg { + border-radius: 15px; + cursor: pointer; + height: 22px; + padding: 5px; + stroke: #f2f2f7; + stroke-width: 2.25; + width: 22px; + transition: 0.1s ease-in-out; +} +section#recent-plaks .recent-plak svg:hover { + background-color: #363636; +} +section#recent-plaks a { + color: inherit; + text-decoration: none; } -body { - background-color: var(--background); - color: var(--text); - font: 400 15px/2 "system-ui", monospace; - margin: 0; -} - -form { - display: flex; - flex-flow: row wrap; -} - -#lines { - color: var(--placeholder); - font: 400 14px/1.6 "JetBrains Mono", monospace; - height: calc(100vh - 29px); - overflow-y: hidden; - padding: 8px 0; - text-align: center; - user-select: none; - width: 26px; -} - -input, select { - background-color: var(--background); - border: 2px solid var(--border); - border-radius: 2px; - color: var(--text); - font-size: 13px; - outline: none; - padding: 6px 8px; - transition: border .15s ease; -} - -input:hover, select:hover { - border-color: var(--text); -} - -button, textarea { - background-color: inherit; - border: none; - outline: none; - resize: none; -} - -#content { - color: var(--text); - font: 400 14px/1.6 "JetBrains Mono", monospace; - height: calc(100vh - 29px); - padding: 8px; - width: calc(100vw - 45px); -} - -nav { - top: 1rem; - display: flex; - flex-flow: row wrap; - position: absolute; - right: 12px; -} - -ul { - display: flex; - flex-flow: row wrap; - gap: 36px; - list-style: none; - margin: 0; - padding: 0 1.9rem; -} - -svg { - cursor: pointer; - height: 24px; - fill: var(--text); - transition: .15s ease; - width: 24px; -} - -svg:hover { - stroke: #fff; -} - -input:focus-visible, select:focus-visible { - border: 2px solid var(--text); +h3 { + font-size: 1.5rem; + margin: 0; + transition: 0.15s ease-in-out; + width: fit-content; } ::selection { - background-color: var(--accent); - color: #fff; -} \ No newline at end of file + background-color: #d30f45; + color: #f2f2f7; +} + +::-webkit-scrollbar { + width: 9px; +} + +::-webkit-scrollbar-track { + background-color: #09090b; +} + +::-webkit-scrollbar-thumb { + background-color: #444; + border-radius: 9px; +} + +::-webkit-scrollbar-thumb:hover { + background-color: #f2f2f7; +} + +body { + background-color: #09090b; + color: #f2f2f7; + font: 400 16px/2 "Inter", "system-ui", sans-serif; + margin: 0; + overflow-x: hidden; +} + +.fr { + display: flex; + flex-flow: row wrap; +} + +#line-numbers, +#content { + font: 400 15px/1.6 "JetBrains Mono", monospace; +} + +#line-numbers { + color: #888; + padding: 16px 1px; + text-align: center; + white-space: pre; + width: 30px; +} + +#content { + color: #f2f2f7; + height: 100%; + min-height: 90vh; + padding: 16px 16px 0 16px; + width: calc(100vw - 65px); +} + +.menu { + gap: 18px; + position: fixed; + right: 16px; + top: 16px; +} +.menu svg { + cursor: pointer; + height: 24px; + fill: none; + margin-bottom: -6px; + stroke: #f2f2f7; + stroke-width: 2; + width: 24px; +} + +input, +select { + background-color: #09090b; + border: 2px solid #363636; + color: #f2f2f7; + font: 500 14px/2 "Inter", "system-ui", sans-serif; + outline: none; + padding: 3px 10px; + width: 150px; + transition: 0.15s ease; +} +input::placeholder, +select::placeholder { + color: #888; +} +input:hover, +select:hover { + border-color: #555; +} +input:focus-visible, +select:focus-visible { + border: 2px solid #bbb; +} + +select { + padding: 8px 10px; +} + +select:focus { + background-color: #09090b; + transition: none; +} + +option { + background-color: #09090b; + color: #f2f2f7; +} +option:focus { + background-color: #d30f45; + color: #09090b; +} + +button, +textarea { + background-color: inherit; + border: none; + margin: 0; + outline: none; + resize: none; +}