mirror of
https://codeberg.org/vlw/vlw.se.git
synced 2025-09-13 21:13:40 +02:00
feat: add new search UI (#24)
* feat: remove old search features * feat: add new page search ui
This commit is contained in:
parent
e1e3a4a68a
commit
3fd7ce6bf0
10 changed files with 270 additions and 253 deletions
|
@ -5,6 +5,7 @@
|
|||
|
||||
--padding: 20px;
|
||||
--running-size: 80px;
|
||||
--header-search-size: var(--running-size);
|
||||
}
|
||||
|
||||
/* # Cornerstones */
|
||||
|
@ -94,15 +95,23 @@ h3 {
|
|||
/* ## Buttons */
|
||||
|
||||
button {
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
color: inherit;
|
||||
fill: inherit;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* ### Inline */
|
||||
|
||||
button.inline {
|
||||
padding: calc(var(--padding) / 2) var(--padding);
|
||||
color: white;
|
||||
border: solid 2px white;
|
||||
border-radius: 6px;
|
||||
background-color: transparent;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
button.solid {
|
||||
button.inline.solid {
|
||||
color: black;
|
||||
border-color: var(--color-accent);
|
||||
background-color: var(--color-accent);
|
||||
|
@ -112,6 +121,8 @@ a > button::after {
|
|||
content: " ➜";
|
||||
}
|
||||
|
||||
/* ### Text links */
|
||||
|
||||
a[target="_blank"] > button::after,
|
||||
:is(h1, h2, h3, p, li) > a[target="_blank"]::after {
|
||||
content: " ↑";
|
||||
|
@ -135,13 +146,31 @@ header {
|
|||
border-bottom: var(--border-style);
|
||||
display: grid;
|
||||
align-items: stretch;
|
||||
justify-items: end;
|
||||
grid-template-columns: 1fr var(--running-size);
|
||||
grid-template-columns: 1fr var(--header-search-size) var(--running-size);
|
||||
grid-template-rows: var(--running-size);
|
||||
background-color: rgba(0, 0, 0, .8);
|
||||
z-index: 100;
|
||||
perspective: 3000px;
|
||||
-webkit-backdrop-filter: blur(20px);
|
||||
backdrop-filter: blur(20px);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
header > * {
|
||||
--anim-3d-depth: 5px;
|
||||
--anim-3d-peek: 25deg;
|
||||
|
||||
transition: 300ms background-color;
|
||||
transform: rotateX(0deg);
|
||||
backface-visibility: hidden;
|
||||
box-shadow: 0 var(--anim-3d-depth) 0 0 rgba(255, 255, 255, .2);
|
||||
}
|
||||
|
||||
/* enable 3d flip animation */
|
||||
@media not (prefers-reduced-motion: reduce) {
|
||||
header > * {
|
||||
transition: 600ms transform, 300ms background-color;
|
||||
}
|
||||
}
|
||||
|
||||
header nav {
|
||||
|
@ -150,27 +179,90 @@ header nav {
|
|||
padding: var(--padding);
|
||||
}
|
||||
|
||||
header .logo {
|
||||
width: calc(var(--running-size) - 1px);
|
||||
height: calc(var(--running-size) - 1px);
|
||||
display: grid;
|
||||
align-items: center;
|
||||
justify-items: center;
|
||||
border-left: var(--border-style);
|
||||
}
|
||||
|
||||
header .logo path.stroke {
|
||||
fill: var(--color-accent);
|
||||
}
|
||||
|
||||
header searchbox {
|
||||
header header .search {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* ### Buttons */
|
||||
|
||||
header button {
|
||||
--icon-size: 25px;
|
||||
|
||||
display: grid;
|
||||
width: 100%;
|
||||
border-left: var(--border-style);
|
||||
grid-template-columns: 1fr;
|
||||
align-items: center;
|
||||
justify-items: center;
|
||||
padding: var(--padding);
|
||||
gap: var(--padding);
|
||||
fill: var(--color-accent);
|
||||
font-size: 13px;
|
||||
color: rgba(255, 255, 255, .5);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
header button:not(.logo) svg {
|
||||
width: var(--icon-size);
|
||||
}
|
||||
|
||||
header button.search p {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* ### Searchbox */
|
||||
|
||||
header searchbox {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
width: 100%;
|
||||
height: var(--running-size);
|
||||
background-color: var(--color-accent);
|
||||
display: grid;
|
||||
align-items: stretch;
|
||||
grid-template-columns: 1fr var(--running-size);
|
||||
grid-template-rows: var(--running-size);
|
||||
box-shadow: none;
|
||||
transform: rotateX(180deg);
|
||||
}
|
||||
|
||||
header searchbox > * {
|
||||
box-shadow: 0 calc(var(--anim-3d-depth) * -1) 0 0 rgba(var(--primer-color-accent), .8);
|
||||
}
|
||||
|
||||
header searchbox button {
|
||||
transition: 300ms background-color, 300ms border-color;
|
||||
border-color: rgba(0, 0, 0, .1);
|
||||
fill: black;
|
||||
}
|
||||
|
||||
header searchbox input {
|
||||
padding: 0 var(--padding);
|
||||
background-color: transparent;
|
||||
outline: none;
|
||||
color: black;
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* #### Active */
|
||||
|
||||
header.searchboxActive > * {
|
||||
transform: rotateX(-180deg);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
header.searchboxActive searchbox {
|
||||
transform: rotateX(0);
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
/* ## Main */
|
||||
|
||||
main {
|
||||
transition: 400ms transform;
|
||||
position: relative;
|
||||
padding: calc(var(--padding) * 1.5);
|
||||
width: 100%;
|
||||
|
@ -186,105 +278,49 @@ main.loading > * {
|
|||
opacity: 0;
|
||||
}
|
||||
|
||||
/* ## Search */
|
||||
/* ## Search results */
|
||||
|
||||
/* ### Box */
|
||||
|
||||
searchbox {
|
||||
--icon-size: 25px;
|
||||
|
||||
display: grid;
|
||||
search-results {
|
||||
transition: 500ms opacity, 300ms transform;
|
||||
position: fixed;
|
||||
top: var(--running-size);
|
||||
right: 0;
|
||||
width: 100%;
|
||||
border-left: var(--border-style);
|
||||
grid-template-columns: var(--icon-size) 1fr;
|
||||
align-items: center;
|
||||
padding: var(--padding);
|
||||
gap: var(--padding);
|
||||
fill: var(--color-accent);
|
||||
font-size: 13px;
|
||||
color: rgba(255, 255, 255, .5);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
searchbox > svg {
|
||||
width: var(--icon-size);
|
||||
}
|
||||
|
||||
/* ### Dialog */
|
||||
|
||||
body.search-dialog-open main {
|
||||
transform: scale(.94);
|
||||
}
|
||||
|
||||
dialog.search {
|
||||
transition: 200ms height cubic-bezier(.41,0,.34,.99);
|
||||
margin: auto;
|
||||
width: 100%;
|
||||
max-width: 1000px;
|
||||
height: calc(var(--running-size) + (var(--padding) * 5));
|
||||
max-height: 1000px;
|
||||
border-color: transparent;
|
||||
background-color: transparent;
|
||||
overflow: visible;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
dialog.search.active {
|
||||
height: 70vh;
|
||||
}
|
||||
|
||||
dialog.search search {
|
||||
transition: 400ms transform, 200ms opacity;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: grid;
|
||||
grid-template-rows: var(--running-size) 1fr;
|
||||
gap: calc(var(--padding) * 2);
|
||||
transform: scale(1.1);
|
||||
overflow: hidden;
|
||||
background-color: rgba(255, 255, 255, .05);
|
||||
-webkit-backdrop-filter: blur(20px);
|
||||
backdrop-filter: brightness(.3) blur(20px);
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 10px 30px 10px black;
|
||||
height: calc(100svh - var(--running-size));
|
||||
background-color: black;
|
||||
pointer-events: none;
|
||||
opacity: 0;
|
||||
transform: scale(.99);
|
||||
transform-origin: 100% 0;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
body.search-dialog-open dialog.search search {
|
||||
transform: scale(1);
|
||||
padding: calc(var(--padding) * 1.5);
|
||||
search-results:not([vv-page]) {
|
||||
display: grid;
|
||||
align-items: center;
|
||||
justify-items: center;
|
||||
}
|
||||
|
||||
header.searchboxActive ~ search-results {
|
||||
opacity: 1;
|
||||
pointer-events: all;
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
search input {
|
||||
transition: 200ms background-color, 200ms box-shadow, 200ms color;
|
||||
border-radius: 6px;
|
||||
border: none;
|
||||
outline: none;
|
||||
color: black;
|
||||
font-size: 16px;
|
||||
padding: var(--padding) calc(var(--padding) * 1.5);
|
||||
background-color: rgba(255, 255, 255, .05);
|
||||
box-shadow: 0 5px 70px 10px rgba(0, 0, 0, .3);
|
||||
color: white;
|
||||
}
|
||||
/* ### "Start typing" prompt */
|
||||
|
||||
search input:focus {
|
||||
background-color: rgba(255, 255, 255, .9);
|
||||
box-shadow: 0 10px 30px 10px black;
|
||||
color: black;
|
||||
}
|
||||
|
||||
/* ### Search results */
|
||||
|
||||
dialog.search search search-results {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
dialog.search search search-results > svg {
|
||||
search-results .info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
margin: auto;
|
||||
width: 150px;
|
||||
fill: rgba(255, 255, 255, .05);
|
||||
gap: 3svh;
|
||||
}
|
||||
|
||||
search-results .info :is(svg, img) {
|
||||
width: 128px;
|
||||
fill: var(--color-accent);
|
||||
}
|
||||
|
||||
/* # Feature queries */
|
||||
|
@ -298,7 +334,7 @@ dialog.search search search-results > svg {
|
|||
|
||||
/* # Components */
|
||||
|
||||
button {
|
||||
button.inline {
|
||||
transition: 200ms background-color, 200ms border-color, 200ms color;
|
||||
}
|
||||
|
||||
|
@ -320,18 +356,31 @@ dialog.search search search-results > svg {
|
|||
fill: var(--color-accent);
|
||||
}
|
||||
|
||||
searchbox {
|
||||
transition: 200ms background-color;
|
||||
header searchbox button:hover {
|
||||
background-color: rgba(0, 0, 0, .08);
|
||||
}
|
||||
|
||||
searchbox:hover {
|
||||
background-color: rgba(255, 255, 255, .07);
|
||||
/* ### Search */
|
||||
|
||||
@media not (prefers-reduced-motion: reduce) {
|
||||
header:not(.searchboxActive) button.search:hover,
|
||||
header:not(.searchboxActive) button.search:hover + button.logo {
|
||||
transform: rotateX(calc(var(--anim-3d-peek) * -1));
|
||||
}
|
||||
|
||||
header:not(.searchboxActive) button.search:hover ~ searchbox {
|
||||
transform: rotateX(calc(180deg - var(--anim-3d-peek)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* # Size queries */
|
||||
|
||||
@media (min-width: 700px) {
|
||||
:root {
|
||||
--header-search-size: 250px;
|
||||
}
|
||||
|
||||
/* # Cornerstones */
|
||||
|
||||
body::before {
|
||||
|
@ -346,19 +395,49 @@ dialog.search search search-results > svg {
|
|||
|
||||
/* ## Header */
|
||||
|
||||
header {
|
||||
grid-template-columns: 1fr 250px var(--running-size);
|
||||
header nav {
|
||||
margin: 0 calc(var(--padding) / 2);
|
||||
}
|
||||
|
||||
header nav {
|
||||
justify-self: start;
|
||||
margin: 0 calc(var(--padding) / 2);
|
||||
header > button.search {
|
||||
grid-template-columns: var(--icon-size) 1fr;
|
||||
}
|
||||
|
||||
header > button.search p {
|
||||
display: initial;
|
||||
}
|
||||
|
||||
header.searchboxActive > nav {
|
||||
transform: rotateX(0deg);
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
/* ### Searchbox */
|
||||
|
||||
header searchbox {
|
||||
width: calc(var(--header-search-size) + var(--running-size));
|
||||
}
|
||||
|
||||
/* ### Menu */
|
||||
|
||||
/* Move the search box to the header */
|
||||
header searchbox {
|
||||
header > button.search {
|
||||
display: grid;
|
||||
justify-items: baseline;
|
||||
}
|
||||
|
||||
@media (min-height: 600px) {
|
||||
search-results {
|
||||
top: calc(var(--running-size) + var(--padding));
|
||||
width: 50%;
|
||||
height: calc(100svh - 100px);
|
||||
background-color: rgba(0, 0, 0, .8);
|
||||
box-shadow:
|
||||
inset 0 0 100px 200px rgba(0, 0, 0, 1),
|
||||
0 0 100px 200px rgba(0, 0, 0, 1)
|
||||
;
|
||||
--webkit-backdrop-filter: blur(15px);
|
||||
backdrop-filter: blur(15px);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -154,6 +154,10 @@ splash::after {
|
|||
opacity: 1;
|
||||
text-shadow: 0 0 10px rgba(var(--primer-color-accent), .4);
|
||||
}
|
||||
|
||||
button.email:hover {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
/* # Size quries */
|
||||
|
@ -169,8 +173,4 @@ splash::after {
|
|||
main img {
|
||||
width: 35vh;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
section.search {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
display: none;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: var(--padding);
|
||||
|
@ -21,6 +21,10 @@ section.search {
|
|||
margin-bottom: calc(var(--padding) * 2);
|
||||
}
|
||||
|
||||
main[vv-page="/search"] > section.search {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
section.search form {
|
||||
display: contents;
|
||||
}
|
||||
|
@ -31,6 +35,11 @@ section.search search {
|
|||
|
||||
section.search input {
|
||||
width: 100%;
|
||||
border: none;
|
||||
color: black;
|
||||
outline: none;
|
||||
padding: var(--padding);
|
||||
background-color: var(--color-accent);
|
||||
}
|
||||
|
||||
section.search button[type="submit"] {
|
||||
|
@ -42,10 +51,6 @@ section.search > svg {
|
|||
width: 100%;
|
||||
}
|
||||
|
||||
body:not([vv-page="/search"]) section.search {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* # Search results */
|
||||
|
||||
section.results .result {
|
||||
|
@ -54,19 +59,6 @@ section.results .result {
|
|||
gap: calc(var(--padding) / 2);
|
||||
}
|
||||
|
||||
/* ---- */
|
||||
|
||||
main > svg,
|
||||
dialog.search search search-results > svg {
|
||||
margin: auto;
|
||||
width: 150px;
|
||||
fill: rgba(255, 255, 255, .05);
|
||||
}
|
||||
|
||||
dialog.search search search-results .empty {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* ## Titles */
|
||||
|
||||
section.title a h2 {
|
||||
|
|
|
@ -1,72 +1,40 @@
|
|||
new vv.Interactions("document");
|
||||
|
||||
const mainElement = document.querySelector(vv._env.MAIN);
|
||||
new vv.Interactions("document", {
|
||||
navigateHome: () => new vv.Navigation("/").navigate(),
|
||||
closeSearchbox: () => document.querySelector("header").classList.remove("searchboxActive"),
|
||||
openSearchbox: () => {
|
||||
document.querySelector("header").classList.add("searchboxActive");
|
||||
// Select searchbox inner input element
|
||||
document.querySelector("searchbox input").focus();
|
||||
}
|
||||
});
|
||||
|
||||
// Crossfade pages on navigation
|
||||
// Or maybe I shouldn't... hmmm
|
||||
mainElement.addEventListener(vv.Navigation.events.LOADING, () => {
|
||||
mainElement.classList.add("loading");
|
||||
|
||||
// Clean up modified transform-origin if set after search dialog animation
|
||||
mainElement.style.removeProperty("transform-origin");
|
||||
});
|
||||
|
||||
mainElement.addEventListener(vv.Navigation.events.LOADED, () => {
|
||||
[...document.querySelectorAll("dialog")].forEach(element => element.close())
|
||||
|
||||
// Wait 200ms for the page fade-in animation to finish
|
||||
setTimeout(() => mainElement.classList.remove("loading"), 200);
|
||||
});
|
||||
|
||||
// Search dialog open/close logic
|
||||
{
|
||||
const CLASNAME_DIALOG_OPEN = "search-dialog-open";
|
||||
// Offset in pixels from scroll position when scaling the main element
|
||||
const TRANSFORM_ORIGIN_Y_PADDING = 350;
|
||||
const mainElement = document.querySelector(vv._env.MAIN);
|
||||
|
||||
const dialog = document.querySelector("dialog.search");
|
||||
|
||||
// "Polyfill" for HTMLDialogELement open and close events
|
||||
(new MutationObserver((mutations) => {
|
||||
// There is only one search dialog elemenet
|
||||
const target = mutations[0].target;
|
||||
|
||||
// Set or unset dialog open class on body depending on dialog visibility
|
||||
target.hasAttribute("open")
|
||||
? target.dispatchEvent(new Event("open"))
|
||||
: target.dispatchEvent(new Event("close"));
|
||||
|
||||
}).observe(dialog, { attributes: true }));
|
||||
|
||||
dialog.addEventListener("open", () => {
|
||||
// Scale main element from the current scroll position
|
||||
mainElement.style.setProperty("transform-origin", `50% calc(${window.scrollY}px + ${TRANSFORM_ORIGIN_Y_PADDING}px)`);
|
||||
|
||||
document.body.classList.add(CLASNAME_DIALOG_OPEN);
|
||||
mainElement.addEventListener(vv.Navigation.events.LOADING, () => {
|
||||
mainElement.classList.add("loading");
|
||||
});
|
||||
dialog.addEventListener("close", () => document.body.classList.remove(CLASNAME_DIALOG_OPEN));
|
||||
|
||||
// Close search dialog if dialog is clicked outside inner content
|
||||
dialog.addEventListener("click", (event) => event.target === dialog ? dialog.close() : null);
|
||||
|
||||
// Open search dialog when searchbox is clicked
|
||||
document.querySelector("searchbox").addEventListener("click", () => dialog.showModal());
|
||||
mainElement.addEventListener(vv.Navigation.events.LOADED, () => {
|
||||
// Close searchbox on main page navigation
|
||||
document.querySelector("header").classList.remove("searchboxActive");
|
||||
|
||||
// Wait 200ms for the page fade-in animation to finish
|
||||
setTimeout(() => mainElement.classList.remove("loading"), 200);
|
||||
});
|
||||
}
|
||||
|
||||
// Search logic
|
||||
// Handle search logic
|
||||
{
|
||||
const searchResultsElement = document.querySelector("search-results");
|
||||
const search = (query) => {
|
||||
new vv.Navigation(`/search?q=${query}`, {
|
||||
carrySearchParams: true
|
||||
}).navigate(searchResultsElement);
|
||||
};
|
||||
|
||||
// Run search on keyup
|
||||
document.querySelector("search input").addEventListener("keyup", (event) => search(event.target.value));
|
||||
|
||||
// Trigger expand search box animation
|
||||
document.querySelector("search input").addEventListener("keydown", () => {
|
||||
searchResultsElement.closest("dialog").classList.add("active");
|
||||
}, { once: true });
|
||||
document.querySelector("header input[type='search']").addEventListener("input", (event) => {
|
||||
// Debounce user input
|
||||
clearTimeout(event.target._throttle);
|
||||
event.target._throttle = setTimeout(() => {
|
||||
// Navigate search-results element on user input
|
||||
new vv.Navigation(`/search?q=${event.target.value}`).navigate(searchResultsElement);
|
||||
}, 100);
|
||||
});
|
||||
}
|
|
@ -1,25 +1 @@
|
|||
// Don't open the search dialog overlay if search page is open stand-alone
|
||||
{
|
||||
const searchBox = document.querySelector("body:not(.search-dialog-open) searchbox");
|
||||
|
||||
// Page is stand-alone
|
||||
if (searchBox) {
|
||||
// Shift focus to the on-page search box instead of opening search dialog on click
|
||||
const shiftSearchboxFocus = () => {
|
||||
// Override normal "open search dialog" behavior
|
||||
document.querySelector("dialog.search").close();
|
||||
|
||||
// Shift focus to the on-page search input instead
|
||||
}
|
||||
|
||||
// Bind event listener to searchbox element
|
||||
document.querySelector("body:not(.search-dialog-open) searchbox").addEventListener("click", shiftSearchboxFocus, true);
|
||||
|
||||
// Remove event listener from searchbox element on page navigation
|
||||
mainElement.addEventListener(vv.Navigation.events.LOADING, () => {
|
||||
searchBox.removeEventListener("click", shiftSearchboxFocus);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
new vv.Interactions("search");
|
BIN
assets/media/travolta.gif
Normal file
BIN
assets/media/travolta.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 238 KiB |
|
@ -49,8 +49,8 @@
|
|||
<h3>encrypt your message with my OpenPGP key.</h3>
|
||||
<p>my key is also listed on the <a href="https://keys.openpgp.org/search?q=victor%40vlw.se" target="_blank" rel="noopener noreferer">openPGP key server</a> for victor@vlw.se so your e-mail client can automatically retreive it if supported.</p>
|
||||
<div class="buttons">
|
||||
<a href="https://keys.openpgp.org/vks/v1/by-fingerprint/DCE987311CB5D2A252F58951D0AD730E1057DFC6"><button class="solid">download ASC</button></a>
|
||||
<a href="https://emailselfdefense.fsf.org/en/" target="_blank" rel="noopener noreferer"><button>more info</button></a>
|
||||
<a href="https://keys.openpgp.org/vks/v1/by-fingerprint/DCE987311CB5D2A252F58951D0AD730E1057DFC6"><button class="inline solid">download ASC</button></a>
|
||||
<a href="https://emailselfdefense.fsf.org/en/" target="_blank" rel="noopener noreferer"><button class="inline">more info</button></a>
|
||||
</div>
|
||||
</section>
|
||||
<?= VV::media("line.svg") ?>
|
||||
|
@ -77,7 +77,7 @@
|
|||
<label title="this field is required">your message<sup>*</sup></label>
|
||||
<textarea name="<?= ContactFieldsEnum::MESSAGE->value ?>" required placeholder="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed molestie dignissim mauris vel dignissim. Sed et aliquet odio, id egestas libero. Vestibulum ut dui a turpis aliquam hendrerit id et dui. Morbi eu tristique quam, sit amet dictum felis. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin ac nibh a ex accumsan ullamcorper non quis eros. Nam at suscipit lacus. Nullam placerat semper sapien, vitae aliquet nisl elementum a. Duis viverra quam eros, eu vestibulum quam egestas sit amet. Duis lobortis varius malesuada. Mauris in fringilla mi. "></textarea>
|
||||
</input-group>
|
||||
<button class="solid">send</button>
|
||||
<button class="inline solid">send</button>
|
||||
</form>
|
||||
</section>
|
||||
<?php else: ?>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
|
||||
<script>
|
||||
<!--//--><![CDATA[//><!--
|
||||
|
@ -44,25 +44,25 @@
|
|||
<nav>
|
||||
<p><a href="/" vv="document" vv-call="navigate">victor westerlund</a></p>
|
||||
</nav>
|
||||
<searchbox>
|
||||
<button class="search" vv="document" vv-call="openSearchbox">
|
||||
<?= VV::media("icons/search.svg") ?>
|
||||
<p>search anything...</p>
|
||||
<p>search vlw.se...</p>
|
||||
</button>
|
||||
<button class="logo" vv="document" vv-call="navigateHome"><?= VV::media("vw.svg") ?></button>
|
||||
<searchbox>
|
||||
<input type="search" autocomplete="off" placeholder="search vlw.se...">
|
||||
<button class="close" vv="document" vv-call="closeSearchbox"><?= VV::media("icons/close.svg") ?></button>
|
||||
</searchbox>
|
||||
<a href="/" vv="document" vv-call="navigate">
|
||||
<div class="logo">
|
||||
<?= VV::media("vw.svg") ?>
|
||||
</div>
|
||||
</a>
|
||||
</header>
|
||||
|
||||
<main></main>
|
||||
|
||||
<dialog class="search">
|
||||
<search>
|
||||
<input type="text" placeholder="start typing to search..."></input>
|
||||
<search-results></search-results>
|
||||
</search>
|
||||
</dialog>
|
||||
|
||||
<search-results>
|
||||
<div class="info empty">
|
||||
<?= VV::media("icons/search.svg") ?>
|
||||
<p>start typing to search</p>
|
||||
</div>
|
||||
</search-results>
|
||||
|
||||
<?php // Bootstrapping ?>
|
||||
<script><?= VV::init() ?></script>
|
||||
|
|
|
@ -18,12 +18,12 @@
|
|||
<section class="search">
|
||||
<form method="GET">
|
||||
<search>
|
||||
<input name="q" type="text" placeholder="search anything..." value="<?= $query ?>"></input>
|
||||
<input name="q" type="text" placeholder="search vlw.se..." value="<?= $query ?>"></input>
|
||||
</search>
|
||||
<button type="submit" class="solid">Search</button>
|
||||
<button type="submit" class="inline solid">Search</button>
|
||||
</form>
|
||||
<?= VV::media("line.svg") ?>
|
||||
<button>advanced search options</button>
|
||||
<button class="inline">advanced search options</button>
|
||||
</section>
|
||||
|
||||
<?php if ($response): ?>
|
||||
|
@ -33,7 +33,7 @@
|
|||
<?php // Do things depending on the response code from API ?>
|
||||
<?php switch ($response->code): default: ?>
|
||||
<?php // An unknown error occured ?>
|
||||
<section class="error">
|
||||
<section class="info">
|
||||
<p>Something went wrong</p>
|
||||
</section>
|
||||
<?php break; ?>
|
||||
|
@ -69,9 +69,9 @@
|
|||
<?php foreach ($result["actions"] as $action): ?>
|
||||
|
||||
<?php if (!$action["external"]): ?>
|
||||
<a href="<?= $action["href"] ?>" vv="search" vv-call="navigate"><button class="<?= $action["class_list"] ?>"><?= $action["display_text"] ?></button></a>
|
||||
<a href="<?= $action["href"] ?>" vv="search" vv-call="navigate"><button class="inline <?= $action["class_list"] ?>"><?= $action["display_text"] ?></button></a>
|
||||
<?php else: ?>
|
||||
<a href="<?= $action["href"] ?>" target="_blank"><button class="<?= $action["class_list"] ?>"><?= $action["display_text"] ?></button></a>
|
||||
<a href="<?= $action["href"] ?>" target="_blank"><button class="inline <?= $action["class_list"] ?>"><?= $action["display_text"] ?></button></a>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php endforeach; ?>
|
||||
|
@ -87,7 +87,8 @@
|
|||
|
||||
<?php // No search matches were found ?>
|
||||
<?php else: ?>
|
||||
<section class="empty">
|
||||
<section class="info noresults">
|
||||
<img src="/assets/media/travolta.gif" alt="">
|
||||
<p>No results for search term "<?= $_GET["q"] ?>"</p>
|
||||
</section>
|
||||
<?php endif; ?>
|
||||
|
@ -96,7 +97,7 @@
|
|||
|
||||
<?php // No access to the search endpoint ?>
|
||||
<?php case 404: ?>
|
||||
<section class="error">
|
||||
<section class="info">
|
||||
<p>Connection to VLW API was successful but lacking permission to search</p>
|
||||
</section>
|
||||
<?php break; ?>
|
||||
|
@ -109,15 +110,16 @@
|
|||
|
||||
<?php // Check the error code of the current error ?>
|
||||
<?php switch ($error_code): default: ?>
|
||||
<section class="error">
|
||||
<section class="info">
|
||||
<p>Unknown request validation error</p>
|
||||
</section>
|
||||
<?php break; ?>
|
||||
|
||||
<?php // Search query string is not long enough ?>
|
||||
<?php case "VALUE_MIN_ERROR": ?>
|
||||
<section class="error">
|
||||
<p>Type at least <?= $error_msg ?> characters to search!</p>
|
||||
<section class="info">
|
||||
<?= VV::media("icons/search.svg") ?>
|
||||
<p>type at least <?= $error_msg ?> characters to search!</p>
|
||||
</section>
|
||||
<?php break; ?>
|
||||
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
<?= VV::media("icons/github.svg") ?>
|
||||
<p>Most of my free open-source software is available on GitHub and it's also mirrored on my server</p>
|
||||
<div class="buttons">
|
||||
<a href="https://github.com/victorwesterlund"><button class="solid">open GitHub</button></a>
|
||||
<a href="https://git.vlw.se"><button>mirror</button></a>
|
||||
<a href="https://github.com/victorwesterlund"><button class="inline solid">open GitHub</button></a>
|
||||
<a href="https://git.vlw.se"><button class="inline">mirror</button></a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
@ -132,7 +132,7 @@
|
|||
$link_href = $action["href"] === null ? "/work/{$item["id"]}" : $action["href"];
|
||||
?>
|
||||
|
||||
<a href="<?= $link_href ?>" <?= $link_attr ?>><button class="<?= $action["class_list"] ?>"><?= $action["display_text"] ?></button></a>
|
||||
<a href="<?= $link_href ?>" <?= $link_attr ?>><button class="inline <?= $action["class_list"] ?>"><?= $action["display_text"] ?></button></a>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
|
Loading…
Add table
Reference in a new issue