tooltips wip

This commit is contained in:
dragonwocky 2021-04-26 15:12:24 +10:00
parent 15b34ef638
commit 1d9785f804
4 changed files with 83 additions and 37 deletions

View File

@ -21,6 +21,7 @@ html[class] {
body { body {
padding: 2rem 2.5rem; padding: 2rem 2.5rem;
position: relative;
margin: 0; margin: 0;
background: var(--theme--sidebar); background: var(--theme--sidebar);
color: var(--theme--text); color: var(--theme--text);
@ -39,7 +40,7 @@ header > * {
margin: 0 1.25rem 0 0; margin: 0 1.25rem 0 0;
font-size: var(--theme--font_heading1-size); font-size: var(--theme--font_heading1-size);
} }
header h1 a:not([data-active]) { header h1 a:not([data-view-active]) {
text-decoration: none; text-decoration: none;
} }
header h1 img { header h1 img {
@ -61,7 +62,7 @@ header h1 svg[data-icon='code'] {
margin-right: 0.3em; margin-right: 0.3em;
} }
img[data-target='notion'] { img[data-view-target='notion'] {
cursor: pointer; cursor: pointer;
} }
@ -95,8 +96,9 @@ img[data-target='notion'] {
[data-container='mod'] > .documentation--body { [data-container='mod'] > .documentation--body {
grid-column: span 2; grid-column: span 2;
} }
body { [data-container='mod'] {
overflow: hidden; overflow: hidden;
max-height: calc(100vh);
} }
} }
@media (min-width: 1350px) { @media (min-width: 1350px) {
@ -372,6 +374,21 @@ label > span:not([class]) {
overflow-x: auto; overflow-x: auto;
} }
.tooltip--list > div {
position: absolute;
background: var(--theme--tooltip);
color: var(--theme--tooltip-text);
font-size: var(--theme--font_ui_small-size);
padding: 0.5rem;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06) !important;
border-radius: 3px;
max-width: 20rem;
display: none;
}
.tooltip--list p {
margin: 0.25rem 0;
}
.notification--list { .notification--list {
position: absolute; position: absolute;
bottom: 1.5rem; bottom: 1.5rem;

View File

@ -8,11 +8,8 @@
<body> <body>
<header> <header>
<h1> <h1>
<img data-target="notion" alt="" width="24" src="../../icons/colour.svg" /><a <img data-view-target="notion" alt="" width="24" src="../../icons/colour.svg" />
href="?view=library" <a href="?view=library" data-view-target="library">library</a>
data-target="library"
>library</a
>
</h1> </h1>
<h1> <h1>
<i data-icon="fa/info"></i><a href="https://notion-enhancer.github.io/">website</a> <i data-icon="fa/info"></i><a href="https://notion-enhancer.github.io/">website</a>
@ -23,9 +20,8 @@
</h1> </h1>
<h1><i data-icon="fa/discord"></i><a href="https://discord.gg/sFWPXtA">support</a></h1> <h1><i data-icon="fa/discord"></i><a href="https://discord.gg/sFWPXtA">support</a></h1>
</header> </header>
<main> <main data-container></main>
<section data-container></section> <section class="tooltip--list"></section>
</main>
<footer class="notification--list"></footer> <footer class="notification--list"></footer>
<script src="./menu.js" type="module"></script> <script src="./menu.js" type="module"></script>
</body> </body>

View File

@ -15,9 +15,30 @@ for (let mod of await registry.get()) {
} }
} }
document.querySelector('img[data-target="notion"]').addEventListener('click', env.focusNotion); document
.querySelector('img[data-view-target="notion"]')
.addEventListener('click', env.focusNotion);
web.hotkeyListener(['Ctrl', 'Alt', 'E'], env.focusNotion); web.hotkeyListener(['Ctrl', 'Alt', 'E'], env.focusNotion);
const tooltips = {
$list: document.querySelector('.tooltip--list'),
_generate($target, text) {
const $tooltip = web.createElement(web.html`<div>${fmt.md.render(text)}</div>`);
this.$list.appendChild($tooltip);
$target.addEventListener('mouseover', (event) => {
$tooltip.style.display = 'block';
});
$target.addEventListener('mousemove', (event) => {
$tooltip.style.top = event.clientY - $tooltip.clientHeight + 'px';
$tooltip.style.left =
event.clientX < window.innerWidth / 2 ? event.clientX + 20 + 'px' : '';
});
$target.addEventListener('mouseout', (event) => {
$tooltip.style.display = '';
});
},
};
const components = {}; const components = {};
components.card = { components.card = {
preview: ({ preview = '' }) => preview: ({ preview = '' }) =>
@ -87,25 +108,26 @@ components.card = {
}, },
}; };
components.options = { components.options = {
async toggle(id, { key, label }) { async toggle(id, { key, label, description }) {
const state = await storage.get(id, key), const state = await storage.get(id, key),
opt = web.createElement(web.html`<label opt = web.createElement(web.html`<label
for="toggle--${web.escapeHtml(`${id}.${key}`)}" for="toggle--${web.escapeHtml(`${id}.${key}`)}"
class="library--toggle_label" class="library--toggle_label"
> >
<input type="checkbox" id="toggle--${web.escapeHtml(`${id}.${key}`)}" <input type="checkbox" id="toggle--${web.escapeHtml(`${id}.${key}`)}"
${state ? 'checked' : ''}/> ${state ? 'checked' : ''}/>
<p><span>${label}</span><span class="library--toggle"></span></p <p><span>${label}</span><span class="library--toggle"></span></p
></label>`); ></label>`);
opt.addEventListener('change', (event) => storage.set(id, key, event.target.checked)); opt.addEventListener('change', (event) => storage.set(id, key, event.target.checked));
tooltips._generate(opt, description);
return opt; return opt;
}, },
async select(id, { key, label, values }) { async select(id, { key, label, description, values }) {
const state = await storage.get(id, key), const state = await storage.get(id, key),
opt = web.createElement(web.html`<label opt = web.createElement(web.html`<label
for="select--${web.escapeHtml(`${id}.${key}`)}" for="select--${web.escapeHtml(`${id}.${key}`)}"
class="library--select_label" class="library--select_label"
> >
<p>${label}</p> <p>${label}</p>
<p class="library--select"> <p class="library--select">
<span><i data-icon="fa/caret-down"></i></span> <span><i data-icon="fa/caret-down"></i></span>
@ -120,14 +142,15 @@ components.options = {
</p> </p>
</label>`); </label>`);
opt.addEventListener('change', (event) => storage.set(id, key, event.target.value)); opt.addEventListener('change', (event) => storage.set(id, key, event.target.value));
tooltips._generate(opt, description);
return opt; return opt;
}, },
async text(id, { key, label }) { async text(id, { key, label, description }) {
const state = await storage.get(id, key), const state = await storage.get(id, key),
opt = web.createElement(web.html`<label opt = web.createElement(web.html`<label
for="text--${web.escapeHtml(`${id}.${key}`)}" for="text--${web.escapeHtml(`${id}.${key}`)}"
class="library--text_label" class="library--text_label"
> >
<p>${label}</p> <p>${label}</p>
<textarea id="text--${web.escapeHtml(`${id}.${key}`)}" rows="1">${state}</textarea> <textarea id="text--${web.escapeHtml(`${id}.${key}`)}" rows="1">${state}</textarea>
</label>`); </label>`);
@ -136,26 +159,28 @@ components.options = {
event.target.style.setProperty('--txt--scroll-height', event.target.scrollHeight + 'px'); event.target.style.setProperty('--txt--scroll-height', event.target.scrollHeight + 'px');
}); });
opt.addEventListener('change', (event) => storage.set(id, key, event.target.value)); opt.addEventListener('change', (event) => storage.set(id, key, event.target.value));
tooltips._generate(opt, description);
return opt; return opt;
}, },
async number(id, { key, label }) { async number(id, { key, label, description }) {
const state = await storage.get(id, key), const state = await storage.get(id, key),
opt = web.createElement(web.html`<label opt = web.createElement(web.html`<label
for="number--${web.escapeHtml(`${id}.${key}`)}" for="number--${web.escapeHtml(`${id}.${key}`)}"
class="library--number_label" class="library--number_label"
> >
<p>${web.escapeHtml(label)}</p> <p>${web.escapeHtml(label)}</p>
<input id="number--${web.escapeHtml(`${id}.${key}`)}" type="number" value="${state}"/> <input id="number--${web.escapeHtml(`${id}.${key}`)}" type="number" value="${state}"/>
</label>`); </label>`);
opt.addEventListener('change', (event) => storage.set(id, key, event.target.value)); opt.addEventListener('change', (event) => storage.set(id, key, event.target.value));
tooltips._generate(opt, description);
return opt; return opt;
}, },
async file(id, { key, label, extensions }) { async file(id, { key, label, description, extensions }) {
const state = await storage.get(id, key), const state = await storage.get(id, key),
opt = web.createElement(web.html`<label opt = web.createElement(web.html`<label
for="file--${web.escapeHtml(`${id}.${key}`)}" for="file--${web.escapeHtml(`${id}.${key}`)}"
class="library--file_label" class="library--file_label"
> >
<input <input
type="file" type="file"
id="file--${web.escapeHtml(`${id}.${key}`)}" id="file--${web.escapeHtml(`${id}.${key}`)}"
@ -170,11 +195,6 @@ components.options = {
<span><i data-icon="fa/file"></i></span> <span><i data-icon="fa/file"></i></span>
<span class="library--file_path">${state || 'choose file...'}</span> <span class="library--file_path">${state || 'choose file...'}</span>
</p> </p>
<p class="library--warning">
warning: browser extensions do not have true filesystem access,
so the content of the file is saved on selection. after editing it,
the file will need to be re-selected.
</p>
</label>`); </label>`);
opt.addEventListener('change', (event) => { opt.addEventListener('change', (event) => {
const file = event.target.files[0], const file = event.target.files[0],
@ -189,6 +209,12 @@ components.options = {
opt.addEventListener('click', (event) => { opt.addEventListener('click', (event) => {
document.documentElement.scrollTop = 0; document.documentElement.scrollTop = 0;
}); });
tooltips._generate(
opt,
`${description}\n\n**warning:** browser extensions do not have true filesystem access,
so the content of the file is saved on selection. after editing it,
the file will need to be re-selected.`
);
return opt; return opt;
}, },
async _generate(mod) { async _generate(mod) {
@ -270,7 +296,9 @@ const views = {
this.$container.innerHTML = ''; this.$container.innerHTML = '';
this.$container.style.opacity = ''; this.$container.style.opacity = '';
this.$container.dataset.container = ''; this.$container.dataset.container = '';
document.querySelector('[data-target][data-active]')?.removeAttribute('data-active'); document
.querySelector('[data-view-target][data-view-active]')
?.removeAttribute('data-view-active');
res(); res();
}, 200); }, 200);
}); });
@ -326,14 +354,14 @@ const views = {
}, },
async mod(mod) { async mod(mod) {
this.$container.dataset.container = 'mod'; this.$container.dataset.container = 'mod';
document.querySelector('header [data-target="library"]').dataset.active = true; document.querySelector('header [data-view-target="library"]').dataset.active = true;
this.$container.append(await components.documentation.buttons(mod)); this.$container.append(await components.documentation.buttons(mod));
this.$container.append(await components.options._generate(mod)); this.$container.append(await components.options._generate(mod));
this.$container.append(await components.documentation.readme(mod)); this.$container.append(await components.documentation.readme(mod));
}, },
async library() { async library() {
this.$container.dataset.container = 'library'; this.$container.dataset.container = 'library';
document.querySelector('header [data-target="library"]').dataset.active = true; document.querySelector('header [data-view-target="library"]').dataset.active = true;
for (let mod of await registry.get()) for (let mod of await registry.get())
this.$container.append(await components.card._generate(mod)); this.$container.append(await components.card._generate(mod));
}, },

View File

@ -25,31 +25,36 @@
"type": "toggle", "type": "toggle",
"key": "toggle", "key": "toggle",
"label": "toggle", "label": "toggle",
"value": true "value": true,
"description": "a toggle"
}, },
{ {
"type": "select", "type": "select",
"key": "select", "key": "select",
"label": "select", "label": "select",
"values": ["option a", "option b", "option c"] "values": ["option a", "option b", "option c"],
"description": "a select"
}, },
{ {
"type": "text", "type": "text",
"key": "text", "key": "text",
"label": "text", "label": "text",
"value": "default" "value": "default",
"description": "a text input"
}, },
{ {
"type": "number", "type": "number",
"key": "number", "key": "number",
"label": "number", "label": "number",
"value": 0 "value": 0,
"description": "a number input"
}, },
{ {
"type": "file", "type": "file",
"key": "file", "key": "file",
"label": "file picker (.css only)", "label": "file picker (.css only)",
"extensions": [".css"] "extensions": [".css"],
"description": "a file picker"
} }
] ]
} }