Skip to content

feat(compiler): CustomStateSet support#6574

Merged
johnjenkins merged 10 commits intomainfrom
feat-customStates
Jan 29, 2026
Merged

feat(compiler): CustomStateSet support#6574
johnjenkins merged 10 commits intomainfrom
feat-customStates

Conversation

@johnjenkins
Copy link
Contributor

@johnjenkins johnjenkins commented Jan 28, 2026

What is the current behavior?

As per the original issue #6285 - Stencil removed the barrier for devs to use CustomStateSet, however - it doesn't document their use within components.

What is the new behavior?

A new declarative api for documenting custom states has been added to the AttachInternals decorator:

@AttachInternals({
  states: {
      new: true, 
      /** If this item is older than 6 months old */
      archived: false
  },
}) internals: ElementInternals;

Results in:

Runtime:

constructor(...) {
    ....
    this.internals = this.attachInternals();
    this.internals.states.add("new");
}

Build time:

Custom-elements-manifest:

"customStates": [
  {
    "name": "archived",
    "description": "If this item is older than 6 months old"
  },
  {
    "name": "new"
  }
]

JSON docs:

"states": [
  {
    "name": "archived",
    "initialValue": false,
    "docs": "If this item is older than 6 months old"
  },
  {
    "name": "new",
    "initialValue": false,
    "docs": ""
  }
],

readme.md

## Custom States

| State              | Initial Value | Description                                                |
| ------------------ | ------------- | ---------------------------------------------------------- |
| `:state(new)`      | `true`        |                                                            |
| `:state(archived)` | `false`       | If this item is older than 6 months old                    |

Rationale

I didn't want to invoke too much Stencil magic; I believe this strikes a balance between quality-of-life and not straying too far from native APIs. After initialisation, users are free to use their internals as per any documentation found on the web.

Additionally, this pattern is extendible if we want to absorb any other meta around ElementInternals later e.g.:

@AttachInternals({
  states: { open: false },
  aria: {
    role: 'dialog'
  },
  form: {
    participates: true
  }
})
internals: ElementInternals;

Documentation

TODO

Does this introduce a breaking change?

  • Yes
  • No

Testing

Unit and WDIO

Other information

@johnjenkins johnjenkins requested a review from a team as a code owner January 28, 2026 00:12
@johnjenkins johnjenkins marked this pull request as draft January 28, 2026 00:13
@johnjenkins johnjenkins marked this pull request as ready for review January 28, 2026 09:45
@johnjenkins johnjenkins changed the title feat(compiler): customStates support feat(compiler): CustomStateSet support Jan 28, 2026
@johnjenkins johnjenkins merged commit cce1e23 into main Jan 29, 2026
69 checks passed
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.

1 participant