diff --git a/docs/assets/plugins/metadata/metadata.js b/docs/assets/plugins/metadata/metadata.js index b09bf260..37045778 100644 --- a/docs/assets/plugins/metadata/metadata.js +++ b/docs/assets/plugins/metadata/metadata.js @@ -7,6 +7,7 @@ function createPropsTable(props) { const table = document.createElement('table'); + table.classList.add('metadata-table'); table.innerHTML = ` @@ -64,6 +65,7 @@ function createEventsTable(events) { const table = document.createElement('table'); + table.classList.add('metadata-table'); table.innerHTML = ` @@ -94,6 +96,7 @@ function createMethodsTable(methods) { const table = document.createElement('table'); + table.classList.add('metadata-table'); table.innerHTML = ` @@ -132,6 +135,7 @@ function createSlotsTable(slots) { const table = document.createElement('table'); + table.classList.add('metadata-table'); table.innerHTML = ` @@ -158,6 +162,7 @@ function createCustomPropertiesTable(styles) { const table = document.createElement('table'); + table.classList.add('metadata-table'); table.innerHTML = ` @@ -186,6 +191,7 @@ function createPartsTable(parts) { const table = document.createElement('table'); + table.classList.add('metadata-table'); table.innerHTML = ` @@ -212,6 +218,7 @@ function createAnimationsTable(animations) { const table = document.createElement('table'); + table.classList.add('metadata-table'); table.innerHTML = ` @@ -456,6 +463,8 @@ result += ` ## Properties ${createPropsTable(props)} + + _Learn more about [properties and attributes](/getting-started/usage#properties)._ `; } @@ -463,6 +472,8 @@ result += ` ## Events ${createEventsTable(component.events)} + + _Learn more about [listening to events](/getting-started/usage#events)._ `; } @@ -470,18 +481,9 @@ result += ` ## Methods -

- Methods can be called by obtaining a reference to the element and calling - el.methodName(). -

- - -

- Methods can be called by obtaining a ref to the element and calling - ref.current.methodName(). -

- ${createMethodsTable(methods)} + + _Learn more about [calling methods](/getting-started/usage#methods)._ `; } @@ -489,6 +491,8 @@ result += ` ## Slots ${createSlotsTable(component.slots)} + + _Learn more about [using slots](/getting-started/usage#slots)._ `; } @@ -496,6 +500,8 @@ result += ` ## CSS Custom Properties ${createCustomPropertiesTable(component.cssProperties)} + + _Learn more about [customizing CSS Custom Properties](/getting-started/customizing#custom-properties)._ `; } @@ -503,6 +509,8 @@ result += ` ## CSS Parts ${createPartsTable(component.cssParts)} + + _Learn more about [customizing CSS Parts](/getting-started/customizing#component-parts)._ `; } @@ -511,7 +519,7 @@ ## Animations ${createAnimationsTable(component.animations)} - Learn how to [customize animations](/getting-started/customizing#animations). + _Learn more about [customizing animations](/getting-started/customizing#animations)._ `; } diff --git a/docs/assets/styles/docs.css b/docs/assets/styles/docs.css index e01dd8b3..c7d06ce3 100644 --- a/docs/assets/styles/docs.css +++ b/docs/assets/styles/docs.css @@ -437,6 +437,10 @@ kbd, cursor: help; } +.markdown-section .metadata-table { + margin-bottom: 0rem; +} + /* Iframes */ .markdown-section iframe { border: none; diff --git a/docs/resources/changelog.md b/docs/resources/changelog.md index 20fb793d..dfa5668e 100644 --- a/docs/resources/changelog.md +++ b/docs/resources/changelog.md @@ -8,6 +8,15 @@ _During the beta period, these restrictions may be relaxed in the event of a mis ## Next +- 🚨 BREAKING: refactored exported parts to ensure composed components and their parts can be targeted via CSS + - Refactored the `eye-dropper-button` part and added `eye-dropper-button__base`, `eye-dropper-button__prefix`, `eye-dropper-button__label`, `eye-dropper-button__suffix`, and `eye-dropper-button__caret` parts to `` + - Refactored the `format-button` part and added `format-button__base`, `format-button__prefix`, `format-button__label`, `format-button__suffix`, and `format-button__caret` parts to `` + - Moved the `close-button` part in `` to the internal `` and removed the `` that wrapped it + - Moved the `close-button` part in `` and `` to point to the host element and added the `close-button__base` part + - Renamed parts in `` from `tag-base` to `tag__base`, `tag-content` to `tag__content`, and `tag-remove-button` to `tag__remove-button` + - Moved the `close-button` part in `` to the internal `` and added the `close-button__base` part + - Moved the `scroll-button` part in `` to the internal `` and added the `scroll-button__base`, `scroll-button--start`, and `scroll-button--end` parts + - Moved the `remove-button` part in `` to the internal `` and added the `remove-button__base` part - 🚨 BREAKING: removed `checked-icon` part from `` in preparation for parts refactor - 🚨 BREAKING: changed the `typeToSelect()` method's argument from `String` to `KeyboardEvent` in `` to support more advanced key combinations - Added `form`, `formaction`, `formmethod`, `formnovalidate`, and `formtarget` attributes to `` [#699](https://github.com/shoelace-style/shoelace/issues/699) diff --git a/docs/resources/contributing.md b/docs/resources/contributing.md index 14078d01..43aba7bb 100644 --- a/docs/resources/contributing.md +++ b/docs/resources/contributing.md @@ -262,6 +262,24 @@ Parts let you target a specific element inside the component's shadow DOM but, b This convention can be relaxed when the developer experience is greatly improved by not following these suggestions. +### Naming CSS Parts + +While CSS parts can be named [virtually anything](https://www.abeautifulsite.net/posts/valid-names-for-css-parts/), within Shoelace they must use the kebab-case convention and lowercase letters. Modifiers must be delimited by `--` like in BEM. This is useful for allowing users to target parts with various states, such as `my-part--focus`. + +When composing elements, use `part` to export the host element and `exportparts` to export its parts. + +```js +render() { + return html` +
+ +
+ `; +} +``` + +This results in a consistent, easy to understand structure for parts. In this example, the `icon` part will target the host element and the `icon__base` part will target the icon's `base` part. + ### Form Controls Form controls should support submission and validation through the following conventions: diff --git a/scripts/plop/plopfile.js b/scripts/plop/plopfile.js index 2b5a6d54..49a8e415 100644 --- a/scripts/plop/plopfile.js +++ b/scripts/plop/plopfile.js @@ -1,6 +1,5 @@ export default function (plop) { plop.setHelper('tagWithoutPrefix', tag => tag.replace(/^sl-/, '')); - plop.setHelper('tagToHumanReadableName', tag => tag.replace(/^sl-/, '').replace(/-/g, ' ')); plop.setHelper('tagToTitle', tag => { const withoutPrefix = plop.getHelper('tagWithoutPrefix'); diff --git a/scripts/plop/templates/component/component.hbs b/scripts/plop/templates/component/component.hbs index eef7cd98..306c316d 100644 --- a/scripts/plop/templates/component/component.hbs +++ b/scripts/plop/templates/component/component.hbs @@ -15,7 +15,7 @@ import styles from './{{ tagWithoutPrefix tag }}.styles'; * @slot - The default slot. * @slot example - An example slot. * - * @csspart {{ tagWithoutPrefix tag }} - The internal wrapper for the {{ tagToHumanReadableName tag }}. + * @csspart base - The component's internal wrapper. * * @cssproperty --example - An example CSS custom property. */ diff --git a/src/components/alert/alert.styles.ts b/src/components/alert/alert.styles.ts index c171ce75..7a05bf17 100644 --- a/src/components/alert/alert.styles.ts +++ b/src/components/alert/alert.styles.ts @@ -28,15 +28,17 @@ export default css` margin: inherit; } + .alert:not(.alert--has-icon) .alert__icon, + .alert:not(.alert--closable) .alert__close-button { + display: none; + } + .alert__icon { flex: 0 0 auto; display: flex; align-items: center; font-size: var(--sl-font-size-large); - } - - .alert__icon ::slotted(*) { - margin-left: var(--sl-spacing-large); + padding-left: var(--sl-spacing-large); } .alert--primary { @@ -85,7 +87,7 @@ export default css` overflow: hidden; } - .alert__close { + .alert__close-button { flex: 0 0 auto; display: flex; align-items: center; diff --git a/src/components/alert/alert.ts b/src/components/alert/alert.ts index bd89e4fc..4af1ac8b 100644 --- a/src/components/alert/alert.ts +++ b/src/components/alert/alert.ts @@ -4,6 +4,7 @@ import { classMap } from 'lit/directives/class-map.js'; import '~/components/icon-button/icon-button'; import { animateTo, stopAnimations } from '~/internal/animate'; import { emit, waitForEvent } from '~/internal/event'; +import { HasSlotController } from '~/internal/slot'; import { watch } from '~/internal/watch'; import { getAnimation, setDefaultAnimation } from '~/utilities/animation-registry'; import styles from './alert.styles'; @@ -24,10 +25,11 @@ const toastStack = Object.assign(document.createElement('div'), { className: 'sl * @event sl-hide - Emitted when the alert closes. * @event sl-after-hide - Emitted after the alert closes and all animations are complete. * - * @csspart base - The component's base wrapper. + * @csspart base - The component's internal wrapper. * @csspart icon - The container that wraps the alert icon. * @csspart message - The alert message. * @csspart close-button - The close button. + * @csspart close-button__base - The close button's `base` part. * * @cssproperty --box-shadow - The alert's box shadow. * @@ -40,6 +42,7 @@ export default class SlAlert extends LitElement { static styles = styles; private autoHideTimeout: number; + private readonly hasSlotController = new HasSlotController(this, 'icon', 'suffix'); @query('[part="base"]') base: HTMLElement; @@ -177,6 +180,7 @@ export default class SlAlert extends LitElement { alert: true, 'alert--open': this.open, 'alert--closable': this.closable, + 'alert--has-icon': this.hasSlotController.test('icon'), 'alert--primary': this.variant === 'primary', 'alert--success': this.variant === 'success', 'alert--neutral': this.variant === 'neutral', @@ -199,14 +203,14 @@ export default class SlAlert extends LitElement { ${this.closable ? html` - - - + ` : ''} diff --git a/src/components/avatar/avatar.ts b/src/components/avatar/avatar.ts index 96ff36e8..293843e0 100644 --- a/src/components/avatar/avatar.ts +++ b/src/components/avatar/avatar.ts @@ -12,7 +12,7 @@ import styles from './avatar.styles'; * * @slot icon - The default icon to use when no image or initials are present. * - * @csspart base - The component's base wrapper. + * @csspart base - The component's internal wrapper. * @csspart icon - The container that wraps the avatar icon. * @csspart initials - The container that wraps the avatar initials. * @csspart image - The avatar image. diff --git a/src/components/badge/badge.ts b/src/components/badge/badge.ts index dcd40a49..f14a476d 100644 --- a/src/components/badge/badge.ts +++ b/src/components/badge/badge.ts @@ -9,7 +9,7 @@ import styles from './badge.styles'; * * @slot - The badge's content. * - * @csspart base - The base wrapper + * @csspart base - The component's internal wrapper. */ @customElement('sl-badge') export default class SlBadge extends LitElement { diff --git a/src/components/breadcrumb-item/breadcrumb-item.ts b/src/components/breadcrumb-item/breadcrumb-item.ts index 63ff5448..0c354ae0 100644 --- a/src/components/breadcrumb-item/breadcrumb-item.ts +++ b/src/components/breadcrumb-item/breadcrumb-item.ts @@ -15,7 +15,7 @@ import styles from './breadcrumb-item.styles'; * @slot separator - The separator to use for the breadcrumb item. This will only change the separator for this item. If * you want to change it for all items in the group, set the separator on `` instead. * - * @csspart base - The component's base wrapper. + * @csspart base - The component's internal wrapper. * @csspart label - The breadcrumb item's label. * @csspart prefix - The container that wraps the prefix slot. * @csspart suffix - The container that wraps the suffix slot. diff --git a/src/components/breadcrumb/breadcrumb.ts b/src/components/breadcrumb/breadcrumb.ts index 1a185edf..ca8e3a13 100644 --- a/src/components/breadcrumb/breadcrumb.ts +++ b/src/components/breadcrumb/breadcrumb.ts @@ -13,7 +13,7 @@ import styles from './breadcrumb.styles'; * * @dependency sl-icon * - * @csspart base - The component's base wrapper. + * @csspart base - The component's internal wrapper. */ @customElement('sl-breadcrumb') export default class SlBreadcrumb extends LitElement { diff --git a/src/components/button-group/button-group.ts b/src/components/button-group/button-group.ts index c47410b4..61055765 100644 --- a/src/components/button-group/button-group.ts +++ b/src/components/button-group/button-group.ts @@ -8,7 +8,7 @@ import styles from './button-group.styles'; * * @slot - One or more `` elements to display in the button group. * - * @csspart base - The component's base wrapper. + * @csspart base - The component's internal wrapper. */ @customElement('sl-button-group') export default class SlButtonGroup extends LitElement { diff --git a/src/components/button/button.ts b/src/components/button/button.ts index a5756724..52e3f73e 100644 --- a/src/components/button/button.ts +++ b/src/components/button/button.ts @@ -22,7 +22,7 @@ import styles from './button.styles'; * @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. * - * @csspart base - The component's base wrapper. + * @csspart base - The component's internal wrapper. * @csspart prefix - The prefix container. * @csspart label - The button's label. * @csspart suffix - The suffix container. diff --git a/src/components/card/card.ts b/src/components/card/card.ts index 278b0b92..07d76ec2 100644 --- a/src/components/card/card.ts +++ b/src/components/card/card.ts @@ -13,7 +13,7 @@ import styles from './card.styles'; * @slot footer - The card's footer. * @slot image - The card's image. * - * @csspart base - The component's base wrapper. + * @csspart base - The component's internal wrapper. * @csspart image - The card's image, if present. * @csspart header - The card's header, if present. * @csspart body - The card's body. diff --git a/src/components/checkbox/checkbox.ts b/src/components/checkbox/checkbox.ts index 12475112..cfa151c0 100644 --- a/src/components/checkbox/checkbox.ts +++ b/src/components/checkbox/checkbox.ts @@ -18,7 +18,7 @@ import styles from './checkbox.styles'; * @event sl-change - Emitted when the control's checked state changes. * @event sl-focus - Emitted when the control gains focus. * - * @csspart base - The component's base wrapper. + * @csspart base - The component's internal wrapper. * @csspart control - The checkbox control. * @csspart checked-icon - The container the wraps the checked icon. * @csspart indeterminate-icon - The container that wraps the indeterminate icon. diff --git a/src/components/color-picker/color-picker.ts b/src/components/color-picker/color-picker.ts index 3f8b6f4a..ad36f14d 100644 --- a/src/components/color-picker/color-picker.ts +++ b/src/components/color-picker/color-picker.ts @@ -43,7 +43,7 @@ declare const EyeDropper: EyeDropperConstructor; * * @event sl-change Emitted when the color picker's value changes. * - * @csspart base - The component's base wrapper + * @csspart base - The component's internal wrapper. * @csspart trigger - The color picker's dropdown trigger. * @csspart swatches - The container that holds swatches. * @csspart swatch - Each individual swatch. @@ -55,8 +55,18 @@ declare const EyeDropper: EyeDropperConstructor; * @csspart slider-handle - Hue and opacity slider handles. * @csspart preview - The preview color. * @csspart input - The text input. - * @csspart eye-dropper-button - The toggle format button's base. - * @csspart format-button - The toggle format button's base. + * @csspart eye-dropper-button - The eye dropper button. + * @csspart eye-dropper-button__button - The eye dropper button's `button` part. + * @csspart eye-dropper-button__prefix - The eye dropper button's `prefix` part. + * @csspart eye-dropper-button__label - The eye dropper button's `label` part. + * @csspart eye-dropper-button__button-suffix - The eye dropper button's `suffix` part. + * @csspart eye-dropper-button__caret - The eye dropper button's `caret` part. + * @csspart format-button - The format button. + * @csspart format-button__button - The format button's `button` part. + * @csspart format-button__prefix - The format button's `prefix` part. + * @csspart format-button__label - The format button's `label` part. + * @csspart format-button__button-suffix - The format button's `suffix` part. + * @csspart format-button__caret - The format button's `caret` part. * * @cssproperty --grid-width - The width of the color grid. * @cssproperty --grid-height - The height of the color grid. @@ -732,8 +742,15 @@ export default class SlColorPicker extends LitElement { ${!this.noFormatToggle ? html` ${this.setLetterCase(this.format)} @@ -742,7 +759,17 @@ export default class SlColorPicker extends LitElement { : ''} ${hasEyeDropper ? html` - + ${this.label.length > 0 ? this.label : String.fromCharCode(65279)} ${this.label.length > 0 ? this.label : String.fromCharCode(65279)} ` element. * @csspart tag - The multi select option, an `` element. - * @csspart tag-base - The tag's `base` part. - * @csspart tag-content - The tag's `content` part. - * @csspart tag-remove-button - The tag's `remove-button` part. + * @csspart tag__base - The tag's `base` part. + * @csspart tag__content - The tag's `content` part. + * @csspart tag__remove-button - The tag's `remove-button` part. * @csspart tags - The container in which multi select options are rendered. */ @customElement('sl-select') @@ -381,7 +381,11 @@ export default class SlSelect extends LitElement { return html` +${total - this.maxTagsVisible} + + +${total - this.maxTagsVisible} + `); } } else { diff --git a/src/components/skeleton/skeleton.ts b/src/components/skeleton/skeleton.ts index 872d419d..d47810f1 100644 --- a/src/components/skeleton/skeleton.ts +++ b/src/components/skeleton/skeleton.ts @@ -7,7 +7,7 @@ import styles from './skeleton.styles'; * @since 2.0 * @status stable * - * @csspart base - The component's base wrapper. + * @csspart base - The component's internal wrapper. * @csspart indicator - The skeleton's indicator which is responsible for its color and animation. * * @cssproperty --border-radius - The skeleton's border radius. diff --git a/src/components/spinner/spinner.ts b/src/components/spinner/spinner.ts index 0d40a1c1..5b23dd1c 100644 --- a/src/components/spinner/spinner.ts +++ b/src/components/spinner/spinner.ts @@ -6,7 +6,7 @@ import styles from './spinner.styles'; * @since 2.0 * @status stable * - * @csspart base - The component's base wrapper. + * @csspart base - The component's internal wrapper. * * @cssproperty --track-width - The width of the track. * @cssproperty --track-color - The color of the track. diff --git a/src/components/switch/switch.ts b/src/components/switch/switch.ts index 1b1f526c..fbec2dde 100644 --- a/src/components/switch/switch.ts +++ b/src/components/switch/switch.ts @@ -18,7 +18,7 @@ import styles from './switch.styles'; * @event sl-change - Emitted when the control's checked state changes. * @event sl-focus - Emitted when the control gains focus. * - * @csspart base - The component's base wrapper. + * @csspart base - The component's internal wrapper. * @csspart control - The switch control. * @csspart thumb - The switch position indicator. * @csspart label - The switch label. diff --git a/src/components/tab-group/tab-group.ts b/src/components/tab-group/tab-group.ts index 7d2f5233..7df81963 100644 --- a/src/components/tab-group/tab-group.ts +++ b/src/components/tab-group/tab-group.ts @@ -22,12 +22,15 @@ import styles from './tab-group.styles'; * @event {{ name: String }} sl-tab-show - Emitted when a tab is shown. * @event {{ name: String }} sl-tab-hide - Emitted when a tab is hidden. * - * @csspart base - The component's base wrapper. + * @csspart base - The component's internal wrapper. * @csspart nav - The tab group navigation container. * @csspart tabs - The container that wraps the slotted tabs. * @csspart active-tab-indicator - An element that displays the currently selected tab. This is a child of the tabs container. * @csspart body - The tab group body where tab panels are slotted in. * @csspart scroll-button - The previous and next scroll buttons that appear when tabs are scrollable. + * @csspart scroll-button--start - Targets the starting scroll button. + * @csspart scroll-button--end - Targets the ending scroll button. + * @csspart scroll-button__base - The scroll button's `base` part. * * @cssproperty --indicator-color - The color of the active tab indicator. * @cssproperty --track-color - The color of the indicator's track (i.e. the line that separates tabs from panels). @@ -361,8 +364,9 @@ export default class SlTabGroup extends LitElement { ${this.hasScrollControls ? html`