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

Web Components support #336

Open
MartinKavik opened this issue Jan 17, 2020 · 14 comments
Open

Web Components support #336

MartinKavik opened this issue Jan 17, 2020 · 14 comments
Labels
API design Proposal for a new or updated Seed API.

Comments

@MartinKavik
Copy link
Member

MartinKavik commented Jan 17, 2020

Hey guys, I'm thinking about implementing first-class support for not-only-Rust Web Components.
Before I write some reasoning about it I would like to know your opinions and experience.
So.. what do you think?

@TatriX
Copy link
Member

TatriX commented Jan 17, 2020

Makes perfect sense to me. If I can reuse existing components easily, I can get results faster. This property is crucial for decision making in commercial projects.

@MartinKavik
Copy link
Member Author

@TatriX do you any experience with them?

@rebo
Copy link
Collaborator

rebo commented Jan 17, 2020

So as mentioned on discord I think in theory this could be a great idea however the interop between seed infrastructure and a Web Component would need to be carefully thought through.

I.e. what api will seed expose to web components and what will it hook into. For instance will connectedCallback and attributeChangeCallback trigger seed messages etc. If so could this fall into the same inconsistent problems that virtual dom diffing triggering lifecycle hooks have?

So in short a good idea but needs careful thought.

@David-OConnor
Copy link
Member

I can't comment at this time, due to not being familiar with Web Components.

@MuhannadAlrusayni
Copy link
Contributor

It would be great to have this functionality, especially Shadow Dom which would allow using CSS animations/selector without relying on CSS files, thus making very dynamic components.

@MartinKavik
Copy link
Member Author

@David-OConnor In a nutshell:

  • It's official low-level browser API which allows you to create custom elements like <my-div my-super-value="3000"><div id="I'm child"></div></my-div>.
  • There are some callbacks like connectedCallback that can be used as lifecycle parts.
  • You can use Shadow DOM to hide DOM tree inside the custom element to isolate CSS styles.
  • DOM selectors doesn't see custom element content so you don't have to patch it with Seed's VirtualDOM.
  • You can extend native DOM elements.
  • It has own local state.
  • We will be able to get it with el_ref.
  • Example of Rust wrapper: https://github.com/richardanaya/webcomponent
  • Short article for React users - https://reactjs.org/docs/web-components.html

@David-OConnor
Copy link
Member

Thank you for the detailed explanation

@mkroehnert
Copy link
Contributor

mkroehnert commented Jan 19, 2020

Hi @MartinKavik I would be interested in generating webcomponents with Seed.
Since @rebo mentioned discussions on discord, I wanted to know where I can find them.
Unfortunately, there is no link or mention on the seed.rs webpage or Github repo.

Edit: found the link in #303 after skimming through open issues. Would it make sense to make the channel more public or do you still want to wait to see if discord is the right choice?

Since I have a small personl project in which I used webcomponents and one where I would like to use them, I could at least do testing, if time permits.

@MartinKavik
Copy link
Member Author

Ad chat - seed-rs/seed-rs.org#22

@MartinKavik
Copy link
Member Author

MartinKavik commented Jan 20, 2020

I did some research about implementation and found a blocker - wasm-bindgen isn't smart enough (yet) to create a necessary bridge between the Rust and JS world to create custom elements.

Unfortunately I don't have enough free time to help them to add needed support. So I have to stop working on this issue until wasm-bindgen is improved or I have a generous sponsor 💰

So.. you can use JS/TS components at the moment, but they are reconnected on each DOM render and not very tested. We/I'll add better support once the blocker above is resolved and I can write a library for creating custom elements.

@lastmjs
Copy link

lastmjs commented Feb 14, 2020

IMO, I think it would be wise to consider exposing the base web components APIs as directly as possible, starting with an focusing on the custom elements API. A Seed component should be an HTML custom element. It should have all of the lifecycle methods of a custom element. It should be a DOM object under the hood. Any conveniences, like automatic getters and setters, can be built on top. This is what I would love to see.

@MartinKavik
Copy link
Member Author

@lastmjs If I understand you correctly - that's the plan.
You would be able to use custom elements as black boxes - it's not important if they were written in/with VanillaJS, Typescript, Rust, LitElement, etc.
The next step would be to create our web component API wrapper/library - so you can reuse your Seed knowledge (e.g. write HTML with Seed macros) and it's not as painful as writing custom elements with the original API.

@lastmjs
Copy link

lastmjs commented Feb 14, 2020

Sounds pretty good then. Though, there are only a few major pain points with the raw custom elements API, IMO. Having a templating library with data binding to properties and event handlers, and automatically rendering when attributes or properties change. I use vanilla custom elements, extending directly from HTMLElement in JavaScript/TypeScript. Using a simple templating library like lit-html and some state management like Redux makes writing custom elements simple and elegant. I suppose my point is, I don't think you need to do much over the custom element APIs.

I also think it would be important to expose the entire custom element API just in case the developer needs access to it. I would still love to be able to hook into connectedCallback and create my own getters and setters

@akhilman
Copy link
Member

https://hybrids.js.org/ does nice job to wrap custom elements with functional API.

import { html, dispatch } from 'hybrids';

function change(host) {
  host.value += 1;
  // Trigger not bubbling `change` custom event
  // Element user can subscribe to this event with
  // `el..addEventListener('change', callback)
  dispatch(host, 'change', { detail: host.value }); 
}

const MyElement = {
  // This `value` becomes an attribute of the custom element.
  // When the user of the element sets new value, 
  // the system calls `render` function with a new value.
  value: 0, 
  render: ({ value }) => html`
    <button onclick="${change}">You clicked me ${value} times!</button>
  `,
};

Receiving attributes from the user could be done as a method for the application builder
Builder::handle_attribute(Builder, Fn(String, Strung) -> Ms) where the first argument is the attribute name and the second is the value. And dispatch could be added to Orders trait.

@MartinKavik MartinKavik added the API design Proposal for a new or updated Seed API. label Mar 9, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
API design Proposal for a new or updated Seed API.
Projects
None yet
Development

No branches or pull requests

8 participants