|
1 | | -<!-- @component |
2 | | -Renders a search widget which when clicked (or the corresponding keyboard shortcut is pressed) opens a search overlay. |
3 | | ---> |
4 | | -<script> |
5 | | - import { BROWSER } from 'esm-env'; |
6 | | - import { query, searching } from './stores.js'; |
7 | | -
|
8 | | - export let q = ''; |
| 1 | +<script lang="ts"> |
| 2 | + import { Icon } from '@steeze-ui/svelte-icon'; |
| 3 | + import { MagnifyingGlass } from '@steeze-ui/heroicons'; |
| 4 | + import { modalStore, type ModalSettings } from '@codingcatdev/blackcatui'; |
| 5 | + import SearchModal from '$lib/search/SearchModal.svelte'; |
| 6 | + import { query } from './stores.js'; |
| 7 | +
|
| 8 | + const showSearch = () => { |
| 9 | + const d: ModalSettings = { |
| 10 | + type: 'component', |
| 11 | + component: { |
| 12 | + ref: SearchModal |
| 13 | + } |
| 14 | + }; |
| 15 | + modalStore.trigger(d); |
| 16 | + }; |
9 | 17 | </script> |
10 | 18 |
|
11 | | -<form class="search-container" action="/search"> |
12 | | - <input |
13 | | - value={q} |
14 | | - on:input={(e) => { |
15 | | - $searching = true; |
16 | | - $query = e.currentTarget.value; |
17 | | - e.currentTarget.value = ''; |
18 | | - }} |
19 | | - on:mousedown|preventDefault={() => ($searching = true)} |
20 | | - on:touchend|preventDefault={() => ($searching = true)} |
21 | | - type="search" |
22 | | - name="q" |
23 | | - placeholder="Search" |
24 | | - aria-label="Search" |
25 | | - spellcheck="false" |
26 | | - /> |
27 | | - |
28 | | - {#if BROWSER} |
29 | | - <div class="shortcut"> |
30 | | - <kbd>{navigator.platform === 'MacIntel' ? '⌘' : 'Ctrl'}</kbd> <kbd>K</kbd> |
31 | | - </div> |
32 | | - {/if} |
33 | | -</form> |
34 | | - |
35 | | -<style> |
36 | | - @keyframes fade-in { |
37 | | - from { |
38 | | - opacity: 0; |
39 | | - } |
40 | | - to { |
41 | | - opacity: 1; |
42 | | - } |
43 | | - } |
44 | | -
|
45 | | - .search-container { |
46 | | - position: relative; |
47 | | - display: flex; |
48 | | - align-items: center; |
49 | | - width: 100%; |
50 | | - height: 100%; |
51 | | - } |
52 | | -
|
53 | | - input { |
54 | | - padding: 0.5em 0.5em 0.4em 2em; |
55 | | - border: 1px solid var(--sk-back-translucent); |
56 | | - font-family: inherit; |
57 | | - font-size: 1.4rem; |
58 | | - /* text-align: center; */ |
59 | | - appearance: none; |
60 | | - -webkit-appearance: none; |
61 | | - width: 100%; |
62 | | - height: 3.2rem; |
63 | | - border-radius: var(--sk-border-radius); |
64 | | - background: no-repeat 1rem 50% / 1em 1em url(../icons/search.svg); |
65 | | - color: var(--sk-text-3); |
66 | | - } |
67 | | -
|
68 | | - input:focus + .shortcut { |
69 | | - display: none; |
70 | | - } |
71 | | -
|
72 | | - input::placeholder { |
73 | | - font-size: 1.2rem; |
74 | | - text-transform: uppercase; |
75 | | - } |
76 | | -
|
77 | | - .shortcut { |
78 | | - color: var(--sk-text-3); |
79 | | - position: absolute; |
80 | | - top: calc(50% - 0.9rem); |
81 | | - right: 0; |
82 | | - width: 100%; |
83 | | - text-align: right; |
84 | | - pointer-events: none; |
85 | | - font-size: 1.2rem; |
86 | | - text-transform: uppercase; |
87 | | - animation: fade-in 0.2s; |
88 | | - } |
89 | | -
|
90 | | - kbd { |
91 | | - display: none; |
92 | | - background: var(--sk-back-2); |
93 | | - border: 1px solid var(--sk-back-translucent); |
94 | | - padding: 0.2rem 0.2rem 0rem 0.2rem; |
95 | | - color: var(--sk-text-3); |
96 | | - font-size: inherit; |
97 | | - font-family: inherit; |
98 | | - border-radius: 2px; |
99 | | - } |
100 | | -
|
101 | | - @media (min-width: 800px) { |
102 | | - .search-container { |
103 | | - width: 11rem; |
104 | | - } |
105 | | -
|
106 | | - .shortcut { |
107 | | - padding: 0 1.6rem 0 0; |
108 | | - } |
109 | | -
|
110 | | - input { |
111 | | - border-radius: 1.6rem; |
112 | | - } |
113 | | -
|
114 | | - input::placeholder { |
115 | | - opacity: 0; |
116 | | - } |
117 | | -
|
118 | | - /* we're using media query as an imperfect proxy for mobile/desktop */ |
119 | | - kbd { |
120 | | - display: inline; |
121 | | - } |
122 | | - } |
123 | | -
|
124 | | - @media (min-width: 960px) { |
125 | | - .search-container { |
126 | | - width: 19rem; |
127 | | - } |
128 | | -
|
129 | | - input::placeholder { |
130 | | - opacity: 1; |
131 | | - } |
132 | | - } |
133 | | -</style> |
| 19 | +<svelte:window |
| 20 | + on:keydown={(e) => { |
| 21 | + if (e.key === 'k' && (navigator.platform === 'MacIntel' ? e.metaKey : e.ctrlKey)) { |
| 22 | + e.preventDefault(); |
| 23 | + $query = ''; |
| 24 | + if ($modalStore.length > 0) { |
| 25 | + modalStore.close(); |
| 26 | + } else { |
| 27 | + showSearch(); |
| 28 | + } |
| 29 | + } |
| 30 | + |
| 31 | + if (e.code === 'Escape') { |
| 32 | + close(); |
| 33 | + } |
| 34 | + }} |
| 35 | +/> |
| 36 | + |
| 37 | +<button |
| 38 | + class="bcu-button p-2 px-4 space-x-4 variant-soft hover:variant-soft-primary flex align-middle" |
| 39 | + on:mousedown|preventDefault={() => showSearch()} |
| 40 | + on:touchend|preventDefault={() => showSearch()} |
| 41 | +> |
| 42 | + <Icon src={MagnifyingGlass} theme="solid" class="w-6" /> |
| 43 | + <span class="hidden md:inline-block badge variant-soft">⌘+K</span></button |
| 44 | +> |
0 commit comments