Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions .changeset/slim-down-solid-element.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
"@solid-design-system/components": minor
---

perf: slim down SolidElement base class to reduce bundle size

Removed rarely-used features from the `SolidElement` base class (inherited by all 59 components) and moved them to opt-in modules, significantly reducing the bundle size for consumers who import individual components.

**What changed:**

- Removed `dir` and `lang` reactive properties (unused by any component; native HTML attributes still work)
- Removed `token()` method and `animate.ts` import — moved to standalone `token()` utility in `src/internal/token.ts` (used by 3 components: tag, video, audio)
- Removed `onThemeChange` lifecycle hook — moved to self-managed listeners in the 2 consuming components (icon, audio)
- Removed CSS `@import` for `interactive.css`, `headline.css`, `paragraph.css` — moved to importable modules in `src/internal/shared-styles.ts` (only added by the ~14 components that actually use them)
- Updated Storybook Vite config to process the new `shared-styles.ts` file with Tailwind

**What remains in SolidElement:**

- Tailwind `--tw-*` CSS variable resets (needed by all components)
- `box-sizing` reset and `[hidden]` rule
- `emit()` method (used by 20+ components)
19 changes: 17 additions & 2 deletions packages/components/src/components/audio/audio.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import { LocalizeController } from '../../utilities/localize';
import { property, query, state } from 'lit/decorators.js';
import { Wave } from './wave';
import cx from 'classix';
import { interactiveStyles } from '../../internal/shared-styles';
import { token } from '../../internal/token';
import SolidElement from '../../internal/solid-element';
import type SdDrawer from '../drawer/drawer';
import type SdRange from '../range/range';
Expand Down Expand Up @@ -50,6 +52,18 @@ import type SdRange from '../range/range';
export default class SdAudio extends SolidElement {
private readonly localize = new LocalizeController(this);

private readonly _boundThemeChange = () => this.onThemeChange();

connectedCallback(): void {
super.connectedCallback();
this.renderRoot.addEventListener('sd-theme-change', this._boundThemeChange);
}

disconnectedCallback(): void {
super.disconnectedCallback();
this.renderRoot.removeEventListener('sd-theme-change', this._boundThemeChange);
}

private readonly hasSlotController = new HasSlotController(this, 'transcript');

/** Reverses the order of the audio controls and timestamps */
Expand Down Expand Up @@ -314,9 +328,9 @@ export default class SdAudio extends SolidElement {
return null;
}

onThemeChange(): void {
private onThemeChange(): void {
this.clear();
setTimeout(this.initAnimation.bind(this), this.token('--sd-duration-fast', 150));
setTimeout(this.initAnimation.bind(this), token(this, '--sd-duration-fast', 150));
}

private initAnimation() {
Expand Down Expand Up @@ -540,6 +554,7 @@ export default class SdAudio extends SolidElement {

static styles = [
...SolidElement.styles,
interactiveStyles,
css`
sd-button::part(base) {
@apply rounded-full h-12 w-12 flex items-center justify-center;
Expand Down
2 changes: 2 additions & 0 deletions packages/components/src/components/breadcrumb/breadcrumb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { customElement } from '../../internal/register-custom-element';
import { LocalizeController } from '../../utilities/localize';
import { property, query, state } from 'lit/decorators.js';
import cx from 'classix';
import { interactiveStyles } from '../../internal/shared-styles';
import SolidElement from '../../internal/solid-element';

/**
Expand Down Expand Up @@ -153,6 +154,7 @@ export default class SdBreadcrumb extends SolidElement {

static styles = [
...SolidElement.styles,
interactiveStyles,
css`
:host {
@apply block relative;
Expand Down
2 changes: 2 additions & 0 deletions packages/components/src/components/carousel/carousel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { range } from 'lit/directives/range.js';
import { ScrollController } from './scroll-controller.js';
import { watch } from '../../internal/watch.js';
import cx from 'classix';
import { interactiveStyles } from '../../internal/shared-styles';
import SdCarouselItem from '../carousel-item/carousel-item.js';
import SolidElement from '../../internal/solid-element.js';

Expand Down Expand Up @@ -834,6 +835,7 @@ export default class SdCarousel extends SolidElement {

static styles = [
...SolidElement.styles,
interactiveStyles,
css`
:host {
--slide-gap: var(--sl-spacing-medium, 1rem);
Expand Down
2 changes: 2 additions & 0 deletions packages/components/src/components/combobox/combobox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { unsafeHTML } from 'lit/directives/unsafe-html.js';
import { waitForEvent } from '../../internal/event.js';
import { watch } from '../../internal/watch.js';
import cx from 'classix';
import { interactiveStyles } from '../../internal/shared-styles';
import SolidElement from '../../internal/solid-element';
import type { SolidFormControl } from '../../internal/solid-element';
import type SdOptgroup from '../optgroup/optgroup.js';
Expand Down Expand Up @@ -1569,6 +1570,7 @@ export default class SdCombobox extends SolidElement implements SolidFormControl
}
static styles = [
...SolidElement.styles,
interactiveStyles,
css`
:host {
@apply block relative w-full;
Expand Down
3 changes: 3 additions & 0 deletions packages/components/src/components/datepicker/datepicker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { LocalizeController } from '../../utilities/localize';
import { property, query, state } from 'lit/decorators.js';
import { watch } from '../../internal/watch';
import cx from 'classix';
import { headlineStyles, interactiveStyles } from '../../internal/shared-styles';
import SolidElement from '../../internal/solid-element';
import type { SolidFormControl } from '../../internal/solid-element';
import type SdPopup from '../popup/popup';
Expand Down Expand Up @@ -2220,6 +2221,8 @@ export default class SdDatepicker extends SolidElement implements SolidFormContr

static styles = [
...SolidElement.styles,
headlineStyles,
interactiveStyles,
css`
:host {
@apply inline-block relative outline-none w-full;
Expand Down
2 changes: 2 additions & 0 deletions packages/components/src/components/dialog/dialog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { property, query } from 'lit/decorators.js';
import { waitForEvent } from '../../internal/event';
import { watch } from '../../internal/watch';
import cx from 'classix';
import { headlineStyles } from '../../internal/shared-styles';
import Modal from '../../internal/modal';
import SolidElement from '../../internal/solid-element';

Expand Down Expand Up @@ -338,6 +339,7 @@ export default class SdDialog extends SolidElement {

static styles = [
...SolidElement.styles,
headlineStyles,
css`
:host {
--width: 662px;
Expand Down
2 changes: 2 additions & 0 deletions packages/components/src/components/expandable/expandable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { property, query } from 'lit/decorators.js';
import { waitForEvent } from '../../internal/event';
import { watch } from '../../internal/watch.js';
import cx from 'classix';
import { interactiveStyles } from '../../internal/shared-styles';
import SolidElement from '../../internal/solid-element';

/**
Expand Down Expand Up @@ -187,6 +188,7 @@ export default class SdExpandable extends SolidElement {

static styles = [
...SolidElement.styles,
interactiveStyles,
css`
:host {
--component-expandable-max-block-size: 90px;
Expand Down
16 changes: 8 additions & 8 deletions packages/components/src/components/icon/icon.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { css, html } from 'lit';
import { customElement } from '../../internal/register-custom-element';
import { getIconLibrary, unwatchIcon, watchIcon } from './library';
import { property, state } from 'lit/decorators.js';
import { requestIcon } from './request';
import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
import { watch } from '../../internal/watch';
import { customElement } from '../../internal/register-custom-element';
import SolidElement from '../../internal/solid-element';
import { watch } from '../../internal/watch';
import { getIconLibrary, unwatchIcon, watchIcon } from './library';
import { requestIcon } from './request';

let parser: DOMParser;

Expand Down Expand Up @@ -48,9 +48,12 @@ export default class SdIcon extends SolidElement {
*/
@property({ reflect: true }) color: 'currentColor' | 'primary' | 'white' = 'currentColor';

private readonly _boundThemeChange = () => this.setIcon();

connectedCallback() {
super.connectedCallback();
watchIcon(this);
this.renderRoot.addEventListener('sd-theme-change', this._boundThemeChange);
}

firstUpdated() {
Expand All @@ -60,10 +63,7 @@ export default class SdIcon extends SolidElement {
disconnectedCallback() {
super.disconnectedCallback();
unwatchIcon(this);
}

protected onThemeChange(): void {
this.setIcon();
this.renderRoot.removeEventListener('sd-theme-change', this._boundThemeChange);
}

private getUrl() {
Expand Down
2 changes: 2 additions & 0 deletions packages/components/src/components/input/input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { longPress } from '../../internal/longpress.js';
import { property, query, state } from 'lit/decorators.js';
import { watch } from '../../internal/watch';
import cx from 'classix';
import { interactiveStyles } from '../../internal/shared-styles';
import SolidElement from '../../internal/solid-element';
import type { SolidFormControl } from '../../internal/solid-element';

Expand Down Expand Up @@ -917,6 +918,7 @@ export default class SdInput extends SolidElement implements SolidFormControl {
*/
static styles = [
...SolidElement.styles,
interactiveStyles,
css`
:host {
@apply box-border relative inline-block text-left w-full;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { ifDefined } from 'lit/directives/if-defined.js';
import { LocalizeController } from '../../utilities/localize';
import { property, query } from 'lit/decorators.js';
import cx from 'classix';
import { interactiveStyles } from '../../internal/shared-styles';
import SolidElement from '../../internal/solid-element';

/**
Expand Down Expand Up @@ -342,6 +343,7 @@ export default class SdNavigationItem extends SolidElement {
*/
static styles = [
...SolidElement.styles,
interactiveStyles,
css`
:host {
@apply inline-block relative box-border;
Expand Down
2 changes: 2 additions & 0 deletions packages/components/src/components/scrollable/scrollable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { ifDefined } from 'lit/directives/if-defined.js';
import { LocalizeController } from '../../utilities/localize';
import { property, query, state } from 'lit/decorators.js';
import cx from 'classix';
import { interactiveStyles } from '../../internal/shared-styles';
import SolidElement from '../../internal/solid-element';

/**
Expand Down Expand Up @@ -409,6 +410,7 @@ export default class SdScrollable extends SolidElement {

static styles = [
...SolidElement.styles,
interactiveStyles,
css`
:host {
--gradient-color: transparent;
Expand Down
2 changes: 2 additions & 0 deletions packages/components/src/components/step/step.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { ifDefined } from 'lit/directives/if-defined.js';
import { property } from 'lit/decorators.js';
import { watch } from '../../internal/watch';
import cx from 'classix';
import { paragraphStyles } from '../../internal/shared-styles';
import SolidElement from '../../internal/solid-element';
/**
* @summary Steps are used inside [step groups](/components/step-group) to guide users through the steps of a process or task..
Expand Down Expand Up @@ -338,6 +339,7 @@ export default class SdStep extends SolidElement {

static styles = [
...SolidElement.styles,
paragraphStyles,
css`
:host {
@apply flex-1;
Expand Down
2 changes: 2 additions & 0 deletions packages/components/src/components/tab-group/tab-group.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { LocalizeController } from '../../utilities/localize';
import { property, query, state } from 'lit/decorators.js';
import { scrollIntoView } from '../../internal/scroll';
import cx from 'classix';
import { interactiveStyles } from '../../internal/shared-styles';
import SolidElement from '../../internal/solid-element';
import type SdTab from '../tab/tab';
import type SdTabPanel from '../tab-panel/tab-panel';
Expand Down Expand Up @@ -452,6 +453,7 @@ export default class SdTabGroup extends SolidElement {

static styles = [
...SolidElement.styles,
interactiveStyles,
css`
:host {
@apply block box-border;
Expand Down
5 changes: 4 additions & 1 deletion packages/components/src/components/tag/tag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import { ifDefined } from 'lit/directives/if-defined.js';
import { LocalizeController } from '../../utilities/localize';
import { property, query } from 'lit/decorators.js';
import cx from 'classix';
import { interactiveStyles } from '../../internal/shared-styles';
import { token } from '../../internal/token';
import SolidElement from '../../internal/solid-element';

/**
Expand Down Expand Up @@ -116,7 +118,7 @@ export default class SdTag extends SolidElement {
this.emit('sd-hide');

this.style.opacity = '0';
await new Promise(resolve => setTimeout(resolve, this.token('--sd-duration-fast', 150)));
await new Promise(resolve => setTimeout(resolve, token(this, '--sd-duration-fast', 150)));
this.hidden = true;

this.emit('sd-after-hide');
Expand Down Expand Up @@ -198,6 +200,7 @@ export default class SdTag extends SolidElement {

static styles = [
...SolidElement.styles,
interactiveStyles,
css`
:host {
@apply inline-block transition-opacity duration-fast ease-in-out;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { customElement } from '../../internal/register-custom-element';
import { HasSlotController } from '../../internal/slot';
import { property, query } from 'lit/decorators.js';
import cx from 'classix';
import { interactiveStyles } from '../../internal/shared-styles';
import SolidElement from '../../internal/solid-element';
/**
* @summary Teasers group information into flexible containers so users can browse a collection of related items and actions.
Expand Down Expand Up @@ -159,6 +160,7 @@ export default class SdTeaserMedia extends SolidElement {

static styles = [
...SolidElement.styles,
interactiveStyles,
css`
:host {
@apply block;
Expand Down
2 changes: 2 additions & 0 deletions packages/components/src/components/tooltip/tooltip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { property, query } from 'lit/decorators.js';
import { waitForEvent } from '../../internal/event';
import { watch } from '../../internal/watch';
import cx from 'classix';
import { interactiveStyles } from '../../internal/shared-styles';
import SolidElement from '../../internal/solid-element';
import type SdPopup from '../popup/popup';

Expand Down Expand Up @@ -369,6 +370,7 @@ export default class SdTooltip extends SolidElement {
}
static styles = [
...SolidElement.styles,
interactiveStyles,
css`
:host {
--hide-delay: 0ms;
Expand Down
5 changes: 4 additions & 1 deletion packages/components/src/components/video/video.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { HasSlotController } from '../../internal/slot';
import { LocalizeController } from '../../utilities/localize';
import { property, query } from 'lit/decorators.js';
import cx from 'classix';
import { interactiveStyles } from '../../internal/shared-styles';
import { token } from '../../internal/token';
import SolidElement from '../../internal/solid-element';

/**
Expand Down Expand Up @@ -64,7 +66,7 @@ export default class SdVideo extends SolidElement {
if (!(this.poster instanceof HTMLImageElement)) return;

this.poster.style.opacity = '0';
await new Promise(resolve => setTimeout(resolve, this.token('--sd-duration-medium', 300)));
await new Promise(resolve => setTimeout(resolve, token(this, '--sd-duration-medium', 300)));
this.poster.style.display = 'none';
}

Expand Down Expand Up @@ -160,6 +162,7 @@ export default class SdVideo extends SolidElement {

static styles = [
...SolidElement.styles,
interactiveStyles,
css`
:host {
@apply relative inline-block overflow-hidden;
Expand Down
15 changes: 15 additions & 0 deletions packages/components/src/internal/shared-styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { unsafeCSS } from 'lit';

const css = unsafeCSS;

export const interactiveStyles = css`
@import '../styles/src/modules/interactive.css';
`;

export const headlineStyles = css`
@import '../styles/src/modules/headline.css';
`;

export const paragraphStyles = css`
@import '../styles/src/modules/paragraph.css';
`;
Loading
Loading