mirror of
https://github.com/shoelace-style/webawesome.git
synced 2026-01-12 12:09:26 +00:00
Add label to select and fix label bug
This commit is contained in:
@@ -8,9 +8,9 @@ All of Shoelace's components make use of the [shadow DOM](https://developer.mozi
|
||||
|
||||
```html preview
|
||||
<sl-form class="form-overview">
|
||||
<sl-input name="name" type="text" placeholder="Name"></sl-input>
|
||||
<sl-input name="name" type="text" label="Name"></sl-input>
|
||||
<br>
|
||||
<sl-select name="options" placeholder="Select your favorite">
|
||||
<sl-select name="options" label="Select your favorite">
|
||||
<sl-menu-item value="birds">Birds</sl-menu-item>
|
||||
<sl-menu-item value="cats">Cats</sl-menu-item>
|
||||
<sl-menu-item value="dogs">Dogs</sl-menu-item>
|
||||
|
||||
@@ -22,6 +22,16 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor i
|
||||
|
||||
## Examples
|
||||
|
||||
### Labels
|
||||
|
||||
```html preview
|
||||
<sl-select label="Select one">
|
||||
<sl-menu-item value="option-1">Option 1</sl-menu-item>
|
||||
<sl-menu-item value="option-2">Option 2</sl-menu-item>
|
||||
<sl-menu-item value="option-3">Option 3</sl-menu-item>
|
||||
</sl-select>
|
||||
```
|
||||
|
||||
### Multiple
|
||||
|
||||
```html preview
|
||||
|
||||
8
src/components.d.ts
vendored
8
src/components.d.ts
vendored
@@ -568,6 +568,10 @@ export namespace Components {
|
||||
* Set to true to disable the select control.
|
||||
*/
|
||||
"disabled": boolean;
|
||||
/**
|
||||
* The select's label.
|
||||
*/
|
||||
"label": string;
|
||||
/**
|
||||
* The maximum number of tags to show when `multiple` is true. After the maximum, "+n" will be shown to indicate the number of additional items that are selected. Set to -1 to remove the limit.
|
||||
*/
|
||||
@@ -1670,6 +1674,10 @@ declare namespace LocalJSX {
|
||||
* Set to true to disable the select control.
|
||||
*/
|
||||
"disabled"?: boolean;
|
||||
/**
|
||||
* The select's label.
|
||||
*/
|
||||
"label"?: string;
|
||||
/**
|
||||
* The maximum number of tags to show when `multiple` is true. After the maximum, "+n" will be shown to indicate the number of additional items that are selected. Set to -1 to remove the limit.
|
||||
*/
|
||||
|
||||
@@ -6,9 +6,6 @@
|
||||
}
|
||||
|
||||
.form-control {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.label {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,31 @@
|
||||
display: block;
|
||||
}
|
||||
|
||||
.form-control {
|
||||
.label {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.form-control--has-label {
|
||||
.label {
|
||||
display: inline-block;
|
||||
margin-bottom: var(--sl-spacing-xx-small);
|
||||
|
||||
&.label--small {
|
||||
font-size: var(--sl-input-font-size-small);
|
||||
}
|
||||
|
||||
&.label--medium {
|
||||
font-size: var(--sl-input-font-size-medium);
|
||||
}
|
||||
|
||||
&.label--large {
|
||||
font-size: var(--sl-input-font-size-large);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.select {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ import { Component, Element, Event, EventEmitter, Prop, State, Watch, h } from '
|
||||
import ResizeObserver from 'resize-observer-polyfill';
|
||||
import { getTextContent } from '../../utilities/slot';
|
||||
|
||||
let id = 0;
|
||||
|
||||
/**
|
||||
* @since 1.0
|
||||
* @status stable
|
||||
@@ -17,6 +19,7 @@ export class Select {
|
||||
this.handleBlur = this.handleBlur.bind(this);
|
||||
this.handleFocus = this.handleFocus.bind(this);
|
||||
this.handleKeyDown = this.handleKeyDown.bind(this);
|
||||
this.handleLabelClick = this.handleLabelClick.bind(this);
|
||||
this.handleMenuKeyDown = this.handleMenuKeyDown.bind(this);
|
||||
this.handleMenuHide = this.handleMenuHide.bind(this);
|
||||
this.handleMenuShow = this.handleMenuShow.bind(this);
|
||||
@@ -26,6 +29,8 @@ export class Select {
|
||||
|
||||
dropdown: HTMLSlDropdownElement;
|
||||
input: HTMLSlInputElement;
|
||||
inputId = `input-${++id}`;
|
||||
labelId = `input-label-${id}`;
|
||||
menu: HTMLSlMenuElement;
|
||||
resizeObserver: any;
|
||||
|
||||
@@ -61,6 +66,9 @@ export class Select {
|
||||
/** The value of the control. This will be a string or an array depending on `multiple`. */
|
||||
@Prop({ mutable: true }) value: string | Array<string> = '';
|
||||
|
||||
/** The select's label. */
|
||||
@Prop() label = '';
|
||||
|
||||
@Watch('multiple')
|
||||
handleMultipleChange() {
|
||||
// Cast to array | string based on `this.multiple`
|
||||
@@ -130,6 +138,10 @@ export class Select {
|
||||
}
|
||||
}
|
||||
|
||||
handleLabelClick() {
|
||||
this.input.setFocus();
|
||||
}
|
||||
|
||||
handleMenuKeyDown(event: KeyboardEvent) {
|
||||
event.stopPropagation();
|
||||
|
||||
@@ -252,55 +264,76 @@ export class Select {
|
||||
|
||||
render() {
|
||||
return (
|
||||
<sl-dropdown
|
||||
ref={el => (this.dropdown = el)}
|
||||
closeOnSelect={!this.multiple}
|
||||
containingElement={this.host}
|
||||
<div
|
||||
class={{
|
||||
select: true,
|
||||
'select--open': this.isOpen,
|
||||
'select--focused': this.hasFocus,
|
||||
'select--disabled': this.disabled,
|
||||
'select--multiple': this.multiple,
|
||||
'select--small': this.size === 'small',
|
||||
'select--medium': this.size === 'medium',
|
||||
'select--large': this.size === 'large'
|
||||
'form-control': true,
|
||||
'form-control--has-label': this.label.length > 0
|
||||
}}
|
||||
onSlShow={this.handleMenuShow}
|
||||
onSlHide={this.handleMenuHide}
|
||||
>
|
||||
<sl-input
|
||||
slot="trigger"
|
||||
ref={el => (this.input = el)}
|
||||
class="select__input"
|
||||
name={this.name}
|
||||
value={this.displayLabel}
|
||||
disabled={this.disabled}
|
||||
placeholder={this.displayLabel === '' && this.displayTags.length === 0 ? this.placeholder : null}
|
||||
readonly={true}
|
||||
size={this.size}
|
||||
onSlFocus={this.handleFocus}
|
||||
onSlBlur={this.handleBlur}
|
||||
onKeyDown={this.handleKeyDown}
|
||||
<label
|
||||
class={{
|
||||
label: true,
|
||||
'label--small': this.size === 'small',
|
||||
'label--medium': this.size === 'medium',
|
||||
'label--large': this.size === 'large'
|
||||
}}
|
||||
htmlFor={this.inputId}
|
||||
onClick={this.handleLabelClick}
|
||||
>
|
||||
{this.displayTags.length && (
|
||||
<span slot="prefix" class="select__tags">
|
||||
{this.displayTags}
|
||||
</span>
|
||||
)}
|
||||
|
||||
<sl-icon slot="suffix" class="select__icon" name="chevron-down" />
|
||||
</sl-input>
|
||||
|
||||
<sl-menu
|
||||
ref={el => (this.menu = el)}
|
||||
class="select__menu"
|
||||
onSlSelect={this.handleMenuSelect}
|
||||
onKeyDown={this.handleMenuKeyDown}
|
||||
<slot name="label">{this.label}</slot>
|
||||
</label>
|
||||
<sl-dropdown
|
||||
ref={el => (this.dropdown = el)}
|
||||
closeOnSelect={!this.multiple}
|
||||
containingElement={this.host}
|
||||
class={{
|
||||
select: true,
|
||||
'select--open': this.isOpen,
|
||||
'select--focused': this.hasFocus,
|
||||
'select--disabled': this.disabled,
|
||||
'select--multiple': this.multiple,
|
||||
'select--small': this.size === 'small',
|
||||
'select--medium': this.size === 'medium',
|
||||
'select--large': this.size === 'large'
|
||||
}}
|
||||
onSlShow={this.handleMenuShow}
|
||||
onSlHide={this.handleMenuHide}
|
||||
>
|
||||
<slot />
|
||||
</sl-menu>
|
||||
</sl-dropdown>
|
||||
<sl-input
|
||||
slot="trigger"
|
||||
ref={el => (this.input = el)}
|
||||
id={this.inputId}
|
||||
class="select__input"
|
||||
name={this.name}
|
||||
value={this.displayLabel}
|
||||
disabled={this.disabled}
|
||||
placeholder={this.displayLabel === '' && this.displayTags.length === 0 ? this.placeholder : null}
|
||||
readonly={true}
|
||||
size={this.size}
|
||||
aria-labelledby={this.labelId}
|
||||
onSlFocus={this.handleFocus}
|
||||
onSlBlur={this.handleBlur}
|
||||
onKeyDown={this.handleKeyDown}
|
||||
>
|
||||
{this.displayTags.length && (
|
||||
<span slot="prefix" class="select__tags">
|
||||
{this.displayTags}
|
||||
</span>
|
||||
)}
|
||||
|
||||
<sl-icon slot="suffix" class="select__icon" name="chevron-down" />
|
||||
</sl-input>
|
||||
|
||||
<sl-menu
|
||||
ref={el => (this.menu = el)}
|
||||
class="select__menu"
|
||||
onSlSelect={this.handleMenuSelect}
|
||||
onKeyDown={this.handleMenuKeyDown}
|
||||
>
|
||||
<slot />
|
||||
</sl-menu>
|
||||
</sl-dropdown>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,9 +6,6 @@
|
||||
}
|
||||
|
||||
.form-control {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.label {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@@ -226,6 +226,7 @@ export class Textarea {
|
||||
autoFocus={this.autofocus}
|
||||
required={this.required}
|
||||
inputMode={this.inputmode}
|
||||
aria-labelledby={this.labelId}
|
||||
onChange={this.handleChange}
|
||||
onInput={this.handleInput}
|
||||
onFocus={this.handleFocus}
|
||||
|
||||
Reference in New Issue
Block a user