feat: New ui index

Init example starts like an application with fullscreen steps leading to an idle or menu state.
Each step has specific events to trigger the next step.

- Add index screen to ui
- Add own script
- Update ui style
This commit is contained in:
sthag 2025-05-02 19:50:26 +02:00
parent 37986e7b4b
commit 234f4e6e7d
4 changed files with 259 additions and 2 deletions

77
source/code/ui.js Normal file
View file

@ -0,0 +1,77 @@
let introDelay = 6;
let hintDelay = 1;
const intro = {
element: document.getElementById('intro'),
delay: introDelay * 1000,
show() {
if (typeof this.timeoutId === 'number') {
this.cancel();
}
console.info("Intro begin.");
this.element.classList.replace('op_hide', 'op_show');
this.timeoutId = setTimeout(
() => {
this.dismiss();
},
this.delay
)
},
dismiss() {
this.element.classList.replace('op_show', 'op_hide');
this.timeoutId = undefined;
this.element.addEventListener('transitionend', () => {
console.info("Intro fin.");
agree();
});
},
cancel() {
clearTimeout(this.timeoutId);
}
};
const agreement = document.getElementById('agreement');
const hint = {
element: document.getElementById('hint'),
delay: hintDelay * 1000,
show() {
if (typeof this.timeoutId === 'number') {
this.cancel();
}
this.element.classList.remove('di_none');
this.timeoutId = setTimeout(
() => {
this.dismiss();
},
this.delay
);
},
dismiss() {
this.element.classList.add('di_none');
this.timeoutId = undefined;
},
cancel() {
clearTimeout(this.timeoutId);
}
};
window.addEventListener('click', () => hint.show());
window.addEventListener('keydown', () => hint.show());
if (intro.element) intro.show();
function agree() {
if (agreement) {
console.info("Agreement show.");
agreement.classList.replace('op_hide', 'op_show');
setTimeout(() => {
agreement.classList.replace('op_show', 'op_hide');
console.info("Agreement closed.");
}, introDelay * 1000)
}
}

View file

@ -0,0 +1,73 @@
---
title: Init
tags:
- demoExample
- index
- ui
---
{% set pageId = "init" %}
{% set pageClass = "html_ui" %}
{% extends "demo/_app.njk" %}
{% block title %}{{ title }}
{% endblock %}
{% block links %}
<link href="{{ pageBase }}css/ui.css" media="all" rel="stylesheet"/>
{% endblock %}
{% block head %}
{{ super() }}
{% endblock %}
{% block body %}
<div id="hint" class="toast di_none" role="alert" aria-live="assertive" aria-atomic="true">
<p>Hold <kbd>space</kbd> to skip.</p>
</div>
<div id="intro" class="op_hide">
<div class="brand">
{# <img src="" alt="Brand logo"> #}
<svg
width="128"
height="128"
viewBox="0 0 128 128"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<g>
<rect
style="display:inline;fill:none;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-dasharray:none"
width="126"
height="126"
x="1"
y="1" />
<circle
style="fill:none;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:bevel;stroke-dasharray:none"
cx="64"
cy="64"
r="63" />
<path
style="fill:none;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:bevel;stroke-dasharray:none"
d="m 9.3926879,32.472455 109.2146221,-2e-6 -54.607309,94.582637 z" />
</g>
</svg>
<h1>Brand name</h1>
</div>
<p>Powered by</p>
<ul class="tech-stack">
<li>Vendor</li>
<li>IDE</li>
<li>Engine</li>
</ul>
</div>
<div id="agreement" class="op_hide">
<div class="hello">Hello World!</div>
<p class="hello">Only left mouse click or any key</p>
</div>
{% endblock %}
{%- block script %}
{{ super() }}
<script src="{{ pageBase }}js/ui.js"></script>
{% endblock %}

View file

@ -1,6 +1,113 @@
@use "sass:map";
@import "demo_config"; @import "demo_config";
@import "hippie-style/hippie"; @import "hippie-style/hippie";
$z-indexes: (
"default": 0,
"content-bottom": 1,
"content-low": 2,
"content-med": 3,
"content-high": 4,
"content-top": 10,
"modal-low": 11,
"modal-med": 12,
"modal-high": 13,
"toast": 100
);
.op_show {
transition: $transition_show;
}
.op_hide {
transition: $transition_hide;
}
.html_ui {
height: 100%;
body {
position: relative;
min-height: 100%;
background-color: black;
}
}
#intro {
@extend %full_parent;
z-index: map.get($z-indexes, "content-top");
overflow: hidden;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background-color: black;
h1,
p,
li {
color: white;
}
}
.brand {
text-align: center;
img {
display: inline-block;
width: 128px;
height: 128px;
background-color: white;
}
*+h1 {
margin-top: $space_small;
margin-bottom: $space_large;
}
}
.tech-stack {
display: flex;
padding-left: 0;
li {
list-style: none;
padding-inline: $space_double;
}
}
#agreement {
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
background-color: $color_back_basic;
}
.toast {
z-index: map.get($z-indexes, "toast");
position: fixed;
right: $space_half;
bottom: $space_double;
p {
color: white;
}
kbd {
border-color: $color_brighter;
color: $color_back_io;
}
}
.hello {
flex: 0 1 auto;
padding: 1em 2em;
background-color: rgba(black, .25);
}
@import "modules/ui/new_module"; @import "modules/ui/new_module";
@import "modules/ui/settings_module"; @import "modules/ui/settings_module";
@import "modules/ui/drag_module"; @import "modules/ui/drag_module";

View file

@ -1,6 +1,6 @@
<!-- body_nav.partial --> <!-- body_nav.partial -->
<div class="pos_rel"> <div class="pos_rel">
<nav class="nav_page_meta js_"> <nav class="nav_page_meta">
<ul> <ul>
<li class="js_scrolltop di_none"> <li class="js_scrolltop di_none">
<a href="#begin" class="a_button_meta"> <a href="#begin" class="a_button_meta">