From e84a27908b0bf6db1b7a47f4bbf554afc6fb9a0f Mon Sep 17 00:00:00 2001 From: Rakina Zata Amni Date: Mon, 2 Sep 2019 15:43:52 +1000 Subject: [PATCH 1/8] Add custom states and :state() pseudo class proposal --- .../custom-states-and-state-pseudo-class.md | 105 ++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 proposals/custom-states-and-state-pseudo-class.md diff --git a/proposals/custom-states-and-state-pseudo-class.md b/proposals/custom-states-and-state-pseudo-class.md new file mode 100644 index 00000000..98da77c3 --- /dev/null +++ b/proposals/custom-states-and-state-pseudo-class.md @@ -0,0 +1,105 @@ +# `ElementInternals.states` and the `:state()` pseudo class + +Author: @rakina, @domenic + +## Introduction + +Built-in elements have certain “states” that can change over time depending on user interaction and other factors, and are exposed to web authors through pseudo classes. For example, some form controls have the “invalid” state, which is exposed through the `:invalid` pseudo class. + +Like built-in elements, custom elements can have various states to be in too, and web authors might want to expose these states in a similar fashion as the built-in elements. With the proposed `ElementInternals.state` property, custom element authors can add and modify custom states for the custom elements, and allow them to be selected with the `:state()` selector. + +### Goals + +- Give a way for custom element authors to expose varying states of the custom elements to custom element users +- Allow styling of custom elements that differ according state +- Allow styling of custom elements that differ according to state even when they are only accessible via shadow parts. That is, `element::part(x):state(y)` should work if `::part(x)` selects a custom element with state y.. + + +### Non-goals + +- Allowing adding custom states to built-in elements. States reflect outward what the element implementation author wishes to show the world; for application-level state, use the `class=""` attribute or similar. +- Allowing custom element authors to modify already-existing/built-in states/pseudo classes, e.g. `:checked`. (This might be added in the future, though.) + +## Example + +```html + + + + + + +Continue? + +``` +## Proposal + +Add a `states` property to the [ElementInternals](https://html.spec.whatwg.org/multipage/custom-elements.html#elementinternals) interface to contain a list of states for the corresponding custom element, and a new `:state(x)` pseudo-class that can select custom elements that contains `x` in its `ElementInternals`' `state`. An example implementation of a custom element that uses this is shown above. + +## Alternatives considered + +### Just use attributes or class names on the custom element +This is bad because the custom element user might use clashing attribute names, causing problems. + + +### Exposing this on shadow host + + Since this is not really related to exposing things from within a shadow tree, it does not make much sense to add states to shadow hosts. [Initial discussions](https://github.com/w3c/webcomponents/issues/738) suggested such an API shape, but that was before we came up with the ElementInternals concept for manipulating state on custom elements. + + +### Allowing custom states to use the same syntax as built-in ones, e.g. `:foo` instead of `:state(foo)` + +This causes compatibility issues if we ever want to introduce new CSS pseudo-classes in the future that could apply to the element. + + +### Different syntax choices for custom states, e.g. :`--state` + +We are open to other suggestions. However the discussion so far seems to favor `:state()`. From d6c4551f2326a9f82a94a0881bafdb8388b13677 Mon Sep 17 00:00:00 2001 From: Rakina Zata Amni Date: Mon, 2 Sep 2019 17:01:37 +1000 Subject: [PATCH 2/8] Add "internals" --- proposals/custom-states-and-state-pseudo-class.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/custom-states-and-state-pseudo-class.md b/proposals/custom-states-and-state-pseudo-class.md index 98da77c3..89f32502 100644 --- a/proposals/custom-states-and-state-pseudo-class.md +++ b/proposals/custom-states-and-state-pseudo-class.md @@ -47,9 +47,9 @@ class LabeledCheckbox extends HTMLElement { set checked(flag) { this._checked = !!flag; if (this._checked) { - this.states.add("checked"); + this._internals.states.add("checked"); } else { - this.states.remove("checked"); + this._internals.states.remove("checked"); } } From 6200ed3679ecedb500313ac5e6da04b5dd98721c Mon Sep 17 00:00:00 2001 From: Rakina Zata Amni Date: Wed, 4 Sep 2019 11:28:18 +0800 Subject: [PATCH 3/8] Apply suggestions from code review Co-Authored-By: Domenic Denicola --- proposals/custom-states-and-state-pseudo-class.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/proposals/custom-states-and-state-pseudo-class.md b/proposals/custom-states-and-state-pseudo-class.md index 89f32502..62843adf 100644 --- a/proposals/custom-states-and-state-pseudo-class.md +++ b/proposals/custom-states-and-state-pseudo-class.md @@ -12,7 +12,7 @@ Like built-in elements, custom elements can have various states to be in too, an - Give a way for custom element authors to expose varying states of the custom elements to custom element users - Allow styling of custom elements that differ according state -- Allow styling of custom elements that differ according to state even when they are only accessible via shadow parts. That is, `element::part(x):state(y)` should work if `::part(x)` selects a custom element with state y.. +- Allow styling of custom elements that differ according to state even when they are only accessible via shadow parts. That is, `element::part(x):state(y)` should work if `::part(x)` selects a custom element with state y. ### Non-goals @@ -92,7 +92,7 @@ This is bad because the custom element user might use clashing attribute names, ### Exposing this on shadow host - Since this is not really related to exposing things from within a shadow tree, it does not make much sense to add states to shadow hosts. [Initial discussions](https://github.com/w3c/webcomponents/issues/738) suggested such an API shape, but that was before we came up with the ElementInternals concept for manipulating state on custom elements. + Since this is not really related to exposing things from within a shadow tree, it does not make much sense to add states to shadow hosts. [Initial discussions](https://github.com/w3c/webcomponents/issues/738) suggested such an API shape, but that was before we came up with the `ElementInternals` concept for manipulating state on custom elements. ### Allowing custom states to use the same syntax as built-in ones, e.g. `:foo` instead of `:state(foo)` @@ -100,6 +100,6 @@ This is bad because the custom element user might use clashing attribute names, This causes compatibility issues if we ever want to introduce new CSS pseudo-classes in the future that could apply to the element. -### Different syntax choices for custom states, e.g. :`--state` +### Different syntax choices for custom states, e.g. `:--state` We are open to other suggestions. However the discussion so far seems to favor `:state()`. From 21cc16ca7e3c96ef50462792d320561f97f7d002 Mon Sep 17 00:00:00 2001 From: Rakina Zata Amni Date: Wed, 4 Sep 2019 11:48:21 +0800 Subject: [PATCH 4/8] Update example --- .../custom-states-and-state-pseudo-class.md | 31 +++++++++++++------ 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/proposals/custom-states-and-state-pseudo-class.md b/proposals/custom-states-and-state-pseudo-class.md index 62843adf..b97b08c8 100644 --- a/proposals/custom-states-and-state-pseudo-class.md +++ b/proposals/custom-states-and-state-pseudo-class.md @@ -6,7 +6,7 @@ Author: @rakina, @domenic Built-in elements have certain “states” that can change over time depending on user interaction and other factors, and are exposed to web authors through pseudo classes. For example, some form controls have the “invalid” state, which is exposed through the `:invalid` pseudo class. -Like built-in elements, custom elements can have various states to be in too, and web authors might want to expose these states in a similar fashion as the built-in elements. With the proposed `ElementInternals.state` property, custom element authors can add and modify custom states for the custom elements, and allow them to be selected with the `:state()` selector. +Like built-in elements, custom elements can have various states to be in too, and web authors might want to expose these states in a similar fashion as the built-in elements. With the proposed `states` property on `ElementInternals`, custom element authors can add and modify custom states for the custom elements, and allow them to be selected with the `:state()` selector. ### Goals @@ -35,11 +35,11 @@ class LabeledCheckbox extends HTMLElement { this._shadowRoot = this.attachShadow({mode: "open"}); this._shadowRoot.innerHTML = - "\ - Label"; + ` + Label`; } get checked() { return this._checked; } @@ -64,8 +64,8 @@ class QuestionBox extends HTMLElement { super(); this._shadowRoot = this.attachShadow({mode: "open"}); this._shadowRoot.innerHTML = - "
Do you agree?
\ - Yes"; + `
Question
+ Yes`; } } customElements.define('labeled-checkbox', LabeledCheckbox); @@ -78,11 +78,24 @@ customElements.define('question-box', QuestionBox); Continue? + + + +You need to check this ``` ## Proposal -Add a `states` property to the [ElementInternals](https://html.spec.whatwg.org/multipage/custom-elements.html#elementinternals) interface to contain a list of states for the corresponding custom element, and a new `:state(x)` pseudo-class that can select custom elements that contains `x` in its `ElementInternals`' `state`. An example implementation of a custom element that uses this is shown above. +``` +partial interface mixin ElementInternals { + readonly attribute DOMTokenList states; +} +`` + +Add a `states` property to the [ElementInternals](https://html.spec.whatwg.org/multipage/custom-elements.html#elementinternals) interface to contain a list of states for the corresponding custom element, and a new `:state(x)` pseudo-class that can select custom elements that contains `x` in its `elementInternals.states`. An example implementation of a custom element that uses this is shown above. ## Alternatives considered From ffa755ddc3e7f8d1f065231bb831bbef19e37bcd Mon Sep 17 00:00:00 2001 From: Domenic Denicola Date: Wed, 4 Sep 2019 11:08:22 -0400 Subject: [PATCH 5/8] Fix IDL block --- proposals/custom-states-and-state-pseudo-class.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/custom-states-and-state-pseudo-class.md b/proposals/custom-states-and-state-pseudo-class.md index b97b08c8..176d7f05 100644 --- a/proposals/custom-states-and-state-pseudo-class.md +++ b/proposals/custom-states-and-state-pseudo-class.md @@ -89,11 +89,11 @@ customElements.define('question-box', QuestionBox); ``` ## Proposal -``` +```webidl partial interface mixin ElementInternals { readonly attribute DOMTokenList states; } -`` +``` Add a `states` property to the [ElementInternals](https://html.spec.whatwg.org/multipage/custom-elements.html#elementinternals) interface to contain a list of states for the corresponding custom element, and a new `:state(x)` pseudo-class that can select custom elements that contains `x` in its `elementInternals.states`. An example implementation of a custom element that uses this is shown above. From 7ccdb8a3a3003e8face410ecbd1c931217550a29 Mon Sep 17 00:00:00 2001 From: Domenic Denicola Date: Wed, 4 Sep 2019 11:10:15 -0400 Subject: [PATCH 6/8] Move simpler example first --- .../custom-states-and-state-pseudo-class.md | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/proposals/custom-states-and-state-pseudo-class.md b/proposals/custom-states-and-state-pseudo-class.md index 176d7f05..f2beeb9c 100644 --- a/proposals/custom-states-and-state-pseudo-class.md +++ b/proposals/custom-states-and-state-pseudo-class.md @@ -24,7 +24,8 @@ Like built-in elements, custom elements can have various states to be in too, an ```html - + + + + + +You need to check this + + + Continue? - - - -You need to check this - ``` ## Proposal From f81867a6ad4201a497257637d7bd3642387e6702 Mon Sep 17 00:00:00 2001 From: Domenic Denicola Date: Wed, 4 Sep 2019 11:11:27 -0400 Subject: [PATCH 7/8] Final minor tweaks --- proposals/custom-states-and-state-pseudo-class.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/proposals/custom-states-and-state-pseudo-class.md b/proposals/custom-states-and-state-pseudo-class.md index f2beeb9c..0bb32c36 100644 --- a/proposals/custom-states-and-state-pseudo-class.md +++ b/proposals/custom-states-and-state-pseudo-class.md @@ -85,7 +85,7 @@ customElements.define('question-box', QuestionBox); @@ -117,6 +117,6 @@ This is bad because the custom element user might use clashing attribute names, This causes compatibility issues if we ever want to introduce new CSS pseudo-classes in the future that could apply to the element. -### Different syntax choices for custom states, e.g. `:--state` +### Different syntax choices for custom states, e.g. `:--foo` -We are open to other suggestions. However the discussion so far seems to favor `:state()`. +We are open to other suggestions. However the discussion so far seems to favor `:state(foo)`. From 6ed12f489bb8a82bd195bc61d7f31a1df2dbf251 Mon Sep 17 00:00:00 2001 From: Domenic Denicola Date: Wed, 4 Sep 2019 11:12:10 -0400 Subject: [PATCH 8/8] Oh, also don't use static.prop for the title --- proposals/custom-states-and-state-pseudo-class.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/custom-states-and-state-pseudo-class.md b/proposals/custom-states-and-state-pseudo-class.md index 0bb32c36..213889b5 100644 --- a/proposals/custom-states-and-state-pseudo-class.md +++ b/proposals/custom-states-and-state-pseudo-class.md @@ -1,4 +1,4 @@ -# `ElementInternals.states` and the `:state()` pseudo class +# `ElementInternals`'s `states` property and the `:state()` pseudo class Author: @rakina, @domenic