Skip to content

feat(shared)!: add ElementInternalsMixin and @cssState decorator - #3612

Draft
jpzwarte wants to merge 3 commits into
fix/3415-disabled-switch-tooltip-v2from
feature/3610-css-state-decorator
Draft

feat(shared)!: add ElementInternalsMixin and @cssState decorator#3612
jpzwarte wants to merge 3 commits into
fix/3415-disabled-switch-tooltip-v2from
feature/3610-css-state-decorator

Conversation

@jpzwarte

Copy link
Copy Markdown
Member

Summary

Adds an ElementInternalsMixin and a @cssState decorator to @sl-design-system/shared, and uses
them across the components that work with ElementInternals and custom CSS states. Closes #3610.

  • ElementInternalsMixin attaches the ElementInternals and exposes them as elementInternals,
    so the component, its subclasses, other mixins and its tests all have one standardized way of
    getting to them. It replaces the readonly internals = this.attachInternals() line every form
    associated element had. A mixin instead of a decorator, because a decorator cannot add a member to
    the type of the class in either the legacy or the standard mode; a mixin can.
  • @cssState keeps a custom CSS state in sync with a boolean property or getter, replacing the
    hand written if (changes.has('x')) { states.add/delete } blocks in updated(). The state name
    defaults to the dasherized property name. It works with both the legacy
    (experimentalDecorators) and the standard TC39 decorators, and uses a single controller per
    element no matter how many properties it decorates.

Both are exported explicitly, as @sl-design-system/shared/mixins/element-internals.js and
@sl-design-system/shared/decorators/css-state.js, not through the barrels.

Breaking change

A Form Associated Custom Element now has to expose its ElementInternals as elementInternals
instead of internals, since that is what FormControlMixin reads the validity and form value
from. All the components in this repo have been updated; the internals property is gone from them.

Refactored

ElementInternalsMixin is applied to 14 components: button, button-bar, checkbox-group,
combobox, date-field, editor, radio-group, select, select-button, switch, tag,
time-field, toggle-button and tool-bar, plus the child-form example. It wraps LitElement
directly, so the mixins that use the internals sit above the one that provides them.

@cssState replaces the manual state juggling for 8 states in 4 components:

Component States
select-button clearable, clear-focused, has-selection
toggle-button pressed, icon-only, text-only
date-field placeholder-shown, has-value
time-field placeholder-shown, has-value

The toggle-button conversion also removes a workaround: render() reads the icon-only state, so
updated() compared the old and new value to trigger an extra requestUpdate(). @cssState
applies in hostUpdate(), before render, so that extra render pass is gone.

States that are computed from measurements or set from event handlers are left as they are
(tag, tool-bar, overflow, button, button-bar, and has-focus in the date and time field).
Converting those means giving them a backing property and deferring them to the next update, which
is a behaviour change rather than a refactor.

Notes

@changeset-bot

changeset-bot Bot commented Aug 18, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 1bf3b50

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 45 packages
Name Type
@sl-design-system/button Major
@sl-design-system/button-bar Major
@sl-design-system/checkbox Major
@sl-design-system/combobox Major
@sl-design-system/date-field Major
@sl-design-system/editor Major
@sl-design-system/radio-group Major
@sl-design-system/select Major
@sl-design-system/switch Major
@sl-design-system/tag Major
@sl-design-system/time-field Major
@sl-design-system/toggle-button Major
@sl-design-system/tool-bar Major
@sl-design-system/shared Minor
@sl-design-system/form Major
@sl-design-system/breadcrumbs Patch
@sl-design-system/calendar Patch
@sl-design-system/dialog Patch
@sl-design-system/drawer Patch
@sl-design-system/emoji Patch
@sl-design-system/grid Patch
@sl-design-system/infotip Patch
@sl-design-system/inline-message Patch
@sl-design-system/menu Patch
@sl-design-system/message-dialog Patch
@sl-design-system/paginator Patch
@sl-design-system/tree Patch
@sl-design-system/angular Patch
@sl-design-system/toggle-group Patch
@sl-design-system/panel Patch
@sl-design-system/accordion Patch
@sl-design-system/announcer Patch
@sl-design-system/avatar Patch
@sl-design-system/callout Patch
@sl-design-system/data-source Patch
@sl-design-system/format-date Patch
@sl-design-system/format-number Patch
@sl-design-system/number-field Patch
@sl-design-system/popover Patch
@sl-design-system/search-field Patch
@sl-design-system/tabs Patch
@sl-design-system/text-area Patch
@sl-design-system/text-field Patch
@sl-design-system/tooltip Patch
@sl-design-system/virtual-list Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Shared] Add ElementInternalsMixin and @cssState decorator

1 participant