diff --git a/CHANGELOG.md b/CHANGELOG.md index 3fa2cd3d1..0f85e510e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ ## 2.0.0-beta.16 +- Add `sl-format-bytes` utility component +- Add `clearable` and `required` props to `sl-select` +- Add `slClear` event to `sl-input` - Fix incorrect `aria-selected` state in `sl-menu-item` ## 2.0.0-beta.15 diff --git a/docs/components/select.md b/docs/components/select.md index acc59729a..85c7907fd 100644 --- a/docs/components/select.md +++ b/docs/components/select.md @@ -5,7 +5,7 @@ Selects allow you to choose one or more items from a dropdown menu. ```html preview - + Option 1 Option 2 Option 3 @@ -20,38 +20,60 @@ Selects allow you to choose one or more items from a dropdown menu. ## Examples -### Labels +### Placeholders -Use the `label` attribute to give the select an accessible label. +Use the `placeholder` attribute to add a placeholder. ```html preview - + Option 1 Option 2 Option 3 ``` -### Help Text +### Clearable -Add descriptive help text to an input with the `help-text` slot. +Use the `clearable` attribute to make the control clearable. ```html preview - - Novice - Intermediate - Advanced + + Option 1 + Option 2 + Option 3 + +``` -
Please tell us your skill level.
+### Pill + +Use the `pill` prop to give selects rounded edges. + +```html preview + + Option 1 + Option 2 + Option 3 + +``` + +### Disabled + +Use the `disabled` prop to disable a select. + +```html preview + + Option 1 + Option 2 + Option 3 ``` ### Multiple -To allow multiple options to be selected, use the `multiple` attribute. +To allow multiple options to be selected, use the `multiple` attribute. It's a good practice to use `clearable` when this option is enabled. ```html preview - + Option 1 Option 2 Option 3 @@ -62,7 +84,25 @@ To allow multiple options to be selected, use the `multiple` attribute. ``` -### Size +### Grouping Options + +Options can be grouped visually using menu labels and menu dividers. + +```html preview + + Group 1 + Option 1 + Option 2 + Option 3 + + Group 2 + Option 4 + Option 5 + Option 6 + +``` + +### Sizes Use the `size` attribute to change a select's size. @@ -90,45 +130,29 @@ Use the `size` attribute to change a select's size. ``` -### Pill +### Labels -Use the `pill` prop to give selects rounded edges. +Use the `label` attribute to give the select an accessible label. ```html preview - + Option 1 Option 2 Option 3 ``` -### Groups +### Help Text -Options can be grouped visually using menu labels and menu dividers. +Add descriptive help text to an input with the `help-text` slot. ```html preview - - Group 1 - Option 1 - Option 2 - Option 3 - - Group 2 - Option 4 - Option 5 - Option 6 - -``` + + Novice + Intermediate + Advanced -### Disabled - -Use the `disabled` prop to disable a select. - -```html preview - - Option 1 - Option 2 - Option 3 +
Please tell us your skill level.
``` diff --git a/src/components.d.ts b/src/components.d.ts index a0e1636b2..915ea861a 100644 --- a/src/components.d.ts +++ b/src/components.d.ts @@ -734,6 +734,10 @@ export namespace Components { "value": number; } interface SlSelect { + /** + * Set to true to add a clear button when the select is populated. + */ + "clearable": boolean; /** * Set to true to disable the select control. */ @@ -1868,6 +1872,10 @@ declare namespace LocalJSX { * Emitted when the control's value changes. */ "onSlChange"?: (event: CustomEvent) => void; + /** + * Emitted when the clear button is activated. + */ + "onSlClear"?: (event: CustomEvent) => void; /** * Emitted when the control gains focus. */ @@ -2092,6 +2100,10 @@ declare namespace LocalJSX { "value"?: number; } interface SlSelect { + /** + * Set to true to add a clear button when the select is populated. + */ + "clearable"?: boolean; /** * Set to true to disable the select control. */ diff --git a/src/components/select/select.scss b/src/components/select/select.scss index 40246c48f..6cba6aa62 100644 --- a/src/components/select/select.scss +++ b/src/components/select/select.scss @@ -37,3 +37,9 @@ .select--open .select__icon sl-icon { transform: rotate(-180deg); } + +// Force the input's clear button to show when the select isn't empty. This is important for the `multiple` option, as +// it doesn't use the input's `value` prop to display the selection. +.select:not(.select--empty) .select__input::part(clear-button) { + visibility: visible; +} diff --git a/src/components/select/select.tsx b/src/components/select/select.tsx index e77591d55..131d6ea04 100644 --- a/src/components/select/select.tsx +++ b/src/components/select/select.tsx @@ -77,6 +77,9 @@ export class Select { /** The select's required attribute. */ @Prop() required: boolean; + /** Set to true to add a clear button when the select is populated. */ + @Prop() clearable = false; + /** Set to true to indicate that the user input is valid. */ @Prop() valid = false; @@ -109,6 +112,7 @@ export class Select { connectedCallback() { this.handleBlur = this.handleBlur.bind(this); this.handleFocus = this.handleFocus.bind(this); + this.handleClear = this.handleClear.bind(this); this.handleKeyDown = this.handleKeyDown.bind(this); this.handleLabelClick = this.handleLabelClick.bind(this); this.handleMenuKeyDown = this.handleMenuKeyDown.bind(this); @@ -156,6 +160,12 @@ export class Select { this.input.setSelectionRange(0, 0); } + handleClear() { + this.value = this.multiple ? [] : ''; + this.syncItemsFromValue(); + this.dropdown.hide(); + } + handleKeyDown(event: KeyboardEvent) { const target = event.target as HTMLElement; @@ -251,7 +261,8 @@ export class Select { pill={this.pill} clearable onClick={event => event.stopPropagation()} - onSlClear={() => { + onSlClear={event => { + event.stopPropagation(); item.checked = false; this.syncValueFromItems(); }} @@ -327,6 +338,7 @@ export class Select { class={{ select: true, 'select--open': this.isOpen, + 'select--empty': this.value.length === 0, 'select--focused': this.hasFocus, 'select--disabled': this.disabled, 'select--multiple': this.multiple, @@ -353,11 +365,13 @@ export class Select { size={this.size} valid={this.valid} invalid={this.invalid} + clearable={this.clearable} required={this.required} aria-labelledby={this.labelId} aria-describedby={this.helpTextId} onSlFocus={this.handleFocus} onSlBlur={this.handleBlur} + onSlClear={this.handleClear} onKeyDown={this.handleKeyDown} > {this.displayTags.length && (