::part Additions
Hi, since new paradigm conserning Custom Pseudo Elements have been introduced http://lists.w3.org/Archives/Public/public-webapps/2013AprJun/0985.html (part 5) I'd like to suggest few additions/changes: 1/ ability to style nested shadow dom elements 2/ change of part attribute from DOMString to DOMTokenList 3/ ability to create complex selectors using ::part the description/reasoning for this can be found here: http://projects.webnt.eu/spec/shadow/index.php In case ::part will not be in spec, the same still applies to pseudos Bronislav Klucka
Re: ::part Additions
On Tue, Jul 2, 2013 at 6:32 AM, Bronislav Klučka wrote: > Hi, > > since new paradigm conserning Custom Pseudo Elements have been introduced > http://lists.w3.org/Archives/Public/public-webapps/2013AprJun/0985.html > (part 5) > > I'd like to suggest few additions/changes: > > 1/ ability to style nested shadow dom elements We discussed this in a previous meeting (surfacing nested component parts, either automatically or via a switch) but I don't recall what the conclusion was. Dimitri? > 2/ change of part attribute from DOMString to DOMTokenList This sounds all right. part='' is already class-like, since multiple elements can have the same part='' value. The example at your page is pretty compelling about this ability's usage. I guess ::part() would also expand to taking a list of idents. > 3/ ability to create complex selectors using ::part Interesting! I guess it would just surface a synthesized tree based on only the elements that contain part=''? That is, two elements would have a parent-child relationship (and thus be selectable with the > combinator) if they were the closest elements with part='', even if there were other elements between them? Like: ~TJ
Re: ::part Additions
On Tue, Jul 2, 2013 at 8:28 AM, Tab Atkins Jr. wrote: > We discussed this in a previous meeting (surfacing nested component > parts, either automatically or via a switch) but I don't recall what > the conclusion was. Dimitri? The issue is tracked by https://www.w3.org/Bugs/Public/show_bug.cgi?id=22462, but I haven't had a chance to look at this in depth yet. :DG<
Re: ::part Additions
On 2.7.2013 17:28, Tab Atkins Jr. wrote: On Tue, Jul 2, 2013 at 6:32 AM, Bronislav Klučka wrote: Hi, since new paradigm conserning Custom Pseudo Elements have been introduced http://lists.w3.org/Archives/Public/public-webapps/2013AprJun/0985.html (part 5) I'd like to suggest few additions/changes: 1/ ability to style nested shadow dom elements We discussed this in a previous meeting (surfacing nested component parts, either automatically or via a switch) but I don't recall what the conclusion was. Dimitri? As Dimitri mentioned, there is a bug https://www.w3.org/Bugs/Public/show_bug.cgi?id=22462 I'm mentioning it in my document, I'm fine with this solution, the question there is with default value. 2/ change of part attribute from DOMString to DOMTokenList This sounds all right. part='' is already class-like, since multiple elements can have the same part='' value. The example at your page is pretty compelling about this ability's usage. I guess ::part() would also expand to taking a list of idents. Why would it? We have established convention for AND operator .class1.class2 would became ::part(node-checked)::part(node-selected) and for OR operator .class1, .class2 would became ::part(node-checked), ::part(node-selected) :matches(.class1, .class2) would became :matches(::part(node-checked), ::part(node-selected)) 3/ ability to create complex selectors using ::part Interesting! I guess it would just surface a synthesized tree based on only the elements that contain part=''? That is, two elements would have a parent-child relationship (and thus be selectable with the > combinator) if they were the closest elements with part='', even if there were other elements between them? Like: ~TJ Interesting point, maybe little bit counter intuitive for some people, but since it's shadow and we are essentially targeting the only visible parts within the DOM it makes sense Brona
Re: ::part Additions
On Tue, Jul 2, 2013 at 8:52 AM, Bronislav Klučka wrote: > On 2.7.2013 17:28, Tab Atkins Jr. wrote: >> On Tue, Jul 2, 2013 at 6:32 AM, Bronislav Klučka >> wrote: >>> 2/ change of part attribute from DOMString to DOMTokenList >> This sounds all right. part='' is already class-like, since multiple >> elements can have the same part='' value. The example at your page is >> pretty compelling about this ability's usage. I guess ::part() would >> also expand to taking a list of idents. > > Why would it? We have established convention for AND operator > .class1.class2 > would became > ::part(node-checked)::part(node-selected) > > and for OR operator > .class1, .class2 > would became > ::part(node-checked), ::part(node-selected) > > :matches(.class1, .class2) > would became > :matches(::part(node-checked), ::part(node-selected)) Oh, no no no. ::part() is not a pseudo-class, it's a pseudo-element - it points to a brand new element, rather than filtering the one you've got. The fact that part='' is acting like class='' notwithstanding, using ::part() like would be an abuse of the syntax. If we want to support this, it has to be through something like "::part(node-checked node-selected)". As an example of why violating the syntax model is a bad idea, this directly conflicts with your desire to surface the ::part()s of nested components - the thing that exposes them might be exposed as a ::part() as well, so you need to be able to chain off of an existing ::part(), like "x-video::part(controls)::part(play-button)" (assuming the controls were actually implemented by another component nested inside the shadow tree). ~TJ
Re: ::part Additions
On 2.7.2013 18:03, Tab Atkins Jr. wrote: On Tue, Jul 2, 2013 at 8:52 AM, Bronislav Klučka wrote: On 2.7.2013 17:28, Tab Atkins Jr. wrote: On Tue, Jul 2, 2013 at 6:32 AM, Bronislav Klučka wrote: 2/ change of part attribute from DOMString to DOMTokenList This sounds all right. part='' is already class-like, since multiple elements can have the same part='' value. The example at your page is pretty compelling about this ability's usage. I guess ::part() would also expand to taking a list of idents. Why would it? We have established convention for AND operator .class1.class2 would became ::part(node-checked)::part(node-selected) and for OR operator .class1, .class2 would became ::part(node-checked), ::part(node-selected) :matches(.class1, .class2) would became :matches(::part(node-checked), ::part(node-selected)) Oh, no no no. ::part() is not a pseudo-class, it's a pseudo-element - it points to a brand new element, rather than filtering the one you've got. The fact that part='' is acting like class='' notwithstanding, using ::part() like would be an abuse of the syntax. If we want to support this, it has to be through something like "::part(node-checked node-selected)". As an example of why violating the syntax model is a bad idea, this directly conflicts with your desire to surface the ::part()s of nested components - the thing that exposes them might be exposed as a ::part() as well, so you need to be able to chain off of an existing ::part(), like "x-video::part(controls)::part(play-button)" (assuming the controls were actually implemented by another component nested inside the shadow tree). ~TJ so x-video::part(controls)::part(play-button) would target part="play-button" within part="controls" within x-video? and the list of idents ::part(part1 part2) {without comma? with comma?} would target part="part1 part2"? an AND operator? the OR I've mentioned being correct? so how about this: ::part(node-checked)::part(node-selected) would represent any selected node within checked node (regardless of level of nesting) ::part(node-checked) > ::part(node-selected) would represent selected node within checked node (directly within, no other part in between) ? Brona
Re: ::part Additions
On 2.7.2013 18:03, Tab Atkins Jr. wrote: On Tue, Jul 2, 2013 at 8:52 AM, Bronislav Klučka wrote: On 2.7.2013 17:28, Tab Atkins Jr. wrote: On Tue, Jul 2, 2013 at 6:32 AM, Bronislav Klučka wrote: 2/ change of part attribute from DOMString to DOMTokenList This sounds all right. part='' is already class-like, since multiple elements can have the same part='' value. The example at your page is pretty compelling about this ability's usage. I guess ::part() would also expand to taking a list of idents. Why would it? We have established convention for AND operator .class1.class2 would became ::part(node-checked)::part(node-selected) and for OR operator .class1, .class2 would became ::part(node-checked), ::part(node-selected) :matches(.class1, .class2) would became :matches(::part(node-checked), ::part(node-selected)) Oh, no no no. ::part() is not a pseudo-class, it's a pseudo-element - it points to a brand new element, rather than filtering the one you've got. The fact that part='' is acting like class='' notwithstanding, using ::part() like would be an abuse of the syntax. If we want to support this, it has to be through something like "::part(node-checked node-selected)". As an example of why violating the syntax model is a bad idea, this directly conflicts with your desire to surface the ::part()s of nested components - the thing that exposes them might be exposed as a ::part() as well, so you need to be able to chain off of an existing ::part(), like "x-video::part(controls)::part(play-button)" (assuming the controls were actually implemented by another component nested inside the shadow tree). ~TJ And back to x-video::part(controls)::part(play-button) example how it would be different from x-video ::part(controls) ::part(play-button) or this wouldn't be possible? the only possibilities being ::part(play-button) or ::part(controls)::part(play-button) or x-video::part(controls)::part(play-button) Brona
Re: ::part Additions
On 2.7.2013 18:21, Bronislav Klučka wrote: On 2.7.2013 18:03, Tab Atkins Jr. wrote: On Tue, Jul 2, 2013 at 8:52 AM, Bronislav Klučka wrote: On 2.7.2013 17:28, Tab Atkins Jr. wrote: On Tue, Jul 2, 2013 at 6:32 AM, Bronislav Klučka wrote: 2/ change of part attribute from DOMString to DOMTokenList This sounds all right. part='' is already class-like, since multiple elements can have the same part='' value. The example at your page is pretty compelling about this ability's usage. I guess ::part() would also expand to taking a list of idents. Why would it? We have established convention for AND operator .class1.class2 would became ::part(node-checked)::part(node-selected) and for OR operator .class1, .class2 would became ::part(node-checked), ::part(node-selected) :matches(.class1, .class2) would became :matches(::part(node-checked), ::part(node-selected)) Oh, no no no. ::part() is not a pseudo-class, it's a pseudo-element - it points to a brand new element, rather than filtering the one you've got. The fact that part='' is acting like class='' notwithstanding, using ::part() like would be an abuse of the syntax. If we want to support this, it has to be through something like "::part(node-checked node-selected)". As an example of why violating the syntax model is a bad idea, this directly conflicts with your desire to surface the ::part()s of nested components - the thing that exposes them might be exposed as a ::part() as well, so you need to be able to chain off of an existing ::part(), like "x-video::part(controls)::part(play-button)" (assuming the controls were actually implemented by another component nested inside the shadow tree). ~TJ And back to x-video::part(controls)::part(play-button) example how it would be different from x-video ::part(controls) ::part(play-button) or this wouldn't be possible? the only possibilities being ::part(play-button) or ::part(controls)::part(play-button) or x-video::part(controls)::part(play-button) Brona I do not want to spam this topic so just last thought on pseudo-elements and custom pseudo elements (parts), it's more generic issue (CSS selector syntax) the no-space syntax can work when there is only one pseudo-element and usually the last one p::first-letter - makes sense thou as an "element:: it would be better to for something like p ::first-letter or p > ::first-letter not to target first letters in SPANs in P.. because its element within other element... not a filter but when we start to nest and go more complex it becomes really strange consider chessboard -- with regular HTML+CSS one would go for something like table td { background: silver; } table tr:nth-of-child(2n + 1) td:nth-of-child(2n), table tr:nth-of-child(2n) td:nth-of-child(2n + 1) { background: black; } -- my way (wrong way) chessboard ::part(cell) { background: silver; } chessboard ::part(row):nth-of-child(2n + 1) ::part(cell):nth-of-child(2n), chessboard ::part(row):nth-of-child(2n) ::part(cell):nth-of-child(2n + 1) { background: black; } nesting working as usual (no change there), replacing TR and TD with custom counterparts - intuitive, easy -- correct way chessboard::part(cell) { background: silver; } chessboard::part(row):nth-of-child(2n + 1)::part(cell):nth-of-child(2n), chessboard::part(row):nth-of-child(2n)::part(cell):nth-of-child(2n + 1) { background: black; } mixing of pseudo classes and pseudo elements into one strange selector one have to carefully read to separate parts, what is pseudo element, what is pseudo class. -- the fact is, that no space creates filtering and space created nesting is throughout the CSS, regardless of selector (tag, class, id, attrribute), with this only exception. pseudo element is not actually filter on set of parents, but nested parts of all parents p ::part(this1) + ::part(this2) makes sense and only one sense p::part(this1) + p::part(this2) is confusing as I wrote above, nesting several pseudo elements, allowing complex selectors makes this a lot more confusing. Brona
Re: ::part Additions
On Tue, Jul 2, 2013 at 9:16 AM, Bronislav Klučka wrote: > On 2.7.2013 18:03, Tab Atkins Jr. wrote: >> On Tue, Jul 2, 2013 at 8:52 AM, Bronislav Klučka >> wrote: >>> >>> On 2.7.2013 17:28, Tab Atkins Jr. wrote: On Tue, Jul 2, 2013 at 6:32 AM, Bronislav Klučka wrote: > > 2/ change of part attribute from DOMString to DOMTokenList This sounds all right. part='' is already class-like, since multiple elements can have the same part='' value. The example at your page is pretty compelling about this ability's usage. I guess ::part() would also expand to taking a list of idents. >>> >>> Why would it? We have established convention for AND operator >>> .class1.class2 >>> would became >>> ::part(node-checked)::part(node-selected) >>> >>> and for OR operator >>> .class1, .class2 >>> would became >>> ::part(node-checked), ::part(node-selected) >>> >>> :matches(.class1, .class2) >>> would became >>> :matches(::part(node-checked), ::part(node-selected)) >> >> Oh, no no no. ::part() is not a pseudo-class, it's a pseudo-element - >> it points to a brand new element, rather than filtering the one you've >> got. The fact that part='' is acting like class='' notwithstanding, >> using ::part() like would be an abuse of the syntax. If we want to >> support this, it has to be through something like "::part(node-checked >> node-selected)". >> >> As an example of why violating the syntax model is a bad idea, this >> directly conflicts with your desire to surface the ::part()s of nested >> components - the thing that exposes them might be exposed as a >> ::part() as well, so you need to be able to chain off of an existing >> ::part(), like "x-video::part(controls)::part(play-button)" (assuming >> the controls were actually implemented by another component nested >> inside the shadow tree). > > so > x-video::part(controls)::part(play-button) > would target part="play-button" within part="controls" within x-video? Not quite what I intended. I was thinking that ::part(controls) would be an element or something, and ::part(play-button) would be in the shadow tree. > and the list of idents > ::part(part1 part2) {without comma? with comma?} > would target part="part1 part2"? an AND operator? > > the OR I've mentioned being correct? Yes to all. > so how about this: > > ::part(node-checked)::part(node-selected) > would represent any selected node within checked node (regardless of level > of nesting) > ::part(node-checked) > ::part(node-selected) > would represent selected node within checked node (directly within, no other > part in between) No, this is definitely inconsistent. The first one would have to be "::part(node-checked) ::part(node-selected)" (with a space between them). An alternative is to go the ::content route, and kill the parentheses. As soon as you type ::part, you're in the "surface shadow tree" of the component (which respects the shape of the real shadow tree, but may skip nodes), and can then use the standard selectors/combinators to get through it. You'd need some additional work to make multiple part values work, perhaps just treating part='' literally as a class, like: x-video::part .play-button Selecting multiple would be: x-tree::part .node-checked.node-selected (though I'd change the part='' stuff around so I could just write ".node.checked.selected") Selecting children would be: x-tree::part .node-checked .node-selected Descending into nested shadow trees would just involve adding more ::part pseudos to the correct places. ~TJ
Re: ::part Additions
there are still too many strange things going on :] see below On 2.7.2013 22:19, Tab Atkins Jr. wrote: On Tue, Jul 2, 2013 at 9:16 AM, Bronislav Klučka wrote: On 2.7.2013 18:03, Tab Atkins Jr. wrote: On Tue, Jul 2, 2013 at 8:52 AM, Bronislav Klučka wrote: On 2.7.2013 17:28, Tab Atkins Jr. wrote: On Tue, Jul 2, 2013 at 6:32 AM, Bronislav Klučka wrote: 2/ change of part attribute from DOMString to DOMTokenList This sounds all right. part='' is already class-like, since multiple elements can have the same part='' value. The example at your page is pretty compelling about this ability's usage. I guess ::part() would also expand to taking a list of idents. Why would it? We have established convention for AND operator .class1.class2 would became ::part(node-checked)::part(node-selected) and for OR operator .class1, .class2 would became ::part(node-checked), ::part(node-selected) :matches(.class1, .class2) would became :matches(::part(node-checked), ::part(node-selected)) Oh, no no no. ::part() is not a pseudo-class, it's a pseudo-element - it points to a brand new element, rather than filtering the one you've got. The fact that part='' is acting like class='' notwithstanding, using ::part() like would be an abuse of the syntax. If we want to support this, it has to be through something like "::part(node-checked node-selected)". As an example of why violating the syntax model is a bad idea, this directly conflicts with your desire to surface the ::part()s of nested components - the thing that exposes them might be exposed as a ::part() as well, so you need to be able to chain off of an existing ::part(), like "x-video::part(controls)::part(play-button)" (assuming the controls were actually implemented by another component nested inside the shadow tree). so x-video::part(controls)::part(play-button) would target part="play-button" within part="controls" within x-video? Not quite what I intended. I was thinking that ::part(controls) would be an element or something, and ::part(play-button) would be in the shadow tree. so it would select something like #SHADOW ROOT #SHADOW ROOT how is it, that one time the ::part targets element and other time attribute? or is it #SHADOW ROOT #SHADOW ROOT ? in both cases, how can you target element inside shadow tree? or do you essentially mean #SHADOW ROOT #SHADOW ROOT so the no space syntax means crossing shadow boudaries and space syntax means no crossing so x-video::part(controls) ::part(play-button) //with space would mean #SHADOW ROOT I have a problem with that, described below and the list of idents ::part(part1 part2) {without comma? with comma?} would target part="part1 part2"? an AND operator? the OR I've mentioned being correct? Yes to all. so how about this: ::part(node-checked)::part(node-selected) would represent any selected node within checked node (regardless of level of nesting) ::part(node-checked) > ::part(node-selected) would represent selected node within checked node (directly within, no other part in between) No, this is definitely inconsistent. The first one would have to be "::part(node-checked) ::part(node-selected)" (with a space between them). An alternative is to go the ::content route, and kill the parentheses. As soon as you type ::part, you're in the "surface shadow tree" of the component (which respects the shape of the real shadow tree, but may skip nodes), and can then use the standard selectors/combinators to get through it. You'd need some additional work to make multiple part values work, perhaps just treating part='' literally as a class, like: x-video::part .play-button Selecting multiple would be: x-tree::part .node-checked.node-selected (though I'd change the part='' stuff around so I could just write ".node.checked.selected") Selecting children would be: x-tree::part .node-checked .node-selected Descending into nested shadow trees would just involve adding more ::part pseudos to the correct places. And that is exactly the problem, TreeView, popup menu, pretty much every controls containers (thing about placing tabs into one tab of another tabs, that is placed into on tab of the third tabs) The shadow nesting could go on and on, there is no way you can style that without knowing the exact structure if I would want all LI to have disc, all I can do is type li { list-style-type: disc; } and it's always, everywhere If I would want all inactive tabs of TabControl (implemented using shadow) to have gray text color what would I do? just wondering... cannot target tab-control::part(tabs) ::part(inactive) - you cannot target element by it's name if the tab control is inside shadow dom inside shadow can you target ::part(tabs) ::part(inactive) without the element selector? does this goes all the way through
Re: ::part Additions
On Tue, Jul 2, 2013 at 5:00 PM, Bronislav Klučka wrote: > On 2.7.2013 22:19, Tab Atkins Jr. wrote: >> On Tue, Jul 2, 2013 at 9:16 AM, Bronislav Klučka >> wrote: >>> so >>> x-video::part(controls)::part(play-button) >>> would target part="play-button" within part="controls" within x-video? >> >> Not quite what I intended. I was thinking that ::part(controls) would >> be an element or something, and ::part(play-button) would >> be in the shadow tree. > > so it would select something like > >#SHADOW ROOT > > #SHADOW ROOT > > > > > how is it, that one time the ::part targets element and other time > attribute? or is it > > >#SHADOW ROOT > > #SHADOW ROOT > > > Sorry, this whole time I've been meaning: #SHADOW ROOT #SHADOW ROOT > x-video::part(controls) ::part(play-button) //with space > would mean > > >#SHADOW ROOT > > > > Yes. >> Descending into nested shadow trees would just involve adding more >> ::part pseudos to the correct places. > > And that is exactly the problem, TreeView, popup menu, pretty much every > controls containers (thing about placing tabs into one tab of another tabs, > that is placed into on tab of the third tabs) > The shadow nesting could go on and on, there is no way you can style that > without knowing the exact structure Right, but the problem you have then is exposing the structure. If you want to be able to style parts based on their position in the tree, you need to start with a consistent tree. Once you mix in shadow, you end up with elements having two sets of children, and you need to be able to distinguish between them. If you can give up the ability to style based on tree structure, and accept only styling based on part='' value, then we can just blindly expose nested things on the uppermost component, so you don't have to know whether they belong to the component itself or something deeper. ~TJ
Re: ::part Additions
On 3.7.2013 5:36, Steve Orvell wrote: 3/ ability to create complex selectors using ::part This concerns me. I will stipulate that you have shown this is useful and that this type of styling is not otherwise as easily achievable. The problem I see is that we've now exposed the structure of a shadowRoot as part of its 'public' styling api. If ::part(foo) > ::part(bar) is an important state, I'm then not allowed to move part bar with respect to part foo. This 'implementation detail' of its ShadowDOM is now set in stone. Perhaps we could achieve similar expressiveness without the inherent brittleness by adding the ability to specify parts that map to a complex selector specified within the shadowRoot. From JavaScript, this might be something like: shadowRootHost.addPart('foobar', '::part(foo) > ::part(bar)'); As tab mentioned in shadow, following parts should be in direct descendant - ancestor relationship, regardless of what is in between (there just can be no other part), I guess this is reasonable exposition, from Delphi / Visual Studio controls experience, in more complex complex controls one simply has to understand the relationship of publicly visible parts of control (if I would want to set an icon on the second tab of PageControl, I simply have to know, where i can find this tab {CustomerInfo.Tabs[1].Icon}) But I like your idea, much more generic and looking at it, since this is Shadow internal issue, I would go as far as shadowRootHost.addPart('article-time', 'article header time'); which would mean that all time elements in header elements in article within this shadow root would be reachable by ::part(article-time), and in next release one could change it to shadowRootHost.addPart('article-time', 'article header time,article footer time'); and ::part(article-time) would target both I like that, because it hides the internals and makes changes easier B. On Tue, Jul 2, 2013 at 6:32 AM, Bronislav Klučka mailto:bronislav.klu...@bauglir.com>> wrote: Hi, since new paradigm conserning Custom Pseudo Elements have been introduced http://lists.w3.org/Archives/Public/public-webapps/2013AprJun/0985.html (part 5) I'd like to suggest few additions/changes: 1/ ability to style nested shadow dom elements 2/ change of part attribute from DOMString to DOMTokenList 3/ ability to create complex selectors using ::part the description/reasoning for this can be found here: http://projects.webnt.eu/spec/shadow/index.php In case ::part will not be in spec, the same still applies to pseudos Bronislav Klucka