Using Web Components Using a combination of JavaScript, HTML, and CSS standard APIs we are able to capture a UI solution in the form of a web component. This is very useful because it allows us to quickly and consistently reproduce UI solutions when the appropriate use case arises. Let's take a button for example, there are CSS rules around making a button look a certain way and it includes variations, such as background-color, that you might want to capture as options for your button. You can create a button web component that does just that, it implements all of the functionality of a button and gives the ability to add configurations to modify the rendered view. The component captures the UI solution and the intent behind it, and exposes those configuration points to anyone who uses it to deliver a combination of markup, styles, and interaction that make up a piece of the UI. Guiding Principles There are some guiding principles that are followed in this set of components that will help understand the choices made to build them. Let's quickly step through them and explain each one. UI is a Result of a Component's State This is the same principle that many frameworks have adopted to ensure a predictable UI from each component. Each component reads its current state and returns a rendered result based on that. If the state changes, the result is recalculated. There are no fetch calls or application logic in any of our components. State is synced to the DOM Our components are custom HTML elements that have their own attributes that are mapped to the class properties and the current state of that component is reflected between them. We have a tool that helps us manage that connection, and the big takeaway here is that if the DOM changes, the component will be notified and if the component changes the DOM will be notified. This keeps the JavaScript class and the DOM synced so that the state of the component is visible on the element itself. Components Rely Heavily on Available CSS The design system predates the components and supplies many CSS utilities or styles written for a specific UI that our components implement. In most cases our components are simply composing these available class names to achieve the UI. What that means is that there is very little that the components are doing that is not available to you outside of them. The components are the implementation of the design system and help you quickly create the UIs that it supports. Components are Composable Each component has all of the required information to render the UI, and even components that are designed to be children of other components can be used in a standalone way, albeit with limited use. What this means is that components can be safely used as children of other components. For example, many of our components use the suite-text or suite-surface components as a part of their markup. Understanding SuiteElement The SuiteElement class is the base that all of our components are built on. It comes with several key features that make crafting components easier for us and some of our other tools are designed to work with it and the documentation component is designed to automatically generate documentation based on it. I'll cover each of those features in detail. Render Method Each component has a render method that calculates the state and returns the UI. Each time the state changes, the render method will be called to determine the new resulting UI and push it to the renderRoot (either the DOM or a shadow DOM). Be careful when making state changes in the render method as it could cause a loop and it is advised to handle changes through an event handler or some other means that is less direct. Attribute Map The @mapAttribute tool handles creating a connection between a class property and a HTML attribute and provides some other utilities for attributes and all of this information is stored on the attributeMap static. The attributeMap is used when a change happens in either the class or the HTML element to know how to process the change and handle the syncronization. Event Map There is a tool for defining custom events on a component that adds any defined events to the event map. This is used by the documentation component to generate a table detailing information for each custom event. Lifecycle Events SuiteElement is set up so that at different points in the lifecycle of a component it will trigger a custom event for anyone listening. This event will fire for the following points in a component's lifecycle:
"suite-connected"
Triggers when the element in the DOM invokes the JavaScript class and before any setup logic is run
"suite-disconnected"
Triggers when the element is removed from the DOM NOTE: The element is removed from the DOM before the event is invoked and this makes event delegation fail, so to listen to this event the listener MUST be on the element itself.
"suite-initialized"
Triggers when the class has finished processing the setup logic and has rendered to the screen
"suite-reflected"
Triggers whenever a mapped attribute's syncronization logic runs