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

fix(kselect, kmultiselect): filtered arrow navigation [KHCP-13956] #2573

Merged

Conversation

portikM
Copy link
Member

@portikM portikM commented Jan 15, 2025

Summary

Addresses: https://konghq.atlassian.net/browse/KHCP-13956

Fixes broken arrow navigation in KSelect and KMultiselect

Verification steps:

  1. Find a sortable instance of KSelect and/or KMultiselect in sandbox or docs
  2. Type a query in and after the component shows the results, remove it
  3. Try navigating through items using up and down arrows - it should work correctly

@portikM portikM self-assigned this Jan 15, 2025
@portikM portikM requested review from adamdehaven, jillztom, Justineo and a team as code owners January 15, 2025 17:54
Copy link

netlify bot commented Jan 15, 2025

Deploy Preview for kongponents-sandbox ready!

Name Link
🔨 Latest commit 126d10d
🔍 Latest deploy log https://app.netlify.com/sites/kongponents-sandbox/deploys/6791441cc96b630008cabc73
😎 Deploy Preview https://deploy-preview-2573--kongponents-sandbox.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

Copy link

netlify bot commented Jan 15, 2025

Deploy Preview for kongponents ready!

Name Link
🔨 Latest commit 126d10d
🔍 Latest deploy log https://app.netlify.com/sites/kongponents/deploys/6791441c73626100087727f2
😎 Deploy Preview https://deploy-preview-2573--kongponents.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

Copy link
Contributor

@Justineo Justineo left a comment

Choose a reason for hiding this comment

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

I left some comments on KMultiselect, which I believe also apply to KSelect.

src/components/KMultiselect/KMultiselect.vue Outdated Show resolved Hide resolved
src/components/KMultiselect/KMultiselectItems.vue Outdated Show resolved Hide resolved
src/components/KMultiselect/KMultiselectItems.vue Outdated Show resolved Hide resolved
src/components/KMultiselect/KMultiselect.vue Outdated Show resolved Hide resolved
src/components/KMultiselect/KMultiselectItems.vue Outdated Show resolved Hide resolved
src/components/KMultiselect/KMultiselectItems.vue Outdated Show resolved Hide resolved
const currentElementIndex = Array.from(selectableItemsElements).findIndex(el => el === target)
// move to the next or previous element
const nextElementIndex = key === 'ArrowDown' ? currentElementIndex + 1 : currentElementIndex - 1
const nextElement = selectableItemsElements[nextElementIndex] as HTMLButtonElement
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
const nextElement = selectableItemsElements[nextElementIndex] as HTMLButtonElement
const nextElement = selectableItemsElements[nextElementIndex]

Copy link
Contributor

Choose a reason for hiding this comment

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

nit: Can we use less verbose variable names?

Copy link
Member Author

Choose a reason for hiding this comment

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

Now that all logic is contained within a single component, I simplified the variable names

src/components/KMultiselect/KMultiselectItems.vue Outdated Show resolved Hide resolved
@@ -469,7 +453,7 @@ const emit = defineEmits<{
(e: 'item-removed', value: MultiselectItem): void
}>()

const kMultiselectItemsContainer = ref<HTMLDivElement | null>(null)
const kMultiselectItems = ref<InstanceType<typeof KMultiselectItems> | null>(null)
Copy link
Contributor

Choose a reason for hiding this comment

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

We can switch to useTemplateRef so that this component type can be automatically inferred from the template.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done

const itemsContainer = ref<HTMLDivElement | null>(null)

const setItemFocus = (): void => {
const firstSelectableItem = itemsContainer.value?.querySelectorAll<HTMLButtonElement>('.multiselect-item button:not([disabled])')[0]
Copy link
Contributor

Choose a reason for hiding this comment

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

Since we are querying the first result here we can use this:

Suggested change
const firstSelectableItem = itemsContainer.value?.querySelectorAll<HTMLButtonElement>('.multiselect-item button:not([disabled])')[0]
const firstSelectableItem = itemsContainer.value?.querySelector<HTMLButtonElement>('.multiselect-item button:not(:disabled)')

nit: I would prefer pseudo classes over attribute selectors as they are more semantically precise ([disabled]:disabled)

Copy link
Member Author

Choose a reason for hiding this comment

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

Done

src/components/KMultiselect/KMultiselectItems.vue Outdated Show resolved Hide resolved
:item="item"
@keydown="onKeyDown"
@keydown="onKeyPress"
Copy link
Contributor

Choose a reason for hiding this comment

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

q: why are we renaming this? onKeyDown seems to be more precise.

Copy link
Member Author

Choose a reason for hiding this comment

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

At one point I realized I got confused as to why this method name suggests that it only handles down key press (since we use that method only for arrow keys events, it could be mistaken for down arrow key press exclusive handler). onKeyPress IMO makes it clear that the method handles any key press.

:key="item.key"
:item="item"
@keydown="onKeyDown"
@keydown="onKeyPress"
Copy link
Contributor

Choose a reason for hiding this comment

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

onKeyDown?

Copy link
Member Author

Choose a reason for hiding this comment

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

See explanation in my other comment.

src/components/KSelect/KSelectItems.vue Outdated Show resolved Hide resolved
src/components/KSelect/KSelectItems.vue Outdated Show resolved Hide resolved
@portikM portikM requested a review from Justineo January 22, 2025 19:21
Copy link
Contributor

@Justineo Justineo left a comment

Choose a reason for hiding this comment

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

LGTM!

@portikM portikM merged commit 7ff96d2 into main Jan 23, 2025
10 checks passed
@portikM portikM deleted the fix/khcp-13956-kselect-kmultiselect-filtered-arrow-navigation branch January 23, 2025 14:42
kongponents-bot pushed a commit that referenced this pull request Jan 23, 2025
## [9.18.2](v9.18.1...v9.18.2) (2025-01-23)

### Bug Fixes

* **kselect, kmultiselect:** filtered arrow navigation [KHCP-13956] ([#2573](#2573)) ([7ff96d2](7ff96d2))
@kongponents-bot
Copy link
Collaborator

🎉 This PR is included in version 9.18.2 🎉

The release is available on:

Your semantic-release bot 📦🚀

@kongponents-bot
Copy link
Collaborator

Preview package from this PR in consuming application

In consuming application project install preview version of kongponents generated by this PR:

@kong/kongponents@pr-2573

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants