Add parts

This commit is contained in:
Cory LaViska
2020-07-13 10:11:36 -04:00
parent 3a021ae191
commit 35a159fd70
36 changed files with 307 additions and 95 deletions

View File

@@ -8,6 +8,11 @@ import { focusVisible } from '../../utilities/focus-visible';
* @slot - The alert's content.
* @slot icon - An icon to show in the alert.
* @slot close-icon - An icon to use in lieu of the default close icon.
*
* @part base - The alert base element.
* @part icon - The container that wraps the alert icon.
* @part message - The alert message.
* @part close-button - The close button.
*/
@Component({
@@ -109,6 +114,7 @@ export class Tab {
<Host hidden>
<div
ref={el => (this.alert = el)}
part="base"
class={{
alert: true,
'alert--open': this.open,
@@ -125,16 +131,16 @@ export class Tab {
aria-hidden={!this.open}
onTransitionEnd={this.handleTransitionEnd}
>
<span class="alert__icon">
<span part="icon" class="alert__icon">
<slot name="icon" />
</span>
<span class="alert__message">
<span part="message" class="alert__message">
<slot />
</span>
{this.closable && (
<button type="button" class="alert__close" onClick={this.handleCloseClick}>
<button part="close-button" class="alert__close" type="button" onClick={this.handleCloseClick}>
<slot name="close-icon">
<sl-icon name="x" />
</slot>

View File

@@ -1,9 +1,9 @@
@import 'component';
/**
* @prop --background-color: The avatar's background color.
* @prop --size: The size of the avatar.
*/
* @prop --background-color: The avatar's background color.
* @prop --size: The size of the avatar.
*/
:host {
display: inline-block;

View File

@@ -5,6 +5,11 @@ import { Component, Prop, State, h } from '@stencil/core';
* @status stable
*
* @slot icon - The default icon to use when no image or initials are present.
*
* @part base - The avatar base element.
* @part icon - The container that wraps the avatar icon.
* @part initials - The container that wraps the avatar initials.
* @part image - The avatar image.
*/
@Component({
@@ -38,26 +43,33 @@ export class Avatar {
render() {
return (
<div
role="image"
aria-label={this.alt}
part="base"
class={{
avatar: true,
'avatar--circle': this.shape === 'circle',
'avatar--rounded': this.shape === 'rounded',
'avatar--square': this.shape === 'square'
}}
role="image"
aria-label={this.alt}
>
{!this.initials && (
<div class="avatar__icon">
<div part="icon" class="avatar__icon">
<slot name="icon">
<sl-icon name="person-fill" />
</slot>
</div>
)}
{this.initials && <div class="avatar__initials">{this.initials}</div>}
{this.initials && (
<div part="initials" class="avatar__initials">
{this.initials}
</div>
)}
{this.image && !this.hasError && <img class="avatar__image" src={this.image} onError={this.handleImageError} />}
{this.image && !this.hasError && (
<img part="image" class="avatar__image" src={this.image} onError={this.handleImageError} />
)}
</div>
);
}

View File

@@ -5,6 +5,8 @@ import { Component, Prop, h } from '@stencil/core';
* @status experimental
*
* @slot - The badge's content.
*
* @part base - The badge base element.
*/
//
@@ -30,6 +32,7 @@ export class Badge {
return (
<span
ref={el => (this.badge = el)}
part="base"
class={{
badge: true,

View File

@@ -7,6 +7,12 @@ import { Component, Event, EventEmitter, Method, Prop, State, h } from '@stencil
* @slot - The button's label.
* @slot prefix - Used to prepend an icon or similar element to the button.
* @slot suffix - Used to append an icon or similar element to the button.
*
* @part base - The base element.
* @part prefix - The prefix container.
* @part label - The button's label.
* @part suffix - The suffix container.
* @part caret - The button's caret.
*/
@Component({
@@ -94,6 +100,7 @@ export class Button {
return (
<button
ref={el => (this.button = el)}
part="base"
class={{
button: true,
@@ -127,17 +134,17 @@ export class Button {
onFocus={this.handleFocus}
onClick={this.handleClick}
>
<span class="button__prefix">
<span part="prefix" class="button__prefix">
<slot name="prefix" />
</span>
<span class="button__label">
<span part="label" class="button__label">
<slot />
</span>
<span class="button__suffix">
<span part="suffix" class="button__suffix">
<slot name="suffix" />
</span>
{this.caret && (
<span class="button__caret">
<span part="caret" class="button__caret">
<svg
viewBox="0 0 24 24"
fill="none"

View File

@@ -7,6 +7,12 @@ let id = 0;
* @status stable
*
* @slot - The checkbox's label.
*
* @part base - The checkbox base element.
* @part control - The checkbox control.
* @part checked-icon - The container the wraps the checked icon.
* @part indeterminate-icon - The container that wraps the indeterminate icon.
* @part label - The checkbox label.
*/
@Component({
@@ -100,8 +106,7 @@ export class Checkbox {
render() {
return (
<label
htmlFor={this.inputId}
role="checkbox"
part="base"
class={{
checkbox: true,
'checkbox--checked': this.checked,
@@ -109,11 +114,13 @@ export class Checkbox {
'checkbox--focused': this.hasFocus,
'checkbox--indeterminate': this.indeterminate
}}
htmlFor={this.inputId}
role="checkbox"
onMouseDown={this.handleMouseDown}
>
<span class="checkbox__control">
<span part="control" class="checkbox__control">
{this.checked && (
<span class="checkbox__icon">
<span part="checked-icon" class="checkbox__icon">
<svg viewBox="0 0 16 16">
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round">
<g stroke="currentColor" stroke-width="2">
@@ -128,7 +135,7 @@ export class Checkbox {
)}
{!this.checked && this.indeterminate && (
<span class="checkbox__icon">
<span part="indeterminate-icon" class="checkbox__icon">
<svg viewBox="0 0 16 16">
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round">
<g stroke="currentColor" stroke-width="2">
@@ -156,7 +163,7 @@ export class Checkbox {
/>
</span>
<span id={this.labelId} class="checkbox__label">
<span part="label" id={this.labelId} class="checkbox__label">
<slot />
</span>
</label>

View File

@@ -1,11 +1,11 @@
@import 'component';
/**
* @prop --hide-duration: The length of the hide transition.
* @prop --hide-timing-function: The timing function (easing) to use for the hide transition.
* @prop --show-duration: The length of the show transition.
* @prop --show-timing-function: The timing function (easing) to use for the show transition.
*/
* @prop --hide-duration: The length of the hide transition.
* @prop --hide-timing-function: The timing function (easing) to use for the hide transition.
* @prop --show-duration: The length of the show transition.
* @prop --show-timing-function: The timing function (easing) to use for the show transition.
*/
:host {
display: block;

View File

@@ -6,6 +6,13 @@ let id = 0;
/**
* @since 1.0
* @status stable
*
* @slot - The details' content.
*
* @part base - The details base container.
* @part summary - The details summary.
* @part summary-icon - The expand/collapse summary icon.
* @part content - The details content.
*/
@Component({
@@ -140,6 +147,7 @@ export class Details {
return (
<div
ref={el => (this.details = el)}
part="base"
class={{
details: true,
'details--open': this.open,
@@ -158,15 +166,23 @@ export class Details {
onClick={this.handleSummaryClick}
onKeyDown={this.handleSummaryKeyDown}
>
<div class="details__summary">{this.summary}</div>
<div part="summary" class="details__summary">
{this.summary}
</div>
<span class="details__summary-icon">
<span part="summary-icon" class="details__summary-icon">
<sl-icon name="chevron-right" />
</span>
</header>
<div ref={el => (this.body = el)} class="details__body" onTransitionEnd={this.handleBodyTransitionEnd}>
<div id={`${this.id}-content`} class="details__content" role="region" aria-labeledby={`${this.id}-header`}>
<div
part="content"
id={`${this.id}-content`}
class="details__content"
role="region"
aria-labeledby={`${this.id}-header`}
>
<slot />
</div>
</div>

View File

@@ -1,8 +1,8 @@
@import 'component';
/**
* @prop --width: The preferred width of the dialog. Note that the dialog will shrink to accommodate smaller screens.
*/
* @prop --width: The preferred width of the dialog. Note that the dialog will shrink to accommodate smaller screens.
*/
:host {
--width: 31rem;

View File

@@ -10,6 +10,16 @@ let id = 0;
*
* @slot - The dialog's content.
* @slot footer - The dialog's footer, usually one or more buttons representing various options.
*
* @part base - The base dialog element.
* @part overlay - The overlay.
* @part panel - The dialog panel (where the dialog and its is rendered).
* @part header - The dialog header.
* @part title - The dialog title.
* @part close-button - The close button.
* @part body - The dialog body.
* @part footer - The dialog footer.
*
*/
@Component({
tag: 'sl-dialog',
@@ -159,6 +169,7 @@ export class Dialog {
return (
<div
ref={el => (this.dialog = el)}
part="base"
class={{
dialog: true,
'dialog--open': this.open
@@ -167,10 +178,11 @@ export class Dialog {
onTransitionEnd={this.handleTransitionEnd}
hidden
>
<div class="dialog__overlay" onClick={this.handleOverlayClick} />
<div part="overlay" class="dialog__overlay" onClick={this.handleOverlayClick} />
<div
ref={el => (this.panel = el)}
part="panel"
class="dialog__panel"
role="dialog"
aria-modal="true"
@@ -180,23 +192,23 @@ export class Dialog {
tabIndex={0}
>
{!this.noHeader && (
<header class="dialog__header">
<span class="dialog__title" id={`${this.id}-title`}>
<header part="header" class="dialog__header">
<span part="title" class="dialog__title" id={`${this.id}-title`}>
{/* If there's no label, use an invisible character to prevent the heading from collapsing */}
{this.label || String.fromCharCode(65279)}
</span>
<button class="dialog__close" type="button" onClick={this.handleCloseClick}>
<button part="close-button" class="dialog__close" type="button" onClick={this.handleCloseClick}>
<sl-icon name="x"></sl-icon>
</button>
</header>
)}
<div class="dialog__body">
<div part="body" class="dialog__body">
<slot />
</div>
{!this.noFooter && (
<footer class="dialog__footer">
<footer part="footer" class="dialog__footer">
<slot name="footer" />
</footer>
)}

View File

@@ -1,8 +1,8 @@
@import 'component';
/**
* @prop --width: The preferred width of the drawer. Note that the drawer will shrink to accommodate smaller screens.
*/
* @prop --width: The preferred width of the drawer. Note that the drawer will shrink to accommodate smaller screens.
*/
:host {
--width: 25rem;

View File

@@ -10,6 +10,15 @@ let id = 0;
*
* @slot - The drawer's content.
* @slot footer - The drawer's footer, usually one or more buttons representing various options.
*
* @part base - The base drawer element.
* @part overlay - The overlay.
* @part panel - The drawer panel (where the drawer and its is rendered).
* @part header - The drawer header.
* @part title - The drawer title.
* @part close-button - The close button.
* @part body - The drawer body.
* @part footer - The drawer footer.
*/
@Component({
tag: 'sl-drawer',
@@ -174,6 +183,7 @@ export class Drawer {
return (
<div
ref={el => (this.drawer = el)}
part="base"
class={{
drawer: true,
'drawer--open': this.open,
@@ -186,10 +196,11 @@ export class Drawer {
onTransitionEnd={this.handleTransitionEnd}
hidden
>
<div class="drawer__overlay" onClick={this.handleOverlayClick} />
<div part="overlay" class="drawer__overlay" onClick={this.handleOverlayClick} />
<div
ref={el => (this.panel = el)}
part="panel"
class="drawer__panel"
role="dialog"
aria-modal="true"
@@ -199,23 +210,23 @@ export class Drawer {
tabIndex={0}
>
{!this.noHeader && (
<header class="drawer__header">
<span class="drawer__title" id={`${this.id}-title`}>
<header part="header" class="drawer__header">
<span part="title" class="drawer__title" id={`${this.id}-title`}>
{/* If there's no label, use an invisible character to prevent the heading from collapsing */}
{this.label || String.fromCharCode(65279)}
</span>
<button class="drawer__close" type="button" onClick={this.handleCloseClick}>
<button part="close-button" class="drawer__close" type="button" onClick={this.handleCloseClick}>
<sl-icon name="x"></sl-icon>
</button>
</header>
)}
<div class="drawer__body">
<div part="body" class="drawer__body">
<slot />
</div>
{!this.noFooter && (
<footer class="drawer__footer">
<footer part="footer" class="drawer__footer">
<slot name="footer" />
</footer>
)}

View File

@@ -10,6 +10,8 @@ let id = 0;
* @slot trigger - The dropdown's trigger, usually a `<sl-button>` element.
* @slot - The dropdown's content.
*
* @part base - The base element of the dropdown.
* @part trigger - The container that wraps the trigger.
* @part panel - The panel that gets shown when the dropdown is open.
*/
@@ -249,6 +251,7 @@ export class Dropdown {
render() {
return (
<div
part="base"
id={this.id}
class={{
dropdown: true,
@@ -258,6 +261,7 @@ export class Dropdown {
aria-haspopup="true"
>
<span
part="trigger"
class="dropdown__trigger"
ref={el => (this.trigger = el)}
onKeyDown={this.handleTriggerKeyDown}

View File

@@ -10,6 +10,10 @@ interface FormControl {
/**
* @since 1.0
* @status experimental
*
* @slot - The form's content.
*
* @part base - The base element of the form.
*/
@Component({
@@ -230,6 +234,7 @@ export class Form {
return (
<div
ref={el => (this.form = el)}
part="base"
class="form"
role="form"
onClick={this.handleClick}

View File

@@ -7,6 +7,8 @@ const parser = new DOMParser();
/**
* @since 1.0
* @status stable
*
* @part base - The base element of the icon.
*/
@Component({
@@ -76,6 +78,6 @@ export class Icon {
}
render() {
return <div class="icon" role="img" aria-label={this.getLabel()} innerHTML={this.svg} />;
return <div part="base" class="icon" role="img" aria-label={this.getLabel()} innerHTML={this.svg} />;
}
}

View File

@@ -6,11 +6,21 @@ let id = 0;
* @since 1.0
* @status stable
*
* @slot label - The input's label. Alternatively, you can use the label prop.
* @slot prefix - Used to prepend an icon or similar element to the input.
* @slot suffix - Used to append an icon or similar element to the input.
* @slot clear-icon - An icon to use in lieu of the default clear icon.
* @slot show-password-icon - An icon to use in lieu of the default show password icon.
* @slot hide-password-icon - An icon to use in lieu of the default hide password icon.
*
* @part base - The base element of the input.
* @part form-control - The form control that wraps the label and the input.
* @part label - The input label.
* @part input - The synthetic input container.
* @part prefix - The input prefix container.
* @part clear-button - The clear button.
* @part password-toggle-button - The password toggle button.
* @part suffix - The input suffix container.
*/
@Component({
@@ -203,12 +213,14 @@ export class Input {
render() {
return (
<div
part="form-control"
class={{
'form-control': true,
'form-control--has-label': this.label.length > 0
}}
>
<label
part="label"
class={{
label: true,
'label--small': this.size === 'small',
@@ -221,6 +233,7 @@ export class Input {
</label>
<div
part="base"
class={{
input: true,
@@ -237,11 +250,12 @@ export class Input {
}}
onMouseDown={this.handleMouseDown}
>
<span class="input__prefix">
<span part="prefix" class="input__prefix">
<slot name="prefix" />
</span>
<input
part="input"
ref={el => (this.input = el)}
id={this.inputId}
class="input__control"
@@ -271,7 +285,13 @@ export class Input {
/>
{this.clearable && (
<button class="input__clear" type="button" onClick={this.handleClearClick} tabindex="-1">
<button
part="clear-button"
class="input__clear"
type="button"
onClick={this.handleClearClick}
tabindex="-1"
>
<slot name="clear-icon">
<sl-icon name="x-circle" />
</slot>
@@ -279,7 +299,13 @@ export class Input {
)}
{this.togglePassword && (
<button class="input__password-toggle" type="button" onClick={this.handlePasswordToggle} tabindex="-1">
<button
part="password-toggle-button"
class="input__password-toggle"
type="button"
onClick={this.handlePasswordToggle}
tabindex="-1"
>
{this.isPasswordVisible ? (
<slot name="show-password-icon">
<sl-icon name="eye-slash" />
@@ -293,7 +319,7 @@ export class Input {
</button>
)}
<span class="input__suffix">
<span part="suffix" class="input__suffix">
<slot name="suffix" />
</span>
</div>

View File

@@ -3,6 +3,8 @@ import { Component, h } from '@stencil/core';
/**
* @since 1.0
* @status stable
*
* @part - The base element of the menu divider.
*/
@Component({
@@ -12,6 +14,6 @@ import { Component, h } from '@stencil/core';
})
export class MenuDivider {
render() {
return <div class="menu-divider" role="separator" />;
return <div part="base" class="menu-divider" role="separator" />;
}
}

View File

@@ -7,7 +7,12 @@ import { Component, Prop, h } from '@stencil/core';
* @slot - The menu item's label.
* @slot prefix - Used to prepend an icon or similar element to the menu item.
* @slot suffix - Used to append an icon or similar element to the menu item.
* @slot check-icon - An icon to use in lieu of the default check icon.
*
* @part base - The base element of the menu item.
* @part checked-icon - The container that wraps the checked icon.
* @part prefix - The prefix container.
* @part label - The menu item label.
* @part suffix - The suffix container.
*/
@Component({
@@ -31,6 +36,7 @@ export class MenuItem {
render() {
return (
<div
part="base"
class={{
'menu-item': true,
'menu-item--checked': this.checked,
@@ -42,21 +48,19 @@ export class MenuItem {
aria-disabled={this.disabled}
aria-selected={this.active}
>
<span class="menu-item__check">
<slot name="check-icon">
<sl-icon name="check2" />
</slot>
<span part="checked-icon" class="menu-item__check">
<sl-icon name="check2" />
</span>
<span class="menu-item__prefix">
<span part="prefix" class="menu-item__prefix">
<slot name="prefix" />
</span>
<span class="menu-item__label">
<span part="label" class="menu-item__label">
<slot />
</span>
<span class="menu-item__suffix">
<span part="suffix" class="menu-item__suffix">
<slot name="suffix" />
</span>
</div>

View File

@@ -3,6 +3,10 @@ import { Component, h } from '@stencil/core';
/**
* @since 1.0
* @status stable
*
* @slot - The menu label's content.
*
* @part base - The base element of the menu label.
*/
@Component({
@@ -13,7 +17,7 @@ import { Component, h } from '@stencil/core';
export class MenuLabel {
render() {
return (
<div class="menu-label">
<div part="base" class="menu-label">
<slot />
</div>
);

View File

@@ -7,6 +7,8 @@ import { getTextContent } from '../../utilities/slot';
* @status stable
*
* @slot - The menu's items.
*
* @part base - The base element of the menu.
*/
@Component({
@@ -186,6 +188,7 @@ export class Menu {
return (
<div
ref={el => (this.menu = el)}
part="base"
class="menu"
tabIndex={0}
role="menu"

View File

@@ -5,6 +5,10 @@ import { Component, Prop, h } from '@stencil/core';
* @status stable
*
* @slot - A label to show inside the indicator.
*
* @part base - The base element of the progress bar.
* @part indicator - The progress bar indicator.
* @part label - The progress bar label.
*/
@Component({
@@ -19,6 +23,7 @@ export class ProgressBar {
render() {
return (
<div
part="base"
class="progress-bar"
role="progressbar"
aria-valuemin="0"
@@ -26,12 +31,13 @@ export class ProgressBar {
aria-valuenow={this.percentage}
>
<div
part="base"
class="progress-bar__indicator"
style={{
width: `${this.percentage}%`
}}
>
<span class="progress-bar__label">
<span part="label" class="progress-bar__label">
<slot />
</span>
</div>

View File

@@ -2,6 +2,10 @@
:host {
display: inline-flex;
}
.progress-ring {
display: inline-flex;
align-items: center;
justify-content: center;
position: relative;

View File

@@ -1,8 +1,13 @@
import { Component, Host, Prop, Watch, h } from '@stencil/core';
import { Component, Prop, Watch, h } from '@stencil/core';
/**
* @since 1.0
* @status stable
*
* @slot - A label to show inside the ring.
*
* @part base - The base element of the progress ring.
* @part label - The progress ring label.
*/
@Component({
@@ -42,8 +47,8 @@ export class Progress {
render() {
return (
<Host>
<svg class="progress-ring" width={this.size} height={this.size}>
<div part="base" class="progress-ring">
<svg class="progress-ring__image" width={this.size} height={this.size}>
<circle
class="progress-ring__track"
stroke-width={this.strokeWidth}
@@ -66,10 +71,10 @@ export class Progress {
/>
</svg>
<span class="progress-ring__label">
<span part="label" class="progress-ring__label">
<slot />
</span>
</Host>
</div>
);
}
}

View File

@@ -7,6 +7,11 @@ let id = 0;
* @status stable
*
* @slot - The radio's label.
*
* @part base - The radio base element.
* @part control - The radio control.
* @part checked-icon - The container the wraps the checked icon.
* @part label - The radio label.
*/
@Component({
@@ -126,19 +131,20 @@ export class Radio {
render() {
return (
<label
htmlFor={this.inputId}
role="radio"
part="base"
class={{
radio: true,
'radio--checked': this.checked,
'radio--disabled': this.disabled,
'radio--focused': this.hasFocus
}}
htmlFor={this.inputId}
role="radio"
onKeyDown={this.handleKeyDown}
onMouseDown={this.handleMouseDown}
>
<span class="radio__control">
<span class="radio__icon">
<span part="control" class="radio__control">
<span part="checked-icon" class="radio__icon">
<svg viewBox="0 0 16 16">
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g fill="currentColor">
@@ -163,7 +169,7 @@ export class Radio {
/>
</span>
<span id={this.labelId} class="radio__label">
<span part="label" id={this.labelId} class="radio__label">
<slot />
</span>
</label>

View File

@@ -4,6 +4,10 @@ import ResizeObserver from 'resize-observer-polyfill';
/**
* @since 1.0
* @status stable
*
* @part base - The base element of the range.
* @part input - The native range input.
* @part tooltip - The range tooltip.
*/
@Component({
@@ -114,6 +118,7 @@ export class Range {
render() {
return (
<div
part="base"
class={{
range: true,
@@ -125,6 +130,7 @@ export class Range {
}}
>
<input
part="input"
ref={el => (this.input = el)}
type="range"
class="range__control"
@@ -139,7 +145,7 @@ export class Range {
onBlur={this.handleBlur}
/>
{this.tooltip !== 'none' && (
<output ref={el => (this.output = el)} class="range__tooltip">
<output part="tooltip" ref={el => (this.output = el)} class="range__tooltip">
{this.tooltipFormatter(this.value)}
</output>
)}

View File

@@ -48,9 +48,12 @@
}
.select__icon {
display: inline-flex;
}
.select__icon sl-icon {
transition: var(--sl-transition-medium) transform ease;
}
.select--open .select__icon {
.select--open .select__icon sl-icon {
transform: rotate(-180deg);
}

View File

@@ -7,6 +7,16 @@ let id = 0;
/**
* @since 1.0
* @status stable
*
* @slot - The select's options in the form of menu items.
* @slot label - The select's label. Alternatively, you can use the label prop.
*
* @part base - The base element of the select (a dropdown).
* @part form-control - The form control that wraps the label and the select.
* @part label - The select label.
* @part input - The select input.
* @part tags - The container in which multiselect options are rendered.
* @part icon - The select icon.
*/
@Component({
@@ -269,12 +279,14 @@ export class Select {
render() {
return (
<div
part="form-control"
class={{
'form-control': true,
'form-control--has-label': this.label.length > 0
}}
>
<label
part="label"
class={{
label: true,
'label--small': this.size === 'small',
@@ -287,6 +299,7 @@ export class Select {
<slot name="label">{this.label}</slot>
</label>
<sl-dropdown
part="base"
ref={el => (this.dropdown = el)}
closeOnSelect={!this.multiple}
containingElement={this.host}
@@ -306,6 +319,7 @@ export class Select {
>
<sl-input
slot="trigger"
part="input"
ref={el => (this.input = el)}
id={this.inputId}
class="select__input"
@@ -322,12 +336,14 @@ export class Select {
onKeyDown={this.handleKeyDown}
>
{this.displayTags.length && (
<span slot="prefix" class="select__tags">
<span part="tags" slot="prefix" class="select__tags">
{this.displayTags}
</span>
)}
<sl-icon slot="suffix" class="select__icon" name="chevron-down" />
<span part="icon" slot="suffix" class="select__icon">
<sl-icon name="chevron-down" />
</span>
</sl-input>
<sl-menu

View File

@@ -3,6 +3,8 @@ import { Component, h } from '@stencil/core';
/**
* @since 1.0
* @status stable
*
* @part base - The base element of the spinner.
*/
@Component({
@@ -12,6 +14,6 @@ import { Component, h } from '@stencil/core';
})
export class Spinner {
render() {
return <span class="spinner" aria-busy="true" aria-live="polite" />;
return <span part="base" class="spinner" aria-busy="true" aria-live="polite" />;
}
}

View File

@@ -6,8 +6,12 @@ let id = 0;
* @since 1.0
* @status stable
*
*
* @slot - The switch's label.
*
* @part base - The base element of the switch.
* @part control - The switch control.
* @part thumb - The switch position indicator.
* @part label - The switch label.
*/
@Component({
@@ -104,6 +108,7 @@ export class Switch {
render() {
return (
<label
part="base"
htmlFor={this.switchId}
role="switch"
class={{
@@ -114,8 +119,8 @@ export class Switch {
}}
onMouseDown={this.handleMouseDown}
>
<span class="switch__control">
<span class="switch__thumb" />
<span part="control" class="switch__control">
<span part="thumb" class="switch__thumb" />
<input
ref={el => (this.input = el)}
@@ -133,7 +138,7 @@ export class Switch {
/>
</span>
<span id={this.labelId} class="switch__label">
<span part="label" id={this.labelId} class="switch__label">
<slot />
</span>
</label>

View File

@@ -9,6 +9,12 @@ import { focusVisible } from '../../utilities/focus-visible';
*
* @slot nav - Used for grouping tabs in the tab group.
* @slot - Used for grouping tab panels in the tab group.
*
* @part base - The base element of the tab group.
* @part nav - The tab group navigation container.
* @part tabs - The container that wraps the slotted tabs.
* @part active-tab-indicator - An element that displays the currently selected tab. This is a child of the tabs container.
* @part body - The tab group body where tab panels are slotted in.
*/
@Component({
@@ -210,6 +216,7 @@ export class TabGroup {
render() {
return (
<div
part="base"
ref={el => (this.tabGroup = el)}
class={{
'tab-group': true,
@@ -223,14 +230,18 @@ export class TabGroup {
onClick={this.handleClick}
onKeyDown={this.handleKeyDown}
>
<div ref={el => (this.nav = el)} class="tab-group__nav" tabindex="-1">
<div ref={el => (this.tabs = el)} class="tab-group__tabs" role="tablist">
<div ref={el => (this.activeTabIndicator = el)} class="tab-group__active-tab-indicator" />
<div ref={el => (this.nav = el)} part="nav" class="tab-group__nav" tabindex="-1">
<div ref={el => (this.tabs = el)} part="tabs" class="tab-group__tabs" role="tablist">
<div
ref={el => (this.activeTabIndicator = el)}
part="active-tab-indicator"
class="tab-group__active-tab-indicator"
/>
<slot name="nav" />
</div>
</div>
<div ref={el => (this.body = el)} class="tab-group__body">
<div ref={el => (this.body = el)} part="body" class="tab-group__body">
<slot />
</div>
</div>

View File

@@ -7,6 +7,8 @@ let id = 0;
* @status stable
*
* @slot - The tab panel's content.
*
* @part base - The base element of the tab panel.
*/
@Component({
@@ -29,7 +31,7 @@ export class TabPanel {
return (
// If the user didn't provide an ID, we'll set one so we can link tabs and tab panels with aria labels
<Host id={this.host.id || this.id} style={{ display: this.active ? 'block' : 'none' }}>
<div class="tab-panel" role="tabpanel" aria-selected={this.active} aria-hidden={!this.active}>
<div part="base" class="tab-panel" role="tabpanel" aria-selected={this.active} aria-hidden={!this.active}>
<slot />
</div>
</Host>

View File

@@ -7,6 +7,8 @@ let id = 0;
* @status stable
*
* @slot - The tab's label.
*
* @part - The base element of the tab.
*/
@Component({
@@ -46,6 +48,7 @@ export class Tab {
// If the user didn't provide an ID, we'll set one so we can link tabs and tab panels with aria labels
<Host id={this.host.id || this.id}>
<div
part="base"
ref={el => (this.tab = el)}
class={{
tab: true,

View File

@@ -5,6 +5,10 @@ import { Component, Event, EventEmitter, Prop, h } from '@stencil/core';
* @status stable
*
* @slot - The tag's content.
*
* @part base - The base element of the tag.
* @part content - The tag content.
* @part remove-button - The remove button.
*/
@Component({
@@ -42,6 +46,7 @@ export class Tag {
return (
<span
ref={el => (this.tag = el)}
part="base"
class={{
tag: true,
@@ -63,12 +68,12 @@ export class Tag {
'tag--removable': this.removable
}}
>
<span class="tag__content">
<span part="content" class="tag__content">
<slot />
</span>
{this.removable && (
<span class="tag__remove" role="button" tabIndex={-1} onClick={this.handleRemoveClick}>
<span part="remove-button" class="tag__remove" role="button" tabIndex={-1} onClick={this.handleRemoveClick}>
<sl-icon name="x" />
</span>
)}

View File

@@ -6,6 +6,13 @@ let id = 0;
/**
* @since 1.0
* @status stable
*
* @slot label - The textarea's label. Alternatively, you can use the label prop.
*
* @part base - The base element of the textarea.
* @part form-control - The form control that wraps the textarea and label.
* @part label - The textarea label.
* @part textarea - The native textarea.
*/
@Component({
@@ -174,12 +181,14 @@ export class Textarea {
render() {
return (
<div
part="form-control"
class={{
'form-control': true,
'form-control--has-label': this.label.length > 0
}}
>
<label
part="label"
class={{
label: true,
'label--small': this.size === 'small',
@@ -191,6 +200,7 @@ export class Textarea {
<slot name="label">{this.label}</slot>
</label>
<div
part="base"
class={{
textarea: true,
@@ -211,6 +221,7 @@ export class Textarea {
}}
>
<textarea
part="textarea"
ref={el => (this.textarea = el)}
id={this.textareaId}
class="textarea__control"

View File

@@ -1,14 +1,14 @@
@import 'component';
/**
* @prop --hide-delay: The amount of time to wait before hiding the tooltip.
* @prop --hide-duration: The amount of time the hide transition takes to complete.
* @prop --hide-timing-function: The timing function (easing) to use for the hide transition.
* @prop --max-width: The maximum width of the tooltip.
* @prop --show-delay: The amount of time to wait before showing the tooltip.
* @prop --show-duration: The amount of time the show transition takes to complete.
* @prop --show-timing-function: The timing function (easing) to use for the show transition.
*/
* @prop --hide-delay: The amount of time to wait before hiding the tooltip.
* @prop --hide-duration: The amount of time the hide transition takes to complete.
* @prop --hide-timing-function: The timing function (easing) to use for the hide transition.
* @prop --max-width: The maximum width of the tooltip.
* @prop --show-delay: The amount of time to wait before showing the tooltip.
* @prop --show-duration: The amount of time the show transition takes to complete.
* @prop --show-timing-function: The timing function (easing) to use for the show transition.
*/
:host {
display: contents;

View File

@@ -8,6 +8,8 @@ let id = 0;
* @status stable
*
* @slot - The tooltip's target element. Only the first element will be used as the target.
*
* @part - The base element of the tooltip.
*/
@Component({
@@ -218,6 +220,7 @@ export class Tooltip {
{!this.disabled && (
<div
part="base"
ref={el => (this.tooltip = el)}
id={this.id}
class={{