‫Welcome to another coding challenge
‫and I hope that you really are finding these useful.
‫And, if you do,
‫then it's now time to build a reusable
‫text expander component.
‫So, here, I have three of these text expander components
‫that we are going to build.
‫So, a text expander is basically
‫when we have some part of a text,
‫and then we have this kind of button here
‫that when we click it
‫will reveal the entirety of the text,
‫and then when we click it again,
‫it will go back to hiding it.
‫So, this one here is basically one
‫of the text expander components
‫and then here we have another one.
‫And, immediately, you see that this one has by default,
‫a lot more text.
‫And, then this button here has some different text
‫than this one
‫and also a different color.
‫But, then when we click it,
‫the behavior is exactly the same.
‫Then, finally, we have another one,
‫and you see that this one has some different styling
‫and also by default it is open.
‫And, so then when we click here, it will close.
‫So, let's go here to the starter code,
‫which as always I have attached as a link to this lecture.
‫And, if for some reason
‫you don't want to build this challenge here on Code Sandbox,
‫just copy paste the code from here
‫and also from the CSS file.
‫So, that's not a lot,
‫but we will still need that.
‫Alright, so, here,
‫I already have the three components included inside the app.
‫And, the component itself right now only renders this to-do,
‫and so, yeah, this here is your to-do,
‫so to build this expander right here.
‫Now, by including these three text expanders here,
‫I'm already giving you a hint into what the public API
‫of this reusable component will look like,
‫because here we already used many of these props.
‫And, so from this,
‫you can kind of imagine what each of them does
‫in order to achieve the three results that we saw here.
‫So, the challenge for you is to now actually go ahead
‫and implement this text expander
‫using everything that we have learned up until this point.
‫And, if for some reason this is a bit difficult,
‫then just imagine this as a collaboration
‫between you and me basically.
‫So, you build as much as you can on your own,
‫and then if you can't move on anymore at some point,
‫you simply watch the rest of the video
‫where I will then basically help you
‫completing this component.
‫And, if you want, you can of course
‫also go crazy with this one
‫and include even a lot more props
‫than just the ones that you see here.
‫So, you can...
‫Yeah, really do a lot of customization here if you want.
‫But, of course,
‫it's also more than enough to just do what we have here.
‫So, this is a really nice exercise,
‫which I hope you will complete, or at least part of it,
‫and then I see you back here with my implementation.
‫Okay, and let's get to work.
‫And, I will immediately start
‫by copying all these corrupt names here.
‫So, selecting them one by one, then copy,
‫and then I will just receive them here,
‫then, of course, just some commas,
‫and then we can get to work.
‫And, in fact, we are actually missing one,
‫which is basically just the text here.
‫So, of course, inside of the expander,
‫we need access to the text.
‫Now, this text is between the opening and the closing tag.
‫And, so what that means is that this is the children
‫of this component,
‫so it's gonna be inside the children prop.
‫So, to start, we can actually immediately render that here,
‫just so we see that this works.
‫And, indeed, here we get the three pieces of text
‫that we have right here.
‫Great, so we already have part of the output,
‫but, of course, we also want that button.
‫So, let's do that.
‫And, here, let's immediately allow the user
‫to pass in a class name.
‫So, in this last one here,
‫the user passes in this box class name.
‫And, so here we then accept that.
‫And, so then let's edit right here.
‫So, class name equals class name like this.
‫And, so this is exactly what we also did
‫in our reusable star rating component, right?
‫Now, in that example,
‫we didn't actually have a class name,
‫but now we have.
‫And, so immediately you see that this third one here
‫got this different styling.
‫Okay, now let's place this text here inside a span,
‫so that then we can add the button.
‫Alright, and now the text of the button
‫can actually be customized.
‫So, that is what we have the prop
‫of the collapse button text for.
‫So, let's get that, place that here,
‫and then we have some error.
‫So, let's see what's happening.
‫Now, we're not closing the span,
‫so that doesn't look too good.
‫And, so here we already have one button.
‫Now, here then we have this like kind of very small button,
‫which doesn't have any text.
‫And, so that's because only this second text expander
‫is actually passing in the text
‫for the collapse button text property.
‫And, so that's because this text here,
‫so this label of the button,
‫is different from the default.
‫So, if we take a look here,
‫then you see that, by default,
‫this one and this one display the text "show more".
‫And, so then this one here is different
‫and it says "show text".
‫So, yeah, this one here is show text.
‫And, here it is actually expand.
‫Okay, so expand button text should be by default show more.
‫And, so now here we have show more,
‫then this one that's different, show text,
‫and then again show more right here.
‫But, now, of course, we want something to happen
‫when we click on this button.
‫So, we want only parts of the text here to be visible.
‫So, we need some state, right?
‫So, let's call this is expanded
‫and set is expanded.
‫Use state.
‫And, then, by default, let's make it false.
‫So, by default, the text should not be expanded,
‫so we only want to see a small piece of the text, alright?
‫And, just make sure
‫that your use date was correctly imported.
‫Okay, and now let's use this is expanded state
‫in order to calculate or to compute the text
‫that we actually want to display here.
‫So, let's do that in a separate variable
‫and let's call it the display text.
‫So, if it is expanded,
‫so if expanded is true,
‫then we want all the text to be shown.
‫And, so that's then the children, right?
‫So, children is that text.
‫That's why we placed that here in the beginning, right?
‫But, if not, then we want something else.
‫So, let's just write test there just to experiment.
‫And, then we will, of course,
‫replace the children here with that display text.
‫And, so, by default,
‫now all three of them have this test here,
‫which is this part.
‫And, so, again,
‫that's because, by default,
‫this expanded is false.
‫Now, actually, if we take a look
‫at one of these components here,
‫then this last one will have the prop
‫of extended equals true.
‫So, right here, I don't have that.
‫So, I have this one,
‫but in the starter file that you will see,
‫I will not have this one,
‫but instead expanded.
‫Okay, so, again, in the starter file that I had here,
‫I had a mistake.
‫So, we had the wrong prop here,
‫and it's that we want an expanded prop,
‫and not this one.
‫So, here it's not button in line, but expanded.
‫But, in the code that you see,
‫this will already have been fixed.
‫So, the meaning of this expanded prop
‫is that if it is set to true,
‫then, by default, the component here will be expanded.
‫And, so that's exactly this third situation right here.
‫So, if we reload this one here,
‫then you see that the third text expander
‫is by default already expanded.
‫Okay, and so that's because expanded is set to true.
‫So, here, let's now actually not use false,
‫but really get this initial state from expanded.
‫And, so then we can set expanded to false by default.
‫And, so this is very similar what we also did
‫in our star rating component.
‫So, there we also set the initial state
‫based on one of the props, right?
‫So, by default, we now have this last one here
‫already opened.
‫And, so this one shows the entire text,
‫while these ones here for now only show test.
‫Now, another thing is that,
‫in this case that the text is expanded,
‫here, the text,
‫so the label of this button should be different.
‫So, it should be show less by default.
‫And, so let's do that here again as a default prop.
‫So, show less.
‫And, so, then here,
‫let's conditionally display that text.
‫So if is expanded,
‫then show the collapse button text,
‫and, if not, then show the expand button text.
‫And, so now it says show less.
‫And, so this other component here
‫will then show collapse text instead of show less.
‫So, because it passes in this special prop
‫that we have defined here.
‫And, if all of these props here
‫and all these default values here
‫look very confusing to you,
‫well, that's just because we are really trying
‫to make this component here very flexible and reusable,
‫so just like we did with our star rating component
‫When we build our normal components in applications,
‫we will not do this, right?
‫We will then usually have the text directly in here,
‫for example, instead of relying on the props
‫and on default values of those props.
‫But, again, here we are striving for maximum reusability.
‫But, anyway, let's now finally actually
‫make this button work.
‫So, specifying the on click prop.
‫Here, we just need a function,
‫and then let's say set is expanded,
‫and then the new state will be based on the current state,
‫so we use the callback function here,
‫and, instead of writing the entire word,
‫let's just say exp, which stands for expanded,
‫and then we just toggle that here.
‫Now, that's it.
‫So, let's see.
‫And, indeed, as we click there, the text is now hidden.
‫And, if we click on one of these,
‫then it will show the text.
‫And, again, it will then hide it.
‫Great, now, next up,
‫let's take care of not displaying the test here,
‫but instead displaying some actual part of the text.
‫Now, notice how here we have this prop,
‫which says collapsed number of words.
‫And, so here let's again specify a default,
‫which is 20.
‫But, of course, it could also be any other value.
‫So, the idea here is that, by default,
‫when the text is collapsed,
‫it will only display exactly this number of words.
‫So, only 20 words.
‫But, then you have, for example,
‫this component here,
‫which shows more words.
‫So, 20, this one should then actually be 10,
‫so that this one here shows in fact more words.
‫So, by default, only 10 words should be displayed.
‫So, let's do that.
‫So, this is just some standard string
‫and array manipulation.
‫So, we can simply split this string by the empty space,
‫which will then give us an array,
‫and then we can slice,
‫or, in other words, we can take all the elements from zero
‫all the way to collapsed number of words.
‫So, by default, we take the first 10 words,
‫so from zero to 10,
‫and now this is still an array,
‫and so we need to put it back to being a string.
‫And, then, we also want to add at the end these three dots.
‫Okay, and we could have used a template literal for this,
‫but we can also just add them here at the end like this.
‫So, that works the same way.
‫And, so, as we click here, it shows all of them them,
‫and otherwise it just shows exactly one, two, three, four,
‫five, six, seven, eight, nine, 10 words,
‫plus these three dots.
‫Beautiful.
‫So, that is already working.
‫Now, all we have to do is to take care
‫of the styling of this button.
‫So, let's again specify an object here.
‫Let's say button style.
‫And, then, background, set it to none,
‫also no border.
‫And, again, this is necessary,
‫because we want this component here
‫to be 100% reusable and standalone.
‫So, it cannot depend on any external styles.
‫So, let's also set a cursor to pointer.
‫Let's give it some margin on the left side of four pixels
‫or let's say six.
‫And, finally, we also want to give it a text color.
‫And, so this is where this button color prop
‫comes into play.
‫So, let's grab that and place that here.
‫And, now, all we have to do is to assign this here
‫to the style prop.
‫So, style, button style,
‫give it a save,
‫and beautiful.
‫So, now this button looks more like text,
‫but it is still missing some color.
‫So, let's by default add some blue color here,
‫which is 1F09cd.
‫Alright, and there we go.
‫So, the second one again is personalizing
‫not only these two texts here on the button,
‫but also the color and the number of words.
‫And, so that's why this one here looks quite different.
‫And, then, again,
‫this one here has this special styling here
‫that's coming right from our CSS file
‫in the form of this box class.
‫Great, so this is working,
‫and, in fact we are now basically finished.
‫So, this text expander component is now highly reusability
‫and it hides all the complexity from the user,
‫so from the consumer of this component,
‫which again is really nice and really important.
‫So, as the developer of this component,
‫then we chose the public API, basically,
‫and therefore allowed the user
‫to customize it to their needs.
‫And, as always, we could have gone really crazy here,
‫and, for example, allow the user
‫to place this button here in different places
‫like below, or on the left side,
‫or, here, right at the very beginning.
‫We could have allowed some more styling here
‫of the entire component.
‫Or, we could also allow the user to specify
‫whether they want to see these three dots here or not.
‫But, again, that's just not necessary,
‫because, with this, we found a nice balance.
‫So, this is the interface that we chose.