Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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