Skip to content

Commit

Permalink
feat(select): implement select
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 523532548
  • Loading branch information
material-web-copybara authored and copybara-github committed Apr 11, 2023
1 parent 55df403 commit 9c202f5
Show file tree
Hide file tree
Showing 22 changed files with 1,771 additions and 2 deletions.
6 changes: 6 additions & 0 deletions select/_filled-select.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
//
// Copyright 2023 Google LLC
// SPDX-License-Identifier: Apache-2.0
//

@forward './lib/filled-select' show theme;
6 changes: 6 additions & 0 deletions select/_outlined-select.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
//
// Copyright 2023 Google LLC
// SPDX-License-Identifier: Apache-2.0
//

@forward './lib/outlined-select' show theme;
50 changes: 50 additions & 0 deletions select/filled-select.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/**
* @license
* Copyright 2023 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/

import {customElement} from 'lit/decorators.js';

import {styles as filledForcedColorsStyles} from './lib/filled-forced-colors-styles.css.js';
import {FilledSelect} from './lib/filled-select.js';
import {styles} from './lib/filled-select-styles.css.js';
import {styles as sharedStyles} from './lib/shared-styles.css.js';

declare global {
interface HTMLElementTagNameMap {
'md-filled-select': MdFilledSelect;
}
}

/**
* @summary
* Select menus display a list of choices on temporary surfaces and display the
* currently selected menu item above the menu.
*
* @description
* The select component allows users to choose a value from a fixed list of
* available options. Composed of an interactive anchor button and a menu, it is
* analogous to the native HTML `<select>` element. This is the "filled"
* variant.
*
* @example
* ```html
* <md-filled-select label="fruits">
* <!-- An empty selected option will give select an "un-filled" state -->
* <md-select-option selected></md-select-option>
* <md-select-option value="apple" headline="Apple"></md-select-option>
* <md-select-option value="banana" headline="Banana"></md-select-option>
* <md-select-option value="kiwi" headline="Kiwi"></md-select-option>
* <md-select-option value="orange" headline="Orange"></md-select-option>
* <md-select-option value="tomato" headline="Tomato"></md-select-option>
* </md-filled-select>
* ```
*
* @final
* @suppress {visibility}
*/
@customElement('md-filled-select')
export class MdFilledSelect extends FilledSelect {
static override styles = [sharedStyles, styles, filledForcedColorsStyles];
}
63 changes: 63 additions & 0 deletions select/harness.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/**
* @license
* Copyright 2023 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/

import {FieldHarness} from '../field/harness.js';
import {Field} from '../field/lib/field.js';
import {Harness} from '../testing/harness.js';

import {Select} from './lib/select.js';
import {SelectOptionHarness} from './lib/selectoption/harness.js';

/**
* Test harness for menu.
*/
export class SelectHarness extends Harness<Select> {
protected getField() {
return this.element.renderRoot.querySelector('.field') as Field;
}
/**
* Shows the menu and returns the first list item element.
*/
protected override async getInteractiveElement() {
await this.element.updateComplete;
return this.getField();
}

override async startHover() {
const field = await this.getField();
const element = await (new SelectFieldHardness(field)).getInteractiveElement();
this.simulateStartHover(element);
}

/** @return ListItem harnesses for the menu's items. */
getItems() {
return this.element.options.map((item) => new SelectOptionHarness(item));
}

async click(quick = true) {
this.element.quick = quick;
await this.element.updateComplete;
const field = await this.getField();
field.click();
}

async clickOption(index: number) {
const menu = this.element.renderRoot.querySelector('md-menu')!;
if (!menu.open) {
console.warn(
'Internal menu is not open. Try calling SelectHarness.prototype.click()');
}
this.getItems()[index].element.click();
}
}

// Private class (not exported)
class SelectFieldHardness extends FieldHarness {
/* Expose so that we can call it from our internal code in SelectHarness. */
override getInteractiveElement() {
return super.getInteractiveElement();
}
}
163 changes: 163 additions & 0 deletions select/lib/_filled-select.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
//
// Copyright 2023 Google LLC
// SPDX-License-Identifier: Apache-2.0
//

// go/keep-sorted start
@use 'sass:list';
@use 'sass:map';
@use 'sass:string';
// go/keep-sorted end
// go/keep-sorted start
@use '../../field/filled-field';
@use '../../sass/shape';
@use '../../sass/theme';
@use '../../tokens';
// go/keep-sorted end

@mixin theme($tokens) {
$tokens: theme.validate-theme(tokens.md-comp-filled-select-values(), $tokens);

@each $token, $value in $tokens {
--md-filled-select-#{$token}: #{$value};
}
}

@mixin styles() {
$tokens: tokens.md-comp-filled-select-values();

:host {
@each $token, $value in $tokens {
--_#{$token}: #{$value};
}

@include filled-field.theme(
(
// go/keep-sorted start
'active-indicator-color': var(--_text-field-active-indicator-color),
'active-indicator-height': var(--_text-field-active-indicator-height),
'container-color': var(--_text-field-container-color),
'container-shape':
shape.corners-to-shape-token('--_text-field-container-shape'),
'content-color': var(--_text-field-input-text-color),
'content-type': var(--_text-field-input-text-type),
'disabled-active-indicator-color':
var(--_text-field-disabled-active-indicator-color),
'disabled-active-indicator-height':
var(--_text-field-disabled-active-indicator-height),
'disabled-active-indicator-opacity':
var(--_text-field-disabled-active-indicator-opacity),
'disabled-container-color': var(--_text-field-disabled-container-color),
'disabled-container-opacity':
var(--_text-field-disabled-container-opacity),
'disabled-content-color': var(--_text-field-disabled-input-text-color),
'disabled-content-opacity':
var(--_text-field-disabled-input-text-opacity),
'disabled-label-text-color':
var(--_text-field-disabled-label-text-color),
'disabled-label-text-opacity':
var(--_text-field-disabled-label-text-opacity),
'disabled-leading-content-color':
var(--_text-field-disabled-leading-icon-color),
'disabled-leading-content-opacity':
var(--_text-field-disabled-leading-icon-opacity),
'disabled-supporting-text-color':
var(--_text-field-disabled-supporting-text-color),
'disabled-supporting-text-opacity':
var(--_text-field-disabled-supporting-text-opacity),
'disabled-trailing-content-color':
var(--_text-field-disabled-trailing-icon-color),
'disabled-trailing-content-opacity':
var(--_text-field-disabled-trailing-icon-opacity),
'error-active-indicator-color':
var(--_text-field-error-active-indicator-color),
'error-content-color': var(--_text-field-error-input-text-color),
'error-focus-active-indicator-color':
var(--_text-field-error-focus-active-indicator-color),
'error-focus-content-color':
var(--_text-field-error-focus-input-text-color),
'error-focus-label-text-color':
var(--_text-field-error-focus-label-text-color),
'error-focus-leading-content-color':
var(--_text-field-error-focus-leading-icon-color),
'error-focus-supporting-text-color':
var(--_text-field-error-focus-supporting-text-color),
'error-focus-trailing-content-color':
var(--_text-field-error-focus-trailing-icon-color),
'error-hover-active-indicator-color':
var(--_text-field-error-hover-active-indicator-color),
'error-hover-content-color':
var(--_text-field-error-hover-input-text-color),
'error-hover-label-text-color':
var(--_text-field-error-hover-label-text-color),
'error-hover-leading-content-color':
var(--_text-field-error-hover-leading-icon-color),
'error-hover-state-layer-color':
var(--_text-field-error-hover-state-layer-color),
'error-hover-state-layer-opacity':
var(--_text-field-error-hover-state-layer-opacity),
'error-hover-supporting-text-color':
var(--_text-field-error-hover-supporting-text-color),
'error-hover-trailing-content-color':
var(--_text-field-error-hover-trailing-icon-color),
'error-label-text-color': var(--_text-field-error-label-text-color),
'error-leading-content-color':
var(--_text-field-error-leading-icon-color),
'error-supporting-text-color':
var(--_text-field-error-supporting-text-color),
'error-trailing-content-color':
var(--_text-field-error-trailing-icon-color),
'focus-active-indicator-color':
var(--_text-field-focus-active-indicator-color),
'focus-active-indicator-height':
var(--_text-field-focus-active-indicator-height),
'focus-content-color': var(--_text-field-focus-input-text-color),
'focus-label-text-color': var(--_text-field-focus-label-text-color),
'focus-leading-content-color':
var(--_text-field-focus-leading-icon-color),
'focus-supporting-text-color':
var(--_text-field-focus-supporting-text-color),
'focus-trailing-content-color':
var(--_text-field-focus-trailing-icon-color),
'hover-active-indicator-color':
var(--_text-field-hover-active-indicator-color),
'hover-active-indicator-height':
var(--_text-field-hover-active-indicator-height),
'hover-content-color': var(--_text-field-hover-input-text-color),
'hover-label-text-color': var(--_text-field-hover-label-text-color),
'hover-leading-content-color':
var(--_text-field-hover-leading-icon-color),
'hover-state-layer-color': var(--_text-field-hover-state-layer-color),
'hover-state-layer-opacity':
var(--_text-field-hover-state-layer-opacity),
'hover-supporting-text-color':
var(--_text-field-hover-supporting-text-color),
'hover-trailing-content-color':
var(--_text-field-hover-trailing-icon-color),
'label-text-color': var(--_text-field-label-text-color),
'label-text-populated-line-height':
var(--_text-field-label-text-populated-line-height),
'label-text-populated-size':
var(--_text-field-label-text-populated-size),
'label-text-type': var(--_text-field-label-text-type),
'leading-content-color': var(--_text-field-leading-icon-color),
'supporting-text-color': var(--_text-field-supporting-text-color),
'supporting-text-type': var(--_text-field-supporting-text-type),
'trailing-content-color': var(--_text-field-trailing-icon-color),
// go/keep-sorted end
)
);
}

[hasstart] .icon.leading {
font-size: var(--_text-field-leading-icon-size);
height: var(--_text-field-leading-icon-size);
width: var(--_text-field-leading-icon-size);
}

[hasend] .icon.trailing {
font-size: var(--_text-field-trailing-icon-size);
height: var(--_text-field-trailing-icon-size);
width: var(--_text-field-trailing-icon-size);
}
}
Loading

0 comments on commit 9c202f5

Please sign in to comment.