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

Meteor Web Component UI / Polymer #5

Open
grigio opened this issue Nov 20, 2014 · 57 comments
Open

Meteor Web Component UI / Polymer #5

grigio opened this issue Nov 20, 2014 · 57 comments

Comments

@grigio
Copy link

grigio commented Nov 20, 2014

I don't know if this is the right place to discuss about it, but I think "high level isolated components" should be easier to integrate in Meteor.

core topics:

  • Polymer and other UIs + Animation support don't play well with Meteor. Polymer uses native browser shadow dom.
  • An immediate solution is to use a Meteor animation library (ex. Momentum) and create the Meteor specific components (ex. Overlay)
  • 3rd part UIs (ex. MaterializeCSS grigio:materialize-sass ) should provide an API to call in .rendered to apply the rich UI decoration when needed (and not assume that everything is ready on document.ready)

Some links

@raix
Copy link
Contributor

raix commented Nov 20, 2014

I got tired of google groups - its completely impossible to keep track of ideas and feature requests. Here at least we have a change to track and discuss things that can be referenced on github. I'm not closing ideas here, and if things get enough traction/votes we have a better chance to influence @meteor

@raix
Copy link
Contributor

raix commented Nov 20, 2014

I'm not sure about polymer it self - but we need a pattern for creating reusable isolated components for blaze/meteor. I've played with it briefly at https://github.com/MeteorWidgets - having reusable components/widgets in general is important.

A feature in here could be a way to tag packages as "ui-components", making it easier to finde when searching.

I did ask @avital about this at Meteor day, but there was not eta on this. It could be a combination that they are short on time and they haven't found a good pattern yet.

@dandv
Copy link
Member

dandv commented Nov 20, 2014

A clearly recommended and well-integrated uniformly-styled modern set of widgets is what Meteor lacks most, towards rapid web app prototyping, I think. See What Meteor Lacks at the end of Why Meteor.

Something like Dijit or Kendo or Polymer/Paper would be great, but apparently it's not easy to integrate grids and other complex data components, and Bootstrap only has a few widgets.

@aldeed
Copy link

aldeed commented Nov 21, 2014

Currently looking into this with regard to having autoform natively support web components. No ETA, and probably won't be too soon.

@marcodejongh
Copy link

On one of the projects I am working on we tried to make re-useable components with spacebars.
Actually pretty easy to do for simple stuff like buttons. But its not very suitable for anything more complicated.

It ends up not being totally un-readable. For example if we make a basic step wizard the use of step control component ends up looking like this:

    {{#_StepControl}}
        {{#assignTemplate obj=this prop='backButtonCaption'}}Back{{/assignTemplate}}
        {{#assignTemplate obj=this prop='nextButtonCaption'}}Next{{/assignTemplate}}
        {{#assignTemplate obj=this prop='finishButtonCaption'}}Finish{{/assignTemplate}}
        {{#_addItem}}
            {{assignValues id="stepEmailType" active=true}}
            {{#assignTemplate obj=this prop='indexCaption'}}1{{/assignTemplate}}
            {{#_setCaption}}Step 1{{/_setCaption}}
            {{#_setContent}}{{> step1}}{{/_setContent}}
        {{/_addItem}}
        {{#_addItem}}
            {{assignValues id="stepConfigure"}}
            {{#assignTemplate obj=this prop='indexCaption'}}2{{/assignTemplate}}
            {{#_setCaption}}Step 2{{/_setCaption}}
            {{#_setContent}}{{> step2}} {{/_setContent}}
        {{/_addItem}}
        {{#_addItem}}
            {{assignValues id="stepPreview"}}
            {{#assignTemplate obj=this prop='indexCaption'}}3{{/assignTemplate}}
            {{#_setCaption}}Preview{{/_setCaption}}
            {{#_setContent}}{{> Step3 }} {{/_setContent}}
        {{/_addItem}}
        {{assignValues finalizer=dostuffwithdata}}
    {{/_StepControl}}

All the assign helpers actually add extra data to the context of the template its how you configure the template.

@awatson1978
Copy link

I had the same experience as @marcodejongh, which is why I've never been a real big fan of adding javascript parsing into the spacebar helpers. It mixes the responsibilities of files too much, and breaks the browsers HTML/JS/CSS division of responsibilities with regard to MVC. Same reason that inline <script> tags are an antipattern, imho.

That being said, the Blaze API really does provide a lot of the functionality needed to implement web components. Instead of using spacebar helpers, it just requires taking the time to actually use Blaze.getData, Blaze.toHTML, and Blaze.toHTMLWithData.

Also, I've been thinking that Blaze.View should be refactored to Blaze.Component or Blaze.Partial. It's like Deps, in that it's focused on core-development and not app-development. And in the same way that Deps got a lot of functionality into place, but eventually needed to be refactored to Tracker to be more app-developer centric, Blaze.View got a lot of functionality into place but isn't exactly what web browsers think of as what gets rendered into a ViewPort. It's wonky, and it seems to me that it might be better off as Blaze.Component or Blaze.Partial.

@marcodejongh
Copy link

@awatson1978 Do you have any examples you can share where you implement web components using the methods you mentioned?

@grigio
Copy link
Author

grigio commented Dec 4, 2014

In my opinion a way to have components is to have templates that you render when you need them (like https://github.com/grigio/meteor-overlay ) but it is very meteor specific.
You should be also be able to attach a datasource to them, imagine a color-picker which may be reused to pick a color for different "color fields"

Space ui adds complexity but also a clear isolation https://github.com/CodeAdventure/space-ui

@awatson1978
Copy link

@marcodejongh - Hmm, convoluted question. Lets see...

Here are links from a Card UI presentation given at the NY Meteor Meetup that's not strictly Meteor focused, but focused on Web Component integration.

I'm not 100% convinced Oasis and Conductor are where to start, as they're focused on sandboxed iFrames and HTML5 Web Messaging. It would be better to implement Web Components, then apply Oasis and Conductor. But they give some good research on what the end-goal might be.

However, having sat through those presentations and done a bit of research, I do think that webcomponent.js is maybe were we want to start.

And it looks like Ben Green has released the numtel:webcomponent package which wraps webcomponent.js.

Looking through the package, it's well documented, the MVC model seems consistent with browser standards, and Ben seems to know exactly what he's doing with this package. So, I'd recommend that everybody star that package, and rally around his efforts.

Once the polyfills are in place, then the question is one of packaging things up.

My first attempt at packaging up a component was a reactive-overlay package, similar to @grigio's meteor-overlay package. Mine is klunkier than his, and not as reusable. But it might be worth comparing/contrasting. It didn't work too well, and I wound up abandoning it for the most part.

The closest I've gotten to properly packaging things up since then is with maybe the clinical-ui-sidebar package. It doesn't even have any included HTML templating. But you can see it in action in the clinical-trials demo in the following two files:

https://github.com/awatson1978/clinical-trials/blob/master/client/app/app.layout.html
https://github.com/awatson1978/clinical-trials/blob/master/client/app/sidebar/westPanel.html

The westPanel.html could be moved into the clinical-ui-sidebars package, in theory. But there are a couple of problems in practice.

  1. The sidebar has some design assumptions that won't be consistent between apps. It assumes that there's a navbar header, and adds 50px of padding at the top. It assumes that it will underlay the navbar, rather than overlay it. And so forth.

Within the clinical-track, it's okay to make such design assumptions, because we can sort of say 'well, if it's going to use the ClinicalFramework, it's simply going to have a certain look-and-feel'. But that only goes so far. More generally, there will probably need to be some sort of configuration option for a component.

In the case of sidebars, it might be something like

{
backgroundColor: Color,
hasHeaderPadding: Boolean,
hasLogo: Boolean,
logoFile: String
}

That's not too horrible; even if somewhat tedious. And I wonder about using a package configuration pattern, like Nemo64 has done with meteor-bootstrap.

EDIT: Looking through @grigio's meteor-overlay package, I think he has a very valid pattern for configuring the component as a JSON object applied in a javascript function. Ideally, we would have both, maybe?
2. People are going to want custom list items. How do we go about injecting data into the HTML? That's the part that I'm hung up on, and where Blaze.toHTMLWithData seems like it might be the answer. But it returns as a string and isn't reactive, apparently. Which makes me question if it's really the solution.

Maybe the solution is simply sub-templates and defining collection APIs in the documentation. Maybe clinical:ui-sidebars should subscribe to a UISidebars or _UISidebars collection.

Anyhow, I'm going to look into adding numtel:webcomponent as a dependency, moving the westPanel.html file into the clinical:ui-sidebars package, and seeing what kind of resulting webcomponent might be made by putting those pieces together.

Also, I've been leaning towards using SemanticUI for Web Components, and moving away from Bootstrap-3. Jack Lukic has attended some of the NY Meteor Meetups, and his MVC approach seems to align better with WebComponents and general browser architecture than jQuery/Bootstrap.

@awatson1978
Copy link

Digging through the cookbook, I came up with maybe an even better example:

dropzone
dropzone-ui demo

Dropzone comes with a complete HTML component, is very close to having an object oriented API in the spacebar helper, attaches the Dropzone object on the window, and provides a javascript API to manipulate the component.

@grigio
Copy link
Author

grigio commented Dec 5, 2014

Here is a test https://github.com/grigio/meteor-component-test/blob/master/example.js using the component API of @stubailo

I like it, is possible to have easly components with shared or standalone data sources.

@yubozhao
Copy link

yubozhao commented Dec 5, 2014

Evented Mind has a iron component that is pretty easy to use, I use it for Form instead of using autoform

https://github.com/EventedMind/iron-component

@dandv
Copy link
Member

dandv commented Dec 5, 2014

@awatson1978

People are going to want custom list items. How do we go about injecting data into the HTML?

I'm working on making Sortable reactive for reorderable drag&drop lists. The way I let the user inject data is with a template.html in the package:

<template name="sortable">
    {{#each items}}
        {{> Template.contentBlock this}}
    {{/each}}
    {{setup}}
</template>
{{#sortable items=players options=myOptions}}

Did you mean something different?

@awatson1978
Copy link

That's very close to what I had in mind, actually. How is {{> Template.contentBlock this}} different than simply calling {{> contentBlock}}?

Also, it would be interesting to be able to do Template.sortable.registerElement('sortable'); and reference the component in HTML:

<!--  items would then need to be wired up to a reactive data source somehow -->
<sortable></sortable>

<!-- maybe add an id? -->
<sortable id="foo"></sortable>

<!-- or how about adding a bunch of attributes? -->
<sortable id="foo" items="players" options="myOptions"></sortable>

@grigio
Copy link
Author

grigio commented Dec 6, 2014

@dandv it seems quite clean an reusable. But I'm still confused how to share the "reactive data source" or the events between the component and the main app

@awatson1978 if you use <sortable></sortable> isn't harder to distinguish "Meteor Components" in templates from just "Custom html tags"?

Main app

  <div id="players_wrapper">
    <p>Some custom player notes</p>
    {{#sortable items=players}}
      <li>{{name}}-{{rank}}</li>
    {{/sortable}}
  </div>

  <div id="generic_wrapper">
    <p>Generic</p>
    {{#sortable items=items}}
      <li>{{name}}-{{rank}}</li>
    {{/sortable}}
  </div>

Components

<template name="sortable">
    <ul>
    {{#each items}}
        {{> Template.contentBlock this}}
    {{/each}}
    </ul>
</template>
  Component.define(Template.sortable, {
    rendered: function () {
      var el = Template.instance().firstNode;
      var sortable = Sortable.create(el);
    },
    helpers: {
    },
    events: {
      // Should be nice to catch the UI update here
      // and update the generic collection from here
    }
  });

@awatson1978
Copy link

@grigio... custom HTML tags are part of the W3C standard for webcomponents. Meteor doesn't get to simply make up it's own definition of what a webcomponent is.

Some background reference material:

I guess the question is: are we discussing WebComponents or are discussing some new-fangled "Meteor WebComponents"? I lean towards the former.

@grigio
Copy link
Author

grigio commented Dec 6, 2014

@awatson1978 I lean towards "Meteor Components" and then Web Components (/ Polymer), so a way to compose components which can emit events or share a reactive data source with the parent components (with existing technologies)

W3C Web Components are standards but:

  • use a <template> tag in a different way of Meteor
  • use shadow DOM, Meteor (Blaze virtual DOM)
  • work natively just in Chrome for now
  • ..
  • You need a Server Side Browser to render a Web Component, which isn't need with Blaze or React

I think the "Meteor Components" issue should be fixed before "Web Components integration", but some topics are common and can be fixed on both sides

@awatson1978
Copy link

Hmm. It seems that we agree that the 'Meteor Components' implementation needs to be figured out before 'Web Components' can be implemented.

However, I'm not sure that there's any real difference between the shadow DOM specified in the WebComponents spec and what MDG has implemented within the Blaze virtual DOM. To turn it around, if you wanted an extremely detailed low-level step-by-step description of how Blaze works, and how it's specifically able to work it's magic within web browsers, just reference the Shadow DOM spec:

http://w3c.github.io/webcomponents/spec/shadow/

The trick to remember is that web standards work two ways. It's not enough that MDG create awesome libraries. The browser developers have to commit to creating environments that guarantee those awesome libraries will work.

I guess what I'm trying to say is that Blaze is the Meteor WebComponent API. Or the closest thing to it. It's just named wonky. Like Deps was a klunky name, and got renamed to Tracker. Try to think of Blaze with other API names. (I've never been a fan of the Blaze.View naming convention, and think that it missed the mark precisely for these kinds of reasons. )

Blaze.renderFromShadowDOM
Blaze.renderWithData
Blaze.remove
Blaze.Shadow
Blaze.currentShadowDom
Blaze.getShadowDom
Blaze.With
Blaze.If

Similarly, I'm not entirely convinced that there's any truly substantive difference between how W3C defines <template> and how Meteor uses it. In theory, someone could simply register a template element to get past the builder, and proceed to use the Template API exactly as the W3C expects:

Template.foo.registerElement('template');

And polyfills are obviously in place to patch browsers until they get native support. So, yeah. I dunno. I guess I just don't see there being substantive differences. I think it's mostly all in place.

@awatson1978
Copy link

Just published a package using numtel:webcomponent to wrap a basic meteor component of sorts.

https://github.com/awatson1978/clinical-ui-alert-panel

The shadow DOM implementation that numtel:webcomponent provides will create a #shadow-root element, which expands to the meteor component. The meteor component is reactive, and will update the shadow DOM without any problem. So, that all seems to work very nicely.

screen shot 2014-12-06 at 3 41 13 pm

The only catch is that it doesn't seem that styling is getting applied to the shadow DOM.

@raix
Copy link
Contributor

raix commented Dec 7, 2014

I really like the paper / material (and the svg morpheus is a nice add on), I'm not that thrilled about Polymer, but it would be nice to benefit of the result. (I like the small animation details)

Core wants server-side rendering:
Ref to core about this

Meteor roadmap ref:
New object oriented api for ui components
Template and helper namespacing
Server side rendering

I want to be able to add check buttons etc. and not have to worry about animations/layout etc. (maybe colors)

I'Why arent we using svg animations a bit more, The ui could be pure svg?

@awatson1978
Copy link

Well, Differential appears to have ditched Famo.us for Polymer?
https://www.youtube.com/watch?v=DsATeVvMIm4

Looks like we're generally on the the right track in this discussion though. Presentation had #shadow-root elements and all of it.

@grigio
Copy link
Author

grigio commented Dec 10, 2014

I had the time to test a bit better the Meteor + Polymer integration and personally I think we could close this issue :)

  • Polymer fixes the problem of indipendent reusable "high level isolated components" + animations/transitions
  • Polymer works fine with Meteor with a few workarounds. NB: There could be some incompatibilities with non native webcomponents browsers on the Polymer side.
  • "Meteor Components" could wrap "custom Polymer components" + Meteor specific code

Here another example http://meteor-polymer-example.meteor.com and some more considerations

@marcodejongh
Copy link

@grigio I've been experimenting with it a little more and I must say I do end up making custom components a lot.

For example a data table solution as provided for normal applications will never work for meteor. So either I havent run into a way of making polymer listen to a reactive data property. OR I'm gonna end up recreating a lot of that kind of stuff.

@grigio
Copy link
Author

grigio commented Dec 10, 2014

@marcodejongh I agree, it depends what you mean with "component". A "reactive data table" doesn't seem something you can do in a Polymer component. But it should be a "Meteor Component" (not bind to a particular collection) which emits data changes via a ReactiveDict or some other reactive style ways (to be reusable in different contexts)

@marcodejongh
Copy link

@ryw Care to weigh in in the discussion? Maybe share some insights from your experiences?

@marcodejongh
Copy link

@grigio I guess that makes sense the only problem I have with it is that I would like to use the component directly in my feature (meteor)template.

So I would actually much rather find a way of reactively updating the data of the polymer element instead of wrapping it. Gonna read up on the databinding options polymer provides see if theres anything I can (ab)use for this.

Ideally I would prefer my meteor templates to look like this:

<template name="someForm>
    <awesome-polymer-table data="{{miniMongoCursor}}">
           <column>id</column>
           <column>name</column>
    </awesome-polymer-table>
</template>

@ryw
Copy link

ryw commented Dec 16, 2014

@marcodejongh we finally extracted some sample code https://github.com/Differential/polymer-demo

I didn't even realize that this lively discussion was going on over here — been pretty heads down lately trying to get http://usercycle.com MVP built. Great stuff though.

I've been encouraging MDG to try to fit W3C WebComponents into their vision for "Meteor components" because I really think WebComponents represents a potentially revolutionary leap in web application architecture — however it's still early and perhaps they don't end up "winning."

Integrating w/ Meteor has been painless, but we're just lightly using WebComponents so far (somewhat intentionally) because these are real products we're building that need to work :)

Happy to answer any other questions and share more code or explain what we're doing in the demo app.

@grigio
Copy link
Author

grigio commented Dec 16, 2014

@ryw Thanks for sharing.
Do you think is possibile to extract Meteor-Polymer component in packages ? At least for custom components?

I think it could be nice that Meteor components could inject rows like this in imports.html

<link rel="import" href="/components/di-form/di-form.html">
<link rel="import" href="/components/di-button/di-button.html">

@rgoomar
Copy link

rgoomar commented Dec 16, 2014

@grigio I don't think you could extract it from a package. It is a similar problem to the way CSS preprocessor files (like LESS and SASS) are handled for packages at this moment.

The way that @marcodejongh implemented it in packages works. But, after a certain amount of files, it may be importing too much. I mean, that was the reason behind using Vulcanize to concatenate the imports. But, on a small-scale application, it should work perfectly fine.

I'm excited to see what MDG does with Meteor Components.

@ryw
Copy link

ryw commented Dec 16, 2014

Yeah I think it's possible, you can see that we're actually inserting rows in the head tag during the Meteor build process here: https://github.com/Differential/meteor-vulcanize/blob/master/vulcanize.js

Tricky part in my mind is how to encapsulate real Meteor functionality inside of a Web Component — @schnie and I have been talking about how there is an ajax component in Polymer, maybe there is a similar package that implements DDP — sort of a "Meteor Lite" library that can interact with a Meteor backend. But it was late, our thoughts were fuzzy, and we haven't talked about it since then :)

We've only worked so far on putting Web Components into our Meteor, not Meteor into our Web Components. I like to think of this stuff through a specific use case, and here's our first idea...

See https://usercycle.com/project/ekxMvhGEGWwWbHi8x?interval=day&range=quarter — we were discussing how cool it'd be if we could provide a <usercycleChart> tag that would allow our users to embed our charts in their own dashboard, and for that the component would have to talk to our servers via ajax or more ideally DDP, and DDP would be cool :) That's all the thinking we've done on it so far, but excited for the prospect.

@marcodejongh
Copy link

@ryw Think the most awesome way to do this is to use the interface of the core-ajax element.

Then turn it's inner workings into a DDP client maybe using asteroid. That way you can grab any polymer element in existence that supports ajax and use it without having to change the module. You just have to import the meteor-core-ajax element instead of the default version

Of course a actual DDP datatransport would be better. But from what I can see none of the elements support defining a custom datatransport. And I much rather sacrifice a small bit of reactivity in favor of ease of re-use of premade elements. I would just set crazy fast polling to the meteor-core-ajax element.

@mquandalle
Copy link

@philcockfield, does UI Harness intend to fix this issue?

@offthegrass
Copy link

what do people think to this approach?

https://github.com/atoy40/meteor-polymer-music

@ryw
Copy link

ryw commented Mar 10, 2015

@offthegrass very cool :) I've talked w/ @schnie about an approach like this; going "pure polymer." One thing i noticed is "broken" back button and no routes. Have you looked into that yet? And have you tried using this on a larger app yet?

@mitar
Copy link

mitar commented Apr 8, 2015

Just released: https://github.com/peerlibrary/meteor-blaze-components

Blaze Components for Meteor are a system for easily developing complex UI elements that need to be reused around your Meteor app.

Feedback welcome. :-)

@awatson1978
Copy link

Initial read-through looks very promising, mitar. I like that you managed to get the inheritance and mixins working. Would like to see it all translated over to javascript, though. Am also thinking it would be great to see this wrapped in a webcomponent, so we could have custom defined html tags...

<ExampleComponent></ExampleComponent>

@jadsonlourenco
Copy link

@mitar Blaze Component that you did is so good, I try work with Polymer, but after some bugs to browser compatibility, etc. So I did some "component" like you, but your idea is much better, thank you! Now I will use that!

I agree with @awatson1978 to have custom HTML tag for each component, also use the same TAG name for register the component in JS, maybe <example-component></example-component>, to maintain de "web component" sintax.

@rgoomar
Copy link

rgoomar commented Apr 8, 2015

@mitar Looks great! But, I would like to see it in JavaScript as well.

@mitar
Copy link

mitar commented Apr 8, 2015

See live tutorial: http://components.meteor.com/

Would like to see it all translated over to javascript, though.

I can make an example.

Am also thinking it would be great to see this wrapped in a webcomponent, so we could have custom defined html tags...

My current plan is to allow wrapping web components into this components. So that you could use Blaze, React, or Polymer components interchangeably. So if you define a Polymer Component inside a this system, you could still do {{#PolymerTag args foo='bar'}}...{{/PolymerTag}} which would then be rendered as a <PolymerTag foo='bar'>...</PolymerTag>. So instead of going the webcomponent direction, I see them only as one possible implementation of these components.

But I have to think more about this. In any case, with current Blaze something like you are suggesting is not really possible. It would require changing the parser. So a job for somebody else.

@grigio
Copy link
Author

grigio commented Apr 8, 2015

Here is an example of a Meteor React reusable component https://github.com/grigio/meteor-react-overlay

@mitar
Copy link

mitar commented Apr 8, 2015

Yes, I will do something similar. But the idea is that they all share the same API. So when you do {{> IncludedComponent}} you do not have to care what is their rendering technology.

@aldeed
Copy link

aldeed commented Apr 9, 2015

Nice. This is definitely a step in the right direction. I'd like to eventually have autoform components based on a more general component api like this. It may be impacted by the lexical scope project, and of course I'd want to see whether there is community/MDG support for it or if they have a different direction in mind.

@mitar
Copy link

mitar commented Apr 9, 2015

I made an example in JavaScript and ES6: https://github.com/peerlibrary/meteor-blaze-components#javascript-and-es6-support

@rgoomar
Copy link

rgoomar commented Apr 9, 2015

Thanks @mitar!

@raix
Copy link
Contributor

raix commented Apr 9, 2015

looking promising @mitar maybe add Styles in there - eg. if at some point we want to leverage shadow dom or native...

@awatson1978
Copy link

I'm really liking this so far. I'm thinking of adding this to most all of my projects, but would love to hear something from MDG that they're thinking of something along these lines also. Some more thoughts as I dig deeper into this:

# this seems redundant?
ExampleComponent.register('ExampleComponent');

# can we do this instead?
BlazeComponent.register('ExampleComponent');

# or this?
Templates.registerComponent('ExampleComponent');

Also, what other functions should the Styles class expose? I've just been using a parseStyle function, and am pretty much sold on the json styling objects.

parseStyle = function(json){
  var result = "";
  $.each(json, function(i, val){
    result = result + i + ":" + val + " ";
  });
  return result;
}

Is Styles being dependent upon a jQuery function reasonable? Would underscore or vanilla node be better?

@mitar
Copy link

mitar commented Apr 15, 2015

Yes, ExampleComponent.register('ExampleComponent') and BlazeComponent.register('ExampleComponent') are equivalent. The question is more of a personal style. You can also do .register directly on the output of extendComponent. Or in CoffeeScript you can call @register inside of a class body.

Templates.registerComponent('ExampleComponent') would be misleading in my opinion. Also, I would like that templates are just one of the possible ways to render the component, when React and Polymer are another (that is why there is a base-component package, with the idea that we could wrap React and Poylmer in a similar way and then allow interoperability (you could include a Blaze Component from React Component and vice versa); registry of components would be shared in that case).

I do not know what that Styles class is? Can you link to what is that?

But I would prefer only underscore dependency. I think it is easier to achieve that than jQuery.

@offthegrass
Copy link

@mitar I think(?) that's a hypothetical Styles class.

This package uses in interesting approach to styling which would work across packages/components, something like..

/packages/app/styles.coffee

@Colour = {}
Colour.primary = new CSSC.Clr '#EEEEEE'
Colour.secondary...
/packages/ui-toolbar/styles.coffee

Meteor.startup ->
        @styles = new CSSC
        @styles
            .add '.toolbar',
                backgroundColor: Colour.primary

Ideally we'll eventually have a separate UI packaging system, i.e. meteor add --component toolbar

/components/toolbar

It's certainly not perfect, as far as I know there's nothing to stop styles leaking out if you accidentally use the same class again, so shadow DOM would be good.

@mitar
Copy link

mitar commented Apr 18, 2015

Hm, interesting. One option we are experimenting at the moment is by having a method on the class which returns styles. Which are applied as inline style into DOM. So you can extend and override it. So something like:

class FooBarComponent extends Component
  toolbarsStyle: ->
    bounds = @componentBounds()

    toolbarWidth = Math.max 500, bounds.width
    extraWidth = toolbarWidth - bounds.width

    left: -extraWidth / 2
    width: toolbarWidth

  css: (styleObject) ->
    style: CSSHelper.objectToString styleObject

class CSSHelper
  @objectToString: (styleObject) ->
    propertyStrings = for camelCaseKey, value of styleObject
      key = camelCaseKey.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase()

      # If a number was passed in, add the unit (except for certain CSS properties, as defined by jQuery)
      value += 'px' if typeof value is 'number' and not $.cssNumber[camelCaseKey]

      "#{key}: #{value};"

    propertyStrings.join ' '

And template:

<template name="FooBarComponent">
  <div class="toolbars" {{css toolbarsStyle}}>
    ...
  </div>
</template>

Seems to work pretty well for us. :-)

@offthegrass
Copy link

Edit: I just realised this is similar to the above.

Check this out.

Another approach to parsing a JS object into inline style using Absurd JS, specifically web components. Cross-browser support.

@offthegrass
Copy link

I made a quick port of a few polymer elements to BlazeComponents as a proof of concept:

Demo
Repo

@mitar
Copy link

mitar commented Apr 23, 2015

This looks awesome!

@mitar
Copy link

mitar commented Apr 23, 2015

If you are lacking any features, feel free to open tickets.

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

No branches or pull requests