Skip to content

Commit

Permalink
add src/lib/NavPalette.svelte invoked with cmd+k for keyboard-only si…
Browse files Browse the repository at this point in the history
…te navigation

with new demo page showing how it's made

bump @sveltejs/kit to ^1.9.2 to fix vitest
  • Loading branch information
janosh committed Mar 1, 2023
1 parent 8d3df3e commit e3f4ea9
Show file tree
Hide file tree
Showing 8 changed files with 136 additions and 14 deletions.
20 changes: 10 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@
},
"devDependencies": {
"@iconify/svelte": "^3.1.0",
"@playwright/test": "^1.31.0",
"@playwright/test": "^1.31.1",
"@sveltejs/adapter-static": "^2.0.1",
"@sveltejs/kit": "^1.8.3",
"@sveltejs/kit": "^1.9.2",
"@sveltejs/package": "2.0.2",
"@sveltejs/vite-plugin-svelte": "^2.0.2",
"@typescript-eslint/eslint-plugin": "^5.53.0",
"@typescript-eslint/parser": "^5.53.0",
"@vitest/coverage-c8": "^0.28.5",
"eslint": "^8.34.0",
"@sveltejs/vite-plugin-svelte": "^2.0.3",
"@typescript-eslint/eslint-plugin": "^5.54.0",
"@typescript-eslint/parser": "^5.54.0",
"@vitest/coverage-c8": "^0.29.2",
"eslint": "^8.35.0",
"eslint-plugin-svelte3": "^4.0.0",
"hastscript": "^7.2.0",
"highlight.js": "^11.7.0",
Expand All @@ -46,14 +46,14 @@
"prettier-plugin-svelte": "^2.9.0",
"rehype-autolink-headings": "^6.1.1",
"rehype-slug": "^5.1.0",
"svelte-check": "^3.0.3",
"svelte-check": "^3.0.4",
"svelte-preprocess": "^5.0.1",
"svelte-toc": "^0.5.2",
"svelte-zoo": "^0.3.4",
"svelte2tsx": "^0.6.1",
"svelte2tsx": "^0.6.2",
"typescript": "^4.9.5",
"vite": "^4.1.4",
"vitest": "^0.28.5"
"vitest": "^0.29.2"
},
"keywords": [
"svelte",
Expand Down
2 changes: 1 addition & 1 deletion src/lib/MultiSelect.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -461,14 +461,14 @@
<input
class={inputClass}
bind:this={input}
{autocomplete}
bind:value={searchText}
on:mouseup|self|stopPropagation={open_dropdown}
on:keydown|stopPropagation={handle_keydown}
on:focus
on:focus={open_dropdown}
{id}
{disabled}
{autocomplete}
{inputmode}
{pattern}
placeholder={selected.length == 0 ? placeholder : null}
Expand Down
70 changes: 70 additions & 0 deletions src/lib/NavPalette.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<script lang="ts">
import { goto } from '$app/navigation'
import { tick } from 'svelte/internal'
import Select from '.'
export let routes: string[] | { label: string; route: string }[]
export let trigger: string = `k`
let open = false
let dialog: HTMLDialogElement
let input: HTMLInputElement
async function toggle(event: KeyboardEvent) {
if (event.key === trigger && event.metaKey && !open) {
// open on cmd+k
open = true
await tick() // wait for dialog to open and input to be mounted
input?.focus()
} else if (event.key === `Escape` && open) {
// close on escape
open = false
}
}
function close_if_outside(event: MouseEvent) {
if (open && !dialog?.contains(event.target as Node)) {
open = false
}
}
function move(
event: CustomEvent<{ option: string | { label: string; route: string } }>
) {
const { option } = event.detail
if (typeof option == `object`) goto(option.route)
else goto(option)
open = false
}
</script>

<svelte:window on:keydown={toggle} on:click={close_if_outside} />

{#if open}
<dialog class:open bind:this={dialog}>
<Select
options={routes}
bind:input
placeholder="Go to..."
on:add={move}
on:keydown={toggle}
--sms-bg="var(--sms-options-bg)"
--sms-width="min(20em, 90vw)"
--sms-max-width="none"
/>
</dialog>
{/if}

<style>
dialog {
position: fixed;
top: 30%;
border: none;
padding: 0;
background-color: transparent;
display: flex;
color: white;
z-index: 10;
font-size: 2.4ex;
}
</style>
1 change: 1 addition & 0 deletions src/lib/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export { default as CircleSpinner } from './CircleSpinner.svelte'
export { default, default as MultiSelect } from './MultiSelect.svelte'
export { default as NavPalette } from './NavPalette.svelte'
export { default as Wiggle } from './Wiggle.svelte'

export type Option = string | number | ObjectOption
Expand Down
4 changes: 1 addition & 3 deletions src/routes/(demos)/+layout.svelte
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script lang="ts">
import { name } from '$root/package.json'
import { DemoNav, Footer } from '$site'
import { DemoNav } from '$site'
</script>

<h1>
Expand All @@ -13,8 +13,6 @@
<slot />
</main>

<Footer />

<style>
h1 {
text-align: center;
Expand Down
29 changes: 29 additions & 0 deletions src/routes/(demos)/nav-palette/+page.svx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<script lang="ts">
export let data: PageServerData
import hljs from 'highlight.js/lib/common'
import 'highlight.js/styles/vs2015.css'
import nav_palette from '$lib/NavPalette.svelte?raw'
</script>

## Nav Palette

You can use `<MultiSelect />` to build a navigation palette in just 70 lines of code (40 without styles).

```svelte stackblitz id="disabled-input-title"
<script>
import { NavPalette } from '$lib'

const routes = Object.keys(import.meta.glob(`./**/+page.{svx,svelte,md}`)).map(
(filename) => {
const parts = filename.split(`/`).filter((part) => !part.startsWith(`(`)) // remove hidden route segments
return `/${parts.slice(1, -1).join(`/`)}`
}
)
</script>

<NavPalette {routes} />
```

Here's `<NavPalette />` component

<pre><code>{@html hljs.highlight(nav_palette, { language: 'typescript' }).value}</code></pre>
13 changes: 13 additions & 0 deletions src/routes/+layout.svelte
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
<script lang="ts">
import { page } from '$app/stores'
import { NavPalette } from '$lib'
import { repository } from '$root/package.json'
import { GitHubCorner } from 'svelte-zoo'
import '../app.css'
import Footer from '../site/Footer.svelte'
const routes = Object.keys(import.meta.glob(`./**/+page.{svx,svelte,md}`)).map(
(filename) => {
const parts = filename.split(`/`).filter((part) => !part.startsWith(`(`)) // remove hidden route segments
return `/${parts.slice(1, -1).join(`/`)}`
}
)
</script>

<NavPalette {routes} />

<GitHubCorner href={repository} />

{#if !$page.error && $page.url.pathname !== `/`}
Expand All @@ -13,6 +24,8 @@

<slot />

<Footer />

<style>
a[href='.'] {
font-size: 15pt;
Expand Down
11 changes: 11 additions & 0 deletions src/site/Footer.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
Edit this page
</a>
</footer>
<small>Use <kbd>cmd+k</kbd> to bring up a nav palette.</small>

<style>
footer {
Expand All @@ -22,4 +23,14 @@
place-content: center;
flex-wrap: wrap;
}
small {
text-align: center;
display: block;
}
small kbd {
background-color: rgba(255, 255, 255, 0.1);
padding: 1pt 3pt;
font-size: larger;
border-radius: 2pt;
}
</style>

0 comments on commit e3f4ea9

Please sign in to comment.