diff options
Diffstat (limited to 'services/docker/nginx/sites/www/src')
-rw-r--r-- | services/docker/nginx/sites/www/src/main.ts | 47 | ||||
-rw-r--r-- | services/docker/nginx/sites/www/src/style.css | 148 |
2 files changed, 195 insertions, 0 deletions
diff --git a/services/docker/nginx/sites/www/src/main.ts b/services/docker/nginx/sites/www/src/main.ts new file mode 100644 index 0000000..09e8661 --- /dev/null +++ b/services/docker/nginx/sites/www/src/main.ts @@ -0,0 +1,47 @@ +import "./style.css"; + +class Emotion { + static opposite_map = new Map<Emotion, Emotion>(); + + constructor(public readonly name: string) { + } + + get opposite(): Emotion { + return Emotion.opposite_map.get(this)!; + } + + get element(): HTMLDivElement { + return document.querySelector<HTMLDivElement>(`.slogan.${this.name}`)! + } + + get elementHeight(): number { + return this.element.clientHeight; + } + + apply() { + localStorage.setItem(emotionKey, this.name); + document.body.dataset.emotion = this.name; + document.body.style.paddingTop = `${this.elementHeight}px`; + } +} + +const happy = new Emotion("happy") +const angry = new Emotion("angry") +Emotion.opposite_map.set(happy, angry) +Emotion.opposite_map.set(angry, happy) + +const emotionKey = "emotion"; +const savedEmotionName = localStorage.getItem(emotionKey) ?? happy.name; + +for (const emotion of [happy, angry]) { + if (emotion.name == savedEmotionName) { + emotion.apply(); + } + emotion.element.addEventListener("click", () => { + emotion.opposite.apply(); + }); +} + +setTimeout(() => { + document.body.style.transition = "padding-top 0.8s"; +}); diff --git a/services/docker/nginx/sites/www/src/style.css b/services/docker/nginx/sites/www/src/style.css new file mode 100644 index 0000000..05c98a0 --- /dev/null +++ b/services/docker/nginx/sites/www/src/style.css @@ -0,0 +1,148 @@ +html { + width: 100%; +} + +body { + width: 100%; + margin: 0; + display: flex; + flex-direction: column; +} + +a { + font-family: monospace; +} + +.fake-link { + font-family: monospace; +} + +#main-article { + max-width: 880px; + margin-top: 1em; + padding: 0 1em; + align-self: center; +} + +#title-name { + font-family: monospace; + background-color: black; + color: white; +} + +@keyframes content-enter { + from { + opacity: 0; + transform: translateY(100px); + } + + to { + opacity: 1; + transform: translateY(0); + } +} + +@keyframes avatar-enter { + from { + opacity: 0; + transform: translateX(100%); + } + + to { + opacity: 1; + transform: translateX(0); + } +} + +#main-article > * { + animation: content-enter 0.8s; +} + +#avatar { + float: right; + animation: avatar-enter 0.8s; +} + +.slogan-container { + width: 100vw; + top: 0; + position: fixed; +} + +.slogan { + width: 100%; + padding: 0.5em 1em; + text-align: center; + box-sizing: border-box; + color: white; + position: absolute; + transform: translateY(-100%); + transition: transform 0.8s; +} + +.slogan.happy { + background-color: dodgerblue; +} + +.slogan.angry { + background-color: orangered; +} + +body[data-emotion="happy"] .slogan.happy { + transform: translateY(0); +} + +body[data-emotion="angry"] .slogan.angry { + transform: translateY(0); +} + +#friends-container { + display: flex; + gap: 1em; +} + +.friend { + flex-grow: 0; + text-align: center; +} + +.friend a { + font-family: unset; +} + +.friend-avatar { + object-fit: cover; +} + +.friend-github { + width: 1em; + vertical-align: middle; + margin-right: -0.5em; +} + +.friend-tag { + font-size: 0.8em; +} + +.citation { + margin: auto; +} + +.citation figcaption { + text-align: right; +} + +#license a { + font-family: initial; + text-decoration: none; +} + +#license-text { + font-family: monospace; + text-decoration: initial; +} + +#license-img-container img { + height: 1em; + vertical-align: middle; +} |