Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom item template support #165

Closed
jouni opened this issue Feb 22, 2016 · 5 comments
Closed

Custom item template support #165

jouni opened this issue Feb 22, 2016 · 5 comments
Assignees

Comments

@jouni
Copy link
Member

jouni commented Feb 22, 2016

Split from #96, where this was already researched.

Research report

Exposing items template is one step beyond the scope of this task. Despite that, it was also prototyped to get the idea of its complexity level.

The prototype branch contains a draft but working implementation: https://github.com/vaadin/vaadin-combo-box/tree/proto/custom-item-template

Exposing an item template is a complex task as well (roughly at the sample level, I’d say). While possible per se, still it requires to introduce a separate vaadin-combo-box-item element and expose the iron-list in the light DOM of the overlay. Deep explanation of the problems below.

  • To achieve that, the first idea was to set the entire iron-list item template with the template provided in the combo-box light DOM.
    • Turned out to be impractical: we still need to have an .item node defined inside the overlay, assigning model and state attributes (like id with index, selected, focused, ARIA role and aria-selected) and basic styles to it.
  • The second idea was: instead of replacing the entire item template, try to compose the built-in item template with the one from the outside, inserting it manually inside the .item wrapper.
    • Hard to implement. The puzzle is: when registering the overlay element, Polymer parses the contents of <template> nodes as well, extracting bindings into the annotations. After this parsing at the register time, it’s impossible to modify the contents of the item template.
      • Tried to disable parsing bindings on the overlay register by adding <template preserve-content> (undocumented Polymer feature) attribute to the iron-list item template. This makes it possible to modify the item template, but at the same time effectively prevents the .item bindings to the overlay methods from being parsed and working. Hence the focused indication and ARIA attributes don’t work.
  • The working idea: instead of manually modifying the item template, change the div.item into a separate vaadin-combo-box-item element, that would support custom template in the template property. This is currently implemented in the prototype branch.
    • For the item element, we need to templatize() it with either a given template or a default item template, stamp a template instance and append it to the light DOM. The changes to the bound item model should be updated on the stamped template instance manually.
    • iron-list exposes the item nodes in the light DOM. But still the overlay also needs to expose the iron-list in the light DOM, in order to be targetable with global CSS.

Related issues

@web-padawan
Copy link
Member

web-padawan commented Jul 12, 2016

@jouni is this task still in the backlog?
Actually I have to use ugly code with deprecated selectors like this to apply some styling to items:

            body > #overlay::shadow .item {
                white-space: normal;
            }

            body > #overlay::shadow .item[selected] {
                color: var(--main-text-color);
                background: var(--combo-box-selected-item-background);
            }

@jouni
Copy link
Member Author

jouni commented Aug 16, 2016

@web-padawan, thanks for asking!

This feature is still on very high priority, but we’re a bit hesitant in working on it just yet, as we’re waiting for the Polymer team to finalise their work on new overlay elements, so that we can be compatible with that.

The biggest problem at the moment is how to make CSS work so that it is still scoped somehow, while the overlay element resides outside the shadow DOM boundary of the owning element, and still keep the developer experience somewhat consistent with regular element styling.

The situation should clarify during the next months.

@jouni jouni added the backlog label Oct 4, 2016
@Saulis Saulis added needs research More information needed to estimate sprint backlog and removed backlog labels Dec 22, 2016
@Saulis Saulis changed the title Custom item template support Custom item template support [1d] Dec 22, 2016
@platosha
Copy link
Contributor

An idea of using CSS style modules for styling the items came to our mind. For example:

<dom-module id="my-item-styles">
  <template>
    <style>
      div {
        color: red;
      }
    </style>
  </template>
</dom-module>

<div>Global scope. This should not be red.</div>

<vaadin-combo-box items-style-module="my-item-styles" items="[1, 2, 3]">
  <template>
    <div>Item scope. This should be red.</div>
  </template>
</vaadin-combo-box>

Appending the style modules programmatically will not be simple, but still possible. After some prototyping with @Saulis, we’ve concluded, that this has to be implemented differently, depending on the Polymer version and DOM mode.

In general, with shadow DOM, simply appending a <style> tag under a shadow root works fine, applying the styles inside the scope, but not leaking them outside. But with Shady DOM, the imported <style> from a module has to be appended to the document, which requires some scoping processing for it to prevent leaking styles to the global scope.

  • With Polymer v1 using shadow DOM mode, we could use <style include="style-module-name"> inside the shadow root of the overlay.
  • With Polymer v1 using shady DOM mode, we have to call Polymer.StyleTransformer.css(styleModuleCssText, overlay.is) manually to process the styles, then we have to append them to the document. See: http://jsbin.com/gefaveraso/edit?html,output
  • With Polymer v2 using shadow DOM mode, we could get the CSS text from the module and append it with a <style> tag inside the shadow root of the overlay.
  • With Polymer v2 using shady DOM mode, we have to call ShadyCSS.prepareTemplate(styleModuleTemplate, overlay.is) to get the styles processed and applied to the specified scope. This is a documented API of the ShadyCSS polyfill.

See also: Polymer/polymer#3123

@jouni
Copy link
Member Author

jouni commented Dec 23, 2016

One question: it would still be possible to style the item templates using global CSS, right? So it would not be mandatory to write a DOM module for them? I would think that’s a more common use case, and the developer/designer just makes sure themselves to scope the styles properly (with BEM style selectors or something similar).

@Saulis Saulis removed the needs research More information needed to estimate label Dec 27, 2016
@Saulis Saulis changed the title Custom item template support [1d] Custom item template support Dec 27, 2016
@upstairlounge
Copy link

Decided to split out the custom styling into its own ticket. In the scope of this ticket, we'll just handle the stamping of the custom item template and placing the item instance.

@Saulis Saulis removed the in review label Jan 23, 2017
manolo pushed a commit to vaadin/vaadin-combo-box-flow that referenced this issue Oct 3, 2020
manolo pushed a commit to vaadin/vaadin-combo-box-flow that referenced this issue Oct 3, 2020
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

No branches or pull requests

5 participants