-
Notifications
You must be signed in to change notification settings - Fork 21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Hide buttons generated by the TryExamples
directive by default
#173
base: main
Are you sure you want to change the base?
Hide buttons generated by the TryExamples
directive by default
#173
Conversation
d63d2e5
to
0ed1b1b
Compare
0ed1b1b
to
09d48ab
Compare
I have rebased this right now and opened a PR because I think it will be better for visibility, plus I would appreciate some help towards bringing this to completion. It's not fully working right now since the directives still seem to contain the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see why this is reasonable, but isn't that going to have the opposite effect on page where the button should be visible, where the page will load and then jump around as buttons are added ?
Thanks for the review, @Carreau. Yes, this will be a slight issue when someone reloads a page and if they are in the middle of a page when doing so – but at the top of the page, it should load as normal, because from there the buttons will be appended to the layout rather than being inserted into a position where the text moves because of the insertion. I am not sure if there is a cleaner way to do this. |
I think this is partially working now – where it breaks is when a |
TryExamples
directive by defaultTryExamples
directive by default
I think this is working now, marking it as ready for review. One small thing to figure out remains: the PR preview at https://jupyterlite-sphinx--173.org.readthedocs.build/en/173/directives/try_examples.html is not un-hiding the button with the custom So this works for all sorts of buttons now (tested locally), except for these non-standard buttons that have user-defined CSS. Let me try to dig further, and meanwhile open this up for further comments. |
I will try to re-review. I'm ok with this in principle. Still unsure if hiding or appending is the best, so I'd like someone else input on this anyway. |
TryExamples
directive by defaultTryExamples
directive by default
Update on this: With the refactoring I performed in my recent commits, I've fixed the problem I had noted above; however, using it on projects downstream, such as NumPy, fails, and I am not able to un-hide the buttons selectively based on the config file. So far, I still haven't been able to figure out why (it apparently has something to do with the CSS rather than with JS). Even though this is marked as a draft, it's ready for review – @Carreau, could you please re-review it when you have time? I discussed this PR with @steppi, who agreed to review it soon after I suggested that I would revisit it, which I now have. Perhaps some trained pairs of eyes will be able to catch issues I haven't been able to :D Also, a note on the jumping around of the contents when the page is loaded: I've tried to implement a solution (not pushed here, though, it should probably be a separate PR) to minimise the CLS value, through pre-allocating space for the container where the button is going to show up. However, for pages where the buttons are ignored/hidden, this check happens at runtime through the JavaScript code – which is not ideal. To achieve a smooth experience and no shifts in the content in the truest sense, this is possible only if we read through the documentation source pages and exclude them based on ignore patterns at build time (i.e., which would be read within the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work to improve the user experience.
I agree that it's a very poor user experience to see a page with buttons and then see those buttons disappear inexplicably.
From that perspective, this pull request looks like it's doing the right thing.
However, if the paradigm is that most websites exclude only a small portion of pages, then this pull request penalizes the main case (include the page, show the buttons) in order to protect the exceptional case (ignore the page, hide the buttons).
I'm not sure there's really any good way to do this other than the one you mentioned—page exclusion patterns should be handled at build-time, not at run-time.
But we need to know why it was architected that way to begin with. There may be some really important use case for being able to dynamically add or remove exclusion patterns without having to rebuild the docs.
I'm requesting changes because the CSS should not have an !important
flag, the toggle function needs fixing I think, and the JavaScript should have less copy-pasted code by creating showButtons()
function.
const buttons = document.getElementsByClassName( | ||
"try_examples_button hidden", | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's more common to write:
const buttons = document.getElementsByClassName( | |
"try_examples_button hidden", | |
); | |
const buttons = document.querySelectorAll( | |
".try_examples_button.hidden", | |
); |
const buttons = document.getElementsByClassName( | ||
"try_examples_button hidden", | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const buttons = document.getElementsByClassName( | |
"try_examples_button hidden", | |
); | |
const buttons = document.querySelectorAll( | |
".try_examples_button.hidden", | |
); |
|
||
/* Some improvements for hidden buttons */ | ||
|
||
/* smooth transitions */ | ||
.try_examples_button { | ||
opacity: 1; | ||
transition: opacity 0.3s ease-in-out; | ||
} | ||
|
||
.try_examples_button.hidden { | ||
display: none; | ||
opacity: 0; | ||
} | ||
|
||
.try_examples_button.fade-in { | ||
transition: opacity 0.3s ease-in-out; | ||
} | ||
|
||
/* to ensure hidden class takes precedence */ | ||
.hidden { | ||
display: none !important; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not entirely sure that it's worth creating the fade-in effect when there is also a content layout shift.
But if we still want to keep it, I suggest a few changes:
/* Some improvements for hidden buttons */ | |
/* smooth transitions */ | |
.try_examples_button { | |
opacity: 1; | |
transition: opacity 0.3s ease-in-out; | |
} | |
.try_examples_button.hidden { | |
display: none; | |
opacity: 0; | |
} | |
.try_examples_button.fade-in { | |
transition: opacity 0.3s ease-in-out; | |
} | |
/* to ensure hidden class takes precedence */ | |
.hidden { | |
display: none !important; | |
} | |
/* Buttons are hidden by default and revealed via JavaScript in another file */ | |
/* The button is revealed in two stages. The first stage removes the hidden class. | |
This gives the button dimensions and causes the page content below to "jump" | |
(get pushed down suddenly). The second stage removes the transparent class, | |
which reveals the button with a slight fade-in effect. */ | |
.try_examples_button.transparent { | |
opacity: 0; | |
} | |
.try_examples_button { | |
opacity: 1; | |
transition: opacity 0.3s ease-in-out; | |
} |
requestAnimationFrame(() => { | ||
for (let button of buttons) { | ||
button.style.opacity = "0"; | ||
button.classList.remove("hidden"); | ||
button.classList.add("fade-in"); | ||
requestAnimationFrame(() => { | ||
button.style.opacity = "1"; | ||
}); | ||
} | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's wrap this in a function:
const showButtons = () => {
const buttons = document.querySelectorAll(
".try_examples_button.hidden",
);
for (let button of buttons) {
button.classList.remove("hidden");
}
// If the hidden and transparent classes are removed
// one right after the other, there is no animation of the opacity
// going from 0 to 1, hence requestAnimationFrame.
requestAnimationFrame(() => {
for (let button of buttons) {
button.classList.remove("transparent");
}
});
}
const buttons = document.getElementsByClassName( | ||
"try_examples_button hidden", | ||
); | ||
for (let button of buttons) { | ||
button.classList.remove("hidden"); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const buttons = document.getElementsByClassName( | |
"try_examples_button hidden", | |
); | |
for (let button of buttons) { | |
button.classList.remove("hidden"); | |
} | |
showButtons(); |
go_back_button_html = ( | ||
'<button class="try_examples_button" ' | ||
'<button class="try_examples_button hidden" ' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From what I can tell, these buttons are already within a .hidden
container.
'<button class="try_examples_button hidden" ' | |
'<button class="try_examples_button" ' |
f"onclick=\"window.tryExamplesHideIframe('{examples_div_id}'," | ||
f"'{iframe_parent_div_id}')\">" | ||
"Go Back</button>" | ||
) | ||
|
||
full_screen_button_html = ( | ||
'<button class="try_examples_button" ' | ||
'<button class="try_examples_button hidden" ' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
'<button class="try_examples_button hidden" ' | |
'<button class="try_examples_button" ' |
@@ -570,7 +571,7 @@ def run(self): | |||
# Button with the onclick event to swap examples with embedded notebook. | |||
try_it_button_html = ( | |||
'<div class="try_examples_button_container">' | |||
'<button class="try_examples_button" ' | |||
'<button class="try_examples_button hidden" ' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
'<button class="try_examples_button hidden" ' | |
'<button class="try_examples_button hidden transparent" ' |
(see other suggestions above)
} | ||
tryExamplesConfigLoaded = true; | ||
}; | ||
|
||
window.toggleTryExamplesButtons = () => { | ||
/* Toggle visibility of TryExamples buttons. For use in console for debug | ||
* purposes. */ | ||
var buttons = document.getElementsByClassName("try_examples_button"); | ||
var buttons = document.getElementsByClassName("try_examples_button hidden"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a toggle function, so you need to be able to find toggle any button whether or not it is already hidden.
var buttons = document.getElementsByClassName("try_examples_button hidden"); | |
var buttons = document.getElementsByClassName("try_examples_button"); |
} | ||
tryExamplesConfigLoaded = true; | ||
}; | ||
|
||
window.toggleTryExamplesButtons = () => { | ||
/* Toggle visibility of TryExamples buttons. For use in console for debug | ||
* purposes. */ | ||
var buttons = document.getElementsByClassName("try_examples_button"); | ||
var buttons = document.getElementsByClassName("try_examples_button hidden"); | ||
|
||
for (var i = 0; i < buttons.length; i++) { | ||
buttons[i].classList.toggle("hidden"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
buttons[i].classList.toggle("hidden"); | |
buttons[i].classList.toggle("hidden"); | |
requestAnimationFrame(() => { | |
buttons[i].classList.toggle("transparent"); | |
}); |
Description
This PR hides the buttons from the
TryExamples
directive by default. This is helpful because the current method of ignoring particular pages based on their URL first loads the buttons and then hides them, which means that they are briefly displayed on that page in the documentation and then hidden – keeping them hidden and then selectively enabling them will minimise this latency and improve user experience.Changes made
try_examples_button
buttonshidden
at the time of generation by adding this keyword to theclassList
loadTryExamplesConfig
function injupyterlite_sphinx.js
to check for thetry_examples_button hidden
class instead and then removehidden
from theclassList
Additional context
N/A