Skip to content

Commit

Permalink
Allow text selection within input tag using Shift + Home or `Shif…
Browse files Browse the repository at this point in the history
…t + End`
  • Loading branch information
michgeek committed Sep 28, 2024
1 parent fed1551 commit 7a43766
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 1 deletion.
8 changes: 7 additions & 1 deletion packages/radix-vue/src/Combobox/ComboboxInput.vue
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ function handleKeyDown(ev: KeyboardEvent) {
}
function handleHomeEnd(ev: KeyboardEvent) {
// allow text selection while maintaining `shift` key
if(ev.shiftKey)
return
ev.preventDefault()
if (!rootContext.open.value)
return
rootContext.onInputNavigation(ev.key === 'Home' ? 'home' : 'end')
Expand Down Expand Up @@ -87,7 +93,7 @@ function handleInput(event: Event) {
@input="handleInput"
@keydown.down.up.prevent="handleKeyDown"
@keydown.enter="rootContext.onInputEnter"
@keydown.home.end.prevent="handleHomeEnd"
@keydown.home.end="handleHomeEnd"
>
<slot />
</Primitive>
Expand Down
38 changes: 38 additions & 0 deletions packages/radix-vue/src/TagsInput/TagsInput.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,15 @@ describe('given default TagsInput', () => {
expect(tags[tags.length - 2].attributes('data-state')).toBe('active')
})

it('should not select the previous tag when press Shift + ArrowLeft', async () => {
await input.trigger('keydown', {
key: 'ArrowLeft',
shiftKey: true,
})
expect(tags[tags.length - 1].attributes('data-state')).not.toBe('inactive')
expect(tags[tags.length - 2].attributes('data-state')).not.toBe('active')
})

it('should select the first item when press Home', async () => {
await input.trigger('keydown', {
key: 'Home',
Expand All @@ -80,6 +89,15 @@ describe('given default TagsInput', () => {
expect(tags[tags.length - 1].attributes('data-state')).toBe('inactive')
})

it('should not select the first item when press Shift + Home', async () => {
await input.trigger('keydown', {
key: 'Home',
shiftKey: true,
})
expect(tags[0].attributes('data-state')).not.toBe('active');
expect(tags[tags.length - 1].attributes('data-state')).not.toBe('inactive')
})

it('should select the last item when press End', async () => {
await input.trigger('keydown', {
key: 'Home',
Expand All @@ -91,13 +109,33 @@ describe('given default TagsInput', () => {
expect(tags[tags.length - 1].attributes('data-state')).toBe('active')
})

it('should not select the last item when press Shift + End', async () => {
await input.trigger('keydown', {
key: 'Home',
})
await input.trigger('keydown', {
key: 'End',
shiftKey: true,
})
expect(tags[0].attributes('data-state')).not.toBe('inactive');
expect(tags[tags.length - 1].attributes('data-state')).not.toBe('active');
})

it('should remove active state when press ArrowRight', async () => {
await input.trigger('keydown', {
key: 'ArrowRight',
})
expect(tags[tags.length - 1].attributes('data-state')).toBe('inactive')
})

it('should not remove active state when press Shift + ArrowRight', async () => {
await input.trigger('keydown', {
key: 'ArrowRight',
shiftKey: true,
})
expect(tags[tags.length - 1].attributes('data-state')).not.toBe('inactive')
})

describe('after pressing on Backspace', () => {
let prevTag: DOMWrapper<HTMLElement>
beforeEach(async () => {
Expand Down
4 changes: 4 additions & 0 deletions packages/radix-vue/src/TagsInput/TagsInputRoot.vue
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,10 @@ provideTagsInputRootContext({
case 'End':
case 'ArrowRight':
case 'ArrowLeft': {
// allow text selection while maintaining `shift` key
if(event.shiftKey)
break
const isArrowRight = (event.key === 'ArrowRight' && dir.value === 'ltr') || (event.key === 'ArrowLeft' && dir.value === 'rtl')
const isArrowLeft = !isArrowRight
// only focus on tags when cursor is at the first position
Expand Down

0 comments on commit 7a43766

Please sign in to comment.