diff --git a/docs/assets/styles/docs.css b/docs/assets/styles/docs.css index 989a2f39..3afdc528 100644 --- a/docs/assets/styles/docs.css +++ b/docs/assets/styles/docs.css @@ -1059,7 +1059,6 @@ html.sidebar-open #menu-toggle { padding: 0.5rem; margin: 0; cursor: pointer; - transition: 250ms scale ease; } #theme-selector:not(:defined) { @@ -1102,12 +1101,6 @@ html.sidebar-open #menu-toggle { color: var(--sl-color-neutral-1000); } -#icon-toolbar button:hover, -#icon-toolbar a:hover, -#theme-selector sl-button:hover { - scale: 1.1; -} - #icon-toolbar a:not(:last-child), #icon-toolbar button:not(:last-child) { margin-right: 0.25rem; diff --git a/docs/pages/components/checkbox.md b/docs/pages/components/checkbox.md index dd88b3f6..f5197b9b 100644 --- a/docs/pages/components/checkbox.md +++ b/docs/pages/components/checkbox.md @@ -89,6 +89,20 @@ const App = () => ( ); ``` +### Help Text + +Add descriptive help text to a switch with the `help-text` attribute. For help texts that contain HTML, use the `help-text` slot instead. + +```html:preview +Label +``` + +```jsx:react +import SlCheckbox from '@shoelace-style/shoelace/dist/react/checkbox'; + +const App = () => Label; +``` + ### Custom Validity Use the `setCustomValidity()` method to set a custom validation message. This will prevent the form from submitting and make the browser display the error message you provide. To clear the error, call this function with an empty string. diff --git a/docs/pages/components/switch.md b/docs/pages/components/switch.md index 31630c06..194a51cf 100644 --- a/docs/pages/components/switch.md +++ b/docs/pages/components/switch.md @@ -75,6 +75,20 @@ const App = () => ( ); ``` +### Help Text + +Add descriptive help text to a switch with the `help-text` attribute. For help texts that contain HTML, use the `help-text` slot instead. + +```html:preview +Label +``` + +```jsx:react +import SlSwitch from '@shoelace-style/shoelace/dist/react/checkbox'; + +const App = () => Label; +``` + ### Custom Styles Use the available custom properties to change how the switch is styled. diff --git a/docs/pages/resources/changelog.md b/docs/pages/resources/changelog.md index 29cf2233..42aec6e5 100644 --- a/docs/pages/resources/changelog.md +++ b/docs/pages/resources/changelog.md @@ -12,6 +12,15 @@ Components with the Experimental bad New versions of Shoelace are released as-needed and generally occur when a critical mass of changes have accumulated. At any time, you can see what's coming in the next release by visiting [next.shoelace.style](https://next.shoelace.style). +## 2.14.0 + +- Added the Arabic translation [#1852] +- Added help text to `` [#1860] +- Added help text to `` [#1800] +- Fixed a bug in `` that caused HTML tags to be included in `getTextLabel()` +- Fixed a bug in `` that caused slides to not switch correctly [#1862] +- Refactored component styles to be consumed more efficiently [#1692] + ## 2.13.1 - Fixed a bug where the safe triangle was always visible when selecting nested `` elements [#1835] diff --git a/package-lock.json b/package-lock.json index 3b4f2171..11bf225a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,13 +1,12 @@ { "name": "@shoelace-style/shoelace", - "version": "2.13.1", + "version": "2.14.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@shoelace-style/shoelace", - "version": "2.13.1", - "hasInstallScript": true, + "version": "2.14.0", "license": "MIT", "dependencies": { "@ctrl/tinycolor": "^4.0.2", diff --git a/package.json b/package.json index ea058a32..01e3f443 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@shoelace-style/shoelace", "description": "A forward-thinking library of web components.", - "version": "2.13.1", + "version": "2.14.0", "homepage": "https://github.com/shoelace-style/shoelace", "author": "Cory LaViska", "license": "MIT", @@ -49,7 +49,7 @@ "start": "node scripts/build.js --serve", "build": "node scripts/build.js", "verify": "npm run prettier:check && npm run lint && npm run build && npm run test", - "postinstall": "npx playwright install", + "prepare": "npx playwright install", "prepublishOnly": "npm run verify", "prettier": "prettier --write --log-level=warn .", "prettier:check": "prettier --check --log-level=warn .", diff --git a/scripts/plop/templates/component/component.hbs b/scripts/plop/templates/component/component.hbs index a5e752c7..dc49d609 100644 --- a/scripts/plop/templates/component/component.hbs +++ b/scripts/plop/templates/component/component.hbs @@ -2,6 +2,7 @@ import { property } from 'lit/decorators.js'; import { html } from 'lit'; import { LocalizeController } from '../../utilities/localize.js'; import { watch } from '../../internal/watch.js'; +import componentStyles from '../../styles/component.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import styles from './{{ tagWithoutPrefix tag }}.styles.js'; import type { CSSResultGroup } from 'lit'; @@ -24,7 +25,7 @@ import type { CSSResultGroup } from 'lit'; * @cssproperty --example - An example CSS custom property. */ export default class {{ properCase tag }} extends ShoelaceElement { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, styles]; private readonly localize = new LocalizeController(this); diff --git a/scripts/plop/templates/component/styles.hbs b/scripts/plop/templates/component/styles.hbs index 1775f7f7..940a1557 100644 --- a/scripts/plop/templates/component/styles.hbs +++ b/scripts/plop/templates/component/styles.hbs @@ -1,9 +1,6 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; export default css` - ${componentStyles} - :host { display: block; } diff --git a/src/components/alert/alert.component.ts b/src/components/alert/alert.component.ts index 5fd0722c..13d8e52f 100644 --- a/src/components/alert/alert.component.ts +++ b/src/components/alert/alert.component.ts @@ -7,6 +7,7 @@ import { LocalizeController } from '../../utilities/localize.js'; import { property, query } from 'lit/decorators.js'; import { waitForEvent } from '../../internal/event.js'; import { watch } from '../../internal/watch.js'; +import componentStyles from '../../styles/component.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import SlIconButton from '../icon-button/icon-button.component.js'; import styles from './alert.styles.js'; @@ -40,7 +41,7 @@ const toastStack = Object.assign(document.createElement('div'), { className: 'sl * @animation alert.hide - The animation to use when hiding the alert. */ export default class SlAlert extends ShoelaceElement { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, styles]; static dependencies = { 'sl-icon-button': SlIconButton }; private autoHideTimeout: number; diff --git a/src/components/alert/alert.styles.ts b/src/components/alert/alert.styles.ts index eb955cde..884230c5 100644 --- a/src/components/alert/alert.styles.ts +++ b/src/components/alert/alert.styles.ts @@ -1,9 +1,6 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; export default css` - ${componentStyles} - :host { display: contents; diff --git a/src/components/animated-image/animated-image.component.ts b/src/components/animated-image/animated-image.component.ts index d301618d..c5a57474 100644 --- a/src/components/animated-image/animated-image.component.ts +++ b/src/components/animated-image/animated-image.component.ts @@ -1,6 +1,7 @@ import { html } from 'lit'; import { property, query, state } from 'lit/decorators.js'; import { watch } from '../../internal/watch.js'; +import componentStyles from '../../styles/component.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import SlIcon from '../icon/icon.component.js'; import styles from './animated-image.styles.js'; @@ -20,13 +21,13 @@ import type { CSSResultGroup } from 'lit'; * @slot play-icon - Optional play icon to use instead of the default. Works best with ``. * @slot pause-icon - Optional pause icon to use instead of the default. Works best with ``. * - * @part - control-box - The container that surrounds the pause/play icons and provides their background. + * @part control-box - The container that surrounds the pause/play icons and provides their background. * * @cssproperty --control-box-size - The size of the icon box. * @cssproperty --icon-size - The size of the play/pause icons. */ export default class SlAnimatedImage extends ShoelaceElement { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, styles]; static dependencies = { 'sl-icon': SlIcon }; @query('.animated-image__animated') animatedImage: HTMLImageElement; diff --git a/src/components/animated-image/animated-image.styles.ts b/src/components/animated-image/animated-image.styles.ts index 3f326284..a32eda72 100644 --- a/src/components/animated-image/animated-image.styles.ts +++ b/src/components/animated-image/animated-image.styles.ts @@ -1,9 +1,6 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; export default css` - ${componentStyles} - :host { --control-box-size: 3rem; --icon-size: calc(var(--control-box-size) * 0.625); diff --git a/src/components/animation/animation.component.ts b/src/components/animation/animation.component.ts index 96a954e1..3a0d3257 100644 --- a/src/components/animation/animation.component.ts +++ b/src/components/animation/animation.component.ts @@ -2,6 +2,7 @@ import { animations } from './animations.js'; import { html } from 'lit'; import { property, queryAsync } from 'lit/decorators.js'; import { watch } from '../../internal/watch.js'; +import componentStyles from '../../styles/component.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import styles from './animation.styles.js'; import type { CSSResultGroup } from 'lit'; @@ -20,7 +21,7 @@ import type { CSSResultGroup } from 'lit'; * animate multiple elements, either wrap them in a single container or use multiple `` elements. */ export default class SlAnimation extends ShoelaceElement { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, styles]; private animation?: Animation; private hasStarted = false; diff --git a/src/components/animation/animation.styles.ts b/src/components/animation/animation.styles.ts index 674851ee..1ef4bf6f 100644 --- a/src/components/animation/animation.styles.ts +++ b/src/components/animation/animation.styles.ts @@ -1,9 +1,6 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; export default css` - ${componentStyles} - :host { display: contents; } diff --git a/src/components/avatar/avatar.component.ts b/src/components/avatar/avatar.component.ts index 6a37ae5b..7b9285ec 100644 --- a/src/components/avatar/avatar.component.ts +++ b/src/components/avatar/avatar.component.ts @@ -2,6 +2,7 @@ import { classMap } from 'lit/directives/class-map.js'; import { html } from 'lit'; import { property, state } from 'lit/decorators.js'; import { watch } from '../../internal/watch.js'; +import componentStyles from '../../styles/component.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import SlIcon from '../icon/icon.component.js'; import styles from './avatar.styles.js'; @@ -25,7 +26,7 @@ import type { CSSResultGroup } from 'lit'; * @cssproperty --size - The size of the avatar. */ export default class SlAvatar extends ShoelaceElement { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, styles]; static dependencies = { 'sl-icon': SlIcon }; diff --git a/src/components/avatar/avatar.styles.ts b/src/components/avatar/avatar.styles.ts index 45c27df5..a04983ef 100644 --- a/src/components/avatar/avatar.styles.ts +++ b/src/components/avatar/avatar.styles.ts @@ -1,9 +1,6 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; export default css` - ${componentStyles} - :host { display: inline-block; diff --git a/src/components/badge/badge.component.ts b/src/components/badge/badge.component.ts index 9232bf61..7d8f262e 100644 --- a/src/components/badge/badge.component.ts +++ b/src/components/badge/badge.component.ts @@ -1,6 +1,7 @@ import { classMap } from 'lit/directives/class-map.js'; import { html } from 'lit'; import { property } from 'lit/decorators.js'; +import componentStyles from '../../styles/component.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import styles from './badge.styles.js'; import type { CSSResultGroup } from 'lit'; @@ -16,7 +17,7 @@ import type { CSSResultGroup } from 'lit'; * @csspart base - The component's base wrapper. */ export default class SlBadge extends ShoelaceElement { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, styles]; /** The badge's theme variant. */ @property({ reflect: true }) variant: 'primary' | 'success' | 'neutral' | 'warning' | 'danger' = 'primary'; diff --git a/src/components/badge/badge.styles.ts b/src/components/badge/badge.styles.ts index 740e6bd7..8da6ad1a 100644 --- a/src/components/badge/badge.styles.ts +++ b/src/components/badge/badge.styles.ts @@ -1,9 +1,6 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; export default css` - ${componentStyles} - :host { display: inline-flex; } diff --git a/src/components/breadcrumb-item/breadcrumb-item.component.ts b/src/components/breadcrumb-item/breadcrumb-item.component.ts index 53e1a8fe..5c81c15b 100644 --- a/src/components/breadcrumb-item/breadcrumb-item.component.ts +++ b/src/components/breadcrumb-item/breadcrumb-item.component.ts @@ -3,6 +3,7 @@ import { HasSlotController } from '../../internal/slot.js'; import { html } from 'lit'; import { ifDefined } from 'lit/directives/if-defined.js'; import { property } from 'lit/decorators.js'; +import componentStyles from '../../styles/component.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import styles from './breadcrumb-item.styles.js'; import type { CSSResultGroup } from 'lit'; @@ -26,7 +27,7 @@ import type { CSSResultGroup } from 'lit'; * @csspart separator - The container that wraps the separator. */ export default class SlBreadcrumbItem extends ShoelaceElement { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, styles]; private readonly hasSlotController = new HasSlotController(this, 'prefix', 'suffix'); diff --git a/src/components/breadcrumb-item/breadcrumb-item.styles.ts b/src/components/breadcrumb-item/breadcrumb-item.styles.ts index fcf1f211..f6c5ca60 100644 --- a/src/components/breadcrumb-item/breadcrumb-item.styles.ts +++ b/src/components/breadcrumb-item/breadcrumb-item.styles.ts @@ -1,9 +1,6 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; export default css` - ${componentStyles} - :host { display: inline-flex; } diff --git a/src/components/breadcrumb/breadcrumb.component.ts b/src/components/breadcrumb/breadcrumb.component.ts index fb481aca..4f314935 100644 --- a/src/components/breadcrumb/breadcrumb.component.ts +++ b/src/components/breadcrumb/breadcrumb.component.ts @@ -1,6 +1,7 @@ import { html } from 'lit'; import { LocalizeController } from '../../utilities/localize.js'; import { property, query } from 'lit/decorators.js'; +import componentStyles from '../../styles/component.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import SlIcon from '../icon/icon.component.js'; import styles from './breadcrumb.styles.js'; @@ -21,7 +22,7 @@ import type SlBreadcrumbItem from '../breadcrumb-item/breadcrumb-item.js'; * @csspart base - The component's base wrapper. */ export default class SlBreadcrumb extends ShoelaceElement { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, styles]; static dependencies = { 'sl-icon': SlIcon }; private readonly localize = new LocalizeController(this); diff --git a/src/components/breadcrumb/breadcrumb.styles.ts b/src/components/breadcrumb/breadcrumb.styles.ts index 8974f84a..86c0e16e 100644 --- a/src/components/breadcrumb/breadcrumb.styles.ts +++ b/src/components/breadcrumb/breadcrumb.styles.ts @@ -1,9 +1,6 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; export default css` - ${componentStyles} - .breadcrumb { display: flex; align-items: center; diff --git a/src/components/button-group/button-group.component.ts b/src/components/button-group/button-group.component.ts index 84328a78..0c7d1ca6 100644 --- a/src/components/button-group/button-group.component.ts +++ b/src/components/button-group/button-group.component.ts @@ -1,5 +1,6 @@ import { html } from 'lit'; import { property, query, state } from 'lit/decorators.js'; +import componentStyles from '../../styles/component.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import styles from './button-group.styles.js'; import type { CSSResultGroup } from 'lit'; @@ -15,7 +16,7 @@ import type { CSSResultGroup } from 'lit'; * @csspart base - The component's base wrapper. */ export default class SlButtonGroup extends ShoelaceElement { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, styles]; @query('slot') defaultSlot: HTMLSlotElement; diff --git a/src/components/button-group/button-group.styles.ts b/src/components/button-group/button-group.styles.ts index 868f5a83..89e6de8d 100644 --- a/src/components/button-group/button-group.styles.ts +++ b/src/components/button-group/button-group.styles.ts @@ -1,9 +1,6 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; export default css` - ${componentStyles} - :host { display: inline-block; } diff --git a/src/components/button/button.component.ts b/src/components/button/button.component.ts index 262dcd72..54ecbb03 100644 --- a/src/components/button/button.component.ts +++ b/src/components/button/button.component.ts @@ -6,6 +6,7 @@ import { ifDefined } from 'lit/directives/if-defined.js'; import { LocalizeController } from '../../utilities/localize.js'; import { property, query, state } from 'lit/decorators.js'; import { watch } from '../../internal/watch.js'; +import componentStyles from '../../styles/component.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import SlIcon from '../icon/icon.component.js'; import SlSpinner from '../spinner/spinner.component.js'; @@ -38,7 +39,7 @@ import type { ShoelaceFormControl } from '../../internal/shoelace-element.js'; * @csspart spinner - The spinner that shows when the button is in the loading state. */ export default class SlButton extends ShoelaceElement implements ShoelaceFormControl { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, styles]; static dependencies = { 'sl-icon': SlIcon, 'sl-spinner': SlSpinner diff --git a/src/components/button/button.styles.ts b/src/components/button/button.styles.ts index 73016b3d..c69ef200 100644 --- a/src/components/button/button.styles.ts +++ b/src/components/button/button.styles.ts @@ -1,9 +1,6 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; export default css` - ${componentStyles} - :host { display: inline-block; position: relative; diff --git a/src/components/card/card.component.ts b/src/components/card/card.component.ts index e9071906..3890cd98 100644 --- a/src/components/card/card.component.ts +++ b/src/components/card/card.component.ts @@ -1,6 +1,7 @@ import { classMap } from 'lit/directives/class-map.js'; import { HasSlotController } from '../../internal/slot.js'; import { html } from 'lit'; +import componentStyles from '../../styles/component.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import styles from './card.styles.js'; import type { CSSResultGroup } from 'lit'; @@ -28,7 +29,7 @@ import type { CSSResultGroup } from 'lit'; * @cssproperty --padding - The padding to use for the card's sections. */ export default class SlCard extends ShoelaceElement { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, styles]; private readonly hasSlotController = new HasSlotController(this, 'footer', 'header', 'image'); diff --git a/src/components/card/card.styles.ts b/src/components/card/card.styles.ts index b334c126..9671516c 100644 --- a/src/components/card/card.styles.ts +++ b/src/components/card/card.styles.ts @@ -1,9 +1,6 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; export default css` - ${componentStyles} - :host { --border-color: var(--sl-color-neutral-200); --border-radius: var(--sl-border-radius-medium); diff --git a/src/components/carousel-item/carousel-item.component.ts b/src/components/carousel-item/carousel-item.component.ts index 274c5f59..7ef2ba16 100644 --- a/src/components/carousel-item/carousel-item.component.ts +++ b/src/components/carousel-item/carousel-item.component.ts @@ -1,4 +1,5 @@ import { html } from 'lit'; +import componentStyles from '../../styles/component.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import styles from './carousel-item.styles.js'; import type { CSSResultGroup } from 'lit'; @@ -15,7 +16,7 @@ import type { CSSResultGroup } from 'lit'; * */ export default class SlCarouselItem extends ShoelaceElement { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, styles]; connectedCallback() { super.connectedCallback(); diff --git a/src/components/carousel-item/carousel-item.styles.ts b/src/components/carousel-item/carousel-item.styles.ts index 4a505374..11e07af3 100644 --- a/src/components/carousel-item/carousel-item.styles.ts +++ b/src/components/carousel-item/carousel-item.styles.ts @@ -1,9 +1,6 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; export default css` - ${componentStyles} - :host { --aspect-ratio: inherit; diff --git a/src/components/carousel/carousel.component.ts b/src/components/carousel/carousel.component.ts index 5e186fc9..21f47bd7 100644 --- a/src/components/carousel/carousel.component.ts +++ b/src/components/carousel/carousel.component.ts @@ -11,6 +11,7 @@ import { prefersReducedMotion } from '../../internal/animate.js'; import { range } from 'lit/directives/range.js'; import { waitForEvent } from '../../internal/event.js'; import { watch } from '../../internal/watch.js'; +import componentStyles from '../../styles/component.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import SlIcon from '../icon/icon.component.js'; import styles from './carousel.styles.js'; @@ -47,7 +48,7 @@ import type SlCarouselItem from '../carousel-item/carousel-item.component.js'; * partially visible as a scroll hint. */ export default class SlCarousel extends ShoelaceElement { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, styles]; static dependencies = { 'sl-icon': SlIcon }; /** When set, allows the user to navigate the carousel in the same direction indefinitely. */ @@ -476,7 +477,7 @@ export default class SlCarousel extends ShoelaceElement { this.scrollToSlide(nextSlide, prefersReducedMotion() ? 'auto' : behavior); } - private async scrollToSlide(slide: HTMLElement, behavior: ScrollBehavior = 'smooth') { + private scrollToSlide(slide: HTMLElement, behavior: ScrollBehavior = 'smooth') { const scrollContainer = this.scrollContainer; const scrollContainerRect = scrollContainer.getBoundingClientRect(); const nextSlideRect = slide.getBoundingClientRect(); @@ -484,16 +485,11 @@ export default class SlCarousel extends ShoelaceElement { const nextLeft = nextSlideRect.left - scrollContainerRect.left; const nextTop = nextSlideRect.top - scrollContainerRect.top; - // If the slide is already in view, don't need to scroll - if (nextLeft !== scrollContainer.scrollLeft || nextTop !== scrollContainer.scrollTop) { - scrollContainer.scrollTo({ - left: nextLeft + scrollContainer.scrollLeft, - top: nextTop + scrollContainer.scrollTop, - behavior - }); - - await waitForEvent(scrollContainer, 'scrollend'); - } + scrollContainer.scrollTo({ + left: nextLeft + scrollContainer.scrollLeft, + top: nextTop + scrollContainer.scrollTop, + behavior + }); } render() { diff --git a/src/components/carousel/carousel.styles.ts b/src/components/carousel/carousel.styles.ts index a26c9446..33ee20eb 100644 --- a/src/components/carousel/carousel.styles.ts +++ b/src/components/carousel/carousel.styles.ts @@ -1,9 +1,6 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; export default css` - ${componentStyles} - :host { --slide-gap: var(--sl-spacing-medium, 1rem); --aspect-ratio: 16 / 9; diff --git a/src/components/carousel/carousel.test.ts b/src/components/carousel/carousel.test.ts index 42d693a7..01cfc8d1 100644 --- a/src/components/carousel/carousel.test.ts +++ b/src/components/carousel/carousel.test.ts @@ -1,6 +1,6 @@ import '../../../dist/shoelace.js'; import { clickOnElement, dragElement, moveMouseOnElement } from '../../internal/test.js'; -import { expect, fixture, html, oneEvent } from '@open-wc/testing'; +import { expect, fixture, html, nextFrame, oneEvent } from '@open-wc/testing'; import { map } from 'lit/directives/map.js'; import { range } from 'lit/directives/range.js'; import { resetMouse } from '@web/test-runner-commands'; @@ -8,10 +8,16 @@ import sinon from 'sinon'; import type SlCarousel from './carousel.js'; describe('', () => { + const sandbox = sinon.createSandbox(); + afterEach(async () => { await resetMouse(); }); + afterEach(() => { + sandbox.restore(); + }); + it('should render a carousel with default configuration', async () => { // Arrange const el = await fixture(html` @@ -34,15 +40,11 @@ describe('', () => { let clock: sinon.SinonFakeTimers; beforeEach(() => { - clock = sinon.useFakeTimers({ + clock = sandbox.useFakeTimers({ now: new Date() }); }); - afterEach(() => { - clock.restore(); - }); - it('should scroll forwards every `autoplay-interval` milliseconds', async () => { // Arrange const el = await fixture(html` @@ -52,7 +54,7 @@ describe('', () => { Node 3 `); - sinon.stub(el, 'next'); + sandbox.stub(el, 'next'); await el.updateComplete; @@ -73,7 +75,7 @@ describe('', () => { Node 3 `); - sinon.stub(el, 'next'); + sandbox.stub(el, 'next'); await el.updateComplete; @@ -96,7 +98,7 @@ describe('', () => { Node 3 `); - sinon.stub(el, 'next'); + sandbox.stub(el, 'next'); await el.updateComplete; @@ -183,7 +185,7 @@ describe('', () => { Node 3 `); - sinon.stub(el, 'goToSlide'); + sandbox.stub(el, 'goToSlide'); await el.updateComplete; // Act @@ -473,7 +475,7 @@ describe('', () => { `); const nextButton: HTMLElement = el.shadowRoot!.querySelector('.carousel__navigation-button--next')!; - sinon.stub(el, 'next'); + sandbox.stub(el, 'next'); await el.updateComplete; @@ -496,7 +498,7 @@ describe('', () => { `); const nextButton: HTMLElement = el.shadowRoot!.querySelector('.carousel__navigation-button--next')!; - sinon.stub(el, 'next'); + sandbox.stub(el, 'next'); el.goToSlide(2, 'auto'); await oneEvent(el.scrollContainer, 'scrollend'); @@ -560,7 +562,7 @@ describe('', () => { await el.updateComplete; const previousButton: HTMLElement = el.shadowRoot!.querySelector('.carousel__navigation-button--previous')!; - sinon.stub(el, 'previous'); + sandbox.stub(el, 'previous'); await el.updateComplete; @@ -584,7 +586,7 @@ describe('', () => { `); const previousButton: HTMLElement = el.shadowRoot!.querySelector('.carousel__navigation-button--previous')!; - sinon.stub(el, 'previous'); + sandbox.stub(el, 'previous'); await el.updateComplete; // Act @@ -632,19 +634,27 @@ describe('', () => { it('should scroll the carousel to the next slide', async () => { // Arrange const el = await fixture(html` - + Node 1 Node 2 Node 3 `); - sinon.stub(el, 'goToSlide'); - await el.updateComplete; + sandbox.spy(el, 'goToSlide'); + const expectedCarouselItem: HTMLElement = el.querySelector('sl-carousel-item:nth-child(2)')!; // Act el.next(); + await oneEvent(el.scrollContainer, 'scrollend'); + await el.updateComplete; - expect(el.goToSlide).to.have.been.calledWith(2); + const containerRect = el.scrollContainer.getBoundingClientRect(); + const itemRect = expectedCarouselItem.getBoundingClientRect(); + + // Assert + expect(el.goToSlide).to.have.been.calledWith(1); + expect(itemRect.top).to.be.equal(containerRect.top); + expect(itemRect.left).to.be.equal(containerRect.left); }); }); @@ -652,19 +662,32 @@ describe('', () => { it('should scroll the carousel to the previous slide', async () => { // Arrange const el = await fixture(html` - + Node 1 Node 2 Node 3 `); - sinon.stub(el, 'goToSlide'); - await el.updateComplete; + const expectedCarouselItem: HTMLElement = el.querySelector('sl-carousel-item:nth-child(1)')!; + + el.goToSlide(1); + + await oneEvent(el.scrollContainer, 'scrollend'); + await nextFrame(); + + sandbox.spy(el, 'goToSlide'); // Act el.previous(); + await oneEvent(el.scrollContainer, 'scrollend'); - expect(el.goToSlide).to.have.been.calledWith(-2); + const containerRect = el.scrollContainer.getBoundingClientRect(); + const itemRect = expectedCarouselItem.getBoundingClientRect(); + + // Assert + expect(el.goToSlide).to.have.been.calledWith(0); + expect(itemRect.top).to.be.equal(containerRect.top); + expect(itemRect.left).to.be.equal(containerRect.left); }); }); diff --git a/src/components/checkbox/checkbox.component.ts b/src/components/checkbox/checkbox.component.ts index bb37a5a4..903d13f0 100644 --- a/src/components/checkbox/checkbox.component.ts +++ b/src/components/checkbox/checkbox.component.ts @@ -1,11 +1,13 @@ import { classMap } from 'lit/directives/class-map.js'; import { defaultValue } from '../../internal/default-value.js'; import { FormControlController } from '../../internal/form.js'; +import { HasSlotController } from '../../internal/slot.js'; import { html } from 'lit'; import { ifDefined } from 'lit/directives/if-defined.js'; import { live } from 'lit/directives/live.js'; import { property, query, state } from 'lit/decorators.js'; import { watch } from '../../internal/watch.js'; +import componentStyles from '../../styles/component.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import SlIcon from '../icon/icon.component.js'; import styles from './checkbox.styles.js'; @@ -21,6 +23,7 @@ import type { ShoelaceFormControl } from '../../internal/shoelace-element.js'; * @dependency sl-icon * * @slot - The checkbox's label. + * @slot help-text - Text that describes how to use the checkbox. Alternatively, you can use the `help-text` attribute. * * @event sl-blur - Emitted when the checkbox loses focus. * @event sl-change - Emitted when the checked state changes. @@ -35,9 +38,10 @@ import type { ShoelaceFormControl } from '../../internal/shoelace-element.js'; * @csspart checked-icon - The checked icon, an `` element. * @csspart indeterminate-icon - The indeterminate icon, an `` element. * @csspart label - The container that wraps the checkbox's label. + * @csspart form-control-help-text - The help text's wrapper. */ export default class SlCheckbox extends ShoelaceElement implements ShoelaceFormControl { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, styles]; static dependencies = { 'sl-icon': SlIcon }; private readonly formControlController = new FormControlController(this, { @@ -45,6 +49,7 @@ export default class SlCheckbox extends ShoelaceElement implements ShoelaceFormC defaultValue: (control: SlCheckbox) => control.defaultChecked, setValue: (control: SlCheckbox, checked: boolean) => (control.checked = checked) }); + private readonly hasSlotController = new HasSlotController(this, 'help-text'); @query('input[type="checkbox"]') input: HTMLInputElement; @@ -86,6 +91,9 @@ export default class SlCheckbox extends ShoelaceElement implements ShoelaceFormC /** Makes the checkbox a required field. */ @property({ type: Boolean, reflect: true }) required = false; + /** The checkbox's help text. If you need to display HTML, use the `help-text` slot instead. */ + @property({ attribute: 'help-text' }) helpText = ''; + /** Gets the validity state object */ get validity() { return this.input.validity; @@ -178,68 +186,93 @@ export default class SlCheckbox extends ShoelaceElement implements ShoelaceFormC } render() { + const hasHelpTextSlot = this.hasSlotController.test('help-text'); + const hasHelpText = this.helpText ? true : !!hasHelpTextSlot; + // // NOTE: we use a around the label slot because of this Chrome bug. // // https://bugs.chromium.org/p/chromium/issues/detail?id=1413733 // return html` - - - - - ${this.checked - ? html` - - ` - : ''} - ${!this.checked && this.indeterminate - ? html` - - ` - : ''} - + - - + + ${this.checked + ? html` + + ` + : ''} + ${!this.checked && this.indeterminate + ? html` + + ` + : ''} + + + + + + + + + ${this.helpText} - + `; } } diff --git a/src/components/checkbox/checkbox.styles.ts b/src/components/checkbox/checkbox.styles.ts index ce8a93ab..7dc0eceb 100644 --- a/src/components/checkbox/checkbox.styles.ts +++ b/src/components/checkbox/checkbox.styles.ts @@ -1,9 +1,6 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; export default css` - ${componentStyles} - :host { display: inline-block; } diff --git a/src/components/checkbox/checkbox.test.ts b/src/components/checkbox/checkbox.test.ts index 2757fde4..0a05a65b 100644 --- a/src/components/checkbox/checkbox.test.ts +++ b/src/components/checkbox/checkbox.test.ts @@ -23,6 +23,7 @@ describe('', () => { expect(el.checked).to.be.false; expect(el.indeterminate).to.be.false; expect(el.defaultChecked).to.be.false; + expect(el.helpText).to.equal(''); }); it('should have title if title attribute is set', async () => { diff --git a/src/components/color-picker/color-picker.component.ts b/src/components/color-picker/color-picker.component.ts index ae361e1d..a56aebfa 100644 --- a/src/components/color-picker/color-picker.component.ts +++ b/src/components/color-picker/color-picker.component.ts @@ -10,6 +10,7 @@ import { property, query, state } from 'lit/decorators.js'; import { styleMap } from 'lit/directives/style-map.js'; import { TinyColor } from '@ctrl/tinycolor'; import { watch } from '../../internal/watch.js'; +import componentStyles from '../../styles/component.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import SlButton from '../button/button.component.js'; import SlButtonGroup from '../button-group/button-group.component.js'; @@ -90,7 +91,7 @@ declare const EyeDropper: EyeDropperConstructor; * @cssproperty --swatch-size - The size of each predefined color swatch. */ export default class SlColorPicker extends ShoelaceElement implements ShoelaceFormControl { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, styles]; static dependencies = { 'sl-button-group': SlButtonGroup, diff --git a/src/components/color-picker/color-picker.styles.ts b/src/components/color-picker/color-picker.styles.ts index 88d78189..364b6761 100644 --- a/src/components/color-picker/color-picker.styles.ts +++ b/src/components/color-picker/color-picker.styles.ts @@ -1,9 +1,6 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; export default css` - ${componentStyles} - :host { --grid-width: 280px; --grid-height: 200px; diff --git a/src/components/copy-button/copy-button.component.ts b/src/components/copy-button/copy-button.component.ts index 84e3921b..cdcbbd80 100644 --- a/src/components/copy-button/copy-button.component.ts +++ b/src/components/copy-button/copy-button.component.ts @@ -3,6 +3,7 @@ import { getAnimation, setDefaultAnimation } from '../../utilities/animation-reg import { html } from 'lit'; import { LocalizeController } from '../../utilities/localize.js'; import { property, query, state } from 'lit/decorators.js'; +import componentStyles from '../../styles/component.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import SlIcon from '../icon/icon.component.js'; import SlTooltip from '../tooltip/tooltip.component.js'; @@ -41,7 +42,7 @@ import type { CSSResultGroup } from 'lit'; * @animation copy.out - The animation to use when feedback icons animate out. */ export default class SlCopyButton extends ShoelaceElement { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, styles]; static dependencies = { 'sl-icon': SlIcon, 'sl-tooltip': SlTooltip diff --git a/src/components/copy-button/copy-button.styles.ts b/src/components/copy-button/copy-button.styles.ts index 29cd4cfb..17f4ddb6 100644 --- a/src/components/copy-button/copy-button.styles.ts +++ b/src/components/copy-button/copy-button.styles.ts @@ -1,9 +1,6 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; export default css` - ${componentStyles} - :host { --error-color: var(--sl-color-danger-600); --success-color: var(--sl-color-success-600); diff --git a/src/components/details/details.component.ts b/src/components/details/details.component.ts index d8b83a43..4e9df5c9 100644 --- a/src/components/details/details.component.ts +++ b/src/components/details/details.component.ts @@ -6,6 +6,7 @@ import { LocalizeController } from '../../utilities/localize.js'; import { property, query } from 'lit/decorators.js'; import { waitForEvent } from '../../internal/event.js'; import { watch } from '../../internal/watch.js'; +import componentStyles from '../../styles/component.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import SlIcon from '../icon/icon.component.js'; import styles from './details.styles.js'; @@ -39,7 +40,7 @@ import type { CSSResultGroup } from 'lit'; * @animation details.hide - The animation to use when hiding details. You can use `height: auto` with this animation. */ export default class SlDetails extends ShoelaceElement { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, styles]; static dependencies = { 'sl-icon': SlIcon diff --git a/src/components/details/details.styles.ts b/src/components/details/details.styles.ts index 9f77a551..2fdb0e13 100644 --- a/src/components/details/details.styles.ts +++ b/src/components/details/details.styles.ts @@ -1,9 +1,6 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; export default css` - ${componentStyles} - :host { display: block; } diff --git a/src/components/dialog/dialog.component.ts b/src/components/dialog/dialog.component.ts index d55a07c3..0d6c5505 100644 --- a/src/components/dialog/dialog.component.ts +++ b/src/components/dialog/dialog.component.ts @@ -9,6 +9,7 @@ import { lockBodyScrolling, unlockBodyScrolling } from '../../internal/scroll.js import { property, query } from 'lit/decorators.js'; import { waitForEvent } from '../../internal/event.js'; import { watch } from '../../internal/watch.js'; +import componentStyles from '../../styles/component.styles.js'; import Modal from '../../internal/modal.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import SlIconButton from '../icon-button/icon-button.component.js'; @@ -66,7 +67,7 @@ import type { CSSResultGroup } from 'lit'; * the third-party modal opens. Upon closing, call `modal.deactivateExternal()` to restore Shoelace's focus trapping. */ export default class SlDialog extends ShoelaceElement { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, styles]; static dependencies = { 'sl-icon-button': SlIconButton }; diff --git a/src/components/dialog/dialog.styles.ts b/src/components/dialog/dialog.styles.ts index 8202a892..bf8a0352 100644 --- a/src/components/dialog/dialog.styles.ts +++ b/src/components/dialog/dialog.styles.ts @@ -1,9 +1,6 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; export default css` - ${componentStyles} - :host { --width: 31rem; --header-spacing: var(--sl-spacing-large); diff --git a/src/components/divider/divider.component.ts b/src/components/divider/divider.component.ts index fad68a03..d6a6b4be 100644 --- a/src/components/divider/divider.component.ts +++ b/src/components/divider/divider.component.ts @@ -1,5 +1,6 @@ import { property } from 'lit/decorators.js'; import { watch } from '../../internal/watch.js'; +import componentStyles from '../../styles/component.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import styles from './divider.styles.js'; import type { CSSResultGroup } from 'lit'; @@ -15,7 +16,7 @@ import type { CSSResultGroup } from 'lit'; * @cssproperty --spacing - The spacing of the divider. */ export default class SlDivider extends ShoelaceElement { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, styles]; /** Draws the divider in a vertical orientation. */ @property({ type: Boolean, reflect: true }) vertical = false; diff --git a/src/components/divider/divider.styles.ts b/src/components/divider/divider.styles.ts index 8c750961..ac44b628 100644 --- a/src/components/divider/divider.styles.ts +++ b/src/components/divider/divider.styles.ts @@ -1,9 +1,6 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; export default css` - ${componentStyles} - :host { --color: var(--sl-panel-border-color); --width: var(--sl-panel-border-width); diff --git a/src/components/drawer/drawer.component.ts b/src/components/drawer/drawer.component.ts index fa08c472..19365143 100644 --- a/src/components/drawer/drawer.component.ts +++ b/src/components/drawer/drawer.component.ts @@ -10,6 +10,7 @@ import { property, query } from 'lit/decorators.js'; import { uppercaseFirstLetter } from '../../internal/string.js'; import { waitForEvent } from '../../internal/event.js'; import { watch } from '../../internal/watch.js'; +import componentStyles from '../../styles/component.styles.js'; import Modal from '../../internal/modal.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import SlIconButton from '../icon-button/icon-button.component.js'; @@ -74,7 +75,7 @@ import type { CSSResultGroup } from 'lit'; * the third-party modal opens. Upon closing, call `modal.deactivateExternal()` to restore Shoelace's focus trapping. */ export default class SlDrawer extends ShoelaceElement { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, styles]; static dependencies = { 'sl-icon-button': SlIconButton }; private readonly hasSlotController = new HasSlotController(this, 'footer'); diff --git a/src/components/drawer/drawer.styles.ts b/src/components/drawer/drawer.styles.ts index 99b49c24..bce0f03f 100644 --- a/src/components/drawer/drawer.styles.ts +++ b/src/components/drawer/drawer.styles.ts @@ -1,9 +1,6 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; export default css` - ${componentStyles} - :host { --size: 25rem; --header-spacing: var(--sl-spacing-large); diff --git a/src/components/dropdown/dropdown.component.ts b/src/components/dropdown/dropdown.component.ts index 2d8f778a..84bdcf89 100644 --- a/src/components/dropdown/dropdown.component.ts +++ b/src/components/dropdown/dropdown.component.ts @@ -7,6 +7,7 @@ import { LocalizeController } from '../../utilities/localize.js'; import { property, query } from 'lit/decorators.js'; import { waitForEvent } from '../../internal/event.js'; import { watch } from '../../internal/watch.js'; +import componentStyles from '../../styles/component.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import SlPopup from '../popup/popup.component.js'; import styles from './dropdown.styles.js'; @@ -40,7 +41,7 @@ import type SlMenu from '../menu/menu.js'; * @animation dropdown.hide - The animation to use when hiding the dropdown. */ export default class SlDropdown extends ShoelaceElement { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, styles]; static dependencies = { 'sl-popup': SlPopup }; @query('.dropdown') popup: SlPopup; diff --git a/src/components/dropdown/dropdown.styles.ts b/src/components/dropdown/dropdown.styles.ts index 79b74981..30f387a3 100644 --- a/src/components/dropdown/dropdown.styles.ts +++ b/src/components/dropdown/dropdown.styles.ts @@ -1,9 +1,6 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; export default css` - ${componentStyles} - :host { display: inline-block; } diff --git a/src/components/icon-button/icon-button.component.ts b/src/components/icon-button/icon-button.component.ts index 26824696..587f19a3 100644 --- a/src/components/icon-button/icon-button.component.ts +++ b/src/components/icon-button/icon-button.component.ts @@ -2,6 +2,7 @@ import { classMap } from 'lit/directives/class-map.js'; import { html, literal } from 'lit/static-html.js'; import { ifDefined } from 'lit/directives/if-defined.js'; import { property, query, state } from 'lit/decorators.js'; +import componentStyles from '../../styles/component.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import SlIcon from '../icon/icon.component.js'; import styles from './icon-button.styles.js'; @@ -21,7 +22,7 @@ import type { CSSResultGroup } from 'lit'; * @csspart base - The component's base wrapper. */ export default class SlIconButton extends ShoelaceElement { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, styles]; static dependencies = { 'sl-icon': SlIcon }; @query('.icon-button') button: HTMLButtonElement | HTMLLinkElement; diff --git a/src/components/icon-button/icon-button.styles.ts b/src/components/icon-button/icon-button.styles.ts index fadb11d9..6414cc7a 100644 --- a/src/components/icon-button/icon-button.styles.ts +++ b/src/components/icon-button/icon-button.styles.ts @@ -1,9 +1,6 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; export default css` - ${componentStyles} - :host { display: inline-block; color: var(--sl-color-neutral-600); diff --git a/src/components/icon/icon.component.ts b/src/components/icon/icon.component.ts index 542ede6e..69ee3b03 100644 --- a/src/components/icon/icon.component.ts +++ b/src/components/icon/icon.component.ts @@ -3,9 +3,9 @@ import { html } from 'lit'; import { isTemplateResult } from 'lit/directive-helpers.js'; import { property, state } from 'lit/decorators.js'; import { watch } from '../../internal/watch.js'; +import componentStyles from '../../styles/component.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import styles from './icon.styles.js'; - import type { CSSResultGroup, HTMLTemplateResult } from 'lit'; const CACHEABLE_ERROR = Symbol(); @@ -33,7 +33,7 @@ interface IconSource { * @csspart use - The element generated when using `spriteSheet: true` */ export default class SlIcon extends ShoelaceElement { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, styles]; private initialRender = false; diff --git a/src/components/icon/icon.styles.ts b/src/components/icon/icon.styles.ts index 85c3a19c..4e550328 100644 --- a/src/components/icon/icon.styles.ts +++ b/src/components/icon/icon.styles.ts @@ -1,9 +1,6 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; export default css` - ${componentStyles} - :host { display: inline-block; width: 1em; diff --git a/src/components/image-comparer/image-comparer.component.ts b/src/components/image-comparer/image-comparer.component.ts index 616e6f0a..9f9cebf9 100644 --- a/src/components/image-comparer/image-comparer.component.ts +++ b/src/components/image-comparer/image-comparer.component.ts @@ -6,6 +6,7 @@ import { LocalizeController } from '../../utilities/localize.js'; import { property, query } from 'lit/decorators.js'; import { styleMap } from 'lit/directives/style-map.js'; import { watch } from '../../internal/watch.js'; +import componentStyles from '../../styles/component.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import SlIcon from '../icon/icon.component.js'; import styles from './image-comparer.styles.js'; @@ -35,7 +36,7 @@ import type { CSSResultGroup } from 'lit'; * @cssproperty --handle-size - The size of the compare handle. */ export default class SlImageComparer extends ShoelaceElement { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, styles]; static scopedElement = { 'sl-icon': SlIcon }; private readonly localize = new LocalizeController(this); diff --git a/src/components/image-comparer/image-comparer.styles.ts b/src/components/image-comparer/image-comparer.styles.ts index 0571c96e..d9f45f93 100644 --- a/src/components/image-comparer/image-comparer.styles.ts +++ b/src/components/image-comparer/image-comparer.styles.ts @@ -1,9 +1,6 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; export default css` - ${componentStyles} - :host { --divider-width: 2px; --handle-size: 2.5rem; diff --git a/src/components/include/include.component.ts b/src/components/include/include.component.ts index 8cb21468..d4dbb2ab 100644 --- a/src/components/include/include.component.ts +++ b/src/components/include/include.component.ts @@ -2,6 +2,7 @@ import { html } from 'lit'; import { property } from 'lit/decorators.js'; import { requestInclude } from './request.js'; import { watch } from '../../internal/watch.js'; +import componentStyles from '../../styles/component.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import styles from './include.styles.js'; import type { CSSResultGroup } from 'lit'; @@ -16,7 +17,7 @@ import type { CSSResultGroup } from 'lit'; * @event {{ status: number }} sl-error - Emitted when the included file fails to load due to an error. */ export default class SlInclude extends ShoelaceElement { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, styles]; /** * The location of the HTML file to include. Be sure you trust the content you are including as it will be executed as diff --git a/src/components/include/include.styles.ts b/src/components/include/include.styles.ts index 1775f7f7..940a1557 100644 --- a/src/components/include/include.styles.ts +++ b/src/components/include/include.styles.ts @@ -1,9 +1,6 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; export default css` - ${componentStyles} - :host { display: block; } diff --git a/src/components/input/input.component.ts b/src/components/input/input.component.ts index 53d619df..84083969 100644 --- a/src/components/input/input.component.ts +++ b/src/components/input/input.component.ts @@ -8,6 +8,8 @@ import { live } from 'lit/directives/live.js'; import { LocalizeController } from '../../utilities/localize.js'; import { property, query, state } from 'lit/decorators.js'; import { watch } from '../../internal/watch.js'; +import componentStyles from '../../styles/component.styles.js'; +import formControlStyles from '../../styles/form-control.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import SlIcon from '../icon/icon.component.js'; import styles from './input.styles.js'; @@ -49,7 +51,7 @@ import type { ShoelaceFormControl } from '../../internal/shoelace-element.js'; * @csspart suffix - The container that wraps the suffix. */ export default class SlInput extends ShoelaceElement implements ShoelaceFormControl { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, formControlStyles, styles]; static dependencies = { 'sl-icon': SlIcon }; private readonly formControlController = new FormControlController(this, { diff --git a/src/components/input/input.styles.ts b/src/components/input/input.styles.ts index f1fdff47..ba7415da 100644 --- a/src/components/input/input.styles.ts +++ b/src/components/input/input.styles.ts @@ -1,11 +1,6 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; -import formControlStyles from '../../styles/form-control.styles.js'; export default css` - ${componentStyles} - ${formControlStyles} - :host { display: block; } diff --git a/src/components/menu-item/menu-item.component.ts b/src/components/menu-item/menu-item.component.ts index adb492b7..c228f574 100644 --- a/src/components/menu-item/menu-item.component.ts +++ b/src/components/menu-item/menu-item.component.ts @@ -5,6 +5,7 @@ import { LocalizeController } from '../../utilities/localize.js'; import { property, query } from 'lit/decorators.js'; import { SubmenuController } from './submenu-controller.js'; import { watch } from '../../internal/watch.js'; +import componentStyles from '../../styles/component.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import SlIcon from '../icon/icon.component.js'; import SlPopup from '../popup/popup.component.js'; @@ -39,7 +40,7 @@ import type { CSSResultGroup } from 'lit'; * @cssproperty [--submenu-offset=-2px] - The distance submenus shift to overlap the parent menu. */ export default class SlMenuItem extends ShoelaceElement { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, styles]; static dependencies = { 'sl-icon': SlIcon, 'sl-popup': SlPopup, diff --git a/src/components/menu-item/menu-item.styles.ts b/src/components/menu-item/menu-item.styles.ts index b8afd7a1..91899489 100644 --- a/src/components/menu-item/menu-item.styles.ts +++ b/src/components/menu-item/menu-item.styles.ts @@ -1,9 +1,6 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; export default css` - ${componentStyles} - :host { --submenu-offset: -2px; diff --git a/src/components/menu-label/menu-label.component.ts b/src/components/menu-label/menu-label.component.ts index 1a8d4b8f..4ff7881b 100644 --- a/src/components/menu-label/menu-label.component.ts +++ b/src/components/menu-label/menu-label.component.ts @@ -1,4 +1,5 @@ import { html } from 'lit'; +import componentStyles from '../../styles/component.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import styles from './menu-label.styles.js'; import type { CSSResultGroup } from 'lit'; @@ -14,7 +15,7 @@ import type { CSSResultGroup } from 'lit'; * @csspart base - The component's base wrapper. */ export default class SlMenuLabel extends ShoelaceElement { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, styles]; render() { return html` `; diff --git a/src/components/menu-label/menu-label.styles.ts b/src/components/menu-label/menu-label.styles.ts index 1e2bafb2..e2fe0c4b 100644 --- a/src/components/menu-label/menu-label.styles.ts +++ b/src/components/menu-label/menu-label.styles.ts @@ -1,9 +1,5 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; - export default css` - ${componentStyles} - :host { display: block; } diff --git a/src/components/menu/menu.component.ts b/src/components/menu/menu.component.ts index 879d033d..c37e2ad9 100644 --- a/src/components/menu/menu.component.ts +++ b/src/components/menu/menu.component.ts @@ -1,9 +1,11 @@ import { html } from 'lit'; import { query } from 'lit/decorators.js'; +import componentStyles from '../../styles/component.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import styles from './menu.styles.js'; import type { CSSResultGroup } from 'lit'; import type SlMenuItem from '../menu-item/menu-item.component.js'; + export interface MenuSelectEventDetail { item: SlMenuItem; } @@ -19,7 +21,7 @@ export interface MenuSelectEventDetail { * @event {{ item: SlMenuItem }} sl-select - Emitted when a menu item is selected. */ export default class SlMenu extends ShoelaceElement { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, styles]; @query('slot') defaultSlot: HTMLSlotElement; diff --git a/src/components/menu/menu.styles.ts b/src/components/menu/menu.styles.ts index d5d0fe74..a01743eb 100644 --- a/src/components/menu/menu.styles.ts +++ b/src/components/menu/menu.styles.ts @@ -1,9 +1,6 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; export default css` - ${componentStyles} - :host { display: block; position: relative; diff --git a/src/components/mutation-observer/mutation-observer.component.ts b/src/components/mutation-observer/mutation-observer.component.ts index 85ed39e7..f78a9cf9 100644 --- a/src/components/mutation-observer/mutation-observer.component.ts +++ b/src/components/mutation-observer/mutation-observer.component.ts @@ -1,6 +1,7 @@ import { html } from 'lit'; import { property } from 'lit/decorators.js'; import { watch } from '../../internal/watch.js'; +import componentStyles from '../../styles/component.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import styles from './mutation-observer.styles.js'; import type { CSSResultGroup } from 'lit'; @@ -16,7 +17,7 @@ import type { CSSResultGroup } from 'lit'; * @slot - The content to watch for mutations. */ export default class SlMutationObserver extends ShoelaceElement { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, styles]; private mutationObserver: MutationObserver; diff --git a/src/components/mutation-observer/mutation-observer.styles.ts b/src/components/mutation-observer/mutation-observer.styles.ts index 674851ee..1ef4bf6f 100644 --- a/src/components/mutation-observer/mutation-observer.styles.ts +++ b/src/components/mutation-observer/mutation-observer.styles.ts @@ -1,9 +1,6 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; export default css` - ${componentStyles} - :host { display: contents; } diff --git a/src/components/option/option.component.ts b/src/components/option/option.component.ts index 142e2628..a9d35b50 100644 --- a/src/components/option/option.component.ts +++ b/src/components/option/option.component.ts @@ -3,6 +3,7 @@ import { html } from 'lit'; import { LocalizeController } from '../../utilities/localize.js'; import { property, query, state } from 'lit/decorators.js'; import { watch } from '../../internal/watch.js'; +import componentStyles from '../../styles/component.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import SlIcon from '../icon/icon.component.js'; import styles from './option.styles.js'; @@ -27,7 +28,7 @@ import type { CSSResultGroup } from 'lit'; * @csspart suffix - The container that wraps the suffix. */ export default class SlOption extends ShoelaceElement { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, styles]; static dependencies = { 'sl-icon': SlIcon }; private cachedTextLabel: string; @@ -112,7 +113,7 @@ export default class SlOption extends ShoelaceElement { [...nodes].forEach(node => { if (node.nodeType === Node.ELEMENT_NODE) { if (!(node as HTMLElement).hasAttribute('slot')) { - label += (node as HTMLElement).outerHTML; + label += (node as HTMLElement).textContent; } } diff --git a/src/components/option/option.styles.ts b/src/components/option/option.styles.ts index 8304ab42..146c7cbf 100644 --- a/src/components/option/option.styles.ts +++ b/src/components/option/option.styles.ts @@ -1,9 +1,6 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; export default css` - ${componentStyles} - :host { display: block; user-select: none; diff --git a/src/components/option/option.test.ts b/src/components/option/option.test.ts index 1112f300..2d5320a7 100644 --- a/src/components/option/option.test.ts +++ b/src/components/option/option.test.ts @@ -52,4 +52,9 @@ describe('', () => { expect(el.value).to.equal('10'); }); + + it('should escape HTML when calling getTextLabel()', async () => { + const el = await fixture(html` Option `); + expect(el.getTextLabel()).to.equal('Option'); + }); }); diff --git a/src/components/popup/popup.component.ts b/src/components/popup/popup.component.ts index 53ff039b..dd7e524c 100644 --- a/src/components/popup/popup.component.ts +++ b/src/components/popup/popup.component.ts @@ -3,6 +3,7 @@ import { classMap } from 'lit/directives/class-map.js'; import { html } from 'lit'; import { offsetParent } from 'composed-offset-position'; import { property, query } from 'lit/decorators.js'; +import componentStyles from '../../styles/component.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import styles from './popup.styles.js'; import type { CSSResultGroup } from 'lit'; @@ -45,7 +46,7 @@ function isVirtualElement(e: unknown): e is VirtualElement { * available when using `auto-size`. */ export default class SlPopup extends ShoelaceElement { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, styles]; private anchorEl: Element | VirtualElement | null; private cleanup: ReturnType | undefined; diff --git a/src/components/popup/popup.styles.ts b/src/components/popup/popup.styles.ts index c1d16127..c278707a 100644 --- a/src/components/popup/popup.styles.ts +++ b/src/components/popup/popup.styles.ts @@ -1,9 +1,6 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; export default css` - ${componentStyles} - :host { --arrow-color: var(--sl-color-neutral-1000); --arrow-size: 6px; diff --git a/src/components/progress-bar/progress-bar.component.ts b/src/components/progress-bar/progress-bar.component.ts index a580226a..e0ec6fff 100644 --- a/src/components/progress-bar/progress-bar.component.ts +++ b/src/components/progress-bar/progress-bar.component.ts @@ -4,6 +4,7 @@ import { ifDefined } from 'lit/directives/if-defined.js'; import { LocalizeController } from '../../utilities/localize.js'; import { property } from 'lit/decorators.js'; import { styleMap } from 'lit/directives/style-map.js'; +import componentStyles from '../../styles/component.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import styles from './progress-bar.styles.js'; import type { CSSResultGroup } from 'lit'; @@ -26,7 +27,7 @@ import type { CSSResultGroup } from 'lit'; * @cssproperty --label-color - The color of the label. */ export default class SlProgressBar extends ShoelaceElement { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, styles]; private readonly localize = new LocalizeController(this); /** The current progress as a percentage, 0 to 100. */ diff --git a/src/components/progress-bar/progress-bar.styles.ts b/src/components/progress-bar/progress-bar.styles.ts index 26fb0c06..f300cf0e 100644 --- a/src/components/progress-bar/progress-bar.styles.ts +++ b/src/components/progress-bar/progress-bar.styles.ts @@ -1,9 +1,6 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; export default css` - ${componentStyles} - :host { --height: 1rem; --track-color: var(--sl-color-neutral-200); diff --git a/src/components/progress-ring/progress-ring.component.ts b/src/components/progress-ring/progress-ring.component.ts index 8b3af3e7..fffd900d 100644 --- a/src/components/progress-ring/progress-ring.component.ts +++ b/src/components/progress-ring/progress-ring.component.ts @@ -1,6 +1,7 @@ import { html } from 'lit'; import { LocalizeController } from '../../utilities/localize.js'; import { property, query, state } from 'lit/decorators.js'; +import componentStyles from '../../styles/component.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import styles from './progress-ring.styles.js'; import type { CSSResultGroup } from 'lit'; @@ -24,7 +25,7 @@ import type { CSSResultGroup } from 'lit'; * @cssproperty --indicator-transition-duration - The duration of the indicator's transition when the value changes. */ export default class SlProgressRing extends ShoelaceElement { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, styles]; private readonly localize = new LocalizeController(this); diff --git a/src/components/progress-ring/progress-ring.styles.ts b/src/components/progress-ring/progress-ring.styles.ts index 590f0e49..de71c6c8 100644 --- a/src/components/progress-ring/progress-ring.styles.ts +++ b/src/components/progress-ring/progress-ring.styles.ts @@ -1,9 +1,6 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; export default css` - ${componentStyles} - :host { --size: 128px; --track-width: 4px; diff --git a/src/components/qr-code/qr-code.component.ts b/src/components/qr-code/qr-code.component.ts index f5dd4c81..f28ab50b 100644 --- a/src/components/qr-code/qr-code.component.ts +++ b/src/components/qr-code/qr-code.component.ts @@ -2,6 +2,7 @@ import { html } from 'lit'; import { property, query } from 'lit/decorators.js'; import { styleMap } from 'lit/directives/style-map.js'; import { watch } from '../../internal/watch.js'; +import componentStyles from '../../styles/component.styles.js'; import QrCreator from 'qr-creator'; import ShoelaceElement from '../../internal/shoelace-element.js'; import styles from './qr-code.styles.js'; @@ -16,7 +17,7 @@ import type { CSSResultGroup } from 'lit'; * @csspart base - The component's base wrapper. */ export default class SlQrCode extends ShoelaceElement { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, styles]; @query('canvas') canvas: HTMLElement; diff --git a/src/components/qr-code/qr-code.styles.ts b/src/components/qr-code/qr-code.styles.ts index af9afa4e..aa50921f 100644 --- a/src/components/qr-code/qr-code.styles.ts +++ b/src/components/qr-code/qr-code.styles.ts @@ -1,9 +1,6 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; export default css` - ${componentStyles} - :host { display: inline-block; } diff --git a/src/components/radio-button/radio-button.component.ts b/src/components/radio-button/radio-button.component.ts index bfc1a65e..773dd16d 100644 --- a/src/components/radio-button/radio-button.component.ts +++ b/src/components/radio-button/radio-button.component.ts @@ -4,6 +4,7 @@ import { html } from 'lit/static-html.js'; import { ifDefined } from 'lit/directives/if-defined.js'; import { property, query, state } from 'lit/decorators.js'; import { watch } from '../../internal/watch.js'; +import componentStyles from '../../styles/component.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import styles from './radio-button.styles.js'; import type { CSSResultGroup } from 'lit'; @@ -29,7 +30,7 @@ import type { CSSResultGroup } from 'lit'; * @csspart suffix - The container that wraps the suffix. */ export default class SlRadioButton extends ShoelaceElement { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, styles]; private readonly hasSlotController = new HasSlotController(this, '[default]', 'prefix', 'suffix'); diff --git a/src/components/radio-group/radio-group.component.ts b/src/components/radio-group/radio-group.component.ts index 35db49fd..b066340d 100644 --- a/src/components/radio-group/radio-group.component.ts +++ b/src/components/radio-group/radio-group.component.ts @@ -9,6 +9,8 @@ import { HasSlotController } from '../../internal/slot.js'; import { html } from 'lit'; import { property, query, state } from 'lit/decorators.js'; import { watch } from '../../internal/watch.js'; +import componentStyles from '../../styles/component.styles.js'; +import formControlStyles from '../../styles/form-control.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import SlButtonGroup from '../button-group/button-group.component.js'; import styles from './radio-group.styles.js'; @@ -42,7 +44,7 @@ import type SlRadioButton from '../radio-button/radio-button.js'; * @csspart button-group__base - The button group's `base` part. */ export default class SlRadioGroup extends ShoelaceElement implements ShoelaceFormControl { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, formControlStyles, styles]; static dependencies = { 'sl-button-group': SlButtonGroup }; protected readonly formControlController = new FormControlController(this); diff --git a/src/components/radio-group/radio-group.styles.ts b/src/components/radio-group/radio-group.styles.ts index 0fcc2658..3cfcf3bb 100644 --- a/src/components/radio-group/radio-group.styles.ts +++ b/src/components/radio-group/radio-group.styles.ts @@ -1,11 +1,6 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; -import formControlStyles from '../../styles/form-control.styles.js'; export default css` - ${componentStyles} - ${formControlStyles} - :host { display: block; } diff --git a/src/components/radio/radio.component.ts b/src/components/radio/radio.component.ts index 88893923..30323e40 100644 --- a/src/components/radio/radio.component.ts +++ b/src/components/radio/radio.component.ts @@ -2,6 +2,7 @@ import { classMap } from 'lit/directives/class-map.js'; import { html } from 'lit'; import { property, state } from 'lit/decorators.js'; import { watch } from '../../internal/watch.js'; +import componentStyles from '../../styles/component.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import SlIcon from '../icon/icon.component.js'; import styles from './radio.styles.js'; @@ -27,7 +28,7 @@ import type { CSSResultGroup } from 'lit'; * @csspart label - The container that wraps the radio's label. */ export default class SlRadio extends ShoelaceElement { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, styles]; static dependencies = { 'sl-icon': SlIcon }; @state() checked = false; diff --git a/src/components/radio/radio.styles.ts b/src/components/radio/radio.styles.ts index a9c0f697..34e5eebb 100644 --- a/src/components/radio/radio.styles.ts +++ b/src/components/radio/radio.styles.ts @@ -1,9 +1,6 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; export default css` - ${componentStyles} - :host { display: block; } diff --git a/src/components/range/range.component.ts b/src/components/range/range.component.ts index 09290f4f..a336ceea 100644 --- a/src/components/range/range.component.ts +++ b/src/components/range/range.component.ts @@ -8,6 +8,8 @@ import { ifDefined } from 'lit/directives/if-defined.js'; import { live } from 'lit/directives/live.js'; import { LocalizeController } from '../../utilities/localize.js'; import { watch } from '../../internal/watch.js'; +import componentStyles from '../../styles/component.styles.js'; +import formControlStyles from '../../styles/form-control.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import styles from './range.styles.js'; import type { CSSResultGroup } from 'lit'; @@ -44,7 +46,7 @@ import type { ShoelaceFormControl } from '../../internal/shoelace-element.js'; * @cssproperty --track-active-offset - The point of origin of the active track. */ export default class SlRange extends ShoelaceElement implements ShoelaceFormControl { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, formControlStyles, styles]; private readonly formControlController = new FormControlController(this); private readonly hasSlotController = new HasSlotController(this, 'help-text', 'label'); diff --git a/src/components/range/range.styles.ts b/src/components/range/range.styles.ts index b42370d7..438108b1 100644 --- a/src/components/range/range.styles.ts +++ b/src/components/range/range.styles.ts @@ -1,11 +1,6 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; -import formControlStyles from '../../styles/form-control.styles.js'; export default css` - ${componentStyles} - ${formControlStyles} - :host { --thumb-size: 20px; --tooltip-offset: 10px; diff --git a/src/components/rating/rating.component.ts b/src/components/rating/rating.component.ts index b65bcafa..a00c2870 100644 --- a/src/components/rating/rating.component.ts +++ b/src/components/rating/rating.component.ts @@ -6,6 +6,7 @@ import { LocalizeController } from '../../utilities/localize.js'; import { styleMap } from 'lit/directives/style-map.js'; import { unsafeHTML } from 'lit/directives/unsafe-html.js'; import { watch } from '../../internal/watch.js'; +import componentStyles from '../../styles/component.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import SlIcon from '../icon/icon.component.js'; import styles from './rating.styles.js'; @@ -32,7 +33,7 @@ import type { CSSResultGroup } from 'lit'; * @cssproperty --symbol-spacing - The spacing to use around symbols. */ export default class SlRating extends ShoelaceElement { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, styles]; static dependencies = { 'sl-icon': SlIcon }; private readonly localize = new LocalizeController(this); diff --git a/src/components/rating/rating.styles.ts b/src/components/rating/rating.styles.ts index d01360c2..ed57fd84 100644 --- a/src/components/rating/rating.styles.ts +++ b/src/components/rating/rating.styles.ts @@ -1,9 +1,6 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; export default css` - ${componentStyles} - :host { --symbol-color: var(--sl-color-neutral-300); --symbol-color-active: var(--sl-color-amber-500); diff --git a/src/components/resize-observer/resize-observer.component.ts b/src/components/resize-observer/resize-observer.component.ts index 26db8689..bb2f2468 100644 --- a/src/components/resize-observer/resize-observer.component.ts +++ b/src/components/resize-observer/resize-observer.component.ts @@ -1,6 +1,7 @@ import { html } from 'lit'; import { property } from 'lit/decorators.js'; import { watch } from '../../internal/watch.js'; +import componentStyles from '../../styles/component.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import styles from './resize-observer.styles.js'; import type { CSSResultGroup } from 'lit'; @@ -16,7 +17,7 @@ import type { CSSResultGroup } from 'lit'; * @event {{ entries: ResizeObserverEntry[] }} sl-resize - Emitted when the element is resized. */ export default class SlResizeObserver extends ShoelaceElement { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, styles]; private resizeObserver: ResizeObserver; private observedElements: HTMLElement[] = []; diff --git a/src/components/resize-observer/resize-observer.styles.ts b/src/components/resize-observer/resize-observer.styles.ts index 674851ee..1ef4bf6f 100644 --- a/src/components/resize-observer/resize-observer.styles.ts +++ b/src/components/resize-observer/resize-observer.styles.ts @@ -1,9 +1,6 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; export default css` - ${componentStyles} - :host { display: contents; } diff --git a/src/components/select/select.component.ts b/src/components/select/select.component.ts index b103d740..44f18cac 100644 --- a/src/components/select/select.component.ts +++ b/src/components/select/select.component.ts @@ -11,6 +11,8 @@ import { scrollIntoView } from '../../internal/scroll.js'; import { unsafeHTML } from 'lit/directives/unsafe-html.js'; import { waitForEvent } from '../../internal/event.js'; import { watch } from '../../internal/watch.js'; +import componentStyles from '../../styles/component.styles.js'; +import formControlStyles from '../../styles/form-control.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import SlIcon from '../icon/icon.component.js'; import SlPopup from '../popup/popup.component.js'; @@ -67,7 +69,7 @@ import type SlOption from '../option/option.component.js'; * @csspart expand-icon - The container that wraps the expand icon. */ export default class SlSelect extends ShoelaceElement implements ShoelaceFormControl { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, formControlStyles, styles]; static dependencies = { 'sl-icon': SlIcon, 'sl-popup': SlPopup, diff --git a/src/components/select/select.styles.ts b/src/components/select/select.styles.ts index 7b247049..991cc492 100644 --- a/src/components/select/select.styles.ts +++ b/src/components/select/select.styles.ts @@ -1,11 +1,6 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; -import formControlStyles from '../../styles/form-control.styles.js'; export default css` - ${componentStyles} - ${formControlStyles} - :host { display: block; } diff --git a/src/components/skeleton/skeleton.component.ts b/src/components/skeleton/skeleton.component.ts index ecee34a5..0ef1d39e 100644 --- a/src/components/skeleton/skeleton.component.ts +++ b/src/components/skeleton/skeleton.component.ts @@ -1,6 +1,7 @@ import { classMap } from 'lit/directives/class-map.js'; import { html } from 'lit'; import { property } from 'lit/decorators.js'; +import componentStyles from '../../styles/component.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import styles from './skeleton.styles.js'; import type { CSSResultGroup } from 'lit'; @@ -19,7 +20,7 @@ import type { CSSResultGroup } from 'lit'; * @cssproperty --sheen-color - The sheen color when the skeleton is in its loading state. */ export default class SlSkeleton extends ShoelaceElement { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, styles]; /** Determines which effect the skeleton will use. */ @property() effect: 'pulse' | 'sheen' | 'none' = 'none'; diff --git a/src/components/skeleton/skeleton.styles.ts b/src/components/skeleton/skeleton.styles.ts index 7e427914..59ae461b 100644 --- a/src/components/skeleton/skeleton.styles.ts +++ b/src/components/skeleton/skeleton.styles.ts @@ -1,9 +1,6 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; export default css` - ${componentStyles} - :host { --border-radius: var(--sl-border-radius-pill); --color: var(--sl-color-neutral-200); diff --git a/src/components/spinner/spinner.component.ts b/src/components/spinner/spinner.component.ts index bd38aaad..2422639a 100644 --- a/src/components/spinner/spinner.component.ts +++ b/src/components/spinner/spinner.component.ts @@ -1,5 +1,6 @@ import { html } from 'lit'; import { LocalizeController } from '../../utilities/localize.js'; +import componentStyles from '../../styles/component.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import styles from './spinner.styles.js'; import type { CSSResultGroup } from 'lit'; @@ -18,7 +19,7 @@ import type { CSSResultGroup } from 'lit'; * @cssproperty --speed - The time it takes for the spinner to complete one animation cycle. */ export default class SlSpinner extends ShoelaceElement { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, styles]; private readonly localize = new LocalizeController(this); diff --git a/src/components/spinner/spinner.styles.ts b/src/components/spinner/spinner.styles.ts index 76384b27..4699b0fa 100644 --- a/src/components/spinner/spinner.styles.ts +++ b/src/components/spinner/spinner.styles.ts @@ -1,5 +1,4 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; // Resizing a spinner element using anything but font-size will break the animation because the animation uses em units. // Therefore, if a spinner is used in a flex container without `flex: none` applied, the spinner can grow/shrink and @@ -7,8 +6,6 @@ import componentStyles from '../../styles/component.styles.js'; // according to its actual dimensions. export default css` - ${componentStyles} - :host { --track-width: 2px; --track-color: rgb(128 128 128 / 25%); diff --git a/src/components/split-panel/split-panel.component.ts b/src/components/split-panel/split-panel.component.ts index c8b658c4..2154e772 100644 --- a/src/components/split-panel/split-panel.component.ts +++ b/src/components/split-panel/split-panel.component.ts @@ -5,6 +5,7 @@ import { ifDefined } from 'lit/directives/if-defined.js'; import { LocalizeController } from '../../utilities/localize.js'; import { property, query } from 'lit/decorators.js'; import { watch } from '../../internal/watch.js'; +import componentStyles from '../../styles/component.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import styles from './split-panel.styles.js'; import type { CSSResultGroup } from 'lit'; @@ -33,7 +34,7 @@ import type { CSSResultGroup } from 'lit'; * @cssproperty [--max=100%] - The maximum allowed size of the primary panel. */ export default class SlSplitPanel extends ShoelaceElement { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, styles]; private cachedPositionInPixels: number; private readonly localize = new LocalizeController(this); diff --git a/src/components/split-panel/split-panel.styles.ts b/src/components/split-panel/split-panel.styles.ts index ff5ae250..7ccc408e 100644 --- a/src/components/split-panel/split-panel.styles.ts +++ b/src/components/split-panel/split-panel.styles.ts @@ -1,9 +1,6 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; export default css` - ${componentStyles} - :host { --divider-width: 4px; --divider-hit-area: 12px; diff --git a/src/components/switch/switch.component.ts b/src/components/switch/switch.component.ts index 2ec28063..d6600cbd 100644 --- a/src/components/switch/switch.component.ts +++ b/src/components/switch/switch.component.ts @@ -1,11 +1,14 @@ import { classMap } from 'lit/directives/class-map.js'; import { defaultValue } from '../../internal/default-value.js'; import { FormControlController } from '../../internal/form.js'; +import { HasSlotController } from '../../internal/slot.js'; import { html } from 'lit'; import { ifDefined } from 'lit/directives/if-defined.js'; import { live } from 'lit/directives/live.js'; import { property, query, state } from 'lit/decorators.js'; import { watch } from '../../internal/watch.js'; +import componentStyles from '../../styles/component.styles.js'; +import formControlStyles from '../../styles/form-control.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import styles from './switch.styles.js'; import type { CSSResultGroup } from 'lit'; @@ -18,6 +21,7 @@ import type { ShoelaceFormControl } from '../../internal/shoelace-element.js'; * @since 2.0 * * @slot - The switch's label. + * @slot help-text - Text that describes how to use the switch. Alternatively, you can use the `help-text` attribute. * * @event sl-blur - Emitted when the control loses focus. * @event sl-change - Emitted when the control's checked state changes. @@ -29,19 +33,21 @@ import type { ShoelaceFormControl } from '../../internal/shoelace-element.js'; * @csspart control - The control that houses the switch's thumb. * @csspart thumb - The switch's thumb. * @csspart label - The switch's label. + * @csspart form-control-help-text - The help text's wrapper. * * @cssproperty --width - The width of the switch. * @cssproperty --height - The height of the switch. * @cssproperty --thumb-size - The size of the thumb. */ export default class SlSwitch extends ShoelaceElement implements ShoelaceFormControl { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, formControlStyles, styles]; private readonly formControlController = new FormControlController(this, { value: (control: SlSwitch) => (control.checked ? control.value || 'on' : undefined), defaultValue: (control: SlSwitch) => control.defaultChecked, setValue: (control: SlSwitch, checked: boolean) => (control.checked = checked) }); + private readonly hasSlotController = new HasSlotController(this, 'help-text'); @query('input[type="checkbox"]') input: HTMLInputElement; @@ -76,6 +82,9 @@ export default class SlSwitch extends ShoelaceElement implements ShoelaceFormCon /** Makes the switch a required field. */ @property({ type: Boolean, reflect: true }) required = false; + /** The switch's help text. If you need to display HTML, use the `help-text` slot instead. */ + @property({ attribute: 'help-text' }) helpText = ''; + /** Gets the validity state object */ get validity() { return this.input.validity; @@ -179,46 +188,69 @@ export default class SlSwitch extends ShoelaceElement implements ShoelaceFormCon } render() { + const hasHelpTextSlot = this.hasSlotController.test('help-text'); + const hasHelpText = this.helpText ? true : !!hasHelpTextSlot; + return html` - - + + - - - + + + - - + + + + + + + ${this.helpText} - + `; } } diff --git a/src/components/switch/switch.styles.ts b/src/components/switch/switch.styles.ts index 31aa0eba..5ef6f636 100644 --- a/src/components/switch/switch.styles.ts +++ b/src/components/switch/switch.styles.ts @@ -1,9 +1,6 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; export default css` - ${componentStyles} - :host { display: inline-block; } diff --git a/src/components/switch/switch.test.ts b/src/components/switch/switch.test.ts index 7fef64f3..b49da597 100644 --- a/src/components/switch/switch.test.ts +++ b/src/components/switch/switch.test.ts @@ -21,6 +21,7 @@ describe('', () => { expect(el.required).to.be.false; expect(el.checked).to.be.false; expect(el.defaultChecked).to.be.false; + expect(el.helpText).to.equal(''); }); it('should have title if title attribute is set', async () => { diff --git a/src/components/tab-group/tab-group.component.ts b/src/components/tab-group/tab-group.component.ts index 27ecf18a..5b592044 100644 --- a/src/components/tab-group/tab-group.component.ts +++ b/src/components/tab-group/tab-group.component.ts @@ -4,6 +4,7 @@ import { LocalizeController } from '../../utilities/localize.js'; import { property, query, state } from 'lit/decorators.js'; import { scrollIntoView } from '../../internal/scroll.js'; import { watch } from '../../internal/watch.js'; +import componentStyles from '../../styles/component.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import SlIconButton from '../icon-button/icon-button.component.js'; import styles from './tab-group.styles.js'; @@ -40,7 +41,7 @@ import type SlTabPanel from '../tab-panel/tab-panel.js'; * @cssproperty --track-width - The width of the indicator's track (the line that separates tabs from panels). */ export default class SlTabGroup extends ShoelaceElement { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, styles]; static dependencies = { 'sl-icon-button': SlIconButton }; private readonly localize = new LocalizeController(this); diff --git a/src/components/tab-group/tab-group.styles.ts b/src/components/tab-group/tab-group.styles.ts index ad776add..7180ec33 100644 --- a/src/components/tab-group/tab-group.styles.ts +++ b/src/components/tab-group/tab-group.styles.ts @@ -1,9 +1,6 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; export default css` - ${componentStyles} - :host { --indicator-color: var(--sl-color-primary-600); --track-color: var(--sl-color-neutral-200); diff --git a/src/components/tab-panel/tab-panel.component.ts b/src/components/tab-panel/tab-panel.component.ts index 599f7529..7f18b219 100644 --- a/src/components/tab-panel/tab-panel.component.ts +++ b/src/components/tab-panel/tab-panel.component.ts @@ -2,6 +2,7 @@ import { classMap } from 'lit/directives/class-map.js'; import { html } from 'lit'; import { property } from 'lit/decorators.js'; import { watch } from '../../internal/watch.js'; +import componentStyles from '../../styles/component.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import styles from './tab-panel.styles.js'; import type { CSSResultGroup } from 'lit'; @@ -21,7 +22,7 @@ let id = 0; * @cssproperty --padding - The tab panel's padding. */ export default class SlTabPanel extends ShoelaceElement { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, styles]; private readonly attrId = ++id; private readonly componentId = `sl-tab-panel-${this.attrId}`; diff --git a/src/components/tab-panel/tab-panel.styles.ts b/src/components/tab-panel/tab-panel.styles.ts index dfec6b30..e0c9f214 100644 --- a/src/components/tab-panel/tab-panel.styles.ts +++ b/src/components/tab-panel/tab-panel.styles.ts @@ -1,9 +1,6 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; export default css` - ${componentStyles} - :host { --padding: 0; diff --git a/src/components/tab/tab.component.ts b/src/components/tab/tab.component.ts index b418c390..1aa14fc8 100644 --- a/src/components/tab/tab.component.ts +++ b/src/components/tab/tab.component.ts @@ -3,6 +3,7 @@ import { html } from 'lit'; import { LocalizeController } from '../../utilities/localize.js'; import { property, query } from 'lit/decorators.js'; import { watch } from '../../internal/watch.js'; +import componentStyles from '../../styles/component.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import SlIconButton from '../icon-button/icon-button.component.js'; import styles from './tab.styles.js'; @@ -27,7 +28,7 @@ let id = 0; * @csspart close-button__base - The close button's exported `base` part. */ export default class SlTab extends ShoelaceElement { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, styles]; static dependencies = { 'sl-icon-button': SlIconButton }; private readonly localize = new LocalizeController(this); diff --git a/src/components/tab/tab.styles.ts b/src/components/tab/tab.styles.ts index 6478e9e1..e2e1e3a0 100644 --- a/src/components/tab/tab.styles.ts +++ b/src/components/tab/tab.styles.ts @@ -1,9 +1,6 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; export default css` - ${componentStyles} - :host { display: inline-block; } diff --git a/src/components/tag/tag.component.ts b/src/components/tag/tag.component.ts index 86f8ee05..f7334e05 100644 --- a/src/components/tag/tag.component.ts +++ b/src/components/tag/tag.component.ts @@ -2,6 +2,7 @@ import { classMap } from 'lit/directives/class-map.js'; import { html } from 'lit'; import { LocalizeController } from '../../utilities/localize.js'; import { property } from 'lit/decorators.js'; +import componentStyles from '../../styles/component.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import SlIconButton from '../icon-button/icon-button.component.js'; import styles from './tag.styles.js'; @@ -25,7 +26,7 @@ import type { CSSResultGroup } from 'lit'; * @csspart remove-button__base - The remove button's exported `base` part. */ export default class SlTag extends ShoelaceElement { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, styles]; static dependencies = { 'sl-icon-button': SlIconButton }; private readonly localize = new LocalizeController(this); diff --git a/src/components/tag/tag.styles.ts b/src/components/tag/tag.styles.ts index 352cb19f..5349d728 100644 --- a/src/components/tag/tag.styles.ts +++ b/src/components/tag/tag.styles.ts @@ -1,9 +1,6 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; export default css` - ${componentStyles} - :host { display: inline-block; } diff --git a/src/components/textarea/textarea.component.ts b/src/components/textarea/textarea.component.ts index 27eccc18..f4c6e0f4 100644 --- a/src/components/textarea/textarea.component.ts +++ b/src/components/textarea/textarea.component.ts @@ -7,6 +7,8 @@ import { ifDefined } from 'lit/directives/if-defined.js'; import { live } from 'lit/directives/live.js'; import { property, query, state } from 'lit/decorators.js'; import { watch } from '../../internal/watch.js'; +import componentStyles from '../../styles/component.styles.js'; +import formControlStyles from '../../styles/form-control.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import styles from './textarea.styles.js'; import type { CSSResultGroup } from 'lit'; @@ -35,7 +37,7 @@ import type { ShoelaceFormControl } from '../../internal/shoelace-element.js'; * @csspart textarea - The internal `` control. */ export default class SlTextarea extends ShoelaceElement implements ShoelaceFormControl { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, formControlStyles, styles]; private readonly formControlController = new FormControlController(this, { assumeInteractionOn: ['sl-blur', 'sl-input'] diff --git a/src/components/textarea/textarea.styles.ts b/src/components/textarea/textarea.styles.ts index f30b2394..3bcdb9ce 100644 --- a/src/components/textarea/textarea.styles.ts +++ b/src/components/textarea/textarea.styles.ts @@ -1,11 +1,6 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; -import formControlStyles from '../../styles/form-control.styles.js'; export default css` - ${componentStyles} - ${formControlStyles} - :host { display: block; } diff --git a/src/components/tooltip/tooltip.component.ts b/src/components/tooltip/tooltip.component.ts index 09ac1368..154dc159 100644 --- a/src/components/tooltip/tooltip.component.ts +++ b/src/components/tooltip/tooltip.component.ts @@ -6,6 +6,7 @@ import { LocalizeController } from '../../utilities/localize.js'; import { property, query } from 'lit/decorators.js'; import { waitForEvent } from '../../internal/event.js'; import { watch } from '../../internal/watch.js'; +import componentStyles from '../../styles/component.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import SlPopup from '../popup/popup.component.js'; import styles from './tooltip.styles.js'; @@ -40,7 +41,7 @@ import type { CSSResultGroup } from 'lit'; * @animation tooltip.hide - The animation to use when hiding the tooltip. */ export default class SlTooltip extends ShoelaceElement { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, styles]; static dependencies = { 'sl-popup': SlPopup }; private hoverTimeout: number; diff --git a/src/components/tooltip/tooltip.styles.ts b/src/components/tooltip/tooltip.styles.ts index 0b8b2619..2fd27519 100644 --- a/src/components/tooltip/tooltip.styles.ts +++ b/src/components/tooltip/tooltip.styles.ts @@ -1,9 +1,6 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; export default css` - ${componentStyles} - :host { --max-width: 20rem; --hide-delay: 0ms; diff --git a/src/components/tree-item/tree-item.component.ts b/src/components/tree-item/tree-item.component.ts index 03487eff..4fe9f733 100644 --- a/src/components/tree-item/tree-item.component.ts +++ b/src/components/tree-item/tree-item.component.ts @@ -7,6 +7,7 @@ import { LocalizeController } from '../../utilities/localize.js'; import { property, query, state } from 'lit/decorators.js'; import { watch } from '../../internal/watch.js'; import { when } from 'lit/directives/when.js'; +import componentStyles from '../../styles/component.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import SlCheckbox from '../checkbox/checkbox.component.js'; import SlIcon from '../icon/icon.component.js'; @@ -57,7 +58,7 @@ import type { CSSResultGroup, PropertyValueMap } from 'lit'; * @csspart checkbox__label - The checkbox's exported `label` part. */ export default class SlTreeItem extends ShoelaceElement { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, styles]; static dependencies = { 'sl-checkbox': SlCheckbox, 'sl-icon': SlIcon, diff --git a/src/components/tree-item/tree-item.styles.ts b/src/components/tree-item/tree-item.styles.ts index c9ca22b6..a18c67fc 100644 --- a/src/components/tree-item/tree-item.styles.ts +++ b/src/components/tree-item/tree-item.styles.ts @@ -1,9 +1,6 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; export default css` - ${componentStyles} - :host { display: block; outline: 0; diff --git a/src/components/tree/tree.component.ts b/src/components/tree/tree.component.ts index 81a0ba6d..78123cca 100644 --- a/src/components/tree/tree.component.ts +++ b/src/components/tree/tree.component.ts @@ -3,6 +3,7 @@ import { html } from 'lit'; import { LocalizeController } from '../../utilities/localize.js'; import { property, query } from 'lit/decorators.js'; import { watch } from '../../internal/watch.js'; +import componentStyles from '../../styles/component.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import SlTreeItem from '../tree-item/tree-item.component.js'; import styles from './tree.styles.js'; @@ -70,7 +71,7 @@ function syncCheckboxes(changedTreeItem: SlTreeItem, initialSync = false) { * @cssproperty [--indent-guide-width=0] - The width of the indentation line. */ export default class SlTree extends ShoelaceElement { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, styles]; @query('slot:not([name])') defaultSlot: HTMLSlotElement; @query('slot[name=expand-icon]') expandedIconSlot: HTMLSlotElement; diff --git a/src/components/tree/tree.styles.ts b/src/components/tree/tree.styles.ts index 0733fcbd..c3364f71 100644 --- a/src/components/tree/tree.styles.ts +++ b/src/components/tree/tree.styles.ts @@ -1,9 +1,6 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; export default css` - ${componentStyles} - :host { /* * These are actually used by tree item, but we define them here so they can more easily be set and all tree items diff --git a/src/components/visually-hidden/visually-hidden.component.ts b/src/components/visually-hidden/visually-hidden.component.ts index c93a6d56..c406df9e 100644 --- a/src/components/visually-hidden/visually-hidden.component.ts +++ b/src/components/visually-hidden/visually-hidden.component.ts @@ -1,4 +1,5 @@ import { html } from 'lit'; +import componentStyles from '../../styles/component.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import styles from './visually-hidden.styles.js'; import type { CSSResultGroup } from 'lit'; @@ -12,7 +13,7 @@ import type { CSSResultGroup } from 'lit'; * @slot - The content to be visually hidden. */ export default class SlVisuallyHidden extends ShoelaceElement { - static styles: CSSResultGroup = styles; + static styles: CSSResultGroup = [componentStyles, styles]; render() { return html` `; diff --git a/src/components/visually-hidden/visually-hidden.styles.ts b/src/components/visually-hidden/visually-hidden.styles.ts index 1f72aab5..fd1d8910 100644 --- a/src/components/visually-hidden/visually-hidden.styles.ts +++ b/src/components/visually-hidden/visually-hidden.styles.ts @@ -1,9 +1,6 @@ import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; export default css` - ${componentStyles} - :host(:not(:focus-within)) { position: absolute !important; width: 1px !important; diff --git a/src/translations/ar.ts b/src/translations/ar.ts new file mode 100644 index 00000000..96352368 --- /dev/null +++ b/src/translations/ar.ts @@ -0,0 +1,41 @@ +import { registerTranslation } from '@shoelace-style/localize'; +import type { Translation } from '../utilities/localize.js'; + +const translation: Translation = { + $code: 'ar', + $name: 'العربية', + $dir: 'rtl', + + carousel: 'كاروسيل', + clearEntry: 'حذف الخيارات', + close: 'اغلاق', + copied: 'تم النسخ', + copy: 'نسخ', + currentValue: 'القيمة الحالية', + error: 'خطأ', + goToSlide: (slide, count) => `عرض شريحة رقم ${slide} من ${count}`, + hidePassword: 'اخفاء كلمة المرور', + loading: 'جاري التحميل', + nextSlide: 'الشريحة التالية', + numOptionsSelected: num => { + if (num === 0) return 'لم يتم تحديد أي خيارات'; + if (num === 1) return 'تم تحديد خيار واحد'; + if (num === 2) return 'تم تحديد خياران'; + if (num > 2 && num < 11) return `تم تحديد ${num} خيارات`; + return `تم تحديد ${num} خيار`; + }, + previousSlide: 'الشريحة السابقة', + progress: 'مقدار التقدم', + remove: 'حذف', + resize: 'تغيير الحجم', + scrollToEnd: 'الانتقال الى النهاية', + scrollToStart: 'الانتقال الى البداية', + selectAColorFromTheScreen: 'اختر لون من الشاشة', + showPassword: 'عرض كلمة المرور', + slideNum: slide => `شريحة ${slide}`, + toggleColorFormat: 'تغيير صيغة عرض اللون' +}; + +registerTranslation(translation); + +export default translation;