Skip to content

Commit b14bb72

Browse files
karahansl
authored andcommitted
feat(select): basic selection and animations (#1647)
1 parent 3ee1b59 commit b14bb72

File tree

15 files changed

+871
-20
lines changed

15 files changed

+871
-20
lines changed

src/demo-app/select/select-demo.html

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,5 @@
1-
<md-select></md-select>
1+
<div class="demo-select">
2+
<md-select placeholder="Food">
3+
<md-option *ngFor="let food of foods"> {{ food.viewValue }} </md-option>
4+
</md-select>
5+
</div>

src/demo-app/select/select-demo.scss

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
.demo-select {
2+
}

src/demo-app/select/select-demo.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,9 @@ import {Component} from '@angular/core';
88
styleUrls: ['select-demo.css'],
99
})
1010
export class SelectDemo {
11-
11+
foods = [
12+
{value: 'steak', viewValue: 'Steak'},
13+
{value: 'pizza', viewValue: 'Pizza'},
14+
{value: 'tacos', viewValue: 'Tacos'}
15+
];
1216
}

src/lib/core/a11y/list-key-manager.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ export class ListKeyManager {
3030
return this._tabOut.asObservable();
3131
}
3232

33+
get focusedItemIndex(): number {
34+
return this._focusedItemIndex;
35+
}
36+
3337
set focusedItemIndex(value: number) {
3438
this._focusedItemIndex = value;
3539
}

src/lib/core/compatibility/style-compatibility.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export const ELEMENTS_SELECTOR = `
2626
md-list-item,
2727
md-menu,
2828
md-nav-list,
29+
md-option,
2930
md-placeholder,
3031
md-progress-bar,
3132
md-progress-circle,

src/lib/select/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
## Work in progress!
2+
3+
The select is still a work in progress, so most features have not been implemented. Not ready for use!

src/lib/select/_select-theme.scss

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,50 @@
22
@import '../core/theming/theming';
33

44
@mixin md-select-theme($theme) {
5+
$foreground: map-get($theme, foreground);
6+
$background: map-get($theme, background);
7+
$primary: map-get($theme, primary);
58

9+
.md-select-trigger {
10+
color: md-color($foreground, hint-text);
11+
border-bottom: 1px solid md-color($foreground, divider);
12+
13+
md-select:focus & {
14+
border-bottom: 1px solid md-color($primary);
15+
}
16+
}
17+
18+
.md-select-placeholder {
19+
md-select:focus & {
20+
color: md-color($primary);
21+
}
22+
}
23+
24+
.md-select-arrow {
25+
color: md-color($foreground, hint-text);
26+
27+
md-select:focus & {
28+
color: md-color($primary);
29+
}
30+
}
31+
32+
.md-select-content {
33+
background: md-color($background, card);
34+
}
35+
36+
.md-select-value {
37+
color: md-color($foreground, text);
38+
}
39+
40+
md-option {
41+
&:hover, &:focus {
42+
background: md-color($background, hover);
43+
}
44+
45+
&.md-selected {
46+
background: md-color($background, hover);
47+
color: md-color($primary);
48+
}
49+
50+
}
651
}

src/lib/select/index.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,22 @@
11
import {NgModule, ModuleWithProviders} from '@angular/core';
2+
import {CommonModule} from '@angular/common';
23
import {MdSelect} from './select';
34
import {MdOption} from './option';
5+
import {OverlayModule} from '../core/overlay/overlay-directives';
6+
import {MdRippleModule} from '../core/ripple/ripple';
7+
import {OVERLAY_PROVIDERS} from '../core/overlay/overlay';
48
export * from './select';
59

610
@NgModule({
7-
imports: [],
11+
imports: [CommonModule, OverlayModule, MdRippleModule],
812
exports: [MdSelect, MdOption],
913
declarations: [MdSelect, MdOption],
1014
})
1115
export class MdSelectModule {
1216
static forRoot(): ModuleWithProviders {
1317
return {
1418
ngModule: MdSelectModule,
15-
providers: []
19+
providers: [OVERLAY_PROVIDERS]
1620
};
1721
}
1822
}

src/lib/select/option.html

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<ng-content></ng-content>
2+
<div class="md-option-ripple" md-ripple md-ripple-background-color="rgba(0,0,0,0)"
3+
[md-ripple-trigger]="_getHostElement()"></div>

src/lib/select/option.ts

Lines changed: 68 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,75 @@
1-
import {Component, ViewEncapsulation} from '@angular/core';
1+
import {
2+
Component,
3+
ElementRef,
4+
EventEmitter,
5+
Output,
6+
Renderer,
7+
ViewEncapsulation
8+
} from '@angular/core';
9+
import {ENTER, SPACE} from '../core/keyboard/keycodes';
210

311
@Component({
412
moduleId: module.id,
513
selector: 'md-option',
6-
template: ``,
14+
host: {
15+
'role': 'option',
16+
'tabindex': '0',
17+
'[class.md-selected]': 'selected',
18+
'[attr.aria-selected]': 'selected.toString()',
19+
'(click)': 'select()',
20+
'(keydown)': '_handleKeydown($event)'
21+
},
22+
templateUrl: 'option.html',
723
styleUrls: ['select.css'],
824
encapsulation: ViewEncapsulation.None
925
})
10-
export class MdOption {}
26+
export class MdOption {
27+
private _selected = false;
28+
29+
/** Event emitted when the option is selected. */
30+
@Output() onSelect = new EventEmitter();
31+
32+
constructor(private _element: ElementRef, private _renderer: Renderer) {}
33+
34+
/** Whether or not the option is currently selected. */
35+
get selected(): boolean {
36+
return this._selected;
37+
}
38+
39+
/**
40+
* The displayed value of the option. It is necessary to show the selected option in the
41+
* select's trigger.
42+
* TODO(kara): Add input property alternative for node envs.
43+
*/
44+
get viewValue(): string {
45+
return this._getHostElement().textContent.trim();
46+
}
47+
48+
/** Selects the option. */
49+
select(): void {
50+
this._selected = true;
51+
this.onSelect.emit();
52+
}
53+
54+
/** Deselects the option. */
55+
deselect(): void {
56+
this._selected = false;
57+
}
58+
59+
/** Sets focus onto this option. */
60+
focus(): void {
61+
this._renderer.invokeElementMethod(this._getHostElement(), 'focus');
62+
}
63+
64+
/** Ensures the option is selected when activated from the keyboard. */
65+
_handleKeydown(event: KeyboardEvent): void {
66+
if (event.keyCode === ENTER || event.keyCode === SPACE) {
67+
this.select();
68+
}
69+
}
70+
71+
_getHostElement(): HTMLElement {
72+
return this._element.nativeElement;
73+
}
74+
75+
}

0 commit comments

Comments
 (0)