[2.x] fix: blank index title control when no nav item is active - #4821
[2.x] fix: blank index title control when no nav item is active#4821karl-bullock wants to merge 1 commit into
Conversation
imorland
left a comment
There was a problem hiding this comment.
Thanks for the thorough writeup — the root-cause analysis here is spot on, and I verified it: SelectDropdown.getButtonContent() derives the label purely from the active child and the nav dropdown passes no defaultLabel, so an unlisted current tag → no active child → blank title. That part's not in question.
Where I'd push back is the layer this is fixed at. Adding the current tag to the nav list doesn't only restore the title — it makes the current tag appear in the index sidebar (desktop and mobile) whenever you're on its page, when it otherwise wouldn't be listed. That's a visible behaviour change to the sidebar beyond the reported bug, and it's the kind of thing that should be a deliberate product decision rather than a side effect of a title fix.
Digging into alternatives, they all felt like they were compensating for the same underlying thing rather than fixing it:
- Passing a
defaultLabelfrom the tags extension — the natural "show the tag name" approach — isn't cleanly reachable: the navSelectDropdownis built inline inIndexSidebar.items()with no hook to supply a per-page label, andextend()can't customise a scalar return, so it'd force anoverride(). - A hardcoded core
defaultLabel("All Discussions") fixes the blank but shows a slightly-wrong title on tag pages, and still leaves the door open on other consumers. - Making the label an
ItemListso it'sextend()-able is really just a single value wearing a list costume — a smell of its own.
The common thread is that they're all working around the title control having nothing to show when no item is active, rather than addressing why it ends up with nothing to show — and the tags list is just what happens to expose it.
Could you take another pass at this? The constraints I'd want a fix to meet: it shouldn't change what appears in the sidebar, it should hold for any consumer that hits the empty-label case (not just tags), and it should avoid an override(). Worth agreeing the approach here before you rebuild it, rather than reworking the current one.
|
Thanks, this is fair. I agree the sidebar behaviour change is the real problem with the current patch: adding the tag to the list to recover the title conflates two separate things. Working within your three constraints (no sidebar change, holds for any consumer, no
So the fix I would propose: 1. Core — defaultLabel={app.current.get('title') ?? app.translator.trans('core.forum.index.all_discussions_link')}That resolves the empty-label case for any consumer, adds nothing to the sidebar, and needs no override. 2. Tags — on a tag page, Net result: an unlisted tag page shows the tag name, the plain index shows "All Discussions", and any other extension caught in the same empty-label spot can set its own page title or fall back to the default. No sidebar change, no The one thing I would want your call on before I rebuild is the |
|
This looks great — thanks for taking it back to the cause rather than working around it. The On the key: agreed that Go ahead and rebuild on that. 👍 |
The index toolbar title (the nav SelectDropdown, App-titleControl) renders blank on any page that filters the discussion list without contributing a nav item of its own. SelectDropdown labels its button with the first active child and falls back to defaultLabel, but IndexSidebar never passed the (required) defaultLabel, so with no active child the label collapsed to nothing and only the sort caret was left. Pass a defaultLabel from IndexSidebar, read from the current page via app.current with the index's own link as the fallback. A page in the empty-label case can now name itself by setting titleControlLabel, and anything else falls back to "All Discussions". This is label-only, so the sidebar is untouched, and it needs no override(). Use that from tags, which is where the bug was reported: addTagList lists primary tags plus only the 3 most discussed secondary tags, so the current tag has no nav item whenever it falls outside those filters, and the set of affected tags shifts as discussion counts change. On a tag page we now set titleControlLabel to the tag name, which surfaces precisely when no item is active while a listed tag still wins through its own active item. Fixes flarum#4819
a5784ab to
13e80d3
Compare
|
Rebuilt on On the three constraints:
Added One thing worth your eye, since it is the only call I had to make that had not already come up: the tags side sets the label from an |
Fixes #4819
What / why
On phone-width viewports the index toolbar title (the nav
SelectDropdown,App-titleControl) renders blank on tag pages whenever the current tag has no item in the index sidebar nav. In practice that means any secondary tag that is not among the 3 most discussed secondary tags, so the set of affected tags shifts as discussion counts change and the bug looks random from an admin's point of view.Root cause
SelectDropdown.getButtonContent()uses the label of the first active child and falls back toattrs.defaultLabel.defaultLabelis declared required onISelectDropdownAttrs, but the nav dropdown built inIndexSidebar.items()never passed one. When no child is active the label collapses to nothing and only the sort caret is left.Tags is what exposes it:
addTagListadds primary tags plus the top 3 secondary tags bydiscussionCount(), so a tag outside those filters contributes no nav item and nothing is active.Fix
Two parts, following the approach agreed in review:
Core.
IndexSidebarnow passes adefaultLabelto the navSelectDropdown, read from the current page with the index's own link as the fallback:This resolves the empty-label case for any consumer, not just tags. A page that filters the discussion list without contributing a nav item can name itself by setting
titleControlLabelonapp.current, which is the existing channel a page uses to hand context to other components. Anything that does not falls back to "All Discussions".Tags. On a tag page, set
app.current.set('titleControlLabel', tag.name()). BecausegetButtonContent()only reaches fordefaultLabelwhen no child is active, this surfaces the tag name precisely in the unlisted-tag case, while a listed tag still wins through its own active item.The change is label-only, so nothing is added to the sidebar, and it needs no
override().addTagListis untouched.On ordering: the tags side sets the label from an
extendonIndexPage.prototype.view. That runs after the originalview()returns, butview()only returns aPageStructurevnode holding a boundsidebarcallback, soIndexSidebar.view()(and thereforeitems()) does not run until later in the diff. The label is always set before it is read. Stale labels are not a concern either, sinceDefaultResolver.makeKey()keys on route name plus route params, so any tag-to-tag or tag-to-index navigation re-creates the page and with itapp.current.Testing
New
framework/core/js/tests/integration/forum/components/IndexSidebar.test.tscovers the title control: that it renders, that it falls back to the index link when no nav item is active, that it usestitleControlLabelwhen a page sets one, and that an active nav item still beatstitleControlLabel. The two behavioural cases fail on2.xwithout theIndexSidebarchange and pass with it.Also verified by hand on a 2.x-dev install with 4 secondary tags at descending discussion counts (4/3/2/1), Chromium at 390x844:
Client-side navigation was checked separately, since the ordering argument above only matters on a route change rather than a fresh load. Driving the router through listed tag, unlisted tag, listed tag, unlisted tag, index, unlisted tag, listed tag gives the correct title at every step, and the unlisted tag never gains a nav item.
No
js/distin the diff, per the contributing docs.