Skip to content

Commit

Permalink
fix(combobox): handle loop property correctly (#950)
Browse files Browse the repository at this point in the history
  • Loading branch information
srflp authored Nov 9, 2023
1 parent 1e50fe2 commit 8fb5e73
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 9 deletions.
5 changes: 5 additions & 0 deletions .changeset/yellow-coins-draw.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@zag-js/combobox": patch
---

Fix a case where item highlight was looping even though loop property was false
2 changes: 1 addition & 1 deletion .xstate/combobox.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ const fetchMachine = createMachine({
actions: ["highlightFirstSelectedItem", "invokeOnOpen"]
}, {
target: "interacting",
actions: ["highlightNextItem", "invokeOnOpen"]
actions: ["highlightFirstItem", "invokeOnOpen"]
}],
"INPUT.ARROW_DOWN+ALT": {
target: "interacting",
Expand Down
47 changes: 45 additions & 2 deletions e2e/combobox.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,15 +78,35 @@ test.describe("combobox", () => {
await expect(page.locator(content)).toBeHidden()
})

test("[keyboard] on arrow down, open and highlight first enabled option", async ({ page }) => {
test("[keyboard / loop] on arrow down, open and highlight first enabled option", async ({ page }) => {
await page.focus(input)
await page.keyboard.press("ArrowDown")
const option = page.locator(options).first()
await expect(page.locator(content)).toBeVisible()
await expectToBeHighlighted(option)
})

test("[keyboard] on arrow up, open and highlight last enabled option", async ({ page }) => {
test("[keyboard / no-loop] on arrow down, open and highlight first enabled option", async ({ page }) => {
await controls(page).bool("loop", false)

await page.focus(input)
await page.keyboard.press("ArrowDown")
const option = page.locator(options).first()
await expect(page.locator(content)).toBeVisible()
await expectToBeHighlighted(option)
})

test("[keyboard / loop] on arrow up, open and highlight last enabled option", async ({ page }) => {
await page.focus(input)
await page.keyboard.press("ArrowUp")
const option = page.locator(options).last()
await expect(page.locator(content)).toBeVisible()
await expectToBeHighlighted(option)
})

test("[keyboard / no-loop] on arrow up, open and highlight last enabled option", async ({ page }) => {
await controls(page).bool("loop", false)

await page.focus(input)
await page.keyboard.press("ArrowUp")
const option = page.locator(options).last()
Expand Down Expand Up @@ -137,13 +157,36 @@ test.describe("combobox", () => {
await expectToBeHighlighted(option_els.first())
})

test("[keyboard / arrowdown / no-loop]", async ({ page }) => {
await controls(page).bool("loop", false)

await page.type(input, "mal")

const option_els = page.locator(options)

await repeat(4, () => page.keyboard.press("ArrowDown"))

await expectToBeHighlighted(option_els.last())
await page.keyboard.press("ArrowDown")
await expectToBeHighlighted(option_els.last())
})

test("[keyboard / arrowup / loop]", async ({ page }) => {
await page.type(input, "mal")
const option_els = page.locator(options)
await page.keyboard.press("ArrowUp")
await expectToBeHighlighted(option_els.last())
})

test("[keyboard / arrowup / no-loop]", async ({ page }) => {
await controls(page).bool("loop", false)

await page.type(input, "mal")
const option_els = page.locator(options)
await page.keyboard.press("ArrowUp")
await expectToBeHighlighted(option_els.first())
})

test("[pointer / open-on-click]", async ({ page }) => {
await controls(page).bool("openOnClick")
await page.click(input, { force: true })
Expand Down
6 changes: 3 additions & 3 deletions packages/machines/combobox/src/combobox.machine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ export function machine<T extends CollectionItem>(userContext: UserDefinedContex
},
{
target: "interacting",
actions: ["highlightNextItem", "invokeOnOpen"],
actions: ["highlightFirstItem", "invokeOnOpen"],
},
],
"INPUT.ARROW_DOWN+ALT": {
Expand Down Expand Up @@ -558,11 +558,11 @@ export function machine<T extends CollectionItem>(userContext: UserDefinedContex
set.highlightedItem(ctx, value)
},
highlightNextItem(ctx) {
const value = ctx.collection.next(ctx.highlightedValue) ?? ctx.collection.first()
const value = ctx.collection.next(ctx.highlightedValue) ?? (ctx.loop ? ctx.collection.first() : null)
set.highlightedItem(ctx, value)
},
highlightPrevItem(ctx) {
const value = ctx.collection.prev(ctx.highlightedValue) ?? ctx.collection.last()
const value = ctx.collection.prev(ctx.highlightedValue) ?? (ctx.loop ? ctx.collection.last() : null)
set.highlightedItem(ctx, value)
},
highlightFirstSelectedItem(ctx) {
Expand Down
2 changes: 1 addition & 1 deletion shared/src/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export const comboboxData = [
{ label: "Albania", code: "AL" },
{ label: "Algeria", code: "DZ" },
{ label: "American Samoa", code: "AS" },
{ label: "AndorrA", code: "AD" },
{ label: "Andorra", code: "AD" },
{ label: "Angola", code: "AO" },
// { label: "Angola", code: "AO" },
{ label: "Anguilla", code: "AI" },
Expand Down
3 changes: 1 addition & 2 deletions website/components/machines/combobox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ const comboboxData = [
{ label: "Albania", code: "AL" },
{ label: "Algeria", code: "DZ" },
{ label: "American Samoa", code: "AS" },
{ label: "AndorrA", code: "AD" },
{ label: "Angola", code: "AO" },
{ label: "Andorra", code: "AD" },
{ label: "Angola", code: "AO" },
{ label: "Anguilla", code: "AI" },
{ label: "Antarctica", code: "AQ" },
Expand Down

4 comments on commit 8fb5e73

@vercel
Copy link

@vercel vercel bot commented on 8fb5e73 Nov 9, 2023

Choose a reason for hiding this comment

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

Successfully deployed to the following URLs:

zag-nextjs – ./examples/next-ts

zag-nextjs-chakra-ui.vercel.app
zag-nextjs-git-main-chakra-ui.vercel.app
zag-two.vercel.app

@vercel
Copy link

@vercel vercel bot commented on 8fb5e73 Nov 9, 2023

Choose a reason for hiding this comment

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

Successfully deployed to the following URLs:

zag-solid – ./examples/solid-ts

zag-solid-chakra-ui.vercel.app
zag-solid-git-main-chakra-ui.vercel.app
zag-solid.vercel.app

@vercel
Copy link

@vercel vercel bot commented on 8fb5e73 Nov 9, 2023

Choose a reason for hiding this comment

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

Successfully deployed to the following URLs:

zag-vue – ./examples/vue-ts

zag-vue-chakra-ui.vercel.app
zag-vue-git-main-chakra-ui.vercel.app
zag-vue.vercel.app

@vercel
Copy link

@vercel vercel bot commented on 8fb5e73 Nov 9, 2023

Choose a reason for hiding this comment

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

Please sign in to comment.