Skip to content

Commit

Permalink
rename NavPalette to CmdPalette and make it execute generic actions o…
Browse files Browse the repository at this point in the history
…n item select

fix CSS vars --sms-placeholder-color, --sms-placeholder-opacity having no effect

add new CSS vars
border: var(--sms-options-border);
border-width: var(--sms-options-border-width);
border-radius: var(--sms-options-border-radius, 1ex);
padding: var(--sms-options-padding);
margin: var(--sms-options-margin, inherit);

fix app.css font size for pre > code not taking effect
  • Loading branch information
janosh committed Mar 1, 2023
1 parent e3f4ea9 commit b27cd80
Show file tree
Hide file tree
Showing 8 changed files with 58 additions and 40 deletions.
5 changes: 5 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,11 @@ If you only want to make small adjustments, you can pass the following CSS varia
- `max-height: var(--sms-options-max-height, 50vh)`: Maximum height of options dropdown.
- `overscroll-behavior: var(--sms-options-overscroll, none)`: Whether scroll events bubble to parent elements when reaching the top/bottom of the options dropdown. See [MDN](https://developer.mozilla.org/docs/Web/CSS/overscroll-behavior).
- `box-shadow: var(--sms-options-shadow, 0 0 14pt -8pt black)`: Box shadow of dropdown list.
- `border: var(--sms-options-border)`
- `border-width: var(--sms-options-border-width)`
- `border-radius: var(--sms-options-border-radius, 1ex)`
- `padding: var(--sms-options-padding)`
- `margin: var(--sms-options-margin, inherit)`
- `div.multiselect > ul.options > li`
- `scroll-margin: var(--sms-options-scroll-margin, 100px)`: Top/bottom margin to keep between dropdown list items and top/bottom screen edge when auto-scrolling list to keep items in view.
- `div.multiselect > ul.options > li.selected`
Expand Down
4 changes: 2 additions & 2 deletions src/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
--text-color: #ccc;

--sms-active-color: var(--blue);
--sms-options-bg: rgb(0, 0, 32);
--sms-options-bg: rgb(33, 31, 47);
--sms-selected-bg: rgba(255, 255, 255, 0.2);
--sms-text-color: white;
--sms-disabled-bg: rgba(7, 1, 34, 0.87);
Expand Down Expand Up @@ -68,10 +68,10 @@ code {
pre code {
background-color: transparent;
display: inline-block;
font-size: 10pt;
}
pre {
border-radius: 4pt;
font-size: 9pt;
background-color: rgba(255, 255, 255, 0.05);
padding: 1em;
overflow-x: auto;
Expand Down
28 changes: 15 additions & 13 deletions src/lib/NavPalette.svelte → src/lib/CmdPalette.svelte
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
<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 actions: Action[]
export let trigger: string = `k`
type Action = { label: string; action: () => void }
let open = false
let dialog: HTMLDialogElement
let input: HTMLInputElement
Expand All @@ -28,12 +29,8 @@
}
}
function move(
event: CustomEvent<{ option: string | { label: string; route: string } }>
) {
const { option } = event.detail
if (typeof option == `object`) goto(option.route)
else goto(option)
function move(event: CustomEvent<{ option: Action }>) {
event.detail.option.action()
open = false
}
</script>
Expand All @@ -43,20 +40,17 @@
{#if open}
<dialog class:open bind:this={dialog}>
<Select
options={routes}
options={actions}
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 {
:where(dialog) {
position: fixed;
top: 30%;
border: none;
Expand All @@ -67,4 +61,12 @@
z-index: 10;
font-size: 2.4ex;
}
dialog :global(div.multiselect) {
--sms-bg: var(--sms-options-bg);
--sms-width: min(20em, 90vw);
--sms-max-width: none;
--sms-placeholder-color: lightgray;
--sms-options-margin: 1px 0;
--sms-options-border-radius: 0 0 1ex 1ex;
}
</style>
15 changes: 10 additions & 5 deletions src/lib/MultiSelect.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@
)
}
const dispatch = createEventDispatcher<DispatchEvents>()
const dispatch = createEventDispatcher<DispatchEvents<Option>>()
let add_option_msg_is_active: boolean = false // controls active state of <li>{createOptionMsg}</li>
let window_width: number
Expand Down Expand Up @@ -681,7 +681,8 @@
cursor: inherit; /* needed for disabled state */
border-radius: 0; /* reset ul.selected > li */
}
:where(div.multiselect > ul.selected > li > input::placeholder) {
/* don't wrap ::placeholder rules in :where() as it seems to be overpowered by browser defaults i.t.o. specificity */
div.multiselect > ul.selected > li > input::placeholder {
padding-left: 5pt;
color: var(--sms-placeholder-color);
opacity: var(--sms-placeholder-opacity);
Expand All @@ -699,18 +700,22 @@
:where(div.multiselect > ul.options) {
list-style: none;
padding: 4pt 0;
top: 100%;
left: 0;
width: 100%;
position: absolute;
border-radius: 1ex;
overflow: auto;
transition: all 0.2s;
box-sizing: border-box;
background: var(--sms-options-bg, white);
max-height: var(--sms-options-max-height, 50vh);
overscroll-behavior: var(--sms-options-overscroll, none);
box-shadow: var(--sms-options-shadow, 0 0 14pt -8pt black);
transition: all 0.2s;
border: var(--sms-options-border);
border-width: var(--sms-options-border-width);
border-radius: var(--sms-options-border-radius, 1ex);
padding: var(--sms-options-padding);
margin: var(--sms-options-margin, inherit);
}
:where(div.multiselect > ul.options.hidden) {
visibility: hidden;
Expand Down
14 changes: 7 additions & 7 deletions src/lib/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export { default as CircleSpinner } from './CircleSpinner.svelte'
export { default as CmdPalette } from './CmdPalette.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 All @@ -16,13 +16,13 @@ export type ObjectOption = {
[key: string]: unknown // allow any other keys users might want
}

export type DispatchEvents = {
add: { option: Option }
remove: { option: Option }
removeAll: { options: Option[] }
export type DispatchEvents<T = Option> = {
add: { option: T }
remove: { option: T }
removeAll: { options: T[] }
change: {
option?: Option
options?: Option[]
option?: T
options?: T[]
type: 'add' | 'remove' | 'removeAll'
}
open: { event: Event }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
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'
import nav_palette from '$lib/CmdPalette.svelte?raw'
</script>

## Nav Palette
Expand All @@ -11,19 +11,23 @@ You can use `<MultiSelect />` to build a navigation palette in just 70 lines of

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

const routes = Object.keys(import.meta.glob(`./**/+page.{svx,svelte,md}`)).map(
const actions = 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(`/`)}`

const route = `/${parts.slice(1, -1).join(`/`)}`

return { label: route, action: () => goto(route) }
}
)
</script>

<NavPalette {routes} />
<CmdPalette {actions} />
```

Here's `<NavPalette />` component
Here's `<CmdPalette />` component

<pre><code>{@html hljs.highlight(nav_palette, { language: 'typescript' }).value}</code></pre>
11 changes: 7 additions & 4 deletions src/routes/+layout.svelte
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
<script lang="ts">
import { goto } from '$app/navigation'
import { page } from '$app/stores'
import { NavPalette } from '$lib'
import { CmdPalette } 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(
const actions = 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(`/`)}`
const route = `/${parts.slice(1, -1).join(`/`)}`
return { label: route, action: () => goto(route) }
}
)
</script>

<NavPalette {routes} />
<CmdPalette {actions} />

<GitHubCorner href={repository} />

Expand Down
5 changes: 2 additions & 3 deletions tests/unit/readme.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { readFileSync } from 'fs'
import src from '$lib/MultiSelect.svelte?raw'
import readme from '$root/readme.md?raw'
import { expect, test } from 'vitest'

const readme = readFileSync(`readme.md`, `utf8`)
const component = `MultiSelect.svelte`
const src = readFileSync(`src/lib/${component}`, `utf8`)

test(`readme documents all props and their correct types and defaults`, () => {
for (const [idx, line] of src.split(`\n`).entries()) {
Expand Down

0 comments on commit b27cd80

Please sign in to comment.