Skip to content

Commit

Permalink
Replace SelectList with SelectField.
Browse files Browse the repository at this point in the history
- Updates QuickSearch to use SelectField.
  • Loading branch information
willnationsdev committed Nov 12, 2023
1 parent 8a23f6b commit 3c9bbea
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 436 deletions.
5 changes: 5 additions & 0 deletions .changeset/quick-avocados-hope.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'svelte-ux': minor
---

Removes SelectList. Updates SelectField features to support SelectList's use case via property/attribute overrides. Updates QuickSearch to use SelectField.
13 changes: 9 additions & 4 deletions packages/svelte-ux/src/lib/components/QuickSearch.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
import Button from '$lib/components/Button.svelte';
import Dialog from '$lib/components/Dialog.svelte';
import SelectList from '$lib/components/SelectList.svelte';
import SelectField from '$lib/components/SelectField.svelte';
import { getComponentTheme } from './theme';
import { cls } from '$lib/utils/styles';
import { smScreen } from '$lib/stores';
import { autoFocus, selectOnFocus } from '$lib/actions';
export let options: { name: string; value: string; group?: string }[] = [];
Expand All @@ -18,10 +19,11 @@
let open = false;
let fieldActions = (node: any) => [autoFocus(node), selectOnFocus(node)];
/*
TODO:
- [ ] Sticky search
- [ ] Refine SelectList / reuse with SelectField (and maybe MultiSelect)
- [ ] Improve size of Dialog (move class to Dialog without breaking overflow)
- [ ] Load descriptions/meta from +page.ts
- [ ] Improve dialog positioning on small viewports (consistent top/bottom with max height)
Expand Down Expand Up @@ -62,12 +64,15 @@
}}
>
<div class="overflow-auto max-h-[min(90dvh,600px)] min-w-[400px] py-1">
<SelectList
<SelectField
icon={mdiMagnify}
placeholder="Search..."
showToggleIcon={false}
optionsMode="list"
{options}
{fieldActions}
on:change
on:change={(e) => (open = false)}
on:change={() => (open = false)}
classes={{
field: {
container: 'border-none hover:shadow-none group-focus-within:shadow-none',
Expand Down
51 changes: 40 additions & 11 deletions packages/svelte-ux/src/lib/components/SelectField.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import { mdiChevronDown, mdiClose } from '@mdi/js';
import Logger from '../utils/logger';
import { selectOnFocus } from '../actions/input';
import { autoFocus, selectOnFocus } from '../actions/input';
import { cls } from '../utils/styles';
import Button from './Button.svelte';
Expand All @@ -14,6 +14,8 @@
import MenuItem from './MenuItem.svelte';
import TextField from './TextField.svelte';
import { getComponentTheme } from './theme';
import Maybe from './Maybe.svelte';
import type { IconInput } from '$lib/utils/icons';
const dispatch = createEventDispatcher<{
change: { value: any; option: any };
Expand All @@ -31,16 +33,26 @@
export let loading: boolean = false;
export let disabled: boolean = false;
export let readonly: boolean = false;
export let icon: string | null = null;
export let icon: IconInput = undefined;
export let toggleIcon: IconInput = mdiChevronDown;
export let closeIcon: IconInput = mdiClose;
export let clearable = true;
export let base = false;
export let rounded = false;
export let dense = false;
export let clearSearchOnOpen = true;
export let tabIterable = false;
export let tabindex = 0;
export let autofocus: ComponentProps<TextField>['autofocus'] = undefined;
export let fieldActions: ComponentProps<TextField>['actions'] = autofocus
? (node) => [autoFocus(node, typeof autofocus === 'object' ? autofocus : undefined), selectOnFocus(node)]
: undefined;
export let showToggleIcon = true;
export let classes: {
root?: string;
field?: string;
field?: string | ComponentProps<TextField>['classes'];
options?: string;
option?: string;
selected?: string;
Expand All @@ -49,13 +61,17 @@
} = {};
const theme = getComponentTheme('SelectField');
let fieldClasses: ComponentProps<TextField>['classes'];
$: fieldClasses = typeof(classes.field) === "string" ? { root: classes.field } : classes.field;
// Menu props
export let placement: Placement = 'bottom-start';
export let autoPlacement = true;
export let matchWidth = true;
export let resize = true;
export let disableTransition = false;
export let menuProps: ComponentProps<Menu> | undefined = undefined;
export let optionsMode: "list" | "menu" = "menu";
$: filteredOptions = options ?? [];
let searchText = '';
Expand Down Expand Up @@ -336,7 +352,14 @@
</script>

<!-- svelte-ignore a11y-click-events-have-key-events -->
<div role="button" tabindex="-1" aria-pressed={open ? "true" : "false"} class={cls('SelectField', theme.root, classes.root, $$props.class)} on:click={onClick}>
<div
role="button"
{tabindex}
aria-pressed={open ? "true" : "false"}
aria-haspopup={optionsMode === "menu" ? "listbox" : undefined}
class={cls('SelectField', theme.root, classes.root, $$props.class)}
on:click={onClick}>

<TextField
{label}
{placeholder}
Expand All @@ -352,10 +375,15 @@
on:blur={onBlur}
on:keydown={onKeyDown}
on:keypress={onKeyPress}
actions={(node) => [selectOnFocus(node)]}
class={cls('h-full', theme.field, classes.field)}
actions={fieldActions}
classes={{
root: cls('h-full'),
...theme.field,
...fieldClasses,
}}
role="combobox"
aria-expanded={open ? "true" : "false"}
aria-autocomplete={optionsMode === "menu" ? "list" : undefined}
{...$$restProps}
>
<slot slot="prepend" name="prepend" />
Expand All @@ -371,16 +399,16 @@
<!-- Do not show chevron or clear buttons -->
{:else if value && clearable}
<Button
icon={mdiClose}
icon={closeIcon}
class="text-black/50 p-1"
on:click={(e) => {
e.stopPropagation();
clear();
}}
/>
{:else}
{:else if showToggleIcon}
<Button
icon={mdiChevronDown}
icon={toggleIcon}
class="text-black/50 p-1 transform {open ? 'rotate-180' : ''}"
tabindex="-1"
/>
Expand All @@ -390,7 +418,7 @@

<!-- Improve initial open display, still needs work when switching from No options found (options.length === 0) -->
{#if options?.length > 0 || loading !== true}
<Menu
<Maybe this={optionsMode === "menu" ? Menu : undefined}
{placement}
{autoPlacement}
{matchWidth}
Expand Down Expand Up @@ -456,6 +484,7 @@
role="option"
aria-selected={option === selected ? "true" : "false"}
aria-disabled={option?.disabled ? "true" : "false"}
tabindex={tabIterable ? 0 : -1}
>
{optionText(option)}
</MenuItem>
Expand All @@ -469,6 +498,6 @@
{/each}
</div>
<slot name="actions" {hide} />
</Menu>
</Maybe>
{/if}
</div>
Loading

0 comments on commit 3c9bbea

Please sign in to comment.