#Stenciljs
Explore tagged Tumblr posts
Text
Web Components & Modular UI

You might have heard the term ‘web components’ being thrown around in UI discussions. But what are web components? And how did they come about? In this article, I will attempt to cover a brief history of web components and the benefits they bring to teams today. I will also dive into how my team uses them. But first, let’s talk about what they are: Web components are a suite of different technologies that allow you to create reusable custom elements for use in your web applications. The functionality of web components is encapsulated away from the rest of your code. This goes a long way to making them more reusable. There are three main technologies: custom elements and their behavior, the ‘hidden’ shadow DOM, and the flexible HTML templates. These are used together to create versatile custom elements with encapsulated functionality that can be reused wherever you like, without fear of code collisions.
Back in 2011, a guy named Alex Russell first introduced the concept of ‘standard’ web components. A couple of years later Google jump-started the web components ‘revolution’ with the release of the Polymer library. The library was based on web components, and served as the authoritative implementation of Material Design for the web. It was soon after this time, a little over a decade ago, that I began to work on a new web application UI project, for which I decided that web components would be a key technology in my front-end tech stack. There were regrets, especially because of the flood of browser errors. I remember a lot of searching and sifting through obscure documentations and blogs to understand how to ‘glue’ the web components together with my application. A lot of the web component implementations felt experimental and it seemed like they were not completely ready for production, to say the least. It felt exciting for the wrong reasons: It was a new frontier of development, but ultimately it bred discouragement because of the challenges.
The React framework soon came along and changed many things. I, for one, rewrote my application in React and ‘never looked back’. It was so much easier to work with. And I’m sure that other developers, who were once web component hopefuls, had a similar experience. At the time, Facebook didn’t want to use web components and build on top of them because they didn’t fit React’s JSX model used for declaring elements. This was yet another reason to be doubtful about them. But obviously, not everyone was. In 2016, the Custom Elements v1 specification was released, which laid the foundation for designing and using new types of DOM elements. Soon after, in a bold statement by Google, YouTube was rewritten in Polymer web components. They kept evolving Polymer knowing that web components were a web standard, an approved spec that modern browsers had to implement.
In 2017, a few developments started to reaffirm web components as a viable modern front-end technology: First of all, the Polymer team started to develop LitElement, a lightweight framework for creating web components. Secondly, the Ionic team created StencilJS, a JavaScript compiler that generated web components. Both of these became reference technologies for web component development. In 2018, Firefox 63 enabled web component support by default and updated developer tools to support them. With Angular 6, came Angular Elements, allowing for packaging Angular components as custom web components. By the time the Lit framework was released in 2019, people were already realizing the value of having a layer of web components, especially because of the headaches from having so many different front-end frameworks. None of those frameworks were ‘native’ like web components.
In the last five years, web components have matured significantly, gaining wider adoption and becoming a more viable alternative to framework-based components, with key advancements through new features, the development of frameworks, and increased browser support. More recently, there has been a move towards more declarative APIs and the potential for fully declaratively defined web components. Web Components are now a commonplace part of front-end development practices, with major players like GitHub, Apple, and Adobe embracing them. They continue to evolve, with ongoing efforts to improve accessibility and other features like server-side rendering. They also continue to gain traction, with increasing browser support and usage in various projects.
Meanwhile, companies are feeling the pain of having built components using a specific framework. Of course, web components solve this problem; they live in harmony with other frameworks, not against them. Teams don’t have to change their frameworks either. Web components adapt to any JavaScript framework because they are natively supported elements in HTML. It’s the standard for components and it’s in every browser. This also makes debugging never too overly challenging because of framework abstractions. They are easy to share across teams and applications, and building a design system around web components means that your design system is framework-agnostic. Libraries have made web components very easy to add anywhere and to incorporate into logic systems, e.g. through native JS events. They work seamlessly across React, Vue, Angular, or plain HTML. This ensures long-term maintainability and prevents vendor lock-in , unlike framework-specific solutions. Web components are also compatible with micro-frontends and module federation, so clearly they are being considered during development of new technologies. Related to this, I’d like to point out that the ‘staying power’ of a technology is greatly enhanced when the technology is built into a specification required to be adopted by popular modern competitors. Such is the case for web components. This is important because some even speculate that native solutions such as web components could replace all frameworks.
So how have we used web components on my team? Our web components live in a repository dedicated to developing them, testing them, and publishing them. They are published and distributed as NPM packages, making them easy to share and import. Each component comes with a Storybook story that is also imported into a separate design-focused Storybook application, our ‘design lab’, where you can visually browse our inventory and interact with the components. Two application teams have adopted most of their components to be from our design system. Three other teams have adopted some of our web components. A few other teams are evaluating our components. The set of components used, and how, varies between application teams. Most will start with the Side Navigation component, especially because it serves as a visual backbone for our platform application UX. Our Grid System component is useful as it provides spacing alignment for all other components on your web page. Of course, our data grid component is central to the functionality of important data-driven UI pages.
Our design lab application has become a great place to start exploring our component offering. Storybook gives you the tools to display each individual component in an organized way and allows people to not only learn about them but also ‘shop the look’ by changing the controls of the component and playing with the component to see if it makes sense for them. We have also built a demo application in our design lab, showcasing visual integrations of these components. This allows users to see an entire UI built with our components, but this also allows us, under the hood, to test these component integrations. More recently, we have built theme-ing previews into our design lab, allowing users to apply a completely custom theme, and see how it affects the built-in demo application and each individual component separately. This ability is quite important, because our web components are compatible with theme-ing changes, and the design lab allows one to preview these ahead of time before you apply a specific theme in your application.
It probably goes without saying that we have used the web component technology to build all of these components. This means that, no matter what front-end framework you are using, you could bring these components into your application already, and even apply theme-ing through them. Using a common set of components that work anywhere, allows you to build applications faster and with a consistent look and feel. This has huge implications, and web components are the best technology suited to deliver this kind of central, modular approach to building UI elements. We don’t want to be limited by a less-robust technology that serves as a barrier to cross-application modularity.
Thank you for reading!
Be sure to also check out this wonderful resource for web components in general: https://github.com/web-padawan/awesome-web-components#articles
0 notes
Text
Software Engineer - StencilJS- Remote (USA) at Ionic
Role Stencil is a compiler for web components, and is the underlying engine for the Ionic Framework. This role will involve collaboration with the rest of the Stencil engineering team to maintain and develop new features for Stencil, fix bugs, and communicate with the broader Stencil community. In this role, you will work with the rest of the team to balance the needs of the Ionic Framework and…

View On WordPress
0 notes
Photo

How to Build Reusable Web Components Using Stencil.js http://bit.ly/34cf6bm
#stenciljs #javascript #nodejs #js #developer
1 note
·
View note
Photo

How to Build Reusable Web Components Using Stencil.js http://bit.ly/34cf6bm
#stenciljs #javascript #nodejs #js #developer
1 note
·
View note
Photo

Angular/Ionic, React, Vue? Future-proof your app with Stencil.js! http://go.learn4startup.com/24778a098f #Stenciljs #Angular #Ionic #Vue
0 notes
Photo

Angular/Ionic, React, Vue? Future-proof your app with Stencil.js! http://go.learn4startup.com/24778a098f #Stenciljs #Angular #Ionic #Vue
0 notes
Text
Watch the videos from TypeScript conference, TSConf 2018
Here in Syndicode, we decided that if you can’t attend the event that is far from you, you should have a chance to watch the videos from it. That’s fair! And we already started the practice of sharing conference videos with videos from RailsConf 2018. Now we want you to watch the v...
#conference#cross-platform#designing interfaces#Ethereum#frontend#google#javascript#JavaScript that scales#js#Microsoft#Open source#programming#smart contracts#software development#Static Analysis#StencilJS#Swagger#TSConf#TSConf 2018#TSConf videos#typescript#TypeScript conference#videos from TSConf 2018#web development#webpack#Webpack and Ethereum smart contracts
0 notes
Photo

Getting Started with StencilJS - A Compiler for Web Components ☞ http://tech.learn4startup.com/3b77fd4fdb #Stenciljs #WebComponents #javascript
#javascript#javascript tutorial#javascript tutorial for beginners#learn javascript for beginners#codequs#morioh
4 notes
·
View notes
Photo

Getting Started with StencilJS - A Compiler for Web Components ☞ http://tech.learn4startup.com/3b77fd4fdb #Stenciljs #WebComponents #javascript
#javascript#javascript tutorial#javascript tutorial for beginners#learn javascript for beginners#codequs#morioh
1 note
·
View note
Photo

RT @trelvao: If you're working on a PWA you really need to join our meetup tomorrow and have a chat with the team behind @Ionicframework and @stenciljs https://t.co/qYEeXcJwBr (via Twitter http://twitter.com/Ionicframework/status/1059555926422761472)
1 note
·
View note
Photo

Angular/Ionic, React, Vue? Future-proof your app with Stencil.js! http://go.learn4startup.com/24778a098f #Stenciljs #Angular #Ionic #Vue
0 notes
Photo

Angular/Ionic, React, Vue? Future-proof your app with Stencil.js! http://go.learn4startup.com/24778a098f #Stenciljs #Angular #Ionic #Vue
0 notes
Text
Create your Own Drag-and-Drop Functionality Using Ionic Gestures
In this tutorial, we will be building out two custom components in Ionic that enable us to drag and drop elements on the screen. We will be able to mark elements as “draggable” to enable the dragging functionality, and we will be able to define a “droppable” target zone for where elements can be dropped. Here is a quick example I built using the end result:
You will find that there are plenty of libraries/packages available for implementing drag/drop functionality in Ionic, but we will be implementing our solution with just Ionic itself - no other external libraries/packages will be required.
Where practical, I prefer to implement my own solutions from scratch rather than relying on a 3rd party library to do the job. I don’t want this tutorial to focus on my opinions of the benefits of this approach, but to briefly explain my position:
You don’t need to spend time researching options and compatibility
You can build exactly the functionality you need (and only what you need)
You will be better positioned to extend the functionality further if required
You will be able to integrate the functionality better with other parts of your application
You don’t need to worry about maintenance or long term support for the package
You won’t end up with a mish-mash of various packages in your application that are kind of just sticky taped together
You learn new stuff!
That doesn’t mean you shouldn’t ever use 3rd party packages, but growing your ability to build things yourself gives you much more freedom in determining whether a particular package provides enough benefits to outweigh the downsides in a particular situation. For some drag/drop scenarios I am sure existing libraries/packages will save a substantial amount of time and effort, but for our goals in this tutorial we can build it out ourselves easily enough.
In fact, enabling dragging of any element around the screen with Ionic Gestures is relatively simple (assuming you already have an understanding of Ionic Gestures, if not I would recommend reading: Create Custom Gestures (Simple Tinder Card Animation)). All we need is a single line of code inside of the onMove handler:
onMove: (ev) => { style.transform = `translate(${ev.deltaX}px, ${ev.deltaY}px)`; }
We just need to set transform on the element we want to drag in response to the move events from the gesture. We translate the x and y values to match the deltaX and deltaY values from the gesture, which indicate the change in position since the beginning of the gesture (e.g. the user has dragged 10px to the right and 5px down since beginning the drag gesture).
This is a big part of the drag and drop functionality, but we have a few more things to consider as well. We would likely also want:
Something useful to happen when the element is dropped
The element to snap back to its original position after it is dropped (perhaps unless it is dropped within a certain zone)
The ability to mark a particular area where the element is allowed to be dropped
This complicates things a little more, but it still doesn’t require overly complex code to implement. Our solution will involve creating an <app-draggable> component and an <app-droppable> component. We will be able to wrap existing elements with <app-draggable> like this:
<app-draggable droppable={this.droppableArea} drop-data={{content: 'some data'}}> <some-element>Drag me!</some-element> </app-draggable>
and create a droppable zone by using <app-droppable> like this:
<app-droppable onElementDropped={(ev) => this.handleDrop(ev.detail)}> <h5>Drop zone!</h5> </app-droppable>
We will link the draggable elements to their designated drop zone using the droppable prop, and we can also supply some data that is passed on to the drop zone through the drop-data prop. Our drop zone emits an elementDropped custom event that will fire whenever an element is dropped within its bounds. The elementDropped event will contain the data passed through drop-data.
Before We Get Started
This example used in this application was creating using Ionic/StencilJS, but the methods being used (e.g. Ionic Gestures) are also available for Angular, React, Vue, etc. If you are following along with StencilJS, I will assume that you already have a reasonable understanding of how to use StencilJS. If you are following along with a framework like Angular, React, or Vue then you will need to adapt parts of this tutorial as we go.
If you would like a thorough introduction to building Ionic applications with StencilJS, you might be interested in checking out my book.
1. Creating the Droppable Component
First, let’s talk about how to create the droppable area. This component doesn’t actually do a whole lot, its main purpose is to receive an event from the draggable component detailing the position in which the the element being dragged was “dropped” (i.e. the coordinates of where the drag gesture ended). It will then determine if those coordinates intersect with its own “bounding client rectangle” on the screen (i.e. the space in which the droppable area occupies on the screen). If the coordinates are within the space that the droppable area occupies, then it will emit an event indicating that something was dropped and any data that was supplied along with it.
Let’s take a look at the code and then talk through it:
import { Component, Element, Event, EventEmitter, Method, Host, h} from "@stencil/core"; @Component({ tag: "app-droppable", styleUrl: "app-droppable.css", shadow: true, }) export class AppDroppable { @Element() hostElement: HTMLElement; @Event() elementDropped: EventEmitter; @Method() async complete(ev, data) { if (this.isInsideDroppableArea(ev.currentX, ev.currentY)) { this.elementDropped.emit(data); } } isInsideDroppableArea(x, y) { const droppableArea = this.hostElement.getBoundingClientRect(); if (x < droppableArea.left || x >= droppableArea.right) { return false; } if (y < droppableArea.top || y >= droppableArea.bottom) { return false; } return true; } render() { return ( <Host> <slot></slot> </Host> ); } }
This component has a publically exposed method called complete. This will allow us to grab a reference to the <app-droppable> element we are interested in, and then call its complete method. We will call this method from within our <app-draggable> gesture to indicate that the gesture has finished, and to supply <app-droppable> with the coordinates and data it needs to do its job.
As you can see, we have also created a method called isInsideDroppableArea that uses getBoundingClientRect to determine the space that the droppable area occupies, and then checks that against the supplied coordinates. This component has no template itself, it will just take on the shape of whatever is inside of the <app-droppable> tags - this allows you to define how you want your droppable area to look without having to modify the internals of this component.
2. Creating the Draggable Component
Now let’s take a look at our draggable component. Most of the work that we need to do within this component is just creating the gesture itself:
import { Component, Element, Prop, Host, h, writeTask } from "@stencil/core"; import { createGesture, Gesture } from "@ionic/core"; @Component({ tag: "app-draggable", styleUrl: "app-draggable.css", shadow: true, }) export class AppDraggable { @Element() hostElement: HTMLElement; @Prop() droppable; @Prop() dropData; componentDidLoad() { const style = this.hostElement.style; const dragGesture: Gesture = createGesture({ el: this.hostElement, gestureName: "draggable", threshold: 0, onStart: () => { writeTask(() => { style.transition = "none"; style.opacity = "0.7"; }); }, onMove: (ev) => { writeTask(() => { style.transform = `translate(${ev.deltaX}px, ${ev.deltaY}px)`; }); }, onEnd: (ev) => { writeTask(() => { style.transition = ".3s ease-out"; style.transform = `translate(0, 0)`; style.zIndex = "inherit"; style.opacity = "1"; }); this.droppable.complete(ev, this.dropData); }, }); dragGesture.enable(); } render() { return ( <Host> <slot></slot> </Host> ); } }
We set up two props on this component: droppable for indicating which <app-droppable> component we want to drag to, and dropData to provide the data we want to pass to the <app-droppable> component when the element is dropped within the droppable zone.
The rest of this component deals with setting up the gesture. I won’t talk about creating gestures in general here, so again, if you are not already familiar with Ionic Gestures I would recommend watching: Create Custom Gestures (Simple Tinder Card Animation)).
An important distinction for this gesture is that we provide a threshold of 0 so that the gesture will work in all directions - by default, gestures will only work in the specified direction (horizontal or vertical). We’ve already discussed setting the transform value inside of the onMove handler, and the other important part here is that we call the complete method of the supplied <app-droppable> component reference when the gesture ends. We also set up some styles so that the element will snap back to its original position once released, and we also reduce the opacity a bit when it is being dragged.
It is important that we set the transition style to none when the gesture begins, because we don’t want to animate the translate changes inside of onMove. This value is updated every time the mouse/pointer moves and having a timed animation animating those changes would mess things up. We do, however, want the transition animation to apply when the element is being translated back to its original position inside of onEnd.
3. Implementing Drag and Drop Functionality
We have our generic drag/drop functionality implemented, now we just need to make use of it. To demonstrate using it, I created a simple example that would allow different types of elements to be dragged to a droppable zone and then render out data passed along from that element. You can see the result of that below:
and the code for this is as follows:
import { Component, State, Element, h } from "@stencil/core"; @Component({ tag: "app-home", styleUrl: "app-home.css", }) export class AppHome { @Element() hostElement: HTMLElement; @State() droppableArea; @State() cards; @State() chosenOne: string = "pick a card..."; componentWillLoad() { this.cards = [ { title: "Drag Me", content: "To another place" }, { title: "Drag Me", content: "I am a far better candidate for dragging" }, { title: "Drag Me", content: "To the place, I belong" }, ]; } componentDidLoad() { this.droppableArea = this.hostElement.querySelector("app-droppable"); } handleDrop(data) { this.chosenOne = data.content; } render() { return [ <ion-header> <ion-toolbar color="primary"> <ion-title>Drag and Drop</ion-title> </ion-toolbar> </ion-header>, <ion-content class="ion-padding"> <app-droppable onElementDropped={(ev) => this.handleDrop(ev.detail)}> <div style={{ border: `3px dashed #cecece`, width: `100%`, height: `200px`, display: `flex`, alignItems: `center`, justifyContent: `center`, }} > <h5>Drop zone!</h5> </div> </app-droppable> <p> <strong>The chosen one:</strong> {this.chosenOne} </p> {this.cards.map((card) => ( <app-draggable droppable={this.droppableArea} drop-data={card}> <ion-card> <ion-card-header> <ion-card-title>{card.title}</ion-card-title> </ion-card-header> <ion-card-content>{card.content}</ion-card-content> </ion-card> </app-draggable> ))} <app-draggable droppable={this.droppableArea} drop-data={{ content: "Why not!" }} > <ion-chip> <ion-icon name="heart" color="primary"></ion-icon> <ion-label>A draggable chip?</ion-label> <ion-icon name="close"></ion-icon> </ion-chip> </app-draggable> <app-draggable droppable={this.droppableArea} drop-data={{ content: "A button???" }} > <ion-button>Drag me too, why not!</ion-button> </app-draggable> </ion-content>, ]; } }
This isn’t a particularly practical example, of course, but it does demonstrate how the components can be used currently.
Summary
Depending on what it is you want to do exactly, you would need to modify the example in this tutorial a little further and perhaps even make some changes to the underlying components themselves.
For example, all we are doing is passing some data along which might suit some circumstances, but perhaps you also want to change the position of elements after they are released. In that case, you would need to modify the onEnd of the gesture to perform some check and implement a different type of behaviour to achieve the result you want (e.g. moving the element to its new position on the screen). Maybe you want the element to disappear completely when it is dropped, and reappear in text form somewhere else (this could also be achieved by changing the onEnd behaviour). Maybe you even want to create something similar to Ionic’s <ion-reorder-group> component that has elements shuffling around on the screen as another element is dragged over it - in that case, you would need to add some extra logic inside of the onMove handler.
I’ll reiterate that in some cases, you might be better served by just using an existing 3rd party solution. But, if it is practical enough to build out the solution you need yourself, I think the benefits are often worth it.
via RSS Feed https://ift.tt/2KKT1ce
0 notes
Photo

I’ve said this before, web components are the future which is why I did video on tools like StencilJS. Today I made a video on the native webcompnents browser API and it is pretty cool. https://youtu.be/F2Ha1YCR1fo https://www.instagram.com/p/B98F_Z_pUmQ/?igshid=wwoq7n2fkaxf
0 notes
Photo

@JavaScript : RT @daviddalbusco: I'm happy to release today two new @deckdeckgo features 🎉 ⏱️ a #pwa presentation timer (with local notifications) 📝 the ability to edit notes and to display them in the #pwa or even to your audience 👉 npm init deckdeckgo Thx @stenciljs community and @insanicae for the ideas https://t.co/W7zDGdN4bV
0 notes