This only works with the site setting desktop category page style set to boxes with subcategories (as it replaces that category page template).
The category collapsing works using your browserâs local storage, so the collapsed state will not be remembered between different devices.
This theme comes with some settings:
category groups - this is how the groups are configured, the setting is formatted as: Category group name: category-slug, category-slug-2, category-slug-3. The category slug is the name of the category as itâs seen in URLs⊠usually all lowercase with no spaces.
show on mobile - if you want to use default category page on mobile, disable this
show ungrouped - this will show all categories not assigned to a group in an âOtherâ group. The name of this group is configurable.
fancy styling - these are some custom styles I added, they stray from our defaults so if youâre working on your own theme you may want to disable this.
There is another component that can group categories and/or subcategories grouped under headers. It is in the Air Full Theme called Modern Category Boxes.
However it could use the collapsible feature and more importantly @awesomerobot 's really cool option to setup category lists for groups.
As for the collapsed stated being remembered woild require additional work as Kris mentioned that this one uses the browser and as such cannot remember last state.
This looks excellent. Iâm getting a error message though.
_vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:4069 Uncaught TypeError: Cannot read properties of undefined (reading âindexOfâ)
at a01db7fd83ffd5f3e61e767c85767c217dfa7e0b.js?__ws=publichappinessmovement.com:65
at _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:39290
at n.t.Mixin.create.c.forEach (_vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:39269)
at n.t.Mixin.create.c.filter (_vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:39289)
at a01db7fd83ffd5f3e61e767c85767c217dfa7e0b.js?__ws=publichappinessmovement.com:64
at Array.forEach ()
at n.catGroupList (a01db7fd83ffd5f3e61e767c85767c217dfa7e0b.js?__ws=publichappinessmovement.com:63)
at n. (_application-ecf386baee119f56a21f6f58e1d96e70e4a129de99451ee32e6eb4304d6749fa.js:1980)
at n.i.get (_vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:28802)
at Je (_vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:27908)
(anonymous) @ a01db7fd83ffd5f3e61e767c85767c217dfa7e0b.js?__ws=publichappinessmovement.com:65
(anonymous) @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:39290
t.Mixin.create.c.forEach @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:39269
t.Mixin.create.c.filter @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:39289
(anonymous) @ a01db7fd83ffd5f3e61e767c85767c217dfa7e0b.js?__ws=publichappinessmovement.com:64
catGroupList @ a01db7fd83ffd5f3e61e767c85767c217dfa7e0b.js?__ws=publichappinessmovement.com:63
(anonymous) @ _application-ecf386baee119f56a21f6f58e1d96e70e4a129de99451ee32e6eb4304d6749fa.js:1980
i.get @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:28802
Je @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:27908
r.compute @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:13922
t.value @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:13745
t.iterate @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:17698
t.isEmpty @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:59327
e.value @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:61661
t.initialize @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:59239
t.peek @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:59214
(anonymous) @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:60425
t.evaluate @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:59648
t.evaluateSyscall @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:63063
t.evaluateInner @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:63009
t.evaluateOuter @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:63001
o.next @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:65133
e.next @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:65235
render @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:19347
V @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:26194
t._renderRoots @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:19646
t._renderRootsTransaction @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:19684
t._renderRoot @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:19607
t._appendDefinition @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:19525
t.appendOutletView @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:19511
t.invoke @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:66552
t.flush @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:66442
t.flush @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:66646
n._end @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:67222
n.end @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:66908
n._run @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:67277
n._join @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:67251
n.join @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:66968
f @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:53760
(anonymous) @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:53864
l @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:3776
c @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:3844
setTimeout (async)
w.readyException @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:4068
(anonymous) @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:4088
l @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:3776
c @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:3844
setTimeout (async)
(anonymous) @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:3882
u @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:3510
fireWith @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:3640
fire @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:3648
u @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:3510
fireWith @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:3640
c @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:3864
setTimeout (async)
(anonymous) @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:3882
u @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:3510
fireWith @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:3640
fire @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:3648
u @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:3510
fireWith @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:3640
ready @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:4120
z @ _vendor-ccc170ebd7d3ab2d70c3e0c52d1121e7ced023e6ed05de129e0060c2a71ba2e3.js:4130
Show 12 more frames
_dcs-discourse-plugin-3bb7d5768f0608bcdfcf8e6c4a9a3fcfec150551e407c8d9173d7ba14849ccc8.js:3078 Uncaught (in promise) TypeError: Cannot read properties of undefined (reading âsetLayoutâ)
at _dcs-discourse-plugin-3bb7d5768f0608bcdfcf8e6c4a9a3fcfec150551e407c8d9173d7ba14849ccc8.js:3078
It worked initially, for 5 mins and then stopped working. I turned off anything that was likely to be conflicting with it with no luck. Iâm running the latest version of this and discourse.
Update: Iâm not confident, but i think the issue is related to category slugs. The slugs which were default slugs were showing up in every grouping, so i changed them from the number format to a text string and the component began behaving correctly.
Update 2: Iâm pretty confident now as iâve recreated it in different ways. If the slug contains numbers it breaks the component.
I also see a small conflict with Agenda, and the Kanban plugin.
In both cases the categories and group title are injected above the main element users would expect to see on that page. Its closed in this image but all sub categories in the group appear here when the dropdown is open. Expected behaviour would be either not to show at all on this page, or to be below the agenda/kanban board.
Hah, this is perfect Kris, I just moved to this from the css hack for my categories
My one request if this is ever added too, would be to allow an easier way in the settings to re-order the groups. Right now it looks like if I wanted to move a category group to the top, I would have to delete them all. Luckily thatâs not a big deal at the end of the day
Another setting that would be cool would be to let a var in the settings configure how many grid columns ( luckily just a 2 second override in css handles this) but could see that being useful for people who donât know that
ââââ
Thanks again for this fantastic component , already loving it and have it setup perfectly
This may need to be a general Discourse feature request and this will be the incorrect place to ask/discuss this question:
Is there a way to have theme components (such as this) have their settings unique to each theme?
For example, We will have a single discourse forum that supports multiple sites. The end goal was to have a unique theme that the user can choose, based on the main âsiteâ they are using the forum for.
In context to this component: It would be really powerful, if we could change the settings of a theme component, for each theme that uses it, In this case, I could change the order of the Category groups based on the theme picked. So if theme Y is picked, the categories based on Y would now be ordered at the top, as that is how it is configured for this theme component for that theme.
Hey,
i found the same need, so i opened a PR on GitHub.
Edit: Actually I thought of reordering within the group, which was completely missing before too. So sorry for this wrong reply. Deleting entire categories to reorder them also just isnât a viable solution
Please feel free to check it out in case you need that functionality.
hi @awesomerobot I just discovered this theme component and find it really interesting. One thing that is weird though: how do you order the categories in each group? I put them in a certain order, but when itâs displayed, that order is not respected.
Did I do something wrong, or are they automagically ordered?
I believe the categories will be ordered by most recent activity. To get a consistent order youâd have to enable the site setting fixed category positions â at that point you can order them from this menu on the upper right of the /categories page:
Ohh thanks, this also solves my problem. I had fixed category positions enabled, but i did not know i could also reorder them like this
This is definitely the better approach, i will close my PR.