In this chapter we're going to implement the code view. This will be a slightly longer chapter in comparison to our last one, simply because we have a bit more components to create. But let's start with adding tabs in our project view component, so that we can switch between the fragment web component and code view component. So as always ensure that you are on your main branch and you can synchronize changes. The last chapter was 12 fragment view.
Now let's go ahead inside of our project view and this time we're going to add a couple of components. So let's go ahead and just in between the fragment and the components UI resizable add tabs, tabs content, tabs list and tabs trigger from components UI tabs. You have them installed when you added chat CN UI. And once you have added them, it's time to use them. So What I'm going to do is I'm going to go below the project view and I will add tab state and set tab state.
I will add use state here. And I will set the options to be preview or code. And by default, it's going to be preview. Now that we have the tab state let's go in the second resizable panel here and let's encapsulate the active fragment within tabs. Now in here let's give the tabs a class name, heightFull, gapY, 0.
Default value will be preview. Value will be tabState. And on value change, we'll get the new value and set tab state to be value as preview or code like this. Then inside of these tabs let's add a new div and let's encapsulate this once again. This div will have a class name of full-width, items-center, padding-2, border-bottom and gap-x of 2.
And then open tabs list and again encapsulate the fragment. Inside of the tabs list, give it a class name of height zero, padding zero, border, and rounded medium. And then finally, inside of here, we can add tabs trigger. The first one will be the value preview with the class name, rounded medium. We're going to render the eye icon here, which you can import from Lucid React.
And while you're here, also import code icon. Let me just move them to the top. There we go. So let me just fix this. Just a second.
So I think I just have to remove this. There we go. So instead of this tabs trigger, add the eye icon. Like that. And a span demo.
And then copy this trigger. This one will be code with the text code and uses the code icon And then outside of the tabs list, go ahead and add a div with class name MLAutoFlexItemsCenter and gapX of 2. And this button will, I'm sorry, this div will encapsulate a button from components UI button, which will not serve any purpose now but it will later so give it as child give it size small variant and for now give it well just default a link from next link, so make sure to add this, with an href of pricing, and add a crown icon, and upgrade text. Great. And now, outside of that div and outside of this div as well, So move this outside, add tabs content.
This one will be for value preview, so you can put this finally inside. And then we're going to have another tabs content or value code. And this will simply be a paragraph to do code. There we go. So make sure tabs content is still inside of tabs.
So now when you go inside of your app here, you should see a button to upgrade, which should lead you to 404 page and you should see that you can switch between demo and between code. The demo doesn't show anything until you select a fragment right so you can see how you can switch between the two. So now let's develop the code part. So in here, it will be quite similar. So let's start by doing the following.
Npm install prism.js This will be used to highlight code syntax. So let's go ahead and develop this simple component inside of source components. So in here, add code view.tsx. And in here, you're going to need just one more thing. So let's actually create a folder code view like this and move this inside.
And you can Change this to be index.tsx. And then go inside of your vibe assets. You can use the link in the description or you can see it on the screen here and find code theme.css. So it's quite long, that's why we are not typing it. So go ahead and copy this and create it here.
So code theme dot CSS and just paste the entire thing inside and save it. And now let's go ahead and develop the code view here. So you're going to import everything from PrismJS. And let me show you PrismJS. Oh, did I install it or not?
Npm install PrismJS. Let me see. PrismJS, it is installed. But I think I also need to do npm install dash d at types Prism.js. There we go.
So Prism.js 1.30 and types 1.26.5. And now it works. Below that, import UseEffect and then import the following things. RisenJS components and then JavaScript, JSX, Python, JSX or TypeScript. You can remove if you're not going to use Python, for example.
And finally, import code theme CSS. So just make sure this is in the same folder. Then, export const code view. And create a simple interface. Props.
Which accepts the code, which is a string, and the language, which is a string. So assign the props. Let's destructure them, code and language. And inside of here, return a pre tag, give it a class name padding2, background color transparent, border none, rounded none, margin zero, and the text extra small. And inside of here, add a code element, which renders the code.
And let's give this a class name. And let's go ahead and use language-lang, like this. Usually if this was a TypeScript class name, you would not do this because you shouldn't do this kind of half dynamic class name, right? You should instead do the full one. But this is not a Tailwind class.
This is a class from Prism, right? That's why you don't have to worry because you can see that it is exactly what it expects. And now let's just use the use effect here for a very simple thing. So on load, simply use prism and highlight all. That's it.
So that's going to be our code view component. And if you go inside of project view, maybe we can already render it. Let's try code view. And let me try adding language to be JS or let's do TS and let's do code. Let me just write const a is equal hello world.
Something like that. Let's see if we are able to preview that and we are. There we go. And I think that it will also affect dark mode. And you can see how the syntax is visible.
Very nice. And now let's actually use this in a file explorer because that's what we have to do next. So we're going to go ahead and create the file explorer inside. Yes, let me just show you how you can import CodeView. So you don't have to go to index.
Index can be used like this. That's why we named it index. So you can just target code view. In case this doesn't work for you for any reason, you can just name this properly, name it code view again, and then just import that way. Now let me just move it up here.
There we go. So now let's create the File Explorer component. I'm going to go inside of Source, Components, File, whoops, FileExplorer.tsx. And let's go ahead and let's prepare the imports copy check icon and copy icon from Lucid React use state, use memo and use callback as well as fragment from react. Hint and button from components.
Button comes from chat-cn meaning it has the UI prefix and hint is our custom component which we created in the previous chapter. Now let's import our new code view, which we just created. And then let's go ahead and add resizable. With resizable handle, panel and panel group. And let's also import everything we need from breadcrumb.
So both of this come from Chatsy and UI, so you have them. Breadcrumb, item, list, page, separator, and ellipsis. Now let's go ahead and let's define our file collection. This is our file collection type. It is basically a type of record string string.
But I like to use this type simply because it uses the path as the key and then the content here. I think this kind of visually makes more sense. I think we did the same thing in our functions. Path, string. Yes, this is exactly how we define our files here.
So I like to do this because I think it visually looks better. Great. So now let's go ahead and first create a function which can extract language from file extension. So get language from extension accepts the file name and returns a string. And what we do here is we simply target the extension part and we take that part and we turn it to lowercase and we default to text if we were unable to do that.
So basically, if we enter something like app.tsx, we return tsx as the language. As simple as that. Perfect. Now let's go ahead and let's create a component which we are going to need in order to even render which file is currently active. So I'm just trying to think what is the best way to build this so that you can see the results as soon as possible, because there's a lot of components we have to build, and I'm just afraid that we might have to build for a lot of time without seeing any results.
So, this is what I will do. We're going to do export const fileExplorer like this. Let's create an interface fileExplorer. Actually, let's just call this fileExplorerProps because we're going to have many components in this file. So I want to name this explicitly to be File Explorer Props.
It will accept files which are a type of file collection, like this. Then let's go ahead and let's use this and we can destructure the files from here. So now what I want to do is I want to add the return resizable a resizable panel group like this with the direction horizontal. And then a resizable panel with a default size of 30 with a minimum size of 30 and the class name background sidebar. And inside of here a paragraph to do tree view like this.
Then let's go ahead and let's add a resizable handle here. With a class name, hover background primary and transition colors like this. And then let's go ahead and do another resizable banner like this with a default size of 70 and a minimum size of 50. And in here, What we are going to do is try and do files first in the array. I'm just thinking of a way.
OK, I know what we can do now. Let's create a state called selected files. Const selectedFile setSelectedFile useState. And it can either be a string or null. And let's go ahead and create a function inside of useState to get the file keys by using object keys and passing the files and then return fileKeys.length is larger than 0, we can select from the file keys the first in the array, otherwise null.
So this way we are going to pre-select the first file we can find. And now that we have this first file, I think it will be a little bit easier for us to build this UI. So inside of this second resizable panel, check if we have the selected file, and if inside of files, we can find this selected file. If we can do that, go ahead and render a div code view like this. Otherwise, let's go ahead and render the alternative, which is a div which says select a file to view its content with a class name, flex height full, items center, justify center, and text muted foreground And I think it's time to render this, so let's go inside of the project view here.
And let's go ahead and render it instead. So remove code view and check if you have active fragment question mark files, render the file explorer component and passing the files to be active fragment dot files as and in here you can choose to use let me just copy from here this type basically because the JSON type will be any, right? So we are now marking it as this. Make sure to import the file explorer and you can remove the code view now because we're going to use it inside of the file explorer. And I think that already, just make sure you have a fragment selected here when you click on code you should have a to do tree view and to do code view perfect and I've had some trouble making this work oh looks like it's working just fine okay my version had some problems I think looks like it works just fine nevertheless okay Now let's go ahead and let's actually develop the tree view and the code view.
So I'm gonna go back inside of the file explorer here, and I think it might be easier to develop the code view first simply because we already have The code view so I'm gonna go inside of this div here and I'm going to add a class name height full width full flex and flex column And then I'm going to open a new div, the class name BorderBottomBGSidebar. Tx for py2 flex. Justify center. Actually, it will be justified between items will be center and gap x will be 2. Then let's add to do breadcrumb, file breadcrumb like this and then add a hint component wrapping our button component and give this a text of copy to clipboard and the side of bottom.
And for this button right here, give it a variant of outline, a size of icon, a class name of ML Auto, on click to be an empty arrow function, and disabled to be false. And inside of here, render the copy icon. So now, when you click on code, you should have the copy to clipboard button. Just make sure you have both button and the hint imported. Great!
And now below this div we're going to open a new div with a class name flex1 overflow auto and render the code view in here select the code to be files and then selected file. And the language will be... Oops. The language will use our function. GetLanguage.romExtension.selectedFile.
Oops. Like this. And by default, you can see that it's selected a specific file. Right now, I'm not able to scroll. We will fix this as well by, let's see, it has overflow auto.
But I think that we are missing something, obviously, because it's preventing us from doing this. So let's see. Everything here seems fine. But yes, I'm not able to scroll to the bottom here. So how about I go inside of the project view here.
And to the value code, add a class name and minimum height of 0. And I think that now, when you select the fragment, there we go. Now I'm able to scroll in all directions. You should be able to scroll left and right and up and down. So basically inside of your project view in the tab content for the value code add a minimum height of 0.
And this will allow you to scroll inside of the code preview. So this is now showcasing the very first file it selected. But now we have to build the tree view so we actually see the file we selected and so that we can choose between other files. And then we need a breadcrumb component here to render the current file. So let's go ahead and let's build the tree view next.
So I'm going to prepare that right here in the file explorer, right above where we added a to-do to render the tree view. Let's add tree view like this. And let's give it some props. Data is going to be an empty array. Value will be selected file.
OnSelect will be an empty function. Now let's go ahead and let's prepare these things here. So what I want to do now is the following. I want to go inside of source, lib utils and I will export function convert files to tree items and I'm going to create a js doc like this simply so you can see what happens. So this js doc is quite useful.
I don't like, I mean, I don't use it usually, but it's useful when I feel like things are not exactly clear. You can see how when you create a comment like this and when you hover over a function, it actually tells you that. So it converts a record of files to a tree structure. So we accept files, which is a record of file paths to content. So this is the input, right?
Source, button, tsx, and then some content. And this is the output that it will return. So that's what we are building now. So let's go ahead and add some props here. Files, which will be a type of path, which is a type of string, and a string.
And it will return a tree item. So now we need to create the tree item object. So let me just do this like so. I'm trying to think of a perfect place to add this to. How about in source, we just create types.ds.
And let's export type tree item. And that will be a string or an array of string and tree item itself. So it can reference itself. It can be a deeply nested array. Now that we have this, we can go back and set up the utils file here.
And we can set the return method to be the return type to be tree item from the types and it's going to be an array of those tree items and it's going to be an error until we actually return that so I want to do this because this way we are certain that we correctly developed this. So let's start by creating an interface tree node like this, which is basically a key which is a string and then tree node which is itself inside or null. Then let's define a tree, which is a type of tree node, and it's going to be an empty object at first. Now let's go ahead and create sorted paths. So we are basically sorting the files alphabetically by their path.
And then what we're going to do is a for loop. So for const filePath of sortedPaths, let's go ahead and split the filePath into parts by doing filePath.split by a forward slash. The current one will be the current tree which is just the empty object for now and then for let index being zero, index being less than the parts length, minus 1, and index increasing by 1 for each iteration. Get the part, so parts, and using this index here, if we cannot find the path, the part in the current object, we need to add it there, like this. And then current is equal to current part, like this.
And then what we have to do outside of here is add the file or the leaf node, right? So const file name is parts, parts.length minus one. Current fileName is equal to null. This will basically indicate that it's a file. This is quite confusing, right?
But once you see how the file structure will look, it will make a little bit more sense. OK, so I think that this... Let me just see. Yeah, so OK, we just finished this for loop, right? And now we have to convert the node.
So let's create an inner function to do that. Function convert node. The node it accepts is a tree node. We have defined the tree node right here. And the name is an optional string.
And it returns back a tree item, an array of tree items or a single tree item. Like this. So let's get the entries to be object.entries from a specific node. If entries.length is equal to zero, return the name or an empty string. Then define the children to be a tree item, like so.
And set it to be an empty array for now. And then let's go ahead and do for const, the structure, the key and the value of entries and do the following. If value is equal to null, That means this is a file. So do children.push key. Else, This is a folder.
So create a subtree using convert, node, and passing the value and the key. So we need to go deeper. We need to recursively call this function again until we find a file. If array is array subtree children.push Open an array of key and spread the subtree. Else, children.push, key and subtree.
Like so. And then, let's go ahead outside of this for and return the children like so and then let's define the result here to be convert node tree and return array is array result result otherwise result inside of the array like this and if you've done it correctly you should have no errors here Now I completely understand that this was a very complex task. And if you are worried that you did it incorrectly, don't worry. I have added my entire utils files to my public assets. So you can just find it here and you can copy it from here for example I can copy this entire file and I can paste it in here like so.
So now I have this convert node and I have the convert files to tree items. Right. So if you want to do a double check, or you just want to copy file because it's easier, you can do that. Don't worry. Yes, a slight mistake here.
My apologies. So don't worry. I will fix this file so it doesn't use this import, because our tree item comes from types. Yes, so import type, tree item. I will fix that.
Instead, I think I can fix it right now. There we go, like so. So when you copy, you won't have that problem. And I will double check by copying this file again, pasting it. Oops, copy it again.
I cannot seem to copy it. Let me try one more time. I think the copy button is still using the old one. Okay, finally, no errors in the utils file. Okay.
So now that you have the convert files to tree items, we can go back inside of the file explorer. And In here, we're going to have to create tree data. So const tree data will be useMemo and return convertFilesToTreeItems and passFiles here. And in here, add files as a dependency. So just make sure you imported our newly created function here.
You can either write that function yourself as we just did or you can copy it from the source code or from the assets folder. Great, now that we have this and we have the tree data, let's go ahead and let's add the const handleFileSelect to be useCallback. And inside of the useCallback, we're going to check the filePath to be a type of string. And if files file path exists, set selected file to be the file path. And add files here.
There we go. Perfect. And now, instead of the tree view, add the tree data here. And on select, add handle file select. Like so.
And now it's time to develop the tree view component so I'm going to go inside of components tree view dot tsx Let's go ahead and create the interface TreeViewProps, which uses the tree item from our types. Like so. And now let's export const TreeView. Let's assign the props TreeViewProps. In here we get data, value and onSelect.
And in here, let's go ahead and let's return a paragraph tree. Actually maybe we can do JSON stringify data, just so we can see what we created. And let's import the tree view from ./.treeview. And if you go back to your app here, select a fragment and click code. There we go.
I have app folder and page.tsx. So those are for me. But if I go into one of my older ones, well, it looks like all of these are pretty simple. So it's going to keep using just a simple example. But if you tell it to build something complicated, you will have more items here.
So this represents a folder and this represents a file. And now, I mean, this is basically how the file structure should look like. And now we're going to use that to properly render the tree view. So let's go ahead and let's import everything we need from the sidebar component. So that's going to be the Sidebar, the content, group, group content, menu, menu button, menu item, menu sub, provider, and rail from components UI sidebar.
You already have this when you added chat.cn UI. And now let's go ahead here And let's render that. So starting with the sidebar provider. And let's render sidebar with collapsible to be none and class name to be with bool. And then sidebar content, sidebar content like so.
Instead of the sidebar content, sidebar group, sidebar group content, sidebar menu. Like that. So you shouldn't see anything now, simply because we didn't add anything in the menu. So now what we have to do is we have to develop the tree component. So let's do that below here.
Const tree will have an interface tree props which will accept item which is a type of tree item. It will accept selected value which will be an optional string or it will be null onSelect which will be an optional function which accepts the value which is a type of string and returns a void and parentPath which will be a string. So let's go ahead and add three props here. And the structure, the item selected value, onSelect and parent path. Like so.
Inside of here, let's first do a destruction of the name and the rest of the items from an array. Array is array item. If it is, we can render the item, otherwise put the item in the array. Then let's get the current path. This will check if we have a parent path and it's going to render dynamically using backticks.
ParentPath forward slash name otherwise just the name of the file. If we don't have any items this means that this is a file. So let's add it's a file. Const is selected here will be selected value equals current path. And in here, we're going to return sidebar menu button with is active to be is selected.
And class name will be data active true, background transparent. And on click here, we'll call on select with a question mark because it can be optional and pass the current path instead of here render the file icon file icon from lucid react Just make sure you have it like that. And below that, a span and the name. And this will have a class name of Truncate, like that. And then go outside of this if clause and this means it's a folder and in here return sidebar menu item with collapsible We now have to import the things from collapsible as well.
My apologies, I forgot about that. So just add collapsible, content, and trigger from components, UI collapsible. You also have those components. So let's go ahead down here. And instead of the sidebar menu item, open Collapsible like that.
Let me just fix this. Collapsible. Give it a class name of group forward slash collapsible. And then add the following class name, which is a little bit longer and looks weird. So basically open curly brackets and this entire thing is inside of that curly brackets and and then if data state is open for this component target the button, target the SVG and target the first child and rotate it by 90 and set the default to open.
Inside of here collapsible trigger with the prop as child. Add a sidebar menu button component with the chevron right icon from Lucid React. And give it a class name of transition transform. So this is the icon that we are going to rotate by 90 once we open this collapsible. And next to it, add a folder icon from Lucid React, and then a span with the name of the folder, and the class name truncate.
And then, outside of the collapsible trigger, use a collapsible content. And inside of this a sidebar menu sub. And inside of here, go over items.map, get the sub-item, and the index, and render the tree again. That's right, we are rendering itself again. And in here, set the key to be index, item to be sub-item, selected value to be selected value on select to be on select whoops, parent path to be current path, like that.
And that's it for the tree component. What we have to do now is we have to actually use the tree component. And we're going to do that by going back here, inside of the sidebar menu, and simply do data.map item and index, render the tree component. Pass in the key to be index, item will be item, selected value will be the value, onSelect will be onSelect, and parentPath will be an empty string. So let's see what we didn't use.
We didn't use sidebarRail, So we forgot that. So let's go down here after sidebar content and render sidebar rail. Now let's go inside of the file explorer. Oh, we already have TreeView. So there we go.
Here we have it and we can open and close it but looks like our select isn't really showing it isn't working so let's fix that or maybe this is the selected state I'm not exactly sure So I'm going to try and develop something a bit more complicated. So I'm going to try to prompt it to something to create more files. So what I did is I asked it to build a landing page with each part in its own component. And that generated a much better result as you can see. So what I'm going to do is I'm going to expand this, I'm going to go back to the code.
And yeah, I still am not able to select this. So let's go ahead and look at what we forgot to do. So okay, these breadcrumbs are unused, that's okay. We're going to use them in a moment, but it seems like this handle file select is not working properly. So what I'm going to do is I'm going to first start by adding a console log and rendering the file path.
So I'm going to open my inspect element here and okay, oh, so it looks app name is being sent. Okay, so that definitely doesn't exist. Let's go inside of a tree view. And let's see what I did wrong. So in here we have onSelect, parentPath, and then the name.
Yes, this doesn't look correct. I think I meant this in the current path. Let me refresh and check. Select the fragment, check. There we go.
So I'm not sure if you can see, well you can definitely see the code is changing, right? And also the file is a little bit bold. So basically the problem was in the TreeView component, the current path, I hardcoded name when what I should have been doing is put it inside of curly brackets like this. Excellent. So now that we have this, the good thing is no need to do anything more in the tree view.
Now, let's go ahead and let's enable the copy button and let's create the file breadcrumb here. So I want to do the file breadcrumb thing first. So I'm going to go inside of the file explorer. Let's go just above it here. So const file breadcrumb like this.
Let's go ahead and create an interface file breadcrumb props which accepts an individual file path. Let's extract the file path from here And let's go ahead and get the path segments by a forward slash. And let's limit the maximum number of segments to be four. So if the path goes deeper than four segments, we are going to be responsive about it. Now let's do const render breadcrumb items like this.
And in here, if path segments.length is lower than or equal than maximum segments, add a comment, show all segments if 4 or less. So let's return path segments here, dot map segment index, const is last will be if the index is equal to path segments dot length minus one and in here return a fragment give it a closing tag give the fragment a key of index, the fragment is imported from React right here. Inside of the fragment, add a breadcrumb item. Check, let me just, breadcrumb. Inside, check is last.
Item Check let me just feel bread bread crumb Inside check is last if it is render bread crumb page and inside the segment and give it a class name of font medium. If it is not last, we're going to render a span element and segment inside and give the span a class name, TextMutedForeground. And then outside of the breadcrumb item, if it is not last, again, add a breadcrumb separator, like so. And this was inside of this if, so let's now add else. We're going to show the first element, and then ellipses if we have more than four of them.
So the first segment is what we care about. PathSegments, first in the array. LastSegment. So pathSegments.length minus one. So it's only those two that we care about.
And once we get those two, let's simply return a fragment breadcrumb item, a span, first segment with a class name, text muted foreground, and then let's go ahead and add the breadcrumb separator and the breadcrumb ellipsis like so. So render the breadcrumb separator and Then a Breadcrumb item which renders the Breadcrumb ellipsis. All of these are imported from the same thing. Then let's add another Breadcrumb item here with a Breadcrumb page and render the last segment inside. And give this a class name of font medium.
And finally, outside of this function, return breadcrumb, and then breadcrumb list. And then render breadcrumb items. Like that. So a little bit of effort here to create nice and responsive file breadcrumbs. And now let's go ahead and let's render them.
So that's going to be rendered in the code view. So there we go to do file breadcrumb just above this hint. Let's render a file breadcrumb. And let's give it a file path to be selected file. And there we go.
App, contact, TSX, features, footer, hero, navbar. And if you create one that's very deep, it will show a maximum of four folders before it uses the responsive mode, and it will just replace the folders in between with an ellipsis, which is basically three dots. Perfect. Now let's implement the copy feature. So we already did this before so we can copy it from that place.
Handle copy, use callback. If we have the selected file, right to the Navigator clipboard with files, selected file. And now we have to add the set copied state. So let me just add it here above the selected file, copied and set copied. Perfect.
So now we have handle copy. And now let's use the handle handleCopy for this button right here. HandleCopy. And let's pass in copied. If it's copied, we will use the copy check icon.
Otherwise, the copy icon. Like this. And you should no longer have any errors in your code, because we are using everything. So when I click copy, it turns into a different icon now. And you can see that I just copied that entire thing.
Amazing! We just developed a super amazing file explorer. So now I'm going to try to prompt it to create a deeper structure but this is pretty much it for this chapter. All right, so this time I told it build a landing page with each part in its own component, use deeply nested folders. And you can see that I definitely got that.
So instead of the app folder, I have a landing and then I have features and then I have the file and you can see our breadcrumb in action now but for example you can see that I can break it right I if I open this too much it breaks so what you can do is you can remove the maximum segments here to be three And it will be reasonable to change the comment here as well. And this is how it will look like then. Let me just refresh. I think the error was because of the hot reload. And let's click on the fragment here.
So let me select Features. Okay, so you can see it works, but it seems like we have some problem here. Okay, list cannot be a descendant of list. Okay, it's a hydration error. It's not exactly too big of a problem, but I'm not too sure how to fix that at the top of my mind right now.
So I'm going to leave it like this. I think it's not too big of an issue. It's a small hydration error, but you can see how it looks, right? And if you click on something simpler like page, you can see that it will display the entire thing. But for something complicated, it will just show you the first and the last segment.
So you can decide if you want to show that for three segments or for four segments, right? Whatever makes sense for you. Amazing, amazing job. So I think this was a much harder chapter, but I think it was worthwhile. We have an actual file explorer now that we can copy files from and explore everything that was created.
We can scroll. Definitely an impressive result. So now let's go ahead and mark these things as completed. And let's open a new branch. So 13 code view.
Let me collapse this. Open the source control. Opening a new branch here. 13 code view, just to double check that's the chapter's name. Once we are on the new chapter, I'm going to stage all of my changes.
13 code view, I'm going to commit and I'm going to publish this branch. As always, a reminder, there's a free CodeRabbit extension you can use to review your files. And now let's go ahead and let's see our pull request. So I'm going to open this new pull request here, and let's review our summary. And here we have the Code Rabbit summary.
We introduced a code viewer with syntax highlighting in GitHub dark theme. We added a file explorer with three view, breadcrumb navigation, and a copy to clipboard functionality for code files. We enhanced the project view with tabbed navigation, allowing users to switch between a live demo and the code view of project fragments. That is exactly what we did in this chapter. As always, a walkthrough of file by file and of course a sequence diagram.
So in here we have this very complicated component which we built, the file explorer which renders the tree view and then finally the code view. So in here you can see it generated the entire sequence diagram for that component along with the prison.js code highlighting. So very very good. We have a few comments here. This one is a good comment.
It's basically telling us to also add an actual type of check. The reason it's telling us this because it could be anything but then at the same time we know that it's always going to be an object. It's going to be a type of JSON, right? So I think this is a little bit redundant. Adding it would not hurt, but I think it's okay the way it is right now.
I'm not sure about this change I think it works just fine like this. And in here I accidentally added two semicolons in the file explorer props so yes of course we can remove that I'm gonna do that in the next chapter. And there we go. Let's merge this pull request and let's go back here and let's go ahead and go back to main and let's synchronize our changes again. And once you've done that, go inside of Source Control, Graph, and just confirm that you merged the 13 successfully.
Amazing, amazing job. That marks the end of this chapter, and see you