Twine Sugarcube 2.36.1 - Display a toolkit on a disabled button

Hi,
I have already asked a related question to this, however, it is somewhat different so I opened up a new post.

I have a button that I disabled using the disable macro[1]
<<disable $DP < $requiredDP>><<button "Pay Tribute">><</button>><</disable>>

Now, when the button is disabled, I want to inform the user using a toolkit why the button is disabled. I was able to successfully create a toolkit, but I have no idea how to make it so that it only shows when the button is disabled.

<div class="hoverTxt">
    <span class="buttonContainer">
        <<disable $DP < $requiredDP>><<button "payTribute">><</button>><</disable>>
    </span>
    <span class="hoverBox">Tooltip Text</span>
</div>

CSS:

<style>
/* Existing styles */
.hoverTxt {
    position: relative;
    display: inline-block;
}

.buttonContainer {
    position: relative; /* Added position to contain the absolute tooltip */
    display: inline-block;
}

.payTribute:disabled {
    background: #999;
    color: #555;
    cursor: not-allowed;
}

.hoverBox {
    position: absolute;
    background-color: #e5e5f5;
    padding: 3px;
    border: 1px solid #666;
    border-radius: 10px;
    visibility: hidden;
    color: black;
    text-decoration: none;
    z-index: 1;
    top: -30px;
    left: 50%;
    transform: translateX(-50%);
    transition: visibility 0.2s ease-in-out; /* Added transition for smooth visibility */
}

/* Adjusted selector to target .hoverBox inside .hoverTxt */
.hoverTxt:hover .hoverBox {
    visibility: visible;
}
</style>

If that code is too complicated, I have also found a simpler and smoother method. The issue here is differnt and kinda weird: It completely removes the button when the button does not get disabled by the <<disable>> macro. Additionally, when the button is disabled and the toolkit appears, it does not appear over the text, instead it moves the text out of the way

<div class="hoverTxt">
    <span class="buttonContainer">
        <<disable $DP < $requiredDP>><<button "payTribute">><</button>><</disable>>
    </span>
    <span class="hoverBox">Tooltip Text</span>
</div>

CSS:

<style>
/*I have excluded my existing, irrelevant styles*/
.hoverTxt {
    position: relative;
    display: inline-block;
}

.buttonContainer {
    position: relative; /* Added position to contain the absolute tooltip */
    display: inline-block;
}

.payTribute:disabled {
    background: #999;
    color: #555;
    cursor: not-allowed;
}

.hoverBox {
    position: absolute;
    background-color: #e5e5f5;
    padding: 3px;
    border: 1px solid #666;
    border-radius: 10px;
    visibility: hidden;
    color: black;
    text-decoration: none;
    z-index: 1;
    top: -30px;
    left: 50%;
    transform: translateX(-50%);
    transition: visibility 0.2s ease-in-out; /* Added transition for smooth visibility */
}

/* Adjusted selector to target .hoverBox inside .hoverTxt */
.hoverTxt:hover .hoverBox {
    visibility: visible;
}
</style>


How wedded are you to using <<disable>> to do this?

The reason I ask, is that this seems like a simple case for just having two versions of the button, one with the tooltip and one without.

<<if $DP < $requiredDP>>
   <div class="hoverTxt">
      <span class="buttonContainer">
          <button disabled>payTribute</button>
      </span>
    <span class="hoverBox">Tooltip Text</span>
<<else>>
   <<button "payTribute">><</button>>
<</if>>

Indeed, you could even do away with the tooltip (which won’t work on mobile) and change the button text to indicate why it is disabled

<<if $DP < $requiredDP>>
   <button disabled>payTribute (disabled, not enough DP)</button>
<<else>>
   <<button "payTribute">><</button>>
<</if>>

@JackyJan

And you could even use the <<widget>> macro to create a custom widget to automate the process.

eg. using @Hituro last example as a starting point…

…the following widget definition…

<<widget "button-opt" container>>
	<<set _label to _args[0]>>
    <<set _condition to _args[1]>>
    <<set _hint to _args[2]>>
    
    <<if Scripting.evalTwineScript(_condition)>>
		<<button "payTribute">>_contents<</button>>
    <<else>>
		<button disabled>payTribute (disabled, not enough DP)</button>
	<</if>>
<</widget>>

…would create a container widget named <<button-opt>>, that could be used in a Passage like so…

<<set $DP to 9>>
<<set $requiredDP to 10>>

/* results in a disabled button */
<<button-opt "payTribute" "$DP >= $requiredDP" "payTribute (disabled, not enough DP)">>code to run when button selected<</button-opt>>

<<set $DP to 11>>

/* results in a selectable button */
<<button-opt "payTribute" "$DP >= $requiredDP" "payTribute (disabled, not enough DP)">>code to run when button selected<</button-opt>>

All right thanks!
I should have thought about that, no I idea why I didn’t. It was pretty late and I was too stubborn to think outside the box the tiniest bit…:)’

Thanks for the widget it worked really well for the code I provided. Thanks to you I think I finally understood how widgets work.

Just to make sure:

<<widget "Name">>
   <<set _variable0 to _args[0]>>
   <<set _variable1 to _args[1]>>
<<set $DP = _variable0>>
<<set $requiredDP = _varibale1>>
Random text
<</widget>>

In combination with
<<Name "10" "20">>
Should set $DP = 10 and $requiredDP=20. As well as display “Random text”

Also what is the purpose of " <<if Scripting.evalTwineScript(_condition)>>"

1: If one of the purposes of the <<Name>> widget is to assign values to the $DP and $requiredDP Story variables, then you don’t need to use Temporary variables within the <<Name>> widget to do that, you can directly assign the contents of the _args array elements to the variables.

<<widget "Name">>
   <<set $DP to _args[0]>>
   <<set $requiredDP to _args[1]>>
   Random text
<</widget>>

2: If the $DP and $requiredDP variables represent Numerical values (like 1, 22, 106, etc) then the arguments being passed to the <<Name>> widget should be Numbers, and not Strings.
eg. <<Name 10 20>>

That method can be used to evaluate a String based representation of Conditional Expression (like "$DP >= $requiredDP") to determine its Boolean based outcome.

eg. If the current values of the $DP and $requiredDP were 15 and 10 respectively then the following method call…

Scripting.evalTwineScript("$DP >= $requiredDP")

…would return true, because 15 >= 10 evaluates to true.

On the other hand, if those variables currently equalled 8 and 13 respectively, then that same method call would return false, because 8 >= 13 does not evaluate to true.

note: While the Scripting.evalTwineScript() method itself is not mentioned in the SugarCube documentation, the related Scripting.evalJavaScript() method is used in one of the examples for SugarCube’s Macro.add() method.

1 Like