Skip to content

Commit

Permalink
fix(inputs): focus handling
Browse files Browse the repository at this point in the history
  • Loading branch information
manucorporat committed Jan 19, 2019
1 parent b50a3cc commit 672d4ec
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 32 deletions.
9 changes: 9 additions & 0 deletions core/src/components/checkbox/checkbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { createColorClasses, hostContext } from '../../utils/theme';
export class Checkbox implements ComponentInterface {

private inputId = `ion-cb-${checkboxIds++}`;
private buttonEl?: HTMLElement;

@Element() el!: HTMLElement;

Expand Down Expand Up @@ -98,9 +99,16 @@ export class Checkbox implements ComponentInterface {

@Listen('click')
onClick() {
this.setFocus();
this.checked = !this.checked;
}

private setFocus() {
if (this.buttonEl) {
this.buttonEl.focus();
}
}

private onFocus = () => {
this.ionFocus.emit();
}
Expand Down Expand Up @@ -146,6 +154,7 @@ export class Checkbox implements ComponentInterface {
onFocus={this.onFocus}
onBlur={this.onBlur}
disabled={this.disabled}
ref={el => this.buttonEl = el}
>
</button>
];
Expand Down
1 change: 1 addition & 0 deletions core/src/components/datetime/datetime.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ export class Datetime implements ComponentInterface {

@Listen('click')
onClick() {
this.setFocus();
this.open();
}

Expand Down
4 changes: 2 additions & 2 deletions core/src/components/input/input.md.vars.scss
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@
$input-md-font-size: inherit !default;

/// @prop - Margin top of the input
$input-md-padding-top: $item-md-padding-top !default;
$input-md-padding-top: 10px !default;

/// @prop - Margin end of the input
$input-md-padding-end: 0 !default;

/// @prop - Margin bottom of the input
$input-md-padding-bottom: $item-md-padding-bottom !default;
$input-md-padding-bottom: 10px !default;

/// @prop - Margin start of the input
$input-md-padding-start: ($item-md-padding-start / 2) !default;
Expand Down
12 changes: 8 additions & 4 deletions core/src/components/item/item.scss
Original file line number Diff line number Diff line change
Expand Up @@ -284,16 +284,21 @@ button, a {
// Item Input Focused
// --------------------------------------------------

:host(.item-interactive.item-has-focus) {
--highlight-background: var(--highlight-color-focused);

:host(.item-interactive.item-has-focus),
:host(.item-interactive.ion-touched.ion-invalid) {
// If the item has a full border and highlight is enabled, show the full item highlight
--full-highlight-height: #{calc(var(--highlight-height) * var(--show-full-highlight))};

// If the item has an inset border and highlight is enabled, show the inset item highlight
--inset-highlight-height: #{calc(var(--highlight-height) * var(--show-inset-highlight))};
}

// Item Input Focus
// --------------------------------------------------

:host(.item-interactive.item-has-focus) {
--highlight-background: var(--highlight-color-focused);
}

// Item Input Valid
// --------------------------------------------------
Expand All @@ -302,7 +307,6 @@ button, a {
--highlight-background: var(--highlight-color-valid);
}


// Item Input Invalid
// --------------------------------------------------

Expand Down
71 changes: 45 additions & 26 deletions core/src/components/range/range.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, ComponentInterface, Element, Event, EventEmitter, Prop, QueueApi, State, Watch } from '@stencil/core';
import { Component, ComponentInterface, Element, Event, EventEmitter, Prop, QueueApi, State, Watch, Listen } from '@stencil/core';

import { Color, Gesture, GestureDetail, KnobName, Mode, RangeChangeEventDetail, RangeValue, StyleEventDetail } from '../../interface';
import { clamp, debounceEvent } from '../../utils/helpers';
Expand Down Expand Up @@ -145,6 +145,24 @@ export class Range implements ComponentInterface {
*/
@Event() ionBlur!: EventEmitter<void>;

@Listen('focusout')
onBlur() {
if (this.hasFocus) {
this.hasFocus = false;
this.ionBlur.emit();
this.emitStyle();
}
}

@Listen('focusin')
onFocus() {
if (!this.hasFocus) {
this.hasFocus = true;
this.ionFocus.emit();
this.emitStyle();
}
}

componentWillLoad() {
this.updateRatio();
this.debounceChanged();
Expand All @@ -165,7 +183,7 @@ export class Range implements ComponentInterface {
this.gesture.setDisabled(this.disabled);
}

private handleKeyboard = (knob: string, isIncrease: boolean) => {
private handleKeyboard = (knob: KnobName, isIncrease: boolean) => {
let step = this.step;
step = step > 0 ? step : 1;
step = step / (this.max - this.min);
Expand Down Expand Up @@ -200,29 +218,12 @@ export class Range implements ComponentInterface {

private emitStyle() {
this.ionStyle.emit({
'interactive': true,
'interactive-disabled': this.disabled
});
}

private fireBlur() {
if (this.hasFocus) {
this.hasFocus = false;
this.ionBlur.emit();
this.emitStyle();
}
}

private fireFocus() {
if (!this.hasFocus) {
this.hasFocus = true;
this.ionFocus.emit();
this.emitStyle();
}
}

private onStart(detail: GestureDetail) {
this.fireFocus();

const rect = this.rect = this.rangeSlider!.getBoundingClientRect() as any;
const currentX = detail.currentX;

Expand All @@ -234,6 +235,8 @@ export class Range implements ComponentInterface {
? 'A'
: 'B';

this.setFocus(this.pressedKnob);

// update the active knob's position
this.update(currentX);
}
Expand All @@ -245,7 +248,6 @@ export class Range implements ComponentInterface {
private onEnd(detail: GestureDetail) {
this.update(detail.currentX);
this.pressedKnob = undefined;
this.fireBlur();
}

private update(currentX: number) {
Expand All @@ -255,8 +257,11 @@ export class Range implements ComponentInterface {
let ratio = clamp(0, (currentX - rect.left) / rect.width, 1);
if (this.snaps) {
// snaps the ratio to the current value
const value = ratioToValue(ratio, this.min, this.max, this.step);
ratio = valueToRatio(value, this.min, this.max);
ratio = valueToRatio(
ratioToValue(ratio, this.min, this.max, this.step),
this.min,
this.max
);
}

// update which knob is pressed
Expand Down Expand Up @@ -317,6 +322,15 @@ export class Range implements ComponentInterface {
this.noUpdate = false;
}

private setFocus(knob: KnobName) {
if (this.el.shadowRoot) {
const knobEl = this.el.shadowRoot.querySelector(knob === 'A' ? '.range-knob-a' : '.range-knob-b') as HTMLElement | undefined;
if (knobEl) {
knobEl.focus();
}
}
}

hostData() {
return {
class: {
Expand Down Expand Up @@ -349,7 +363,10 @@ export class Range implements ComponentInterface {

return [
<slot name="start"></slot>,
<div class="range-slider" ref={el => this.rangeSlider = el}>
<div
class="range-slider"
ref={el => this.rangeSlider = el}
>
{ticks.map(t => (
<div
style={{ left: t.left }}
Expand Down Expand Up @@ -401,7 +418,7 @@ export class Range implements ComponentInterface {
}

interface RangeKnob {
knob: string;
knob: KnobName;
value: number;
ratio: number;
min: number;
Expand All @@ -410,7 +427,7 @@ interface RangeKnob {
pressed: boolean;
pin: boolean;

handleKeyboard: (name: string, isIncrease: boolean) => void;
handleKeyboard: (name: KnobName, isIncrease: boolean) => void;
}

function renderKnob({ knob, value, ratio, min, max, disabled, pressed, pin, handleKeyboard }: RangeKnob) {
Expand All @@ -431,6 +448,8 @@ function renderKnob({ knob, value, ratio, min, max, disabled, pressed, pin, hand
}}
class={{
'range-knob-handle': true,
'range-knob-a': knob === 'A',
'range-knob-b': knob === 'B',
'range-knob-pressed': pressed,
'range-knob-min': value === min,
'range-knob-max': value === max
Expand Down
1 change: 1 addition & 0 deletions core/src/components/select/select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ export class Select implements ComponentInterface {

@Listen('click')
onClick(ev: UIEvent) {
this.setFocus();
this.open(ev);
}

Expand Down
9 changes: 9 additions & 0 deletions core/src/components/toggle/toggle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export class Toggle implements ComponentInterface {
private inputId = `ion-tg-${toggleIds++}`;
private pivotX = 0;
private gesture?: Gesture;
private buttonEl?: HTMLElement;

@Element() el!: HTMLElement;

Expand Down Expand Up @@ -133,6 +134,7 @@ export class Toggle implements ComponentInterface {

// touch-action does not work in iOS
detail.event.preventDefault();
this.setFocus();
return true;
}

Expand All @@ -159,6 +161,12 @@ export class Toggle implements ComponentInterface {
return this.value || '';
}

private setFocus() {
if (this.buttonEl) {
this.buttonEl.focus();
}
}

private onFocus = () => {
this.ionFocus.emit();
}
Expand Down Expand Up @@ -205,6 +213,7 @@ export class Toggle implements ComponentInterface {
onFocus={this.onFocus}
onBlur={this.onBlur}
disabled={this.disabled}
ref={el => this.buttonEl = el}
>
</button>
];
Expand Down

0 comments on commit 672d4ec

Please sign in to comment.