Skip to content

Commit 99cdc6a

Browse files
committed
feat: ⚡
1 parent 04d5898 commit 99cdc6a

18 files changed

+1981
-389
lines changed

README.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# svelte-spotlight ![svelte-themes minzip package size](https://img.shields.io/bundlephobia/minzip/svelte-spotlight) ![Version](https://img.shields.io/npm/v/svelte-spotlight.svg?colorB=green)
2+
3+
Headless spotlight component for Svelte
4+
5+
Build your site global search box in minutes
6+
7+
```bash
8+
pnpm add svelte-spotlight
9+
10+
npm install svelte-spotlight
11+
12+
yarn add svelte-spotlight
13+
```
14+
15+
- ✅ Bring your own style, completely headless. Svelte-spotlight only handle the layout.
16+
- ✅ Search method agnostic, local or asynchronous.
17+
- ✅ Data agnostic, render flat lists or grouped results. Integrate perfectly with Algolia
18+
- ✅ multi-index search.
19+
- ✅ Great DX with full TS support
20+
- ✅ 9 slots to customize every part you need
21+
- ✅ Animate it as you wish
22+
- ✅ Keyboard shortcut and navigation
23+
- ✅ Accessible
24+
25+
# [DOCUMENTATION & EXAMPLES](https://svelte-spotlight.vercel.app)

documentation/package.json

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,38 +13,38 @@
1313
"format": "prettier --ignore-path .gitignore --write --plugin-search-dir=. ."
1414
},
1515
"dependencies": {
16-
"svelte-spotlight": "workspace:*",
1716
"@algolia/client-search": "^4.13.0",
18-
"@fontsource/fira-mono": "^4.5.4",
19-
"@playwright/test": "^1.20.0",
17+
"@fontsource/fira-mono": "^4.5.7",
18+
"@playwright/test": "^1.20.2",
2019
"@sveltejs/adapter-auto": "next",
2120
"@sveltejs/kit": "next",
2221
"@types/cookie": "^0.4.1",
23-
"@typescript-eslint/eslint-plugin": "^5.16.0",
24-
"@typescript-eslint/parser": "^5.16.0",
22+
"@typescript-eslint/eslint-plugin": "^5.18.0",
23+
"@typescript-eslint/parser": "^5.18.0",
2524
"algoliasearch": "^4.13.0",
2625
"autoprefixer": "^10.4.4",
27-
"daisyui": "^2.11.1",
26+
"daisyui": "^2.13.6",
2827
"eslint": "^7.32.0",
2928
"eslint-config-prettier": "^8.5.0",
3029
"eslint-plugin-svelte3": "^3.4.1",
3130
"match-sorter": "^6.3.1",
3231
"phosphor-svelte": "^1.1.2",
3332
"postcss": "^8.4.12",
34-
"prettier": "^2.6.0",
35-
"prettier-plugin-svelte": "^2.6.0",
33+
"prettier": "^2.6.2",
34+
"prettier-plugin-svelte": "^2.7.0",
3635
"prism-svelte": "^0.5.0",
3736
"prismjs": "^1.27.0",
38-
"svelte": "^3.46.4",
39-
"svelte-check": "^2.4.6",
37+
"svelte": "^3.47.0",
38+
"svelte-check": "^2.6.0",
4039
"svelte-icons": "^2.1.0",
41-
"svelte-preprocess": "^4.10.4",
40+
"svelte-preprocess": "^4.10.5",
41+
"svelte-spotlight": "workspace:*",
4242
"svelte-themes": "^0.0.98",
43-
"svelte2tsx": "^0.5.6",
43+
"svelte2tsx": "^0.5.8",
4444
"tailwindcss": "^3.0.23",
4545
"tslib": "^2.3.1",
46-
"type-fest": "^2.12.1",
47-
"typescript": "~4.6.2"
46+
"type-fest": "^2.12.2",
47+
"typescript": "~4.6.3"
4848
},
4949
"type": "module",
5050
"svelte": "SvelteSpotlight.svelte"

documentation/src/components/Anatomy/Anatomy.svelte

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
component: DynamicSlots
3030
}
3131
];
32+
3233
let currentTab = tabs[0];
3334
</script>
3435

documentation/src/components/Anatomy/Classes.svelte

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,17 @@
1919
<code class="class">.sl-content</code> <code class="props">contentClass</code>
2020
</div>
2121
<div class="anatomy-part col-span-8 opacity-40">Content top</div>
22-
<div class="anatomy-part col-span-5 ">
22+
<div class="anatomy-part col-span-5">
2323
<div>
2424
<code class="class">.sl-results</code>
2525
<code class="props">resultsClass</code>
2626
</div>
27-
<div class="anatomy-part mt-3 opacity-40 ">Group header</div>
28-
<div class="anatomy-part mt-3 opacity-40 ">Result</div>
27+
28+
<div class="anatomy-part mt-3">
29+
<div><code class="class">.sl-results-list</code></div>
30+
<div class="anatomy-part mt-3 opacity-40 ">Group header</div>
31+
<div class="anatomy-part mt-3"><code class="class">.sl-results-item</code></div>
32+
</div>
2933
</div>
3034
<div class="anatomy-part col-span-3 opacity-40 ">Side panel</div>
3135
<div class="anatomy-part col-span-8 opacity-40 ">Content bottom</div>

documentation/src/components/Anatomy/DynamicSlots.svelte

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,12 @@
1313
<div class="col-span-8"><code class="props">contentComponent</code></div>
1414
<div class="anatomy-part col-span-8 opacity-40 ">Content top</div>
1515
<div class="anatomy-part col-span-5 opacity-40 ">
16-
<div>Results / Groups</div>
17-
<div class="anatomy-part mt-3 ">Group header</div>
18-
<div class="anatomy-part mt-3 ">Result</div>
16+
<div>Results</div>
17+
<div class="anatomy-part mt-3">
18+
<div>Group</div>
19+
<div class="anatomy-part mt-3 ">Group header</div>
20+
<div class="anatomy-part mt-3 ">Result</div>
21+
</div>
1922
</div>
2023
<div class="anatomy-part col-span-3 opacity-40 ">Side panel</div>
2124
<div class="anatomy-part col-span-8 opacity-40">Content bottom</div>

documentation/src/components/Anatomy/Slots.svelte

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,13 @@
1717
<code class="props">contentTop</code>
1818
</div>
1919
<div class="anatomy-part col-span-5 ">
20-
<div class="opacity-40">Results / Groups</div>
21-
<div class="anatomy-part mt-3"><code class="props">groupHeader</code></div>
22-
<div class="anatomy-part mt-3"><code class="props">result</code></div>
20+
<div class="opacity-40">Results</div>
21+
22+
<div class="anatomy-part mt-3">
23+
<div class="opacity-40">Group</div>
24+
<div class="anatomy-part mt-3"><code class="props">groupHeader</code></div>
25+
<div class="anatomy-part mt-3"><code class="props">result</code></div>
26+
</div>
2327
</div>
2428
<div class="anatomy-part col-span-3"><code class="props">sidePanel</code></div>
2529
<div class="anatomy-part col-span-8 ">

documentation/src/components/Anatomy/Structure.svelte

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,12 @@
1111
<div class="col-span-8">Content</div>
1212
<div class="anatomy-part col-span-8 ">Content top</div>
1313
<div class="anatomy-part col-span-5 ">
14-
<div>Results / Groups</div>
15-
<div class="anatomy-part mt-3">Group header</div>
16-
<div class="anatomy-part mt-3">Result</div>
14+
<div>Results</div>
15+
<div class="anatomy-part mt-3">
16+
<div>Group</div>
17+
<div class="anatomy-part mt-3">Group header</div>
18+
<div class="anatomy-part mt-3">Result</div>
19+
</div>
1720
</div>
1821
<div class="anatomy-part col-span-3 ">Side panel</div>
1922
<div class="anatomy-part col-span-8 ">Content bottom</div>

documentation/src/components/Examples/example.ts

Lines changed: 57 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
export const tailwind = `<script lang="ts">
2-
import SvelteSpotlight from 'svelte-spotlight';
2+
import SvelteSpotlight from 'svelte-spotlight/SvelteSpotlight.svelte';
33
import { matchSorter } from 'match-sorter';
44
let query = "";
55
let items = [
@@ -44,7 +44,7 @@ $: results = matchSorter(items, query, { keys: ['title'] });
4444
</div>
4545
</SvelteSpotlight>`;
4646
export const css = `<script lang="ts">
47-
import SvelteSpotlight from 'svelte-spotlight';
47+
import SvelteSpotlight from 'svelte-spotlight/SvelteSpotlight.svelte';
4848
import { matchSorter } from 'match-sorter';
4949
let query = "";
5050
let items = [
@@ -87,51 +87,61 @@ $: results = matchSorter(items, query, { keys: ['title'] });
8787
</SvelteSpotlight>
8888
8989
<style>
90-
.result {
91-
cursor: pointer;
92-
font-size: 14px;
93-
padding-left: 2.5rem;
94-
padding-right: 2.5rem;
95-
padding-top: 0.75rem;
96-
padding-bottom: 0.75rem;
97-
width: 100%;
98-
color: black;
99-
}
100-
.noResults,
101-
.result p {
102-
color: gray;
103-
font-size: 12px;
104-
}
105-
.result:hover,
106-
.result[data-selected='true'] {
107-
background: whitesmoke;
108-
}
109-
.noResults{
110-
padding-left: 2.5rem;
111-
padding-right: 2.5rem;
112-
padding-top: 0.75rem;
113-
padding-bottom: 0.75rem;
114-
}
115-
:global(.sl-modal) {
116-
width: 600px;
117-
max-width: 95%;
118-
background: white;
119-
box-shadow: 0 0 #0000, 0 0 #0000, 0 10px 15px -3px rgb(0 0 0 / 0.1),
120-
0 4px 6px -4px rgb(0 0 0 / 0.1);
121-
border-radius: 0.1rem;
122-
}
90+
.result {
91+
cursor: pointer;
92+
font-size: 14px;
93+
width: 100%;
94+
color: black;
95+
padding-left: 2.5rem;
96+
padding-right: 2.5rem;
97+
padding-top: 0.75rem;
98+
padding-bottom: 0.75rem;
99+
}
100+
.noResults,
101+
.result p {
102+
color: gray;
103+
font-size: 12px;
104+
}
105+
.result:hover,
106+
.result[data-selected="true"] {
107+
background: whitesmoke;
108+
}
109+
.noResults {
110+
padding-left: 2.5rem;
111+
padding-right: 2.5rem;
112+
padding-top: 0.75rem;
113+
padding-bottom: 0.75rem;
114+
}
115+
:global(.sl-modal) {
116+
width: 600px;
117+
max-width: 95%;
118+
background: white;
119+
box-shadow: 0 0 #0000, 0 0 #0000, 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
120+
border-radius: 0.1rem;
121+
}
122+
123+
:global(.sl-results-item) {
124+
display: flex;
125+
}
126+
127+
:global(.sl-results-list) {
128+
padding: 0px !important;
129+
margin: 0px !important;
130+
}
123131
124-
:global(.sl-header) {
125-
padding-left: 2.5rem;
126-
padding-right: 2.5rem;
127-
padding-top: 0.75rem;
128-
padding-bottom: 0.75rem;
129-
border-bottom: 2px whitesmoke solid;
130-
}
132+
:global(.sl-header) {
133+
padding-left: 2.5rem;
134+
padding-right: 2.5rem;
135+
padding-top: 0.75rem;
136+
padding-bottom: 0.75rem;
137+
border-bottom: 2px whitesmoke solid;
138+
}
131139
132-
:global(.sl-input) {
133-
outline: none;
134-
background: transparent;
135-
color: #000000;
136-
}
140+
:global(.sl-input) {
141+
outline: none;
142+
background: transparent;
143+
color: #000000;
144+
border: none;
145+
padding: 10px 20px;
146+
}
137147
</style>`;

documentation/src/components/Navigation.svelte

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
export let isAlgoliaExampleOpen;
55
export let isSimpleExampleOpen;
66
const links = ['Installation', 'Anatomy', 'Props', 'Slots', 'Example'];
7+
import { browser } from '$app/env';
8+
$: isMac = browser && /mac/i.test(navigator.platform);
79
</script>
810

911
<div class="flex-1 flex flex-col">
@@ -25,15 +27,15 @@
2527
class="btn btn-outline btn-accent mt-5"
2628
on:click={() => (isAlgoliaExampleOpen = !isAlgoliaExampleOpen)}
2729
>
28-
Open complex Algolia example ( + k)
30+
Open complex Algolia example ({!isMac ? 'ctrl' : ''} + k)
2931
</button>
3032
</div>
3133
<div class="px-4">
3234
<button
3335
class="btn btn-outline btn-secondary mt-5"
3436
on:click={() => (isSimpleExampleOpen = !isSimpleExampleOpen)}
3537
>
36-
Open basic documentation example ( + j)
38+
Open basic documentation example ({!isMac ? 'ctrl' : ''} + j)
3739
</button>
3840
</div>
3941
</div>

documentation/src/components/Props/Props.svelte

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,18 @@
8181
description: 'Whether the search input is focused',
8282
type: 'boolean',
8383
defaultValue: 'false'
84+
},
85+
{
86+
name: 'listElement',
87+
description: ' HTML element type for the the result list',
88+
type: 'string',
89+
defaultValue: 'ul'
90+
},
91+
{
92+
name: 'resultElement',
93+
description: 'HTML element type for the result element',
94+
type: 'string',
95+
defaultValue: 'li'
8496
}
8597
]
8698
},

documentation/src/components/Simple/Simple.svelte

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
<script lang="ts">
22
import SvelteSpotlight from 'svelte-spotlight/src/lib/SvelteSpotlight.svelte';
33
import { matchSorter } from 'match-sorter';
4+
import { browser } from '$app/env';
5+
46
export let isOpen;
57
let query = '';
68
let items = [
@@ -36,9 +38,11 @@
3638
<SvelteSpotlight
3739
{results}
3840
bind:query
39-
combo={{ key: 'l', metaKey: true }}
41+
combo={browser && !/mac/i.test(navigator.platform)
42+
? { key: 'l', ctrlKey: true }
43+
: { key: 'l', metaKey: true }}
4044
bind:isOpen
41-
modalClass={'w-[600px] max-w-[95%] bg-base-100 shadow-lg overflow-hidden rounded-sm'}
45+
modalClass={'w-[600px] max-w-[95%] bg-base-100 shadow-lg overflow-hidden rounded-sm'}
4246
headerClass={'py-3 px-10 border-b-2 border-base-300 border-b-solid'}
4347
inputClass="focus:outline-none bg-transparent"
4448
resultIdKey="title"

documentation/src/routes/index.svelte

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@
4343
<li>9 slots to customize every part you need</li>
4444
<li>Animate it as you wish</li>
4545
<li>Keyboard shortcut and navigation</li>
46-
<li>Accessible (kind of)</li>
46+
<li>Accessible (but can be better)</li>
47+
<li>No dependencies</li>
4748
</ul>
4849
<Anatomy />
4950
<Props />

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
"scripts": {
33
"dev:doc": "pnpm run dev --filter svelte-spotlight-documentation",
44
"package": "pnpm run package --filter svelte-spotlight",
5-
"build": "pnpm run build --filter svelte-spotlight-documentation"
5+
"publish": "cd svelte-spotlight/package && npm publish",
6+
"build": "pnpm run build --filter svelte-spotlight-documentation",
7+
"copy:readme": "cp ./svelte-spotlight/README.md README.md",
8+
"deploy": "vercel --prod"
69
}
710
}

0 commit comments

Comments
 (0)