FKB Pro – Soziales Theme

Das einzige kleine Problem mit dem SCSS-Code ist, dass es keine automatische Zeilenumbruch gibt, sodass die Wörter abgeschnitten werden :wink:

Was meinst du? Kannst du einen Screenshot schicken?

Hier ist ein Screenshot meines Handys. Man erkennt, dass der Name der Kategorie nicht vollständig angezeigt wird

1 „Gefällt mir“

Dieses Verhalten ist im Kernabschnitt beabsichtigt. Wenn du jedoch möchtest, dass der Kategorie-Name auf eine neue Zeile umgebrochen wird, anstatt abgeschnitten zu werden, kannst du Folgendes versuchen:

.category-heading {
  &.--has-logo {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    gap: var(--space-4);
  }
  &__content {
    min-width: 0;
    .badge-category__wrapper {
      max-width: 100%;
      white-space: normal;
      overflow-wrap: anywhere;
      .badge-category {
        &.--style-emoji,
        &.--style-icon {
          align-items: baseline;
        }
      }
    }
  }
}
3 „Gefällt mir“

Super, es funktioniert! @Don, du bist ein Meister :clap:

1 „Gefällt mir“

Ich habe bemerkt, dass in der Tablet-Version die Kategoriebeschreibung fehlt, während sie in der mobilen Version vorhanden ist. Ich denke, es wäre sinnvoll, auch in der mobilen Version dasselbe zu tun. :thinking:

Ich habe auch bemerkt, dass es bei der Verwendung von verschachtelten Antworten ein kleines Anzeigeproblem mit dem Avatar gibt, der etwas zu groß dargestellt wird.

Weiß jemand, ob mir das allein so vorkommt?

Danke @gilles! Ich habe ein Update dafür zusammengeführt…

2 „Gefällt mir“

Ich habe es getestet und alles funktioniert. Danke @Don für deine schnelle Reaktion :clap: :+1:

1 „Gefällt mir“

@Don ich habe einen kleinen Darstellungsfehler im Desktop-Modus auf dem Computer ohne Seitenleiste festgestellt, nur zur Info :wink:

1 „Gefällt mir“

Danke, ich habe es hier behoben: FIX: Enhance category heading styles in SCSS · VaperinaDEV/fkb-pro-theme@95a3c25 · GitHub

4 „Gefällt mir“

Getestet und genehmigt :+1:

1 „Gefällt mir“

Ich habe das gerade installiert. Ich bin mir ziemlich sicher, dass direkt nach der Installation ein Fakebook-Panel auf der rechten Seite war, aber bei mir scheint es verschwunden zu sein. Ich weiß nicht, was ich geändert habe, damit es verschwindet, und wie ich es zurückbekomme.

Hallo :waving_hand: Unten rechts gibt es einen Button, um diesen Abschnitt ein- oder auszublenden.

Ich habe das Theme aktualisiert: DEV: Improve FKB panel and right sidebar layout handling - Pull Request #78 - VaperinaDEV/fkb-pro-theme - GitHub

2 „Gefällt mir“

Ah, da ist er ja – danke! Hmm, muss ich ihn wohl versehentlich gedrückt haben? Oder wurde er deaktiviert, als ich das auf dem Mobilgerät aufgerufen habe? Ich werde ein paar Versuche machen und mich dann wieder melden.

1 „Gefällt mir“

Ja, auf dem Handy wird es nicht angezeigt.

Ja, natürlich.

Ich hatte mir überlegt, dass es möglich ist, dass es für mich auf dem Desktop deaktiviert wurde, als ich unser Forum auf dem Mobilgerät las. Ich habe den Test gerade durchgeführt, und das Panel wurde nicht deaktiviert. Wie also mein Panel auf dem Desktop deaktiviert wurde, bleibt ein Rätsel – ich muss versehentlich auf den Deaktivierungs-Pfeil geklickt haben.

1 „Gefällt mir“

Hi Don! Ich finde das FKB Pro Theme einfach super.

Kleine Bitte: Wäre es möglich, eine Einstellung hinzuzufügen, die mehrere Teilnehmer-Avatare auf den Themenkarten anzeigt, statt nur den letzten Poster?

Der einzelne Avatar sieht zwar sehr clean aus, aber mehrere Teilnehmer zu zeigen, unterstreicht wirklich, wie aktiv eine Diskussion ist. Ein Schalter dafür wäre großartig!

Danke für deine tolle Arbeit! Leo

Hallo @Don, ich habe eine kleine persönliche Anpassung am FKB Pro-Theme vorgenommen, um einen schwebenden Chat-Button hinzuzufügen: auf Tablet und Desktop unten rechts und auf dem Handy unten links, mit demselben Effekt wie beim Button „Thema erstellen“. Ich denke, im Code ginge es besser, aber so funktioniert es: :rofl:

Hier ist mein Komponenten-Code: css


// 1. HAUPTSCHWEBENDER BUTTON 
.header-dropdown-toggle.chat-header-icon {
    position: fixed !important;
    bottom: 60px !important;
    right: 20px !important;
    z-index: 9999 !important;
    
    /* Perfekte Maße (Kreis) */
    width: 60px !important;
    height: 60px !important;
    min-width: 60px !important;
    min-height: 60px !important;
    border-radius: 50% !important;
    
    /* Leuchtendes Blau und farbiger Schatten */
    background: #0084ff !important;
    box-shadow: 0 4px 14px rgba(0, 132, 255, 0.4), 0 2px 4px rgba(0, 0, 0, 0.1) !important;
    
    /* Aufräumen der Abstände */
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
    padding: 0 !important;
    margin: 0 !important;
    border: none !important;
    
    /* Fließender Übergang */
    transition: transform 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275), opacity 0.3s ease, box-shadow 0.2s ease !important;
}

/* Spezifische Position auf Mobile (Bildschirme <= 640px) */
@media (max-width: 640px) {
    .header-dropdown-toggle.chat-header-icon {
        bottom: 80px !important; 
        left: 20px !important;   /* Ändere zu right: 20px, wenn du es lieber rechts haben möchtest */
    }
}

/* Hover-Effekt (leichte Vergrößerung) */
.header-dropdown-toggle.chat-header-icon:hover {
    transform: scale(1.08) !important;
    box-shadow: 0 6px 20px rgba(0, 132, 255, 0.5), 0 4px 8px rgba(0, 0, 0, 0.15) !important;
}


/* 2. AUFRÄUMEN DES NATIVEN GRÜNEN HINTERGRUNDS VON DISCOURSE                 */

.header-dropdown-toggle.chat-header-icon .icon,
.header-dropdown-toggle.chat-header-icon span:not(.badge-notification):not(.chat-badge):not([class*="unread"]):not([class*="count"]) {
    background-color: transparent !important;
    box-shadow: none !important;
    border: none !important;
}


/* 3. PERFEKTES ZENTRIEREN DES ICONS (Die Blase)                  */

.header-dropdown-toggle.chat-header-icon .d-icon,
.header-dropdown-toggle.chat-header-icon svg {
    position: absolute !important;
    top: 50% !important;
    left: 50% !important;
    transform: translate(-50%, -50%) !important; 
    
    margin: 0 !important;
    padding: 0 !important;
    width: 32px !important;
    height: 32px !important;
    color: #ffffff !important;
    
    filter: drop-shadow(0 2px 2px rgba(0, 0, 0, 0.1)) !important;
}


/* 4. BENACHRICHTIGUNGS-BADGE (Grüner Zähler + sichtbare Zahl) */

.header-dropdown-toggle.chat-header-icon .badge-notification,
.header-dropdown-toggle.chat-header-icon .chat-badge,
.header-dropdown-toggle.chat-header-icon .unread-notifications,
.header-dropdown-toggle.chat-header-icon [class*="badge"],
.d-header-icons .header-dropdown-toggle.chat-header-icon .badge-notification {
    position: absolute !important;
    top: -4px !important;
    right: -4px !important;
    left: auto !important;
    margin: 0 !important;
    z-index: 10 !important; 
    
    /* Erzwungene grüne Farbe */
    background-color: #53A548 !important;  
    background: #53A548 !important;
    color: #ffffff !important;
    
    /* Erzwungene Typografie, um die Zahl sichtbar zu machen */
    font-size: 13px !important;
    font-weight: bold !important;
    line-height: 18px !important;
    letter-spacing: normal !important;
    text-indent: 0 !important;
    
    /* Maße und Form */
    padding: 0 6px !important;
    min-width: 22px !important;
    height: 22px !important;
    border-radius: 50px !important;
    border: 2px solid #ffffff !important;
    box-sizing: border-box !important;
    
    /* Zentrieren der Zahl */
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
    white-space: nowrap !important;
    overflow: visible !important;
    
    /* Grüne Puls-Animation (verknüpft mit deinen Keyframes) */
    animation: badge-pulse 2s infinite !important; 
}

/* Erzwingt, dass alle Kind-Elemente (falls Discourse die Zahl in ein span einbettet) angezeigt werden */
.header-dropdown-toggle.chat-header-icon .badge-notification *,
.header-dropdown-toggle.chat-header-icon .chat-badge *,
.header-dropdown-toggle.chat-header-icon [class*="badge"] * {
    color: #ffffff !important;
    background: transparent !important;
    display: inline-block !important;
    visibility: visible !important;
    opacity: 1 !important;
    font-size: inherit !important;
}

/* 5. KORRIGIERTE ANIMATIONEN (Radar-Effekt & Bounce)            */


/* 5.1 - Die Radarwelle (Puls) um das rote Badge */
.header-dropdown-toggle.chat-header-icon .badge-notification,
.header-dropdown-toggle.chat-header-icon .chat-badge,
.header-dropdown-toggle.chat-header-icon .chat-channel-unread-indicator {
    animation: badge-pulse 2s infinite !important;
    transform-origin: center !important;
}

/* 5.2 - Bounce-Effekt auf den gesamten blauen Button, wenn eine Nachricht vorliegt */
.header-dropdown-toggle.chat-header-icon:has(.badge-notification),
.header-dropdown-toggle.chat-header-icon:has(.chat-badge),
.header-dropdown-toggle.chat-header-icon:has(.chat-channel-unread-indicator) {
    animation: chat-bounce 3s infinite !important;
}

/* --- DEFINITION DER KEYFRAMES (Nicht ändern) --- */

/* Definition der Welle: Wir nutzen nur box-shadow, um Darstellungsfehler zu vermeiden */
@keyframes badge-pulse {
    0% {
        box-shadow: 0 0 0 0 rgba(250, 62, 62, 0.8);
    }
    70% {
        box-shadow: 0 0 0 10px rgba(250, 62, 62, 0);
    }
    100% {
        box-shadow: 0 0 0 0 rgba(250, 62, 62, 0);
    }
}

/* Definition des Bounce: Der Button hüpft alle 3 Sekunden leicht */
@keyframes chat-bounce {
    0%, 20%, 50%, 80%, 100% { 
        transform: translateY(0); 
    }
    40% { 
        transform: translateY(-6px); 
    }
    60% { 
        transform: translateY(-3px); 
    }
}

/* 6. PULSATION IN DER KANAL- UND PRIVATNACHRICHTENLISTE  */


/* 6.1 - Überlauf für Listencontainer erlauben */
.chat-channel-row,
.chat-channel-list-item,
.chat-drawer-container .chat-channel-unread-indicator,
.chat-channel-row .chat-channel-unread-indicator {
    overflow: visible !important;
}

/* 6.2 - Stil und Abstände des Indikator-Punkts */
.chat-channel-row .chat-channel-unread-indicator,
.chat-channel-row .badge-notification,
.chat-channel-row .unread-indicator,
.chat-drawer-container .chat-channel-unread-indicator,
.chat-full-page .chat-channel-unread-indicator,
.chat-channel-list-item .chat-channel-unread-indicator {
    animation: list-dot-pulse 1.8s infinite !important;
    border-radius: 50% !important;
    position: relative !important;
    overflow: visible !important;
    margin: 0 6px !important; /* Abstand, damit es nicht an Text und Datum klebt */
}

/* 6.3 - Angepasste Animation (kompaktere Welle, max. 6px) */
@keyframes list-dot-pulse {
    0% {
        box-shadow: 0 0 0 0 rgba(0, 132, 255, 0.7); /* Passt sich der Farbe des Punkts an */
    }
    70% {
        box-shadow: 0 0 0 6px rgba(0, 132, 255, 0); /* Reduzierter Radius, um in der Zeile zu bleiben */
    }
    100% {
        box-shadow: 0 0 0 0 rgba(0, 132, 255, 0);
    }
}

und das JS:

import { apiInitializer } from "discourse/lib/api";

export default apiInitializer((api) => {
    let lastScrollTop = 0;
    let isHiddenByScroll = false;

    // 1. Scroll-Handler (NUR auf Mobile aktiv)
    window.addEventListener("scroll", () => {
        const isMobile = window.innerWidth <= 640;
        const floatBtn = document.querySelector('.header-dropdown-toggle.chat-header-icon');

        if (!floatBtn) return;

        // Wenn wir auf einem Desktop sind, stellen wir sicher, dass der Button immer sichtbar bleibt
        if (!isMobile) {
            if (isHiddenByScroll) {
                floatBtn.style.setProperty('transform', 'translateY(0) scale(1)', 'important');
                floatBtn.style.setProperty('opacity', '1', 'important');
                isHiddenByScroll = false;
            }
            return;
        }

        const currentScrollTop = window.pageYOffset || document.documentElement.scrollTop;

        // Wenn wir nach unten scrollen (und 100px überschritten haben)
        if (currentScrollTop > lastScrollTop && currentScrollTop > 100) {
            if (!isHiddenByScroll) {
                floatBtn.style.setProperty('transform', 'translateY(100px) scale(0.8)', 'important');
                floatBtn.style.setProperty('opacity', '0', 'important');
                isHiddenByScroll = true;
            }
        } 
        // Wenn wir nach oben scrollen
        else if (currentScrollTop < lastScrollTop) {
            if (isHiddenByScroll) {
                floatBtn.style.setProperty('transform', 'translateY(0) scale(1)', 'important');
                floatBtn.style.setProperty('opacity', '1', 'important');
                isHiddenByScroll = false;
            }
        }
        lastScrollTop = currentScrollTop <= 0 ? 0 : currentScrollTop;
    }, { passive: true });

    // 2. MutationObserver zum Verwalten der Basis-Anzeige
    const observer = new MutationObserver(() => {
        const chatOpen = document.querySelector('.chat-drawer, .d-chat-floating-panel, .chat-widget, .chat-panel, .chat-out-of-container, .chat-full-page');
        const isChatRoute = window.location.pathname.startsWith('/chat');
        const hasFullPageClass = document.body.classList.contains('has-full-page-chat');
        
        const isMobile = window.innerWidth <= 640;
        const isTopicRoute = window.location.pathname.includes('/t/') || document.body.classList.contains('archetype-regular');
        const hideOnMobileTopic = isMobile && isTopicRoute;

        const floatBtn = document.querySelector('.header-dropdown-toggle.chat-header-icon');
        
        if (floatBtn) {
            if (chatOpen || isChatRoute || hasFullPageClass || hideOnMobileTopic) {
                floatBtn.style.setProperty('display', 'none', 'important');
            } else {
                floatBtn.style.setProperty('display', 'flex', 'important');
                
                // Saubere Verwaltung der Mobile-/Desktop-Position
                if (isMobile) {
                    floatBtn.style.setProperty('left', '10px', 'important'); // Wert ändern, wenn du es weiter verschieben möchtest
                    floatBtn.style.removeProperty('right');
                } else {
                    floatBtn.style.setProperty('right', '20px', 'important');
                    floatBtn.style.removeProperty('left');
                }
            }
        }
    });

    observer.observe(document.body, { childList: true, subtree: true, attributes: true });
});