Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions packages/date-picker/src/vaadin-date-picker-mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -616,6 +616,24 @@ export const DatePickerMixin = (subclass) =>
return !this._shouldKeepFocusRing;
}

/**
* Override method inherited from `ClearButtonMixin`
* to not blur on clear button mousedown when opened
* so that focus remains in the input field.
*
* @param {Event} event
* @return {boolean}
* @protected
* @override
*/
_shouldKeepFocusOnClearMousedown(event) {
if (this.opened) {
return true;
}

return super._shouldKeepFocusOnClearMousedown(event);
}

/**
* Override method inherited from `FocusMixin`
* to prevent removing the `focused` attribute:
Expand Down
24 changes: 24 additions & 0 deletions packages/date-picker/test/basic.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,30 @@ describe('clear button', () => {
click(clearButton);
expect(datePicker.opened).to.be.not.ok;
});

it('should not prevent default on clear button mousedown if input is not focused', () => {
datePicker.value = '2001-01-01';
const event = new CustomEvent('mousedown', { cancelable: true });
clearButton.dispatchEvent(event);
expect(event.defaultPrevented).to.be.false;
});

it('should prevent default on clear button mousedown if input is focused', () => {
datePicker.value = '2001-01-01';
datePicker.inputElement.focus();
const event = new CustomEvent('mousedown', { cancelable: true });
clearButton.dispatchEvent(event);
expect(event.defaultPrevented).to.be.true;
});

it('should prevent default on clear button mousedown when opened', async () => {
datePicker.value = '2001-01-01';
await open(datePicker);
datePicker.inputElement.blur();
const event = new CustomEvent('mousedown', { cancelable: true });
clearButton.dispatchEvent(event);
expect(event.defaultPrevented).to.be.true;
});
});

describe('initial value attribute', () => {
Expand Down
19 changes: 18 additions & 1 deletion packages/field-base/src/clear-button-mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* Copyright (c) 2021 - 2025 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
*/
import { isElementFocused } from '@vaadin/a11y-base/src/focus-utils.js';
import { KeyboardMixin } from '@vaadin/a11y-base/src/keyboard-mixin.js';
import { isTouch } from '@vaadin/component-base/src/browser-utils.js';
import { InputMixin } from './input-mixin.js';
Expand Down Expand Up @@ -71,7 +72,10 @@ export const ClearButtonMixin = (superclass) =>
* @protected
*/
_onClearButtonMouseDown(event) {
event.preventDefault();
if (this._shouldKeepFocusOnClearMousedown(event)) {
event.preventDefault();
}

if (!isTouch) {
this.inputElement.focus();
}
Expand Down Expand Up @@ -109,4 +113,17 @@ export const ClearButtonMixin = (superclass) =>
this.inputElement.dispatchEvent(new Event('input', { bubbles: true, composed: true }));
this.inputElement.dispatchEvent(new Event('change', { bubbles: true }));
}

/**
* Whether to keep focus inside the field on clear button
* mousedown. By default, if the field has focus, it gets
* preserved using `preventDefault()` on mousedown event
* in order to avoid blur and change events.
*
* @protected
* @return {boolean}
*/
_shouldKeepFocusOnClearMousedown() {
return isElementFocused(this.inputElement);
}
Comment on lines +117 to +128
Copy link
Contributor

Choose a reason for hiding this comment

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

Question: One thing that might not be clear from taking a look at this method for classes that might want to override it is that the caller passes the original event. Should it be somehow documented here? Also, the event is not being used by the overridden method in the DatePickerMixin; is it actually needed?

};
9 changes: 8 additions & 1 deletion packages/field-base/test/clear-button-mixin.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,14 @@ describe('ClearButtonMixin', () => {
expect(spy.calledOnce).to.be.true;
});

it('should prevent default on clear button mousedown', () => {
it('should not prevent default on clear button mousedown if input is not focused', () => {
const event = new CustomEvent('mousedown', { cancelable: true });
clearButton.dispatchEvent(event);
expect(event.defaultPrevented).to.be.false;
});

it('should prevent default on clear button mousedown if input is focused', () => {
input.focus();
const event = new CustomEvent('mousedown', { cancelable: true });
clearButton.dispatchEvent(event);
expect(event.defaultPrevented).to.be.true;
Expand Down