Add widget launcher preview
This commit is contained in:
@@ -231,6 +231,190 @@ label { display: grid; gap: 6px; color: var(--muted); font-size: 13px; }
|
|||||||
width: auto;
|
width: auto;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
.launcher-preview-settings {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
.launcher-preview-stage {
|
||||||
|
min-height: 112px;
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
border: 1px solid var(--line);
|
||||||
|
border-radius: 8px;
|
||||||
|
background:
|
||||||
|
linear-gradient(90deg, rgb(15 143 111 / 5%) 1px, transparent 1px),
|
||||||
|
linear-gradient(rgb(15 143 111 / 5%) 1px, transparent 1px),
|
||||||
|
#ffffff;
|
||||||
|
background-size: 18px 18px;
|
||||||
|
}
|
||||||
|
.launcher-preview {
|
||||||
|
--preview-brand: var(--brand);
|
||||||
|
--preview-text: #ffffff;
|
||||||
|
position: relative;
|
||||||
|
width: 58px;
|
||||||
|
height: 58px;
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: var(--preview-brand);
|
||||||
|
color: var(--preview-text);
|
||||||
|
box-shadow: 0 12px 30px rgb(0 0 0 / 22%);
|
||||||
|
cursor: default;
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
.launcher-preview.effect-breathe {
|
||||||
|
animation: launcherPreviewBreathe 2.8s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
.launcher-preview.effect-ring::before {
|
||||||
|
position: absolute;
|
||||||
|
inset: -5px;
|
||||||
|
border: 2px solid var(--preview-brand);
|
||||||
|
border-radius: 50%;
|
||||||
|
opacity: .62;
|
||||||
|
content: "";
|
||||||
|
animation: launcherPreviewRing 2.2s ease-out infinite;
|
||||||
|
}
|
||||||
|
.launcher-preview-label {
|
||||||
|
position: absolute;
|
||||||
|
right: 68px;
|
||||||
|
top: 50%;
|
||||||
|
max-width: 150px;
|
||||||
|
padding: 7px 10px;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: var(--ink);
|
||||||
|
color: #ffffff;
|
||||||
|
font-size: 12px;
|
||||||
|
white-space: nowrap;
|
||||||
|
box-shadow: 0 10px 24px rgb(0 0 0 / 18%);
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(-50%) translateX(8px);
|
||||||
|
transition: opacity .18s ease, transform .18s ease;
|
||||||
|
}
|
||||||
|
.launcher-preview.show-label .launcher-preview-label {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(-50%) translateX(0);
|
||||||
|
}
|
||||||
|
.launcher-preview-icon,
|
||||||
|
.launcher-preview-icon::before,
|
||||||
|
.launcher-preview-icon::after {
|
||||||
|
display: block;
|
||||||
|
content: "";
|
||||||
|
}
|
||||||
|
.launcher-preview-icon {
|
||||||
|
position: relative;
|
||||||
|
margin: 0 auto;
|
||||||
|
color: var(--preview-text);
|
||||||
|
}
|
||||||
|
.preview-shape-circle .launcher-preview-icon,
|
||||||
|
.preview-shape-circle .launcher-preview-icon::before,
|
||||||
|
.preview-shape-circle .launcher-preview-icon::after {
|
||||||
|
height: 3px;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: var(--preview-text);
|
||||||
|
}
|
||||||
|
.preview-shape-circle .launcher-preview-icon {
|
||||||
|
width: 26px;
|
||||||
|
}
|
||||||
|
.preview-shape-circle .launcher-preview-icon::before {
|
||||||
|
transform: translateY(-8px);
|
||||||
|
}
|
||||||
|
.preview-shape-circle .launcher-preview-icon::after {
|
||||||
|
width: 18px;
|
||||||
|
transform: translateY(5px);
|
||||||
|
}
|
||||||
|
.preview-shape-bubble .launcher-preview-icon {
|
||||||
|
width: 30px;
|
||||||
|
height: 23px;
|
||||||
|
border: 3px solid var(--preview-text);
|
||||||
|
border-radius: 13px;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
.preview-shape-bubble .launcher-preview-icon::before {
|
||||||
|
position: absolute;
|
||||||
|
left: 5px;
|
||||||
|
top: 7px;
|
||||||
|
width: 4px;
|
||||||
|
height: 4px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: var(--preview-text);
|
||||||
|
box-shadow: 8px 0 0 var(--preview-text), 16px 0 0 var(--preview-text);
|
||||||
|
}
|
||||||
|
.preview-shape-bubble .launcher-preview-icon::after {
|
||||||
|
position: absolute;
|
||||||
|
right: 2px;
|
||||||
|
bottom: -8px;
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
border-left: 3px solid var(--preview-text);
|
||||||
|
border-bottom: 3px solid var(--preview-text);
|
||||||
|
border-bottom-left-radius: 8px;
|
||||||
|
background: transparent;
|
||||||
|
transform: rotate(-18deg);
|
||||||
|
}
|
||||||
|
.preview-shape-messenger .launcher-preview-icon {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: var(--preview-text);
|
||||||
|
}
|
||||||
|
.preview-shape-messenger .launcher-preview-icon::before {
|
||||||
|
position: absolute;
|
||||||
|
left: 8px;
|
||||||
|
top: 8px;
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
background: var(--preview-brand);
|
||||||
|
clip-path: polygon(0 56%, 42% 56%, 58% 22%, 100% 22%, 58% 78%, 42% 78%);
|
||||||
|
}
|
||||||
|
.preview-shape-messenger .launcher-preview-icon::after {
|
||||||
|
position: absolute;
|
||||||
|
right: 5px;
|
||||||
|
bottom: 1px;
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
border-radius: 0 0 8px 0;
|
||||||
|
background: var(--preview-text);
|
||||||
|
transform: rotate(25deg);
|
||||||
|
}
|
||||||
|
.preview-shape-whatsapp .launcher-preview-icon {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
border: 3px solid var(--preview-text);
|
||||||
|
border-radius: 50%;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
.preview-shape-whatsapp .launcher-preview-icon::before {
|
||||||
|
position: absolute;
|
||||||
|
left: 8px;
|
||||||
|
top: 7px;
|
||||||
|
width: 12px;
|
||||||
|
height: 15px;
|
||||||
|
border: 3px solid var(--preview-text);
|
||||||
|
border-left-color: transparent;
|
||||||
|
border-top-color: transparent;
|
||||||
|
border-radius: 0 0 12px 0;
|
||||||
|
transform: rotate(-35deg);
|
||||||
|
}
|
||||||
|
.preview-shape-whatsapp .launcher-preview-icon::after {
|
||||||
|
position: absolute;
|
||||||
|
left: 1px;
|
||||||
|
bottom: -4px;
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
border-left: 3px solid var(--preview-text);
|
||||||
|
border-bottom: 3px solid var(--preview-text);
|
||||||
|
background: transparent;
|
||||||
|
transform: rotate(12deg);
|
||||||
|
}
|
||||||
|
@keyframes launcherPreviewBreathe {
|
||||||
|
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 launcherPreviewRing {
|
||||||
|
0% { transform: scale(.92); opacity: .58; }
|
||||||
|
70% { transform: scale(1.22); opacity: 0; }
|
||||||
|
100% { transform: scale(.92); opacity: 0; }
|
||||||
|
}
|
||||||
.widget-language-settings {
|
.widget-language-settings {
|
||||||
grid-template-columns: 112px minmax(230px, 1fr);
|
grid-template-columns: 112px minmax(230px, 1fr);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -174,6 +174,15 @@
|
|||||||
<label><input name="launcherRing" type="checkbox"> svetelny prstenec</label>
|
<label><input name="launcherRing" type="checkbox"> svetelny prstenec</label>
|
||||||
<label><input name="launcherHoverLabel" type="checkbox"> napis pri najeti</label>
|
<label><input name="launcherHoverLabel" type="checkbox"> napis pri najeti</label>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
<fieldset class="effect-settings launcher-preview-settings">
|
||||||
|
<legend>Nahled tlacitka</legend>
|
||||||
|
<div class="launcher-preview-stage">
|
||||||
|
<button id="launcherPreview" class="launcher-preview" type="button" aria-label="Nahled tlacitka">
|
||||||
|
<span class="launcher-preview-icon" aria-hidden="true"></span>
|
||||||
|
<span class="launcher-preview-label">Napiste nam</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
<fieldset class="effect-settings">
|
<fieldset class="effect-settings">
|
||||||
<legend>Efekt pri nove zprave</legend>
|
<legend>Efekt pri nove zprave</legend>
|
||||||
<label><input name="messagePulse" type="checkbox"> pulzovani</label>
|
<label><input name="messagePulse" type="checkbox"> pulzovani</label>
|
||||||
|
|||||||
@@ -130,14 +130,27 @@ document.querySelectorAll("[data-settings-tab]").forEach((button) => {
|
|||||||
});
|
});
|
||||||
$("#settingsForm").brand.addEventListener("input", (event) => {
|
$("#settingsForm").brand.addEventListener("input", (event) => {
|
||||||
$("#settingsForm").brandHex.value = normalizeHexColor(event.target.value) || event.target.value;
|
$("#settingsForm").brandHex.value = normalizeHexColor(event.target.value) || event.target.value;
|
||||||
|
renderLauncherPreview();
|
||||||
});
|
});
|
||||||
$("#settingsForm").brandHex.addEventListener("input", (event) => {
|
$("#settingsForm").brandHex.addEventListener("input", (event) => {
|
||||||
const color = normalizeHexColor(event.target.value);
|
const color = normalizeHexColor(event.target.value);
|
||||||
if (color) $("#settingsForm").brand.value = color;
|
if (color) $("#settingsForm").brand.value = color;
|
||||||
|
renderLauncherPreview();
|
||||||
});
|
});
|
||||||
$("#settingsForm").defaultLanguage.addEventListener("change", () => {
|
$("#settingsForm").defaultLanguage.addEventListener("change", () => {
|
||||||
updateDefaultLanguagePicker();
|
updateDefaultLanguagePicker();
|
||||||
renderWidgetCopyFields($("#settingsForm").defaultLanguage.value);
|
renderWidgetCopyFields($("#settingsForm").defaultLanguage.value);
|
||||||
|
renderLauncherPreview();
|
||||||
|
});
|
||||||
|
$("#settingsForm").addEventListener("input", (event) => {
|
||||||
|
if (event.target.matches("[name='launcherShape'], [name='launcherBreathe'], [name='launcherRing'], [name='launcherHoverLabel'], [name='copyOnlineLabel']")) {
|
||||||
|
renderLauncherPreview();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
$("#settingsForm").addEventListener("change", (event) => {
|
||||||
|
if (event.target.matches("[name='launcherShape'], [name='launcherBreathe'], [name='launcherRing'], [name='launcherHoverLabel']")) {
|
||||||
|
renderLauncherPreview();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
$("#defaultLanguagePicker").addEventListener("click", (event) => {
|
$("#defaultLanguagePicker").addEventListener("click", (event) => {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
@@ -536,6 +549,7 @@ function renderSite() {
|
|||||||
renderModelOptions(s.translations?.model || "gpt-5-mini");
|
renderModelOptions(s.translations?.model || "gpt-5-mini");
|
||||||
renderPresenceSettings(s.adminPresence || {});
|
renderPresenceSettings(s.adminPresence || {});
|
||||||
renderTelegramSettings(s.telegram || {});
|
renderTelegramSettings(s.telegram || {});
|
||||||
|
renderLauncherPreview();
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderWidgetLanguageOptions(form, settings) {
|
function renderWidgetLanguageOptions(form, settings) {
|
||||||
@@ -625,6 +639,26 @@ function renderWidgetCopyFields(language) {
|
|||||||
form.copyInfoText.value = copy.infoText || "";
|
form.copyInfoText.value = copy.infoText || "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renderLauncherPreview() {
|
||||||
|
const preview = $("#launcherPreview");
|
||||||
|
const form = $("#settingsForm");
|
||||||
|
if (!preview || !form) return;
|
||||||
|
const shape = ["circle", "bubble", "messenger", "whatsapp"].includes(form.launcherShape.value)
|
||||||
|
? form.launcherShape.value
|
||||||
|
: "bubble";
|
||||||
|
const brand = normalizeHexColor(form.brandHex.value) || normalizeHexColor(form.brand.value) || "#0f8f6f";
|
||||||
|
preview.style.setProperty("--preview-brand", brand);
|
||||||
|
preview.className = [
|
||||||
|
"launcher-preview",
|
||||||
|
`preview-shape-${shape}`,
|
||||||
|
form.launcherBreathe.checked ? "effect-breathe" : "",
|
||||||
|
form.launcherRing.checked ? "effect-ring" : "",
|
||||||
|
form.launcherHoverLabel.checked ? "show-label" : ""
|
||||||
|
].filter(Boolean).join(" ");
|
||||||
|
const label = preview.querySelector(".launcher-preview-label");
|
||||||
|
if (label) label.textContent = form.copyOnlineLabel.value || "Napiste nam";
|
||||||
|
}
|
||||||
|
|
||||||
function widgetCopyForAdmin(settings, language) {
|
function widgetCopyForAdmin(settings, language) {
|
||||||
const lang = language || "cs";
|
const lang = language || "cs";
|
||||||
const copy = settings.widgetCopy?.[lang] || {};
|
const copy = settings.widgetCopy?.[lang] || {};
|
||||||
|
|||||||
Reference in New Issue
Block a user