Make Your Own Svelte Component Library

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey friends today we're going to learn how to make your own UI components in swelt in this example we're going to make an awesome and accessible accordion which is really easier to do than you think but you're going to learn other things for example how to compose components in sweld how to use context as you can see here this is an awesome accordion only one can be open at a time if we pass these collapse props and if we don't pass it then you can have multiple open at a time I also have another prop here which is going to be open and since this is a loop I'm going to say if I is equal to zero so we're going to have one by default open if I refresh it you can see it works as expected then you're also going to learn something really awesome how we can pass CSS variables to cell components which makes styling and customization extremely simple so I can go here for example accordion background I can say black and then I can change the accordion item color itself say accordion color you can change it to something like aqua and how awesome is this and this is really extendable so if you're working on your own component Library you're going to learn how you can do that so yeah I'm excited to get started if you want to follow along create a circuit project I'm just using the basic template with typescript you don't have to use typescript it's purely optional and you can always find the example and everything I'm saying here in the post so as you can see here in our page I have some items which you're going to use to Loop over the accordion items inside our layout importing our regular CSS file and in a CSS file I have some basic resets I set the height on the HTML and body element and then I Center everything using this awesome one line of CSS and basically that's it all reference before we get started I want to talk about something really important I really want to focus on the techniques and how you can approach implementing this kind of things so you can apply to your own project or learn something new alright so you want to make a cast the mui component they basically are replacing some functionality of the browser and no one can blame you because the browser has a lot of awful Primitives so what do you do well thankfully there is the web accessibility initiative or Aria offering practices guide APG where you can go and you can learn how to implement these things so you can go to the patterns you can see here is the pattern for all the popular UI elements if you have to implement it yourself so they're saying okay if you're going to do this yourself at least do it right and it's truly nothing intimidating so they really describe the pattern here we have an example you can play with they even tell you what you need to do which you're going to look at this is just a lot of text but it's really not that complicated and then if you go to the example they have this example and unfortunately they also included for some example a form here which makes the code example complicated for no reason but yeah basically that's it so if you look at here keyboard support it tells you what you need to do space or enter should focus the accordion pressing tab should move the focus and using shift tab should move the focus back and then they even show you what role property State and tab index attribute use so you just go here okay check check really nothing intimidating and then they even give you some code including the JavaScript which isn't relevant to us because we're going to use sweld but you can see here is even the HTML source code so they tell you hey this is semantically correct and again this just looks like a lot of code because they included a form for whatever reason and over complicated things for no reason but yeah you can see here it is so basically this is how you can approach doing these sort of things and there's really another awesome thing which is open UI let me just look it up so basically open UI is focused on researching these design patterns and bringing them to the browser if it ever happens that is right because you can also go to this page and you can look the research on for example let's look at an accordion so you can see here is the resource they even link to other design libraries how they use it so you have everything here in one place how they do it so for example if you look at the switch here is from InDesign Atlas kit Evergreen I haven't heard about most of these to be honest but yeah you can see how others implemented if you need some inspiration but yeah that's basically it so let's go build an accordion all right friends let's get started so you can do this many different ways and what I love to do before I write any code I like to think about a magical API I would love to use so you can just dream it up I can say accordion and then I can start thinking okay how do I want to approach this I know that I'm going to have an accordion component but what kind of API do I want to use how do I want this thing to look like and then I can walk backwards I don't even have to understand if this is possible if I just have an idea I can just ask someone hey is this possible as well how can you do this right and this is really super exciting when you start to get into that mindset and you start to realize that almost anything is possible so what can we do we can for example pass these items and then I'm thinking okay maybe we can Loop over these items in the accordion and show them but that's kinda meh because you have to always specify an array then you have to pass it but then maybe let's look at another option so maybe we can use composition as well we can create an accordion and then we can maybe have an accordion item so you can do it like this and then we can give the rendering control to the user so they can pass whatever they want they can say title or whatever they can insert a paragraph like a description okay that's starting to look a lot better and I started doing okay how am I going to do that well basically I have an accordion you're going to have to think how can we pass some state to the child Elements which is also fun and in the case of the accordion item how are we going to pass the data we're using props in celt of course so if we remove this we can just use name slot so we can place the items wherever we want so let me just create a div for example and I can say slot titles are going to put it in the slot which is the title and then we'll just say item one let's just copy it over and this is going to be the content and you can also make another one for an icon if you want or Etc and this is already starting to look good to me so you can remove this one and of course we didn't create anything yet so that's going to be a problem if we save right and now this is starting to get real right so we're thinking about this API we're just thinking okay if I have an accordion the default Behavior I want is that you can open each one but maybe if you can pass a magical prop like collapse you can only have one open at a time which is really cool but what if I want to have an accordion item open by default how can I specify that well for that accordion item I confess a prop such as open and that's going to be really cool but let me just remove that and let's go to implementing the accordion so I'm going to open the sidebar in Source lip folder which is default by Alias I'm going to create new file which is going to create a folder using this neat trick so I'm going to say components accordion and then I'm going to create the first file which is going to be index TS actually because we're going to export the component so let me show you something cool now I can go here and I can create an accordion and by the way it's really not important if you use lowercase or uppercase for the cell component name that's really relevant I prefer lowercase so I can do this I can create a new one I'm also going to have an accordion item and I can close this so what did I create this index.s file so we can export these components and we can just use one import for them so you can for example do import accordion from now we can get autocomplete and now I can say accordion item from accordion item and now we would have to say export and then you can do accordion accordion item which would work great but there's another syntax you can use so instead of doing this you can say export since this is a default text where we can say default as accordion from accordion swelt let me just copy this over so we can say accordion item same thing you can remove this and now we have our export so we can close this file so we just go here and now we can import it so you can say import accordion and accordion item from since this is Alias we can use lib we can say components accordion is going to be it and if you just created the loop folder and circuit has issues recognized and it just restart the developer Source you can go to your terminal control dot control C to stop it and you can say PPM randf and everything should work and awesome we don't get any errors and we can start working on the accordion all right so let me just rename this to content two and I'm just going to duplicate this over so we have more things to work with let's say item two and content 2. all right so let's create the accordion item we're going to go here I'm just going to create a regular div and I'm just going to give it a class name accordion and then you can pass anything we have here so if you don't know what a slot is basically here you have an accordion so you can say okay everything inside of here is like a black hole so celt is going to slip it up basically that's what a slot is so anything else you're going to show here or just pass it to another component just like you have in regular HTML right because a parent can have children so I'm going to go here and I'm going to add a simple script and now we're just going to say export let collapse and by default we're going to say false so this is going to be our prop which is going to collapse all the other accordion if you specified and then let's add some simple styles so here I'm going to say accordion and we're going to do something cool so I'm going to use a CSS variable I'm going to name it accordion with and then we can specify a fallback value is going to be 60 characters we're going to say padding same thing accordion padding one ram by default and then for the color you can say accordion color I'm going to say hsl 10 10 because I really like this color now I'm going to say background color accordion background and I'm going to use C 2020 10 and of course these secondary or default values can also be CSS variables which I encourage you to do but for the sake of the tutorial I'm just going to hard code it like this all right then I'm going to have a border radius accordion radius I'm going to say 4 pixels and then I'm going to have a box shadow for the young Shadow make sure you spell it right and the default value is going to be 0 pixel one pixel 20 pixel hsl is going to be 2020 ten and eight percent for the Shadow and you can also pass the opacity which actually if you say slash you can do something like 10 but you already pick the color I want so everything works great awesome and basically we can pass the CSS variables to the component in soil to override them and how awesome is this you don't even have to do that you can just Define these variables in your Global Styles or whatever as you can see we already have the element here so let's start working on the accordion item so you can show it on the page let me also save this and now we're going to go here I'm going to create a script and by default the first prop we're going to do export let open false just so we know each one is open or not and because each one of those is a component this state is specific to that component so if you change open it's not going to change the open state for any other value but only for that instance of the component alright so let's create an accordion item like this then you're going to have a button which is going to have a class accordion toggle and inside of here we're going to have a title so we're going to say accordion title and this is the slot you're going to pass so you would do something like this but you can also pass multiple slots if you want and you can give it a name so this is going to be the slot name title and then we're going to add the carrot or that pointy symbol I actually don't know what the name of that is but I'm just going to name it accordion carrot you can paste it on SVG or whatever else you want an icon here that's really up to you and then I'm also going to use an emoji so I'm going to say point so let's say we should see our two items how beautiful is that friends so now after the button this is going to be our item we can say if open and then we can give it a class of accordion content so you can also complete it and now we can give this a slot right so how do we do it we say name and we're going to give it a name of content so as you can see nothing shows up right here but if we say true then you can see here is the text which you have to add some Styles so let's do that quickly so I'm going to go to the Styles here I'm going to say accordion toggle with 100 percent padding so again since the CSS variables Cascade is CSS right we can override these values here so you can say accordion padding and we're also going to give it a default we can say color bar accordion color and we can say inherit and we need to override some styles for these ugly buttons by default so I'm going to say font inherit font weight is going to be 600 border none background none and since we also want a cursor pointer here when you hover over it you can say cursor pointer let's also give it a border radius we can say accordion radius and you can specify a default value and now let's see so we can specify Let's see we can also say display Flex justify content space between so I want this text to be on the left and the pointy boy to be on the right so we can do that and this is you're going to use a hover later I'm just going to say transition background color 0.1 second is let's save that and awesome this one looks better so let's give it a hover for the end say accordion hover is going to be a new value but we can use a default one which is going to be 20 20 20 and 20 percent and then for the accordion content we also want to give you the same padding so I think we can even go here I'll just do this so we can say accordion padding one ram all right and let's see why we don't have our color so inherits it from this color so let's see I probably did a mistake here here is color oh this shouldn't be dark it shouldn't be a light value like 98 so if we save this really awesome and of course nothing works yet but as you can see now we're starting to see some results and our wish stop code is now reality so another thing you can do if we inspect this element right now you can see all of these elements here going to have a wrapper but there is this really useful thing insult if you don't want an extra wrapper you can use swelt fragments so let's just select all of these divs Ctrl d now I'm going to say swelled fragment and this is going to just remove those extra wrappers and awesome now we don't have those extra divs or record this is optional you don't have to do this alright so let's first toggle this open so we can go to the button here it is so you can see on click we can say toggle open and I can just specify a function here function so we'll open and now we're just going to flip the Boolean so we can say open equals to whatever is the opposite so we can save this and just close the developer tools so now we should see that this works and this is really awesome all right so this works great but let's get to the brain Twisted part so we have our component here and then we have an accordion here and we have our prop collapse right and this is really great we can pass the prop and we can receive it here but how do we actually pass this data to your child elements of course you can pass it using props so you can say here collapse if on but now we have to use collapse for every item and you have to keep track somewhere is this updated or not and this would get really tedious so what we can do is use the swell context API so let me open TL draw this is turning into a teal draw tutorial so we have your parent here child and of course there's plenty of ways of doing it you can use a store but that's Global right and we're going to use a store with context actually so basically your goal is to somehow pass data to your child components without using props and that's basically where the context API comes in so you can come here and then you can use the context API so you can set it in your parent and maybe you're familiar with context from react it's really similar to that probably inspired by that to be honest so you can set the context here in the parent and now you can just access this data inside any of your child components you can go as deep as you want but there's a problem how do we know which ID is active so for this ID to be active we somehow need to assign it an ID right which is going to be really easy then we can use the context to keep the track of the active ID and we're going to need to use a store because the values in context aren't reactive so we can update the currently active component and then we can say if this is the currently active component then it should be only open one at a time alright so how can we do that well inside of the accordion here let me just save this file we're going to go to the accordion and now we can just import firstly going to import our writable from swell it's well store and then we're going to import the context so we can say set context from swelt so how do you set the context well it's really simple you can just say set context and you can just pass it a value so for example we can say collapse and now we want to pass it to the children right so you can also pass collapse and if you specify collapse you can say set context active and we're going to create the active one right now so this is going to be the active component ID and this needs to be a store because it's not reactive right so you need to always update this value so you can say const active component ID is going to be a writable and by default is going to be null and I'm going to type it right now for people who don't care about typescript so we're going to do that a bit later and also now we can save this and now we can go to the accordion item let's just copy this import over so you can go to the top Here and Now how you have set context you have get context and now when you're here you can say collapse you can say get context now you can use the key to get the value we can do the same for the active component ID we can say get context rename Detective and awesome and now let me just go to the developer tools Ctrl shift I inside the console so just log these values collapse active component ID and because active component ID is a store we have to use the dollar sign so you can see its default null alright but remember we also need to set a unique ID for the component so how can we do that we can go here we can say cons component ID and now we can use math random or whatever you want but I'm going to use the built-in crypto modules this is built into node and the browser so you can say crypto random uuid so this is going to give a random name to our component if we login component ID so you can see every component is going to have a random ID now we can know which one is active so let's define a couple of functions if we just remove this so we're going to have a function set active this is going to be really simple as saying active component ID we need to subscribe to it with this dollar symbol because this is a store but if you were not in as well component in another file you have to use the method restore so you can say set and then you can set it to the component ID but since we're using stores in a Cell component we can use this sugar active component ID and you can just set it to the component ID and this is going to be updated and if you're curious this is complaining because it doesn't have a type which you're going to cover later so here we have toggle often but I'm going to make another function function handle click so here I'm going to say hey if the user passed collapse then we're going to set this component to active otherwise we're just going to use the default Behavior toggle open so now let's also Define some reactive variables here so this is the accordion item to be open by default so we can say open if that is true and collapse is true then we're just going to short circulate and set it to active so this is going to set the default item to be opened so now let's have another reactive variable is active so we can look if the active component Vector component ID matches the component ID and also be careful to not do the same mistake I do all the time don't say equals because this always trips me up when I type something quick make sure that you're comparing it so you're saying hey active component ID if equals to component say hey this is the active one and based on that we're going to have a reactive value is open so if collapse is passed then we're going to look at this value is active otherwise we're going to look at the value of open that is passed and now we can change this on click here to handle click and here instead of open we can now say is open let's save this and everything should work the same as before but now if we go here let me see page so so again we have collapse you can see it already works it's one at a time if you remove collapse ah how beautiful is this so let's see if we pass in collapse and now we had a value open right so this is open let me just refresh everything so this is the first one let me specify it for the second one oh now the second one is going to be open by default and everything else works the same all right so since we have a list of accordion items here we can Loop over them so let's do that instead I'm going to cut this and then we can say each I have this handy snippet now I can say items as item now let me just paste this over so we just need to pass in the values this is going to be item title this is going to be item content all right let's save everything and now we should have everything working how beautiful is this friends all right so let me just close this and let's add an animation so we can go here so we can go to the bottom and let's just specify the rotation so we're going to have a class of open and we're going to have a class of close so let's say transform rotate 90 degrees you can also use the single value if you want it also works so you can say transition transform 0.3 seconds ease now we copy over the same thing because we want one for the enter animation one for the exit animation you know instead of 90 degrees you're going to rotate it back so you can go to our carrot and we can use the class directive so this is really slick let me just do it like this prettier is going to ruin it but it's going to be easier to see for now so we can use a class directive so hey toggle this open class if what if it's open how awesome is this and then toggle the close animation if it's not open awesome let's save this and now let's look okay now how awesome is this now it works now when it's closed it's totals ah just that little touch of Whimsy is what makes my day but if you notice there's one problem well it isn't a problem this works great but how do we animate this and animating the height is historically very difficult recently it's very easy you can do it using CSS grid but swell has this awesome slight transition for us so we can say import slide I can type from swelt transition so let's put it here and now we can go to the item now we can say transition slide look at this how awesome is this friends right there's one more thing we have to do we have to specify the transition to be local because local transitions only play When the block they belong to is created or destroyed so for example the problem would be let's say that you have a page navigation here and since you're using the page navigation it will trigger all of these transitions right so we're just saying okay just keep it local to this block and this is simple as just saying local and awesome how beautiful is these friends alright friends so we're almost done but let's look again at the why Arya specification so if you remember let me just pump the phone size down we need all of these attributes so let's just edit quickly all right so it's really simple first you need to go to the button here and then I'm just going to add some Aria rolls here so we have on click we have the class and now we have to say area expanded and now for the area expander we can just say is open which is easy because we're using soiled then we have to specify Aria controls and we have to give it the same name so it has an identifier for the screen reader we're going to use the component ID you can end this whatever you want banana it's really important that it matches you can see here it tells you what to do expand the true controls and that's it for the button so now we just need to do it for our content here is our content let me just make space here so it tells you that you should use roll region we can also say Aria hidden when it's not open but I'm not sure how useful this is because it's not even rendered on the screen but if you're not using swell for the transition in CSS this is then required I think and then you can say labeled by as it says right here labeled by and we need to give it the same ID so you can say accordion component ID so we can save everything and if you go back here let me just show you so now we have it here in our element so we have the accordion the toggle button carrot as you can see here is the area expanded area controls so the screen readers are going to have an easier time but you if you just tap here then you have Focus if you press step again it's going to go to the second item third item fourth item shift tab should bring the focus back right here pressing enter should expand it networks as attendant so as you can see here it's not really that bad alright so we're almost done but let's clean up the code a bit I'm going to make the context code a lot nicer and I'm going to show you the types so what I'm going to do I'm going to open the sidebar here in our accordion I'm going to create two files I'm going to say context the Azure so everything is neat and tidy and I'm going to create types DS and first I'm going to include the types here so I'm going to say type accordion options which is only collapse and it's a Boolean then I can say type active ID which is going to be a string or null and I can say type collapse context and you're going to see how you're going to use this right now and this is going to be really a neat way to keep everything in one place because you don't have to import your types everywhere for the context to be happy so we can say active ID context and this is going to be a writable which is going to be imported as a type from Salt so you can say writable see it's it's a generic we can say active ID yeah and now we just need to export these values awesome and basically that's all the types done so now let's go back to the context file and basically instead of having things all over the place you're going to have everything in one single file so if you remember we have const active component ID which is a writable so let's import that from Salt so what type is that going to be active ID which is going to get imported from the types we're going to pass default null and then I'm going to Define two functions I'm going to say function set accordion options and then I'm going to have another function get accordion options and you can do this however you want but this is really neat so what are the options you're going to pass there's only one which you're going to pass as an object collapse and now we can just give it a type of accordion options I'm just going to get imported from our types how awesome is this and now we can do the same thing we've done before we can say set context we're going to set it to collapse the collapse we passed and then we're going to also say set context which will probably import it from Salt right I'll just move this to the top so this is going to be the active ID let's say active component ID and now we can also pass it a type here like this set context so this is going to be the collapse context and this is going to be the active ID context which really isn't that intimidating there's just really a lot of letters on the screen as you can see even the Auto Import rooftop so you can just clean this up you can say import type and let's see where this was important so if you specified set content just here then you would have to import this type again in this file where you consume it right and instead we can just do everything here so you can just say const collapse and now you can say get context how awesome is that you can say collapse what type is that collapse context this is really awesome you can say active component ID get context and we can get active and we can pass it a generic type which is going to be active ID context awesome but now we can return it so we can restructure it so you can return collapse active component ID and don't forget to export these functions save and that's basically it alright so now we're going to see how clean Things become so we can just remove this we don't need all of this junk we can remove the writable and context and let's see if the Auto Import works so we want set accordion options ah awesome it Imports this and now what options do we want to set we want to set collapse we want to pass an object that's really awesome we can save that so now this becomes much easier so now we can go here and we can remove all of this junk also so we need the component ID but we can remove collapse and this for now all right so let's also import it get accordion options how beautiful is this so let's just remove this we're going to remove this and this is an option actually a function my bad so we can just structure it we can say const and now since we typed everything we get great autocompletion if you press Ctrl spacebar we get collapse active component ID so now we have everything in place so now this stops complaining because it knows what type it is right and let me just do it like this and basically that's it really nothing intimidating if this is the first time you're doing it's probably a little bit confusing but just give it a try practice it on something maybe simpler so you understand what context is just pass some data like a hot potato through your components so let's see if all this works how beautiful is this friends so everything works the same as before we just made it a lot cleaner so as you can see this is a start of a great UI component Library you can use yourself or make one for the public to consume and also remember the variables from before so let me just first try this out and just do this and I'm going to say open if it's zero then if I refresh this awesome it works just close this and now remember we also have access to the customization so you can say accordion background you can make it white and then you can say accordion color I think say black and awesome now we have this and now we can change the hover style so you can say accordion however so let's see let's give it a white color and then we're not going to see it anywhere let's give it something random like aqua I'm a genius friends awesome how beautiful is this friends chef's kiss alright so that's it if you like what you've seen don't forget to like And subscribe and you can support me by becoming a patron and join the Discord thank you for watching and catch you in the next one peace [Music] thank you foreign [Music]
Info
Channel: Joy of Code
Views: 10,957
Rating: undefined out of 5
Keywords: svelte, sveltekit, component, library
Id: teXFHcugXaI
Channel Id: undefined
Length: 35min 16sec (2116 seconds)
Published: Fri May 26 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.