﻿1
00:00:01,380 --> 00:00:03,090
‫Our last use case

2
00:00:03,090 --> 00:00:05,430
‫of the compound component pattern

3
00:00:05,430 --> 00:00:09,240
‫will be to build a reusable context menu,

4
00:00:09,240 --> 00:00:12,450
‫which will make our application really feel

5
00:00:12,450 --> 00:00:14,700
‫like an actual application

6
00:00:14,700 --> 00:00:17,520
‫that you use every day on the web.

7
00:00:17,520 --> 00:00:20,040
‫And this will be a long one,

8
00:00:20,040 --> 00:00:23,103
‫but let's still do it all in one go.

9
00:00:25,020 --> 00:00:28,620
‫So what we want to do here is to give each

10
00:00:28,620 --> 00:00:33,060
‫of these cabin rows a button here that we can click.

11
00:00:33,060 --> 00:00:35,010
‫And then when we click that button,

12
00:00:35,010 --> 00:00:37,500
‫a small context menu appears,

13
00:00:37,500 --> 00:00:42,210
‫which ultimately will contain these three actions here,

14
00:00:42,210 --> 00:00:45,873
‫so duplicating, editing, and deleting.

15
00:00:46,830 --> 00:00:50,460
‫Now what's special about these menus is that only one

16
00:00:50,460 --> 00:00:53,250
‫of them can be open at the same time,

17
00:00:53,250 --> 00:00:56,880
‫which means that we need to wrap the entire table here

18
00:00:56,880 --> 00:01:00,810
‫into that menus component that we are going to build.

19
00:01:00,810 --> 00:01:03,090
‫And then inside each of the rows,

20
00:01:03,090 --> 00:01:05,913
‫we will have a menu child component.

21
00:01:07,170 --> 00:01:08,250
‫All right.

22
00:01:08,250 --> 00:01:12,003
‫And so let's actually write that in our code.

23
00:01:13,110 --> 00:01:17,940
‫So we already have, again, the table component right here

24
00:01:17,940 --> 00:01:21,390
‫or actually not table, but menus.

25
00:01:21,390 --> 00:01:24,060
‫So that's what we're building this time.

26
00:01:24,060 --> 00:01:25,540
‫And so let me immediately

27
00:01:26,610 --> 00:01:30,505
‫create the function component here.

28
00:01:30,505 --> 00:01:34,743
‫And then for now, I will just return the children.

29
00:01:41,310 --> 00:01:44,610
‫All right, and so as I was saying,

30
00:01:44,610 --> 00:01:47,430
‫we actually need to wrap everything here,

31
00:01:47,430 --> 00:01:51,360
‫so all the rows inside those menus

32
00:01:51,360 --> 00:01:53,940
‫so that those menus can then keep track

33
00:01:53,940 --> 00:01:56,490
‫which of the four menus,

34
00:01:56,490 --> 00:01:59,910
‫so four right now because we have four rows.

35
00:01:59,910 --> 00:02:03,510
‫And so again, that menu needs to keep track

36
00:02:03,510 --> 00:02:08,223
‫which of the four menus are actually opened at the time.

37
00:02:09,480 --> 00:02:13,560
‫So let's come to our CabinTable,

38
00:02:13,560 --> 00:02:17,130
‫and as I said, we will then wrap all of this

39
00:02:17,130 --> 00:02:20,433
‫into that menus component.

40
00:02:22,650 --> 00:02:26,760
‫Let's place that here at the end, and nice.

41
00:02:26,760 --> 00:02:29,730
‫So for now, nothing happens here, of course,

42
00:02:29,730 --> 00:02:34,470
‫but now inside the table body inside of each cabin row,

43
00:02:34,470 --> 00:02:37,353
‫we will have a Menus.Menu.

44
00:02:38,850 --> 00:02:41,100
‫So let's come here, and for now,

45
00:02:41,100 --> 00:02:44,223
‫we will place this here after all of this stuff.

46
00:02:45,330 --> 00:02:48,240
‫So after this Modal, we will have,

47
00:02:48,240 --> 00:02:51,210
‫as I just said, one Menus.Menu.

48
00:02:54,540 --> 00:02:59,340
‫And we need to import this menus component here, of course,

49
00:02:59,340 --> 00:03:01,680
‫as I just did initially.

50
00:03:01,680 --> 00:03:04,023
‫So, very important that we have this one here.

51
00:03:05,554 --> 00:03:08,970
‫And so now let's again build out the API

52
00:03:08,970 --> 00:03:11,850
‫of this component that we want to implement.

53
00:03:11,850 --> 00:03:15,870
‫And this one is going to be a very complex one,

54
00:03:15,870 --> 00:03:18,900
‫so this lecture here will be the hardest one

55
00:03:18,900 --> 00:03:20,430
‫of this section.

56
00:03:20,430 --> 00:03:21,900
‫And so if it's too much,

57
00:03:21,900 --> 00:03:25,140
‫then that's absolutely no problem at all.

58
00:03:25,140 --> 00:03:28,500
‫This is really, really advanced stuff already.

59
00:03:28,500 --> 00:03:30,150
‫But the reason for that is

60
00:03:30,150 --> 00:03:33,120
‫that we are already approaching the end of the course,

61
00:03:33,120 --> 00:03:35,460
‫and many students have asked me

62
00:03:35,460 --> 00:03:37,830
‫for advanced content like this.

63
00:03:37,830 --> 00:03:41,160
‫And so I'm basically giving it to you.

64
00:03:41,160 --> 00:03:44,700
‫And also you might be noticing that at this point,

65
00:03:44,700 --> 00:03:48,510
‫it is not so much about React itself anymore,

66
00:03:48,510 --> 00:03:52,440
‫but really more about application development itself.

67
00:03:52,440 --> 00:03:56,100
‫And things are also getting a bit more opinionated,

68
00:03:56,100 --> 00:03:59,430
‫so many of these things are basically my way

69
00:03:59,430 --> 00:04:02,490
‫of doing things and with my opinion in them,

70
00:04:02,490 --> 00:04:05,790
‫but, of course, I tried to make it as general

71
00:04:05,790 --> 00:04:07,920
‫and as broad as possible

72
00:04:07,920 --> 00:04:11,040
‫so that all of you can learn a lot from this

73
00:04:11,040 --> 00:04:14,163
‫and use it in your own applications in the future.

74
00:04:15,150 --> 00:04:18,360
‫All right, but with all that being said,

75
00:04:18,360 --> 00:04:22,830
‫let's now see what we need inside a menu.

76
00:04:22,830 --> 00:04:26,520
‫So, a menu, as you have seen many times

77
00:04:26,520 --> 00:04:30,450
‫on the web already, is always composed of a button.

78
00:04:30,450 --> 00:04:33,810
‫And so then when you click on that toggle button,

79
00:04:33,810 --> 00:04:35,580
‫a list will open,

80
00:04:35,580 --> 00:04:40,173
‫and then that list itself is composed of many buttons.

81
00:04:41,070 --> 00:04:42,903
‫So let's do that.

82
00:04:44,070 --> 00:04:47,640
‫So we will have a Menus.Toggle,

83
00:04:47,640 --> 00:04:52,640
‫which we can use to open and close this menu right here.

84
00:04:52,740 --> 00:04:57,420
‫And then we will have a Menu.List,

85
00:04:57,420 --> 00:05:01,410
‫which will then contain a bunch of buttons.

86
00:05:01,410 --> 00:05:04,710
‫So, Menu.Button.

87
00:05:04,710 --> 00:05:08,520
‫So basically each of them will be one list element

88
00:05:08,520 --> 00:05:10,290
‫of the list.

89
00:05:10,290 --> 00:05:13,473
‫And so here, let's just write something for now.

90
00:05:14,340 --> 00:05:18,810
‫So let's say Duplicate, then Edit,

91
00:05:18,810 --> 00:05:21,540
‫and then Delete.

92
00:05:21,540 --> 00:05:24,150
‫Now, just like before with the modal,

93
00:05:24,150 --> 00:05:27,750
‫we will have many of these menus on the page

94
00:05:27,750 --> 00:05:30,930
‫and therefore many toggles and many lists.

95
00:05:30,930 --> 00:05:33,960
‫And so therefore, we will have to connect this toggle

96
00:05:33,960 --> 00:05:35,820
‫with this list again

97
00:05:35,820 --> 00:05:38,430
‫so that we know that this exact toggle

98
00:05:38,430 --> 00:05:40,953
‫should then open up this list.

99
00:05:42,810 --> 00:05:46,590
‫So previously we used the name and the opens prop,

100
00:05:46,590 --> 00:05:49,380
‫but here let's make it a bit more simple

101
00:05:49,380 --> 00:05:51,210
‫and simply use an ID.

102
00:05:51,210 --> 00:05:54,663
‫So for this, we will just use the current cabinId,

103
00:05:55,590 --> 00:05:58,743
‫so both on the toggle and on the list.

104
00:05:59,700 --> 00:06:01,920
‫So, cabinId.

105
00:06:01,920 --> 00:06:05,730
‫And then the parent menus component will keep track

106
00:06:05,730 --> 00:06:09,573
‫which of the menu ID is currently being displayed.

107
00:06:10,740 --> 00:06:12,000
‫All right.

108
00:06:12,000 --> 00:06:15,060
‫And for now, I think that's it.

109
00:06:15,060 --> 00:06:17,490
‫So later we will pass in some more props,

110
00:06:17,490 --> 00:06:20,640
‫but for now, we can work with this.

111
00:06:20,640 --> 00:06:24,420
‫So we have a menu, a toggle, a list, and a button.

112
00:06:24,420 --> 00:06:29,420
‫And so let's come to our menus here and implement those.

113
00:06:36,540 --> 00:06:39,120
‫So the menu we actually don't really need

114
00:06:39,120 --> 00:06:42,453
‫because all that is is some styling,

115
00:06:43,620 --> 00:06:46,560
‫so this one right here.

116
00:06:46,560 --> 00:06:50,043
‫So actually let's change this just to Menu.

117
00:06:52,320 --> 00:06:53,283
‫All right.

118
00:06:56,880 --> 00:07:00,450
‫And so here let's then implement the toggle,

119
00:07:00,450 --> 00:07:02,313
‫which remember has an ID.

120
00:07:04,200 --> 00:07:08,310
‫Then we have the list itself,

121
00:07:08,310 --> 00:07:10,353
‫which also needs an ID.

122
00:07:12,060 --> 00:07:15,213
‫And finally we have the button.

123
00:07:16,920 --> 00:07:19,440
‫So for now, no props, but yeah,

124
00:07:19,440 --> 00:07:22,410
‫we are going to need the children for sure.

125
00:07:22,410 --> 00:07:27,410
‫And so now in the end, let's do Menus.Menu is = Menu,

126
00:07:28,560 --> 00:07:30,900
‫which, as I mentioned earlier,

127
00:07:30,900 --> 00:07:33,300
‫is simply that styled component.

128
00:07:33,300 --> 00:07:35,283
‫Then we have the toggle.

129
00:07:38,280 --> 00:07:42,460
‫Then we have the list

130
00:07:45,960 --> 00:07:48,663
‫and finally also the button.

131
00:07:52,230 --> 00:07:53,163
‫All right.

132
00:07:54,060 --> 00:07:56,190
‫And then next up, as always,

133
00:07:56,190 --> 00:07:58,570
‫let's create our MenusContext.

134
00:08:04,371 --> 00:08:08,100
‫And then here, as we already mentioned earlier,

135
00:08:08,100 --> 00:08:09,570
‫we will need to keep track

136
00:08:09,570 --> 00:08:13,383
‫which one is the currently open ID.

137
00:08:14,760 --> 00:08:18,183
‫So, of course, we use some state for that.

138
00:08:23,990 --> 00:08:26,670
‫And then here, let's, as always,

139
00:08:26,670 --> 00:08:31,563
‫return MenusContext.Provider.

140
00:08:33,810 --> 00:08:36,760
‫And then in here, we provide the openId

141
00:08:38,070 --> 00:08:41,103
‫and later also some setter functions.

142
00:08:42,870 --> 00:08:44,130
‫And let's actually immediately

143
00:08:44,130 --> 00:08:46,413
‫create those setter functions.

144
00:08:47,550 --> 00:08:51,780
‫So here by default, we start off with an empty string.

145
00:08:51,780 --> 00:08:53,160
‫And so that basically means

146
00:08:53,160 --> 00:08:56,520
‫that none of the menus is currently open.

147
00:08:56,520 --> 00:09:00,520
‫And so basically that means that the close function is

148
00:09:01,650 --> 00:09:05,680
‫to set the OpenId

149
00:09:06,870 --> 00:09:08,403
‫to that empty string.

150
00:09:09,840 --> 00:09:11,490
‫On the other hand,

151
00:09:11,490 --> 00:09:16,490
‫the open function is simply exactly the same as setOpenId,

152
00:09:18,600 --> 00:09:23,160
‫so just like we did earlier also in the modal component.

153
00:09:23,160 --> 00:09:28,160
‫So let's pass these down in here as well.

154
00:09:28,320 --> 00:09:32,610
‫And then let's build out our other three components.

155
00:09:32,610 --> 00:09:35,940
‫And let's begin with the easiest one here.

156
00:09:35,940 --> 00:09:40,000
‫So for now, here we will simply return a list item

157
00:09:40,950 --> 00:09:44,490
‫because this will be inside the list, remember?

158
00:09:44,490 --> 00:09:47,400
‫And so this will be an unordered list.

159
00:09:47,400 --> 00:09:51,540
‫So here to be semantically correct, we need a list item,

160
00:09:51,540 --> 00:09:54,483
‫and then in there, we will have a styled button.

161
00:09:58,110 --> 00:10:00,450
‫And so for now, all we're gonna do

162
00:10:00,450 --> 00:10:02,613
‫is to pass in the children.

163
00:10:03,810 --> 00:10:05,370
‫So this is the easy one.

164
00:10:05,370 --> 00:10:08,493
‫Let's now tackle the two complicated ones.

165
00:10:09,540 --> 00:10:14,497
‫So here we want to return the StyledToggle,

166
00:10:15,570 --> 00:10:19,890
‫and please make sure to always check out these styles here

167
00:10:19,890 --> 00:10:21,630
‫'cause otherwise this is all going

168
00:10:21,630 --> 00:10:24,720
‫to feel even more like black magic.

169
00:10:24,720 --> 00:10:26,700
‫And the same, of course, is true

170
00:10:26,700 --> 00:10:30,660
‫for the other components that we built previously.

171
00:10:30,660 --> 00:10:33,600
‫So we cannot build all the styles here in the videos

172
00:10:33,600 --> 00:10:37,620
‫because then this project will be like 50 hours long,

173
00:10:37,620 --> 00:10:39,063
‫and that we can't have.

174
00:10:40,050 --> 00:10:44,533
‫But anyway, let's here create a function called handleClick,

175
00:10:45,870 --> 00:10:47,223
‫which we will call,

176
00:10:48,090 --> 00:10:52,467
‫and actually let's only specify it here like this for now.

177
00:10:52,467 --> 00:10:55,530
‫And then here we will want an icon.

178
00:10:55,530 --> 00:10:59,793
‫So this one is called Hi, then EllipsisVertical.

179
00:11:01,290 --> 00:11:03,240
‫So it's like these three dots

180
00:11:03,240 --> 00:11:05,103
‫that I'm sure you have seen before.

181
00:11:06,660 --> 00:11:11,133
‫Here then let's create that handleClick function.

182
00:11:13,230 --> 00:11:15,540
‫And so here is where we will then decide

183
00:11:15,540 --> 00:11:19,620
‫whether we want to open or to close the menu,

184
00:11:19,620 --> 00:11:20,823
‫or actually the list.

185
00:11:22,020 --> 00:11:27,020
‫So let's grab those two or actually all the values.

186
00:11:27,330 --> 00:11:29,410
‫So we need both the ID

187
00:11:30,983 --> 00:11:33,690
‫and the close and the open functions

188
00:11:33,690 --> 00:11:36,150
‫in order to do this decision.

189
00:11:36,150 --> 00:11:40,590
‫And so we get them from useContext

190
00:11:40,590 --> 00:11:42,283
‫on the MenuContext.

191
00:11:46,183 --> 00:11:50,043
‫All right, and so here, let's now do the check.

192
00:11:51,150 --> 00:11:55,170
‫So if the openId is empty,

193
00:11:55,170 --> 00:11:57,033
‫meaning that there is no ID,

194
00:11:58,290 --> 00:12:01,067
‫or if the openId,

195
00:12:02,670 --> 00:12:07,530
‫so basically if the currently open menu is different

196
00:12:07,530 --> 00:12:12,270
‫from the ID of this exact button that is being clicked,

197
00:12:12,270 --> 00:12:16,350
‫then let's open the menu.

198
00:12:16,350 --> 00:12:21,330
‫And we do this by passing in the ID of exactly this button

199
00:12:21,330 --> 00:12:26,280
‫because this button is connected to that menu by this ID.

200
00:12:26,280 --> 00:12:29,973
‫And otherwise we just close the menu.

201
00:12:31,260 --> 00:12:36,260
‫So again, if right now none of the menus is open,

202
00:12:36,390 --> 00:12:40,830
‫which is what we have right here, so then open this one,

203
00:12:40,830 --> 00:12:43,593
‫so the one with the ID that has been clicked.

204
00:12:44,700 --> 00:12:49,700
‫Or also if there is currently an open menu already,

205
00:12:50,040 --> 00:12:52,560
‫but it's different than the one that's being clicked,

206
00:12:52,560 --> 00:12:55,740
‫then we also want to open this one,

207
00:12:55,740 --> 00:12:57,420
‫so the one that has been clicked.

208
00:12:57,420 --> 00:13:00,720
‫But in all other cases, then we just want to close it.

209
00:13:00,720 --> 00:13:04,800
‫So that other case is basically whenever the openId

210
00:13:04,800 --> 00:13:06,750
‫is equal to this id,

211
00:13:06,750 --> 00:13:10,320
‫or in other words, whenever the menu is already open.

212
00:13:10,320 --> 00:13:13,470
‫So if we then click again, we close that,

213
00:13:13,470 --> 00:13:15,240
‫and this will all make sense

214
00:13:15,240 --> 00:13:17,940
‫once we see this here actually working.

215
00:13:17,940 --> 00:13:22,443
‫But for that, we need to also finish this list component.

216
00:13:23,400 --> 00:13:24,690
‫So I believe that this one

217
00:13:24,690 --> 00:13:27,600
‫for now will just work bare bones,

218
00:13:27,600 --> 00:13:30,123
‫and so let's move on to the last one.

219
00:13:31,920 --> 00:13:35,973
‫So here from the context, we will need the openId,

220
00:13:39,510 --> 00:13:43,260
‫so MenuContext, because now we need to compare

221
00:13:43,260 --> 00:13:48,260
‫that openId with the ID of this list,

222
00:13:48,540 --> 00:13:52,020
‫so basically just like before with the modal window

223
00:13:52,020 --> 00:13:54,480
‫where we compared the window name

224
00:13:54,480 --> 00:13:57,360
‫with the currently opened name.

225
00:13:57,360 --> 00:14:00,690
‫And so here we now have to do exactly the same thing.

226
00:14:00,690 --> 00:14:05,690
‫So basically if the currently openId is different

227
00:14:06,450 --> 00:14:10,500
‫from this list ID, then return nothing.

228
00:14:10,500 --> 00:14:14,550
‫But if the ID of the list matches the one

229
00:14:14,550 --> 00:14:17,970
‫that is currently open, then we want to render something.

230
00:14:17,970 --> 00:14:21,603
‫So then we do render this list of buttons.

231
00:14:22,470 --> 00:14:25,983
‫And so here, let's actually again return a portal.

232
00:14:26,880 --> 00:14:31,880
‫So create portal because this element here will also float

233
00:14:31,890 --> 00:14:33,453
‫on top of the UI.

234
00:14:34,290 --> 00:14:36,000
‫And so in cases like that,

235
00:14:36,000 --> 00:14:39,450
‫it's always a good idea to use a portal.

236
00:14:39,450 --> 00:14:41,670
‫So here we will have our JSX,

237
00:14:41,670 --> 00:14:46,140
‫which is the StyledList for now,

238
00:14:46,140 --> 00:14:49,740
‫and then in here, we will pass the children,

239
00:14:49,740 --> 00:14:52,200
‫which are going to be all of these buttons,

240
00:14:52,200 --> 00:14:55,200
‫if you remember, from here.

241
00:14:55,200 --> 00:14:58,470
‫So we have the list, and that receives these buttons.

242
00:14:58,470 --> 00:15:01,443
‫So those are their children.

243
00:15:05,340 --> 00:15:07,200
‫Just like this.

244
00:15:07,200 --> 00:15:09,660
‫And then the second argument of the portal,

245
00:15:09,660 --> 00:15:13,473
‫let's again do document.body.

246
00:15:14,910 --> 00:15:18,990
‫Okay, but now let's actually go check out this StyledList

247
00:15:18,990 --> 00:15:22,023
‫because there is something very particular about it.

248
00:15:22,950 --> 00:15:27,950
‫So this StyledList here is with the position of fixed,

249
00:15:28,080 --> 00:15:30,750
‫so just like the modal window before.

250
00:15:30,750 --> 00:15:33,990
‫And what is special here is the fact that the right

251
00:15:33,990 --> 00:15:38,880
‫and the top CSS properties come from the position prop.

252
00:15:38,880 --> 00:15:41,400
‫So basically here we need to pass in the X

253
00:15:41,400 --> 00:15:44,340
‫and the Y coordinates of this menu

254
00:15:44,340 --> 00:15:47,880
‫'cause we will want it to be displayed exactly

255
00:15:47,880 --> 00:15:50,463
‫below the button that will appear there.

256
00:15:52,200 --> 00:15:55,770
‫So we will have to later calculate that position.

257
00:15:55,770 --> 00:15:59,460
‫But for now, while we are still experimenting around

258
00:15:59,460 --> 00:16:02,643
‫with this, let's just do some fictional position.

259
00:16:04,110 --> 00:16:07,533
‫So here, this expects an object with X.

260
00:16:08,400 --> 00:16:10,470
‫Let's set it to 20

261
00:16:10,470 --> 00:16:13,323
‫and Y also to 20.

262
00:16:15,570 --> 00:16:16,503
‫All right.

263
00:16:18,090 --> 00:16:21,420
‫Now here, I'm not sure why we're getting this error,

264
00:16:21,420 --> 00:16:22,530
‫but...

265
00:16:22,530 --> 00:16:25,293
‫Ah, well, it is actually Menus,

266
00:16:28,470 --> 00:16:29,703
‫not just Menu.

267
00:16:31,020 --> 00:16:33,900
‫And we have an error, but that's no problem.

268
00:16:33,900 --> 00:16:36,270
‫I'm sure we can fix it.

269
00:16:36,270 --> 00:16:39,960
‫So that's a lot of errors, 77.

270
00:16:39,960 --> 00:16:41,560
‫Let's go all the way to the top.

271
00:16:46,530 --> 00:16:50,283
‫So here it says we maybe forgot to export some component.

272
00:16:51,270 --> 00:16:53,253
‫Let's see what we have next.

273
00:16:55,890 --> 00:17:00,000
‫And okay, let's see if that's the case.

274
00:17:00,000 --> 00:17:02,673
‫Ah, here it's Menus.

275
00:17:03,720 --> 00:17:08,720
‫So maybe that's the only problem, but I don't believe that.

276
00:17:09,510 --> 00:17:13,290
‫Or, well, actually it looks like it.

277
00:17:13,290 --> 00:17:16,440
‫So here we have a nice-looking button,

278
00:17:16,440 --> 00:17:18,933
‫and so let's check what happens when we click it.

279
00:17:20,400 --> 00:17:23,553
‫Well, beautiful, there is our list.

280
00:17:24,720 --> 00:17:28,080
‫Let's click it again, and then it disappears.

281
00:17:28,080 --> 00:17:31,470
‫Great, so something is already working here.

282
00:17:31,470 --> 00:17:34,140
‫Let's click here, and it shows up again.

283
00:17:34,140 --> 00:17:36,150
‫Click here, and it closes.

284
00:17:36,150 --> 00:17:39,960
‫And also if we click this one and then another one,

285
00:17:39,960 --> 00:17:41,610
‫well, now we can't really see

286
00:17:41,610 --> 00:17:43,503
‫because it appears in the same place,

287
00:17:44,640 --> 00:17:48,273
‫but trust me that it did close and then open another one.

288
00:17:49,560 --> 00:17:52,470
‫Great, so we have some bare-bones functionality

289
00:17:52,470 --> 00:17:54,000
‫here already working.

290
00:17:54,000 --> 00:17:57,720
‫And so next up, let's make this a little bit nicer,

291
00:17:57,720 --> 00:18:00,340
‫so add a few more features there

292
00:18:01,440 --> 00:18:06,333
‫and starting with the actual positioning of the list.

293
00:18:07,170 --> 00:18:10,500
‫Now this position of the list needs to be calculated

294
00:18:10,500 --> 00:18:13,443
‫as soon as this button here is clicked.

295
00:18:14,550 --> 00:18:17,883
‫And so let's do that right here in handleClick.

296
00:18:18,900 --> 00:18:22,410
‫So first off, here let's receive the event

297
00:18:22,410 --> 00:18:25,590
‫that has been fired off, so that click event.

298
00:18:25,590 --> 00:18:30,590
‫And so then on that, we can do e.target,

299
00:18:30,780 --> 00:18:33,423
‫and then we want to get the closest button,

300
00:18:34,470 --> 00:18:39,470
‫so just to make sure that we really get the position

301
00:18:39,990 --> 00:18:44,073
‫of the button and not of the SVG icon here.

302
00:18:45,060 --> 00:18:48,510
‫So this then basically does some DOM traversing,

303
00:18:48,510 --> 00:18:51,180
‫finding the closest button parent.

304
00:18:51,180 --> 00:18:54,090
‫And then here we can then call another DOM function,

305
00:18:54,090 --> 00:18:59,090
‫which is getBoundingClientRect.

306
00:19:01,440 --> 00:19:02,640
‫It's a weird name,

307
00:19:02,640 --> 00:19:06,960
‫but basically what this will do is to give us some data

308
00:19:06,960 --> 00:19:08,793
‫about the element's position.

309
00:19:09,690 --> 00:19:12,330
‫Let's call it rect for rectangle,

310
00:19:12,330 --> 00:19:15,723
‫and then let's start by just logging this to the console.

311
00:19:19,830 --> 00:19:24,830
‫So each time we click here, then we get an error.

312
00:19:25,710 --> 00:19:28,623
‫So it's getBounding.

313
00:19:29,700 --> 00:19:32,940
‫Let's try that again, and nice.

314
00:19:32,940 --> 00:19:36,540
‫So here we get now the X and Y positions.

315
00:19:36,540 --> 00:19:37,800
‫And so based on that,

316
00:19:37,800 --> 00:19:41,223
‫we can now determine where we want to render the list.

317
00:19:43,080 --> 00:19:45,270
‫So let's get that data,

318
00:19:45,270 --> 00:19:47,700
‫but where should we actually store it?

319
00:19:47,700 --> 00:19:51,330
‫Because we will determine the data here in this component,

320
00:19:51,330 --> 00:19:54,240
‫but we do actually need it here.

321
00:19:54,240 --> 00:19:58,050
‫So in order to pass it from one place to another,

322
00:19:58,050 --> 00:20:01,323
‫we will store it in the parents state.

323
00:20:02,970 --> 00:20:06,990
‫So let's create position

324
00:20:06,990 --> 00:20:09,063
‫and setPosition,

325
00:20:11,176 --> 00:20:13,710
‫useState again,

326
00:20:13,710 --> 00:20:15,930
‫and let's start with null.

327
00:20:15,930 --> 00:20:19,443
‫And then we also pass these two into our context,

328
00:20:20,370 --> 00:20:22,953
‫so position and setPosition.

329
00:20:26,767 --> 00:20:29,020
‫Then here we grab that setPosition,

330
00:20:31,350 --> 00:20:32,733
‫and then here,

331
00:20:35,310 --> 00:20:36,360
‫let's do setPosition.

332
00:20:37,740 --> 00:20:42,740
‫And as before, we are expecting an object with X and Y.

333
00:20:44,460 --> 00:20:47,673
‫Now here I already figured out how to calculate this,

334
00:20:48,660 --> 00:20:52,533
‫so it's going to be the window's width, basically,

335
00:20:53,670 --> 00:20:58,060
‫minus the width of the rectangle itself

336
00:20:59,640 --> 00:21:04,640
‫and minus the X coordinate of the rectangle.

337
00:21:05,820 --> 00:21:08,610
‫So I cannot really explain why that is,

338
00:21:08,610 --> 00:21:10,560
‫but if you think about this,

339
00:21:10,560 --> 00:21:13,650
‫then you will actually figure out the exact same thing.

340
00:21:13,650 --> 00:21:15,150
‫And now for the Y position,

341
00:21:15,150 --> 00:21:20,150
‫all we need to do is to take the rectangle's Y position.

342
00:21:22,740 --> 00:21:25,650
‫So basically that's up here.

343
00:21:25,650 --> 00:21:28,110
‫Then we will add the height of the button,

344
00:21:28,110 --> 00:21:29,850
‫which will leave us up here.

345
00:21:29,850 --> 00:21:33,840
‫And then we just add some pixels for margin.

346
00:21:33,840 --> 00:21:35,973
‫So, rect.height,

347
00:21:38,760 --> 00:21:41,283
‫and then plus eight pixels.

348
00:21:43,110 --> 00:21:44,103
‫All right.

349
00:21:45,210 --> 00:21:49,083
‫And again, please try to understand that positioning there.

350
00:21:50,580 --> 00:21:53,370
‫But anyway, here we now grab that position

351
00:21:53,370 --> 00:21:56,013
‫and pass that in here.

352
00:21:57,150 --> 00:22:00,210
‫And so now let's see.

353
00:22:00,210 --> 00:22:01,623
‫Yeah, great.

354
00:22:03,330 --> 00:22:08,330
‫So, the same now here and here and here.

355
00:22:08,460 --> 00:22:09,690
‫Beautiful.

356
00:22:09,690 --> 00:22:11,940
‫There's just one problem with this,

357
00:22:11,940 --> 00:22:14,160
‫which we are actually not going to fix

358
00:22:14,160 --> 00:22:15,990
‫because it takes too much time,

359
00:22:15,990 --> 00:22:18,150
‫which is if we scroll now,

360
00:22:18,150 --> 00:22:23,150
‫then the menu will stay at the same position on our screen

361
00:22:23,220 --> 00:22:25,740
‫because it has the fixed position.

362
00:22:25,740 --> 00:22:27,930
‫So we could, of course, fix this,

363
00:22:27,930 --> 00:22:30,720
‫but that's just a bit too hard.

364
00:22:30,720 --> 00:22:33,120
‫So I'll just leave it like this,

365
00:22:33,120 --> 00:22:34,713
‫click here to close it.

366
00:22:35,670 --> 00:22:37,830
‫And so this is really good enough

367
00:22:37,830 --> 00:22:39,780
‫for what we are building here

368
00:22:39,780 --> 00:22:42,303
‫or what we are actually just learning here.

369
00:22:43,680 --> 00:22:48,510
‫Okay, next up, let's make these buttons here a bit nicer.

370
00:22:48,510 --> 00:22:52,953
‫And for that, we will want to pass in an icon.

371
00:22:53,820 --> 00:22:55,830
‫So we want to allow an icon,

372
00:22:55,830 --> 00:23:00,830
‫and so let's use the same ones that we used here earlier,

373
00:23:01,050 --> 00:23:03,963
‫so this one for duplicating.

374
00:23:06,870 --> 00:23:10,143
‫And then let's do the same thing in the other ones.

375
00:23:14,820 --> 00:23:16,323
‫So here it's HiPencil,

376
00:23:19,620 --> 00:23:22,840
‫and here it is HiTrash.

377
00:23:28,467 --> 00:23:31,323
‫Now of these three buttons right there,

378
00:23:32,280 --> 00:23:36,063
‫only one of them has an onClick handler, I believe.

379
00:23:37,200 --> 00:23:39,540
‫Yeah, just this one right here.

380
00:23:39,540 --> 00:23:43,020
‫And so actually we want our buttons right there

381
00:23:43,020 --> 00:23:47,010
‫to also be able to receive this onClick.

382
00:23:47,010 --> 00:23:50,220
‫So it's not mandatory, but they can receive it.

383
00:23:50,220 --> 00:23:52,950
‫And so let's grab this here as well

384
00:23:52,950 --> 00:23:57,950
‫and then place it right here.

385
00:23:58,140 --> 00:24:00,600
‫So now it's getting a bit hard to find.

386
00:24:00,600 --> 00:24:02,853
‫Let's add some spacing here maybe.

387
00:24:03,690 --> 00:24:05,100
‫So that's better.

388
00:24:05,100 --> 00:24:09,513
‫So let's now handle that icon and onClick prop on here.

389
00:24:11,070 --> 00:24:14,140
‫So, icon and onClick.

390
00:24:17,340 --> 00:24:22,340
‫So first off, let's place that icon here

391
00:24:22,410 --> 00:24:27,033
‫and then placing this children here into a span.

392
00:24:31,590 --> 00:24:36,590
‫All right, then here, let's use onClick

393
00:24:37,080 --> 00:24:39,493
‫and then a function called handleClick.

394
00:24:42,570 --> 00:24:44,560
‫So let's define that here again

395
00:24:46,800 --> 00:24:49,683
‫because we actually need to do multiple things.

396
00:24:50,910 --> 00:24:55,470
‫So, first of all, we want to conditionally call onClick,

397
00:24:55,470 --> 00:24:58,650
‫and for that, again we use optional chaining.

398
00:24:58,650 --> 00:25:03,243
‫And then afterwards, we also want to close our menu.

399
00:25:04,800 --> 00:25:07,080
‫So let's call close,

400
00:25:07,080 --> 00:25:10,483
‫and then, of course, we need to get it from the context,

401
00:25:13,661 --> 00:25:18,661
‫useContext like this with the menus context.

402
00:25:20,070 --> 00:25:22,320
‫And there we go.

403
00:25:22,320 --> 00:25:23,820
‫Let's see.

404
00:25:23,820 --> 00:25:25,560
‫And beautiful.

405
00:25:25,560 --> 00:25:28,770
‫So this is starting to really look like something,

406
00:25:28,770 --> 00:25:32,310
‫and actually this button should already be working.

407
00:25:32,310 --> 00:25:33,453
‫So let's click that,

408
00:25:34,620 --> 00:25:39,273
‫and indeed, our copy of 001 has been created.

409
00:25:40,110 --> 00:25:40,943
‫Great.

410
00:25:42,000 --> 00:25:44,400
‫Now these two here don't work yet,

411
00:25:44,400 --> 00:25:47,970
‫but if we click them, then the menu gets closed already.

412
00:25:47,970 --> 00:25:50,583
‫So that part of closing already works.

413
00:25:51,840 --> 00:25:53,640
‫Now what we also want to do

414
00:25:53,640 --> 00:25:56,190
‫is that when we click outside here,

415
00:25:56,190 --> 00:26:00,570
‫just like with the modal, we want the menu to close.

416
00:26:00,570 --> 00:26:03,630
‫So right now, of course, that doesn't happen,

417
00:26:03,630 --> 00:26:04,890
‫but luckily for us,

418
00:26:04,890 --> 00:26:08,283
‫we already have that useOutsideClick hook.

419
00:26:09,900 --> 00:26:11,460
‫So we can use that here

420
00:26:11,460 --> 00:26:16,460
‫because this is where we want to register that click.

421
00:26:16,620 --> 00:26:19,560
‫So if we click outside of this list,

422
00:26:19,560 --> 00:26:21,063
‫then we want it to close.

423
00:26:22,680 --> 00:26:26,133
‫So this is going to return a ref,

424
00:26:27,360 --> 00:26:30,930
‫so, useOutsideClick.

425
00:26:30,930 --> 00:26:32,010
‫And then the handler here

426
00:26:32,010 --> 00:26:35,673
‫in this case will again be our close function.

427
00:26:36,960 --> 00:26:38,790
‫So let's grab that.

428
00:26:38,790 --> 00:26:40,230
‫And then we just need

429
00:26:40,230 --> 00:26:44,703
‫to attach this ref here to this element.

430
00:26:47,940 --> 00:26:49,533
‫So let's try that.

431
00:26:51,930 --> 00:26:55,050
‫And it seems to be working.

432
00:26:55,050 --> 00:26:56,400
‫So we click outside.

433
00:26:56,400 --> 00:26:58,200
‫It disappears.

434
00:26:58,200 --> 00:27:01,413
‫And as we click here, then that also disappears.

435
00:27:04,170 --> 00:27:08,100
‫Let's just try to see what happens if maybe we pass

436
00:27:08,100 --> 00:27:11,100
‫in false here for that second argument,

437
00:27:11,100 --> 00:27:12,993
‫so that listenCapturing.

438
00:27:15,060 --> 00:27:18,150
‫And so, well, now that doesn't work at all.

439
00:27:18,150 --> 00:27:23,103
‫And so we again need this here to be true basically.

440
00:27:24,510 --> 00:27:28,260
‫All right, and so now this works really, really great,

441
00:27:28,260 --> 00:27:30,120
‫so I'm really happy with the result

442
00:27:30,120 --> 00:27:32,430
‫and with the way this looks like.

443
00:27:32,430 --> 00:27:34,290
‫Now all we need to do

444
00:27:34,290 --> 00:27:39,090
‫is to actually place these actions here in there,

445
00:27:39,090 --> 00:27:42,450
‫so making the edit and the delete work

446
00:27:42,450 --> 00:27:45,813
‫'cause the menu itself is, I think, finished.

447
00:27:47,100 --> 00:27:51,240
‫So, it's a big one, and it was a lot of work, as I said,

448
00:27:51,240 --> 00:27:55,143
‫but the result is really satisfying, I think.

449
00:27:56,310 --> 00:28:00,360
‫But anyway, now we will need to change this a lot.

450
00:28:00,360 --> 00:28:03,360
‫So if you want to keep the old version,

451
00:28:03,360 --> 00:28:06,240
‫I will just duplicate this here,

452
00:28:06,240 --> 00:28:08,790
‫again, calling it version one.

453
00:28:08,790 --> 00:28:11,380
‫And in this one, we can even completely get rid

454
00:28:12,240 --> 00:28:13,383
‫of what we did here.

455
00:28:14,400 --> 00:28:17,073
‫So we should have taken that copy earlier,

456
00:28:19,980 --> 00:28:22,203
‫but we can just do it now as well.

457
00:28:23,250 --> 00:28:24,570
‫Now, okay.

458
00:28:24,570 --> 00:28:26,370
‫And so now comes the time

459
00:28:26,370 --> 00:28:29,613
‫where things will get really, really confusing.

460
00:28:30,990 --> 00:28:35,990
‫So the first button here, we actually no longer need,

461
00:28:36,930 --> 00:28:39,150
‫so that one is already working.

462
00:28:39,150 --> 00:28:41,340
‫But now as for these other two,

463
00:28:41,340 --> 00:28:43,563
‫this is where it gets complicated.

464
00:28:44,880 --> 00:28:49,020
‫So we already have some buttons right here,

465
00:28:49,020 --> 00:28:51,930
‫but these buttons are not that pretty.

466
00:28:51,930 --> 00:28:53,760
‫So they are just these buttons.

467
00:28:53,760 --> 00:28:56,400
‫And so we'll actually want these buttons

468
00:28:56,400 --> 00:28:59,250
‫to be these ones right here.

469
00:28:59,250 --> 00:29:04,250
‫So these menu buttons should be inside this Modal.Open.

470
00:29:06,390 --> 00:29:09,843
‫So here we will now basically mix the two together.

471
00:29:11,160 --> 00:29:16,160
‫So again, that will be quite confusing, but let's do it.

472
00:29:17,190 --> 00:29:22,057
‫So we should actually grab all of this stuff here

473
00:29:23,880 --> 00:29:28,880
‫or maybe even everything, so even where we open the menu.

474
00:29:29,700 --> 00:29:32,860
‫So let's grab that and place it

475
00:29:35,400 --> 00:29:38,190
‫still again inside the modal.

476
00:29:38,190 --> 00:29:40,323
‫So the modal should be outside.

477
00:29:42,480 --> 00:29:43,860
‫Yeah, so right now it's not.

478
00:29:43,860 --> 00:29:47,703
‫That's why we get that error, but there we go.

479
00:29:49,740 --> 00:29:54,330
‫All right, and so now we can do what we just said earlier.

480
00:29:54,330 --> 00:29:58,170
‫So we can grab these buttons right here

481
00:29:58,170 --> 00:30:02,880
‫and place them into Modal.Open.

482
00:30:02,880 --> 00:30:06,540
‫So this one we actually don't need, but this one we need.

483
00:30:06,540 --> 00:30:08,250
‫So this one is for edit,

484
00:30:08,250 --> 00:30:11,493
‫so let's grab this and place it right here,

485
00:30:13,830 --> 00:30:15,180
‫so just like this.

486
00:30:15,180 --> 00:30:18,120
‫And then we take the entire thing

487
00:30:18,120 --> 00:30:21,153
‫and put it back into our menus list.

488
00:30:23,220 --> 00:30:26,943
‫All right, and then we do the same thing with the other one.

489
00:30:28,980 --> 00:30:32,223
‫So let's grab this Modal.Open,

490
00:30:33,060 --> 00:30:34,650
‫place that here,

491
00:30:34,650 --> 00:30:37,860
‫and then we replace that button in there

492
00:30:37,860 --> 00:30:40,143
‫with the button of our menu,

493
00:30:41,910 --> 00:30:43,170
‫just like this.

494
00:30:43,170 --> 00:30:46,080
‫And so now these two windows here are a bit separated,

495
00:30:46,080 --> 00:30:47,790
‫but that's no problem at all.

496
00:30:47,790 --> 00:30:51,393
‫It's going to work just exactly the same way as before.

497
00:30:53,550 --> 00:30:55,980
‫So, let's just recap.

498
00:30:55,980 --> 00:30:59,940
‫So we have, of course, our Menus.Menu,

499
00:30:59,940 --> 00:31:02,070
‫which is now inside the modal.

500
00:31:02,070 --> 00:31:03,390
‫Then we have to toggle.

501
00:31:03,390 --> 00:31:04,593
‫Then we have the list.

502
00:31:06,570 --> 00:31:10,020
‫And then for two of them, so for two of the buttons,

503
00:31:10,020 --> 00:31:12,930
‫we have them inside Modal.Open

504
00:31:12,930 --> 00:31:15,660
‫because these two should actually trigger

505
00:31:15,660 --> 00:31:17,613
‫our modal windows to open.

506
00:31:19,350 --> 00:31:21,660
‫All right, that's no problem at all.

507
00:31:21,660 --> 00:31:25,260
‫And then we have these two windows here outside

508
00:31:25,260 --> 00:31:27,180
‫of the menu list,

509
00:31:27,180 --> 00:31:31,200
‫and I believe that this is actually all.

510
00:31:31,200 --> 00:31:33,453
‫This should work perfectly fine.

511
00:31:34,470 --> 00:31:36,120
‫So let's try to edit,

512
00:31:36,120 --> 00:31:38,133
‫and beautiful.

513
00:31:39,270 --> 00:31:41,130
‫So this is so great.

514
00:31:41,130 --> 00:31:42,630
‫Like, it makes me really happy

515
00:31:42,630 --> 00:31:46,260
‫to see this working so nicely,

516
00:31:46,260 --> 00:31:48,063
‫the same thing for deleting.

517
00:31:49,722 --> 00:31:50,910
‫Let's close this one.

518
00:31:50,910 --> 00:31:55,910
‫If I try to edit this one, then we will get the 008 here.

519
00:31:55,980 --> 00:31:59,910
‫Yeah, so everything again working perfectly fine.

520
00:31:59,910 --> 00:32:01,710
‫We can click outside here.

521
00:32:01,710 --> 00:32:05,220
‫We can open a menu, also click outside.

522
00:32:05,220 --> 00:32:08,130
‫And so this is really just a great experience

523
00:32:08,130 --> 00:32:11,400
‫and a great design as well.

524
00:32:11,400 --> 00:32:14,670
‫So, congratulations for reaching the end

525
00:32:14,670 --> 00:32:17,940
‫of this pretty advanced section right here.

526
00:32:17,940 --> 00:32:20,130
‫So this was really fun for me,

527
00:32:20,130 --> 00:32:22,470
‫and I hope that you feel the same.

528
00:32:22,470 --> 00:32:25,170
‫So study all that we did here,

529
00:32:25,170 --> 00:32:27,210
‫and then we can move on together

530
00:32:27,210 --> 00:32:30,180
‫and build out the rest of the application

531
00:32:30,180 --> 00:32:32,133
‫right in the next section.

