#36 close popup via x or click outside

This commit is contained in:
neil 2022-12-23 10:31:36 +08:00
parent b04975861e
commit 363670a431
3 changed files with 62 additions and 36 deletions

View file

@ -9,16 +9,16 @@
import { installPackage } from '@api'; import { installPackage } from '@api';
import type { AirtablePost } from '@tea/ui/types'; import type { AirtablePost } from '@tea/ui/types';
let term: string; let term: string;
let packagesFound: GUIPackage[] = []; let packages: GUIPackage[] = [];
let articles: AirtablePost[] = []; // news, blogs, etc let articles: AirtablePost[] = []; // news, blogs, etc
let workshops: AirtablePost[] = []; // workshops, course let workshops: AirtablePost[] = []; // workshops, course
let loading = true;
searchStore.subscribe((v) => { searchStore.subscribe((v) => {
term = v; term = v;
}); });
searchStore.packagesSearch.subscribe((pkgs) => { searchStore.packagesSearch.subscribe((pkgs) => {
packagesFound = pkgs; packages = pkgs;
}); });
searchStore.postsSearch.subscribe((posts) => { searchStore.postsSearch.subscribe((posts) => {
let partialArticles: AirtablePost[] = []; let partialArticles: AirtablePost[] = [];
@ -36,6 +36,8 @@
workshops = partialWorkshops; workshops = partialWorkshops;
}); });
searchStore.searching.subscribe((v) => (loading = v));
const getCTALabel = (state: PackageStates): string => { const getCTALabel = (state: PackageStates): string => {
return { return {
[PackageStates.AVAILABLE]: 'INSTALL', [PackageStates.AVAILABLE]: 'INSTALL',
@ -44,24 +46,32 @@
[PackageStates.UNINSTALLED]: 'RE-INSTALL' [PackageStates.UNINSTALLED]: 'RE-INSTALL'
}[state]; }[state];
}; };
const onClose = () => {
term = '';
};
</script> </script>
<section class={term ? 'show' : ''}> <section class={term ? 'show' : ''}>
<div class="border border-gray bg-black"> <!-- svelte-ignore a11y-click-events-have-key-events -->
<header class="p-4 text-2xl text-primary"> <figure on:click={onClose} />
Showing search results for `{term}` <div class="z-20 border border-gray bg-black">
<header class="flex justify-between p-4">
<div class="text-2xl text-primary">Showing search results for `{term}`</div>
<button on:click={onClose}>&#x2715</button>
</header> </header>
<menu class="flex h-8 w-full gap-4 bg-accent px-4 text-xs"> <menu class="flex h-8 w-full gap-4 bg-accent px-4 text-xs">
<button>packages ({packagesFound.length})</button> <button>packages ({packages.length})</button>
<button>articles ({articles.length})</button> <button>articles ({articles.length})</button>
<button>workshops ({workshops.length})</button> <button>workshops ({workshops.length})</button>
</menu> </menu>
<header class="p-4 text-lg text-primary"> <header class="p-4 text-lg text-primary">
Top Package Results ({packagesFound.length}) Top Package Results ({packages.length})
</header> </header>
<ul class="grid grid-cols-3"> <ul class="grid grid-cols-3">
{#if packagesFound.length > 0} {#if packages.length > 0}
{#each packagesFound as pkg} {#each packages as pkg}
<div class={pkg.state === PackageStates.INSTALLING ? 'animate-pulse' : ''}> <div class={pkg.state === PackageStates.INSTALLING ? 'animate-pulse' : ''}>
<PackageCard <PackageCard
{pkg} {pkg}
@ -79,7 +89,7 @@
/> />
</div> </div>
{/each} {/each}
{:else} {:else if loading}
{#each Array(12) as _} {#each Array(12) as _}
<section class="h-50 border border-gray p-4"> <section class="h-50 border border-gray p-4">
<Preloader /> <Preloader />
@ -92,7 +102,7 @@
</header> </header>
{#if articles.length} {#if articles.length}
<Posts posts={articles} linkTarget="_blank" /> <Posts posts={articles} linkTarget="_blank" />
{:else} {:else if loading}
<section class="h-64 border border-gray bg-black p-4"> <section class="h-64 border border-gray bg-black p-4">
<Preloader /> <Preloader />
</section> </section>
@ -102,7 +112,7 @@
</header> </header>
{#if workshops.length} {#if workshops.length}
<Posts posts={workshops} linkTarget="_blank" /> <Posts posts={workshops} linkTarget="_blank" />
{:else} {:else if loading}
<section class="h-64 border border-gray bg-black p-4"> <section class="h-64 border border-gray bg-black p-4">
<Preloader /> <Preloader />
</section> </section>
@ -122,14 +132,23 @@
opacity: 0%; opacity: 0%;
overflow: hidden; overflow: hidden;
height: 0px; height: 0px;
z-index: 10;
} }
section > figure {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
}
section.show { section.show {
opacity: 100%; opacity: 100%;
height: 100%; height: 100%;
} }
section > div { section > div {
position: relative;
height: 0%; height: 0%;
transition: height 0.6s ease-in-out; transition: height 0.6s ease-in-out;
overflow-y: scroll; overflow-y: scroll;

View file

@ -119,6 +119,7 @@ function initPosts() {
export const postsStore = initPosts(); export const postsStore = initPosts();
function initSearchStore() { function initSearchStore() {
const searching = writable<boolean>(false);
const { subscribe, set } = writable<string>(''); const { subscribe, set } = writable<string>('');
const packagesSearch = writable<GUIPackage[]>([]); const packagesSearch = writable<GUIPackage[]>([]);
const postsSearch = writable<AirtablePost[]>([]); const postsSearch = writable<AirtablePost[]>([]);
@ -137,18 +138,29 @@ function initSearchStore() {
return { return {
term, term,
searching,
packagesSearch, packagesSearch,
postsSearch, postsSearch,
packagesFound, packagesFound,
subscribe, subscribe,
search: async (term: string) => { search: async (term: string) => {
searching.set(true);
try {
if (term) {
const [resultPkgs, resultPosts] = await Promise.all([ const [resultPkgs, resultPosts] = await Promise.all([
packagesStore.search(term, 5), packagesStore.search(term, 5),
postsStore.search(term, 10) postsStore.search(term, 10)
]); ]);
packagesSearch.set(resultPkgs); packagesSearch.set(resultPkgs);
postsSearch.set(resultPosts); postsSearch.set(resultPosts);
} else {
packagesSearch.set([]);
postsSearch.set([]);
}
set(term); set(term);
} finally {
searching.set(false);
}
} }
}; };
} }

View file

@ -6,7 +6,7 @@
import FooterLinks from '$components/FooterLinks/FooterLinks.svelte'; import FooterLinks from '$components/FooterLinks/FooterLinks.svelte';
import { backLink as backLinkStore } from '$libs/stores'; import { backLink as backLinkStore } from '$libs/stores';
import SearchResults from '$components/SearchResults/SearchResults.svelte'; import SearchPopupResults from '$components/SearchPopupResults/SearchPopupResults.svelte';
let view: HTMLElement; let view: HTMLElement;
@ -37,7 +37,7 @@
<footer class="mt-8 w-full border border-r-0 border-gray bg-black"> <footer class="mt-8 w-full border border-r-0 border-gray bg-black">
<FooterLinks /> <FooterLinks />
</footer> </footer>
<SearchResults /> <SearchPopupResults />
</section> </section>
</div> </div>
@ -58,15 +58,17 @@
overflow-y: scroll; overflow-y: scroll;
} }
@media screen and (min-width: 1440px) {
figure { figure {
position: fixed;
z-index: 0; z-index: 0;
position: fixed;
top: 220px; top: 220px;
left: 240px; left: 240px;
right: 0px; right: 0px;
bottom: 0px; bottom: 0px;
background-image: url('/images/gui-background-grid.svg'); background-image: url('/images/gui-background-grid.svg');
}
@media screen and (min-width: 1440px) {
figure {
background-size: cover; background-size: cover;
background-repeat: repeat-y; background-repeat: repeat-y;
} }
@ -76,13 +78,6 @@
} }
@media screen and (max-width: 1440px) { @media screen and (max-width: 1440px) {
figure { figure {
position: fixed;
z-index: 0;
top: 220px;
left: 240px;
right: 0px;
bottom: 0px;
background-image: url('/images/gui-background-grid.svg');
background-size: contain; background-size: contain;
background-repeat: repeat; background-repeat: repeat;
} }