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

Include focus mixin in focusable widgets #608

Merged
merged 2 commits into from
Oct 11, 2018
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
6 changes: 4 additions & 2 deletions src/checkbox/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { WidgetBase } from '@dojo/framework/widget-core/WidgetBase';
import { DNode } from '@dojo/framework/widget-core/interfaces';
import { ThemedMixin, ThemedProperties, theme } from '@dojo/framework/widget-core/mixins/Themed';
import { FocusMixin, FocusProperties } from '@dojo/framework/widget-core/mixins/Focus';
import Focus from '@dojo/framework/widget-core/meta/Focus';
import Label from '../label/index';
import { CustomAriaProperties, LabeledProperties, InputProperties, CheckboxRadioEventProperties, KeyEventProperties, PointerEventProperties } from '../common/interfaces';
Expand All @@ -21,7 +22,7 @@ import { customElement } from '@dojo/framework/widget-core/decorators/customElem
* @property onLabel Label to show in the "on" positin of a toggle
* @property value The current value
*/
export interface CheckboxProperties extends ThemedProperties, InputProperties, LabeledProperties, KeyEventProperties, PointerEventProperties, CustomAriaProperties, CheckboxRadioEventProperties {
export interface CheckboxProperties extends ThemedProperties, InputProperties, FocusProperties, LabeledProperties, KeyEventProperties, PointerEventProperties, CustomAriaProperties, CheckboxRadioEventProperties {
checked?: boolean;
mode?: Mode;
offLabel?: DNode;
Expand All @@ -37,7 +38,7 @@ export enum Mode {
toggle = 'toggle'
}

export const ThemedBase = ThemedMixin(WidgetBase);
export const ThemedBase = ThemedMixin(FocusMixin(WidgetBase));

@theme(css)
@customElement<CheckboxProperties>({
Expand Down Expand Up @@ -189,6 +190,7 @@ export class CheckboxBase<P extends CheckboxProperties = CheckboxProperties> ext
classes: this.theme(css.input),
checked,
disabled,
focus: this.shouldFocus,
'aria-invalid': invalid === true ? 'true' : null,
name,
readOnly,
Expand Down
6 changes: 6 additions & 0 deletions src/checkbox/tests/unit/Checkbox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ const expected = function(label = false, toggle = false, toggleLabels = false, c
classes: css.input,
checked,
disabled: undefined,
focus: noop,
'aria-invalid': null,
name: undefined,
readOnly: undefined,
Expand Down Expand Up @@ -119,6 +120,7 @@ registerSuite('Checkbox', {
classes: css.input,
checked: true,
disabled: undefined,
focus: noop,
'aria-invalid': null,
readOnly: undefined,
'aria-readonly': null,
Expand Down Expand Up @@ -168,6 +170,7 @@ registerSuite('Checkbox', {
id: '',
classes: css.input,
checked: false,
focus: noop,
'aria-invalid': 'true',
'aria-readonly': 'true',
type: 'checkbox',
Expand Down Expand Up @@ -203,6 +206,7 @@ registerSuite('Checkbox', {
id: '',
classes: css.input,
checked: false,
focus: noop,
'aria-invalid': null,
'aria-readonly': null,
type: 'checkbox',
Expand Down Expand Up @@ -252,6 +256,7 @@ registerSuite('Checkbox', {
v('input', {
disabled: true,
classes: css.input,
focus: noop,
'aria-invalid': 'true',
readOnly: true,
'aria-readonly': 'true',
Expand Down Expand Up @@ -307,6 +312,7 @@ registerSuite('Checkbox', {
classes: css.input,
checked: false,
disabled: undefined,
focus: noop,
'aria-invalid': null,
name: undefined,
readOnly: undefined,
Expand Down
4 changes: 2 additions & 2 deletions src/combobox/tests/functional/ComboBox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ registerSuite('ComboBox', {
return getPage(this.remote)
.findByCssSelector(`.${css.clear}`)
.click()
.sleep(30)
.sleep(DELAY)
.getActiveElement()
.getTagName()
.then(tag => {
Expand All @@ -135,7 +135,7 @@ registerSuite('ComboBox', {
.type(keys.TAB)
.getActiveElement()
.type(keys.ENTER)
.sleep(30)
.sleep(DELAY)
.getActiveElement()
.getTagName()
.then(tag => {
Expand Down
35 changes: 14 additions & 21 deletions src/listbox/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { CustomAriaProperties } from '../common/interfaces';
import { formatAriaProperties, Keys } from '../common/util';
import MetaBase from '@dojo/framework/widget-core/meta/Base';
import { ThemedMixin, ThemedProperties, theme } from '@dojo/framework/widget-core/mixins/Themed';
import { FocusMixin, FocusProperties } from '@dojo/framework/widget-core/mixins/Focus';
import { uuid } from '@dojo/framework/core/util';
import { v, w } from '@dojo/framework/widget-core/d';
import { WidgetBase } from '@dojo/framework/widget-core/WidgetBase';
Expand Down Expand Up @@ -45,14 +46,13 @@ export class ScrollMeta extends MetaBase {
* @property onOptionSelect Called with the option data of the new requested selected item
*/

export interface ListboxProperties extends ThemedProperties, CustomAriaProperties {
export interface ListboxProperties extends ThemedProperties, FocusProperties, CustomAriaProperties {
activeIndex?: number;
getOptionDisabled?(option: any, index: number): boolean;
getOptionId?(option: any, index: number): string;
getOptionLabel?(option: any, index: number): DNode;
getOptionSelected?(option: any, index: number): boolean;
widgetId?: string;
focus?: boolean;
multiselect?: boolean;
optionData?: any[];
tabIndex?: number;
Expand All @@ -62,15 +62,14 @@ export interface ListboxProperties extends ThemedProperties, CustomAriaPropertie
onOptionSelect?(option: any, index: number, key?: string | number): void;
}

export const ThemedBase = ThemedMixin(WidgetBase);
export const ThemedBase = ThemedMixin(FocusMixin(WidgetBase));

@theme(css)
@diffProperty('optionData', reference)
@customElement<ListboxProperties>({
tag: 'dojo-listbox',
properties: [
'activeIndex',
'focus',
'multiselect',
'tabIndex',
'visualFocus',
Expand Down Expand Up @@ -239,27 +238,21 @@ export class ListboxBase<P extends ListboxProperties = ListboxProperties> extend
aria = {},
widgetId,
multiselect = false,
focus,
tabIndex = 0
} = this.properties;
const themeClasses = this.getModifierClasses();

return v('div', () => {
if (focus) {
this.meta(Focus).set('root');
}

return {
...formatAriaProperties(aria),
'aria-activedescendant': this._getOptionId(activeIndex),
'aria-multiselectable': multiselect ? 'true' : null,
classes: this.theme([ css.root, ...themeClasses ]),
id: widgetId,
key: 'root',
role: 'listbox',
tabIndex,
onkeydown: this._onKeyDown
};
return v('div', {
...formatAriaProperties(aria),
'aria-activedescendant': this._getOptionId(activeIndex),
'aria-multiselectable': multiselect ? 'true' : null,
classes: this.theme([ css.root, ...themeClasses ]),
id: widgetId,
focus: this.shouldFocus,
key: 'root',
role: 'listbox',
tabIndex,
onkeydown: this._onKeyDown
}, this.renderOptions());
}
}
Expand Down
3 changes: 3 additions & 0 deletions src/listbox/tests/unit/Listbox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ const expectedVdom = function(options: DNode[] = []) {
'aria-multiselectable': null,
classes: [ css.root, null ],
id: undefined,
focus: noop,
key: 'root',
role: 'listbox',
tabIndex: 0,
Expand Down Expand Up @@ -153,6 +154,7 @@ registerSuite('Listbox', {
classes: [ css.root, css.focused ],
id: 'bar',
tabIndex: -1,
focus: noop,
key: 'root',
role: 'listbox',
onkeydown: noop
Expand Down Expand Up @@ -192,6 +194,7 @@ registerSuite('Listbox', {
'aria-multiselectable': null,
classes: [ css.root, css.focused ],
id: undefined,
focus: noop,
key: 'root',
role: 'listbox',
tabIndex: 0,
Expand Down
6 changes: 4 additions & 2 deletions src/radio/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { WidgetBase } from '@dojo/framework/widget-core/WidgetBase';
import { DNode } from '@dojo/framework/widget-core/interfaces';
import { ThemedMixin, ThemedProperties, theme } from '@dojo/framework/widget-core/mixins/Themed';
import { FocusMixin, FocusProperties } from '@dojo/framework/widget-core/mixins/Focus';
import Focus from '@dojo/framework/widget-core/meta/Focus';
import Label from '../label/index';
import { CustomAriaProperties, LabeledProperties, InputProperties, KeyEventProperties, CheckboxRadioEventProperties, PointerEventProperties } from '../common/interfaces';
Expand All @@ -18,12 +19,12 @@ import { customElement } from '@dojo/framework/widget-core/decorators/customElem
* @property checked Checked/unchecked property of the radio
* @property value The current value
*/
export interface RadioProperties extends ThemedProperties, LabeledProperties, InputProperties, KeyEventProperties, PointerEventProperties, CustomAriaProperties, CheckboxRadioEventProperties {
export interface RadioProperties extends ThemedProperties, LabeledProperties, InputProperties, FocusProperties, KeyEventProperties, PointerEventProperties, CustomAriaProperties, CheckboxRadioEventProperties {
checked?: boolean;
value?: string;
}

export const ThemedBase = ThemedMixin(WidgetBase);
export const ThemedBase = ThemedMixin(FocusMixin(WidgetBase));

@theme(css)
@customElement<RadioProperties>({
Expand Down Expand Up @@ -146,6 +147,7 @@ export class RadioBase<P extends RadioProperties = RadioProperties> extends Them
classes: this.theme(css.input),
checked,
disabled,
focus: this.shouldFocus,
'aria-invalid': invalid === true ? 'true' : null,
name,
readOnly,
Expand Down
1 change: 1 addition & 0 deletions src/radio/tests/unit/Radio.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ const expected = function({ label = false, rootOverrides = {}, inputOverrides =
classes: css.input,
checked: false,
disabled: disabled,
focus: noop,
'aria-invalid': invalid ? 'true' : null,
name: undefined,
readOnly: readOnly,
Expand Down
25 changes: 12 additions & 13 deletions src/select/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { diffProperty } from '@dojo/framework/widget-core/decorators/diffPropert
import { reference } from '@dojo/framework/widget-core/diff';
import { DNode } from '@dojo/framework/widget-core/interfaces';
import { ThemedMixin, ThemedProperties, theme } from '@dojo/framework/widget-core/mixins/Themed';
import { FocusMixin, FocusProperties } from '@dojo/framework/widget-core/mixins/Focus';
import Focus from '@dojo/framework/widget-core/meta/Focus';
import { v, w } from '@dojo/framework/widget-core/d';
import { uuid } from '@dojo/framework/core/util';
Expand Down Expand Up @@ -31,7 +32,7 @@ import { customElement } from '@dojo/framework/widget-core/decorators/customElem
* @property useNativeElement Use the native <select> element if true
* @property value The current value
*/
export interface SelectProperties extends ThemedProperties, InputProperties, LabeledProperties, CustomAriaProperties {
export interface SelectProperties extends ThemedProperties, InputProperties, FocusProperties, LabeledProperties, CustomAriaProperties {
getOptionDisabled?(option: any, index: number): boolean;
getOptionId?(option: any, index: number): string;
getOptionLabel?(option: any): DNode;
Expand All @@ -47,7 +48,7 @@ export interface SelectProperties extends ThemedProperties, InputProperties, Lab
value?: string;
}

export const ThemedBase = ThemedMixin(WidgetBase);
export const ThemedBase = ThemedMixin(FocusMixin(WidgetBase));

@theme(css)
@diffProperty('options', reference)
Expand Down Expand Up @@ -80,8 +81,8 @@ export const ThemedBase = ThemedMixin(WidgetBase);
]
})
export class SelectBase<P extends SelectProperties = SelectProperties> extends ThemedBase<P, null> {
private _callListboxFocus = false;
private _focusedIndex = 0;
private _focusNode = 'trigger';
private _ignoreBlur = false;
private _open = false;
private _baseId = uuid();
Expand Down Expand Up @@ -142,14 +143,16 @@ export class SelectBase<P extends SelectProperties = SelectProperties> extends T

// custom select events
private _openSelect() {
this._callListboxFocus = true;
this.focus();
this._focusNode = 'listbox';
this._ignoreBlur = true;
this._open = true;
this._focusedIndex = this._focusedIndex || 0;
this.invalidate();
}

private _closeSelect() {
this._focusNode = 'trigger';
this._ignoreBlur = true;
this._open = false;
this.invalidate();
Expand All @@ -158,8 +161,8 @@ export class SelectBase<P extends SelectProperties = SelectProperties> extends T
private _onDropdownKeyDown(event: KeyboardEvent) {
event.stopPropagation();
if (event.which === Keys.Escape) {
this.meta(Focus).set('trigger');
this._closeSelect();
this.focus();
}
}

Expand Down Expand Up @@ -265,6 +268,7 @@ export class SelectBase<P extends SelectProperties = SelectProperties> extends T
...formatAriaProperties(aria),
classes: this.theme(css.input),
disabled,
focus: this.shouldFocus,
'aria-invalid': invalid ? 'true' : null,
id: widgetId,
name,
Expand Down Expand Up @@ -298,12 +302,6 @@ export class SelectBase<P extends SelectProperties = SelectProperties> extends T
_focusedIndex
} = this;

const focusListbox = this._callListboxFocus;

if (this._callListboxFocus) {
this._callListboxFocus = false;
}

// create dropdown trigger and select box
return v('div', {
key: 'wrapper',
Expand All @@ -319,7 +317,7 @@ export class SelectBase<P extends SelectProperties = SelectProperties> extends T
key: 'listbox',
activeIndex: _focusedIndex,
widgetId: widgetId,
focus: focusListbox,
focus: this._focusNode === 'listbox' ? this.shouldFocus : () => false,
optionData: options,
tabIndex: _open ? 0 : -1,
getOptionDisabled,
Expand All @@ -333,8 +331,8 @@ export class SelectBase<P extends SelectProperties = SelectProperties> extends T
},
onOptionSelect: (option: any) => {
onChange && onChange(option, key);
this.meta(Focus).set('trigger');
this._closeSelect();
this.focus();
},
onKeyDown: (event: KeyboardEvent) => {
const index = this._getSelectedIndexOnInput(event);
Expand Down Expand Up @@ -386,6 +384,7 @@ export class SelectBase<P extends SelectProperties = SelectProperties> extends T
'aria-required': required ? 'true' : null,
classes: this.theme([ css.trigger, isPlaceholder ? css.placeholder : null ]),
disabled: disabled || readOnly,
focus: this._focusNode === 'trigger' ? this.shouldFocus : () => false,
key: 'trigger',
type: 'button',
value,
Expand Down
Loading