Hi there @SYZYGY .
Great question, it’s always good to take that into account before undertaking changes like this. In this case I’m not making a new theme, and I expect the additions to survive future updates from Discourse. Basically here’s how configuration works in Discourse:
- Themes are all-inclusive, with HTML and CSS that affects the layout and can add/remove visual elements. The default BLF theme is “Sam’s Simple Theme” from one of the Discourse co-founders. When using properly supported 3rd-party themes like this they can be update automatically from their upstream source independently or in tandem with a Discourse core update, but always remain independent (i.e. a Discourse update doesn’t overwrite them). This isn’t the case with some forum platforms, so keep an eye on that.
- Theme components can be created from upstream repositories or created from scratch, and they can be associated independently with any or all of the installed themes. They allow for applying CSS rules that will override the rules if they already exist in the base theme that is in use. If there are absolute color definitions defined these will override the Discourse color scheme that is in use. They can also inject JS into different sections of the page.
- Color schemes define a small selection of color variables, and most themes obey them and/or use lighter versions of those base colors for some elements. Color schemes can be married to themes and the user can choose them independently of the theme.
So to apply TK’s “theme” (which is actually a massive set of CSS rules, and not the same as a Discourse theme) I first installed a duplicate copy of “Sam’s Simple Theme” (which will continue to receive updates whenever he commits them) and renamed it to “ToyKeeper’s Theme”, and then I created a new theme component associated with “ToyKeeper’s Theme” and in the theme component I simply pasted in TK’s CSS rules into the GUI for CSS overrides in the theme component.
That would be this monstrosity here. It’s actually inspired by the cleanest and most effective code example I could find on Discourse Meta for accomplishing a similar task, but it’s still really ugly because we’re still in the early days of the Discourse sidebar and it’s not set up yet for customization. The following code gets added to the “Head” section of a theme component that I associated with the default BLF Theme to add all sorts of random tweaks and overrides:
<script>
const links1 = [
// FontAwesome icons may need to be added in the site settings if they don't correctly appear
{ title: "BLF Rules", src: "/rules", icon: "gavel" },
{ title: "Commercial Sellers", src: "/commercial", icon: "gift" },
{ title: "Related Sites", src: "/related-sites", icon: "globe" },
{ title: "Contact the Admin", src: "/new-message?username=sb56637", icon: "envelope" }
]
const links2 = [
// FontAwesome icons may need to be added in the site settings if they don't correctly appear
{ title: "My Activity", src: "/my/activity", icon: "" },
{ title: "My Participation", src: "/search?expanded=false&q=in%3Aposted%20order%3Alatest", icon: "" },
{ title: "My Watched Threads", src: "/latest?order=activity&state=watching", icon: "" },
{ title: "My Tracked Threads", src: "/latest?order=activity&state=tracking", icon: "" }
]
$(document).ready(function () {
if (document.getElementById("toggle-hamburger-menu")) {
// We're in mobile view
addToggleListener(document.getElementById("toggle-hamburger-menu"))
} else {
// We're in desktop view
addToggleListener(document.getElementsByClassName("btn-sidebar-toggle")[0])
addCustomLinks1()
addCustomLinks2()
}
function addToggleListener(toggleEl) {
if (toggleEl) {
toggleEl.addEventListener("click", function () {
// Wait a bit for the sidebar to load
setTimeout(function() {
let sidebar = document.getElementsByClassName("sidebar-section-header").length
if (sidebar) {
addCustomLinks1()
addCustomLinks2()
}
}, 100)
})
}
}
function addCustomLinks1() {
// Wait a bit until navigation has been loaded
setTimeout(function () {
const parentEl = document.getElementsByClassName("sidebar-section-content")[0]
let linksAlreadyAdded = document.getElementsByClassName("sidebar-section-custom-link1").length
if (parentEl && !linksAlreadyAdded) {
links1.filter(function (link) {
let linkDiv = document.createElement("li")
let linkTitleTrim = link.title.replace(/\s+/g, '')
linkDiv.className = "sidebar-section-link-wrapper sidebar-section-custom-link1"
linkDiv.innerHTML = `<a href="${link.src}" class="sidebar-section-link sidebar-section-link-everything sidebar-row ember-view">
<span class="sidebar-section-link-prefix icon" id="link_${linkTitleTrim}"></span>
<span class="sidebar-section-link-content-text"> ${link.title} </span>
</a>
`
parentEl.append(linkDiv)
let linkIcon = document.getElementById("link_" + linkTitleTrim)
if (linkIcon && link.icon) {
linkIcon.innerHTML = `<svg viewBox="0 0 640 512" class="fa d-icon svg-icon prefix-icon svg-string d-icon-${link.icon}" xmlns="http://www.w3.org/2000/svg">
<use xlink:href="#${link.icon}"></use>
</svg>
`
}
})
}
}, 100)
}
function addCustomLinks2() {
// Wait a bit until navigation has been loaded
setTimeout(function () {
const customHeader = document.createElement("div")
customHeader.className = "sidebar-section-wrapper sidebar-section-blf"
customHeader.innerHTML = `
<div class="sidebar-section-header-wrapper sidebar-row">
<span class="sidebar-section-header-caret">
<svg class="fa d-icon d-icon-angle-down svg-icon svg-string" xmlns="http://www.w3.org/2000/svg"><use href="#angle-down"></use></svg>
</span>
<button id="ember11" class="sidebar-section-header sidebar-section-header-collapsable btn-flat btn no-text" type="button">
<span class="sidebar-section-header-text"> My Links </span>
</button>
</div>
<div class="sidebar-section-blf" id="customNavigation"/>
`
const sidebar = document.getElementsByClassName("sidebar-sections")[0]
sidebar.prepend(customHeader)
const parentEl = document.getElementsByClassName("sidebar-section-blf")[0]
let linksAlreadyAdded = document.getElementsByClassName("sidebar-section-custom-link2").length
if (parentEl && !linksAlreadyAdded) {
links2.filter(function (link) {
let linkDiv = document.createElement("li")
let linkTitleTrim = link.title.replace(/\s+/g, '')
linkDiv.className = "sidebar-section-link-wrapper sidebar-section-custom-link2"
linkDiv.innerHTML = `<a href="${link.src}" class="sidebar-section-link sidebar-section-link-everything sidebar-row ember-view">
<span class="sidebar-section-link-prefix icon" id="link_${linkTitleTrim}"></span>
<span class="sidebar-section-link-content-text"> ${link.title} </span>
</a>
`
parentEl.append(linkDiv)
let linkIcon = document.getElementById("link_" + linkTitleTrim)
if (linkIcon && link.icon) {
linkIcon.innerHTML = `<svg viewBox="0 0 640 512" class="fa d-icon svg-icon prefix-icon svg-string d-icon-${link.icon}" xmlns="http://www.w3.org/2000/svg">
<use xlink:href="#${link.icon}"></use>
</svg>
`
}
})
let theUl = document.createElement("ul")
theUl.className = "sidebar-section-content"
parentEl.append(theUl)
}
}, 100)
}
})
</script>
Oh, and it also requires some CSS overrides too in the same theme component :
.sidebar-section-categories {
display: flex; /* Setup a flex layout so you can reorder things */
flex-direction: column;
order: +1;
}
.sidebar-section-tags {
display: flex; /* Setup a flex layout so you can reorder things */
flex-direction: column;
order: +1;
}
.sidebar-section-blf {
display: flex; /* Setup a flex layout so you can reorder things */
flex-direction: column;
order: +1;
}
.sidebar-section-content {
display: flex; /* Setup a flex layout so you can reorder things */
flex-direction: column;
.sidebar-more-section-links-details {
order: +1;
}
}
.sidebar-section-message {
display: none;
}
.sidebar-wrapper li a.sidebar-section-link-about {
display: none;
}
.sidebar-wrapper li a.sidebar-section-link-faq {
display: none;
}
.sidebar-more-section-links-details-content-secondary .sidebar-section-link.sidebar-section-link-about {
display: none;
}
.sidebar-more-section-links-details-content-secondary .sidebar-section-link.sidebar-section-link-faq {
display: none;
}