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

feat(ui5-slider): focus and keyboard handling implementation #2614

Merged
merged 16 commits into from
Jan 11, 2021
Merged
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/base/src/Keys.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,14 @@ const isUp = event => (event.key ? (event.key === "ArrowUp" || event.key === "Up

const isDown = event => (event.key ? (event.key === "ArrowDown" || event.key === "Down") : event.keyCode === KeyCodes.ARROW_DOWN) && !hasModifierKeys(event);

const isLeftCtrl = event => (event.key ? (event.key === "ArrowLeft" || event.key === "Left") : event.keyCode === KeyCodes.ARROW_LEFT) && checkModifierKeys(event, true, false, false);

const isRightCtrl = event => (event.key ? (event.key === "ArrowRight" || event.key === "Right") : event.keyCode === KeyCodes.ARROW_RIGHT) && checkModifierKeys(event, true, false, false);
ndeshev marked this conversation as resolved.
Show resolved Hide resolved

const isUpCtrl = event => (event.key ? (event.key === "ArrowUp" || event.key === "Up") : event.keyCode === KeyCodes.ARROW_UP) && checkModifierKeys(event, true, false, false);

const isDownCtrl = event => (event.key ? (event.key === "ArrowDown" || event.key === "Down") : event.keyCode === KeyCodes.ARROW_DOWN) && checkModifierKeys(event, true, false, false);

const isHome = event => (event.key ? event.key === "Home" : event.keyCode === KeyCodes.HOME) && !hasModifierKeys(event);

const isEnd = event => (event.key ? event.key === "End" : event.keyCode === KeyCodes.END) && !hasModifierKeys(event);
Expand Down Expand Up @@ -145,6 +153,10 @@ const isPageUpShiftCtrl = event => (event.key ? event.key === "PageUp" : event.k

const isPageDownShiftCtrl = event => (event.key ? event.key === "PageDown" : event.keyCode === KeyCodes.PAGE_DOWN) && checkModifierKeys(event, true, false, true);

const isPlus = event => (event.key ? event.key === "+" : event.keyCode === KeyCodes.PLUS) || (event.keyCode === KeyCodes.NUMPAD_PLUS && !hasModifierKeys(event));

const isMinus = event => (event.key ? event.key === "-" : event.keyCode === KeyCodes.MINUS) || (event.keyCode === KeyCodes.NUMPAD_MINUS && !hasModifierKeys(event));

const isShow = event => {
if (event.key) {
return isF4(event) || isShowByArrows(event);
Expand Down Expand Up @@ -176,8 +188,14 @@ export {
isRight,
isUp,
isDown,
isLeftCtrl,
isRightCtrl,
isUpCtrl,
isDownCtrl,
isHome,
isEnd,
isPlus,
isMinus,
isHomeCtrl,
isEndCtrl,
isEscape,
Expand Down
7 changes: 5 additions & 2 deletions packages/main/src/RangeSlider.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import Float from "@ui5/webcomponents-base/dist/types/Float.js";
import { fetchI18nBundle, getI18nBundle } from "@ui5/webcomponents-base/dist/i18nBundle.js";
import ResizeHandler from "@ui5/webcomponents-base/dist/delegate/ResizeHandler.js";
import SliderBase from "./SliderBase.js";

// Template
import RangeSliderTemplate from "./generated/templates/RangeSliderTemplate.lit.js";

/**
Expand Down Expand Up @@ -99,6 +98,10 @@ class RangeSlider extends SliderBase {
this.i18nBundle = getI18nBundle("@ui5/webcomponents");
}

onEnterDOM() {
ResizeHandler.register(this, this._resizeHandler);
ndeshev marked this conversation as resolved.
Show resolved Hide resolved
}

get tooltipStartValue() {
const stepPrecision = this.constructor._getDecimalPrecisionOfNumber(this._effectiveStep);
return this.startValue.toFixed(stepPrecision);
Expand Down
8 changes: 7 additions & 1 deletion packages/main/src/Slider.hbs
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
{{>include "./SliderBase.hbs"}}

{{#*inline "handles"}}
<div class="ui5-slider-handle" style="{{styles.handle}}">
<div class="ui5-slider-handle"
style="{{styles.handle}}"
tabindex="{{tabIndex}}"
@focusout="{{_onfocusout}}"
@focusin="{{_onfocusin}}"
data-sap-focus-ref
>
{{#if showTooltip}}
<div class="ui5-slider-tooltip" style="{{styles.tooltip}}">
<span class="ui5-slider-tooltip-value">{{tooltipValue}}</span>
Expand Down
54 changes: 51 additions & 3 deletions packages/main/src/Slider.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Float from "@ui5/webcomponents-base/dist/types/Float.js";
import { fetchI18nBundle, getI18nBundle } from "@ui5/webcomponents-base/dist/i18nBundle.js";
import { isEscape } from "@ui5/webcomponents-base/dist/Keys.js";
import SliderBase from "./SliderBase.js";

// Template
Expand Down Expand Up @@ -82,6 +83,7 @@ class Slider extends SliderBase {
constructor() {
super();
this._stateStorage.value = null;
this._setInitialValue("value", null);
this.i18nBundle = getI18nBundle("@ui5/webcomponents");
}

Expand Down Expand Up @@ -121,13 +123,41 @@ class Slider extends SliderBase {
const newValue = this.handleDownBase(event);
this._valueOnInteractionStart = this.value;

// Set initial value if one is not set previously on focus in.
// It will be restored if ESC key is pressed.
if (this._getInitialValue("value") === null) {
this._setInitialValue("value", this.value);
}

// Do not yet update the Slider if press is over a handle. It will be updated if the user drags the mouse.
if (!this._isHandlePressed(this.constructor.getPageXValueFromEvent(event))) {
this._updateHandleAndProgress(newValue);
this.updateValue("value", newValue);
}
}

_onfocusin(event) {
// Set initial value if one is not set previously on focus in.
// It will be restored if ESC key is pressed.
if (this._getInitialValue("value") === null) {
this._setInitialValue("value", this.value);
}
}

_onfocusout(event) {
// Prevent focusout when the focus is getting set within the slider internal
// element (on the handle), before the Slider' customElement itself is finished focusing
if (this._isFocusing()) {
this._preventFocusOut();
return;
}

// Reset focus state and the stored Slider's initial
// value that was saved when it was first focused in
this._setInitialValue("value", null);
}


/**
* Called when the user moves the slider
*
Expand Down Expand Up @@ -166,9 +196,7 @@ class Slider extends SliderBase {
* @private
*/
_isHandlePressed(clientX) {
const sliderHandle = this.shadowRoot.querySelector(".ui5-slider-handle");
const sliderHandleDomRect = sliderHandle.getBoundingClientRect();

const sliderHandleDomRect = this._sliderHandle.getBoundingClientRect();
return clientX >= sliderHandleDomRect.left && clientX <= sliderHandleDomRect.right;
}

Expand All @@ -187,6 +215,18 @@ class Slider extends SliderBase {
this._handlePositionFromStart = this._progressPercentage * 100;
}

_handleActionKeyPress(event) {
const min = this._effectiveMin;
const max = this._effectiveMax;
const currentValue = this.value;
const newValue = isEscape(event) ? this._getInitialValue("value") : this.constructor.clipValue(this._handleActionKeyPressBase(event, "value") + currentValue, min, max);

if (newValue !== currentValue) {
this._updateHandleAndProgress(newValue);
this.updateValue("value", newValue);
}
}

get styles() {
return {
progress: {
Expand All @@ -212,6 +252,10 @@ class Slider extends SliderBase {
};
}

get _sliderHandle() {
return this.shadowRoot.querySelector(".ui5-slider-handle");
}

get labelItems() {
return this._labelItems;
}
Expand All @@ -221,6 +265,10 @@ class Slider extends SliderBase {
return this.value.toFixed(stepPrecision);
}

get tabIndexProgress() {
return "-1";
}

static async onDefine() {
await fetchI18nBundle("@ui5/webcomponents");
}
Expand Down
4 changes: 3 additions & 1 deletion packages/main/src/SliderBase.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
@touchstart="{{_ontouchstart}}"
@mouseover="{{_onmouseover}}"
@mouseout="{{_onmouseout}}"
@keydown="{{_onkeydown}}"
@keyup="{{_onkeyup}}"
dir="{{effectiveDir}}"
>
<div class="ui5-slider-inner">
Expand All @@ -21,7 +23,7 @@
{{/if}}

<div class="ui5-slider-progress-container">
<div class="ui5-slider-progress" style="{{styles.progress}}"></div>
<div class="ui5-slider-progress" style="{{styles.progress}}" @focusout="{{_onfocusout}}" @focusin="{{_onfocusin}}" tabindex="{{tabIndexProgress}}"></div>
</div>
{{> handles}}
</div>
Expand Down
Loading