Something that has annoyed me ever since I found the built-in tabs macro, is that if you don’t supply a default tab, then the default display is that no tab is selected. IMHO, that is plain ugly and also inconsistent, since once you have selected a tab there is no way to go back to nothing selected (apart from deleting the relevant state tiddler).
I created a modified tabs macro that defaults to the first title if no default is supplied and it seems to be OK:
Edit: the changes are the two $set widgets after the $qualify
I share your point of view. I’m using the following workarounds for my purposes:
if the tab list is dynamic, I set a filter-based variable that hold the tab tiddlers; the tabs macro uses the first element from this list as the default tab
an empty tab tiddler with caption “×” is added to the end of the tab list, selecting this empty tab can be used to “collapse” the tabs macro.
A simplified pseudo code
<$set name="tabsList" filter="filter expression that returns relevant tabs, including the empty × tab at the end" >
<% if [<tabsList>!match[the empty × tab]] %>
<!-- Do not show tabs macro at all if the only tab in tabsList is the empty × one -->
<$transclude $variable="tabs" tabsList=<<tabsList>> default={{{ [enlist<tabsList>] }}} />
<% endif %>
</$set>
No tabs has been the default behavior, changing it now would break backwards compatibility.
But maybe some easy way to optionally use first tab as default or to have some way to close all tabs would be worth implementing?
E.g. <<tabs "tab1 tab2" defaultFirst:"yes" allowReset:"yes">>, but with some better choice of wording.
I’ve thought about this problem too, but without getting around to generating the workaround or posting about it here.
It seems the direct specification of the default tab was a reasonable behavior back when tab sets tended not to be dynamic. Given the increasing power of dynamic sets of tabs, we really need to have a dynamic way of setting the default tab.
Thanks for starting the conversation, along with directions toward a solution!
Ah, I realize my point of frustration is not with basic tabs macro, but with toc-tabbed macros, which do not seem to have any default parameter at all! (I didn’t realize this until I tried the solution by @TW_Tones — in my toc-tabbed solutions — and then went looking for the Default parameter documentation when it didn’t work . Not just not dynamic — not there.)
I would love to have this parameter available, and — in parallel with the theme of this post — specifiable by way of a filter so that it can be effectively used in templates, etc.
It would be different, but I think it would be backwards compatible. I think “not showing anything” has never been misused by 3rd party authors, which would prevent us to change it now.
IMO the first item would be a good choice.
There is also an issue, if the current state of the tabs macro points to a “non existent” tiddler. This also shows “nothing”, which imo is a pain.
It seems a bit nasty to be needing to explicitly copy all the parameters, but it works (unlike my code above which failed when tiddler titles had spaces).
I’m not sure why this would be so, and @pmario’s comments also seem open to an improvement.
No prior expectations would be broken by adding, for example, an additional available parameter to the tabs macro — which I’d suggest calling avoidnullstate or something like that. When specified, it causes the tab macro to display the first tab if there is no selected or default value specified. (Of course, if the tabs macro is fed a filter with zero results, that’s a different problem. “Avoid” implies an attempt, not magical prevention. )
I’d suggest doing the same for the tabbed-toc macros.
Thanks. The problem I had was that my original attempts at modifying the tabs macro all failed when dealing with tiddlers with spaces in their title. However, you’ve encouraged me to revisit that, and this is what I’ve come up with:
(Edit: rolled the $sets into the $let, Edit2: replaced backtick braces with triple braces, for consistency with existing code)
How it works:
New parameter defaultFilter is a filter that is applied to tabsList to determine the default tab. If you want to default to the first tab title, set it to [first[]]. Maybe someone would prefer [last[]]? Or something else!
I’ve also added support for a tiddler $:/config/TabsMacro/defaultFilter. If you’d like all your tabs macros to have a default filter of [first[]] (like I’d like it to), then that filter goes in this tiddler.
If you have none of this defaultFilter stuff, then it works just like now.
I did a test with this code. No extra options. first[] is hardcoded. It makes the code much simpler. IMO a new parameter increases complexity quite a bit.
This solution still has the problem, that it shows an empty body, if the state-tiddler contains a non existent tiddler title. eg: If that tiddler got deleted. But since that’s a much rarer edge-case I did not bother to resolve that one. It makes the whole code much more complex, imo for a very little win.
My experience of TiddlyWiki development has been of a keen interest in not changing existing functionality - that would include no selected tabs if no default was specified. I’ve already stated in my OP I think no selected tabs is a silly idea, in which case it should be as simple as (your then<__default__> and enlist_input[] seem superfluous):
Yes, that definitely simplifies things, but I know there are plenty of older TWs still around. I’ve submitted a pull request to add both types of examples to the main tiddlywiki site.