Skip to content

Implement search preview #1883

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

Closed
wants to merge 3 commits into from
Closed
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
76 changes: 70 additions & 6 deletions assets/css/autocomplete.css
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,23 @@
background-color: transparent;
}

.autocomplete-preview {
width: 100%;
margin: 0;
height: 65vh;
font-family: var(--sansFontFamily);
border: 4px solid var(--autocompleteBorder);
font-weight: 300;
flex-grow: 12;
font-size: 0.9rem;
}

.autocomplete-preview iframe {
width: 100%;
height: 100%;
border: 0;
}

.autocomplete-results {
list-style: none;
margin: 0;
Expand All @@ -40,20 +57,47 @@
display: block;
}

.autocomplete-suggestions {
background-color: var(--autocompleBackground);
border-radius: 8px;
.autocomplete-container {
position: absolute;
top: 15px;
width: 100%;
z-index: 200;
}

.autocomplete-suggestions {
background-color: var(--autocompleBackground);
border-radius: 8px;
box-shadow: 0px 15px 99px 0px var(--autocompleteBorder);
overflow-y: auto;
max-height: 450px;
white-space: normal;
overflow-x: hidden;
}

.autocomplete-suggestions.previewing:has(.selected) {
max-height: 900px;
}

.autocomplete-suggestions.previewing:has(.selected) .autocomplete-suggestion:not(.selected) {
display: none;
}

.autocomplete-suggestions.previewing:has(.selected) .autocomplete-preview+.autocomplete-suggestion {
display: block;
}

.autocomplete-suggestions.previewing:not(:has(.selected)) .autocomplete-preview {
display: none;
}

.autocomplete-suggestions:not(.previewing) .autocomplete-preview {
display: none;
}

.autocomplete-preview {
width: 100%
}

.autocomplete-suggestion {
color: inherit;
display: block;
Expand All @@ -77,6 +121,24 @@
background-color: var(--autocompleteHover);
}

.autocomplete-suggestion:not(.selected) .autocomplete-suggestion-preview-indicator {
display: none;
}

.autocomplete-suggestion-preview-indicator {
float: right;
border-radius: 100%;
}

.autocomplete-suggestions.previewing .autocomplete-suggestion-preview-indicator-closed {
display: none;
}

.autocomplete-suggestions:not(.previewing) .autocomplete-suggestion-preview-indicator-open {
display: none;
}


.autocomplete-suggestion em {
font-style: normal;
font-weight: bold;
Expand Down Expand Up @@ -117,8 +179,10 @@

/* Style the scrollbar track (the area behind the thumb) */
.autocomplete-suggestions::-webkit-scrollbar {
width: 5px; /* Set the width of the scrollbar */
border-radius: 7px; /* Add rounded corners to the thumb */
width: 5px;
/* Set the width of the scrollbar */
border-radius: 7px;
/* Add rounded corners to the thumb */
flex-shrink: 0;
}

Expand All @@ -137,4 +201,4 @@
.autocomplete-results .press-return {
display: none;
}
}
}
13 changes: 11 additions & 2 deletions assets/css/content/functions.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from {
background-color: var(--textDetailBackground);
}

to {
background-color: var(--blink);
}
Expand All @@ -14,8 +15,12 @@
animation-timing-function: ease-in-out;
}

.content-inner .detail-header:not(.detail-header-preview) {
margin: 2.0 0 1.0em;
}

.content-inner .detail-header {
margin: 2.0em 0 1.0em;
margin: 0 0 1.0em;
padding: .5em 1em;
background-color: var(--textDetailBackground);
border-left: 3px solid var(--textDetailAccent);
Expand Down Expand Up @@ -88,15 +93,19 @@
.content-inner .docstring:is(h2, h3, h4, h5) {
font-weight: 700;
}

.content-inner .docstring h2 {
font-size: 1.1em;
}

.content-inner .docstring h3 {
font-size: 1.0em;
}

.content-inner .docstring h4 {
font-size: .95em;
}

.content-inner .docstring h5 {
font-size: .9em;
}
Expand All @@ -105,4 +114,4 @@
display: block;
padding: 9px 15px;
background-color: var(--fnDeprecated);
}
}
15 changes: 13 additions & 2 deletions assets/css/layout.css
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,23 @@ body {
}

.content {
height: 100%;
width: 100%;
}

.content:not(.content-preview) {
width: calc(100% - var(--sidebarWidth));
left: var(--sidebarWidth);
height: 100%;
position: absolute;
}

.content-inner {
.content.content-preview {
padding-left: 16px;
padding-right: 16px;
padding-bottom: 16px;
}

.content:not(.content-preview) .content-inner {
max-width: var(--content-width);
min-height: 100%;
margin: 0 auto;
Expand Down Expand Up @@ -121,6 +131,7 @@ body.sidebar-closed .content {
}

@media screen and (max-width: 768px) {

.content,
body.sidebar-opening .content {
left: 0;
Expand Down
52 changes: 52 additions & 0 deletions assets/js/autocomplete/autocomplete-list.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export const AUTOCOMPLETE_SUGGESTION_SELECTOR = '.autocomplete-suggestion'

const state = {
autocompleteSuggestions: [],
previewOpen: false,
selectedIdx: -1
}

Expand Down Expand Up @@ -89,12 +90,63 @@ export function moveAutocompleteSelection (offset) {

if (elementToSelect) {
elementToSelect.classList.add('selected')
showPreview(elementToSelect)

elementToSelect.scrollIntoView({ block: 'nearest' })
} else {
qs(AUTOCOMPLETE_SUGGESTION_LIST_SELECTOR).scrollTop = 0
}
}

/**
* Toggles the preview state of the autocomplete list
*/
export function togglePreview () {
state.previewOpen = !state.previewOpen;
const suggestionList = qs(AUTOCOMPLETE_SUGGESTION_LIST_SELECTOR)
if (state.previewOpen) {
suggestionList.classList.add('previewing')
const elementToSelect = qs(`${AUTOCOMPLETE_SUGGESTION_SELECTOR}[data-index="${state.selectedIdx}"]`)
showPreview(elementToSelect)
} else {
suggestionList.classList.remove('previewing')
const container = previewContainer()

if (container) {
container.remove()
};
}
}

function showPreview(elementToSelect) {
const container = previewContainer()

if (container) {
container.remove()
};

const suggestionList = qs(AUTOCOMPLETE_SUGGESTION_LIST_SELECTOR)

if(state.previewOpen && elementToSelect) {
suggestionList.classList.add('previewing')
const newContainer = document.createElement('div')
newContainer.classList.add('autocomplete-preview')
const iframe = document.createElement('iframe')
const previewHref = elementToSelect.href.replace('.html', '.html?preview=true')
// The minimum permissions necessary for the iframe to run JavaScript and communicate with the parent window.
iframe.setAttribute('sandbox', 'allow-scripts allow-same-origin allow-popups allow-forms')
Copy link
Member

Choose a reason for hiding this comment

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

Quick question: is there a reason why you add allow-popups and allow-forms?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

IIRC it was necessary for the iframe to render properly, but it was something I set early so we should explore removing it. I think allow-popups was to allow the hover info to work inside of previews.

iframe.setAttribute('src', previewHref)
newContainer.replaceChildren(iframe)
elementToSelect.parentNode.insertBefore(newContainer, elementToSelect.nextSibling);
} else {
suggestionList.classList.remove('previewing')
}
}

function previewContainer() {
return qs('.autocomplete-preview')
}

function newAutocompleteIndex (offset) {
// Include the default first option with index -1
const length = state.autocompleteSuggestions.length + 1
Expand Down
2 changes: 2 additions & 0 deletions assets/js/entry/html.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { initialize as initCopyButton } from '../copy-button'
import { initialize as initSettings } from '../settings'
import { initialize as initOs } from '../os'
import { initialize as initTabsets } from '../tabsets'
import { initialize as initPreview} from '../preview'

onDocumentReady(() => {
initTheme()
Expand All @@ -39,4 +40,5 @@ onDocumentReady(() => {
initSettings()
initOs()
initTabsets()
initPreview()
})
48 changes: 30 additions & 18 deletions assets/js/handlebars/templates/autocomplete-suggestions.handlebars
Original file line number Diff line number Diff line change
@@ -1,34 +1,46 @@
<div class="triangle"></div>
<div class="autocomplete-suggestions">
<div class="autocomplete-results">
<span>
Autocompletion results for <span class="bold">"{{term}}"</span>
</span>
<span class="press-return">
Press <span class="bold">RETURN</span> for full-text search
</span>
</div>
<div>
{{#each suggestions}}
<div class="autocomplete-container">
<div class="autocomplete-suggestions">
<div class="autocomplete-results">
<span>
Autocompletion results for <span class="bold">"{{term}}"</span>
</span>
<span class="press-return">
Press <span class="bold">RETURN</span> for full-text search, <span class="bold">TAB</span> for previews
</span>
</div>
<div>
{{#each suggestions}}
<a href="{{link}}" class="autocomplete-suggestion" data-index="{{@index}}" tabindex="-1">
<div class="title">
{{# if deprecated }}
<s><span class="header" translate="no">{{{title}}}</span></s>
<s><span class="header" translate="no">{{{title}}}</span></s>
{{ else }}
<span class="header" translate="no">{{{title}}}</span>
<span class="header" translate="no">{{{title}}}</span>
{{/if}}

{{#each labels}}
<span class="label">{{this}}</span>
<span class="label">{{this}}</span>
{{/each}}
<div class="autocomplete-suggestion-preview-indicator autocomplete-suggestion-preview-indicator-open" onclick="togglePreview()">
<button type="button">
Close Preview
</button>
</div>
<div class="autocomplete-suggestion-preview-indicator autocomplete-suggestion-preview-indicator-closed" onclick="togglePreview()">
<button type="button">
Open Preview <span class="ri-arrow-right-s-line"/>
</button>
</div>
</div>

{{#if description}}
<div class="description" translate="no">
{{{description}}}
</div>
<div class="description" translate="no">
{{{description}}}
</div>
{{/if}}
</a>
{{/each}}
{{/each}}
</div>
</div>
</div>
Loading