From b6124fb3a5ca92f9aebab9f632e6a4e33356343e Mon Sep 17 00:00:00 2001 From: Lars Gebhardt-Kusche Date: Sat, 24 Jan 2026 02:04:46 +0100 Subject: [PATCH] dasd --- partials/landing/main/material-matrix.php | 2 + public/assets/app.css | 81 ++++++++++++++- public/assets/app.js | 119 ++++++++++++++++++++-- 3 files changed, 188 insertions(+), 14 deletions(-) diff --git a/partials/landing/main/material-matrix.php b/partials/landing/main/material-matrix.php index 36263f5..3362985 100644 --- a/partials/landing/main/material-matrix.php +++ b/partials/landing/main/material-matrix.php @@ -52,6 +52,8 @@ $app->assets()->addScript('/assets/app.js', 'footer', true); + +
diff --git a/public/assets/app.css b/public/assets/app.css index c584e42..27b0629 100644 --- a/public/assets/app.css +++ b/public/assets/app.css @@ -28,9 +28,9 @@ } .mm-shell { - max-width: 1200px; + max-width: 1500px; margin: 0 auto; - padding: 3rem 2rem 4rem; + padding: 2.5rem 1.5rem 4rem; animation: fadeUp 0.6s ease both; } @@ -161,8 +161,81 @@ vertical-align: top; } -.mm-table tbody td[title] { - cursor: help; + +.mm-info-btn { + display: inline-flex; + align-items: center; + gap: 0.35rem; + font-size: 0.7rem; + font-weight: 600; + border-radius: 999px; + border: 1px solid var(--line); + background: #fff7ed; + color: #9a3412; + padding: 0.15rem 0.5rem; + margin-top: 0.3rem; +} + +.mm-tooltip { + position: fixed; + z-index: 50; + max-width: 280px; + background: #101018; + color: #f4f4f7; + border-radius: 12px; + padding: 0.6rem 0.75rem; + box-shadow: 0 16px 40px rgba(0, 0, 0, 0.25); + font-size: 0.75rem; + line-height: 1.35; + pointer-events: none; + opacity: 0; + transform: translateY(6px); + transition: opacity 0.12s ease, transform 0.12s ease; +} + +.mm-tooltip.is-visible { + opacity: 1; + transform: translateY(0); +} + +.mm-details-row { + background: #fffaf3; +} + +.mm-details { + padding: 0.9rem 1rem; + border-left: 3px solid var(--accent); + display: grid; + grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); + gap: 0.6rem 1rem; + font-size: 0.85rem; + color: var(--muted); + position: relative; +} + +.mm-details strong { + color: var(--ink); + display: block; + font-size: 0.75rem; + text-transform: uppercase; + letter-spacing: 0.08em; +} + +.mm-row-toggle { + cursor: pointer; +} + +.mm-details-close { + position: absolute; + top: 0.6rem; + right: 0.8rem; + border: 1px solid var(--line); + background: #fff; + border-radius: 999px; + padding: 0.2rem 0.6rem; + font-size: 0.7rem; + color: var(--muted); + cursor: pointer; } .mm-table tbody tr:nth-child(even) { diff --git a/public/assets/app.js b/public/assets/app.js index 41f471f..9905be2 100644 --- a/public/assets/app.js +++ b/public/assets/app.js @@ -6,6 +6,7 @@ const tableHead = document.getElementById('tableHead'); const statusEl = document.getElementById('status'); const errorBox = document.getElementById('errorBox'); + const tooltipEl = document.getElementById('mmTooltip'); if (!printerSelect || !printerCompare || !matBody || !tableHead) { return; @@ -142,17 +143,20 @@ ? { icon: '✅', text: 'niedrig' } : (m.emission === 'medium' ? { icon: '⚠️', text: 'mittel' } : { icon: '⛔', text: 'hoch' }); - const tooltipLines = [ - m.tg_celsius ? `Tg °C: ${m.tg_celsius}` : 'Tg °C: –', - m.nozzle_req ? `Düse: ${m.nozzle_req}` : 'Düse: –', - m.plate_req ? `Platte: ${m.plate_req}` : 'Platte: –', - m.extra_req ? `Zusatz: ${m.extra_req}` : 'Zusatz: –', - m.emission ? `Emission: ${m.emission}` : 'Emission: –' - ]; - const tooltip = escapeHtml(tooltipLines.join(' | ')); - let html = ''; - html += `${escapeHtml(m.code)}
${escapeHtml(m.short_desc || '')}
`; + const detailPayload = { + tg: m.tg_celsius ?? '–', + nozzle: m.nozzle_req ?? '–', + plate: m.plate_req ?? '–', + extra: m.extra_req ?? '–', + emission: m.emission ?? '–' + }; + const detailAttr = escapeHtml(JSON.stringify(detailPayload)); + html += `` + + `${escapeHtml(m.code)}` + + `
${escapeHtml(m.short_desc || '')}
` + + `` + + ``; html += `${escapeHtml(m.properties || '')}`; html += `${escapeHtml(m.application || '')}`; html += `${kid.icon}`; @@ -186,6 +190,101 @@ }); } + function setTooltip(content, x, y) { + if (!tooltipEl) return; + tooltipEl.textContent = content; + const padding = 12; + const maxX = window.innerWidth - tooltipEl.offsetWidth - padding; + const maxY = window.innerHeight - tooltipEl.offsetHeight - padding; + const left = Math.min(x + 14, maxX); + const top = Math.min(y + 14, maxY); + tooltipEl.style.left = Math.max(left, padding) + 'px'; + tooltipEl.style.top = Math.max(top, padding) + 'px'; + tooltipEl.classList.add('is-visible'); + tooltipEl.setAttribute('aria-hidden', 'false'); + } + + function hideTooltip() { + if (!tooltipEl) return; + tooltipEl.classList.remove('is-visible'); + tooltipEl.setAttribute('aria-hidden', 'true'); + } + + function buildDetailsHtml(details) { + return ` + +
Tg °C${escapeHtml(details.tg)}
+
Düse${escapeHtml(details.nozzle)}
+
Platte${escapeHtml(details.plate)}
+
Zusatz${escapeHtml(details.extra)}
+
Emission${escapeHtml(details.emission)}
+ `; + } + + function closeActiveDetails() { + const open = matBody.querySelector('tr.mm-details-row'); + if (open) { + open.remove(); + } + const active = matBody.querySelector('tr.is-active'); + if (active) { + active.classList.remove('is-active'); + } + } + + matBody.addEventListener('mouseover', (e) => { + const cell = e.target.closest('[data-details]'); + if (!cell) return; + let details; + try { + details = JSON.parse(cell.dataset.details || '{}'); + } catch { + details = {}; + } + const hoverText = `Tg °C: ${details.tg ?? '–'} | Düse: ${details.nozzle ?? '–'} | Platte: ${details.plate ?? '–'} | Zusatz: ${details.extra ?? '–'} | Emission: ${details.emission ?? '–'}`; + setTooltip(hoverText, e.clientX, e.clientY); + }); + + matBody.addEventListener('mousemove', (e) => { + if (!tooltipEl || tooltipEl.getAttribute('aria-hidden') === 'true') return; + setTooltip(tooltipEl.textContent, e.clientX, e.clientY); + }); + + matBody.addEventListener('mouseout', (e) => { + if (e.target.closest('[data-details]')) { + hideTooltip(); + } + }); + + matBody.addEventListener('click', (e) => { + if (e.target.closest('.mm-details-close')) { + closeActiveDetails(); + return; + } + + const cell = e.target.closest('[data-details]'); + if (!cell) return; + + const row = cell.closest('tr'); + const isActive = row.classList.contains('is-active'); + closeActiveDetails(); + if (isActive) return; + + let details; + try { + details = JSON.parse(cell.dataset.details || '{}'); + } catch { + details = {}; + } + + const colCount = row.children.length; + const detailRow = document.createElement('tr'); + detailRow.className = 'mm-details-row'; + detailRow.innerHTML = `
${buildDetailsHtml(details)}
`; + row.classList.add('is-active'); + row.parentNode.insertBefore(detailRow, row.nextSibling); + }); + printerSelect.addEventListener('change', e => { const id = e.target.value; if (id) {