Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Manage the active item via focus instead constant value #81

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 5 additions & 8 deletions src/docs/03-combobox.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,17 +86,14 @@ Comboboxes are the foundation of accessible autocompletes and command palettes f
>
{#each filtered as value}
{@const active = $combobox.active === value}
{@const selected = $combobox.selected === value}
<li
class="relative cursor-default select-none py-2 pl-10 pr-4 {active ? 'bg-teal-600 text-white' : 'text-gray-900'}"
class="relative cursor-default select-none py-2 pl-10 pr-4 focus:outline-none font-normal aria-selected:font-medium {active ? 'bg-teal-600 text-white' : 'text-gray-900'} group"
use:combobox.item={{ value }}
>
<span class="block truncate {selected ? 'font-medium' : 'font-normal'}">{value.name}</span>
{#if selected}
<span class="absolute inset-y-0 left-0 flex items-center pl-3 {active ? 'text-white' : 'text-teal-600'}">
<Check class="h-5 w-5" />
</span>
{/if}
<span class="block truncate">{value.name}</span>
<span class="absolute invisible group-aria-selected:visible inset-y-0 left-0 flex items-center pl-3 {active ? 'text-white' : 'text-teal-600'}">
<Check class="h-5 w-5" />
</span>
</li>
{:else}
<li class="relative cursor-default select-none py-2 pl-10 pr-4 text-gray-900">
Expand Down
13 changes: 5 additions & 8 deletions src/docs/04-combobox-multi.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,17 +101,14 @@ Pass an array to the `selected` property of `createCombobox` to trigger multi-se
>
{#each filtered as value}
{@const active = $combobox.active === value}
{@const selected = $combobox.selected.includes(value)}
<li
class="relative cursor-default select-none py-2 pl-4 pr-9 focus:outline-none {active ? 'bg-teal-600 text-white' : 'text-gray-900'}"
class="relative cursor-default select-none py-2 pl-4 pr-9 focus:outline-none font-normal aria-selected:font-medium {active ? 'bg-teal-600 text-white' : 'text-gray-900'} group"
use:combobox.item={{ value }}
>
<span class="block truncate {selected ? 'font-semibold' : 'font-normal'}">{value.name}</span>
{#if selected}
<span class="absolute inset-y-0 right-0 flex items-center pr-3 {active ? 'text-white' : 'text-teal-600'}">
<Check class="h-5 w-5" />
</span>
{/if}
<span class="block truncate">{value.name}</span>
<span class="absolute invisible group-aria-selected:visible inset-y-0 right-0 flex items-center pr-3 {active ? 'text-white' : 'text-teal-600'}">
<Check class="h-5 w-5" />
</span>
</li>
{:else}
<li class="relative cursor-default select-none py-2 pl-10 pr-4 text-gray-900">
Expand Down
14 changes: 5 additions & 9 deletions src/docs/07-listbox.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,18 +73,14 @@ Listboxes are a great foundation for building custom, accessible select menus fo
class="absolute mt-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-sm shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none"
>
{#each people as value, i}
{@const active = $listbox.active === value}
{@const selected = $listbox.selected === value}
<li
class="relative cursor-default select-none py-2 pl-10 pr-4 {active ? 'bg-amber-100 text-amber-900' : 'text-gray-900'}"
class="relative cursor-default select-none py-2 pl-10 pr-4 text-gray-900 focus:outline-none focus:bg-amber-100 focus:text-amber-900 group"
use:listbox.item={{ value }}
>
<span class="block truncate {selected ? 'font-medium' : 'font-normal'}">{value.name}</span>
{#if selected}
<span class="absolute inset-y-0 left-0 flex items-center pl-3 text-amber-600">
<Check class="h-5 w-5" />
</span>
{/if}
<span class="block truncate font-normal group-aria-selected:font-medium">{value.name}</span>
<span class="absolute invisible group-aria-selected:visible inset-y-0 left-0 flex items-center pl-3 text-amber-600">
<Check class="h-5 w-5" />
</span>
</li>
{/each}
</ul>
Expand Down
14 changes: 5 additions & 9 deletions src/docs/08-listbox-multi.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,18 +92,14 @@ Pass an array to the `selected` property of `createListbox` to trigger multi-sel
class="absolute mt-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-sm shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none"
>
{#each people as value (value.id)}
{@const active = $listbox.active === value}
{@const selected = $listbox.selected.includes(value)}
<li
class="relative cursor-default select-none py-2 pl-4 pr-9 focus:outline-none {active ? 'bg-orange-100 text-orange-900' : 'text-gray-900'}"
class="relative cursor-default select-none py-2 pl-4 pr-9 text-gray-900 focus:outline-none focus:bg-orange-100 focus:text-orange-900 group"
use:listbox.item={{ value }}
>
<span class="block truncate {selected ? 'font-semibold' : 'font-normal'}">{value.name}</span>
{#if selected}
<span class="absolute inset-y-0 right-0 flex items-center pr-3 text-orange-600">
<Check class="h-5 w-5" />
</span>
{/if}
<span class="block truncate font-normal group-aria-selected:font-semibold">{value.name}</span>
<span class="absolute invisible group-aria-selected:visible inset-y-0 right-0 flex items-center pr-3 text-orange-600">
<Check class="h-5 w-5" />
</span>
</li>
{/each}
</ul>
Expand Down
2 changes: 1 addition & 1 deletion src/docs/09-menu.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ Menus offer an easy way to build custom, accessible dropdown components with rob
{@const active = $menu.active === option.text}
<button
use:menu.item
class="group flex rounded-md items-center w-full px-2 py-2 text-sm {active ? 'bg-violet-500 text-white' : 'text-gray-900'}"
class="group flex rounded-md items-center w-full px-2 py-2 text-sm text-gray-900 focus:outline-none focus:bg-violet-500 focus:text-white"
>
<svelte:component this={option.icon} class="w-5 h-5 mr-2" {active} />
{option.text}
Expand Down
2 changes: 1 addition & 1 deletion src/lib/listbox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export function createListbox(init?: Partial<Listbox>) {
set({ active })
const item = state.items[active]
if (item) {
item.node.scrollIntoView({ block: 'nearest' })
item.node.focus()
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed the scrollIntoView call line because the focus method also functions as a scroll.

}
}
}
Expand Down
10 changes: 9 additions & 1 deletion src/lib/menu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,15 @@ export function createMenu(init?: Partial<Menu>) {
const toggle = () => state.expanded ? close() : open()

// set focused (active) item (open if not expanded) only if changed
const focus = (active: number, expand = false) => state.active !== active && set({ expanded: state.expanded || expand, active })
const focus = (active: number, expand = false) => {
if (state.active !== active) {
set({ expanded: state.expanded || expand, active })
const item = state.items[active];
if (item) {
item.node.focus()
}
}
}

// set focus (active) to first
const first = () => focus(firstActive(state), true)
Expand Down
13 changes: 5 additions & 8 deletions src/routes/example/combobox/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -55,17 +55,14 @@
>
{#each filtered as value}
{@const active = $combobox.active === value}
{@const selected = $combobox.selected === value}
<li
class="relative cursor-default select-none py-2 pl-10 pr-4 {active ? 'bg-teal-600 text-white' : 'text-gray-900'}"
class="relative cursor-default select-none py-2 pl-10 pr-4 focus:outline-none font-normal aria-selected:font-medium {active ? 'bg-teal-600 text-white' : 'text-gray-900'} group"
use:combobox.item={{ value }}
>
<span class="block truncate {selected ? 'font-medium' : 'font-normal'}">{value.name}</span>
{#if selected}
<span class="absolute inset-y-0 left-0 flex items-center pl-3 {active ? 'text-white' : 'text-teal-600'}">
<Check class="h-5 w-5" />
</span>
{/if}
<span class="block truncate">{value.name}</span>
<span class="absolute invisible group-aria-selected:visible inset-y-0 left-0 flex items-center pl-3 {active ? 'text-white' : 'text-teal-600'}">
<Check class="h-5 w-5" />
</span>
</li>
{:else}
<li class="relative cursor-default select-none py-2 pl-10 pr-4 text-gray-900">
Expand Down
13 changes: 5 additions & 8 deletions src/routes/example/combobox/multi/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -71,17 +71,14 @@
>
{#each filtered as value}
{@const active = $combobox.active === value}
{@const selected = $combobox.selected.includes(value)}
<li
class="relative cursor-default select-none py-2 pl-4 pr-9 focus:outline-none {active ? 'bg-teal-600 text-white' : 'text-gray-900'}"
class="relative cursor-default select-none py-2 pl-4 pr-9 focus:outline-none font-normal aria-selected:font-medium {active ? 'bg-teal-600 text-white' : 'text-gray-900'} group"
use:combobox.item={{ value }}
>
<span class="block truncate {selected ? 'font-semibold' : 'font-normal'}">{value.name}</span>
{#if selected}
<span class="absolute inset-y-0 right-0 flex items-center pr-3 {active ? 'text-white' : 'text-teal-600'}">
<Check class="h-5 w-5" />
</span>
{/if}
<span class="block truncate">{value.name}</span>
<span class="absolute invisible group-aria-selected:visible inset-y-0 right-0 flex items-center pr-3 {active ? 'text-white' : 'text-teal-600'}">
<Check class="h-5 w-5" />
</span>
</li>
{:else}
<li class="relative cursor-default select-none py-2 pl-10 pr-4 text-gray-900">
Expand Down
10 changes: 3 additions & 7 deletions src/routes/example/listbox/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,14 @@
class="absolute mt-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-sm shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none"
>
{#each people as value, i}
{@const active = $listbox.active === value}
{@const selected = $listbox.selected === value}
<li
class="relative cursor-default select-none py-2 pl-10 pr-4 {active ? 'bg-amber-100 text-amber-900' : 'text-gray-900'}"
class="relative cursor-default select-none py-2 pl-10 pr-4 font-normal aria-selected:font-medium text-gray-900 focus:outline-none focus:bg-amber-100 focus:text-amber-900 group"
use:listbox.item={{ value }}
>
<span class="block truncate {selected ? 'font-medium' : 'font-normal'}">{value.name}</span>
{#if selected}
<span class="absolute inset-y-0 left-0 flex items-center pl-3 text-amber-600">
<span class="block truncate">{value.name}</span>
<span class="absolute invisible group-aria-selected:visible inset-y-0 left-0 flex items-center pl-3 text-amber-600">
<Check class="h-5 w-5" />
</span>
{/if}
</li>
{/each}
</ul>
Expand Down
10 changes: 3 additions & 7 deletions src/routes/example/listbox/multi/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -62,18 +62,14 @@
class="absolute mt-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-sm shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none"
>
{#each people as value (value.id)}
{@const active = $listbox.active === value}
{@const selected = $listbox.selected.includes(value)}
<li
class="relative cursor-default select-none py-2 pl-4 pr-9 focus:outline-none {active ? 'bg-orange-100 text-orange-900' : 'text-gray-900'}"
class="relative cursor-default select-none py-2 pl-4 pr-9 font-normal aria-selected:font-medium text-gray-900 focus:outline-none focus:bg-orange-100 focus:text-orange-900 group"
use:listbox.item={{ value }}
>
<span class="block truncate {selected ? 'font-semibold' : 'font-normal'}">{value.name}</span>
{#if selected}
<span class="absolute inset-y-0 right-0 flex items-center pr-3 text-orange-600">
<span class="block truncate">{value.name}</span>
<span class="absolute invisible group-aria-selected:visible inset-y-0 right-0 flex items-center pr-3 text-orange-600">
<Check class="h-5 w-5" />
</span>
{/if}
</li>
{/each}
</ul>
Expand Down
2 changes: 1 addition & 1 deletion src/routes/example/menu/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
{@const active = $menu.active === option.text}
<button
use:menu.item
class="group flex rounded-md items-center w-full px-2 py-2 text-sm {active ? 'bg-violet-500 text-white' : 'text-gray-900'}"
class="group flex rounded-md items-center w-full px-2 py-2 text-sm text-gray-900 focus:outline-none focus:bg-violet-500 focus:text-white"
>
<svelte:component this={option.icon} class="w-5 h-5 mr-2" {active} />
{option.text}
Expand Down