Skip to content

Commit

Permalink
feat: add keyboad navigation to select with autocomplete (#3097)
Browse files Browse the repository at this point in the history
* feat: add possibility to know if option hidden

* feat: add keyboard navigation

* fix: fix opening select when multiple and search enabled

* feat: add select on enter

* refactor: remove unused import

* refactor: move select autocomplete feature to separate component

* refactor: rename search to autocomplete

* refactor: rename autocomplete show case

* fix: fix dynamic change of withOptionsAutocomplete

* feat: add to showcase possibility to enable/disable autocomplete

* fix: fix button focus after closing options
  • Loading branch information
sashaqred committed Aug 31, 2022
1 parent 07ddd8c commit c52fe3a
Show file tree
Hide file tree
Showing 22 changed files with 2,873 additions and 263 deletions.
8 changes: 4 additions & 4 deletions src/app/playground-components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1162,10 +1162,10 @@ export const PLAYGROUND_COMPONENTS: ComponentLink[] = [
name: 'Select Icon',
},
{
path: 'select-search-showcase.component',
link: '/select/select-search-showcase.component',
component: 'SelectSearchShowcaseComponent',
name: 'Select Search Showcase',
path: 'select-autocomplete-showcase.component',
link: '/select/select-autocomplete-showcase.component',
component: 'SelectAutocompleteShowcaseComponent',
name: 'Select Autocomplete Showcase',
},
],
},
Expand Down
34 changes: 18 additions & 16 deletions src/framework/theme/components/option/option.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,16 +82,11 @@ import { NbSelectComponent } from '../select/select.component';
styleUrls: ['./option.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<nb-checkbox *ngIf="withCheckbox"
[checked]="selected"
[disabled]="disabled"
aria-hidden="true">
</nb-checkbox>
<nb-checkbox *ngIf="withCheckbox" [checked]="selected" [disabled]="disabled" aria-hidden="true"> </nb-checkbox>
<ng-content></ng-content>
`,
})
export class NbOptionComponent<T = any> implements OnDestroy, AfterViewInit, NbFocusableOption, NbHighlightableOption {

protected disabledByGroup = false;

/**
Expand Down Expand Up @@ -132,11 +127,13 @@ export class NbOptionComponent<T = any> implements OnDestroy, AfterViewInit, NbF
@HostBinding('attr.id')
id: string = `nb-option-${lastOptionId++}`;

constructor(@Optional() @Inject(NB_SELECT_INJECTION_TOKEN) parent,
protected elementRef: ElementRef,
protected cd: ChangeDetectorRef,
protected zone: NgZone,
protected renderer: Renderer2) {
constructor(
@Optional() @Inject(NB_SELECT_INJECTION_TOKEN) parent,
protected elementRef: ElementRef,
protected cd: ChangeDetectorRef,
protected zone: NgZone,
protected renderer: Renderer2,
) {
this.parent = parent;
}

Expand All @@ -146,9 +143,11 @@ export class NbOptionComponent<T = any> implements OnDestroy, AfterViewInit, NbF

ngAfterViewInit() {
// TODO: #2254
this.zone.runOutsideAngular(() => setTimeout(() => {
this.renderer.addClass(this.elementRef.nativeElement, 'nb-transition');
}));
this.zone.runOutsideAngular(() =>
setTimeout(() => {
this.renderer.addClass(this.elementRef.nativeElement, 'nb-transition');
}),
);
}

/**
Expand All @@ -162,6 +161,10 @@ export class NbOptionComponent<T = any> implements OnDestroy, AfterViewInit, NbF
return this.elementRef.nativeElement.textContent;
}

get hidden() {
return this.elementRef.nativeElement.hidden;
}

// TODO: replace with isShowCheckbox property to control this behaviour outside, issues/1965
@HostBinding('class.multiple')
get multiple() {
Expand All @@ -188,7 +191,7 @@ export class NbOptionComponent<T = any> implements OnDestroy, AfterViewInit, NbF
@HostBinding('class.active')
get activeClass() {
return this._active;
};
}
protected _active: boolean = false;

@HostListener('click', ['$event'])
Expand Down Expand Up @@ -252,5 +255,4 @@ export class NbOptionComponent<T = any> implements OnDestroy, AfterViewInit, NbF
this._active = false;
this.cd.markForCheck();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
@use '../../styles/theming' as *;
@use '../form-field/form-field.component.theme' as form-field-theme;

@mixin select-with-autocomplete-filled {
nb-select-with-autocomplete.appearance-filled .select-button {
border-style: nb-theme(select-filled-border-style);
border-width: nb-theme(select-filled-border-width);
}

@each $size in nb-get-sizes() {
nb-select-with-autocomplete.appearance-filled.size-#{$size} .select-button {
padding: nb-theme(select-filled-#{$size}-padding);
@include nb-ltr(padding-right, nb-theme(select-icon-offset));
@include nb-rtl(padding-left, nb-theme(select-icon-offset));
}

@include form-field-theme.nb-form-field-with-prefix(
'nb-select-with-autocomplete.appearance-filled.size-#{$size} .select-button',
$size
);
}

@each $status in nb-get-statuses() {
nb-select-with-autocomplete.appearance-filled.status-#{$status} .select-button {
background-color: nb-theme(select-filled-#{$status}-background-color);
border-color: nb-theme(select-filled-#{$status}-border-color);
color: nb-theme(select-filled-#{$status}-text-color);

&.placeholder {
color: nb-theme(select-filled-#{$status}-placeholder-text-color);
}

&:focus {
background-color: nb-theme(select-filled-#{$status}-focus-background-color);
border-color: nb-theme(select-filled-#{$status}-focus-border-color);
}
&:hover {
background-color: nb-theme(select-filled-#{$status}-hover-background-color);
border-color: nb-theme(select-filled-#{$status}-hover-border-color);
}

&[disabled] {
background-color: nb-theme(select-filled-#{$status}-disabled-background-color);
border-color: nb-theme(select-filled-#{$status}-disabled-border-color);
color: nb-theme(select-filled-#{$status}-disabled-text-color);

nb-icon {
color: nb-theme(select-filled-#{$status}-disabled-icon-color);
}
}

nb-icon {
color: nb-theme(select-filled-#{$status}-icon-color);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
@use '../../styles/theming' as *;
@use '../form-field/form-field.component.theme' as form-field-theme;

@mixin select-with-autocomplete-hero {
nb-select-with-autocomplete.appearance-hero .select-button {
border: none;
}

@each $size in nb-get-sizes() {
nb-select-with-autocomplete.appearance-hero.size-#{$size} .select-button {
padding: nb-theme(select-hero-#{$size}-padding);
@include nb-ltr(padding-right, nb-theme(select-icon-offset));
@include nb-rtl(padding-left, nb-theme(select-icon-offset));
}
@include form-field-theme.nb-form-field-with-prefix(
'nb-select-with-autocomplete.appearance-hero.size-#{$size} .select-button',
$size
);
}

@each $status in nb-get-statuses() {
nb-select-with-autocomplete.appearance-hero.status-#{$status} .select-button {
$left-color: nb-theme(select-hero-#{$status}-left-background-color);
$right-color: nb-theme(select-hero-#{$status}-right-background-color);
background-image: linear-gradient(to right, $left-color, $right-color);
color: nb-theme(select-hero-#{$status}-text-color);

&.placeholder {
color: nb-theme(select-hero-#{$status}-placeholder-text-color);
}

&:focus {
$left-color: nb-theme(select-hero-#{$status}-focus-left-background-color);
$right-color: nb-theme(select-hero-#{$status}-focus-right-background-color);
background-image: linear-gradient(to right, $left-color, $right-color);
}
&:hover {
$left-color: nb-theme(select-hero-#{$status}-hover-left-background-color);
$right-color: nb-theme(select-hero-#{$status}-hover-right-background-color);
background-image: linear-gradient(to right, $left-color, $right-color);
}
&[disabled] {
color: nb-theme(select-hero-#{$status}-disabled-text-color);
background-color: nb-theme(select-hero-#{$status}-disabled-background-color);
background-image: none;

nb-icon {
color: nb-theme(select-hero-#{$status}-disabled-icon-color);
}
}

nb-icon {
color: nb-theme(select-hero-#{$status}-icon-color);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
@use '../../styles/theming' as *;
@use '../form-field/form-field.component.theme' as form-field-theme;

@mixin select-with-autocomplete-outline {
nb-select-with-autocomplete.appearance-outline .select-button {
border-style: nb-theme(select-outline-border-style);
border-width: nb-theme(select-outline-border-width);

&.top {
border-top-style: nb-theme(select-outline-adjacent-border-style);
border-top-width: nb-theme(select-outline-adjacent-border-width);
}
&.bottom {
border-bottom-style: nb-theme(select-outline-adjacent-border-style);
border-bottom-width: nb-theme(select-outline-adjacent-border-width);
}
}

@each $status in nb-get-statuses() {
nb-select-with-autocomplete.appearance-outline.status-#{$status} .select-button {
background-color: nb-theme(select-outline-#{$status}-background-color);
border-color: nb-theme(select-outline-#{$status}-border-color);
color: nb-theme(select-outline-#{$status}-text-color);

&.placeholder {
color: nb-theme(select-outline-#{$status}-placeholder-text-color);
}
nb-icon {
color: nb-theme(select-outline-#{$status}-icon-color);
}

&:focus {
background-color: nb-theme(select-outline-#{$status}-focus-background-color);
border-color: nb-theme(select-outline-#{$status}-focus-border-color);
}
&:hover {
background-color: nb-theme(select-outline-#{$status}-hover-background-color);
border-color: nb-theme(select-outline-#{$status}-hover-border-color);
}

&[disabled] {
color: nb-theme(select-outline-#{$status}-disabled-text-color);
background-color: nb-theme(select-outline-#{$status}-disabled-background-color);
border-color: nb-theme(select-outline-#{$status}-disabled-border-color);

nb-icon {
color: nb-theme(select-outline-#{$status}-disabled-icon-color);
}
}

&.bottom,
&.top {
border-color: nb-theme(select-outline-#{$status}-open-border-color);
}

&.top {
border-top-color: nb-theme(select-outline-#{$status}-adjacent-border-color);
}
&.bottom {
border-bottom-color: nb-theme(select-outline-#{$status}-adjacent-border-color);
}
}
}

@each $size in nb-get-sizes() {
nb-select-with-autocomplete.appearance-outline.size-#{$size} .select-button {
padding: nb-theme(select-outline-#{$size}-padding);
@include nb-ltr(padding-right, nb-theme(select-icon-offset));
@include nb-rtl(padding-left, nb-theme(select-icon-offset));
}

@include form-field-theme.nb-form-field-with-prefix(
'nb-select-with-autocomplete.appearance-outline.size-#{$size} .select-button',
$size
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* @license
* Copyright Akveo. All Rights Reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*/

@use '../../styles/theming' as *;
@use '../form-field/form-field.component.theme' as form-field-theme;
@use 'select-with-autocomplete-outline';
@use 'select-with-autocomplete-filled';
@use 'select-with-autocomplete-hero';

@mixin nb-select-with-autocomplete-theme() {
nb-select-with-autocomplete .select-button {
min-width: nb-theme(select-min-width);
cursor: nb-theme(select-cursor);
font-family: nb-theme(select-text-font-family);

&.placeholder {
font-family: nb-theme(select-placeholder-text-font-family);
}
&:focus {
outline: none;
}
&[disabled] {
cursor: nb-theme(select-disabled-cursor);
}
}

@each $size in nb-get-sizes() {
nb-select-with-autocomplete.size-#{$size} {
.select-button {
font-size: nb-theme(select-#{$size}-text-font-size);
font-weight: nb-theme(select-#{$size}-text-font-weight);
line-height: nb-theme(select-#{$size}-text-line-height);

&.placeholder {
font-size: nb-theme(select-#{$size}-placeholder-text-font-size);
font-weight: nb-theme(select-#{$size}-placeholder-text-font-weight);
}

&.empty::before {
content: ' ';
display: block;
height: nb-theme(select-#{$size}-text-line-height);
}
}

&:not(.full-width) {
max-width: nb-theme(select-#{$size}-max-width);
}
}
}

@each $shape in nb-get-shapes() {
nb-select-with-autocomplete.shape-#{$shape} .select-button {
border-radius: nb-theme(select-#{$shape}-border-radius);
}
}

@include select-with-autocomplete-outline.select-with-autocomplete-outline();
@include select-with-autocomplete-filled.select-with-autocomplete-filled();
@include select-with-autocomplete-hero.select-with-autocomplete-hero();

@include form-field-theme.nb-form-field-root-component('nb-select-with-autocomplete');
}
Loading

0 comments on commit c52fe3a

Please sign in to comment.