Build a UI Library with React, Typescript, TailwindCSS and Storybook

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hi there in this video I'm going to show you how to build a UI Library using react T CSS and storybook we're going to create four different components for this Library which will be a button component which will be served in three different variants such as solid button outline and ghost then we're going to have an input component which will be useful for Gathering user information such as a plain text password numbers and also dates we're going to have also a text component just for displaying some basic text in different styling we will also have a layout stock component which will be useful for applying a vertical layout to our screens or containers and finally we are going to put everything together by constructing this login form which will use only the the components that we have defined above so without further Ado let's get started okay let's start by creating a new react project we are going to use VD for creating our react Library so let's run yarn create VD let's name this project simple UI select react as a framework waran typescript let's see inside simple UI and install all the dependencies by running yarn okay once done we can start up the server and it should be listening on the port 5173 let's see if it's working yep it's working correctly okay next up will be open this project on vs code so let me select simple UI open up okay so this is our initial project structure first thing that we like to do is to initialize a git repository so let's make a first comit uh let's open up the source control for the commit message I will use the copilot hint and let's go to commit this great okay next stop I think will be uh setting up pror for automatic formatting our uh files when we save for do that we are going to need a vs code folder where we are going to define the setting. Json inside we are going to paste this configuration uh right here so as you can see as soon as I save the file has been formatted automatically okay uh let's try making some initial changes to see if it's working correctly let's remove this uh also this stuff let's try to Define a paragraph which say it works and as soon as I save the we can see that pror is working correctly I think we are we are going to have to restart our Dev server and yep it's working properly even though it's all the way on the left but this should not be a problem now uh I'm going to remove all this file because uh we are actually building a library and not an application so we don't need any of this file except for index. CSS and like for showcase how our application will work we are going to use story book that we are going to implement later so let's remove all this file okay okay so uh let's commit this stuff perfect as a next step I would like to configure the TS config what we are going to do is adding the a base URL which will be the current folder and also Define some uh part alysis in this case we can um apply this suggestion given by copilot and this is needed for avoiding having like absolute Parts with many dots inside as a next step we are going to uh update also the yesl file and we are going to apply uh some custom uh rules uh we are going to replace this with another configuration where we basically shut down uh some yes link uh rules uh great so okay let's commit this stuff okay now let's start by scaffolding our library structure and we are going to need some different folders one for storing our components uh another one for storing some mtil function and finally another folder that I will call example where we're going to or some kind of screen okay inside this components folder we can start by defining a first our first component which will be a button um I'm going to define the index. TSX great let's define our component button and actually uh this will be uh HTML button element most important inside the component folder we're going to need to Define another file called index. TSX so we're going to need this file for like collecting all the export uh for uh relative uh Imports yeah at this point we are going to need to install Tailwind so let's go to Tailwind CSS uh VD which will be which is a guide basically that explain uh how to set up Tailwind in a VD project and so we can start by installing uh tail wi assess so all the dependencies so uh we are going to need these three dependencies first so this YN OD and while it's installing Next Step will be generating the Tailwind config file that we are going to do in this way Del win CSS in it DP will generate the BSS config JS and also the tawi config so third step is like uh defining where our Tailwind classes are uses so uh we can just put the source folder to tell Tailwind to look out for Tailwind classes um inside this all this directory right here next step will be adding the Tailwind directives inside the index. CSS so let's go here remove everything uh actually I think that I didn't copy this out great if we go back to our button and trying to find class name we should have the intelligence enabled for uh Tailwind as we have seen before we don't have any application entry point for this project because this is uh as I say this is a library so uh we are going to install story book for showcasing our components and examples so uh Next Step will be first starting by committing this stuff let's go here run NP story book uh in it okay once story book has finished completing installing it ask us if we want to add some yes link rule to enance our Dev experience and yeah we can install it okay so as you can see story book has launch automatically we can skip all this stuff and I guess that it adds that's so many files that uh we don't actually want so we can safely remove this folder stories and what we can do is like updating the main configuration of storybook so here you can see our storybook find out their stories defined in our code base so it basically go inside the source folder and you start to looking for all the MDX file or or it search for all the file that have the stories. JS jsx TS TSX uh file extension okay since we are using pysis in our code base basically we have to specify uh special configuration to enable story book to work properly with uh PES that we Define the TS config uh in order to do this we are going to add this uh configuration right here that I will uh just paste and it's basically this VD final uh property so basically we are saying to storybook to go in the T config file and search for all the paes that we have defined to make this configuration work we have to install a special uh function which is this TS config BS in order to do that we need to um install new dependencies which is y-d which is called VTS config PS so let's add it to our project we should be able to add a new dependencies which is uh this function TS config P from with TS config PS so we need also to import uh PA from PA this is the native module PA which uh is used to resolve p in our project so okay this is the first configuration we actually need another configuration under the preview. TS file so basically here we need to link storybook to Tailwind CSS and the way to do this is to import the index. CSS file which is located under the source folder and if you recall from that it basically contain all the tail wi uh directive great okay so now we can start by defining our first story let's go here and Define a new file called index. stories. TSX and as you can see inside every component we are going to define the index. TSX file which is the implementation file of our component and a separate story file so um uh first thing that we need to do inside our stories is to import some type we're going to need meta and story uh object then we're going to need to import uh our button component then we have to Define an object called meta is of type meta with the type of component button and here we're going to define a title which will be under components button we have to specify the component itself specify some parameters for example the layout we want lay out to be centered and finally the TX property where we set auto docks this is needed for generating a page called docks okay from that we are going to export this default meta since this is needed and then Define a type story uh which will be equal to the story object of type of meta actually we have to reimport this and for Define a first story so here we Define a first story where we pass as children of our button let's say the string click me so now what we need to do before checking if it's working properly is going back to our button component and taking in input all the props that a button element expect in order to do that we can do component props of button accessing to all these props find in a typon notation here and then spreading out this props so in this way we access all the props of the button and from here we are able to basically specify we have access to all the possible attribute that a button element expect to take an input okay so let's try to run story book at this point let's run yarn story book and you can see that Tailwind is working properly the text is blue we have no custom style since Tailwind by default strip out all the default CSS uh base style and we can see that we have all also this docs autogenerated page where we can Define all the uh different props that this button takes in input okay as you can see the string click me is not rendered this is because we are actually defined um custom children here and we can safely remove this and basically uh use a self AOC closing tag and if we go back here and refresh you can see that now we can put everything here like hello and it's working fine great okay before moving in um let's commit all these latest changes and also this one and now it's time to talking about how we are going to handle all the styling part for our components ideally we want to use uh Tailwind for applying custom style to our component library but actually since we're building custom Library we want to we are aiming to creating component similar to for example uh chakra UI let's take for example the button component you can see that every component accepts different prop which enable us to Define sizes for example small medium large different variants for our button different colors and everything is done by the finding props so we want to achieve the same result in order to achieve this we are going to need to install three libraries which are clsx clsx is basically a library for constructing class name string uh conditionally then we're going to need uh Tailwind merge and finally we are going to had a library called class variance Authority which I'm going to show you here class viance Authority also named CVA and basically all that this Library does uh is permit us to Define different variants for our uh component so basically here we Define some of the props that our component takes in input and apply to this uh props particular styling for example here we are saying that for a button component we want a prop name intent and this intent prop can have the value primary or secondary and if we apply primary um we are going to uh apply this Tailwind style and if we have secondary we are going to apply this one instead we are going to have different props for example here we have hent but we have also uh sizes with value small and medium with the relative Styles we can also compound this variance for example if we have um a primary hinted with a medium sides we want to apply the tail wind class uppercase to our button component and we can also Define some default uh variant okay so at this point uh we are going to need a function that we are going to Define inside the utls folder so let's start by defining an indexx file and so what we're going to do here is import clsx and also the class value from CSX then we going to need to import uh Tailwind merch from Tailwind merch and after that we are going to define a function called CN that what it basically does taking uh multiple classes from class uh value and then basically apply a Tailwind merge and then uh apply a clsx so what it basically does is to apply the clsx function to all these classes these classes are going to be defined inside our class variance Authority and merging them together let's see how does it work let's go back to our button and let's define some uh button styes we're going to use the CVA function import CVA from CVA uh class variance Authority the first parameter is going to be the default style that our uh button component is going to have so for example we want our button to be full width um okay actually before start implementing our style for the button component we can go inside the vs code folder open the settings. Json and Define a new property let's paste this here so what this property does is basically enable the Tailwind intelligence inside the CVA function so now if I open up string quotes I should be able to access to all the Tailwind classes great as I was saying before this CV function permits us to Define different style for our components the first parameter in this case will be the default style for our button component so let's start by saying that uh we want a full width and we want our button to have some rounded border we want the font to be semi bold having no outline when it's focus and finally when our button is disabled we have no cursor csor not allowed and so this this first parameter is so is the default uh style that our button component is going to have then we can Define differ prop or variance different props that our component is going to accept in input so actually yeah we want to define a prop called variant which could be solid outline with some kind of Border let's remove the color from here we want also another variant called ghost where we applying the transition colors and a duration of 300 we want also another prop called Sid where we Define small uh with a px of four uh py of two and and text set to small and let me just copy the other two uh values which are medium and large and also we are going to accept uh a color scheme which is going to accept as value only the primary value okay so let's define also some compounding variance so compound variant basically are applied when multiple variants start to combine one each other for example when we had a solid variant with the color skin primary we want to apply the BG primary 500 with this over styling and the same is for the outlin button of the offered the cost uh button uh actually you can see here that we are using primary which is not supported by Tailwind in order to do that let's go ahead inside the Tailwind config and extend our tee uh configuration and let's add a new colors called primary and let's define our primary color to be blue actually for having this color we have to import color uh from Tailwind CSS color so our primary color will be uh the blue colors uh provided by Tailwind CSS great so if we go back inside our variance you can see that now the extension is working properly and give us the proper uh suggestion finally I'm going to apply also some default variants so if we don't specify any kind of custom property that we uh Define above uh we're going to apply um solid variant medium sides and the color scheme to primary okay then at this point what we can do is to first off uh extend our button props by using the variant props of type of uh button style this variant props should be come from the class variant authorities great so now our btom props should uh receive all this new custom prop that we have defined here for example if I go here you can say that now I can assess the variant uh prop I can access the sides and also the color scheme once we have all of this here we are missing a commo let's remove this class name because we are going to use the previously defined function n and thisn function is going to use the button style that we Define above and passing an object with uh different props like variant sides uh color scheme and also we want to extract the class name prop since we want to potentially um update our button component by defining Uh custom like Tailwind classes from like the consumer point of view great so if we go back to the index stories of the button component you can see that uh inside the argument that this button takes an input we should have the variant and you can see that here we can accept solid outline or ghost we're going to use solid we can specify a side which should have uh small medium and large let's define a medium and also we should have a color scheme which can be only uh primary if we go back to our story book you can see that everything is working fine so our component has a blue background and based on the variant that we set this case solid and as side of MD color scheme primary we can see that is rendered correctly actually we have also the the full story that we defined which is using the solid variant that we defined before what we can do uh now is instead of having this default story Uh define specific stories like for example one for the solid uh variant another one for the outline variant and a final story for the ghost button so uh if we go back to story book and let's go ahead inside the docs page we can see that we have all the different button the solid variant the outline and the cost button you can see how the transition is applying smoothly also for the outline we have like the 3D different stories applied for every variant of this Bon component great so actually we are missing like to make this component uh Library proof we're actually missing one property which is the ref prop in order to have the ref prop which should be like be able to access here we have to use the forward ref function provided by react this forward ref function accept to type parameters the one is the props the the element that we are working on in this case an HTML button element and the second is the props that the component accept as input so this forward ref accept in input uh function which is the element so it's basically pretty much the same we have to return this button Buton here inside and inside the function that we are defining we're going to have all this stuff that we extracted here so we can remove it from here this part can be safely removed now and also this okay as you can see now is formatted nicely and is much more clear after the com we have a second argument which is the ref which we can pass here great now is our first component is pretty much ready we have all the variant we have the ref prop and we can move to our second component which will be a text component but before moving in Let's uh commit this stuff great so let's now Define our second component which will be the test text component let's define the index. SX file okay so let's start by defining component we will name text the text component we can start by defining it as a span component we will need all the props so type uh text props equals to component uh props of a spawn let the spread access these props here text props and passing it inside the spawn element props uh great we can Define all the class variance that we want to apply to our text component I already already prepared this so let's just paste it here we have to import our CVA variance Authority let's take a quick look at this style so we apply for every text component a full width and we Define the following props the emphasis which can be only low where we apply a Tex gray 600 and a font light we apply some the prop sides which is basically map to hwind class to manipulate the size of the text we have the weight prop a property for aligning the text and two Boolean prop for applying underline or italic text styling and by default we apply like the base uh font sides and we align the text to the left so to accept this we have to access the variant props of type of textes we have to access it here great our text is now should be ready let's define some story index. stories. SX and here I will just copy some stories that I already prepared so we basically Define The Meta object which put the text inside the components or folder in story book here we Define the default a default story with a a long string inside so let's go back to story book and let's see if this text component is rendered correctly actually is a rendering text because we have to remove this and applying a self closing tag our text component is working fine we can actually go here put our string hello world okay so at this point this component is missing the forward reference let's do the same thing we did for our button component so forward ra pass here HTML spawn element and also the text props this will take an input function which should be this one we don't need also these text props I guess and here we should be able to access the ref can then spread here great actually we are missing an important part for this text component which is the S prop what is the S prop for example uh we want this text component to be rendered as an H1 or H2 as a paragraph As a span currently we are rendering all text component as a span but we want this to be dynamic in order to provide this feature we have to Define first some utility types which I'm going to Define inside the U folder so let's create a new folder is called type and here let's create a file name index do TS okay inside this file we are going to Define some type that will enable us to passing the reference to the text component and accept in input a generic HTML element to pass as the srop I'm going to Define some uh type first we need the type uh props of which basically extract all the props of a particular component then we Define another type called s prop that add the S property to the prop that our component takes in input then we need another type uh which is extendable prop paste everything here uh now uh these are a little bit tricky to understand but basically what we are doing is to Define some types that accept in input a generic element type and from this generic element type we extract the all the props that this element takes in input along with the S prop and also we should be able also to take an input the ref prop so they are a little bit trigger but I suggest you to take a moment to understand how they work so let's back to our text prop what we're going to do is to remove this is old uh type text prop and Define a new one which is also name text prop but we'll take a generic type parameter which will extend a react element type and this will be equal to polymorphic uh component props with ref where we pass the the generic type c which should be an element type and also all the variant uh props that we Define above so we have this text props type and we also need another type name text component which is equal to a generic type argument which also extend react element type which by default is a spun so every component that does not define uh the the S prop will be rendered as a as a spawn we're going to define the props which are text prop of C we are going to return our react react element or null this point what we need to do is to apply a type annotation to our text component to be equal to text component then remove this type argument from the forward reference because now we have to apply a generic type argument inside a forward rep function here we have to define the element type which should be equal to the spun so this props will now be type we have to define a type annotation which will be equal to text prop of C and also this ra will be equal to morphic gra of C at this point we have to extract some of the prop that this text component takes in input including the S prop and also all the variant properties like uh align s emphasis metallic underline weight and also the class name now what we have to do is extract a variable called component which will represent the component that will render this text component so it can be yes or if it's not defined will be a spun and then we can use this component inside the rendering function okay here also we have to Define our class name where we pass the CN function and pass the text style inside here we have to pass all the variant wait emphasis oops EMP is italic underline align and also class name uh great so we should have everything set up and finally all the remaining props which we should take from here uh great uh as you can see if we see this error I was not able to understand why typescript was throwing this error the way that I fix this for now is to expect uh a typing error but for now we can leave it like this and yeah now our text component is ready to accept all the variants that we Define in the text style and also like we can render this component by using custom HTML element or if we don't specify anything we use the spawn element so if we go back inside this index. story uh you can see that now I can pass this has and pass for example H1 if we go back to story book and hit refresh if we open up the inspector this component now is rendered as an H1 this enable has to build bulletproof components okay before moving in let's commit our latest changes okay so now we can create uh another component that I will call input so let's define the implementation file let's export this input component obviously this input will use the input HTML element we can remove everything here and use an self closing Auto do let's take all the uh input props component props of input and then let's pradit this props here and say input props and go here pass this props great let's define also some basic styling so let's import here TVA from class variance Authority these are some basic styling that we can use uh for our input text so we set full WID border border gray rounded border yeah some basic styling okay at this point uh what we need to do is to get the class name and actually uh extend this uh input so let's define it here and let's take the variable props from type of input style let's import this from variant props right so here we can Define our class Name by using the TN function passing the input styles we're not defining any particular variant for this component so we don't have to pass anything inside the input Style by default let's set this type to text and remove the auto complete okay we need also to uh apply the forward reference so here we are going to say HTML input element and here input props we are going to copy this out here inside we can remove also this type ofn notation get the reference and pass the reference here great our input component is now ready so let's define some stories and I'm going to just pay some stories that I already made it so as always we Define our uh meta object and here I Define like some basic story for our input text component for example here we are defining an input text here an input password input number and also input date we have our new input component this is the input text variant this is the password uh example number date as well and in the docs page we have all the different variants put together in the single page great uh we are going to use these components like button input text to create a login for to put all these Library components together and see how they works but before we do that we actually miss other components uh let's first commit everything what are we missing right now is uh some layout component so let's create a new folder layout here inside a new folder as well called box I would like to Define stock let's define the implementation of box so let's define our box component this is actually we can uh remove this and using a self closing tag and Define the Box props to be equal to component props uh of div here instructing the props all the various props and spread it out here great then we do have to forward the reference and here def find the HTML div element also the Box props and pass the reference here great this will be our box props we don't Define any kind of variant because is a layout component so does not make any sense to have particular styling for for this component but actually we are going to leverage this box component to define a new uh this other component the stock so let's define this implementation file so let's name it stock great let's remove all the this thing and we're going to use the box with self enclosing tck let's define the stack props which will be basically equal to the Box props because they are pretty much the same correct we have to first export this type great so now we can update a import and pass it there stock props colum uh stock props wring all the props here and passing it right [Music] here actually we are getting this error here because the Box props are missing the reference so we have to use component props with ref uh which we can import uh from react and now yeah error has disappeared let's define the class name so we are going to use the Cen we are going to pass um for example a flex and flex uh column with the item set to start so basically a stock is when every element is stuck one after each other the second arumand will be the other uh class name that we are going to extract from the list of props great the stock props can be Leed like that uh let's define a new Sor stories. SX let me just copy some initial configuration here we can start leveraging the catalysis but for doing that we have to uh start exporting all the components from the main index file another Main main index where we export everything go back to our story import our stock component this is the same configuration we applied for the other stories and now let's define a particular story to see how this stock uh work so let Define a story we have to define a custom render function to uh make it work so here we can take the arguments Let's uh declare our star component which will take all the arguments and let's define also some class name like let te some Gap little bit of ping and also a BG gray uh 400 and inside the stock we can uh Define multiple box which are going to we have to import this and here we are going to Define for example a we of uh 100 pixel an eight of 100 pixel and a background of blue 500 actually we can self enclose this and let's redefine box let's copy this out let's make the second box red and the third one uh green this stock will contain this three box of 100 by 100 pixel great let's go back to story book and we should be able to see our stock under the layout folder since we decare this under layout slash and this is our uh stock component you can see that the three boxes are stuck one each other okay then let's commit everything let's go back to our Explorer now we have all the components that we need for this Library we have button input layout and text we can make our first example which will be a login screen where we are going to use all of these component and this example will be available on story book as well so let's define our login form okay so uh let's start by creating this login form let's start by defining a parent box uh great so let's import our uh box and let's add some horizontal ping and vertical ping also some border and Border gray set to 300 great so now we are going to use the stock component let's start by defining a text component Port it from text from components uh this text will be this case an H2 and we'll have weight of bold and also will be Center aligned and a size of 3 Exel and also a custom class name set the marching button to two and inside this text we are going to add the login text so under the login text we are going to have like a subtitle which is going to say say please enter your credentials to log in and this text uh will be a spun we have the emphasis set to low and also the sides set to small will be centered aligned and also have a class name of margin bottom 8 while we doing this we can start by defining also the uh story we can just paste it actually we don't need to specify anything uh inside the main story that will be named uh login okay so let's see how this is coming it's coming as expected we have our login title and also subtitle so let's add some field let's add uh a text which say user username and this will be rendered as a label we'll have an HTML for usern name sides of small weight of medium and also a class name to set the margin button set to 1.5 okay now let's use our input text component uh this could be self enclosing let's import it it will be type of text an ID having same username placeholder set to username and also let's define some margin bottom set to four uh great a password the password type so we Define first a text label and then an input component which will have the types set to password let's say how it's coming it's coming great finally we are going to have submit button we say login let's import it this will be of type submit we have a variant set to solid and a class name of marching bottom set to 10 if we go back to story book you can see that this input text is not setting margin bottom to apply some spacing to the below password text label and this is because uh if we go inside the input component we are not Plus the class name inside the input style we can actually doing now and now it should working properly and great now we have our login screen that we build entirely uh relying on our library and set an username uh password and also we have our submit button here there you have it we actually build our simple Library so let's commit this new changes so the final point of this video will be showing you how to make this Library a standalone package that we can possibly push in a package registry like mpm or yarn and so in order to do that we have to make some tweaks on the various configuration file that we have so first off let's head into the V.C config.sys this case our pysis start with the head symbol we need to import uh path from path and here do pa. resource solve and so basically resolve all the inputs that start with the at symbol inside the source folder the second configuration is the build property we are going to define the LI configuration where we basically Define the entry but. resolve uh directory name here we're going to use Source components SL index. TSX that means that the entry point of this Library will be inside source component and basically all the stuff that we are exporting inside actually here we are missing all the components from our layout so let's do in this way so after the entry point we should specify a name for this Library this case we can name it simple UI and then specify the file name for the import which will be simple- UI actually this is file name like that great second option will be the roll up option where we basically Define all the dependencies that we don't want to bring inside our package we have to Define also the output where we def find some globals uh like react will be react and reacton will be react D capitalized great we have actually we need to Define also a custom plugin which is name VD plugin DTS let's going to install it so let's clear the console and run y-d uh VD plugin GT s great now let's import this plugin right here and as a last step let's define this DTS plugin and we have to pass the rad types that to true oops true great what this plugin does basically is generating the index. D.S file which is uh the file which contain all the type for all the components and function that we are exporting great so this was for the vid configuration last step will be going into the package.json we have to define the files property set to this actually set to this great then specifying the main entry point for uh this file which will be this is the simple UI UMD CJs and then Define the module simplo i. JS then we need to Define some exports the current folder where we are going to have s import this simple. JS and as require we're going to have the this simple - MD uh CJs that should be hit now if we go here and we run y build uh V Should uh try to bundle uh this library but actually is not able to resolve the entry model Source components dots because actually its name is uh we have to go back here and name this as TSX now it should work here build if you go take a look at our Explorer we can see that V generate is this folder which inside contains some file including the uh simple UI and simple UI UMD basically this UMD file will uh change based on the environment of where this Library is being imported and it will be transformed into commonjs or the newest es module we have all the types declared inside here actually here we have also this vvg we actually don't need this because so we can remove the public folder and we can actually remove the index folder index. HML since we don't need it anymore so let's run another build and let's see if it is clear CLE it up yeah you can see that now uh we don't have that SVG anymore great so this will be like shipped as our package library and we can publish as I was saying in a registry to be used by other uh user or by us for making our uh personal project great let's commit this stuff and there you have it that was pretty much it for this video I hope that you find it useful to understand what's are the step required to building uh a library as always if you like this video leave a thumbs up and if you have any kind of question feel free to reach me out in the comments and as always we will catch in the next video
Info
Channel: Gionatha
Views: 7,059
Rating: undefined out of 5
Keywords: react, typescript, tailwindcss, storybook, ui
Id: L8SxJ_cN1qc
Channel Id: undefined
Length: 63min 19sec (3799 seconds)
Published: Tue Dec 12 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.