narrow desktop breakpoint constraint relaxed somewhat to accomodate more fringe-case window aspect ratios; #id_gear_btn now, like #id_kit_btn, restyles to contain --quaUser rgb value when menu is active; dashboard.html include ordering switched for #id_dash_applet_menu & #id_gear_btn, to fix an issue causing the menu to overlay the btn instead of the other way around
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed

This commit is contained in:
Disco DeDisco
2026-03-15 16:39:14 -04:00
parent 2e24175ec8
commit ff7b71792f
8 changed files with 79 additions and 50 deletions

View File

@@ -6,7 +6,9 @@ const initGearMenus = () => {
e.stopPropagation(); e.stopPropagation();
const menu = document.getElementById(menuId); const menu = document.getElementById(menuId);
if (!menu) return; if (!menu) return;
menu.style.display = menu.style.display === 'none' ? 'block' : 'none'; const opening = menu.style.display === 'none' || menu.style.display === '';
menu.style.display = opening ? 'block' : 'none';
gear.classList.toggle('active', opening);
}); });
document.addEventListener('click', (e) => { document.addEventListener('click', (e) => {
@@ -14,6 +16,7 @@ const initGearMenus = () => {
if (!menu || menu.style.display === 'none') return; if (!menu || menu.style.display === 'none') return;
if (e.target.closest('.applet-menu-cancel') || !menu.contains(e.target)) { if (e.target.closest('.applet-menu-cancel') || !menu.contains(e.target)) {
menu.style.display = 'none'; menu.style.display = 'none';
gear.classList.remove('active');
} }
}); });
}) })
@@ -33,5 +36,6 @@ document.body.addEventListener('htmx:afterSwap', (e) => {
document.querySelectorAll('.gear-btn').forEach(gear => { document.querySelectorAll('.gear-btn').forEach(gear => {
const menu = document.getElementById(gear.dataset.menuTarget); const menu = document.getElementById(gear.dataset.menuTarget);
if (menu) menu.style.display = 'none'; if (menu) menu.style.display = 'none';
gear.classList.remove('active');
}); });
}); });

View File

@@ -9,8 +9,10 @@
}); });
btn.addEventListener('click', function () { btn.addEventListener('click', function () {
if (dialog.open) { if (btn.classList.contains('active')) {
dialog.close(); dialog.removeAttribute('open');
btn.classList.remove('active');
clearSelection();
return; return;
} }
fetch(btn.dataset.kitUrl, { fetch(btn.dataset.kitUrl, {
@@ -61,9 +63,9 @@
}); });
function attachCardListeners() { function attachCardListeners() {
dialog.querySelectorAll('.kit-card').forEach(function (card) { dialog.querySelectorAll('.token[data-token-id]').forEach(function (card) {
card.addEventListener('click', function () { card.addEventListener('click', function () {
dialog.querySelectorAll('.kit-card.selected').forEach(function (c) { dialog.querySelectorAll('.token[data-token-id].selected').forEach(function (c) {
c.classList.remove('selected'); c.classList.remove('selected');
}); });
card.classList.add('selected'); card.classList.add('selected');
@@ -71,6 +73,21 @@
var slot = document.querySelector('.token-slot'); var slot = document.querySelector('.token-slot');
if (slot) slot.classList.add('ready'); if (slot) slot.classList.add('ready');
}); });
card.addEventListener('mouseenter', function () {
var tooltip = card.querySelector('.token-tooltip');
if (!tooltip) return;
var rect = card.getBoundingClientRect();
tooltip.style.position = 'fixed';
tooltip.style.bottom = (window.innerHeight - rect.top + 8) + 'px';
tooltip.style.left = rect.left + 'px';
tooltip.style.display = 'block';
});
card.addEventListener('mouseleave', function () {
var tooltip = card.querySelector('.token-tooltip');
if (tooltip) tooltip.style.display = '';
});
}); });
} }

View File

@@ -15,6 +15,11 @@
border-radius: 50%; border-radius: 50%;
background-color: rgba(var(--priUser), 1); background-color: rgba(var(--priUser), 1);
border: 0.15rem solid rgba(var(--secUser), 1); border: 0.15rem solid rgba(var(--secUser), 1);
&.active {
color: rgba(var(--quaUser), 1);
border-color: rgba(var(--quaUser), 1);
}
} }
// ── Applet menu (shared structure) ───────────────────────── // ── Applet menu (shared structure) ─────────────────────────

View File

@@ -66,54 +66,35 @@
.kit-bag-label { .kit-bag-label {
font-size: 0.55rem; font-size: 0.55rem;
text-transform: uppercase; text-transform: uppercase;
text-decoration: underline;
letter-spacing: 0.12em; letter-spacing: 0.12em;
color: rgba(var(--secUser), 0.35); color: rgba(var(--secUser), 0.35);
writing-mode: vertical-rl; writing-mode: vertical-rl;
text-orientation: mixed; text-orientation: mixed;
transform: rotate(180deg); transform: rotate(180deg);
padding: 0 0.25rem 0 0.5rem;
} }
.kit-bag-row { .kit-bag-row {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
gap: 0.4rem; gap: 0.75rem;
} }
.kit-card { #id_kit_bag_dialog {
display: flex; .token {
flex-direction: column; font-size: 1.5rem;
align-items: center; cursor: pointer;
gap: 0.15rem; transition: filter 0.15s;
padding: 0.3rem 0.4rem; padding: 0 0.125rem;
border: 0.1rem solid rgba(var(--terUser), 0.35);
border-radius: 0.4rem; &:hover .token-tooltip { display: none; } // JS positions these as fixed
cursor: pointer;
min-width: 3rem;
transition: border-color 0.15s, box-shadow 0.15s;
i {
font-size: 1.1rem;
color: rgba(var(--terUser), 0.7);
} }
.kit-card-label { .token-tooltip {
font-size: 0.5rem; z-index: 9999;
color: rgba(var(--secUser), 0.45);
text-align: center;
white-space: nowrap;
}
&:hover {
border-color: rgba(var(--terUser), 0.7);
}
&.selected {
border-color: rgba(var(--terUser), 1);
box-shadow:
0 0 0.4rem rgba(var(--terUser), 0.5),
0 0 1rem rgba(var(--terUser), 0.2)
;
i { color: rgba(var(--terUser), 1); }
} }
} }

View File

@@ -327,7 +327,7 @@ body:has(.gate-overlay) {
} }
// Narrow viewport — scale down, 2×3 slot grid (portrait mobile + narrow desktop) // Narrow viewport — scale down, 2×3 slot grid (portrait mobile + narrow desktop)
@media (max-width: 550px) { @media (max-width: 700px) {
.gate-modal { .gate-modal {
padding: 1.25rem 1.5rem; padding: 1.25rem 1.5rem;

View File

@@ -16,6 +16,17 @@
font-size: 0.95rem; font-size: 0.95rem;
margin: 0 0 0.3rem 0; margin: 0 0 0.3rem 0;
color: rgba(var(--terUser), 1); color: rgba(var(--terUser), 1);
display: flex;
justify-content: space-between;
align-items: baseline;
gap: 0.5rem;
.token-count {
font-size: 0.75rem;
opacity: 0.65;
font-weight: normal;
flex-shrink: 0;
}
} }
p { p {

View File

@@ -11,8 +11,8 @@
{% block content %} {% block content %}
{% if user.is_authenticated %} {% if user.is_authenticated %}
<div id="id_dash_content" class="dashboard-page"> <div id="id_dash_content" class="dashboard-page">
{% include "apps/applets/_partials/_gear.html" with menu_id="id_dash_applet_menu" %}
{% include "apps/dashboard/_partials/_applets.html" %} {% include "apps/dashboard/_partials/_applets.html" %}
{% include "apps/applets/_partials/_gear.html" with menu_id="id_dash_applet_menu" %}
</div> </div>
{% endif %} {% endif %}
{% endblock content %} {% endblock content %}

View File

@@ -5,7 +5,7 @@
{% for token in tokens %} {% for token in tokens %}
{% if token.token_type == "coin" or token.token_type == "pass" %} {% if token.token_type == "coin" or token.token_type == "pass" %}
<div <div
class="kit-card" class="token"
draggable="true" draggable="true"
data-token-id="{{ token.id }}" data-token-id="{{ token.id }}"
data-token-type="{{ token.token_type }}" data-token-type="{{ token.token_type }}"
@@ -15,7 +15,14 @@
{% else %} {% else %}
<i class="fa-solid fa-clipboard"></i> <i class="fa-solid fa-clipboard"></i>
{% endif %} {% endif %}
<span class="kit-card-label">{{ token.tooltip_name }}</span> <div class="token-tooltip">
<h4>{{ token.tooltip_name }}</h4>
<p>{{ token.tooltip_description }}</p>
{% if token.tooltip_shoptalk %}
<small><em>{{ token.tooltip_shoptalk }}</em></small>
{% endif %}
<p class="expiry">{{ token.tooltip_expiry }}</p>
</div>
</div> </div>
{% endif %} {% endif %}
{% endfor %} {% endfor %}
@@ -26,28 +33,32 @@
<div class="kit-bag-row"> <div class="kit-bag-row">
{% if free_token %} {% if free_token %}
<div <div
class="kit-card" class="token"
draggable="true" draggable="true"
data-token-id="{{ free_token.id }}" data-token-id="{{ free_token.id }}"
data-token-type="{{ free_token.token_type }}" data-token-type="{{ free_token.token_type }}"
> >
<i class="fa-solid fa-coins"></i> <i class="fa-solid fa-coins"></i>
<span class="kit-card-label"> <div class="token-tooltip">
{{ free_token.tooltip_name }}{% if free_count > 1 %} <span class="kit-card-count">(×{{ free_count }})</span>{% endif %} <h4>{{ free_token.tooltip_name }}{% if free_count > 1 %} <span class="token-count">(×{{ free_count }})</span>{% endif %}</h4>
</span> <p>{{ free_token.tooltip_description }}</p>
<p class="expiry">{{ free_token.tooltip_expiry }}</p>
</div>
</div> </div>
{% endif %} {% endif %}
{% if tithe_token %} {% if tithe_token %}
<div <div
class="kit-card" class="token"
draggable="true" draggable="true"
data-token-id="{{ tithe_token.id }}" data-token-id="{{ tithe_token.id }}"
data-token-type="{{ tithe_token.token_type }}" data-token-type="{{ tithe_token.token_type }}"
> >
<i class="fa-solid fa-piggy-bank"></i> <i class="fa-solid fa-piggy-bank"></i>
<span class="kit-card-label"> <div class="token-tooltip">
{{ tithe_token.tooltip_name }}{% if tithe_count > 1 %} <span class="kit-card-count">(×{{ tithe_count }})</span>{% endif %} <h4>{{ tithe_token.tooltip_name }}{% if tithe_count > 1 %} <span class="token-count">(×{{ tithe_count }})</span>{% endif %}</h4>
</span> <p>{{ tithe_token.tooltip_description }}</p>
<p class="expiry">{{ tithe_token.tooltip_expiry }}</p>
</div>
</div> </div>
{% endif %} {% endif %}
</div> </div>