Building Web Components for React

Although Web Components were introduced in 2011, they're not the average developer's first or second choice for writing UI layouts, despite what the technology offers.

This is partly due to the increase in JavaScript frameworks, component-driven development enthusiasts, and other esoteric factors over the years.

Now comes Shoelace, a UI library built on Web Components technology that provides the same experience as any JavaScript framework, but with better advantages.

In this article, we will introduce Shoelace, how to completely uninstall Internet Explorer on Windows 10? Detailed graphic uninstall steps to see its inner workings and demonstrate how to use its components with React to build a simple interface.

prerequisites

To follow along with this tutorial, you need the following:

  • Working knowledge of React

  • The latest version of Node.js is installed on your computer

What is shoelace?

Shoelace is an open source, framework-independent component for building accessible web applications.

Unlike traditional UI libraries that export user interface components and elements specific to a particular framework, Shoelace provides a collection of highly customizable UI components built on a framework-agnostic technology known as Web Components.

What are web components?

Web Components are a combination of standard web technologies, how to encode MPEG video with Canopus Procoder? Graphic tutorial sharing allows you to create reusable custom elements or components that encapsulate functionality and style away from the rest of your code.

The Web Components specification consists of three technologies:

  • Custom Elements: These are HTML elements with custom tag names and behaviors, specified by a set of JavaScript APIs, that can be used anywhere in the application

  • Shadow Dom: This is a set of JavaScript APIs that attach a scoped DOM tree to elements. It isolates the functionality and styling of custom elements to avoid conflicts with other parts of the document

  • HTML templates: These are HTML elements ( and ) that enable you to create markup templates that won't be rendered until <template>``<slot> is called

These techniques are used together to create web components with encapsulated functionality.

Check out the documentation to learn more about the Web Components specification.

Benefits of using Shoelace

Front-end frameworks such as Angular, React, and Vue.js are built on the concept of using component-driven development to create organized UIs of components, encapsulating content, functionality, and styling into a single JavaScript file.

While this does alleviate the complex constraints that exist in web development, it does have some disadvantages:

  • Components are framework-specific, meaning they can only be used in the framework for which they were designed

  • Developers must learn how to use the framework of component design

  • Component life is limited by frame life

  • Developers have to rebuild base components when switching to another framework

Web Components are designed to solve these problems.

Shoelace is built on Web Components technology. Fun Notes It exports HTML and DOM standard components supported by every modern browser and works across different frameworks.

There are many benefits to using Shoelace; here are some:

  • Fully customizable components to match existing designs

  • Ability to build multiple applications using different frameworks sharing the same UI components

  • Ability to switch frameworks without rebuilding underlying components

  • Ongoing Browser Support

Getting Started with Shoelace

Installing Shoelace is as easy as adding tags to the project documentation. Interesting Notes Sitemap However, not every framework provides built-in support for Web Components. <script></script>

For example, the React render tree does not properly propagate events emitted by web components. To solve this problem, Shoelace created wrappers that let us use Web Components in React.

There are three official ways to integrate Shoelace into a project:

  • CDN: This is the easiest way to integrate Shoelace into your project; it requires adding a CDN script and style link to the document

  • Local installation: This method allows you to install Shoelace locally using the Node.js package manager

  • Pick: Installing Shoelace via CDN or locally will yield the full library size in your project, reducing your application's load time. Instead, Shoelace lets you pick and install only the components you actually need

Install

In this article, we'll use React to demonstrate the use of Shoelace. Since Shoelace uses a React wrapper, we can only install the library locally using npm.

For the purposes of this demonstration, I'm assuming you already have a React project set up. Now, go ahead and install Shoelace with the following command:

npm install @shoelace-style/shoelace

Once Shoelace is installed, you can start using its components by importing them into components, like this:

import { SlInput } from "@shoelace-style/shoelace/dist/react";
function App() {
  return (
    <div className="App ">
      <SlInput value={"David"} label="Name" />
    </div>
  );
}
​
export default App;

As you can see, the Shoelace component is imported as a React component, not an actual custom element. This is unique to React; the components in the above code will be imported as custom elements into other frameworks such as Vue, Svelte or Angular. <SlButton>``<sl-button>

The above code will render a barebones input element to the browser, but without default styles:

theme selection

The Shoelace component is designed to be highly compatible with different theming systems your project may have. You can choose between light or dark themes, or create custom themes out of the box.

Themes added to the project will determine the default styling of components. For example, suppose a theme is added to a project by linking a stylesheet to the project file: light``App.js

import "./App.css";
import { SlInput } from "@shoelace-style/shoelace/dist/react";
​
//light theme stylesheet
import "@shoelace-style/shoelace/dist/themes/light.css";
​
function App() {
  return (
    <div className="App">
      <SlInput value={"David"} label="Name" />
    </div>
  );
}
​
export default App;

The input component will be rendered with the default style (determined by the theme in this case) as follows: light

If you add a theme instead, the component will render with the default style corresponding to that theme: dark

Unlike themes, to use a theme you must activate a stylesheet after importing it into your project. You can do this by adding on the parent inside the file like so: light darksl-theme-dark classNamediv ``App.js

//dark theme stylesheet
import "@shoelace-style/shoelace/dist/themes/dark.css";
​
function App() {
​
  return (
    <div className="App sl-theme-dark">
      <SlInput value={"hello"} />
    </div>
  );
}
​
export default App;

By now, you should have a basic understanding of how Shoelace works and how to integrate it into a React project.

Next, let's create a composite to better understand the inner workings of the Shoelace component.

Using Web Components in React

Shoelace provides unique components that you won't find in many other framework libraries. Things like and really push the idea of ​​what is possible with a library. image composer``split panel

For our example project, we'll build a card component with a button and gear icon that fires events when clicked.

If you want to follow along with the example project, create a folder inside that folder and add a file: components srccard.jsx

Next, import the component into the file and add it to the following section: card App.jsreturn

//App.jsx
import { useState } from "react";
import "./App.css";
import Example from "./components/example";
​
function App() {
  return (
    <div className="App">
      <Example />
    </div>
  );
}
​
export default App;

Now, you need to import all the components used throughout the tutorial into a file: card.jsx

//example.js
import {
  SlButton,
  SlCard,
  SlDrawer,
  SlIconButton,
  SlDialog,
  SlSwitch,
} from "@shoelace-style/shoelace/dist/react";

With that done, it's time to start composing the cards!

In the body of the component, declare the component and nest the following code inside it: <Slcard>

<SlCard style={
  
  { maxWidth: "300px" }} >
<img
  src="https://images.unsplash.com/photo-1667120651808-34305af680d3?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1736&q=80"
  alt="A squirrel sits on a wood."
  slot="image"
/>
<strong>Squirrel</strong>
<br />
<p>Squirrels are members of the family Sciuridae, a family that includes…</p>
<br />
<small>6 weeks old</small>
<div slot="footer"
 style={
  
  {
    display: "flex",
    alignItems: "center",
    justifyContent: "space-between",
 }}
>
  <SlButton variant="primary" pill>
    More Info
  </SlButton>
  <SlIconButton
    name="gear"
  ></SlIconButton>
</div>
</SlCard>

Here we've added an image, title, and description to the card using the , , and elements. We also added a footer with nested shoelace button and icon components: img strongsmall ``div

Before importing and using resources such as icons, be sure to set the base path of the Shoelace resource in the file: App.jsx

//App.jsx
import { setBasePath } from "@shoelace-style/shoelace/dist/utilities/base-path";
setBasePath(
  "https://cdn.jsdelivr.net/npm/@shoelace-style/[email protected]/dist/"
);

and attributes on the tag are Shoelace attributes that some web components use to accept content within them. In our project, we use it to define the image and footer section of the card portfolio. slot imgdiv

This property tells the component where to place the element it is called on. to have a footer, for example if you put the code at the top of the card component, just before the label: slot divslot``img

<SlCard style={
  
  { maxWidth: "300px" }}>
<div slot="footer"
   style={
  
  {
      display: "flex",
      alignItems: "center",
      justifyContent: "space-between",
   }}
  >
    <SlButton variant="primary" pill>
      More Info
    </SlButton>
    <SlIconButton
      name="gear"
    ></SlIconButton>
  </div>
  <img
    src="https://images.unsplash.com/photo-1667120651808-34305af680d3?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1736&q=80"
    alt="A squirrel sits on a wood."
    slot="image"
  />
  <strong>Squirrel</strong>
  <br />
  <p>Squirrels are members of the family Sciuridae, a family that includes…</p>
  <br />
  <small>6 weeks old</small>
</SlCard>;

The footer will still render at the bottom of the card in the browser. The same goes for tags. div``img

Visit the component documentation page to see other component slots and how to use them. card

Next, let's see how to customize the card composition using CSS.

Styling Shoelace Web Components

As you may have noticed, the Shoelace components aren't particularly well styled out of the box, but they have enough styles to get you started.

In order to align the design of the Shoelace component with that of your application, you must first understand how Shoelace utilizes the shadow DOM.

As mentioned earlier, the Shadow DOM encapsulates the styling and behavior of custom elements. So styles from outside the shadow DOM won't affect the inner content, so you can't simply use CSS selectors to target the inside of a custom element.

Use your browser's devtools to see the buttons in the card's footer. It should look like this: More Info

Before we start styling our components, we need to understand what's going on here. This component creates an element with three nested elements representing each part of the Web Component: , , and . <SlButton> buttonspan prefixlabel``suffix

The second element wraps an element responsible for rendering any content passed between the Web Components markup. span``<slot>

Note; this is our button's shadow DOM. It encapsulates the content inside the custom element. shadow-root``button

The underlying element is what we need to style. However, since this cannot be done from the outside using just regular CSS selectors, we'll use one of the methods provided by Shoelaces to style the custom element. button

There are three ways to customize the Shoelace custom element; you can use components, design tokens, or custom attributes.

The official documentation provides detailed instructions on how to use these methods for customization. For convenience, we'll demonstrate how to customize components using the first method (component parts).

The Shoelace component exposes a property that allows you to target custom elements from outside the shadow root using CSS pseudo-selectors. part``::part()

If you look closely at the custom elements in devtool, you'll notice an attribute on the base element: <SlButton> partbutton

<button
part="base"
class="button button--primary button--medium button--standard button--pill button--has-label"
type="button"
role="button"
aria-disabled="false"
tabindex="0"
>
...
</button>;

You can target attributes on elements by simply giving the component a and adding a selector to it in the CSS file: part(base) <SlButton>className``::part()

.button::part(base){
  color: black;
  background-color: green;
}

Alternatively, you can use a component as a selector, but it must be used with an actual custom element, not a React component exported by the wrapper. So let's use instead: sl-button``SlButton

sl-button::part(base){
  color: black;
  background-color: green;
}

This CSS code will change the button's text and background color from white to black and blue to green respectively:

There are a few important things to note here. Since every component has a base part, every button on the page will have this style selected. To fix this quirk, we can use the component method again. We'll give the button one and use that instead of the component's name. button``className

We don't have many other styles on our cards. In this case, the default styling is good enough, so we'll leave it as is.

Next, let's look at how to add event listeners to the button and gear icons. More info

event handling

The Shoelace component emits events and methods, the usage of which may be slightly different than what you are used to in React. For example, a component has a method that, when called, manually triggers the popup state of the component. However, you must use React's Hook to access the underlying custom element to use this method: dialog showdialog``useRef

import React from "react";
import { SlDialog } from "@shoelace-style/shoelace/dist/react";

export default function Example() {
  const ref = React.useRef();
  return (
    <div>
      <SlDialog label="dialog" ref={ref}></SlDialog>
    </div>
  );
}

The component also emits an event that fires when the dialog is shown. In React, you can listen to the same event using: sl-show``onSlShow

import React from "react";
import { SlDialog } from "@shoelace-style/shoelace/dist/react";

export default function Example() {
  const aFunc = () =>{
    console.log("This function will run when the dialog component shows");
  }
  return (
    <div>
      <SlDialog label="dialog" onSlShow={aFunc}></SlDialog>
    </div>
  );
}

Alternatively, you can use React's event handlers, e.g. on components like: onClick SlButton<SlIconButton>

import React from "react";
import { SlDialog } from "@shoelace-style/shoelace/dist/react";

export default function Example() {
  const [toggle, setToggle] = React.useState(false)
  return (
    <div>
      <SlDialog label="dialog" onClick={() => setToggle(true)}></SlDialog>
    </div>
  );
}

Next, we'll add event handlers and components that open when the button and gear icon components on the card are clicked. onClick drawerdialog``More Info

This component will display more information about the content of the card. This component will render a component that disables or enables the button when its state changes. drawer dialogswitch``More Info

The first thing we need to do is create three different states for each event in the file: example.jsx

 const [open, setOpen] = React.useState(false);
 const [dialog, setDialog] = React.useState(false);
  const [toggle, setToggle] = React.useState(true);

Next, add event handlers to the footer button and gear icon with callback functions for toggle and state variable values: onClick OpenDialog

<SlButton
onClick={() => setOpen(true)}
  variant="primary"
  pill
>
  More Info
</SlButton>
<SlIconButton
  name="gear"
  onClick={() => setDialog(true)}
></SlIconButton>

Now, when the button is clicked, its event handler sets the value of the and state to . Open Dialogtrue

Next, add and components below the card composition, the content and props are as follows: drawer``dialog

<SlDrawer
  label="Squirrel"
  placement="start"
  open={open}
  onSlAfterHide={() => setOpen(false)}
>
  <img
    src="https://images.unsplash.com/photo-1667120651808-34305af680d3?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1736&q=80"
    alt="A squirrel sits on a wood."
   style={
  
  { width: "100%" }}
  />
  <p>
    Squirrels are members of the family Sciuridae, a family that includes
    small or medium-size rodents. The squirrel family includes tree
    squirrels, ground squirrels, and flying squirrels. Squirrels are
    indigenous to the Americas, Eurasia, and Africa, and were introduced
    by humans to Australia.
  </p>

  <SlButton
    slot="footer"
    variant="primary"
    onClick={() => setOpen(false)}
  >
    Close
  </SlButton>
</SlDrawer>
<SlDialog
  label="Dialog"
  open={dialog}
  onSlAfterHide={() => setDialog(false)}
>
  <div
    style={
  
  {
      display: "flex",
      alignItems: "center",
      justifyContent: "space-between",
    }}
  >
    <p>Enable/Disable Drawer button</p>
    <SlSwitch
      onSlChange={() => setToggle(toggle ? false : true)}
    ></SlSwitch>
  </div>
  <SlButton
    slot="footer"
    variant="primary"
    onClick={() => setDialog(false)}
  >
    Close
  </SlButton>
</SlDialog>

props on both components allow you to pass state variables that control their open and closed states. We are using this instead of the and method. open showhide

By passing the and state props, we tell the components to display when the value of their respective state is true: Open Dialogopen

Inside the footer of both components is a component that has the state set to, thus closing them. button onClickfalse

Unlike other components, components nested within components do not use handlers for their events. Instead, we use event handlers to set the toggle state. SlSwitch dialogonClick``onSlChange

<SlSwitch
onSlChange={() => setToggle(toggle ? false : true)}
 ></SlSwitch>

Here we check if the value of the state is a state before setting a new value for it. toggle``true

Currently, the state does not trigger anything. We want it to disable or enable the button based on its current value. So what we do is add a prop to the button and pass the state variable to it as a parameter: toggle More Infodisabled``toggle

<SlButton
onClick={() => setOpen(true)}
  variant="primary"
  disabled={toggle}
  pill
  className="button"
>
  More Info
</SlButton>

That's it! We managed to create an interactive card deck with minimal effort. We can easily transfer our composition to other frameworks, such as Svelte, Angular or Vue, thanks to Shoelace and Web Components technology, almost no adjustments are required.

in conclusion

In this article, we introduced Shoelace and Web Components. We also looked at how Shoelace leverages Web Components technology to create a framework-agnostic UI library.

This article also showcases Shoelace's , , , and components, and demonstrates how they can be used together to form a simple interface. button cardinput dialogdrawer``switch

Guess you like

Origin blog.csdn.net/weixin_47967031/article/details/132624561