mirror of
https://github.com/dpnmw/community-landing.git
synced 2026-03-18 09:27:16 +00:00
Admin Menu Sorting
Fix broken admin menu sorting and rearrange frontend ui elements
This commit is contained in:
@@ -30,15 +30,18 @@ const TABS = [
|
||||
"hero_video_url", "hero_video_button_color", "hero_video_blur_on_hover",
|
||||
"hero_bg_dark", "hero_bg_light", "hero_min_height", "hero_border_style",
|
||||
"hero_card_bg_dark", "hero_card_bg_light", "hero_card_opacity",
|
||||
"contributors_enabled", "contributors_days", "contributors_count"
|
||||
"contributors_enabled", "contributors_title", "contributors_title_enabled",
|
||||
"contributors_count_label", "contributors_count_label_enabled",
|
||||
"contributors_days", "contributors_count"
|
||||
])
|
||||
},
|
||||
{
|
||||
id: "stats",
|
||||
label: "Stats",
|
||||
settings: new Set([
|
||||
"stats_enabled", "stat_labels_enabled",
|
||||
"stats_title", "stat_icon_color", "stat_icon_bg_color", "stat_icon_shape", "stat_counter_color",
|
||||
"stats_enabled", "stat_labels_enabled", "stats_title_enabled",
|
||||
"stats_title", "stat_card_style",
|
||||
"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_round_numbers",
|
||||
"stats_bg_dark", "stats_bg_light", "stats_min_height", "stats_border_style"
|
||||
@@ -141,31 +144,33 @@ function applyTabFilter() {
|
||||
}
|
||||
});
|
||||
|
||||
// Update filter-active dimming on whichever tab container exists
|
||||
const nativeTabs = container.querySelector(".admin-plugin-config-area__tabs");
|
||||
if (nativeTabs) {
|
||||
nativeTabs.classList.toggle("cl-filter-active", filterActive);
|
||||
// Update filter-active dimming on native nav or standalone tab bar
|
||||
const nativeNav = document.querySelector(".d-nav-submenu__tabs");
|
||||
if (nativeNav) {
|
||||
nativeNav.classList.toggle("cl-filter-active", filterActive);
|
||||
}
|
||||
const standaloneTabs = container.querySelector(".cl-admin-tabs");
|
||||
if (standaloneTabs) {
|
||||
standaloneTabs.classList.toggle("filter-active", filterActive);
|
||||
const standaloneBar = document.querySelector(".cl-admin-tabs");
|
||||
if (standaloneBar) {
|
||||
standaloneBar.classList.toggle("filter-active", filterActive);
|
||||
}
|
||||
}
|
||||
|
||||
function updateActiveStates(activeId) {
|
||||
const container = getContainer();
|
||||
if (!container) return;
|
||||
|
||||
// Update all our injected tabs
|
||||
container.querySelectorAll(".cl-admin-tab").forEach((btn) => {
|
||||
btn.classList.toggle("active", btn.dataset.tab === activeId);
|
||||
// Native nav: our injected <li> tabs
|
||||
document.querySelectorAll("li.cl-admin-tab").forEach((li) => {
|
||||
li.classList.toggle("active", li.dataset.tab === activeId);
|
||||
});
|
||||
|
||||
// Update native Settings link if present
|
||||
const nativeLink = container.querySelector(".cl-native-settings-link");
|
||||
if (nativeLink) {
|
||||
nativeLink.classList.toggle("active", activeId === "settings");
|
||||
// Native nav: the original Settings <li>
|
||||
const nativeItem = document.querySelector(".cl-native-settings-item");
|
||||
if (nativeItem) {
|
||||
nativeItem.classList.toggle("active", activeId === "settings");
|
||||
}
|
||||
|
||||
// Standalone fallback: <button> tabs
|
||||
document.querySelectorAll("button.cl-admin-tab").forEach((btn) => {
|
||||
btn.classList.toggle("active", btn.dataset.tab === activeId);
|
||||
});
|
||||
}
|
||||
|
||||
function findFilterInput(container) {
|
||||
@@ -218,7 +223,6 @@ function buildTabsUI() {
|
||||
if (!container) return false;
|
||||
|
||||
// Already injected — just re-apply filter
|
||||
// Search broadly: native tabs may be a sibling of container, not a child
|
||||
if (document.querySelector(".cl-admin-tab")) {
|
||||
applyTabFilter();
|
||||
return true;
|
||||
@@ -233,35 +237,46 @@ function buildTabsUI() {
|
||||
);
|
||||
if (!hasOurs) return false;
|
||||
|
||||
// ── Strategy 1: Inject into native Discourse tab bar ──
|
||||
// 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");
|
||||
if (nativeLink) {
|
||||
nativeLink.classList.add("cl-native-settings-link", "active");
|
||||
nativeLink.addEventListener("click", (e) => {
|
||||
e.preventDefault();
|
||||
handleTabClick(container, "settings");
|
||||
});
|
||||
// ── Strategy 1: Inject into native Discourse nav tab bar ──
|
||||
// Native structure: <ul class="nav-pills action-list d-nav-submenu__tabs">
|
||||
// <li class="admin-plugin-config-page__top-nav-item"><a>Settings</a></li>
|
||||
const nativeTabsList = document.querySelector(".d-nav-submenu__tabs");
|
||||
if (nativeTabsList) {
|
||||
// Hook the native "Settings" <li> so clicking it activates our Settings tab
|
||||
const nativeSettingsItem = nativeTabsList.querySelector(
|
||||
".admin-plugin-config-page__top-nav-item"
|
||||
);
|
||||
if (nativeSettingsItem) {
|
||||
nativeSettingsItem.classList.add("cl-native-settings-item");
|
||||
const nativeLink = nativeSettingsItem.querySelector("a");
|
||||
if (nativeLink) {
|
||||
nativeLink.addEventListener("click", (e) => {
|
||||
e.preventDefault();
|
||||
handleTabClick(container, "settings");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Inject our section tabs into the native bar (skip "settings" — native link handles that)
|
||||
// Inject our section tabs as <li> items (skip "settings" — native handles it)
|
||||
TABS.forEach((tab) => {
|
||||
if (tab.id === "settings") return;
|
||||
|
||||
const btn = document.createElement("button");
|
||||
btn.className = "cl-admin-tab";
|
||||
btn.textContent = tab.label;
|
||||
btn.dataset.tab = tab.id;
|
||||
btn.addEventListener("click", () => handleTabClick(container, tab.id));
|
||||
nativeTabsEl.appendChild(btn);
|
||||
const li = document.createElement("li");
|
||||
li.className = "admin-plugin-config-page__top-nav-item cl-admin-tab";
|
||||
li.dataset.tab = tab.id;
|
||||
li.title = tab.label;
|
||||
|
||||
const a = document.createElement("a");
|
||||
a.textContent = tab.label;
|
||||
a.addEventListener("click", (e) => {
|
||||
e.preventDefault();
|
||||
handleTabClick(container, tab.id);
|
||||
});
|
||||
|
||||
li.appendChild(a);
|
||||
nativeTabsList.appendChild(li);
|
||||
});
|
||||
|
||||
nativeTabsEl.classList.add("cl-tabs-injected");
|
||||
container.classList.add("cl-tabs-active");
|
||||
wrapBgPairs();
|
||||
applyTabFilter();
|
||||
|
||||
@@ -9,64 +9,31 @@
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* ── Injected tabs inside native Discourse tab bar ── */
|
||||
/* ── Injected tabs inside native Discourse nav bar ──
|
||||
Native structure: <ul class="nav-pills d-nav-submenu__tabs">
|
||||
<li class="admin-plugin-config-page__top-nav-item"><a>Settings</a></li>
|
||||
<li class="admin-plugin-config-page__top-nav-item cl-admin-tab"><a>Hero</a></li>
|
||||
</ul> */
|
||||
|
||||
.admin-plugin-config-area__tabs.cl-tabs-injected {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 0;
|
||||
}
|
||||
|
||||
.admin-plugin-config-area__tabs.cl-tabs-injected .cl-admin-tab {
|
||||
padding: 10px 14px;
|
||||
border: none;
|
||||
background: none;
|
||||
color: var(--primary-medium, #888);
|
||||
font-size: 0.875em;
|
||||
font-weight: 600;
|
||||
.d-nav-submenu__tabs li.cl-admin-tab {
|
||||
cursor: pointer;
|
||||
border-bottom: 2px solid transparent;
|
||||
margin-bottom: -1px;
|
||||
transition: color 0.15s ease, border-color 0.15s ease, opacity 0.15s ease;
|
||||
}
|
||||
|
||||
.admin-plugin-config-area__tabs.cl-tabs-injected .cl-admin-tab:hover {
|
||||
color: var(--primary, #333);
|
||||
}
|
||||
|
||||
.admin-plugin-config-area__tabs.cl-tabs-injected .cl-admin-tab.active {
|
||||
color: var(--tertiary, #0088cc);
|
||||
border-bottom-color: var(--tertiary, #0088cc);
|
||||
}
|
||||
|
||||
/* Native "Settings" link — match our tab styling when active/inactive */
|
||||
.admin-plugin-config-area__tabs.cl-tabs-injected .cl-native-settings-link {
|
||||
transition: color 0.15s ease, border-color 0.15s ease, opacity 0.15s ease;
|
||||
}
|
||||
|
||||
.admin-plugin-config-area__tabs.cl-tabs-injected .cl-native-settings-link:not(.active) {
|
||||
color: var(--primary-medium, #888);
|
||||
border-bottom-color: transparent;
|
||||
.d-nav-submenu__tabs li.cl-admin-tab a {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* Dimmed state when Discourse filter/search is active */
|
||||
.admin-plugin-config-area__tabs.cl-filter-active .cl-admin-tab,
|
||||
.admin-plugin-config-area__tabs.cl-filter-active .cl-native-settings-link {
|
||||
.d-nav-submenu__tabs.cl-filter-active > li {
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
.admin-plugin-config-area__tabs.cl-filter-active .cl-admin-tab.active,
|
||||
.admin-plugin-config-area__tabs.cl-filter-active .cl-native-settings-link.active {
|
||||
.d-nav-submenu__tabs.cl-filter-active > li.active {
|
||||
opacity: 1;
|
||||
border-bottom-color: transparent;
|
||||
}
|
||||
|
||||
/* Dark mode */
|
||||
html.dark-scheme .admin-plugin-config-area__tabs.cl-tabs-injected .cl-admin-tab:hover {
|
||||
color: var(--primary, #ddd);
|
||||
}
|
||||
|
||||
/* ── Standalone tab bar (fallback for older Discourse without native tabs) ── */
|
||||
/* ── Standalone tab bar (fallback for older Discourse without native nav) ── */
|
||||
|
||||
.cl-admin-tabs {
|
||||
display: flex;
|
||||
|
||||
@@ -878,12 +878,21 @@
|
||||
/* ── Hero Creators (top 3 ranked pills in hero) ── */
|
||||
.cl-hero__creators {
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.cl-hero__creators-title {
|
||||
font-size: 0.85rem;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.08em;
|
||||
color: var(--cl-muted);
|
||||
margin: 0 0 0.25rem;
|
||||
}
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════
|
||||
3. COMPACT STATS BAR — icon + count + label inline
|
||||
═══════════════════════════════════════════════════════════════════ */
|
||||
@@ -986,6 +995,45 @@
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
/* Stat card style variants */
|
||||
.cl-stat-card--rectangle {
|
||||
border-radius: var(--cl-radius-sm);
|
||||
}
|
||||
|
||||
.cl-stat-card--rounded {
|
||||
border-radius: 16px;
|
||||
}
|
||||
|
||||
.cl-stat-card--pill {
|
||||
border-radius: 50px;
|
||||
padding: 0.85rem 1.5rem;
|
||||
}
|
||||
|
||||
.cl-stat-card--minimal {
|
||||
background: transparent;
|
||||
border: none;
|
||||
backdrop-filter: none;
|
||||
-webkit-backdrop-filter: none;
|
||||
}
|
||||
|
||||
.cl-stat-card--minimal:hover {
|
||||
background: transparent;
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.cl-stat-card--minimal .cl-stat-card__icon-wrap {
|
||||
background: transparent;
|
||||
color: var(--cl-stat-icon-color);
|
||||
}
|
||||
|
||||
.cl-stat-card--minimal:hover .cl-stat-card__icon-wrap {
|
||||
background: transparent;
|
||||
color: var(--cl-accent);
|
||||
transform: scale(1.15);
|
||||
}
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════
|
||||
4. ABOUT — split layout: image left on gradient, text right
|
||||
═══════════════════════════════════════════════════════════════════ */
|
||||
@@ -1208,16 +1256,18 @@
|
||||
}
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════
|
||||
6. CREATOR PILLS — used in hero section
|
||||
6. CREATOR PILLS — vertical stack in hero section
|
||||
═══════════════════════════════════════════════════════════════════ */
|
||||
.cl-creator-pill {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
padding: 0.6rem 1.25rem 0.6rem 0.6rem;
|
||||
width: 100%;
|
||||
max-width: 340px;
|
||||
background: var(--cl-card);
|
||||
border: 1px solid var(--cl-border);
|
||||
border-radius: 50px;
|
||||
border-radius: 14px;
|
||||
text-decoration: none;
|
||||
position: relative;
|
||||
transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1);
|
||||
@@ -1234,27 +1284,26 @@
|
||||
|
||||
.cl-creator-pill__rank {
|
||||
position: absolute;
|
||||
top: -6px;
|
||||
left: -6px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 50%;
|
||||
top: -8px;
|
||||
right: -8px;
|
||||
padding: 0.15rem 0.5rem;
|
||||
border-radius: 50px;
|
||||
background: var(--rank-color);
|
||||
color: #000;
|
||||
font-size: 0.65rem;
|
||||
font-size: 0.6rem;
|
||||
font-weight: 900;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
letter-spacing: 0.03em;
|
||||
white-space: nowrap;
|
||||
z-index: 2;
|
||||
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.cl-creator-pill__avatar {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
border-radius: 50%;
|
||||
object-fit: cover;
|
||||
flex-shrink: 0;
|
||||
border: 2px solid var(--rank-color, var(--cl-border));
|
||||
transition: border-color 0.3s ease;
|
||||
}
|
||||
@@ -1263,24 +1312,27 @@
|
||||
border-color: var(--rank-color, var(--cl-accent));
|
||||
}
|
||||
|
||||
.cl-creator-pill__info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-width: 0;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.cl-creator-pill__name {
|
||||
font-size: 0.95rem;
|
||||
font-size: 0.9rem;
|
||||
font-weight: 700;
|
||||
color: var(--cl-text-strong);
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.cl-creator-pill__count {
|
||||
font-size: 0.8rem;
|
||||
font-size: 0.75rem;
|
||||
color: var(--cl-accent);
|
||||
white-space: nowrap;
|
||||
font-weight: 800;
|
||||
margin-left: auto;
|
||||
padding: 0.15rem 0.6rem;
|
||||
min-width: 1.5em;
|
||||
text-align: center;
|
||||
background: var(--cl-accent-subtle);
|
||||
border-radius: 50px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════
|
||||
|
||||
Reference in New Issue
Block a user