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

[Doc] Upgrade example gallery #5

Merged
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
184 changes: 74 additions & 110 deletions doc/source/_static/css/examples.css
Original file line number Diff line number Diff line change
@@ -1,89 +1,108 @@
:root {
--ray-example-gallery-gap-x: 18px;
--ray-example-gallery-gap-y: 22px;
--sidebar-top: 5em;
}

#site-navigation {
width: 330px !important;
border-right: none;
margin-left: 32px;
overflow-y: auto;
max-height: calc(100vh - var(--sidebar-top));
position: sticky;
top: var(--sidebar-top) !important;
z-index: 1000;
.gallery-sidebar {
width: 100%;
}

#site-navigation h5 {
.gallery-sidebar h5 {
font-size: 16px;
font-weight: 600;
color: #000;
}

#site-navigation h6 {
.gallery-sidebar h6 {
font-size: 14px;
font-weight: 600;
color: #000;
text-transform: uppercase;
}

/* Hide the default sidebar content */
#site-navigation > div.bd-sidebar__content {
display: none;
.searchDiv {
margin-bottom: 2em;
display: flex;
flex-direction: row;
border: 1px solid var(--pst-color-border);
border-radius: 4px;
background-color: var(--pst-color-on-background);
justify-content: center;
align-items: center;
height: 50px;
}
#site-navigation > div.rtd-footer-container {
display: none;

#search-input-label {
height: 100%;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
}

.searchDiv {
margin-bottom: 2em;
.searchDiv:focus-within {
outline: 2px solid var(--pst-color-border);
}

#search-icon {
fill: var(--pst-color-text-base);
margin: 0em 1em;
}

#searchInput {
width: 100%;
color: #5F6469;
border: 1px solid #D2DCE6;
height: 50px;
border-radius: 4px;
background-color: #F9FAFB;
background-image: url("data:image/svg+xml,%3Csvg width='25' height='25' viewBox='0 0 25 25' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cg id='Systems / search-line' clip-path='url(%23clip0_1_150)'%3E%3Crect width='24' height='24' transform='translate(0.398529 0.0546875)' fill='%23F9FAFB'/%3E%3Cg id='Group'%3E%3Cpath id='Vector' d='M18.4295 16.6717L22.7125 20.9537L21.2975 22.3687L17.0155 18.0857C15.4223 19.3629 13.4405 20.0576 11.3985 20.0547C6.43053 20.0547 2.39853 16.0227 2.39853 11.0547C2.39853 6.08669 6.43053 2.05469 11.3985 2.05469C16.3665 2.05469 20.3985 6.08669 20.3985 11.0547C20.4014 13.0967 19.7068 15.0784 18.4295 16.6717ZM16.4235 15.9297C17.6926 14.6246 18.4014 12.8751 18.3985 11.0547C18.3985 7.18669 15.2655 4.05469 11.3985 4.05469C7.53053 4.05469 4.39853 7.18669 4.39853 11.0547C4.39853 14.9217 7.53053 18.0547 11.3985 18.0547C13.219 18.0576 14.9684 17.3488 16.2735 16.0797L16.4235 15.9297V15.9297Z' fill='%238C9196'/%3E%3C/g%3E%3C/g%3E%3Cdefs%3E%3CclipPath id='clip0_1_150'%3E%3Crect width='24' height='24' fill='white' transform='translate(0.398529 0.0546875)'/%3E%3C/clipPath%3E%3C/defs%3E%3C/svg%3E%0A");
background-repeat: no-repeat;
background-position-x: 0.5em;
background-position-y: center;
background-size: 1.5em;
padding-left: 3em;
color: var(--pst-color-text-base);
border: none;
background-color: transparent;
}

#searchInput:focus-visible {
outline: none;
}

#searchInput::placeholder {
color: #5F6469;
color: var(--pst-color-text-muted);
opacity: 1;
}

.tag {
margin-bottom: 5px;
font-size: small;
color: #000000;
border: 1px solid #D2DCE6;
border-radius: 14px;
display: flex;
flex-direction: row;
align-items: center;
width: fit-content;
gap: 1em;
/* Tag button styling */
.tag-group {
display: flex;
flex-flow: wrap;
gap: 0em 0.5em;
}

.tag.btn-outline-primary {
color: #000000;
.tag {
margin-bottom: 5px;
font-size: small;
background-color: var(--pst-color-on-background);
border: 1px solid var(--pst-color-border);
border-radius: 14px;
display: flex;
flex-direction: row;
align-items: center;
width: fit-content;
gap: 0.5em;
color: var(--pst-color-text-base);
padding: 3px 12px 3px 12px;
line-height: 20px;
}

.tag-btn-wrapper {
display: flex;
flex-direction: row;
flex-wrap: wrap;
gap: 1em;
.tag > svg > path {
fill: var(--pst-color-text-base);
}
.tag:hover {
background-color: var(--pst-color-info-highlight) !important;
color: var(--pst-color-info-text) !important;
}
.tag:hover > svg > path {
fill: var(--pst-color-info-text) !important;
}

/* Selected tag buttons */
.tag.btn-primary {
background-color: var(--pst-color-info-bg);
}
/* Inactive tag buttons */
.tag.btn-outline-primary {
background-color: var(--pst-color-on-background);
}

div.sd-container-fluid.docutils > div {
Expand All @@ -103,9 +122,10 @@ div.gallery-item {
width: auto;
}

/* Override sphinx-design box shadow styles */
div.gallery-item > div.sd-card {
border-radius: 8px;
box-shadow: 0px 4px 10px 0px rgba(0, 0, 0, 0.05) !important;
box-shadow: 0 .125rem .25rem var(--pst-color-shadow) !important;
border: none;
}

/* Example gallery "Tutorial" title */
Expand Down Expand Up @@ -148,18 +168,6 @@ div.sd-card-title > span.sd-bg-info.sd-bg-text-info {
background-color: initial !important;
}

div.sd-card-body > p.sd-card-text > a {
text-align: initial;
}

div.sd-card-body > p.sd-card-text > a > span {
color: rgb(81, 81, 81);
}

#main-content {
max-width: 100%;
}

#noMatches {
display: flex;
flex-direction: column;
Expand All @@ -177,47 +185,3 @@ div.sd-card-body > p.sd-card-text > a > span {
#noMatches.hidden,.gallery-item.hidden {
display: none !important;
}

.btn-primary {
color: #004293;
background: rgba(61, 138, 233, 0.20);
padding: 3px 12px 3px 12px;
border: 1px solid #D2DCE6;
}

button.try-anyscale {
background-color: initial !important;
width: fit-content;
padding: 0 !important;
margin-left: auto !important;
float: initial !important;
}

button.try-anyscale > svg {
display: none;
}

button.try-anyscale > i {
display: none;
}

button.try-anyscale > span {
margin: 0;
text-decoration-line: underline;
font-weight: 500;
color: #000;
}

.top-nav-content {
justify-content: initial;
}

/* Hide nav bar that has github, fullscreen, and print icons */
div.header-article.row.sticky-top.noprint {
display: none !important;
}

/* Hide the footer with 'prev article' and 'next article' buttons */
.footer-article.hidden {
display: none !important;
}
111 changes: 111 additions & 0 deletions doc/source/_static/js/examples.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/**
* Check whether a panel matches the selected filter tags.
*
* @param {any} panel Example gallery item
* @param {Array<Array<string>>} groupedActiveTags Groups of tags selected by the user.
* @returns {boolean} True if the panel should be shown, false otherwise
*/
function panelMatchesTags(panel, groupedActiveTags) {
// Show the panel if every tagGroup has at least one active tag in the classList,
// or if no tag in a group is selected.
return groupedActiveTags.every(tagGroup => {
return tagGroup.length === 0 || Array.from(panel.classList).some(tag => tagGroup.includes(tag))
})
}


window.addEventListener('load', () => {

/* Fetch the tags that the user can filter on from the buttons in the sidebar
* Additionally retrieve the elements that we need for filtering.
*/
const tags = {}
document.querySelectorAll('div.tag-section').forEach(group => {
tags[group.id] = group.querySelectorAll('div.tag-group > div.tag.btn')
})
const noMatchesElement = document.querySelector("#noMatches");
const panels = document.querySelectorAll('.gallery-item')

/**
* Filter the links to the examples in the example gallery
* by the selected tags and the current search query.
*/
function filterPanels() {
const query = document.getElementById("searchInput").value.toLowerCase();
const activeTags = Array.from(document.querySelectorAll('.tag.btn-primary')).map(el => el.id);
const groupedActiveTags = Object.values(tags).map(group => {
const tagNames = Array.from(group).map(element => element.id);
return activeTags.filter(activeTag => tagNames.includes(activeTag));
})

// Show all panels first
panels.forEach(panel => panel.classList.remove("hidden"));

let toHide = [];
let toShow = [];

// Show each panel if it has every active tag and matches the search query
panels.forEach(panel => {
const text = (panel.textContent + panel.classList.toString()).toLowerCase();
// const hasTag = activeTags.every(tag => panel.classList.contains(tag));
const hasTag = panelMatchesTags(panel, groupedActiveTags)
const hasText = text.includes(query.toLowerCase());

if (hasTag && hasText) {
toShow.push(panel);
} else {
toHide.push(panel);
}
})

toShow.forEach(panel => panel.classList.remove("hidden"));
toHide.forEach(panel => panel.classList.add("hidden"));

// If no matches are found, display the noMatches element
if (toShow.length === 0) {
noMatchesElement.classList.remove("hidden");
} else {
noMatchesElement.classList.add("hidden");
}

// Set the URL to match the active tags using query parameters
history.replaceState(null, null, activeTags.length === 0 ? location.pathname : `?tags=${activeTags.join(',')}`);
}

// Generate the callback triggered when a user clicks on a tag filter button.
document.querySelectorAll('.tag').forEach(tag => {
tag.addEventListener('click', () => {
// Toggle "tag" buttons on click.
if (tag.classList.contains('btn-primary')) {
// deactivate filter button
tag.classList.replace('btn-primary', 'btn-outline-primary');
} else {
// activate filter button
tag.classList.replace('btn-outline-primary', 'btn-primary');
}
filterPanels()
});
});

// Add event listener for keypresses in the search bar
const searchInput = document.getElementById("searchInput");
if (searchInput) {
searchInput.addEventListener("keyup", function (event) {
event.preventDefault();
filterPanels();
});
}

// Add the ability to provide URL query parameters to filter examples on page load
const urlParams = new URLSearchParams(window.location.search);
if (urlParams.size > 0) {
const urlTagParams = urlParams.get('tags').split(',');
urlTagParams.forEach(tag => {
const tagButton = document.getElementById(tag);
if (tagButton) {
tagButton.classList.replace('btn-outline-primary', 'btn-primary');
}
});
filterPanels();
}
});
Loading