mirror of
https://github.com/dpnmw/community-landing.git
synced 2026-03-18 09:27:16 +00:00
UI Revamped v5
Landing page section migration and ui improvements.
This commit is contained in:
@@ -118,11 +118,19 @@
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
// 6. STAT COUNTER
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
function formatRounded(n) {
|
||||
if (n < 1000) return n.toLocaleString();
|
||||
if (n < 10000) return (n / 1000).toFixed(1).replace(/\.0$/, "") + "K";
|
||||
if (n < 1000000) return Math.round(n / 1000) + "K";
|
||||
return (n / 1000000).toFixed(1).replace(/\.0$/, "") + "M";
|
||||
}
|
||||
|
||||
function animateCount(el) {
|
||||
if (el.classList.contains("counted")) return;
|
||||
el.classList.add("counted");
|
||||
var target = parseInt(el.getAttribute("data-count"), 10);
|
||||
if (isNaN(target) || target === 0) return;
|
||||
var round = el.getAttribute("data-round") === "true";
|
||||
|
||||
var duration = 2000;
|
||||
var start = null;
|
||||
@@ -131,9 +139,10 @@
|
||||
function step(ts) {
|
||||
if (!start) start = ts;
|
||||
var p = Math.min((ts - start) / duration, 1);
|
||||
el.textContent = Math.floor(target * ease(p)).toLocaleString();
|
||||
var current = Math.floor(target * ease(p));
|
||||
el.textContent = round ? formatRounded(current) : current.toLocaleString();
|
||||
if (p < 1) requestAnimationFrame(step);
|
||||
else el.textContent = target.toLocaleString();
|
||||
else el.textContent = round ? formatRounded(target) : target.toLocaleString();
|
||||
}
|
||||
requestAnimationFrame(step);
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ const TABS = [
|
||||
"hero_image_urls", "hero_image_max_height",
|
||||
"hero_primary_button_label", "hero_primary_button_url",
|
||||
"hero_secondary_button_label", "hero_secondary_button_url",
|
||||
"hero_video_url",
|
||||
"hero_video_url", "hero_video_button_color", "hero_video_blur_on_hover",
|
||||
"hero_bg_dark", "hero_bg_light", "hero_min_height", "hero_border_style"
|
||||
])
|
||||
},
|
||||
@@ -37,7 +37,7 @@ const TABS = [
|
||||
settings: new Set([
|
||||
"stats_title", "stat_icon_color", "stat_icon_bg_color", "stat_icon_shape", "stat_counter_color",
|
||||
"stat_members_label", "stat_topics_label", "stat_posts_label",
|
||||
"stat_likes_label", "stat_chats_label",
|
||||
"stat_likes_label", "stat_chats_label", "stat_round_numbers",
|
||||
"stats_bg_dark", "stats_bg_light", "stats_min_height", "stats_border_style"
|
||||
])
|
||||
},
|
||||
@@ -184,7 +184,8 @@ function buildTabsUI() {
|
||||
if (!container) return false;
|
||||
|
||||
// Already injected — just re-apply filter
|
||||
if (container.querySelector(".cl-admin-tab")) {
|
||||
// Search broadly: native tabs may be a sibling of container, not a child
|
||||
if (document.querySelector(".cl-admin-tab")) {
|
||||
applyTabFilter();
|
||||
return true;
|
||||
}
|
||||
@@ -199,7 +200,10 @@ function buildTabsUI() {
|
||||
if (!hasOurs) return false;
|
||||
|
||||
// ── Strategy 1: Inject into native Discourse tab bar ──
|
||||
const nativeTabsEl = container.querySelector(".admin-plugin-config-area__tabs");
|
||||
// Native tabs may be a sibling of our container, so search at page level
|
||||
const page = container.closest(".admin-plugin-config-page") || container.parentElement;
|
||||
const nativeTabsEl = (page && page.querySelector(".admin-plugin-config-area__tabs")) ||
|
||||
document.querySelector(".admin-plugin-config-area__tabs");
|
||||
if (nativeTabsEl) {
|
||||
// Find the native "Settings" link and hook into it
|
||||
const nativeLink = nativeTabsEl.querySelector("a");
|
||||
@@ -326,7 +330,7 @@ export default {
|
||||
return;
|
||||
}
|
||||
const c = getContainer();
|
||||
if (c && !c.querySelector(".cl-admin-tab")) {
|
||||
if (c && !document.querySelector(".cl-admin-tab")) {
|
||||
buildTabsUI();
|
||||
}
|
||||
}, 500);
|
||||
|
||||
@@ -739,7 +739,7 @@
|
||||
height: 80px;
|
||||
border-radius: 50%;
|
||||
border: none;
|
||||
background: var(--cl-accent);
|
||||
background: var(--cl-video-btn-bg, var(--cl-accent));
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
@@ -752,7 +752,7 @@
|
||||
|
||||
.cl-hero-play:hover {
|
||||
transform: translate(-50%, -50%) scale(1.1);
|
||||
background: var(--cl-accent-hover);
|
||||
background: var(--cl-video-btn-bg, var(--cl-accent-hover));
|
||||
box-shadow: 0 12px 40px var(--cl-accent-glow);
|
||||
}
|
||||
|
||||
@@ -882,26 +882,44 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* ── Blur hero image on play button hover ── */
|
||||
.cl-hero__image:has(.cl-hero-play[data-blur-hover="true"]:hover) .cl-hero__image-img {
|
||||
filter: blur(4px);
|
||||
transition: filter 0.4s ease;
|
||||
}
|
||||
|
||||
.cl-hero__image .cl-hero__image-img {
|
||||
transition: filter 0.4s ease;
|
||||
}
|
||||
|
||||
/* ── Hero Creators (top 3 pills in hero) ── */
|
||||
.cl-hero__creators {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.75rem;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════
|
||||
3. PREMIUM STATS — icon with bg, label, animated counter
|
||||
3. COMPACT STATS BAR — icon + count + label inline
|
||||
═══════════════════════════════════════════════════════════════════ */
|
||||
.cl-stats {
|
||||
padding: 2.5rem 0 2rem;
|
||||
padding: 2rem 0 1.5rem;
|
||||
}
|
||||
|
||||
.cl-stats__grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 0.75rem;
|
||||
gap: 0.6rem;
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
@media (min-width: 480px) {
|
||||
.cl-stats__grid {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
@media (min-width: 768px) {
|
||||
.cl-stats__grid {
|
||||
grid-template-columns: repeat(5, 1fr);
|
||||
}
|
||||
@@ -909,14 +927,13 @@
|
||||
|
||||
.cl-stat-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
padding: 2.5rem 1.5rem;
|
||||
gap: 0.75rem;
|
||||
padding: 1rem 1.25rem;
|
||||
background: var(--cl-card);
|
||||
border: 1px solid var(--cl-border);
|
||||
border-radius: var(--cl-radius);
|
||||
text-align: center;
|
||||
border-radius: var(--cl-radius-sm);
|
||||
backdrop-filter: var(--cl-blur);
|
||||
-webkit-backdrop-filter: var(--cl-blur);
|
||||
transition: all 0.4s cubic-bezier(0.16, 1, 0.3, 1);
|
||||
@@ -924,18 +941,18 @@
|
||||
|
||||
.cl-stat-card:hover {
|
||||
border-color: var(--cl-accent);
|
||||
transform: translateY(-10px);
|
||||
box-shadow: 0 20px 40px var(--cl-shadow);
|
||||
transform: translateY(-4px);
|
||||
box-shadow: 0 12px 28px var(--cl-shadow);
|
||||
background: var(--cl-glass);
|
||||
}
|
||||
|
||||
/* Icon with background */
|
||||
.cl-stat-card__icon-wrap {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 56px;
|
||||
height: 56px;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
flex-shrink: 0;
|
||||
background: var(--cl-stat-icon-bg);
|
||||
color: var(--cl-stat-icon-color);
|
||||
transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1);
|
||||
@@ -948,8 +965,8 @@
|
||||
}
|
||||
|
||||
.cl-stat-card__icon-wrap svg {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
|
||||
.cl-stat-icon--circle {
|
||||
@@ -957,24 +974,32 @@
|
||||
}
|
||||
|
||||
.cl-stat-icon--rounded {
|
||||
border-radius: 16px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.cl-stat-card__text {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.cl-stat-card__value {
|
||||
font-size: 1.3rem;
|
||||
font-weight: 900;
|
||||
color: var(--cl-stat-counter-color, var(--cl-text-strong));
|
||||
letter-spacing: -0.02em;
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
.cl-stat-card__label {
|
||||
font-size: 0.85rem;
|
||||
font-size: 0.72rem;
|
||||
color: var(--cl-muted);
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
|
||||
/* Counter */
|
||||
.cl-stat-card__value {
|
||||
font-size: 2rem;
|
||||
font-weight: 900;
|
||||
color: var(--cl-stat-counter-color, var(--cl-text-strong));
|
||||
letter-spacing: -0.02em;
|
||||
line-height: 1;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════
|
||||
@@ -1266,7 +1291,7 @@
|
||||
}
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════
|
||||
7. COMMUNITY SPACES — colored header cards
|
||||
7. COMMUNITY SPACES — compact horizontal pills with accent stripe
|
||||
═══════════════════════════════════════════════════════════════════ */
|
||||
.cl-spaces {
|
||||
padding: 1.5rem 0 2rem;
|
||||
@@ -1274,85 +1299,61 @@
|
||||
|
||||
.cl-spaces__grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 0.85rem;
|
||||
grid-template-columns: 1fr;
|
||||
gap: 0.6rem;
|
||||
}
|
||||
|
||||
@media (min-width: 480px) {
|
||||
.cl-spaces__grid {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
grid-template-columns: repeat(2, 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);
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
.cl-space-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
padding: 0.6rem 1rem 0.6rem 0.6rem;
|
||||
background: var(--cl-space-card-bg, var(--cl-card));
|
||||
border: 1px solid var(--cl-border);
|
||||
border-radius: var(--cl-radius);
|
||||
border-left: 3px solid var(--space-color);
|
||||
border-radius: var(--cl-radius-sm);
|
||||
text-decoration: none;
|
||||
overflow: hidden;
|
||||
transition: all 0.5s cubic-bezier(0.16, 1, 0.3, 1);
|
||||
transition: all 0.4s cubic-bezier(0.16, 1, 0.3, 1);
|
||||
backdrop-filter: var(--cl-blur);
|
||||
-webkit-backdrop-filter: var(--cl-blur);
|
||||
}
|
||||
|
||||
.cl-space-card:hover {
|
||||
border-color: var(--cl-accent);
|
||||
transform: translateY(-10px);
|
||||
box-shadow: 0 25px 50px var(--cl-shadow);
|
||||
}
|
||||
|
||||
/* Colored header band */
|
||||
.cl-space-card__header {
|
||||
background: var(--space-color);
|
||||
padding: 2.5rem 1rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.cl-space-card__header::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(0, 0, 0, 0.1));
|
||||
pointer-events: none;
|
||||
border-left-color: var(--space-color);
|
||||
transform: translateY(-4px);
|
||||
box-shadow: 0 12px 28px var(--cl-shadow);
|
||||
background: var(--cl-glass);
|
||||
}
|
||||
|
||||
.cl-space-card__icon {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
border-radius: 18px;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
overflow: hidden;
|
||||
background: rgba(255, 255, 255, 0.25);
|
||||
backdrop-filter: blur(10px);
|
||||
-webkit-backdrop-filter: blur(10px);
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||
transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1);
|
||||
flex-shrink: 0;
|
||||
background: var(--space-color);
|
||||
transition: transform 0.3s cubic-bezier(0.16, 1, 0.3, 1);
|
||||
}
|
||||
|
||||
.cl-space-card:hover .cl-space-card__icon {
|
||||
transform: scale(1.15) rotate(3deg);
|
||||
transform: scale(1.1) rotate(5deg);
|
||||
}
|
||||
|
||||
.cl-space-card__icon img {
|
||||
@@ -1362,23 +1363,21 @@
|
||||
}
|
||||
|
||||
.cl-space-card__letter {
|
||||
font-size: 1.8rem;
|
||||
font-size: 0.9rem;
|
||||
font-weight: 900;
|
||||
color: #fff;
|
||||
line-height: 1;
|
||||
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
/* Card body */
|
||||
.cl-space-card__body {
|
||||
padding: 1.25rem 1.25rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.25rem;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.cl-space-card__name {
|
||||
font-size: 0.95rem;
|
||||
font-size: 0.88rem;
|
||||
font-weight: 800;
|
||||
color: var(--cl-text-strong);
|
||||
white-space: nowrap;
|
||||
@@ -1387,7 +1386,7 @@
|
||||
}
|
||||
|
||||
.cl-space-card__sub {
|
||||
font-size: 0.78rem;
|
||||
font-size: 0.72rem;
|
||||
color: var(--cl-muted);
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
|
||||
@@ -36,6 +36,8 @@ en:
|
||||
hero_secondary_button_label: "Text on the secondary (outlined) CTA button."
|
||||
hero_secondary_button_url: "URL the secondary button links to."
|
||||
hero_video_url: "URL for a hero video. Supports MP4 and YouTube links. A play button appears in the hero area; clicking opens a lightbox modal with the video."
|
||||
hero_video_button_color: "Custom background color for the hero video play button. Leave blank to use the accent color."
|
||||
hero_video_blur_on_hover: "Apply a blur effect to the hero image when hovering the play button."
|
||||
hero_bg_dark: "Background color for the hero section in dark mode. Hex value. Leave blank for default."
|
||||
hero_bg_light: "Background color for the hero section in light mode. Hex value. Leave blank for default."
|
||||
hero_min_height: "Minimum height for the hero section in pixels. Set to 0 for auto height."
|
||||
@@ -52,6 +54,7 @@ en:
|
||||
stat_posts_label: "Custom label for the Posts stat card."
|
||||
stat_likes_label: "Custom label for the Likes stat card."
|
||||
stat_chats_label: "Custom label for the Chats stat card. Shows total chat messages if the Chat plugin is active."
|
||||
stat_round_numbers: "Round large numbers for a cleaner display: 1000 becomes 1K, 12345 becomes 12.3K, 1234567 becomes 1.2M."
|
||||
stats_bg_dark: "Background color for the stats section in dark mode. Leave blank for default."
|
||||
stats_bg_light: "Background color for the stats section in light mode. Leave blank for default."
|
||||
stats_min_height: "Minimum height for the stats section in pixels. Set to 0 for auto height."
|
||||
|
||||
@@ -130,6 +130,12 @@ plugins:
|
||||
hero_video_url:
|
||||
default: ""
|
||||
type: string
|
||||
hero_video_button_color:
|
||||
default: ""
|
||||
type: color
|
||||
hero_video_blur_on_hover:
|
||||
default: true
|
||||
type: bool
|
||||
hero_bg_dark:
|
||||
default: ""
|
||||
type: color
|
||||
@@ -186,6 +192,9 @@ plugins:
|
||||
stat_chats_label:
|
||||
default: "Chats"
|
||||
type: string
|
||||
stat_round_numbers:
|
||||
default: false
|
||||
type: bool
|
||||
stats_bg_dark:
|
||||
default: ""
|
||||
type: color
|
||||
|
||||
@@ -157,10 +157,30 @@ module CommunityLanding
|
||||
html << "<div class=\"cl-hero__actions\">\n"
|
||||
html << "<a href=\"#{primary_url}\" class=\"cl-btn cl-btn--primary cl-btn--lg\">#{e(primary_label)}</a>\n"
|
||||
html << "<a href=\"#{secondary_url}\" class=\"cl-btn cl-btn--ghost cl-btn--lg\">#{e(secondary_label)}</a>\n"
|
||||
html << "</div>\n</div>\n"
|
||||
html << "</div>\n"
|
||||
|
||||
# Hero creators (top 3)
|
||||
contributors = @data[:contributors]
|
||||
if (@s.contributors_enabled rescue false) && contributors&.any?
|
||||
top3 = contributors.first(3)
|
||||
html << "<div class=\"cl-hero__creators\">\n"
|
||||
top3.each do |user|
|
||||
avatar_url = user.avatar_template.gsub("{size}", "120")
|
||||
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__count\">#{activity_count}</span>\n"
|
||||
html << "</a>\n"
|
||||
end
|
||||
html << "</div>\n"
|
||||
end
|
||||
|
||||
html << "</div>\n"
|
||||
|
||||
hero_image_urls_raw = @s.hero_image_urls.presence
|
||||
hero_video = @s.hero_video_url.presence rescue nil
|
||||
blur_attr = (@s.hero_video_blur_on_hover rescue true) ? " data-blur-hover=\"true\"" : ""
|
||||
has_images = false
|
||||
|
||||
if hero_image_urls_raw
|
||||
@@ -171,7 +191,7 @@ module CommunityLanding
|
||||
html << "<div class=\"cl-hero__image\" data-hero-images=\"#{e(urls.to_json)}\">\n"
|
||||
html << "<img src=\"#{urls.first}\" alt=\"#{e(site_name)}\" class=\"cl-hero__image-img\" style=\"max-height: #{img_max_h}px;\">\n"
|
||||
if hero_video
|
||||
html << "<button class=\"cl-hero-play\" data-video-url=\"#{e(hero_video)}\" aria-label=\"Play video\">"
|
||||
html << "<button class=\"cl-hero-play\" data-video-url=\"#{e(hero_video)}\"#{blur_attr} aria-label=\"Play video\">"
|
||||
html << "<span class=\"cl-hero-play__icon\">#{Icons::PLAY_SVG}</span>"
|
||||
html << "</button>\n"
|
||||
end
|
||||
@@ -181,7 +201,7 @@ module CommunityLanding
|
||||
|
||||
if hero_video && !has_images
|
||||
html << "<div class=\"cl-hero__image cl-hero__image--video-only\">\n"
|
||||
html << "<button class=\"cl-hero-play\" data-video-url=\"#{e(hero_video)}\" aria-label=\"Play video\">"
|
||||
html << "<button class=\"cl-hero-play\" data-video-url=\"#{e(hero_video)}\"#{blur_attr} aria-label=\"Play video\">"
|
||||
html << "<span class=\"cl-hero-play__icon\">#{Icons::PLAY_SVG}</span>"
|
||||
html << "</button>\n"
|
||||
html << "</div>\n"
|
||||
@@ -199,16 +219,17 @@ module CommunityLanding
|
||||
border = @s.stats_border_style rescue "none"
|
||||
min_h = @s.stats_min_height rescue 0
|
||||
icon_shape = @s.stat_icon_shape rescue "circle"
|
||||
round_nums = @s.stat_round_numbers rescue false
|
||||
|
||||
html = +""
|
||||
html << "<section class=\"cl-stats cl-anim\" id=\"cl-stats-row\"#{section_style(border, min_h)}><div class=\"cl-container\">\n"
|
||||
html << "<h2 class=\"cl-section-title\">#{e(stats_title)}</h2>\n"
|
||||
html << "<div class=\"cl-stats__grid\">\n"
|
||||
html << stat_card(Icons::STAT_MEMBERS_SVG, stats[:members], @s.stat_members_label, icon_shape)
|
||||
html << stat_card(Icons::STAT_TOPICS_SVG, stats[:topics], @s.stat_topics_label, icon_shape)
|
||||
html << stat_card(Icons::STAT_POSTS_SVG, stats[:posts], @s.stat_posts_label, icon_shape)
|
||||
html << stat_card(Icons::STAT_LIKES_SVG, stats[:likes], @s.stat_likes_label, icon_shape)
|
||||
html << stat_card(Icons::STAT_CHATS_SVG, stats[:chats], @s.stat_chats_label, icon_shape)
|
||||
html << stat_card(Icons::STAT_MEMBERS_SVG, stats[:members], @s.stat_members_label, icon_shape, round_nums)
|
||||
html << stat_card(Icons::STAT_TOPICS_SVG, stats[:topics], @s.stat_topics_label, icon_shape, round_nums)
|
||||
html << stat_card(Icons::STAT_POSTS_SVG, stats[:posts], @s.stat_posts_label, icon_shape, round_nums)
|
||||
html << stat_card(Icons::STAT_LIKES_SVG, stats[:likes], @s.stat_likes_label, icon_shape, round_nums)
|
||||
html << stat_card(Icons::STAT_CHATS_SVG, stats[:chats], @s.stat_chats_label, icon_shape, round_nums)
|
||||
html << "</div>\n</div></section>\n"
|
||||
html
|
||||
end
|
||||
@@ -339,8 +360,7 @@ module CommunityLanding
|
||||
light = 45 + (group.name.bytes.last.to_i % 12)
|
||||
icon_color = "hsl(#{hue}, #{sat}%, #{light}%)"
|
||||
|
||||
html << "<a href=\"#{login_url}\" class=\"cl-space-card\">\n"
|
||||
html << "<div class=\"cl-space-card__header\" style=\"--space-color: #{icon_color}\">\n"
|
||||
html << "<a href=\"#{login_url}\" class=\"cl-space-card\" style=\"--space-color: #{icon_color}\">\n"
|
||||
html << "<div class=\"cl-space-card__icon\">"
|
||||
if group.flair_url.present?
|
||||
html << "<img src=\"#{group.flair_url}\" alt=\"\">"
|
||||
@@ -348,7 +368,6 @@ module CommunityLanding
|
||||
html << "<span class=\"cl-space-card__letter\">#{group.name[0].upcase}</span>"
|
||||
end
|
||||
html << "</div>\n"
|
||||
html << "</div>\n"
|
||||
html << "<div class=\"cl-space-card__body\">\n"
|
||||
html << "<span class=\"cl-space-card__name\">#{e(display_name)}</span>\n"
|
||||
html << "<span class=\"cl-space-card__sub\">#{group.user_count} members</span>\n"
|
||||
@@ -447,12 +466,15 @@ module CommunityLanding
|
||||
|
||||
# ── Shared helpers ──
|
||||
|
||||
def stat_card(icon_svg, count, label, icon_shape = "circle")
|
||||
def stat_card(icon_svg, count, label, icon_shape = "circle", round_numbers = false)
|
||||
shape_class = icon_shape == "rounded" ? "cl-stat-icon--rounded" : "cl-stat-icon--circle"
|
||||
round_attr = round_numbers ? ' data-round="true"' : ''
|
||||
"<div class=\"cl-stat-card\">\n" \
|
||||
"<div class=\"cl-stat-card__icon-wrap #{shape_class}\">#{icon_svg}</div>\n" \
|
||||
"<div class=\"cl-stat-card__text\">\n" \
|
||||
"<span class=\"cl-stat-card__value\" data-count=\"#{count}\"#{round_attr}>0</span>\n" \
|
||||
"<span class=\"cl-stat-card__label\">#{e(label)}</span>\n" \
|
||||
"<span class=\"cl-stat-card__value\" data-count=\"#{count}\">0</span>\n" \
|
||||
"</div>\n" \
|
||||
"</div>\n"
|
||||
end
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ module CommunityLanding
|
||||
stat_counter = hex(@s.stat_counter_color.presence) rescue nil
|
||||
space_card_bg = hex(@s.groups_card_bg_color.presence) rescue nil
|
||||
topic_card_bg = hex(@s.topics_card_bg_color.presence) rescue nil
|
||||
video_btn_bg = hex(@s.hero_video_button_color.presence) rescue nil
|
||||
accent_rgb = hex_to_rgb(accent)
|
||||
stat_icon_rgb = hex_to_rgb(stat_icon)
|
||||
|
||||
@@ -35,6 +36,7 @@ module CommunityLanding
|
||||
topic_card_bg_val = topic_card_bg || "var(--cl-card)"
|
||||
|
||||
about_bg_extra = about_bg_img ? ", url('#{about_bg_img}') center/cover no-repeat" : ""
|
||||
video_btn_line = video_btn_bg ? "\n --cl-video-btn-bg: #{video_btn_bg};" : ""
|
||||
|
||||
"<style>
|
||||
:root, [data-theme=\"dark\"] {
|
||||
@@ -51,7 +53,7 @@ module CommunityLanding
|
||||
--cl-stat-icon-bg: #{stat_icon_bg_val};
|
||||
--cl-stat-counter-color: #{stat_counter_val};
|
||||
--cl-space-card-bg: #{space_card_bg_val};
|
||||
--cl-topic-card-bg: #{topic_card_bg_val};
|
||||
--cl-topic-card-bg: #{topic_card_bg_val};#{video_btn_line}
|
||||
--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});
|
||||
}
|
||||
@@ -69,7 +71,7 @@ module CommunityLanding
|
||||
--cl-stat-icon-bg: #{stat_icon_bg_val};
|
||||
--cl-stat-counter-color: #{stat_counter_val};
|
||||
--cl-space-card-bg: #{space_card_bg_val};
|
||||
--cl-topic-card-bg: #{topic_card_bg_val};
|
||||
--cl-topic-card-bg: #{topic_card_bg_val};#{video_btn_line}
|
||||
--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});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user