mirror of
https://github.com/dpnmw/community-landing.git
synced 2026-03-18 09:27:16 +00:00
UI Reworked v2
Changes to the frontend and backed ui and settings otpions.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
// Community Landing v2 — JS
|
||||
// Theme detection, scroll animations, stat counters, horizontal scroll
|
||||
// Community Landing v2.1 — JS
|
||||
// Theme, scroll animations, stat counters, smooth horizontal drag
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
(function () {
|
||||
"use strict";
|
||||
@@ -51,7 +51,7 @@
|
||||
img.src = pick;
|
||||
img.onload = function () { img.style.opacity = ""; img.classList.add("loaded"); };
|
||||
img.onerror = function () { img.src = images[0]; img.style.opacity = ""; img.classList.add("loaded"); };
|
||||
} catch (e) { /* invalid JSON, keep default first image */ }
|
||||
} catch (e) { /* invalid JSON */ }
|
||||
})();
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
@@ -59,6 +59,12 @@
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
var navbar = $("#cl-navbar");
|
||||
if (navbar) {
|
||||
// Apply custom navbar bg/border from data attributes
|
||||
var navBg = navbar.getAttribute("data-nav-bg");
|
||||
var navBorder = navbar.getAttribute("data-nav-border");
|
||||
if (navBg) navbar.style.setProperty("--cl-nav-bg", navBg);
|
||||
if (navBorder) navbar.style.setProperty("--cl-nav-border", "1px " + navBorder + " var(--cl-border)");
|
||||
|
||||
var onScroll = function () {
|
||||
navbar.classList.toggle("scrolled", window.scrollY > 50);
|
||||
};
|
||||
@@ -82,23 +88,31 @@
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
// 4. SCROLL REVEAL ANIMATIONS
|
||||
// 4. SCROLL REVEAL ANIMATIONS (supports configurable anim types)
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
if ("IntersectionObserver" in window) {
|
||||
var animType = document.documentElement.getAttribute("data-scroll-anim") || "fade_up";
|
||||
|
||||
if (animType !== "none" && "IntersectionObserver" in window) {
|
||||
var revealObserver = new IntersectionObserver(
|
||||
function (entries) {
|
||||
entries.forEach(function (entry) {
|
||||
if (entry.isIntersecting) {
|
||||
entry.target.classList.add("visible");
|
||||
revealObserver.unobserve(entry.target);
|
||||
}
|
||||
});
|
||||
},
|
||||
{ threshold: 0.1, rootMargin: "0px 0px -40px 0px" }
|
||||
{ threshold: 0.08, rootMargin: "0px 0px -30px 0px" }
|
||||
);
|
||||
|
||||
$$(".cl-reveal").forEach(function (el) {
|
||||
$$(".cl-anim").forEach(function (el) {
|
||||
revealObserver.observe(el);
|
||||
});
|
||||
} else {
|
||||
// No animation — make everything visible immediately
|
||||
$$(".cl-anim").forEach(function (el) {
|
||||
el.classList.add("visible");
|
||||
});
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
@@ -139,32 +153,86 @@
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
// 6. HORIZONTAL SCROLL — drag support for trending discussions
|
||||
// 6. SMOOTH HORIZONTAL DRAG — trending discussions
|
||||
// Prevents link clicks during drag, smooth momentum scrolling
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
$$(".cl-topics__scroll").forEach(function (scroll) {
|
||||
var isDown = false, startX, scrollLeft;
|
||||
$$(".cl-topics__scroll").forEach(function (scrollEl) {
|
||||
var isDown = false;
|
||||
var startX = 0;
|
||||
var scrollStart = 0;
|
||||
var moved = false;
|
||||
var velX = 0;
|
||||
var lastX = 0;
|
||||
var lastTime = 0;
|
||||
var momentumId = null;
|
||||
|
||||
scroll.addEventListener("mousedown", function (e) {
|
||||
function stopMomentum() {
|
||||
if (momentumId) {
|
||||
cancelAnimationFrame(momentumId);
|
||||
momentumId = null;
|
||||
}
|
||||
}
|
||||
|
||||
function doMomentum() {
|
||||
if (Math.abs(velX) < 0.5) return;
|
||||
scrollEl.scrollLeft -= velX;
|
||||
velX *= 0.92;
|
||||
momentumId = requestAnimationFrame(doMomentum);
|
||||
}
|
||||
|
||||
scrollEl.addEventListener("mousedown", function (ev) {
|
||||
stopMomentum();
|
||||
isDown = true;
|
||||
scroll.style.cursor = "grabbing";
|
||||
startX = e.pageX - scroll.offsetLeft;
|
||||
scrollLeft = scroll.scrollLeft;
|
||||
moved = false;
|
||||
startX = ev.pageX;
|
||||
scrollStart = scrollEl.scrollLeft;
|
||||
lastX = ev.pageX;
|
||||
lastTime = Date.now();
|
||||
velX = 0;
|
||||
scrollEl.style.scrollSnapType = "none";
|
||||
scrollEl.style.userSelect = "none";
|
||||
});
|
||||
scroll.addEventListener("mouseleave", function () {
|
||||
isDown = false;
|
||||
scroll.style.cursor = "";
|
||||
});
|
||||
scroll.addEventListener("mouseup", function () {
|
||||
isDown = false;
|
||||
scroll.style.cursor = "";
|
||||
});
|
||||
scroll.addEventListener("mousemove", function (e) {
|
||||
|
||||
window.addEventListener("mousemove", function (ev) {
|
||||
if (!isDown) return;
|
||||
e.preventDefault();
|
||||
var x = e.pageX - scroll.offsetLeft;
|
||||
var walk = (x - startX) * 1.5;
|
||||
scroll.scrollLeft = scrollLeft - walk;
|
||||
var dx = ev.pageX - startX;
|
||||
if (Math.abs(dx) > 3) moved = true;
|
||||
var now = Date.now();
|
||||
var dt = now - lastTime;
|
||||
if (dt > 0) {
|
||||
velX = (ev.pageX - lastX) / dt * 16;
|
||||
}
|
||||
lastX = ev.pageX;
|
||||
lastTime = now;
|
||||
scrollEl.scrollLeft = scrollStart - dx;
|
||||
});
|
||||
|
||||
function endDrag() {
|
||||
if (!isDown) return;
|
||||
isDown = false;
|
||||
scrollEl.style.userSelect = "";
|
||||
if (Math.abs(velX) > 1) {
|
||||
doMomentum();
|
||||
}
|
||||
// Re-enable snap after a tick
|
||||
setTimeout(function () {
|
||||
scrollEl.style.scrollSnapType = "";
|
||||
}, 100);
|
||||
}
|
||||
|
||||
window.addEventListener("mouseup", endDrag);
|
||||
scrollEl.addEventListener("mouseleave", endDrag);
|
||||
|
||||
// Prevent link navigation if we dragged
|
||||
scrollEl.addEventListener("click", function (ev) {
|
||||
if (moved) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
moved = false;
|
||||
}
|
||||
}, true);
|
||||
|
||||
// Touch support — native scrolling works, no extra handling needed
|
||||
});
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
|
||||
74
assets/stylesheets/community_landing/admin.css
Normal file
74
assets/stylesheets/community_landing/admin.css
Normal file
@@ -0,0 +1,74 @@
|
||||
/* ═══════════════════════════════════════════════════════════════════
|
||||
Community Landing — Admin Settings Panel Styles
|
||||
Adds visual separators and spacing between setting groups
|
||||
═══════════════════════════════════════════════════════════════════ */
|
||||
|
||||
/* All community_landing settings get extra bottom spacing */
|
||||
.admin-detail .row.setting[data-setting^="community_landing_"] {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
/* ── Section separator borders ──
|
||||
These selectors target the FIRST setting of each group to add
|
||||
a visible border-top separator with extra padding above it. */
|
||||
|
||||
/* Branding section */
|
||||
.admin-detail .row.setting[data-setting="community_landing_logo_dark_url"],
|
||||
/* Global Colors section */
|
||||
.admin-detail .row.setting[data-setting="community_landing_accent_color"],
|
||||
/* Custom CSS section */
|
||||
.admin-detail .row.setting[data-setting="community_landing_custom_css"],
|
||||
/* Scroll Animations section */
|
||||
.admin-detail .row.setting[data-setting="community_landing_scroll_animation"],
|
||||
/* Row 1: Navbar */
|
||||
.admin-detail .row.setting[data-setting="community_landing_navbar_signin_label"],
|
||||
/* Row 2: Hero Section */
|
||||
.admin-detail .row.setting[data-setting="community_landing_hero_title"],
|
||||
/* Row 3: Premium Stats */
|
||||
.admin-detail .row.setting[data-setting="community_landing_stats_title"],
|
||||
/* Row 4: About Community */
|
||||
.admin-detail .row.setting[data-setting="community_landing_about_enabled"],
|
||||
/* Row 5: Trending Discussions */
|
||||
.admin-detail .row.setting[data-setting="community_landing_topics_enabled"],
|
||||
/* Row 6: Top Creators */
|
||||
.admin-detail .row.setting[data-setting="community_landing_contributors_enabled"],
|
||||
/* Row 7: Community Spaces */
|
||||
.admin-detail .row.setting[data-setting="community_landing_groups_enabled"],
|
||||
/* Row 8: App Download CTA */
|
||||
.admin-detail .row.setting[data-setting="community_landing_show_app_ctas"],
|
||||
/* Row 9: Footer */
|
||||
.admin-detail .row.setting[data-setting="community_landing_footer_description"] {
|
||||
border-top: 2px solid rgba(0, 0, 0, 0.12);
|
||||
margin-top: 28px;
|
||||
padding-top: 24px;
|
||||
}
|
||||
|
||||
/* Dark mode admin panel support */
|
||||
.admin-detail.dark .row.setting[data-setting="community_landing_logo_dark_url"],
|
||||
.admin-detail.dark .row.setting[data-setting="community_landing_accent_color"],
|
||||
.admin-detail.dark .row.setting[data-setting="community_landing_custom_css"],
|
||||
.admin-detail.dark .row.setting[data-setting="community_landing_scroll_animation"],
|
||||
.admin-detail.dark .row.setting[data-setting="community_landing_navbar_signin_label"],
|
||||
.admin-detail.dark .row.setting[data-setting="community_landing_hero_title"],
|
||||
.admin-detail.dark .row.setting[data-setting="community_landing_stats_title"],
|
||||
.admin-detail.dark .row.setting[data-setting="community_landing_about_enabled"],
|
||||
.admin-detail.dark .row.setting[data-setting="community_landing_topics_enabled"],
|
||||
.admin-detail.dark .row.setting[data-setting="community_landing_contributors_enabled"],
|
||||
.admin-detail.dark .row.setting[data-setting="community_landing_groups_enabled"],
|
||||
.admin-detail.dark .row.setting[data-setting="community_landing_show_app_ctas"],
|
||||
.admin-detail.dark .row.setting[data-setting="community_landing_footer_description"],
|
||||
html.dark-scheme .admin-detail .row.setting[data-setting="community_landing_logo_dark_url"],
|
||||
html.dark-scheme .admin-detail .row.setting[data-setting="community_landing_accent_color"],
|
||||
html.dark-scheme .admin-detail .row.setting[data-setting="community_landing_custom_css"],
|
||||
html.dark-scheme .admin-detail .row.setting[data-setting="community_landing_scroll_animation"],
|
||||
html.dark-scheme .admin-detail .row.setting[data-setting="community_landing_navbar_signin_label"],
|
||||
html.dark-scheme .admin-detail .row.setting[data-setting="community_landing_hero_title"],
|
||||
html.dark-scheme .admin-detail .row.setting[data-setting="community_landing_stats_title"],
|
||||
html.dark-scheme .admin-detail .row.setting[data-setting="community_landing_about_enabled"],
|
||||
html.dark-scheme .admin-detail .row.setting[data-setting="community_landing_topics_enabled"],
|
||||
html.dark-scheme .admin-detail .row.setting[data-setting="community_landing_contributors_enabled"],
|
||||
html.dark-scheme .admin-detail .row.setting[data-setting="community_landing_groups_enabled"],
|
||||
html.dark-scheme .admin-detail .row.setting[data-setting="community_landing_show_app_ctas"],
|
||||
html.dark-scheme .admin-detail .row.setting[data-setting="community_landing_footer_description"] {
|
||||
border-top-color: rgba(255, 255, 255, 0.12);
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/* ═══════════════════════════════════════════════════════════════════
|
||||
Community Landing v2 — Warm, modern full-width row design
|
||||
Community Landing v2.1 — Premium warm design
|
||||
═══════════════════════════════════════════════════════════════════ */
|
||||
|
||||
:root, [data-theme="dark"] {
|
||||
@@ -22,16 +22,14 @@
|
||||
--cl-glass: rgba(15, 15, 35, 0.5);
|
||||
--cl-glass-border: rgba(255, 255, 255, 0.06);
|
||||
--cl-orb-1: rgba(212, 162, 78, 0.12);
|
||||
--cl-orb-2: rgba(99, 215, 255, 0.06);
|
||||
--cl-gradient-text: linear-gradient(135deg, #e8c47a, #d4a24e, #e8c47a);
|
||||
--cl-section-alt: rgba(255, 255, 255, 0.015);
|
||||
--cl-scrolled-nav: rgba(6, 6, 15, 0.95);
|
||||
--cl-radius: 16px;
|
||||
--cl-radius-sm: 10px;
|
||||
--cl-radius-xs: 6px;
|
||||
--cl-stat-icon-color: #d4a24e;
|
||||
--cl-about-gradient: linear-gradient(135deg, #1a1820, #1c1a22);
|
||||
--cl-app-gradient: linear-gradient(135deg, #d4a24e, #c4922e);
|
||||
--cl-about-gradient: linear-gradient(135deg, #1a1820, #1c1a22, #1a1820);
|
||||
--cl-app-gradient: linear-gradient(135deg, #d4a24e, #c4922e, #b8862e);
|
||||
color-scheme: dark;
|
||||
}
|
||||
|
||||
@@ -55,12 +53,10 @@
|
||||
--cl-glass: rgba(255, 255, 255, 0.6);
|
||||
--cl-glass-border: rgba(0, 0, 0, 0.05);
|
||||
--cl-orb-1: rgba(212, 162, 78, 0.08);
|
||||
--cl-orb-2: rgba(56, 189, 248, 0.04);
|
||||
--cl-gradient-text: linear-gradient(135deg, #d4a24e, #b8862e, #d4a24e);
|
||||
--cl-section-alt: rgba(0, 0, 0, 0.015);
|
||||
--cl-scrolled-nav: rgba(250, 246, 240, 0.95);
|
||||
--cl-about-gradient: linear-gradient(135deg, #fdf6ec, #fef9f0);
|
||||
--cl-app-gradient: linear-gradient(135deg, #d4a24e, #b8862e);
|
||||
--cl-about-gradient: linear-gradient(135deg, #fdf6ec, #fef9f0, #fdf6ec);
|
||||
--cl-app-gradient: linear-gradient(135deg, #d4a24e, #c4922e, #b8862e);
|
||||
color-scheme: light;
|
||||
}
|
||||
|
||||
@@ -85,12 +81,10 @@
|
||||
--cl-glass: rgba(255, 255, 255, 0.6);
|
||||
--cl-glass-border: rgba(0, 0, 0, 0.05);
|
||||
--cl-orb-1: rgba(212, 162, 78, 0.08);
|
||||
--cl-orb-2: rgba(56, 189, 248, 0.04);
|
||||
--cl-gradient-text: linear-gradient(135deg, #d4a24e, #b8862e, #d4a24e);
|
||||
--cl-section-alt: rgba(0, 0, 0, 0.015);
|
||||
--cl-scrolled-nav: rgba(250, 246, 240, 0.95);
|
||||
--cl-about-gradient: linear-gradient(135deg, #fdf6ec, #fef9f0);
|
||||
--cl-app-gradient: linear-gradient(135deg, #d4a24e, #b8862e);
|
||||
--cl-about-gradient: linear-gradient(135deg, #fdf6ec, #fef9f0, #fdf6ec);
|
||||
--cl-app-gradient: linear-gradient(135deg, #d4a24e, #c4922e, #b8862e);
|
||||
color-scheme: light;
|
||||
}
|
||||
}
|
||||
@@ -116,27 +110,58 @@
|
||||
margin: 0 0 1.25rem; letter-spacing: -0.01em;
|
||||
}
|
||||
|
||||
/* ── Scroll Reveal ── */
|
||||
.cl-reveal { opacity: 0; transform: translateY(24px); transition: opacity 0.6s cubic-bezier(0.16,1,0.3,1), transform 0.6s cubic-bezier(0.16,1,0.3,1); }
|
||||
.cl-reveal.visible { opacity: 1; transform: translateY(0); }
|
||||
/* ═══════════════════════════════════════════════════════════════════
|
||||
SCROLL ANIMATIONS — configurable via data-scroll-anim
|
||||
═══════════════════════════════════════════════════════════════════ */
|
||||
.cl-anim {
|
||||
opacity: 0;
|
||||
transition: opacity 0.7s cubic-bezier(0.16,1,0.3,1), transform 0.7s cubic-bezier(0.16,1,0.3,1);
|
||||
}
|
||||
|
||||
/* fade_up (default) */
|
||||
[data-scroll-anim="fade_up"] .cl-anim { transform: translateY(32px); }
|
||||
[data-scroll-anim="fade_up"] .cl-anim.visible { opacity: 1; transform: translateY(0); }
|
||||
|
||||
/* fade_in */
|
||||
[data-scroll-anim="fade_in"] .cl-anim { transform: none; }
|
||||
[data-scroll-anim="fade_in"] .cl-anim.visible { opacity: 1; }
|
||||
|
||||
/* slide_left */
|
||||
[data-scroll-anim="slide_left"] .cl-anim { transform: translateX(-48px); }
|
||||
[data-scroll-anim="slide_left"] .cl-anim.visible { opacity: 1; transform: translateX(0); }
|
||||
|
||||
/* slide_right */
|
||||
[data-scroll-anim="slide_right"] .cl-anim { transform: translateX(48px); }
|
||||
[data-scroll-anim="slide_right"] .cl-anim.visible { opacity: 1; transform: translateX(0); }
|
||||
|
||||
/* zoom_in */
|
||||
[data-scroll-anim="zoom_in"] .cl-anim { transform: scale(0.88); }
|
||||
[data-scroll-anim="zoom_in"] .cl-anim.visible { opacity: 1; transform: scale(1); }
|
||||
|
||||
/* flip_up */
|
||||
[data-scroll-anim="flip_up"] .cl-anim { transform: perspective(600px) rotateX(12deg) translateY(24px); }
|
||||
[data-scroll-anim="flip_up"] .cl-anim.visible { opacity: 1; transform: perspective(600px) rotateX(0) translateY(0); }
|
||||
|
||||
/* none */
|
||||
[data-scroll-anim="none"] .cl-anim { opacity: 1; transform: none; transition: none; }
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════
|
||||
BUTTONS
|
||||
═══════════════════════════════════════════════════════════════════ */
|
||||
.cl-btn {
|
||||
display: inline-flex; align-items: center; justify-content: center;
|
||||
padding: 0.65rem 1.5rem; border: none; border-radius: var(--cl-radius-sm);
|
||||
padding: 0.65rem 1.5rem; border: none; border-radius: 50px;
|
||||
font-size: 0.88rem; font-weight: 600; cursor: pointer;
|
||||
transition: all 0.2s ease; text-decoration: none; white-space: nowrap;
|
||||
}
|
||||
.cl-btn--primary { background: var(--cl-accent); color: #fff; border-radius: 50px; }
|
||||
.cl-btn--primary { background: var(--cl-accent); color: #fff; }
|
||||
.cl-btn--primary:hover { background: var(--cl-accent-hover); transform: translateY(-1px); box-shadow: 0 4px 20px var(--cl-accent-glow); }
|
||||
.cl-btn--ghost { background: transparent; color: var(--cl-text-strong); border: 1px solid var(--cl-border); border-radius: 50px; }
|
||||
.cl-btn--ghost { background: transparent; color: var(--cl-text-strong); border: 1px solid var(--cl-border); }
|
||||
.cl-btn--ghost:hover { background: var(--cl-accent-subtle); border-color: var(--cl-border-hover); }
|
||||
.cl-btn--lg { padding: 0.8rem 2rem; font-size: 0.95rem; }
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════
|
||||
NAVBAR — minimal, theme toggle left, auth buttons right
|
||||
1. NAVBAR — logo left, theme toggle + auth right
|
||||
═══════════════════════════════════════════════════════════════════ */
|
||||
.cl-navbar {
|
||||
position: fixed; top: 0; left: 0; right: 0; z-index: 1000;
|
||||
@@ -144,9 +169,10 @@
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
.cl-navbar.scrolled {
|
||||
background: var(--cl-scrolled-nav);
|
||||
background: var(--cl-nav-bg, var(--cl-scrolled-nav));
|
||||
backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px);
|
||||
box-shadow: 0 1px 0 var(--cl-border);
|
||||
border-bottom: var(--cl-nav-border, none);
|
||||
padding: 0.55rem 0;
|
||||
}
|
||||
.cl-navbar__inner {
|
||||
@@ -156,6 +182,10 @@
|
||||
@media (min-width: 768px) { .cl-navbar__inner { padding: 0 2rem; } }
|
||||
|
||||
.cl-navbar__left { display: flex; align-items: center; gap: 0.6rem; }
|
||||
.cl-navbar__brand { display: flex; align-items: center; gap: 0.6rem; text-decoration: none; color: var(--cl-text-strong); }
|
||||
.cl-navbar__logo { width: auto; object-fit: contain; }
|
||||
.cl-navbar__site-name { font-size: 1.05rem; font-weight: 700; letter-spacing: -0.02em; }
|
||||
|
||||
.cl-navbar__right { display: none; align-items: center; gap: 0.5rem; }
|
||||
@media (min-width: 768px) { .cl-navbar__right { display: flex; } }
|
||||
|
||||
@@ -216,30 +246,50 @@
|
||||
}
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════
|
||||
HERO — warm, rounded container style
|
||||
2. HERO
|
||||
═══════════════════════════════════════════════════════════════════ */
|
||||
.cl-hero {
|
||||
padding: 6rem 1.25rem 2.5rem;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
padding: 5.5rem 1.25rem 2.5rem;
|
||||
position: relative;
|
||||
}
|
||||
@media (min-width: 768px) { .cl-hero { padding: 6rem 2rem 3rem; } }
|
||||
|
||||
.cl-hero__inner {
|
||||
max-width: 1200px; width: 100%; margin: 0 auto;
|
||||
/* Full-width background image (non-card mode) */
|
||||
.cl-hero__bg {
|
||||
position: absolute; inset: 0; z-index: 0;
|
||||
background-size: cover; background-position: center;
|
||||
}
|
||||
.cl-hero__bg::after {
|
||||
content: ""; position: absolute; inset: 0;
|
||||
background: linear-gradient(to bottom, rgba(0,0,0,0.5), rgba(0,0,0,0.7));
|
||||
}
|
||||
|
||||
/* Card mode */
|
||||
.cl-hero--card .cl-hero__inner {
|
||||
background: var(--cl-card);
|
||||
border: 1px solid var(--cl-border);
|
||||
border-radius: 24px;
|
||||
box-shadow: 0 4px 40px var(--cl-shadow);
|
||||
background-size: cover; background-position: center;
|
||||
}
|
||||
|
||||
/* Non-card mode */
|
||||
.cl-hero:not(.cl-hero--card) .cl-hero__inner {
|
||||
background: transparent;
|
||||
}
|
||||
.cl-hero:not(.cl-hero--card) .cl-hero__title,
|
||||
.cl-hero:not(.cl-hero--card) .cl-hero__subtitle {
|
||||
position: relative; z-index: 1;
|
||||
}
|
||||
|
||||
.cl-hero__inner {
|
||||
max-width: 1200px; width: 100%; margin: 0 auto;
|
||||
padding: 2.5rem 2rem;
|
||||
display: flex; flex-direction: column; gap: 2rem;
|
||||
position: relative; overflow: hidden;
|
||||
box-shadow: 0 4px 40px var(--cl-shadow);
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
.cl-hero__inner { padding: 3rem 3rem; }
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
.cl-hero__inner { flex-direction: row; align-items: center; gap: 3rem; padding: 3.5rem 3.5rem; }
|
||||
position: relative; z-index: 1; overflow: hidden;
|
||||
}
|
||||
@media (min-width: 768px) { .cl-hero__inner { padding: 3rem; } }
|
||||
@media (min-width: 1024px) { .cl-hero__inner { flex-direction: row; align-items: center; gap: 3rem; padding: 3.5rem; } }
|
||||
|
||||
.cl-hero__content { flex-shrink: 0; animation: cl-fade-up 0.8s cubic-bezier(0.16,1,0.3,1) both; }
|
||||
@media (min-width: 1024px) { .cl-hero__content { flex: 0 0 42%; } }
|
||||
@@ -266,6 +316,7 @@
|
||||
font-weight: 800; color: var(--cl-hero-text);
|
||||
margin: 0 0 0.75rem; line-height: 1.1; letter-spacing: -0.03em;
|
||||
}
|
||||
.cl-hero--card .cl-hero__title { color: var(--cl-text-strong); }
|
||||
.cl-hero__title-accent {
|
||||
background: var(--cl-gradient-text);
|
||||
-webkit-background-clip: text; background-clip: text;
|
||||
@@ -278,7 +329,7 @@
|
||||
.cl-hero__actions { display: flex; flex-wrap: wrap; gap: 0.6rem; }
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════
|
||||
PREMIUM STATS — full-width row with heading
|
||||
3. PREMIUM STATS — icon + label on one line, counter below
|
||||
═══════════════════════════════════════════════════════════════════ */
|
||||
.cl-stats { padding: 2.5rem 0 2rem; }
|
||||
|
||||
@@ -289,7 +340,7 @@
|
||||
@media (min-width: 1024px) { .cl-stats__grid { grid-template-columns: repeat(5, 1fr); } }
|
||||
|
||||
.cl-stat-card {
|
||||
display: flex; flex-direction: column; align-items: center; gap: 0.3rem;
|
||||
display: flex; flex-direction: column; align-items: center; gap: 0.5rem;
|
||||
padding: 1.5rem 1rem;
|
||||
background: var(--cl-card); border: 1px solid var(--cl-border);
|
||||
border-radius: var(--cl-radius); text-align: center;
|
||||
@@ -297,22 +348,26 @@
|
||||
}
|
||||
.cl-stat-card:hover { border-color: var(--cl-border-hover); transform: translateY(-3px); box-shadow: 0 8px 24px rgba(0,0,0,0.08); }
|
||||
|
||||
.cl-stat-card__icon { color: var(--cl-stat-icon-color); margin-bottom: 0.25rem; }
|
||||
.cl-stat-card__icon svg { width: 26px; height: 26px; }
|
||||
|
||||
.cl-stat-card__label {
|
||||
font-size: 0.72rem; color: var(--cl-muted);
|
||||
text-transform: uppercase; letter-spacing: 0.08em; font-weight: 600;
|
||||
order: 1;
|
||||
/* Icon + Label on same line */
|
||||
.cl-stat-card__top {
|
||||
display: flex; align-items: center; gap: 0.4rem;
|
||||
}
|
||||
.cl-stat-card__icon { color: var(--cl-stat-icon-color); display: flex; align-items: center; }
|
||||
.cl-stat-card__icon svg { width: 22px; height: 22px; }
|
||||
.cl-stat-card__label {
|
||||
font-size: 0.78rem; color: var(--cl-muted);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* Counter below */
|
||||
.cl-stat-card__value {
|
||||
font-size: 1.75rem; font-weight: 800;
|
||||
color: var(--cl-text-strong); letter-spacing: -0.02em;
|
||||
order: 2;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════
|
||||
ABOUT COMMUNITY — full-width gradient card
|
||||
4. ABOUT COMMUNITY — full-width gradient card
|
||||
═══════════════════════════════════════════════════════════════════ */
|
||||
.cl-about { padding: 1rem 0 2rem; }
|
||||
|
||||
@@ -323,6 +378,7 @@
|
||||
padding: 2rem 2.5rem;
|
||||
position: relative;
|
||||
box-shadow: 0 2px 16px rgba(0,0,0,0.04);
|
||||
background-size: cover; background-position: center;
|
||||
}
|
||||
|
||||
.cl-about__heading {
|
||||
@@ -355,7 +411,7 @@
|
||||
.cl-about__role { font-size: 0.78rem; color: var(--cl-muted); }
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════
|
||||
TRENDING DISCUSSIONS — horizontal scrollable cards
|
||||
5. TRENDING DISCUSSIONS — horizontal scrollable cards
|
||||
═══════════════════════════════════════════════════════════════════ */
|
||||
.cl-topics { padding: 1.5rem 0 2rem; }
|
||||
|
||||
@@ -364,52 +420,55 @@
|
||||
overflow-x: auto; overflow-y: hidden;
|
||||
scroll-snap-type: x mandatory;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
padding-bottom: 0.5rem;
|
||||
padding-bottom: 0.75rem;
|
||||
scrollbar-width: none;
|
||||
cursor: grab;
|
||||
}
|
||||
.cl-topics__scroll::-webkit-scrollbar { display: none; }
|
||||
.cl-topics__scroll:active { cursor: grabbing; }
|
||||
|
||||
.cl-topic-card {
|
||||
flex: 0 0 220px;
|
||||
flex: 0 0 230px;
|
||||
scroll-snap-align: start;
|
||||
display: flex; flex-direction: column; gap: 0.5rem;
|
||||
padding: 1rem 1.15rem;
|
||||
display: flex; flex-direction: column;
|
||||
padding: 1.15rem 1.25rem;
|
||||
background: var(--cl-card);
|
||||
border: 1px solid var(--cl-border);
|
||||
border-radius: var(--cl-radius);
|
||||
text-decoration: none; color: var(--cl-text);
|
||||
transition: all 0.2s ease;
|
||||
min-height: 130px;
|
||||
min-height: 145px;
|
||||
}
|
||||
@media (min-width: 640px) { .cl-topic-card { flex: 0 0 240px; } }
|
||||
@media (min-width: 640px) { .cl-topic-card { flex: 0 0 250px; } }
|
||||
.cl-topic-card:hover { border-color: var(--cl-border-hover); transform: translateY(-2px); box-shadow: 0 6px 20px rgba(0,0,0,0.08); }
|
||||
|
||||
.cl-topic-card__cat {
|
||||
display: inline-block; padding: 0.15rem 0.6rem; border-radius: 4px;
|
||||
font-size: 0.6rem; font-weight: 700; color: #fff;
|
||||
display: inline-block; padding: 0.2rem 0.65rem; border-radius: 5px;
|
||||
font-size: 0.62rem; font-weight: 700; color: #fff;
|
||||
background: var(--cat-color); text-transform: uppercase; letter-spacing: 0.04em;
|
||||
white-space: nowrap; align-self: flex-start;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.cl-topic-card__title {
|
||||
font-weight: 600; color: var(--cl-text-strong);
|
||||
font-size: 0.85rem; line-height: 1.4;
|
||||
font-size: 0.88rem; line-height: 1.45;
|
||||
display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
|
||||
overflow: hidden; flex: 1;
|
||||
}
|
||||
|
||||
.cl-topic-card__meta {
|
||||
display: flex; align-items: center; gap: 0.75rem;
|
||||
margin-top: auto; padding-top: 0.5rem;
|
||||
display: flex; align-items: center; gap: 1rem;
|
||||
margin-top: auto; padding-top: 0.65rem;
|
||||
}
|
||||
.cl-topic-card__stat {
|
||||
display: flex; align-items: center; gap: 0.2rem;
|
||||
color: var(--cl-muted); font-size: 0.75rem;
|
||||
display: inline-flex; align-items: center; gap: 0.25rem;
|
||||
color: var(--cl-muted); font-size: 0.78rem;
|
||||
}
|
||||
.cl-topic-card__stat svg { opacity: 0.6; }
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════
|
||||
TOP CREATORS — pill badges with avatar, @username, cheers
|
||||
6. TOP CREATORS — pill badges
|
||||
═══════════════════════════════════════════════════════════════════ */
|
||||
.cl-creators { padding: 1.5rem 0 2rem; }
|
||||
|
||||
@@ -427,31 +486,33 @@
|
||||
.cl-creator-pill:hover { border-color: var(--cl-border-hover); background: var(--cl-accent-subtle); }
|
||||
|
||||
.cl-creator-pill__avatar {
|
||||
width: 30px; height: 30px; border-radius: 50%; object-fit: cover;
|
||||
width: 32px; height: 32px; border-radius: 50%; object-fit: cover;
|
||||
border: 2px solid var(--cl-border);
|
||||
}
|
||||
.cl-creator-pill__name {
|
||||
font-size: 0.8rem; font-weight: 600; color: var(--cl-text-strong);
|
||||
font-size: 0.82rem; font-weight: 600; color: var(--cl-text-strong);
|
||||
white-space: nowrap;
|
||||
}
|
||||
.cl-creator-pill__cheers {
|
||||
font-size: 0.7rem; color: var(--cl-muted); white-space: nowrap;
|
||||
.cl-creator-pill__activity {
|
||||
font-size: 0.72rem; color: var(--cl-muted); white-space: nowrap;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════
|
||||
COMMUNITY SPACES — colored icon cards
|
||||
7. COMMUNITY SPACES — large colored icon cards
|
||||
═══════════════════════════════════════════════════════════════════ */
|
||||
.cl-spaces { padding: 1.5rem 0 2rem; }
|
||||
|
||||
.cl-spaces__grid {
|
||||
display: grid; grid-template-columns: repeat(2, 1fr); gap: 0.75rem;
|
||||
display: grid; grid-template-columns: repeat(2, 1fr); gap: 0.85rem;
|
||||
}
|
||||
@media (min-width: 480px) { .cl-spaces__grid { grid-template-columns: repeat(3, 1fr); } }
|
||||
@media (min-width: 768px) { .cl-spaces__grid { grid-template-columns: repeat(4, 1fr); } }
|
||||
@media (min-width: 1024px) { .cl-spaces__grid { grid-template-columns: repeat(5, 1fr); } }
|
||||
|
||||
.cl-space-card {
|
||||
display: flex; flex-direction: column; align-items: center; gap: 0.5rem;
|
||||
padding: 1.25rem 0.75rem;
|
||||
display: flex; flex-direction: column; align-items: center; gap: 0.6rem;
|
||||
padding: 1.5rem 1rem 1.25rem;
|
||||
background: var(--cl-card); border: 1px solid var(--cl-border);
|
||||
border-radius: var(--cl-radius);
|
||||
text-decoration: none; text-align: center;
|
||||
@@ -460,32 +521,33 @@
|
||||
.cl-space-card:hover { border-color: var(--cl-border-hover); transform: translateY(-3px); box-shadow: 0 8px 24px rgba(0,0,0,0.08); }
|
||||
|
||||
.cl-space-card__icon {
|
||||
width: 56px; height: 56px; border-radius: 14px;
|
||||
width: 64px; height: 64px; border-radius: 16px;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
|
||||
}
|
||||
.cl-space-card__icon img { width: 100%; height: 100%; object-fit: cover; }
|
||||
|
||||
.cl-space-card__letter {
|
||||
font-size: 1.4rem; font-weight: 800; color: #fff;
|
||||
line-height: 1;
|
||||
font-size: 1.6rem; font-weight: 800; color: #fff;
|
||||
line-height: 1; text-shadow: 0 1px 2px rgba(0,0,0,0.2);
|
||||
}
|
||||
|
||||
.cl-space-card__name {
|
||||
font-size: 0.82rem; font-weight: 600; color: var(--cl-text-strong);
|
||||
font-size: 0.85rem; font-weight: 700; color: var(--cl-text-strong);
|
||||
white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%;
|
||||
}
|
||||
.cl-space-card__count { font-size: 0.7rem; color: var(--cl-muted); }
|
||||
.cl-space-card__sub { font-size: 0.72rem; color: var(--cl-muted); font-weight: 500; }
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════
|
||||
APP CTA — split layout: content left, image right
|
||||
8. APP CTA — split layout with gradient
|
||||
═══════════════════════════════════════════════════════════════════ */
|
||||
.cl-app-cta { padding: 2rem 0; }
|
||||
|
||||
.cl-app-cta__inner {
|
||||
background: var(--cl-app-gradient);
|
||||
border-radius: 20px;
|
||||
padding: 2.5rem 2.5rem;
|
||||
padding: 2.5rem;
|
||||
display: flex; flex-direction: column; gap: 2rem;
|
||||
position: relative; overflow: hidden;
|
||||
min-height: 200px;
|
||||
@@ -496,7 +558,8 @@
|
||||
|
||||
.cl-app-cta__inner::before {
|
||||
content: ""; position: absolute; inset: 0;
|
||||
background: radial-gradient(circle at 30% 50%, rgba(255,255,255,0.1) 0%, transparent 50%);
|
||||
background: radial-gradient(circle at 20% 50%, rgba(255,255,255,0.12) 0%, transparent 50%);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.cl-app-cta__content { position: relative; z-index: 1; flex: 1; }
|
||||
@@ -511,6 +574,7 @@
|
||||
|
||||
.cl-app-cta__badges { display: flex; gap: 0.75rem; flex-wrap: wrap; }
|
||||
|
||||
/* Default icon+text badge */
|
||||
.cl-app-badge {
|
||||
display: inline-flex; align-items: center; gap: 0.5rem;
|
||||
padding: 0.6rem 1.2rem;
|
||||
@@ -528,6 +592,18 @@
|
||||
.cl-app-badge__icon svg { width: 20px; height: 20px; }
|
||||
.cl-app-badge__label { white-space: nowrap; }
|
||||
|
||||
/* Custom full-image badge */
|
||||
.cl-app-badge-img {
|
||||
display: inline-flex; overflow: hidden;
|
||||
transition: all 0.2s; text-decoration: none;
|
||||
}
|
||||
.cl-app-badge-img:hover { transform: translateY(-2px); opacity: 0.9; }
|
||||
.cl-app-badge-img img { display: block; }
|
||||
.cl-app-badge-img.cl-app-badge--rounded { border-radius: var(--cl-radius-sm); }
|
||||
.cl-app-badge-img.cl-app-badge--pill { border-radius: 50px; }
|
||||
.cl-app-badge-img.cl-app-badge--square { border-radius: 4px; }
|
||||
|
||||
/* CTA image (right side) */
|
||||
.cl-app-cta__image {
|
||||
position: relative; z-index: 1;
|
||||
display: flex; align-items: flex-end; justify-content: center;
|
||||
@@ -540,12 +616,10 @@
|
||||
max-height: 280px; width: auto; object-fit: contain;
|
||||
filter: drop-shadow(0 8px 32px rgba(0,0,0,0.2));
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
.cl-app-cta__img { max-height: 320px; }
|
||||
}
|
||||
@media (min-width: 768px) { .cl-app-cta__img { max-height: 320px; } }
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════
|
||||
FOOTER DESCRIPTION
|
||||
9. FOOTER DESCRIPTION
|
||||
═══════════════════════════════════════════════════════════════════ */
|
||||
.cl-footer-desc { padding: 1.5rem 0; }
|
||||
.cl-footer-desc__text {
|
||||
@@ -554,7 +628,7 @@
|
||||
}
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════
|
||||
FOOTER — logo + links left, copyright right
|
||||
10. FOOTER
|
||||
═══════════════════════════════════════════════════════════════════ */
|
||||
.cl-footer {
|
||||
background: var(--cl-footer-bg); padding: 1.5rem 0;
|
||||
@@ -584,9 +658,7 @@
|
||||
.cl-footer__link:hover { color: var(--cl-accent); }
|
||||
|
||||
.cl-footer__right { display: flex; align-items: center; }
|
||||
.cl-footer__copy {
|
||||
font-size: 0.75rem; color: var(--cl-muted);
|
||||
}
|
||||
.cl-footer__copy { font-size: 0.75rem; color: var(--cl-muted); }
|
||||
|
||||
.cl-footer__text { color: var(--cl-muted); font-size: 0.82rem; padding: 1rem 0 0; }
|
||||
|
||||
@@ -594,9 +666,9 @@
|
||||
REDUCED MOTION
|
||||
═══════════════════════════════════════════════════════════════════ */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.cl-reveal, .cl-hero__content, .cl-hero__image, .cl-btn {
|
||||
.cl-anim, .cl-hero__content, .cl-hero__image, .cl-btn {
|
||||
animation-duration: 0.01ms !important;
|
||||
transition-duration: 0.01ms !important;
|
||||
}
|
||||
.cl-reveal { opacity: 1; transform: none; }
|
||||
.cl-anim { opacity: 1; transform: none; }
|
||||
}
|
||||
|
||||
@@ -1,88 +1,114 @@
|
||||
en:
|
||||
site_settings:
|
||||
# ── Master Switch ──
|
||||
community_landing_enabled: "Activate the community landing page. When enabled, logged-out visitors see a branded welcome page instead of the default Discourse homepage."
|
||||
community_landing_enabled: "━━ LANDING PAGE ━━ — Enable the branded community landing page. When turned on, logged-out visitors see a custom welcome page instead of the default Discourse homepage. All sections below are configurable."
|
||||
|
||||
# ── Branding: Logo ──
|
||||
community_landing_logo_dark_url: "Logo image URL for dark mode. Shown in the navbar and footer. Leave blank to display the site name as text."
|
||||
community_landing_logo_dark_url: "━━ BRANDING ━━ — Logo image URL for dark mode. Displayed in the navbar header and footer. Leave blank to show the site name as text instead."
|
||||
community_landing_logo_light_url: "Logo image URL for light mode. If not set, the dark logo is used for both themes."
|
||||
community_landing_logo_height: "Logo height in pixels (16–80). Applies to both the navbar and footer logos."
|
||||
community_landing_footer_logo_url: "Override logo specifically for the footer. If not set, the navbar logo is used."
|
||||
|
||||
# ── Navbar ──
|
||||
community_landing_navbar_signin_label: "Text for the sign-in link in the navigation bar."
|
||||
community_landing_navbar_join_label: "Text for the join/register button in the navigation bar."
|
||||
|
||||
# ── Hero Section: Content ──
|
||||
community_landing_hero_title: "The large headline displayed in the hero section. The last word is automatically highlighted with your accent color gradient."
|
||||
community_landing_hero_subtitle: "Supporting text shown below the hero title. Use this to briefly describe your community's purpose or value proposition."
|
||||
|
||||
# ── Hero Section: Imagery ──
|
||||
community_landing_hero_background_image_url: "Full-bleed background image behind the entire hero section. A dark overlay is applied automatically to maintain text readability."
|
||||
community_landing_hero_image_urls: "Images displayed on the right side of the hero section. Add up to 5 image URLs — a random one is shown on each visit. Click + to add each image row."
|
||||
community_landing_hero_image_max_height: "Maximum height (in pixels) for the hero image. Keeps tall images from overwhelming the hero section. Range: 100–1200px."
|
||||
|
||||
# ── Hero Section: Call-to-Action Buttons ──
|
||||
community_landing_hero_primary_button_label: "Text on the primary (filled) call-to-action button in the hero section."
|
||||
community_landing_hero_primary_button_url: "Where the primary button links to. Use a relative path like /latest or an absolute URL."
|
||||
community_landing_hero_secondary_button_label: "Text on the secondary (outlined) call-to-action button in the hero section."
|
||||
community_landing_hero_secondary_button_url: "Where the secondary button links to. Defaults to the login page."
|
||||
community_landing_footer_logo_url: "Override logo specifically for the footer. If not set, the navbar logo is reused."
|
||||
|
||||
# ── Appearance: Color Scheme ──
|
||||
community_landing_accent_color: "Primary accent color used for buttons, links, highlights, and gradients. Enter a hex value (e.g. #d4a24e)."
|
||||
community_landing_accent_hover_color: "Accent color on hover states. Should be slightly lighter or brighter than the primary accent. Hex value (e.g. #c4922e)."
|
||||
community_landing_dark_bg_color: "Background color for dark mode. Sets the overall page tone in dark theme. Hex value (e.g. #06060f)."
|
||||
community_landing_light_bg_color: "Background color for light mode. Sets the overall page tone in light theme. Hex value (e.g. #faf6f0)."
|
||||
community_landing_accent_color: "━━ GLOBAL COLORS ━━ — Primary accent color used across the entire landing page: buttons, links, highlights, gradients, and stat icons. Enter a hex value (e.g. #d4a24e)."
|
||||
community_landing_accent_hover_color: "Accent color on hover states. Should be slightly lighter or darker than the primary accent. Hex value."
|
||||
community_landing_dark_bg_color: "Background color for dark mode. Sets the overall page background when in dark theme. Hex value."
|
||||
community_landing_light_bg_color: "Background color for light mode. Sets the overall page background when in light theme. Hex value."
|
||||
|
||||
# ── Section: Stats ──
|
||||
community_landing_stats_title: "Heading text displayed above the stats counter row. Set to 'Premium Stats' by default."
|
||||
community_landing_stat_icon_color: "Color for the stat counter icons. Enter a hex value (e.g. #d4a24e). Applies to all stat icons uniformly."
|
||||
community_landing_stat_members_label: "Custom label for the Members stat counter shown in the stats row below the hero."
|
||||
community_landing_stat_topics_label: "Custom label for the Topics stat counter."
|
||||
community_landing_stat_posts_label: "Custom label for the Posts stat counter."
|
||||
community_landing_stat_likes_label: "Custom label for the Likes stat counter."
|
||||
community_landing_stat_chats_label: "Custom label for the Chats stat counter. Shows total chat messages if the Chat plugin is enabled."
|
||||
# ── Custom CSS ──
|
||||
community_landing_custom_css: "━━ CUSTOM CSS ━━ — Inject your own CSS directly into the landing page. Use this for fine-tuning styles, overriding any default, or adding completely custom design touches. Paste raw CSS rules here (no <style> tags needed). This CSS loads after all other styles, giving it the highest priority."
|
||||
|
||||
# ── Section: About ──
|
||||
community_landing_about_enabled: "Show the About section with a quote card describing your community."
|
||||
community_landing_about_title: "Title heading displayed at the top of the About Community section."
|
||||
community_landing_about_role: "Subtitle shown below the about author name (e.g. 'Community Manager', 'Founded 2020'). If blank, the site name is used."
|
||||
community_landing_about_body: "Main body text for the About section. Supports basic HTML tags: p, a, strong, em, ul, li, br."
|
||||
community_landing_about_image_url: "Small avatar image shown next to the about section author name. Works best with a square image."
|
||||
community_landing_about_gradient_start: "Start color for the About section card gradient background. Hex value (e.g. #fdf6ec)."
|
||||
community_landing_about_gradient_end: "End color for the About section card gradient background. Hex value (e.g. #fef9f0)."
|
||||
# ── Scroll Animations ──
|
||||
community_landing_scroll_animation: "━━ SCROLL ANIMATIONS ━━ — Choose how sections animate into view as the visitor scrolls down the page. Options: fade_up (slide up from below), fade_in (appear in place), slide_left / slide_right (horizontal entrance), zoom_in (scale up from smaller), flip_up (3D rotation), or none to disable all scroll animations."
|
||||
|
||||
# ── Section: App Download Banner ──
|
||||
community_landing_show_app_ctas: "Show a mobile app download banner above the footer. Requires at least one app store URL to be set."
|
||||
community_landing_ios_app_url: "Apple App Store URL for your iOS app. Leave blank to hide the iOS badge."
|
||||
community_landing_android_app_url: "Google Play Store URL for your Android app. Leave blank to hide the Android badge."
|
||||
community_landing_ios_app_icon_url: "Custom image URL for the iOS app badge (e.g. an uploaded SVG or PNG). If not set, a default text badge is shown."
|
||||
community_landing_android_app_icon_url: "Custom image URL for the Android app badge (e.g. an uploaded SVG or PNG). If not set, a default text badge is shown."
|
||||
community_landing_app_badge_height: "Height of app badges in pixels (30–80). Applies to both default and custom icon badges."
|
||||
community_landing_app_badge_style: "Border-radius style for app badges: rounded (12px corners), pill (fully rounded ends), or square (minimal rounding)."
|
||||
community_landing_app_cta_headline: "Bold headline text shown in the app download banner."
|
||||
community_landing_app_cta_subtext: "Supporting text shown below the app banner headline."
|
||||
community_landing_app_cta_gradient_start: "Start color for the app CTA section gradient background. Hex value (e.g. #d4a24e)."
|
||||
community_landing_app_cta_gradient_end: "End color for the app CTA section gradient background. Hex value (e.g. #b8862e)."
|
||||
community_landing_app_cta_image_url: "Image displayed on the right side of the app CTA banner. Supports PNG for transparent backgrounds. Shown overlapping above the gradient area."
|
||||
# ── Navbar ──
|
||||
community_landing_navbar_signin_label: "━━ ROW 1: NAVBAR ━━ — The fixed navigation bar at the top of the page with your logo, theme toggle, sign-in link, and join button. This setting controls the text for the sign-in link."
|
||||
community_landing_navbar_join_label: "Text for the join/register call-to-action button in the navbar."
|
||||
community_landing_navbar_bg_color: "Custom background color for the navbar when scrolled. Leave blank for the default frosted glass effect."
|
||||
community_landing_navbar_border_style: "Border line style at the bottom of the navbar when scrolled. Choose none, solid, dashed, or dotted."
|
||||
|
||||
# ── Section: Top Contributors ──
|
||||
community_landing_contributors_enabled: "Show a section highlighting your most active community members with their avatars and usernames."
|
||||
community_landing_contributors_title: "Heading text for the Top Creators section."
|
||||
community_landing_contributors_days: "Lookback period in days for calculating top contributors. A larger number gives a broader view of active members."
|
||||
community_landing_contributors_count: "How many top contributors to display. Recommended: 6–12 for a balanced layout."
|
||||
# ── Hero Section ──
|
||||
community_landing_hero_title: "━━ ROW 2: HERO SECTION ━━ — The large welcome area at the top of the page with headline, subtitle, CTA buttons, and optional imagery. This setting is the main headline text. The last word is automatically highlighted with your accent color gradient."
|
||||
community_landing_hero_subtitle: "Supporting text shown below the hero headline. Describe your community's purpose or value proposition."
|
||||
community_landing_hero_card_enabled: "Wrap the hero content inside a rounded card container with a subtle border and shadow. Turn off for a flat, full-width hero layout."
|
||||
community_landing_hero_background_image_url: "Full-bleed background image behind the hero section. In card mode, the image fills the card with a dark overlay. In flat mode, it covers the entire section."
|
||||
community_landing_hero_image_urls: "Images displayed on the right side of the hero. Add up to 5 image URLs — a random one is shown on each page load. Click + to add rows."
|
||||
community_landing_hero_image_max_height: "Maximum height in pixels for the hero image (100–1200). Prevents tall images from overwhelming the section."
|
||||
community_landing_hero_primary_button_label: "Text on the primary (filled, accent-colored) call-to-action button."
|
||||
community_landing_hero_primary_button_url: "URL the primary button links to. Use a relative path like /latest or an absolute URL."
|
||||
community_landing_hero_secondary_button_label: "Text on the secondary (outlined) call-to-action button."
|
||||
community_landing_hero_secondary_button_url: "URL the secondary button links to. Defaults to the login page."
|
||||
community_landing_hero_bg_color: "Custom background color for the hero section wrapper. Leave blank for the default page background."
|
||||
community_landing_hero_border_style: "Border line style at the bottom of the hero section. Choose none, solid, dashed, or dotted."
|
||||
|
||||
# ── Section: Groups ──
|
||||
community_landing_groups_enabled: "Show public groups as browsable cards. Only groups with public visibility are displayed."
|
||||
community_landing_groups_title: "Heading text for the Community Spaces section."
|
||||
community_landing_groups_count: "Number of group cards to display (default 5). Only public, non-automatic groups are shown."
|
||||
# ── Stats Section ──
|
||||
community_landing_stats_title: "━━ ROW 3: PREMIUM STATS ━━ — A full-width row displaying live community statistics (members, topics, posts, likes, chats) with animated counters and icons. Each card shows the icon and label on one line with the counter number below. This setting is the section heading text."
|
||||
community_landing_stat_icon_color: "Color for all stat counter icons. Enter a hex value (e.g. #d4a24e). Matches your accent color by default."
|
||||
community_landing_stat_members_label: "Custom label for the Members stat counter card."
|
||||
community_landing_stat_topics_label: "Custom label for the Topics stat counter card."
|
||||
community_landing_stat_posts_label: "Custom label for the Posts stat counter card."
|
||||
community_landing_stat_likes_label: "Custom label for the Likes stat counter card."
|
||||
community_landing_stat_chats_label: "Custom label for the Chats stat counter card. Shows total chat messages if the Chat plugin is active."
|
||||
community_landing_stats_bg_color: "Custom background color for the stats section wrapper. Leave blank for default."
|
||||
community_landing_stats_border_style: "Border line style at the bottom of the stats section."
|
||||
|
||||
# ── Section: Trending Discussions ──
|
||||
community_landing_topics_enabled: "Show a list of trending discussions as horizontally scrollable cards."
|
||||
community_landing_topics_title: "Heading text for the Trending Discussions section."
|
||||
community_landing_topics_count: "Number of trending topics to display. Shows the most-replied topics from the last 30 days."
|
||||
# ── About Section ──
|
||||
community_landing_about_enabled: "━━ ROW 4: ABOUT COMMUNITY ━━ — A full-width gradient card with a bold heading, decorative quote icon, community description text, and author attribution (avatar, name, role). Supports a 3-color gradient background and an optional overlay image. Toggle this to show or hide the entire section."
|
||||
community_landing_about_heading_enabled: "Show the bold heading text (e.g. 'About Community') at the top of the card. Turn off to start directly with the quote icon and description."
|
||||
community_landing_about_heading: "The bold heading text displayed at the top of the About card (e.g. 'About Community', 'Our Story', 'Who We Are')."
|
||||
community_landing_about_title: "Author or community name shown in the card's bottom attribution area, next to the avatar."
|
||||
community_landing_about_role: "Subtitle below the author name (e.g. 'Community Manager', 'Founded 2020'). If blank, the site name is used."
|
||||
community_landing_about_body: "Main body text for the About card. This is the community description. Supports basic HTML: p, a, strong, em, ul, li, br."
|
||||
community_landing_about_image_url: "Small avatar image shown next to the author name in the card footer. Square images work best."
|
||||
community_landing_about_gradient_start: "First color (left) of the About card's 3-color gradient background. Hex value (e.g. #fdf6ec)."
|
||||
community_landing_about_gradient_mid: "Middle color of the About card gradient. Hex value (e.g. #fef9f0)."
|
||||
community_landing_about_gradient_end: "Third color (right) of the About card gradient. Hex value (e.g. #fdf6ec)."
|
||||
community_landing_about_background_image_url: "Background image layered on top of the gradient. Use a subtle pattern or texture. The gradient shows through any transparent areas."
|
||||
community_landing_about_bg_color: "Custom background color for the about section wrapper (the area around the card). Leave blank for default."
|
||||
community_landing_about_border_style: "Border line style at the bottom of the about section."
|
||||
|
||||
# ── Trending Discussions ──
|
||||
community_landing_topics_enabled: "━━ ROW 5: TRENDING DISCUSSIONS ━━ — A horizontally scrollable row of topic cards showing the most active discussions. Each card displays the category badge, topic title, reply count, and like count — all pulled live from your forum. Supports drag-to-scroll on desktop and native swipe on mobile. Toggle to show or hide."
|
||||
community_landing_topics_title: "Heading text displayed above the scrollable topic cards (e.g. 'Trending Discussions', 'Hot Topics')."
|
||||
community_landing_topics_count: "Number of trending topic cards to display. Shows the most-replied topics from the last 30 days."
|
||||
community_landing_topics_bg_color: "Custom background color for the trending discussions section wrapper. Leave blank for default."
|
||||
community_landing_topics_border_style: "Border line style at the bottom of the trending section."
|
||||
|
||||
# ── Top Creators ──
|
||||
community_landing_contributors_enabled: "━━ ROW 6: TOP CREATORS ━━ — A row of pill-shaped badges showing your most active community members. Each pill displays the user's avatar, @username, and activity count (number of posts in the lookback period). Toggle to show or hide the entire section."
|
||||
community_landing_contributors_title: "Heading text displayed above the creator pills (e.g. 'Top Creators', 'Most Active Members')."
|
||||
community_landing_contributors_days: "Lookback period in days for calculating top contributors. A larger number captures a wider time range of activity."
|
||||
community_landing_contributors_count: "Number of top contributor pills to display. Recommended: 6–12 for a balanced layout."
|
||||
community_landing_contributors_bg_color: "Custom background color for the creators section wrapper. Leave blank for default."
|
||||
community_landing_contributors_border_style: "Border line style at the bottom of the creators section."
|
||||
|
||||
# ── Community Spaces ──
|
||||
community_landing_groups_enabled: "━━ ROW 7: COMMUNITY SPACES ━━ — A grid of colorful cards representing your public community groups. Each card shows a large colored icon (with the group's first letter if no flair is set), the group name, and member count. Only publicly visible, non-automatic groups are displayed. Toggle to show or hide."
|
||||
community_landing_groups_title: "Heading text displayed above the group cards (e.g. 'Community Spaces', 'Our Groups')."
|
||||
community_landing_groups_count: "Number of group cards to display. Only public, non-automatic groups are shown."
|
||||
community_landing_groups_bg_color: "Custom background color for the community spaces section wrapper. Leave blank for default."
|
||||
community_landing_groups_border_style: "Border line style at the bottom of the spaces section."
|
||||
|
||||
# ── App Download CTA ──
|
||||
community_landing_show_app_ctas: "━━ ROW 8: APP DOWNLOAD CTA ━━ — A gradient banner promoting your mobile app with a headline, subtitle, download badges (App Store / Google Play), and an optional promotional image on the right side. The gradient, badge style, and all text are fully configurable. Requires at least one app store URL. Toggle to show or hide."
|
||||
community_landing_ios_app_url: "Apple App Store URL for your iOS app. Leave blank to hide the iOS badge entirely."
|
||||
community_landing_android_app_url: "Google Play Store URL for your Android app. Leave blank to hide the Android badge entirely."
|
||||
community_landing_ios_app_badge_image_url: "Replace the entire iOS badge button with a custom image (e.g. an official App Store badge PNG/SVG). Leave blank to use the default icon+text button."
|
||||
community_landing_android_app_badge_image_url: "Replace the entire Android badge button with a custom image (e.g. an official Google Play badge PNG/SVG). Leave blank to use the default icon+text button."
|
||||
community_landing_app_badge_height: "Height of app download badges in pixels (30–80). Applies to both default and custom image badges."
|
||||
community_landing_app_badge_style: "Border-radius style for default badges: rounded (soft corners), pill (fully rounded), or square (minimal rounding)."
|
||||
community_landing_app_cta_headline: "Bold headline text in the app download banner (e.g. 'Get the best experience on our app')."
|
||||
community_landing_app_cta_subtext: "Supporting text below the headline (e.g. 'Available free on iOS and Android')."
|
||||
community_landing_app_cta_gradient_start: "First color (left) of the app CTA 3-color gradient background. Hex value."
|
||||
community_landing_app_cta_gradient_mid: "Middle color of the app CTA gradient. Hex value."
|
||||
community_landing_app_cta_gradient_end: "Third color (right) of the app CTA gradient. Hex value."
|
||||
community_landing_app_cta_image_url: "Promotional image on the right side of the CTA (e.g. a phone mockup). Supports PNG for transparent backgrounds. The image extends above the gradient area."
|
||||
community_landing_app_cta_bg_color: "Custom background color for the app CTA section wrapper (behind the gradient card). Leave blank for default."
|
||||
community_landing_app_cta_border_style: "Border line style at the bottom of the app CTA section."
|
||||
|
||||
# ── Footer ──
|
||||
community_landing_footer_description: "Description text displayed between the app CTA and footer navigation. Useful for a brief community description or tagline."
|
||||
community_landing_footer_text: "Optional text displayed in the footer area. Supports basic HTML: p, a, strong, em, ul, li, br."
|
||||
community_landing_footer_links: 'Footer navigation links as a JSON array. Format: [{"label":"Terms","url":"/tos"},{"label":"Privacy","url":"/privacy"}]'
|
||||
community_landing_footer_description: "━━ ROW 9: FOOTER ━━ — The bottom of the page with your logo, navigation links, copyright notice, and optional description text. This setting adds a description paragraph between the app CTA and the footer bar. Useful for a brief community tagline or mission statement."
|
||||
community_landing_footer_text: "Optional HTML text displayed inside the footer bar area. Supports: p, a, strong, em, ul, li, br."
|
||||
community_landing_footer_links: 'Footer navigation links as a JSON array. Format: [{"label":"Terms","url":"/tos"},{"label":"Privacy","url":"/privacy"}]. Logo and links appear on the left, copyright on the right.'
|
||||
community_landing_footer_bg_color: "Custom background color for the footer bar. Leave blank for the default footer background."
|
||||
community_landing_footer_border_style: "Border line style at the top of the footer bar. Defaults to solid."
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
plugins:
|
||||
# ── Master Switch ──
|
||||
# ══════════════════════════════════════════
|
||||
# Master Switch
|
||||
# ══════════════════════════════════════════
|
||||
community_landing_enabled:
|
||||
default: true
|
||||
type: bool
|
||||
|
||||
# ── Branding: Logo ──
|
||||
# ══════════════════════════════════════════
|
||||
# Branding: Logo
|
||||
# ══════════════════════════════════════════
|
||||
community_landing_logo_dark_url:
|
||||
default: ""
|
||||
type: string
|
||||
@@ -20,50 +24,9 @@ plugins:
|
||||
default: ""
|
||||
type: string
|
||||
|
||||
# ── Navbar ──
|
||||
community_landing_navbar_signin_label:
|
||||
default: "Sign In"
|
||||
type: string
|
||||
community_landing_navbar_join_label:
|
||||
default: "Get Started"
|
||||
type: string
|
||||
|
||||
# ── Hero Section: Content ──
|
||||
community_landing_hero_title:
|
||||
default: "Welcome to Our Creative HeadQuarters"
|
||||
type: string
|
||||
community_landing_hero_subtitle:
|
||||
default: "Are you ready to start your creative journey?"
|
||||
type: string
|
||||
|
||||
# ── Hero Section: Imagery ──
|
||||
community_landing_hero_background_image_url:
|
||||
default: ""
|
||||
type: string
|
||||
community_landing_hero_image_urls:
|
||||
default: ""
|
||||
type: list
|
||||
community_landing_hero_image_max_height:
|
||||
default: 500
|
||||
type: integer
|
||||
min: 100
|
||||
max: 1200
|
||||
|
||||
# ── Hero Section: Call-to-Action Buttons ──
|
||||
community_landing_hero_primary_button_label:
|
||||
default: "View Latest Topics"
|
||||
type: string
|
||||
community_landing_hero_primary_button_url:
|
||||
default: "/latest"
|
||||
type: string
|
||||
community_landing_hero_secondary_button_label:
|
||||
default: "Explore Our Spaces"
|
||||
type: string
|
||||
community_landing_hero_secondary_button_url:
|
||||
default: "/login"
|
||||
type: string
|
||||
|
||||
# ── Appearance: Color Scheme ──
|
||||
# ══════════════════════════════════════════
|
||||
# Appearance: Color Scheme
|
||||
# ══════════════════════════════════════════
|
||||
community_landing_accent_color:
|
||||
default: "#d4a24e"
|
||||
type: string
|
||||
@@ -77,7 +40,99 @@ plugins:
|
||||
default: "#faf6f0"
|
||||
type: string
|
||||
|
||||
# ── Section: Stats ──
|
||||
# ══════════════════════════════════════════
|
||||
# Scroll Animations
|
||||
# ══════════════════════════════════════════
|
||||
community_landing_scroll_animation:
|
||||
default: "fade_up"
|
||||
type: enum
|
||||
choices:
|
||||
- fade_up
|
||||
- fade_in
|
||||
- slide_left
|
||||
- slide_right
|
||||
- zoom_in
|
||||
- flip_up
|
||||
- none
|
||||
|
||||
# ══════════════════════════════════════════
|
||||
# Custom CSS
|
||||
# ══════════════════════════════════════════
|
||||
community_landing_custom_css:
|
||||
default: ""
|
||||
type: string
|
||||
|
||||
# ══════════════════════════════════════════
|
||||
# 1. Navbar
|
||||
# ══════════════════════════════════════════
|
||||
community_landing_navbar_signin_label:
|
||||
default: "Sign In"
|
||||
type: string
|
||||
community_landing_navbar_join_label:
|
||||
default: "Get Started"
|
||||
type: string
|
||||
community_landing_navbar_bg_color:
|
||||
default: ""
|
||||
type: string
|
||||
community_landing_navbar_border_style:
|
||||
default: "none"
|
||||
type: enum
|
||||
choices:
|
||||
- none
|
||||
- solid
|
||||
- dashed
|
||||
- dotted
|
||||
|
||||
# ══════════════════════════════════════════
|
||||
# 2. Hero Section
|
||||
# ══════════════════════════════════════════
|
||||
community_landing_hero_title:
|
||||
default: "Welcome to Our Creative HeadQuarters"
|
||||
type: string
|
||||
community_landing_hero_subtitle:
|
||||
default: "Are you ready to start your creative journey?"
|
||||
type: string
|
||||
community_landing_hero_card_enabled:
|
||||
default: true
|
||||
type: bool
|
||||
community_landing_hero_background_image_url:
|
||||
default: ""
|
||||
type: string
|
||||
community_landing_hero_image_urls:
|
||||
default: ""
|
||||
type: list
|
||||
community_landing_hero_image_max_height:
|
||||
default: 500
|
||||
type: integer
|
||||
min: 100
|
||||
max: 1200
|
||||
community_landing_hero_primary_button_label:
|
||||
default: "View Latest Topics"
|
||||
type: string
|
||||
community_landing_hero_primary_button_url:
|
||||
default: "/latest"
|
||||
type: string
|
||||
community_landing_hero_secondary_button_label:
|
||||
default: "Explore Our Spaces"
|
||||
type: string
|
||||
community_landing_hero_secondary_button_url:
|
||||
default: "/login"
|
||||
type: string
|
||||
community_landing_hero_bg_color:
|
||||
default: ""
|
||||
type: string
|
||||
community_landing_hero_border_style:
|
||||
default: "none"
|
||||
type: enum
|
||||
choices:
|
||||
- none
|
||||
- solid
|
||||
- dashed
|
||||
- dotted
|
||||
|
||||
# ══════════════════════════════════════════
|
||||
# 3. Premium Stats Section
|
||||
# ══════════════════════════════════════════
|
||||
community_landing_stats_title:
|
||||
default: "Premium Stats"
|
||||
type: string
|
||||
@@ -99,14 +154,33 @@ plugins:
|
||||
community_landing_stat_chats_label:
|
||||
default: "Chats"
|
||||
type: string
|
||||
community_landing_stats_bg_color:
|
||||
default: ""
|
||||
type: string
|
||||
community_landing_stats_border_style:
|
||||
default: "none"
|
||||
type: enum
|
||||
choices:
|
||||
- none
|
||||
- solid
|
||||
- dashed
|
||||
- dotted
|
||||
|
||||
# ── Section: About ──
|
||||
# ══════════════════════════════════════════
|
||||
# 4. About Community Section
|
||||
# ══════════════════════════════════════════
|
||||
community_landing_about_enabled:
|
||||
default: true
|
||||
type: bool
|
||||
community_landing_about_title:
|
||||
community_landing_about_heading_enabled:
|
||||
default: true
|
||||
type: bool
|
||||
community_landing_about_heading:
|
||||
default: "About Community"
|
||||
type: string
|
||||
community_landing_about_title:
|
||||
default: "Community Name"
|
||||
type: string
|
||||
community_landing_about_role:
|
||||
default: ""
|
||||
type: string
|
||||
@@ -119,11 +193,105 @@ plugins:
|
||||
community_landing_about_gradient_start:
|
||||
default: "#fdf6ec"
|
||||
type: string
|
||||
community_landing_about_gradient_end:
|
||||
community_landing_about_gradient_mid:
|
||||
default: "#fef9f0"
|
||||
type: string
|
||||
community_landing_about_gradient_end:
|
||||
default: "#fdf6ec"
|
||||
type: string
|
||||
community_landing_about_background_image_url:
|
||||
default: ""
|
||||
type: string
|
||||
community_landing_about_bg_color:
|
||||
default: ""
|
||||
type: string
|
||||
community_landing_about_border_style:
|
||||
default: "none"
|
||||
type: enum
|
||||
choices:
|
||||
- none
|
||||
- solid
|
||||
- dashed
|
||||
- dotted
|
||||
|
||||
# ── Section: App Download Banner ──
|
||||
# ══════════════════════════════════════════
|
||||
# 5. Trending Discussions Section
|
||||
# ══════════════════════════════════════════
|
||||
community_landing_topics_enabled:
|
||||
default: true
|
||||
type: bool
|
||||
community_landing_topics_title:
|
||||
default: "Trending Discussions"
|
||||
type: string
|
||||
community_landing_topics_count:
|
||||
default: 5
|
||||
type: integer
|
||||
community_landing_topics_bg_color:
|
||||
default: ""
|
||||
type: string
|
||||
community_landing_topics_border_style:
|
||||
default: "none"
|
||||
type: enum
|
||||
choices:
|
||||
- none
|
||||
- solid
|
||||
- dashed
|
||||
- dotted
|
||||
|
||||
# ══════════════════════════════════════════
|
||||
# 6. Top Creators Section
|
||||
# ══════════════════════════════════════════
|
||||
community_landing_contributors_enabled:
|
||||
default: true
|
||||
type: bool
|
||||
community_landing_contributors_title:
|
||||
default: "Top Creators"
|
||||
type: string
|
||||
community_landing_contributors_days:
|
||||
default: 90
|
||||
type: integer
|
||||
community_landing_contributors_count:
|
||||
default: 10
|
||||
type: integer
|
||||
community_landing_contributors_bg_color:
|
||||
default: ""
|
||||
type: string
|
||||
community_landing_contributors_border_style:
|
||||
default: "none"
|
||||
type: enum
|
||||
choices:
|
||||
- none
|
||||
- solid
|
||||
- dashed
|
||||
- dotted
|
||||
|
||||
# ══════════════════════════════════════════
|
||||
# 7. Community Spaces Section
|
||||
# ══════════════════════════════════════════
|
||||
community_landing_groups_enabled:
|
||||
default: true
|
||||
type: bool
|
||||
community_landing_groups_title:
|
||||
default: "Community Spaces"
|
||||
type: string
|
||||
community_landing_groups_count:
|
||||
default: 5
|
||||
type: integer
|
||||
community_landing_groups_bg_color:
|
||||
default: ""
|
||||
type: string
|
||||
community_landing_groups_border_style:
|
||||
default: "none"
|
||||
type: enum
|
||||
choices:
|
||||
- none
|
||||
- solid
|
||||
- dashed
|
||||
- dotted
|
||||
|
||||
# ══════════════════════════════════════════
|
||||
# 8. App Download CTA Section
|
||||
# ══════════════════════════════════════════
|
||||
community_landing_show_app_ctas:
|
||||
default: true
|
||||
type: bool
|
||||
@@ -133,10 +301,10 @@ plugins:
|
||||
community_landing_android_app_url:
|
||||
default: ""
|
||||
type: string
|
||||
community_landing_ios_app_icon_url:
|
||||
community_landing_ios_app_badge_image_url:
|
||||
default: ""
|
||||
type: string
|
||||
community_landing_android_app_icon_url:
|
||||
community_landing_android_app_badge_image_url:
|
||||
default: ""
|
||||
type: string
|
||||
community_landing_app_badge_height:
|
||||
@@ -160,50 +328,30 @@ plugins:
|
||||
community_landing_app_cta_gradient_start:
|
||||
default: "#d4a24e"
|
||||
type: string
|
||||
community_landing_app_cta_gradient_mid:
|
||||
default: "#c4922e"
|
||||
type: string
|
||||
community_landing_app_cta_gradient_end:
|
||||
default: "#b8862e"
|
||||
type: string
|
||||
community_landing_app_cta_image_url:
|
||||
default: ""
|
||||
type: string
|
||||
|
||||
# ── Section: Top Contributors ──
|
||||
community_landing_contributors_enabled:
|
||||
default: true
|
||||
type: bool
|
||||
community_landing_contributors_title:
|
||||
default: "Top Creators"
|
||||
community_landing_app_cta_bg_color:
|
||||
default: ""
|
||||
type: string
|
||||
community_landing_contributors_days:
|
||||
default: 90
|
||||
type: integer
|
||||
community_landing_contributors_count:
|
||||
default: 10
|
||||
type: integer
|
||||
community_landing_app_cta_border_style:
|
||||
default: "none"
|
||||
type: enum
|
||||
choices:
|
||||
- none
|
||||
- solid
|
||||
- dashed
|
||||
- dotted
|
||||
|
||||
# ── Section: Groups ──
|
||||
community_landing_groups_enabled:
|
||||
default: true
|
||||
type: bool
|
||||
community_landing_groups_title:
|
||||
default: "Community Spaces"
|
||||
type: string
|
||||
community_landing_groups_count:
|
||||
default: 5
|
||||
type: integer
|
||||
|
||||
# ── Section: Trending Discussions ──
|
||||
community_landing_topics_enabled:
|
||||
default: true
|
||||
type: bool
|
||||
community_landing_topics_title:
|
||||
default: "Trending Discussions"
|
||||
type: string
|
||||
community_landing_topics_count:
|
||||
default: 5
|
||||
type: integer
|
||||
|
||||
# ── Footer ──
|
||||
# ══════════════════════════════════════════
|
||||
# 9. Footer
|
||||
# ══════════════════════════════════════════
|
||||
community_landing_footer_description:
|
||||
default: ""
|
||||
type: string
|
||||
@@ -213,3 +361,14 @@ plugins:
|
||||
community_landing_footer_links:
|
||||
default: '[{"label":"Brand","url":"/about"},{"label":"Links","url":"/links"},{"label":"Terms","url":"/tos"},{"label":"Privacy","url":"/privacy"}]'
|
||||
type: string
|
||||
community_landing_footer_bg_color:
|
||||
default: ""
|
||||
type: string
|
||||
community_landing_footer_border_style:
|
||||
default: "solid"
|
||||
type: enum
|
||||
choices:
|
||||
- none
|
||||
- solid
|
||||
- dashed
|
||||
- dotted
|
||||
|
||||
214
plugin.rb
214
plugin.rb
@@ -2,12 +2,14 @@
|
||||
|
||||
# name: community-landing
|
||||
# about: Branded public landing page for unauthenticated visitors
|
||||
# version: 2.0.0
|
||||
# version: 2.1.0
|
||||
# authors: Community
|
||||
# url: https://github.com/community/community-landing
|
||||
|
||||
enabled_site_setting :community_landing_enabled
|
||||
|
||||
register_asset "stylesheets/community_landing/admin.css", :admin
|
||||
|
||||
after_initialize do
|
||||
module ::CommunityLanding
|
||||
PLUGIN_NAME = "community-landing"
|
||||
@@ -130,11 +132,17 @@ after_initialize do
|
||||
dark_bg = s.community_landing_dark_bg_color.presence || "#06060f"
|
||||
light_bg = s.community_landing_light_bg_color.presence || "#faf6f0"
|
||||
stat_icon_color = s.community_landing_stat_icon_color.presence || accent
|
||||
about_grad_start = s.community_landing_about_gradient_start.presence || "#fdf6ec"
|
||||
about_grad_end = s.community_landing_about_gradient_end.presence || "#fef9f0"
|
||||
app_grad_start = s.community_landing_app_cta_gradient_start.presence || accent
|
||||
app_grad_end = s.community_landing_app_cta_gradient_end.presence || accent_hover
|
||||
about_g1 = s.community_landing_about_gradient_start.presence || "#fdf6ec"
|
||||
about_g2 = s.community_landing_about_gradient_mid.presence || "#fef9f0"
|
||||
about_g3 = s.community_landing_about_gradient_end.presence || "#fdf6ec"
|
||||
about_bg_img = s.community_landing_about_background_image_url.presence
|
||||
app_g1 = s.community_landing_app_cta_gradient_start.presence || accent
|
||||
app_g2 = s.community_landing_app_cta_gradient_mid.presence || accent_hover
|
||||
app_g3 = s.community_landing_app_cta_gradient_end.presence || accent_hover
|
||||
accent_rgb = hex_to_rgb(accent)
|
||||
anim = s.community_landing_scroll_animation rescue "fade_up"
|
||||
|
||||
about_bg_extra = about_bg_img ? ", url('#{about_bg_img}') center/cover no-repeat" : ""
|
||||
|
||||
"<style>
|
||||
:root, [data-theme=\"dark\"] {
|
||||
@@ -148,8 +156,8 @@ after_initialize do
|
||||
--cl-border-hover: rgba(#{accent_rgb}, 0.25);
|
||||
--cl-orb-1: rgba(#{accent_rgb}, 0.12);
|
||||
--cl-stat-icon-color: #{stat_icon_color};
|
||||
--cl-about-gradient: linear-gradient(135deg, #{about_grad_start}, #{about_grad_end});
|
||||
--cl-app-gradient: linear-gradient(135deg, #{app_grad_start}, #{app_grad_end});
|
||||
--cl-about-gradient: linear-gradient(135deg, #{about_g1}, #{about_g2}, #{about_g3})#{about_bg_extra};
|
||||
--cl-app-gradient: linear-gradient(135deg, #{app_g1}, #{app_g2}, #{app_g3});
|
||||
}
|
||||
[data-theme=\"light\"] {
|
||||
--cl-accent: #{accent};
|
||||
@@ -162,8 +170,8 @@ after_initialize do
|
||||
--cl-border-hover: rgba(#{accent_rgb}, 0.3);
|
||||
--cl-orb-1: rgba(#{accent_rgb}, 0.08);
|
||||
--cl-stat-icon-color: #{stat_icon_color};
|
||||
--cl-about-gradient: linear-gradient(135deg, #{about_grad_start}, #{about_grad_end});
|
||||
--cl-app-gradient: linear-gradient(135deg, #{app_grad_start}, #{app_grad_end});
|
||||
--cl-about-gradient: linear-gradient(135deg, #{about_g1}, #{about_g2}, #{about_g3})#{about_bg_extra};
|
||||
--cl-app-gradient: linear-gradient(135deg, #{app_g1}, #{app_g2}, #{app_g3});
|
||||
}
|
||||
@media (prefers-color-scheme: light) {
|
||||
:root:not([data-theme=\"dark\"]) {
|
||||
@@ -177,13 +185,22 @@ after_initialize do
|
||||
--cl-border-hover: rgba(#{accent_rgb}, 0.3);
|
||||
--cl-orb-1: rgba(#{accent_rgb}, 0.08);
|
||||
--cl-stat-icon-color: #{stat_icon_color};
|
||||
--cl-about-gradient: linear-gradient(135deg, #{about_grad_start}, #{about_grad_end});
|
||||
--cl-app-gradient: linear-gradient(135deg, #{app_grad_start}, #{app_grad_end});
|
||||
--cl-about-gradient: linear-gradient(135deg, #{about_g1}, #{about_g2}, #{about_g3})#{about_bg_extra};
|
||||
--cl-app-gradient: linear-gradient(135deg, #{app_g1}, #{app_g2}, #{app_g3});
|
||||
}
|
||||
}
|
||||
</style>\n"
|
||||
end
|
||||
|
||||
# ── Section row style helpers ──
|
||||
|
||||
def section_style(bg_color, border_style)
|
||||
parts = []
|
||||
parts << "background: #{bg_color};" if bg_color.present?
|
||||
parts << "border-bottom: 1px #{border_style} var(--cl-border);" if border_style.present? && border_style != "none"
|
||||
parts.any? ? " style=\"#{parts.join(" ")}\"" : ""
|
||||
end
|
||||
|
||||
# ── Logo helpers ──
|
||||
|
||||
def logo_img(url, alt, css_class, height)
|
||||
@@ -199,24 +216,12 @@ after_initialize do
|
||||
end
|
||||
end
|
||||
|
||||
# ── App badge helper ──
|
||||
|
||||
def render_app_badge(store_url, icon_svg, label, badge_h, badge_style)
|
||||
style_class = case badge_style
|
||||
when "pill" then "cl-app-badge--pill"
|
||||
when "square" then "cl-app-badge--square"
|
||||
else "cl-app-badge--rounded"
|
||||
end
|
||||
"<a href=\"#{store_url}\" class=\"cl-app-badge #{style_class}\" target=\"_blank\" rel=\"noopener noreferrer\">" \
|
||||
"<span class=\"cl-app-badge__icon\">#{icon_svg}</span>" \
|
||||
"<span class=\"cl-app-badge__label\">#{e(label)}</span>" \
|
||||
"</a>\n"
|
||||
end
|
||||
|
||||
def build_html(css, js)
|
||||
s = SiteSetting
|
||||
site_name = s.title
|
||||
login_url = "/login"
|
||||
anim_class = s.community_landing_scroll_animation rescue "fade_up"
|
||||
anim_class = "none" if anim_class.blank?
|
||||
|
||||
# Logo URLs
|
||||
logo_dark_url = s.community_landing_logo_dark_url.presence
|
||||
@@ -228,11 +233,10 @@ after_initialize do
|
||||
has_logo = logo_dark_url.present? || logo_light_url.present?
|
||||
logo_h = s.community_landing_logo_height rescue 30
|
||||
og_logo = logo_dark_url || logo_light_url
|
||||
|
||||
footer_logo_url = s.community_landing_footer_logo_url.presence
|
||||
|
||||
html = +""
|
||||
html << "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n"
|
||||
html << "<!DOCTYPE html>\n<html lang=\"en\" data-scroll-anim=\"#{e(anim_class)}\">\n<head>\n"
|
||||
html << "<meta charset=\"UTF-8\">\n"
|
||||
html << "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, viewport-fit=cover\">\n"
|
||||
html << "<meta name=\"color-scheme\" content=\"dark light\">\n"
|
||||
@@ -246,30 +250,66 @@ after_initialize do
|
||||
html << "<link rel=\"canonical\" href=\"#{Discourse.base_url}\">\n"
|
||||
html << "<style>\n#{css}\n</style>\n"
|
||||
html << build_color_overrides(s)
|
||||
|
||||
# Custom CSS injection
|
||||
custom_css = s.community_landing_custom_css.presence rescue nil
|
||||
if custom_css
|
||||
html << "<style>\n/* Custom CSS */\n#{custom_css}\n</style>\n"
|
||||
end
|
||||
|
||||
html << "</head>\n<body class=\"cl-body\">\n"
|
||||
|
||||
signin_label = s.community_landing_navbar_signin_label.presence || "Sign In"
|
||||
join_label = s.community_landing_navbar_join_label.presence || "Get Started"
|
||||
|
||||
# ── NAVBAR ──
|
||||
html << "<nav class=\"cl-navbar\" id=\"cl-navbar\"><div class=\"cl-navbar__inner\">\n"
|
||||
# ── 1. NAVBAR ──
|
||||
navbar_bg = s.community_landing_navbar_bg_color.presence rescue nil
|
||||
navbar_border = s.community_landing_navbar_border_style rescue "none"
|
||||
navbar_data = ""
|
||||
navbar_data << " data-nav-bg=\"#{e(navbar_bg)}\"" if navbar_bg
|
||||
navbar_data << " data-nav-border=\"#{e(navbar_border)}\"" if navbar_border && navbar_border != "none"
|
||||
html << "<nav class=\"cl-navbar\" id=\"cl-navbar\"#{navbar_data}><div class=\"cl-navbar__inner\">\n"
|
||||
html << "<div class=\"cl-navbar__left\">"
|
||||
html << "<button class=\"cl-theme-toggle\" aria-label=\"Toggle theme\">#{SUN_SVG}#{MOON_SVG}</button>\n"
|
||||
html << "<a href=\"/\" class=\"cl-navbar__brand\">"
|
||||
if has_logo
|
||||
html << render_logo(logo_dark_url, logo_light_url, site_name, "cl-navbar__logo", logo_h)
|
||||
else
|
||||
html << "<span class=\"cl-navbar__site-name\">#{e(site_name)}</span>"
|
||||
end
|
||||
html << "</a>\n"
|
||||
html << "</div>"
|
||||
html << "<div class=\"cl-navbar__right\">"
|
||||
html << "<button class=\"cl-theme-toggle\" aria-label=\"Toggle theme\">#{SUN_SVG}#{MOON_SVG}</button>\n"
|
||||
html << "<a href=\"#{login_url}\" class=\"cl-navbar__link cl-btn--ghost\">#{e(signin_label)}</a>\n"
|
||||
html << "<a href=\"#{login_url}\" class=\"cl-navbar__link cl-btn--primary\">#{e(join_label)}</a>\n"
|
||||
html << "</div>"
|
||||
html << "<button class=\"cl-navbar__hamburger\" id=\"cl-hamburger\" aria-label=\"Toggle menu\"><span></span><span></span><span></span></button>\n"
|
||||
html << "<div class=\"cl-navbar__mobile-menu\" id=\"cl-nav-links\">\n"
|
||||
html << "<button class=\"cl-theme-toggle\" aria-label=\"Toggle theme\">#{SUN_SVG}#{MOON_SVG}</button>\n"
|
||||
html << "<a href=\"#{login_url}\" class=\"cl-navbar__link cl-btn--ghost\">#{e(signin_label)}</a>\n"
|
||||
html << "<a href=\"#{login_url}\" class=\"cl-navbar__link cl-btn--primary\">#{e(join_label)}</a>\n"
|
||||
html << "</div>"
|
||||
html << "</div></nav>\n"
|
||||
|
||||
# ── HERO ──
|
||||
html << "<section class=\"cl-hero\" id=\"cl-hero\">\n"
|
||||
html << "<div class=\"cl-hero__inner\">\n"
|
||||
# ── 2. HERO ──
|
||||
hero_card = s.community_landing_hero_card_enabled rescue true
|
||||
hero_bg_img = s.community_landing_hero_background_image_url.presence
|
||||
hero_bg_color = s.community_landing_hero_bg_color.presence
|
||||
hero_border = s.community_landing_hero_border_style rescue "none"
|
||||
|
||||
hero_section_style = section_style(hero_bg_color, hero_border)
|
||||
html << "<section class=\"cl-hero#{hero_card ? ' cl-hero--card' : ''}\" id=\"cl-hero\"#{hero_section_style}>\n"
|
||||
|
||||
if hero_bg_img && !hero_card
|
||||
html << "<div class=\"cl-hero__bg\" style=\"background-image: url('#{hero_bg_img}');\"></div>\n"
|
||||
end
|
||||
|
||||
inner_style = ""
|
||||
if hero_card && hero_bg_img
|
||||
inner_style = " style=\"background-image: linear-gradient(rgba(0,0,0,0.4), rgba(0,0,0,0.4)), url('#{hero_bg_img}'); background-size: cover; background-position: center;\""
|
||||
end
|
||||
|
||||
html << "<div class=\"cl-hero__inner\"#{inner_style}>\n"
|
||||
html << "<div class=\"cl-hero__content\">\n"
|
||||
|
||||
title_words = s.community_landing_hero_title.to_s.split(" ")
|
||||
@@ -292,7 +332,6 @@ after_initialize do
|
||||
html << "</div>\n"
|
||||
html << "</div>\n"
|
||||
|
||||
# Hero image
|
||||
hero_image_urls_raw = s.community_landing_hero_image_urls.presence
|
||||
if hero_image_urls_raw
|
||||
urls = hero_image_urls_raw.split("|").map(&:strip).reject(&:empty?).first(5)
|
||||
@@ -306,9 +345,11 @@ after_initialize do
|
||||
|
||||
html << "</div></section>\n"
|
||||
|
||||
# ── PREMIUM STATS ROW ──
|
||||
# ── 3. PREMIUM STATS ──
|
||||
stats_title = s.community_landing_stats_title.presence || "Premium Stats"
|
||||
html << "<section class=\"cl-stats cl-reveal\" id=\"cl-stats-row\"><div class=\"cl-container\">\n"
|
||||
stats_bg = s.community_landing_stats_bg_color.presence
|
||||
stats_border = s.community_landing_stats_border_style rescue "none"
|
||||
html << "<section class=\"cl-stats cl-anim\" id=\"cl-stats-row\"#{section_style(stats_bg, stats_border)}><div class=\"cl-container\">\n"
|
||||
html << "<h2 class=\"cl-section-title\">#{e(stats_title)}</h2>\n"
|
||||
html << "<div class=\"cl-stats__grid\">\n"
|
||||
html << stats_counter_card(STAT_MEMBERS_SVG, @stats[:members], s.community_landing_stat_members_label)
|
||||
@@ -318,14 +359,19 @@ after_initialize do
|
||||
html << stats_counter_card(STAT_CHATS_SVG, @stats[:chats], s.community_landing_stat_chats_label)
|
||||
html << "</div>\n</div></section>\n"
|
||||
|
||||
# ── ABOUT COMMUNITY — full-width card ──
|
||||
# ── 4. ABOUT COMMUNITY ──
|
||||
if s.community_landing_about_enabled
|
||||
about_body = s.community_landing_about_body.presence || ""
|
||||
about_image = s.community_landing_about_image_url.presence
|
||||
about_role = s.community_landing_about_role.presence || site_name
|
||||
html << "<section class=\"cl-about cl-reveal\" id=\"cl-about\"><div class=\"cl-container\">\n"
|
||||
about_heading_on = s.community_landing_about_heading_enabled rescue true
|
||||
about_heading = s.community_landing_about_heading.presence || "About Community"
|
||||
about_bg = s.community_landing_about_bg_color.presence
|
||||
about_border = s.community_landing_about_border_style rescue "none"
|
||||
|
||||
html << "<section class=\"cl-about cl-anim\" id=\"cl-about\"#{section_style(about_bg, about_border)}><div class=\"cl-container\">\n"
|
||||
html << "<div class=\"cl-about__card\">\n"
|
||||
html << "<h2 class=\"cl-about__heading\">#{e(s.community_landing_about_title)}</h2>\n"
|
||||
html << "<h2 class=\"cl-about__heading\">#{e(about_heading)}</h2>\n" if about_heading_on
|
||||
html << QUOTE_SVG
|
||||
if about_body.present?
|
||||
html << "<div class=\"cl-about__body\">#{about_body}</div>\n"
|
||||
@@ -342,53 +388,63 @@ after_initialize do
|
||||
html << "</div></section>\n"
|
||||
end
|
||||
|
||||
# ── TRENDING DISCUSSIONS — horizontal scrollable cards ──
|
||||
# ── 5. TRENDING DISCUSSIONS ──
|
||||
if s.community_landing_topics_enabled && @hot_topics&.any?
|
||||
html << "<section class=\"cl-topics cl-reveal\" id=\"cl-topics\"><div class=\"cl-container\">\n"
|
||||
topics_bg = s.community_landing_topics_bg_color.presence
|
||||
topics_border = s.community_landing_topics_border_style rescue "none"
|
||||
html << "<section class=\"cl-topics cl-anim\" id=\"cl-topics\"#{section_style(topics_bg, topics_border)}><div class=\"cl-container\">\n"
|
||||
html << "<h2 class=\"cl-section-title\">#{e(s.community_landing_topics_title)}</h2>\n"
|
||||
html << "<div class=\"cl-topics__scroll\">\n"
|
||||
@hot_topics.each do |topic|
|
||||
topic_likes = topic.like_count rescue 0
|
||||
topic_replies = topic.posts_count.to_i
|
||||
html << "<a href=\"#{login_url}\" class=\"cl-topic-card\">\n"
|
||||
if topic.category
|
||||
html << "<span class=\"cl-topic-card__cat\" style=\"--cat-color: ##{topic.category.color}\">#{e(topic.category.name)}</span>\n"
|
||||
end
|
||||
html << "<span class=\"cl-topic-card__title\">#{e(topic.title)}</span>\n"
|
||||
html << "<div class=\"cl-topic-card__meta\">"
|
||||
html << "<span class=\"cl-topic-card__stat\">#{COMMENT_SVG} #{topic.posts_count}</span>"
|
||||
html << "<span class=\"cl-topic-card__stat\">#{HEART_SVG} #{topic.like_count}</span>"
|
||||
html << "<span class=\"cl-topic-card__stat\">#{COMMENT_SVG} #{topic_replies}</span>"
|
||||
html << "<span class=\"cl-topic-card__stat\">#{HEART_SVG} #{topic_likes}</span>"
|
||||
html << "</div>"
|
||||
html << "</a>\n"
|
||||
end
|
||||
html << "</div>\n</div></section>\n"
|
||||
end
|
||||
|
||||
# ── TOP CREATORS — pill badges ──
|
||||
# ── 6. TOP CREATORS ──
|
||||
if s.community_landing_contributors_enabled && @top_contributors&.any?
|
||||
html << "<section class=\"cl-creators cl-reveal\" id=\"cl-contributors\"><div class=\"cl-container\">\n"
|
||||
contrib_bg = s.community_landing_contributors_bg_color.presence
|
||||
contrib_border = s.community_landing_contributors_border_style rescue "none"
|
||||
html << "<section class=\"cl-creators cl-anim\" id=\"cl-contributors\"#{section_style(contrib_bg, contrib_border)}><div class=\"cl-container\">\n"
|
||||
html << "<h2 class=\"cl-section-title\">#{e(s.community_landing_contributors_title)}</h2>\n"
|
||||
html << "<div class=\"cl-creators__list\">\n"
|
||||
@top_contributors.each do |user|
|
||||
avatar_url = user.avatar_template.gsub("{size}", "120")
|
||||
cheers = user.respond_to?(:post_count) ? user.post_count : 0
|
||||
activity_count = user.attributes["post_count"].to_i rescue 0
|
||||
html << "<a href=\"#{login_url}\" class=\"cl-creator-pill\">\n"
|
||||
html << "<img src=\"#{avatar_url}\" alt=\"#{e(user.username)}\" class=\"cl-creator-pill__avatar\" loading=\"lazy\">\n"
|
||||
html << "<span class=\"cl-creator-pill__name\">@#{e(user.username)}</span>\n"
|
||||
html << "<span class=\"cl-creator-pill__cheers\">#{cheers} cheers</span>\n"
|
||||
html << "<span class=\"cl-creator-pill__activity\">#{activity_count} Activity</span>\n"
|
||||
html << "</a>\n"
|
||||
end
|
||||
html << "</div>\n</div></section>\n"
|
||||
end
|
||||
|
||||
# ── COMMUNITY SPACES — colored cards ──
|
||||
# ── 7. COMMUNITY SPACES ──
|
||||
if s.community_landing_groups_enabled && @groups&.any?
|
||||
html << "<section class=\"cl-spaces cl-reveal\" id=\"cl-groups\"><div class=\"cl-container\">\n"
|
||||
groups_bg = s.community_landing_groups_bg_color.presence
|
||||
groups_border = s.community_landing_groups_border_style rescue "none"
|
||||
html << "<section class=\"cl-spaces cl-anim\" id=\"cl-groups\"#{section_style(groups_bg, groups_border)}><div class=\"cl-container\">\n"
|
||||
html << "<h2 class=\"cl-section-title\">#{e(s.community_landing_groups_title)}</h2>\n"
|
||||
html << "<div class=\"cl-spaces__grid\">\n"
|
||||
@groups.each do |group|
|
||||
display_name = group.name.tr("_-", " ").gsub(/\b\w/, &:upcase)
|
||||
hue = group.name.bytes.sum % 360
|
||||
sat = 50 + (group.name.bytes.first.to_i % 20)
|
||||
light = 40 + (group.name.bytes.last.to_i % 15)
|
||||
html << "<a href=\"#{login_url}\" class=\"cl-space-card\">\n"
|
||||
html << "<div class=\"cl-space-card__icon\" style=\"background: hsl(#{hue}, 55%, 50%)\">"
|
||||
html << "<div class=\"cl-space-card__icon\" style=\"background: hsl(#{hue}, #{sat}%, #{light}%)\">"
|
||||
if group.flair_url.present?
|
||||
html << "<img src=\"#{group.flair_url}\" alt=\"\">"
|
||||
else
|
||||
@@ -396,29 +452,61 @@ after_initialize do
|
||||
end
|
||||
html << "</div>\n"
|
||||
html << "<span class=\"cl-space-card__name\">#{e(display_name)}</span>\n"
|
||||
html << "<span class=\"cl-space-card__count\">#{group.user_count} members</span>\n"
|
||||
html << "<span class=\"cl-space-card__sub\">#{group.user_count} members</span>\n"
|
||||
html << "</a>\n"
|
||||
end
|
||||
html << "</div>\n</div></section>\n"
|
||||
end
|
||||
|
||||
# ── APP CTA — split layout with image ──
|
||||
# ── 8. APP CTA ──
|
||||
if s.community_landing_show_app_ctas && (s.community_landing_ios_app_url.present? || s.community_landing_android_app_url.present?)
|
||||
badge_h = s.community_landing_app_badge_height rescue 45
|
||||
badge_style = s.community_landing_app_badge_style rescue "rounded"
|
||||
app_image = s.community_landing_app_cta_image_url.presence
|
||||
ios_custom = s.community_landing_ios_app_badge_image_url.presence rescue nil
|
||||
android_custom = s.community_landing_android_app_badge_image_url.presence rescue nil
|
||||
app_bg = s.community_landing_app_cta_bg_color.presence
|
||||
app_border = s.community_landing_app_cta_border_style rescue "none"
|
||||
|
||||
html << "<section class=\"cl-app-cta cl-reveal\" id=\"cl-app-cta\"><div class=\"cl-container\">\n"
|
||||
html << "<section class=\"cl-app-cta cl-anim\" id=\"cl-app-cta\"#{section_style(app_bg, app_border)}><div class=\"cl-container\">\n"
|
||||
html << "<div class=\"cl-app-cta__inner\">\n"
|
||||
html << "<div class=\"cl-app-cta__content\">\n"
|
||||
html << "<h2 class=\"cl-app-cta__headline\">#{e(s.community_landing_app_cta_headline)}</h2>\n"
|
||||
html << "<p class=\"cl-app-cta__subtext\">#{e(s.community_landing_app_cta_subtext)}</p>\n" if s.community_landing_app_cta_subtext.present?
|
||||
html << "<div class=\"cl-app-cta__badges\">\n"
|
||||
if s.community_landing_ios_app_url.present?
|
||||
html << render_app_badge(s.community_landing_ios_app_url, IOS_BADGE_SVG, "App Store", badge_h, badge_style)
|
||||
if ios_custom
|
||||
style_class = case badge_style
|
||||
when "pill" then "cl-app-badge--pill"
|
||||
when "square" then "cl-app-badge--square"
|
||||
else "cl-app-badge--rounded"
|
||||
end
|
||||
html << "<a href=\"#{s.community_landing_ios_app_url}\" class=\"cl-app-badge-img #{style_class}\" target=\"_blank\" rel=\"noopener noreferrer\">"
|
||||
html << "<img src=\"#{ios_custom}\" alt=\"App Store\" style=\"height: #{badge_h}px; width: auto;\">"
|
||||
html << "</a>\n"
|
||||
else
|
||||
html << "<a href=\"#{s.community_landing_ios_app_url}\" class=\"cl-app-badge cl-app-badge--#{badge_style == 'pill' ? 'pill' : badge_style == 'square' ? 'square' : 'rounded'}\" target=\"_blank\" rel=\"noopener noreferrer\">"
|
||||
html << "<span class=\"cl-app-badge__icon\">#{IOS_BADGE_SVG}</span>"
|
||||
html << "<span class=\"cl-app-badge__label\">App Store</span>"
|
||||
html << "</a>\n"
|
||||
end
|
||||
end
|
||||
if s.community_landing_android_app_url.present?
|
||||
html << render_app_badge(s.community_landing_android_app_url, ANDROID_BADGE_SVG, "Google Play", badge_h, badge_style)
|
||||
if android_custom
|
||||
style_class = case badge_style
|
||||
when "pill" then "cl-app-badge--pill"
|
||||
when "square" then "cl-app-badge--square"
|
||||
else "cl-app-badge--rounded"
|
||||
end
|
||||
html << "<a href=\"#{s.community_landing_android_app_url}\" class=\"cl-app-badge-img #{style_class}\" target=\"_blank\" rel=\"noopener noreferrer\">"
|
||||
html << "<img src=\"#{android_custom}\" alt=\"Google Play\" style=\"height: #{badge_h}px; width: auto;\">"
|
||||
html << "</a>\n"
|
||||
else
|
||||
html << "<a href=\"#{s.community_landing_android_app_url}\" class=\"cl-app-badge cl-app-badge--#{badge_style == 'pill' ? 'pill' : badge_style == 'square' ? 'square' : 'rounded'}\" target=\"_blank\" rel=\"noopener noreferrer\">"
|
||||
html << "<span class=\"cl-app-badge__icon\">#{ANDROID_BADGE_SVG}</span>"
|
||||
html << "<span class=\"cl-app-badge__label\">Google Play</span>"
|
||||
html << "</a>\n"
|
||||
end
|
||||
end
|
||||
html << "</div>\n"
|
||||
html << "</div>\n"
|
||||
@@ -431,15 +519,21 @@ after_initialize do
|
||||
html << "</div></section>\n"
|
||||
end
|
||||
|
||||
# ── FOOTER DESCRIPTION ──
|
||||
# ── 9. FOOTER DESCRIPTION ──
|
||||
if s.community_landing_footer_description.present?
|
||||
html << "<div class=\"cl-footer-desc\"><div class=\"cl-container\">\n"
|
||||
html << "<p class=\"cl-footer-desc__text\">#{s.community_landing_footer_description}</p>\n"
|
||||
html << "</div></div>\n"
|
||||
end
|
||||
|
||||
# ── FOOTER ──
|
||||
html << "<footer class=\"cl-footer\" id=\"cl-footer\">\n"
|
||||
# ── 10. FOOTER ──
|
||||
footer_bg = s.community_landing_footer_bg_color.presence rescue nil
|
||||
footer_border = s.community_landing_footer_border_style rescue "solid"
|
||||
footer_style_parts = []
|
||||
footer_style_parts << "background: #{footer_bg};" if footer_bg
|
||||
footer_style_parts << "border-top: 1px #{footer_border} var(--cl-border);" if footer_border && footer_border != "none"
|
||||
footer_style_attr = footer_style_parts.any? ? " style=\"#{footer_style_parts.join(" ")}\"" : ""
|
||||
html << "<footer class=\"cl-footer\" id=\"cl-footer\"#{footer_style_attr}>\n"
|
||||
html << "<div class=\"cl-container\">\n"
|
||||
html << "<div class=\"cl-footer__row\">\n"
|
||||
html << "<div class=\"cl-footer__left\">\n"
|
||||
@@ -476,8 +570,10 @@ after_initialize do
|
||||
|
||||
def stats_counter_card(icon_svg, count, label)
|
||||
"<div class=\"cl-stat-card\">\n" \
|
||||
"<div class=\"cl-stat-card__icon\">#{icon_svg}</div>\n" \
|
||||
"<div class=\"cl-stat-card__top\">\n" \
|
||||
"<span class=\"cl-stat-card__icon\">#{icon_svg}</span>\n" \
|
||||
"<span class=\"cl-stat-card__label\">#{e(label)}</span>\n" \
|
||||
"</div>\n" \
|
||||
"<span class=\"cl-stat-card__value\" data-count=\"#{count}\">0</span>\n" \
|
||||
"</div>\n"
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user