Add configurable widget online effects
This commit is contained in:
+43
-7
@@ -25,8 +25,9 @@
|
||||
|
||||
root.innerHTML = `
|
||||
<style>${styles(settings)}</style>
|
||||
<button class="mf-launcher" type="button" aria-label="${copy.title}">
|
||||
<span></span>
|
||||
<button class="mf-launcher ${launcherEffectClasses(settings, site.isOnline)}" type="button" aria-label="${copy.title}">
|
||||
<span class="mf-launcher-icon"></span>
|
||||
<span class="mf-launcher-label">${escapeHtml(site.isOnline ? "Jsme online" : "Offline")}</span>
|
||||
</button>
|
||||
<section class="mf-panel" aria-live="polite">
|
||||
<header>
|
||||
@@ -413,10 +414,23 @@
|
||||
};
|
||||
}
|
||||
|
||||
function launcherEffectClasses(settings, isOnline) {
|
||||
const effects = settings.launcherEffects || {};
|
||||
return [
|
||||
isOnline ? "mf-online" : "mf-offline",
|
||||
effects.breathe ? "mf-effect-breathe" : "",
|
||||
effects.ring ? "mf-effect-ring" : "",
|
||||
effects.hoverLabel ? "mf-effect-hover-label" : "",
|
||||
effects.wave ? "mf-effect-wave" : "",
|
||||
effects.avatar ? "mf-effect-avatar" : ""
|
||||
].filter(Boolean).join(" ");
|
||||
}
|
||||
|
||||
function styles(settings) {
|
||||
const c = settings.colors;
|
||||
const desktop = settings.desktop;
|
||||
const mobile = settings.mobile;
|
||||
const labelOffset = desktop.side === "left" ? "left: 68px; right: auto;" : "right: 68px; left: auto;";
|
||||
return `
|
||||
:host { all: initial; font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; color: ${c.text}; }
|
||||
* { box-sizing: border-box; }
|
||||
@@ -424,12 +438,21 @@
|
||||
.mf-launcher {
|
||||
position: fixed; z-index: 2147483000; ${desktop.side}: ${desktop.sideOffsetPx}px; bottom: ${desktop.bottomPx}px;
|
||||
width: 58px; height: 58px; border: 0; border-radius: 50%; background: ${c.brand}; color: ${c.brandText};
|
||||
box-shadow: 0 12px 30px rgb(0 0 0 / 22%); cursor: pointer;
|
||||
box-shadow: 0 12px 30px rgb(0 0 0 / 22%); cursor: pointer; overflow: visible;
|
||||
}
|
||||
.mf-launcher span, .mf-launcher span:before, .mf-launcher span:after { display: block; background: ${c.brandText}; height: 3px; border-radius: 4px; content: ""; }
|
||||
.mf-launcher span { width: 26px; margin: 0 auto; }
|
||||
.mf-launcher span:before { transform: translateY(-8px); }
|
||||
.mf-launcher span:after { transform: translateY(5px); width: 18px; }
|
||||
.mf-launcher-icon, .mf-launcher-icon:before, .mf-launcher-icon:after { display: block; background: ${c.brandText}; height: 3px; border-radius: 4px; content: ""; }
|
||||
.mf-launcher-icon { width: 26px; margin: 0 auto; }
|
||||
.mf-launcher-icon:before { transform: translateY(-8px); }
|
||||
.mf-launcher-icon:after { transform: translateY(5px); width: 18px; }
|
||||
.mf-launcher-label { position: absolute; ${labelOffset} top: 50%; transform: translateY(-50%) translateX(8px); opacity: 0; pointer-events: none; white-space: nowrap; border-radius: 999px; padding: 7px 10px; background: ${c.text}; color: white; font-size: 12px; box-shadow: 0 10px 24px rgb(0 0 0 / 18%); transition: opacity .18s ease, transform .18s ease; }
|
||||
.mf-effect-hover-label:hover .mf-launcher-label { opacity: 1; transform: translateY(-50%) translateX(0); }
|
||||
.mf-online.mf-effect-breathe { animation: mfBreathe 2.8s ease-in-out infinite; }
|
||||
.mf-online.mf-effect-ring:before { position: absolute; inset: -5px; border: 2px solid ${c.brand}; border-radius: 50%; opacity: .62; content: ""; animation: mfRing 2.2s ease-out infinite; }
|
||||
.mf-online.mf-effect-wave:after { position: absolute; inset: 0; border-radius: 50%; content: ""; box-shadow: 0 0 0 0 rgb(15 143 111 / 42%); animation: mfWaveOnce 1.7s ease-out 1 .6s; pointer-events: none; }
|
||||
.mf-effect-avatar .mf-launcher-icon { width: 26px; height: 20px; border-radius: 12px 12px 10px 10px; background: rgb(255 255 255 / 24%); border: 2px solid ${c.brandText}; position: relative; }
|
||||
.mf-effect-avatar .mf-launcher-icon:before { position: absolute; left: 6px; top: 6px; width: 4px; height: 4px; border-radius: 50%; background: ${c.brandText}; transform: none; box-shadow: 10px 0 0 ${c.brandText}; }
|
||||
.mf-effect-avatar .mf-launcher-icon:after { position: absolute; left: 7px; top: 13px; width: 12px; height: 2px; border-radius: 999px; background: ${c.brandText}; transform: none; opacity: .88; }
|
||||
.mf-offline { filter: grayscale(.2) saturate(.72); opacity: .86; }
|
||||
.mf-launcher.mf-notify { animation: mfPulse 1.15s ease-out infinite; }
|
||||
.mf-panel {
|
||||
position: fixed; z-index: 2147483001; ${desktop.side}: ${desktop.sideOffsetPx}px; bottom: ${desktop.bottomPx + 72}px;
|
||||
@@ -480,6 +503,19 @@
|
||||
70% { box-shadow: 0 12px 30px rgb(0 0 0 / 22%), 0 0 0 14px rgb(15 143 111 / 0%); transform: scale(1.04); }
|
||||
100% { box-shadow: 0 12px 30px rgb(0 0 0 / 22%), 0 0 0 0 rgb(15 143 111 / 0%); transform: scale(1); }
|
||||
}
|
||||
@keyframes mfBreathe {
|
||||
0%, 100% { transform: scale(1); box-shadow: 0 12px 30px rgb(0 0 0 / 22%); }
|
||||
50% { transform: scale(1.035); box-shadow: 0 16px 36px rgb(0 0 0 / 20%), 0 0 0 8px rgb(15 143 111 / 10%); }
|
||||
}
|
||||
@keyframes mfRing {
|
||||
0% { transform: scale(.92); opacity: .58; }
|
||||
70% { transform: scale(1.22); opacity: 0; }
|
||||
100% { transform: scale(.92); opacity: 0; }
|
||||
}
|
||||
@keyframes mfWaveOnce {
|
||||
0% { transform: scale(1); opacity: .7; }
|
||||
100% { transform: scale(1.58); opacity: 0; }
|
||||
}
|
||||
@media (max-width: 640px) {
|
||||
.mf-launcher { ${mobile.side}: ${mobile.sideOffsetPx}px; bottom: ${mobile.bottomPx}px; }
|
||||
.mf-panel { ${mobile.side}: ${mobile.sideOffsetPx}px; bottom: ${mobile.bottomPx + 68}px; width: min(${mobile.widthPx}px, calc(100vw - 24px)); max-height: calc(100vh - 96px); }
|
||||
|
||||
Reference in New Issue
Block a user