@limetech/mdc-p2-select
v4.0.0
Published
The Material Components web select (text field drop-down) component
Downloads
7
Readme
Select Menus
MDC Select provides Material Design single-option select menus, using the MDC menu. The Select component is fully accessible, and supports RTL rendering.
Design & API Documentation
Installation
npm install @limetech/mdc-p2-select
Basic Usage
The select uses an MDCMenu
component instance to contain the list of options, but uses the
data-value
attribute instead of value
to represent the options' values.
NOTE: The
data-value
attribute must be present on each option.
The select requires that you set the width
of the mdc-select__anchor
element as well as setting the width of the mdc-select__menu
element to match. This is best done through the use of another class (e.g. demo-width-class
in the example HTML and CSS below).
HTML
<div class="mdc-select">
<div class="mdc-select__anchor demo-width-class">
<i class="mdc-select__dropdown-icon"></i>
<div class="mdc-select__selected-text"></div>
<span class="mdc-floating-label">Pick a Food Group</span>
<div class="mdc-line-ripple"></div>
</div>
<div class="mdc-select__menu mdc-menu mdc-menu-surface demo-width-class">
<ul class="mdc-list">
<li class="mdc-list-item mdc-list-item--selected" data-value="" aria-selected="true"></li>
<li class="mdc-list-item" data-value="grains">
Bread, Cereal, Rice, and Pasta
</li>
<li class="mdc-list-item" data-value="vegetables">
Vegetables
</li>
<li class="mdc-list-item" data-value="fruit">
Fruit
</li>
</ul>
</div>
</div>
Styles
When using the select, you will also need to load the Menu and List components' styles.
@import "@limetech/mdc-p2-list/mdc-list";
@import "@limetech/mdc-p2-menu-surface/mdc-menu-surface";
@import "@limetech/mdc-p2-menu/mdc-menu";
@import "@limetech/mdc-p2-select/mdc-select";
.demo-width-class {
width: 25rem;
}
JavaScript Instantiation
import {MDCSelect} from '@limetech/mdc-p2-select';
const select = new MDCSelect(document.querySelector('.mdc-select'));
select.listen('MDCSelect:change', () => {
alert(`Selected option at index ${select.selectedIndex} with value "${select.value}"`);
});
See Importing the JS component for more information on how to import JavaScript.
Accessibility (a11y)
In order to have an accessible component for users, it's recommended that you follow the WAI-ARIA example for Collapsible Dropdown Listbox. The following is an example of the select component with all of the necessary aria attributes.
<div class="mdc-select">
<div class="mdc-select__anchor">
<i class="mdc-select__dropdown-icon"></i>
<div id="demo-selected-text" class="mdc-select__selected-text" role="button" aria-haspopup="listbox" aria-labelledby="demo-label demo-selected-text">Vegetables</div>
<span id="demo-label" class="mdc-floating-label mdc-floating-label--float-above">Pick a Food Group</span>
<div class="mdc-line-ripple"></div>
</div>
<div class="mdc-select__menu mdc-menu mdc-menu-surface" role="listbox">
<ul class="mdc-list">
<li class="mdc-list-item mdc-list-item--selected" data-value="" role="option"></li>
<li class="mdc-list-item" data-value="grains" role="option">
Bread, Cereal, Rice, and Pasta
</li>
<li class="mdc-list-item mdc-list-item--disabled" data-value="vegetables" aria-selected="true" aria-disabled="true" role="option">
Vegetables
</li>
<li class="mdc-list-item" data-value="fruit" role="option">
Fruit
</li>
</ul>
</div>
</div>
Variants
Outlined Select
The Select Outlined variant uses the mdc-notched-outline
in place of the mdc-line-ripple
element and adds the
mdc-select--outlined
modifier class on the root element. All other elements for each type of select remain the
same.
<div class="mdc-select mdc-select--outlined">
<div class="mdc-select__anchor">
<div class="mdc-notched-outline">
<div class="mdc-notched-outline__leading"></div>
<div class="mdc-notched-outline__notch">
<label class="mdc-floating-label">Pick a Food Group</label>
</div>
<div class="mdc-notched-outline__trailing"></div>
</div>
</div>
<!-- Other elements from the select remain. -->
<div class="mdc-select__menu mdc-menu mdc-menu-surface" role="listbox">...</div>
</div>
Additional Information
Select with pre-selected option
To indicate a select component that has a pre-selected value, use the mdc-list-item--selected
class
to set the selected item. The select also needs the text from the selected element copied to the
mdc-select__selected-text
element.
<div class="mdc-select">
<div class="mdc-select__anchor demo-width-class">
<i class="mdc-select__dropdown-icon"></i>
<div class="mdc-select__selected-text">Vegetables</div>
<span class="mdc-floating-label mdc-floating-label--float-above">Pick a Food Group</span>
<div class="mdc-line-ripple"></div>
</div>
<div class="mdc-select__menu demo-width-class mdc-menu mdc-menu-surface">
<ul class="mdc-list">
<li class="mdc-list-item" data-value=""></li>
<li class="mdc-list-item" data-value="grains">
Bread, Cereal, Rice, and Pasta
</li>
<li class="mdc-list-item mdc-list-item--selected" data-value="vegetables" aria-selected="true">
Vegetables
</li>
<li class="mdc-list-item" data-value="fruit">
Fruit
</li>
</ul>
</div>
</div>
Using the floating label as the placeholder
Leave the mdc-select__selected-text
element empty and don't specify an element as selected.
If leaving the field empty should be a valid option, include an mdc-list-item
element at the beginning of
the list with an empty data-value
attribute.
<li class="mdc-list-item mdc-list-item--selected" aria-selected="true" role="option" data-value=""></li>
Required select
To style a select menu as required and enable validation, add the mdc-select--required
class to the mdc-select
element
and set the aria-required
attribute on the mdc-select__selected-text
element to be "true"
.
<div class="mdc-select mdc-select--required">
<div class="mdc-select__anchor">
<i class="mdc-select__dropdown-icon"></i>
<div class="mdc-select__selected-text" aria-required="true"></div>
<span class="mdc-floating-label">Pick a Food Group</span>
<div class="mdc-line-ripple"></div>
</div>
<div class="mdc-select__menu mdc-menu mdc-menu-surface">
...
</div>
</div>
NOTE: To programmatically set a select as required, use the
required
property in theMDCSelect
API.
Disabled select
Add the mdc-select--disabled
class to the mdc-select
element and and set the
aria-disabled
attribute on the mdc-select__selected-text
element to be "true"
.
<div class="mdc-select mdc-select--disabled">
<div class="mdc-select__anchor">
<i class="mdc-select__dropdown-icon"></i>
<div class="mdc-select__selected-text" aria-disabled="true"></div>
<span class="mdc-floating-label">Pick a Food Group</span>
<div class="mdc-line-ripple"></div>
</div>
<div class="mdc-select__menu mdc-menu mdc-menu-surface">
...
</div>
</div>
NOTE: To programmatically set a select as disabled, use the
disabled
property in theMDCSelect
API.
Disabled options
Add the mdc-list-item--disabled
class to list items that are disabled.
Disabled list items are removed from the list items index and are ignored entirely. You cannot
programmatically select a disabled list item.
<div class="mdc-select">
<div class="mdc-select__anchor">
...
</div>
<div class="mdc-select__menu mdc-menu mdc-menu-surface">
<ul class="mdc-list">
<li class="mdc-list-item" data-value=""></li>
<li class="mdc-list-item" data-value="grains">
Bread, Cereal, Rice, and Pasta
</li>
<li class="mdc-list-item mdc-list-item--selected mdc-list-item--disabled" data-value="vegetables">
Vegetables
</li>
<li class="mdc-list-item" data-value="fruit">
Fruit
</li>
</ul>
</div>
</div>
Select with Helper Text
The helper text provides supplemental information and/or validation messages to users. It appears when the select element is focused and disappears on blur by default, or it can be persistent. See here for more information on using helper text.
Select with Leading Icons
Leading icons can be added within the default or outlined variant of MDC Select as visual indicators as well as interaction targets. See here for more information on using icons.
Select with No Label
A label is not required if a separate, adjacent label is provided elsewhere. To correctly style
MDC Select without a label, add the class mdc-select--no-label
and remove the label from the
structure.
Filled
<div class="mdc-select mdc-select--no-label">
<div class="mdc-select__anchor demo-width-class">
<i class="mdc-select__dropdown-icon"></i>
<div class="mdc-select__selected-text"></div>
<div class="mdc-line-ripple"></div>
</div>
<div class="mdc-select__menu mdc-menu mdc-menu-surface demo-width-class">
<ul class="mdc-list">
<li class="mdc-list-item mdc-list-item--selected" data-value="" aria-selected="true"></li>
<li class="mdc-list-item" data-value="grains">
Bread, Cereal, Rice, and Pasta
</li>
<li class="mdc-list-item" data-value="vegetables">
Vegetables
</li>
<li class="mdc-list-item" data-value="fruit">
Fruit
</li>
</ul>
</div>
</div>
Outlined
<div class="mdc-select mdc-select--outlined mdc-select--no-label">
<div class="mdc-select__anchor demo-width-class">
<i class="mdc-select__dropdown-icon"></i>
<div class="mdc-select__selected-text"></div>
<div class="mdc-notched-outline">
<div class="mdc-notched-outline__leading"></div>
<div class="mdc-notched-outline__trailing"></div>
</div>
</div>
<!-- Other elements from the select remain. -->
<div class="mdc-select__menu mdc-menu mdc-menu-surface demo-width-class">...</div>
</div>
Style Customization
CSS Classes
| Class | Description |
| --- | --- |
| mdc-select
| Mandatory. |
| mdc-select__anchor
| Mandatory. This element should be placed within the mdc-select
element. |
| mdc-select__menu
| Mandatory. This class should be placed on the mdc-menu
element within the mdc-select
element. |
| mdc-select__dropdown-icon
| Mandatory. Should be placed on an i
element within the mdc-select__anchor
element. Used for the dropdown arrow svg and animation.
| mdc-select__selected-text
| Mandatory. This class should be placed on a div
within the mdc-select__anchor
element. |
| mdc-select__icon
| Optional. Should be placed on an i
or svg
element within the mdc-select__anchor
element. Used for the leading icon.
| mdc-select--activated
| Optional. Styles the activated state of select. This class will be added automatically when menu is opened.
| mdc-select--disabled
| Optional. Styles the select as disabled. This class should be applied to the root element when the disabled
attribute is applied to the <select>
element. |
| mdc-select--outlined
| Optional. Styles the select as outlined select. |
| mdc-select--with-leading-icon
| Styles the select as a select with a leading icon. |
| mdc-select--no-label
| Styles the select as a select without a label. |
NOTE: To further customize the MDCMenu or the MDCList component contained within the select, please refer to their respective documentation.
Sass Mixins
Mixins should be included in the context of a custom class applied to the component's root element, e.g. .my-select
.
Mixin | Description
--- | ---
mdc-select-ink-color($color)
| Customizes the color of the selected item displayed in the select.
mdc-select-container-fill-color($color)
| Customizes the background color of the select.
mdc-select-label-color($color)
| Customizes the label color of the select in the unfocused state.
mdc-select-focused-label-color($color)
| Customizes the label color of the select when focused.
mdc-select-bottom-line-color($color)
| Customizes the color of the default bottom line of the select.
mdc-select-focused-bottom-line-color($color)
| Customizes the color of the bottom line of the select when focused.
mdc-select-shape-radius($radius, $rtl-reflexive)
| Sets rounded shape to boxed select variant with given radius size. Set $rtl-reflexive
to true to flip radius values in RTL context, defaults to false.
mdc-select-hover-bottom-line-color($color)
| Customizes the color of the bottom line when the select is hovered.
mdc-select-outline-color($color)
| Customizes the color of the notched outline.
mdc-select-outline-shape-radius($radius, $rtl-reflexive)
| Sets the border radius of of the outlined select variant. Set $rtl-reflexive
to true to flip radius values in RTL context, defaults to false.
mdc-select-focused-outline-color($color)
| Customizes the color of the outline of the select when focused.
mdc-select-hover-outline-color($color)
| Customizes the color of the outline when the select is hovered.
NOTE: To further customize the floating label, please see the floating label documentation.
MDCSelect
API
The MDCSelect
component API is modeled after a subset of the HTMLSelectElement
functionality.
Property | Type | Description
--- | --- | ---
value
| string
| The value
/data-value
of the currently selected option.
selectedIndex
| number
| The index of the currently selected option. Set to -1 if no option is currently selected. Changing this property will update the select element.
disabled
| boolean
| Whether or not the component is disabled. Setting this sets the disabled state on the component.
valid
| boolean
| Whether or not the component is in a valid state. Setting this updates styles on the component, but does not affect the native validity state.
required
| boolean
| Whether or not the component is required. Setting this updates the required
or aria-required
attribute on the component and enables validation.
leadingIconAriaLabel
| string
(write-only) | Proxies to the foundation's setLeadingIconAriaLabel
method.
leadingIconContent
| string
(write-only) | Proxies to the foundation's setLeadingIconContent
method.
helperTextContent
| string
(write-only)| Proxies to the foundation's setHelperTextContent
method when set.
ripple
| MDCRipple
| Ripple instance attached to outlined select variant, or null
for all other variants.
Events
Event Name | Data | Description
--- | --- | ---
MDCSelect:change
| {value: string, index: number}
| Used to indicate when an element has been selected. This event also includes the value of the item and the index.
Usage within Web Frameworks
If you are using a JavaScript framework, such as React or Angular, you can create a Select for your framework. Depending on your needs, you can use the Simple Approach: Wrapping MDC Web Vanilla Components, or the Advanced Approach: Using Foundations and Adapters. Please follow the instructions here.
MDCSelectAdapter
| Method Signature | Description |
| --- | --- |
| addClass(className: string) => void
| Adds a class to the select element. |
| removeClass(className: string) => void
| Removes a class from the select element. |
| hasClass(className: string) => boolean
| Returns true if the select element has the className in its classList. |
| activateBottomLine() => void
| Activates the bottom line component. |
| deactivateBottomLine() => void
| Deactivates the bottom line component. |
| getSelectedMenuItem() => Element
| Returns the selected menu item element. |
| hasLabel() => boolean
| Returns true if the select contains a label. |
| floatLabel(value: boolean) => void
| Floats or defloats label. |
| getLabelWidth() => number
| Returns the offsetWidth of the label element. |
| hasOutline() => boolean
| Returns true if the select
has the notched outline element. |
| notchOutline(labelWidth: number) => void
| Switches the notched outline element to its "notched state." |
| closeOutline() => void
| Switches the notched outline element to its closed state. |
| setDisabled(isDisabled: boolean) => void
| Enables or disables the select. |
| setRippleCenter(normalizedX: number) => void
| Sets the line ripple center to the provided normalizedX value. |
| notifyChange(value: string) => void
| Emits the MDCSelect:change
event when an element is selected. |
| setSelectedText(text: string) => void
| Sets the text content of the selectedText element to the given string. |
| isSelectedTextFocused() => boolean
| Returns whether the selected text element is focused. |
| getSelectedTextAttr(attr: string) => string
| Gets the given attribute on the selected text element. |
| setSelectedTextAttr(attr: string, value: string) => void
| Sets the given attribute on the selected text element. |
| openMenu() => void
| Causes the menu element in the select to open. |
| closeMenu() => void
| Causes the menu element in the select to close. |
| getAnchorElement() => Element
| Returns the select anchor element. |
| setMenuAnchorElement(anchorEl: Element) => void
| Sets the menu anchor element. |
| setMenuAnchorCorner(anchorCorner: Corner) => void
| Sets the menu anchor corner. |
| setMenuWrapFocus(wrapFocus: boolean) => void
| Sets whether the menu should wrap focus. |
| setAttributeAtIndex(index: number, attributeName: string, attributeValue: string) => void
| Sets the attribute on the menu item at the given index. |
| removeAttributeAtIndex(index: number, attributeName: string) => void
| Removes the attribute on the menu item at the given index. |
| focusMenuItemAtIndex(index: number) => void
| Focuses the menu item at the given index. |
| getMenuItemValues() => string[]
| Returns an array representing the VALUE_ATTR attributes of each menu item. |
| getMenuItemCount() => number
| Returns the number of menu items. |
| getMenuItemAttr(menuItem: Element, attr: string) => string
| Returns the given attribute on the the menu item element. |
| getMenuItemTextAtIndex(index: number) => string
| Gets the text content of the menu item element at the given index. |
| addClassAtIndex(menuItem: Element, className: string) => void
| Adds the class name on the menu item at the given index. |
| removeClassAtIndex(menuItem: Element, className: string) => void
| Removes the class name on the menu item at the given index. |
MDCSelectFoundation
| Method Signature | Description |
| --- | --- |
| notchOutline(openNotch: boolean) => void
| Opens/closes the notched outline. |
| getDisabled() => boolean
| Gets the disabled state. |
| setDisabled(isDisabled: boolean) => void
| Updates the disabled state. |
| handleFocus() => void
| Handles a focus event on the select
element. |
| handleBlur() => void
| Handles a blur event on the select
element. |
| handleClick(normalizedX: number) => void
| Sets the line ripple center to the normalizedX for the line ripple. |
| handleMenuOpened() => void
| Handles menu or menu surface opened event.
| handleMenuClosed() => void
| Handles menu or menu surface closed event.
| handleMenuItemAction() => void
| Handles menu selected event.
| handleChange() => void
| Handles a change to the select
element's value. This must be called both for change
events and programmatic changes requested via the component API. |
| handleKeydown(event: KeyboardEvent) => void
| Handles opening the menu when the mdc-select__selected-text
element is focused and the user presses the Enter
or Space
key. |
| getSelectedIndex() => number
| Returns the index of the currently selected menu item. |
| setSelectedIndex(index: number) => void
| Handles setting the mdc-select__selected-text
element and closing the menu. Also causes the label to float and outline to notch if needed. |
| getValue() => string
| Handles getting the value through the adapter. |
| setValue() => string
| Sets the selected index to the index of the menu item with the given value. |
| setValid(isValid: boolean) => void
| Sets the valid state through the adapter. |
| isValid() => boolean
| Gets the valid state through the adapter's checkValidity
API. |
| setRequired(isRequired: boolean) => void
| Sets the required state through the adapter. |
| getRequired() => boolean
| Gets the required state through the adapter. |
| init() => void
| Initializes the foundation. |
| layout() => void
| Handles determining if the notched outline should be notched. |
| setLeadingIconAriaLabel(label: string) => void
| Sets the aria label of the leading icon. |
| setLeadingIconContent(content: string) => void
| Sets the text content of the leading icon. |
| setHelperTextContent(content: string) => void
| Sets the content of the helper text. |
MDCSelectFoundation
supports multiple optional sub-elements: helper text and icon. The foundations of these sub-elements must be passed in as constructor arguments to MDCSelectFoundation
.