diff options
Diffstat (limited to 'static/pages')
| -rw-r--r-- | static/pages/image-viewer/index.css | 17 | ||||
| -rw-r--r-- | static/pages/image-viewer/index.js | 20 | ||||
| -rw-r--r-- | static/pages/login/index.css | 129 | ||||
| -rw-r--r-- | static/pages/login/index.js | 48 | ||||
| -rw-r--r-- | static/pages/main/index.css | 69 | ||||
| -rw-r--r-- | static/pages/main/index.js | 97 | ||||
| -rw-r--r-- | static/pages/settings/index.css | 83 | ||||
| -rw-r--r-- | static/pages/settings/index.js | 62 | ||||
| -rw-r--r-- | static/pages/shuffle/index.css | 6 | ||||
| -rw-r--r-- | static/pages/shuffle/index.js | 17 |
10 files changed, 548 insertions, 0 deletions
diff --git a/static/pages/image-viewer/index.css b/static/pages/image-viewer/index.css new file mode 100644 index 0000000..6f53333 --- /dev/null +++ b/static/pages/image-viewer/index.css @@ -0,0 +1,17 @@ + +#container { + width: 100%; + height: 100vh; + overflow-y: auto; + display: grid; + gap: 10px; + padding: 10px; +} + +#container img { + margin: auto; + max-width: 700px; + width: 100%; + border-radius: var(--border-radius); + box-shadow: #223223aa 1px 1px 4px; +} diff --git a/static/pages/image-viewer/index.js b/static/pages/image-viewer/index.js new file mode 100644 index 0000000..76d720f --- /dev/null +++ b/static/pages/image-viewer/index.js @@ -0,0 +1,20 @@ +import * as sfw from 'sfw'; +const { Div, Img } = sfw.element.native; + +const css = await sfw.css(import.meta.url, './index.css') + +export default class ImageViewer extends sfw.element.Container { + #container + + constructor() { + super({ css }); + + this.body.append( + this.#container = Div.new({ id: 'container' }) + ); + } + + add(url) { + this.#container.append(Img.new({ src: url })); + } +} diff --git a/static/pages/login/index.css b/static/pages/login/index.css new file mode 100644 index 0000000..8a59d83 --- /dev/null +++ b/static/pages/login/index.css @@ -0,0 +1,129 @@ +#container { + background: var(--page-background); + overflow: hidden; + width: 100%; + height: 100%; +} + +#box { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + max-width: 300px; + width: 100%; + padding: 20px; + box-shadow: #223223aa 1px 1px 4px; + border-radius: var(--border-radius); + background: #ffffff99; + backdrop-filter: blur(10px); + z-index: 2000; +} + +#title { + font-family: 'Pacifico'; + position: absolute; + width: 100%; + height: 100%; + text-align: center; + top: 0px; + padding-top: 50px; + font-size: 2.5em; + z-index: 1000; + text-shadow: -1px -1px 0 var(--page-background), + 1px 1px 0 var(--page-background), + 1px -1px 0 var(--page-background), + -1px 1px 0 var(--page-background); + overflow: hidden; +} + +@keyframes left-bubble { + from { + width: 0px; + height: 0px; + } + to { + width: 100vw; + height: 100vw; + } +} + +#title:before { + content: ''; + display: block; + position: absolute; + top: -30px; + left: 0px; + background: var(--primary); + transform: translate(-50%, -50%); + border-radius: 100%; + z-index: -1; + animation: left-bubble 1s normal forwards ease; + width: 100vw; + height: 100vw; +} + +@keyframes right-bubble { + from { + width: 0px; + height: 0px; + } + to { + width: 200vw; + height: 200vw; + } +} + +#title:after { + content: ''; + display: block; + position: absolute; + bottom: 55%; + right: 0px; + width: 200vw; + height: 200vw; + transform: translate(50%, 50%); + background: var(--fg); + border-radius: 100%; + z-index: -2; + animation: right-bubble 1s normal forwards ease; +} + +#form { + display: grid; + grid-template-columns: 100px auto; + max-width: 300px; + width: 100%; + margin: 0; + margin-bottom: 20px; + border-radius: 3px; + gap: 10px; +} + +#form input { + width: 100%; +} + +#form label { + margin: auto 0px; + font-weight: bold; +} + +button { + width: 100%; +} + +#subtitle { + position: absolute; + bottom: 50px; + left: 50%; + transform: translate(-50%, 0); + white-space: nowrap; + font-family: 'Pacifico'; + color: #69717d; + z-index: 1000; + text-shadow: -1px -1px 0 var(--page-background), + 1px 1px 0 var(--page-background), + 1px -1px 0 var(--page-background), + -1px 1px 0 var(--page-background); +} diff --git a/static/pages/login/index.js b/static/pages/login/index.js new file mode 100644 index 0000000..fc14dbf --- /dev/null +++ b/static/pages/login/index.js @@ -0,0 +1,48 @@ +import * as sfw from 'sfw'; +const { Div, Label, H1: Title, Input, Button } = sfw.element.native; + +const css = await sfw.css(import.meta.url, './index.css'); + +export default class LoginView extends sfw.element.Container { + #user + #password + + constructor() { + super({ css }); + + this.onlogin = () => {}; + + this.body.append( + Div.new({ + id: 'container', + children: [ + Div.new({ id: 'title', innerText: 'Memora' }), + Div.new({ + id: 'box', + children: [ + + Div.new({ + id: 'form', + children: [ + Label.new({ innerText: 'User' }), + this.#user = Input.new({ }), + + Label.new({ innerText: 'Password' }), + this.#password = Input.new({ type: 'password' }), + ] + }), + Button.new({ + innerText: 'Login', + onclick: () => this.onlogin(this.#user.value, this.#password.value), + }), + ] + }), + Div.new({ + id: 'subtitle', + innerText: 'Where nostalgia is home.', + }), + ] + }) + ); + } +} diff --git a/static/pages/main/index.css b/static/pages/main/index.css new file mode 100644 index 0000000..421e689 --- /dev/null +++ b/static/pages/main/index.css @@ -0,0 +1,69 @@ + +:host { + display: grid; + height: 100%; + width: 100%; + background: var(--page-background); +} + +#bar { + position: fixed; + bottom: 5px; + left: 5px; + right: 5px; + background: #fff9; + box-shadow: #223223aa 1px 1px 4px; + display: grid; + grid-template-columns: 1fr 1fr 1fr 1fr 1fr ; + height: 50px; + backdrop-filter: blur(10px); + border-radius: var(--border-radius); + transition: bottom 0.1s ease; +} + +#bar.hidden { + bottom: -200px; +} + +.menu-button { + color: var(--fg-disabled); + width: 18px; + height: 18px; + border-radius: 100%; + margin: auto; + cursor: pointer; + user-select: none; + align-content: center; + text-align: center; +} + +.menu-button.add { + width: 60px; + height: 60px; + margin-top: -20px; + background: var(--primary); + transition: width 0.1s ease, height 0.1s ease, margin 0.1s ease; + color: var(--card-background); + font-weight: bold; + font-size: 2em; +} + +.menu-button.add .icon { + width: 30px; + height: 30px; + display: grid; + margin: auto; +} + +.menu-button.add .icon .bi-house-fill { + width: 20px; + height: 20px; + margin: auto; +} + +.menu-button .icon { + width: 100%; + height: 100%; + display: grid; + margin: auto; +} diff --git a/static/pages/main/index.js b/static/pages/main/index.js new file mode 100644 index 0000000..9bf0aae --- /dev/null +++ b/static/pages/main/index.js @@ -0,0 +1,97 @@ +import * as sfw from 'sfw'; +const { Div, Input } = sfw.element.native; + +import icons from '/icons/index.js'; + +const css = await sfw.css(import.meta.url, './index.css'); + +export default class MainView extends sfw.element.Container { + #active_kind + #active_button + #active_view + #bar + + static Kind = Object.freeze({ + 'upload': 0, + 'home': 1, + }); + + constructor() { + super({ css }); + + this.onsearch = () => {} + this.onmonth = () => {} + this.onupload = () => {} + this.onshuffle = () => {} + this.onhome = () => {} + + this.body.append( + this.#active_view = Div.new({ id: 'main' }), + + this.#bar = Div.new({ + id: 'bar', + children: [ + Div.new({ + className: 'menu-button', + children: [ icons.search ], + onclick: (e) => { + e.stopPropagation(); + this.onsearch(); + } + }), + + Div.new({ + className: 'menu-button', + children: [ icons.calendar ], + onclick: () => this.onmonth(), + }), + + this.#active_button = Div.new({ + className: 'menu-button add', + children: [ icons.add ], + onclick: () => this.onupload() + }), + + Div.new({ + className: 'menu-button', + children: [ icons.shuffle ], + onclick: () => this.onshuffle(), + }), + + Div.new({ + className: 'menu-button', + children: [ icons.settings ], + onclick: () => this.onsettings(), + }), + ], + }), + ); + } + + hide() { + this.#bar.classList.add('hidden'); + } + + show() { + this.#bar.classList.remove('hidden'); + } + + set active_view(element) { + this.#active_view.innerHTML = ''; + this.#active_view.append(element); + } + + set active_kind(kind) { + if (kind == MainView.Kind.home) { + this.#active_button.innerHTML = ''; + this.#active_button.append(icons.home); + this.#active_button.onclick = () => this.onhome(); + } else if (kind == MainView.Kind.upload) { + this.#active_button.innerHTML = ''; + this.#active_button.append(icons.add); + this.#active_button.onclick = () => this.onupload(); + } else { + console.error(`invalid kind ${kind}`); + } + } +} diff --git a/static/pages/settings/index.css b/static/pages/settings/index.css new file mode 100644 index 0000000..5128c18 --- /dev/null +++ b/static/pages/settings/index.css @@ -0,0 +1,83 @@ + +#container { + width: 100%; + height: 100%; + background: var(--page-background); + padding: 40px; + display: flex; + flex-flow: column; + gap: 20px; +} + +#profile-image { + width: 200px; + height: 200px; + position: relative; + margin: auto; + margin-top: 50px; + margin-bottom: 30px; +} + +#image-container { + position: relative; + border-radius: 100%; + width: 100%; + height: 100%; + top: 0px; + left: 0px; + overflow: hidden; +} + +#image-container img { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + min-width: 100%; + min-height: 100%; + width: 100%; + height: 100%; + object-fit: cover; + user-select: none; +} + +#profile-image #edit-container { + overflow: unset; +} + +#profile-image #edit { + position: absolute; + top: 15px; + right: 15px; + background: var(--card-background); + width: 30px; + height: 30px; + padding: 6px; + border-radius: 100%; + box-shadow: var(--shadow); + cursor: pointer; +} + +#info-box { + width: 100%; + text-align: center; + color: var(--fg-disabled); + font-weight: lighter; + user-select: none; +} + +#info-box #name { + font-family: 'Pacifico'; +} + +#logout { + padding: 10px; + width: 100%; + text-align: center; + background: #ee5151; + box-shadow: var(--shadow); + color: #fff; + font-weight: bold; + border-radius: var(--border-radius); + cursor: pointer; +} diff --git a/static/pages/settings/index.js b/static/pages/settings/index.js new file mode 100644 index 0000000..da30ba7 --- /dev/null +++ b/static/pages/settings/index.js @@ -0,0 +1,62 @@ +import * as sfw from 'sfw'; +const { Div, Img } = sfw.element.native; + +import Editable from '../../widgets/editable/index.js'; + +import icons from '../../icons/index.js'; + +const css = await sfw.css(import.meta.url, './index.css'); + +export default class SettingsView extends sfw.element.Container { + constructor() { + super({ css }); + + this.onlogout = () => {}; + + this.body.append( + Div.new({ + id: 'container', + children: [ + Div.new({ + id: 'profile-image', + children: [ + Div.new({ + id: 'image-container', + children: [ + Img.new({ + src: '/images/0010.jpg', + }), + ] + }), + Div.new({ + id: 'edit', + children: [ icons.edit ] + }), + ] + }), + Editable.new({ + title: 'Name', + value: 'Nathan Reiner' + }), + Editable.new({ + title: 'Birthday', + type: 'date', + value: '2002-08-06', + }), + Div.new({ + id: 'logout', + innerText: 'Log-out', + onclick: () => this.onlogout(), + }), + Div.new({ + id: 'info-box', + children: [ + Div.new({ id: 'name', innerText: 'Memora' }), + Div.new({ id: 'version', innerText: '0.0.1-unstable' }), + ] + }), + ] + }) + ) + } +} diff --git a/static/pages/shuffle/index.css b/static/pages/shuffle/index.css new file mode 100644 index 0000000..534a647 --- /dev/null +++ b/static/pages/shuffle/index.css @@ -0,0 +1,6 @@ + +#container { + width: 100%; + height: 100%; + background: var(--page-background); +} diff --git a/static/pages/shuffle/index.js b/static/pages/shuffle/index.js new file mode 100644 index 0000000..b282556 --- /dev/null +++ b/static/pages/shuffle/index.js @@ -0,0 +1,17 @@ +import * as sfw from 'sfw'; +const { Div } = sfw.element.native; + +const css = await sfw.css(import.meta.url, './index.css'); + +export default class ShuffleView extends sfw.element.Container { + constructor() { + super({ css }); + + this.body.append( + Div.new({ + id: 'container', + innerText: 'shuffle', + }) + ) + } +} |