 React, Angular and View all allow writing custom components, but what if you want to write a custom web component that works in all three, or even in some web framework that hasn't been invented yet? In this edition of Browser Native, you'll learn how to write web components that will run in any modern web browser. So let me bring in my colleague, Julie Turner. Hey. Julie. So what do you think? Have you ever used these web components to write web components? I have. This is definitely, so I've said in other places that I do a lot of writing of React solutions right now because of the platforms that I typically build for, but web component development is definitely something that I'm interested in as a co-maintenor of a library where we're building components that need to be used in multiple frameworks and frameworks that haven't been invented. So web components are definitely top of my mind. Yeah, that's the H2O library. That's H2O. That's right. Yeah. That's really cool. If anyone hasn't checked it out, we'll put the link in the comments. That would be a good idea. Let's do that. Yeah. But there's another example I think is the graph toolkit. So there's this graph toolkit where you can take a component that logs you in or shows a user or shows your calendar or something, and it all looks exactly like it would look like in a Microsoft product. Right. And... Yeah. And you can use it in any of the frameworks because of it being written as a web component. And I think it's super powerful. It's absolutely powerful for the right product or the right solution, you know, thing that you're building, it makes a ton of sense when you can use them. Cool. So let's take a look at one. Yeah, let's... This one is pretty simple. This is really just like all of our samples in browser native. We want to just get the core concept across and not complicate it any more than needed. So hopefully we've done that, and this example is a stopwatch component. So it's really simple. Here you can see the HTML, and I'm bringing in a script here, stopwatch.js. And then I've got a button on the screen, and you'll see why in a minute because it's going to sort of force us to think about the fact that we want to isolate our components. And so you'll see what that is. And then here I am with three stopwatches on the page. So stopwatch, I can give it a color. I can give it some text or even a child, some child HTML. And what happens when it works is that you just get these little stopwatches. Again, they're dead simple, but you can start them and stop them just by clicking, and it just increments every second. So the problem is that this button up here is not supposed to look like those other stopwatches. And so it works, but the styling is wrong. So if we come over to style.css, you'll see that buttons are supposed to have a yellow border and a black background and yellow text. And it does not look like that. So the reason it doesn't really is because the stopwatch has a style too. And the stopwatch says, oh, a button is supposed to look like this. Right. You know, so I think we'll deal with that in the next section. OK. But let's go ahead and look at the code. So the actual stopwatch.js. So this is the script that was invoked from the main page, from our HTML page. And the first thing it's going to do is bring in the style sheet. It's own little style sheet. I love this import statement. That was such an interesting thing to learn, to be able to assert a type or an import. Yes. And as far as I know, this only works for CSS now. I want one for HTML and for some other types. Oh, yes, me too. And it is interesting because it ends up taking the style. So this is the note dot slash we're in a sub folder here. So it's this one. Yeah. And it's bringing in these styles, but it's doing it in. It's bringing them in as some kind of CSS object and not really, you know, as just text string. So down here. So here's the state of the button. And by the way, it's just these are just in private members. So the button element itself, whether it's running the start time and the accumulated time. And part of it just as an aside, the reason that I didn't just say how much time is because this call down here, the set interval is not exactly accurate. Oh, OK. Something else could slow it down. Right, right. That of just counting how many times have I run this little set interval code. Instead of that, and plus you could start and stop it, which we're throwing off, right? I'm actually doing the math, taking the time of day. When it started, taking the current time of day. And so you can set the interval to anything you want. And that's how frequently we'll update. But that doesn't have anything to do with how long the time has been. That's smart. Yeah, I like that. You could update it. I think I have it updating every second, but you could do anything you want. So anyway, so here you see document adopted style sheets. And obviously, this is different from adopting a child or adopting a I use getting users adopted or whatever that's all right. That's those other point people do that. But but here what we're doing is we're just taking the style sheet object. And we it wants an array. So we're putting it into an array all by itself. Yeah, and that's going to apply those styles to the document object. So to the whole, that's why this button up here ends up getting the wrong style. Because, you know, the style tag up here or the link to the style sheet in the HTML got overwritten when when I called that right. As you said, document dot, OK, got it. In the next section, we'll fix that. Right. So at that point, we're going to just go in and create the DOM element that's actually the button, set the inner text to be the time of zero format time of zero. So I have a little format time function that just does the formatting. It's nothing fancy. Then what we're going to do is take this. So recall in the original HTML, I have stopwatch. I can say color equals. All right. Yeah. Right. So this next little piece is going to take this element. And I should have probably pointed this out before, but we're we're making a class that extends HTML element. So it's not like we're making something that's like an HTML element. We're actually making making a new HTML element. Yeah. So now this in this case, and we did, we talked about this in some of our previous videos, I'm in the constructor. So this means what you would think it means in any almost any language. This is, I can say this dot element dot style dot background color. And then this dot attributes is going to let me get to the attributes of my element that were actually just on the page. Right. Yeah. So that's how they get the colors. And you could do that as much as you want. You could have a bunch of different attributes and do whatever you want. And then we're going to append our button to ourselves basically as a child. Yeah. Yeah. Okay. Right. So and then there's this little piece of logic that does the when you click on it, it's going to start or stop the timer. And I won't go into the into the math of this, but it's kind of taking into account that you might have stopped and stopped during a bunch of times and that the interval might not be exact. And it's just remembering how much time to show. Okay. And then here's the format time function, which is again not specific to this topic. So whatever it just makes it look like a time with our seconds and minutes. And then down at the bottom is the magic, right? This is what's saying, okay, you've got this class. It's, it's derived from HTML element. Nope. So let's define that as a custom element. Okay. And that's where that stop dash watch comes from. And I believe you do the same thing. You put a dash in the name. Yep. So that is, that's kind of a convention, right? That I think I think it is a general convention. Yeah. The other way you could do it is with, um, that's not called camel case, but it's called, there's another where you, um, uh, capitalize where the words are and that's kind of the same idea, but you'd put instead of capitalizing you dash, right? Right. And I think that the, the deal, if I remember correctly is that the browser people or the standards have said that they will never put a dash in an actual HTML element. Oh, if you put a dash in yours, then it's clearly custom. Your element might conflict with my element in the future. Like it both ended up making a stopwatch, but the standards committee is never going to make a stop dash watch. If they, you know, what if I decided to call it div or something, right? It would, and then a div came along and it messed everything up. So that's right. So this is where having some governance or some namespacing around components that you create is probably a good idea if you're going to adopt this. But yeah, can you exactly good point? Do as I say, not as I do. Don't call it stop dash watch. Call it your project dash something. You know, you show where custom elements was defined. Custom elements is, um, is built into the browser. Right. But is it when you're, you're importing it? Nope. It just knows that, oh, it's on the window object. It's on the window object. Got it. Okay. So it's built into the browser and you can do that at any time. Very cool. This is sort of going deeper to sort of explain how we're containerizing and encapsulating whatever is inside of our custom component so that we can be isolated from the rest of the page and what's going on in the rest of the page and specifically addressing that CSS styling issue that we had. I mean, I think let's dive in, show me, show me the way. The first thing I want to say is that the Shadow DOM that's here that we're going to look at is different from the one in React. Oh, that's a good point. Yeah. So I got confused initially because I thought, I know what the Shadow DOM is. And I was like, hey, don't it was, it was the React Shadow DOM. Right. Their own version of it. That's proving that there are not enough metaphors in English language and we have to reuse them and then everybody gets confused. I could make a comment about big companies reusing English words, but I won't. So let's just go to it. Yeah, I'll imagine what you're talking about. We're using the same name for two or three things is always, always fun. That too. So let's take a look at the code. There we are. And the HTML hasn't changed. It's the same thing. So if you missed the previous episode, you might want to go watch it, but we've made a custom web component called stopwatch. And last time the, the style of the stopwatch overwrote the style on the page. So there's a, but a plain old ordinary button at the top. And now we fixed that. So the, the button at the top, you know, OK, it might be a little ugly. I am not an artist, but it looks like I intended it to look, which is right, kind of ugly. And these still work independently and pick up the color off of the, off the attribute. So the problem before was that we, if you recall, we had our regular style sheet, which has the yellow and black button that was called in by the page. And then here in the stopwatch subfolder, we have the styles that are used by the stopwatch. Sure. And then the code imports that. And last time we were attaching that as the adopted style sheet of the document object. Right, right. So the only difference here in the code is these lines here. We're going to create a shadow DOM and attach it to this object. So this again is our component, which is extending an HTML element. So it is an HTML element, but instead of attaching the styles to the document object, we're going to make a shadow DOM attached to this element. And we'll call that shadow root, we'll remember that. And then we will apply the adopted style sheet to the shadow root. Right, OK. And that's it. Well, there's no other change. It's just those lines of code are enough to tell the browser everything underneath of this shadow root element is to be isolated. OK, cool. From a CSS point of view, right? Now, I wonder if the SharePoint framework had had this and if just a speculation, but imagine that the sequence had happened differently. OK. And that Internet Explorer had been put out to Pastor before the SharePoint framework. Do you think we would still have those CSS modules that are used in the SharePoint framework where it puts a funny GUID on the end of all the games? Yeah, certainly wouldn't need it in that case. I mean, it's it's actually an excellent use case to say that any web part that's being built or any component that extends the page in SharePoint work well, teams, its iframe. So it's a little different, but let's just go with that theory, right? But if you're trying to play nice on the SharePoint page, that your solution would be a web component is really interesting because you're right, all of your CSS would then be isolated to the to the component that you've built. Interesting, really interesting. I am always not sure how to think about that. I could almost I mean, now that you're talking, it's making me think, well, would SharePoint framework have even been designed the way that it well, I guess it it is very open, though, you don't have to use React. No, I was right. I always write mine and you build a React component. And I was thinking, what if I built a web component? And I've done it. I've done it works framework that works. OK. Yeah, yeah, you can do no framework and you can build a web component in using the SharePoint framework at that 100 percent works. Well, what I guess we're sort of discussing is what if the SharePoint framework itself made you a their base class made you a web component? Yeah, that or even, I guess, with the technique that you use, where you just say no framework and you make a web component. And then I'm controlling you could you could you could use this shadow DOM thing to prevent collisions on the page. Oh, I 100 percent could and and have done it and it works great. And OK. Yeah. And it's something I'm leaning towards in a direction of. But at the same time, like the share that the engineering team could have taken that on and isolated you by default. And done it sort of automatically. Yeah, and you wouldn't have even known you were being isolated. So it's because other than if you are don't define all your CSS styles, you're not going to look the same as the page. So there's there's an aspect of that. But yeah. OK. So well, it's good to know that this is usable right now. Absolutely. Yes. If you do what this sample does pretty much in the code. But exactly. Or you can use the framework that I've played around with a little bit that's sort of like helper classes and helper functions called LIT that help you build web components and gives you some state and other things like that that you're maybe used to using because of using like a framework like React. That that is a really interesting framework that you can take a look at. So I'd love to know if any of our viewers, you know, use the SharePoint framework. Do you think this might be useful? Would you like to see maybe some of Julie's examples where she's actually applying this inside of SharePoint in particular? That might be interesting. So yeah, I'd love to hear from people in the comments. Well, did you like this episode? We hope you did. Please give us a thumbs up and consider subscribing to the channel so you can be notified of any new episodes that are released. And I hope to see you at the next one. Thanks. Thanks.