Skip to content
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

Draft
wants to merge 13 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions jupyterlite_sphinx/jupyterlite_sphinx.css
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
background:
radial-gradient(farthest-side, #ffa516 94%, #0000) top/8px 8px no-repeat,
conic-gradient(#0000 30%, #ffa516);
mask: radial-gradient(farthest-side, #0000 calc(100% - 8px), #000 0);
-webkit-mask: radial-gradient(farthest-side, #0000 calc(100% - 8px), #000 0);
animation: l13 1s infinite linear;
}
Expand All @@ -75,3 +76,25 @@
display: none;
}
}

/* 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;
}
Comment on lines +79 to +100

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:

Suggested change
/* 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;
}

77 changes: 66 additions & 11 deletions jupyterlite_sphinx/jupyterlite_sphinx.js
Original file line number Diff line number Diff line change
Expand Up @@ -163,15 +163,48 @@ window.loadTryExamplesConfig = async (configFilePath) => {
const response = await fetch(configFileUrl);
if (!response.ok) {
if (response.status === 404) {
// Try examples ignore file is not present.
console.log("Optional try_examples config file not found.");
// Try examples ignore file is not present. Enable all interactive examples
// in that case.
console.log(
"Optional try_examples config file not found. Enabling all interactive examples.",
);

// Grab all hidden try examples buttons and fade them in
const buttons = document.getElementsByClassName(
"try_examples_button hidden",
);
Comment on lines +173 to +175

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:

Suggested change
const buttons = document.getElementsByClassName(
"try_examples_button hidden",
);
const buttons = document.querySelectorAll(
".try_examples_button.hidden",
);


requestAnimationFrame(() => {
for (let button of buttons) {
button.style.opacity = "0";
button.classList.remove("hidden");
button.classList.add("fade-in");
requestAnimationFrame(() => {
button.style.opacity = "1";
});
}
});
Comment on lines +177 to +186

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");
    }
  });
}


tryExamplesConfigLoaded = true;

return;
}
throw new Error(`Error fetching ${configFilePath}`);
}

const data = await response.json();
if (!data) {
// If config file exists but is empty, treat it like a missing config
// and enable all interactive examples since there is no ignore pattern
console.log(
"Try examples config file is empty. Enabling all interactive examples.",
);
const buttons = document.getElementsByClassName(
"try_examples_button hidden",
);
Comment on lines +202 to +204

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const buttons = document.getElementsByClassName(
"try_examples_button hidden",
);
const buttons = document.querySelectorAll(
".try_examples_button.hidden",
);

for (let button of buttons) {
button.classList.remove("hidden");
}
Comment on lines +202 to +207

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const buttons = document.getElementsByClassName(
"try_examples_button hidden",
);
for (let button of buttons) {
button.classList.remove("hidden");
}
showButtons();

return;
}

Expand All @@ -180,29 +213,51 @@ window.loadTryExamplesConfig = async (configFilePath) => {
tryExamplesGlobalMinHeight = parseInt(data.global_min_height);
}

// Disable interactive examples if file matches one of the ignore patterns
// by hiding try_examples_buttons.
Patterns = data.ignore_patterns;
// Selectively enable interactive examples if file matches one of the ignore patterns
// by un-hiding try_examples_buttons with a smooth transition
const Patterns = data.ignore_patterns || [];
let shouldShowButtons = true;

Comment on lines +219 to +220

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let shouldShowButtons = true;

for (let pattern of Patterns) {
let regex = new RegExp(pattern);
if (regex.test(currentPageUrl)) {
agriyakhetarpal marked this conversation as resolved.
Show resolved Hide resolved
var buttons = document.getElementsByClassName("try_examples_button");
for (var i = 0; i < buttons.length; i++) {
buttons[i].classList.add("hidden");
}
shouldShowButtons = false;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
shouldShowButtons = false;
showButtons();

break;
}
}

if (shouldShowButtons) {
const buttons = document.getElementsByClassName(
"try_examples_button hidden",
);
requestAnimationFrame(() => {
for (let button of buttons) {
button.style.opacity = "0";
button.classList.remove("hidden");
button.classList.add("fade-in");
requestAnimationFrame(() => {
button.style.opacity = "1";
});
}
});
}
Comment on lines +228 to +243

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (shouldShowButtons) {
const buttons = document.getElementsByClassName(
"try_examples_button hidden",
);
requestAnimationFrame(() => {
for (let button of buttons) {
button.style.opacity = "0";
button.classList.remove("hidden");
button.classList.add("fade-in");
requestAnimationFrame(() => {
button.style.opacity = "1";
});
}
});
}

} catch (error) {
console.error(error);
// On error, enable all buttons as a fallback to maintain current behavior
console.error("Error loading try_examples config:", error);
const buttons = document.getElementsByClassName(
"try_examples_button hidden",
);
for (let button of buttons) {
button.classList.remove("hidden");
}
Comment on lines +247 to +252

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const buttons = document.getElementsByClassName(
"try_examples_button hidden",
);
for (let button of buttons) {
button.classList.remove("hidden");
}
showButtons();

}
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");

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.

Suggested change
var buttons = document.getElementsByClassName("try_examples_button hidden");
var buttons = document.getElementsByClassName("try_examples_button");


for (var i = 0; i < buttons.length; i++) {
buttons[i].classList.toggle("hidden");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
buttons[i].classList.toggle("hidden");
buttons[i].classList.toggle("hidden");
requestAnimationFrame(() => {
buttons[i].classList.toggle("transparent");
});

Expand Down
7 changes: 4 additions & 3 deletions jupyterlite_sphinx/jupyterlite_sphinx.py
Original file line number Diff line number Diff line change
Expand Up @@ -553,15 +553,16 @@ def run(self):
)

# Button with the onclick event to swap embedded notebook back to examples.
# This includes a 'hidden' class by default to hide until the page is loaded.
go_back_button_html = (
'<button class="try_examples_button" '
'<button class="try_examples_button hidden" '

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.

Suggested change
'<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" '

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
'<button class="try_examples_button hidden" '
'<button class="try_examples_button" '

f"onclick=\"window.openInNewTab('{examples_div_id}',"
f"'{iframe_parent_div_id}')\">"
"Open In Tab</button>"
Expand All @@ -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" '

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
'<button class="try_examples_button hidden" '
'<button class="try_examples_button hidden transparent" '

(see other suggestions above)

f"onclick=\"window.tryExamplesShowIframe('{examples_div_id}',"
f"'{iframe_div_id}','{iframe_parent_div_id}','{iframe_src}',"
f"'{height}')\">"
Expand Down
Loading