Skip to content
This repository has been archived by the owner on Jan 13, 2025. It is now read-only.

feat(select): Add outlined variant #2674

Merged
merged 13 commits into from
Jun 5, 2018
Merged
105 changes: 105 additions & 0 deletions demos/select.html
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ <h2 class="mdc-typography--headline6">Fully-Featured JS Component</h2>
</button>
</div>
</section>

<section class="example">
<h2 class="mdc-typography--headline6">Select box</h2>
<section id="box-demo-wrapper">
Expand Down Expand Up @@ -178,6 +179,67 @@ <h2 class="mdc-typography--headline6">Select box</h2>
</button>
</div>
</section>

<section class="example">
<h2 class="mdc-typography--headline6">Outlined Select</h2>
<section>
<div id="outline-js-select" class="mdc-select mdc-select--outlined">
<select class="mdc-select__native-control" id="outlined-select">
<option value="" disabled selected>
</option>
<option value="grains">
Bread, Cereal, Rice, and Pasta
</option>
<option value="vegetables" disabled>
Vegetables
</option>
<option value="fruit">
Fruit
</option>
<option value="dairy">
Milk, Yogurt, and Cheese
</option>
<option value="meat">
Meat, Poultry, Fish, Dry Beans, Eggs, and Nuts
</option>
<option value="fats">
Fats, Oils, and Sweets
</option>
</select>
<label class="mdc-floating-label" for="outlined-select">Food Group</label>
<div class="mdc-notched-outline">
<svg>
<path class="mdc-notched-outline__path"></path>
</svg>
</div>
<div class="mdc-notched-outline__idle"></div>
</div>
</section>
<p>Currently selected: <span id="currently-selected-outline">(none)</span></p>
<div>
<input type="checkbox" id="rtl-outline">
<label for="rtl-outline">RTL</label>
</div>
<div>
<input type="checkbox" id="alternate-colors-outline">
<label for="alternate-colors-outline">Alternate Colors</label>
</div>
<div>
<input type="checkbox" id="disabled-outline">
<label for="disabled-outline">Disabled</label>
</div>
<div class="button-container">
<button class="mdc-button mdc-button--raised" id="set-selected-index-zero-button-outline">
Set Selected Index (0)
</button>
</div>
<div class="button-container">
<button class="mdc-button mdc-button--raised" id="set-value-meat-button-outline">
Set Value to Meat
</button>
</div>
</section>

<section class="example">
<h2 class="mdc-typography--headline6">Pre-selected option via HTML</h2>
<section>
Expand Down Expand Up @@ -307,6 +369,49 @@ <h2 class="mdc-typography--headline6">MDC Select with optgroups</h2>
updateSelectedTextContent();
});
});

demoReady(function() {

var root = document.getElementById('outline-js-select');
var currentlySelected = document.getElementById('currently-selected-outline');
var select = new mdc.select.MDCSelect(root);
var demoWrapper = root.parentElement;
var rtlCb = document.getElementById('rtl-outline');
var alternateColorsCb = document.getElementById('alternate-colors-outline');
var disabledCb = document.getElementById('disabled-outline');
var setSelectedButton = document.getElementById('set-selected-index-zero-button-outline');
var setValueMeatButton = document.getElementById('set-value-meat-button-outline');
function updateSelectedTextContent() {
var value = select.value;
var index = select.selectedIndex;
currentlySelected.textContent = value ? value + ' at index ' + index : '(none)';
}
root.addEventListener('change', function() {
updateSelectedTextContent();
});
rtlCb.addEventListener('change', function() {
if (rtlCb.checked) {
demoWrapper.setAttribute('dir', 'rtl');
} else {
demoWrapper.removeAttribute('dir');
}
select.layout();
});
alternateColorsCb.addEventListener('change', function() {
root.classList[alternateColorsCb.checked ? 'add' : 'remove']('demo-select-custom-colors');
});
disabledCb.addEventListener('change', function() {
select.disabled = disabledCb.checked;
});
setSelectedButton.addEventListener('click', function() {
select.selectedIndex = 0;
updateSelectedTextContent();
});
setValueMeatButton.addEventListener('click', function() {
select.value = 'meat';
updateSelectedTextContent();
});
});
</script>
</body>
</html>
6 changes: 6 additions & 0 deletions demos/select.scss
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@
@include mdc-select-container-fill-color(rgba(blue, .1));
}

.demo-select-custom-colors.mdc-select--outlined {
@include mdc-select-outline-color(rgba(blue, .6));
@include mdc-select-hover-outline-color(rgba(blue, .87));
@include mdc-select-focused-outline-color(green);
}

.button-container {
margin: 8px 0;
}
Expand Down
22 changes: 22 additions & 0 deletions packages/mdc-select/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,26 @@ modifier class on the root element.
</div>
```

### 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.

```html
<div class="mdc-select mdc-select--outlined">
<select class="mdc-select__native-control">
...
</select>
<label class="mdc-floating-label">Pick a Food Group</label>
<div class="mdc-notched-outline">
<svg>
<path class="mdc-notched-outline__path"></path>
</svg>
</div>
<div class="mdc-notched-outline__idle"></div>
</div>
```

### Additional Information

#### Select with pre-selected option
Expand Down Expand Up @@ -195,6 +215,7 @@ Mixin | Description
`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-hover-bottom-line-color($color)` | Customizes the color of the bottom line when select is hovered.
`mdc-select-outline-corner-radius($color)` | Customizes the color of the notched outline when select is focused.

> NOTE: To further customize the floating label, please see the [floating label documentation](./../mdc-floating-label/README.md).

Expand Down Expand Up @@ -237,6 +258,7 @@ If you are using a JavaScript framework, such as React or Angular, you can creat

| Method Signature | Description |
| --- | --- |
| `notchOutline(openNotch: boolean) => void` | Opens/closes the notched outline. |
| `setValue(value: string) => void` | Sets the value of the component. |
| `setDisabled(disabled: boolean) => void` | Adds/removes disabled class, and sets disabled attribute on the component. |
| `setSelectedIndex(selectedIndex: number) => void` | Sets the selected index of the component. |
66 changes: 66 additions & 0 deletions packages/mdc-select/_mixins.scss
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
@import "@material/floating-label/mixins";
@import "@material/theme/mixins";
@import "@material/line-ripple/mixins";
@import "@material/notched-outline/mixins";

// Public

Expand Down Expand Up @@ -64,13 +65,38 @@
}
}

@mixin mdc-select-outline-color($color) {
&:not(.mdc-select--disabled) {
@include mdc-select-outline-color_($color);
}
}

@mixin mdc-select-hover-outline-color($color) {
&:not(.mdc-select--disabled) {
@include mdc-select-hover-outline-color_($color);
}
}

@mixin mdc-select-focused-outline-color($color) {
&:not(.mdc-select--disabled) {
@include mdc-select-focused-outline-color_($color);
}
}

// Private
@mixin mdc-select-focused-line-ripple_ {
.mdc-select__native-control:focus ~ .mdc-line-ripple {
@content;
}
}

@mixin mdc-select-focused-outline_ {
.mdc-select__native-control:focus ~ .mdc-notched-outline {
@include mdc-notched-outline-stroke-width(2px);
@content;
}
}

@mixin mdc-select-ink-color_($color) {
.mdc-select__native-control {
@include mdc-theme-prop(color, $color);
Expand Down Expand Up @@ -100,3 +126,43 @@
@mixin mdc-select-dd-arrow-svg-bg_($fill-hex-number: 000000, $opacity: .54) {
background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2210px%22%20height%3D%225px%22%20viewBox%3D%227%2010%2010%205%22%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%3E%0A%20%20%20%20%3Cpolygon%20id%3D%22Shape%22%20stroke%3D%22none%22%20fill%3D%22%23#{$fill-hex-number}%22%20fill-rule%3D%22evenodd%22%20opacity%3D%22#{$opacity}%22%20points%3D%227%2010%2012%2015%2017%2010%22%3E%3C%2Fpolygon%3E%0A%3C%2Fsvg%3E");
}

@mixin mdc-select-outline-corner-radius($radius) {
// NOTE: idle and notched state border radius mixins
// are broken into 2 different mixins, otherwise
// we would be overly specific (big no, no). The cause of
// this is because .mdc-notched-outline and .mdc-notched-outline__idle
// are siblings. .mdc-notched-outline__idle needs to be a child of
// .mdc-notched-outline in order to remedy this issue.
.mdc-notched-outline {
@include mdc-notched-outline-corner-radius($radius);
}

@include mdc-notched-outline-idle-corner-radius($radius);
}

@mixin mdc-select-outline-color_($color) {
// NOTE: outlined version of select wants the "idle" and
// "notched" outline to have the same color. This covers two cases:
// 1) text field renders with NO value in the "idle" state
// 2) text field renders with a value in the "notched" state
@include mdc-notched-outline-idle-color($color);
@include mdc-notched-outline-color($color);
}

@mixin mdc-select-hover-outline-color_($color) {
&:not(.mdc-select__native-control:focus) .mdc-select__native-control:hover ~ {
@include mdc-notched-outline-idle-color($color);

// stylelint-disable-next-line selector-max-specificity
.mdc-notched-outline {
@include mdc-notched-outline-color($color);
}
}
}

@mixin mdc-select-focused-outline-color_($color) {
@include mdc-select-focused-outline_ {
@include mdc-notched-outline-color($color);
}
}
10 changes: 10 additions & 0 deletions packages/mdc-select/_variables.scss
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

$mdc-select-arrow-padding: 26px;
$mdc-select-label-padding: 16px;
$mdc-select-border-radius: 4px;

$mdc-select-ink-color: rgba(mdc-theme-prop-value(on-surface), .87);
$mdc-select-disabled-ink-color: rgba(mdc-theme-prop-value(on-surface), .37);
Expand All @@ -32,3 +33,12 @@ $mdc-select-bottom-line-hover-color: rgba(mdc-theme-prop-value(on-surface), .87)

$mdc-select-box-fill-color: mix(mdc-theme-prop-value(on-surface), mdc-theme-prop-value(surface), 4%);
$mdc-select-box-disabled-fill-color: mix(mdc-theme-prop-value(on-surface), mdc-theme-prop-value(surface), 2%);

$mdc-select-outlined-idle-border: rgba(mdc-theme-prop-value(on-surface), .24);

// should be .06 after mdc-select opacity is applied
$mdc-select-outlined-disabled-border: rgba(mdc-theme-prop-value(on-surface), .16);
$mdc-select-outlined-hover-border: rgba(mdc-theme-prop-value(on-surface), .87);

$mdc-select-outlined-label-position-y: 130%;
$mdc-select-outlined-dense-label-position-y: 110%;
13 changes: 11 additions & 2 deletions packages/mdc-select/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,24 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export const cssClasses = {
const cssClasses = {
BOX: 'mdc-select--box',
DISABLED: 'mdc-select--disabled',
ROOT: 'mdc-select',
OUTLINED: 'mdc-select--outlined',
};

export const strings = {
const strings = {
CHANGE_EVENT: 'MDCSelect:change',
LINE_RIPPLE_SELECTOR: '.mdc-line-ripple',
LABEL_SELECTOR: '.mdc-floating-label',
NATIVE_CONTROL_SELECTOR: '.mdc-select__native-control',
OUTLINE_SELECTOR: '.mdc-notched-outline',
};

/** @enum {number} */
const numbers = {
LABEL_SCALE: 0.75,
};

export {cssClasses, strings, numbers};
34 changes: 33 additions & 1 deletion packages/mdc-select/foundation.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,17 @@
*/

import {MDCFoundation} from '@material/base/index';
import {cssClasses, strings} from './constants';
import {cssClasses, strings, numbers} from './constants';

export default class MDCSelectFoundation extends MDCFoundation {
static get cssClasses() {
return cssClasses;
}

static get numbers() {
return numbers;
}

static get strings() {
return strings;
}
Expand All @@ -30,6 +34,7 @@ export default class MDCSelectFoundation extends MDCFoundation {
return {
addClass: (/* className: string */) => {},
removeClass: (/* className: string */) => {},
hasClass: (/* className: string */) => false,
floatLabel: (/* value: boolean */) => {},
activateBottomLine: () => {},
deactivateBottomLine: () => {},
Expand All @@ -40,6 +45,12 @@ export default class MDCSelectFoundation extends MDCFoundation {
setDisabled: (/* disabled: boolean */) => {},
getValue: () => /* string */ '',
setValue: (/* value: string */) => {},
isRtl: () => false,
hasLabel: () => {},
getLabelWidth: () => {},
hasOutline: () => {},
notchOutline: () => {},
closeOutline: () => {},
};
}

Expand Down Expand Up @@ -86,10 +97,12 @@ export default class MDCSelectFoundation extends MDCFoundation {
floatLabelWithValue_() {
const optionHasValue = this.adapter_.getValue().length > 0;
this.adapter_.floatLabel(optionHasValue);
this.notchOutline(optionHasValue);
}

handleFocus_() {
this.adapter_.floatLabel(true);
this.notchOutline(true);
this.adapter_.activateBottomLine();
}

Expand All @@ -101,4 +114,23 @@ export default class MDCSelectFoundation extends MDCFoundation {
handleSelect_() {
this.setSelectedIndex(this.adapter_.getSelectedIndex());
}

/**
* Opens/closes the notched outline.
* @param {boolean} openNotch
*/
notchOutline(openNotch) {
if (!this.adapter_.hasOutline() || !this.adapter_.hasLabel()) {
return;
}

if (openNotch) {
const labelScale = numbers.LABEL_SCALE;
const labelWidth = this.adapter_.getLabelWidth() * labelScale;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The select doesn't have a dense variant yet.

const isRtl = this.adapter_.isRtl();
this.adapter_.notchOutline(labelWidth, isRtl);
} else {
this.adapter_.closeOutline();
}
}
}
Loading