@rpg-engine/long-bow 0.7.22 → 0.7.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,230 +1,128 @@
1
- import {
2
- ICharacter,
3
- IChatMessage,
4
- IPrivateChatMessage,
5
- ITradeChatMessage,
6
- } from '@rpg-engine/shared';
7
- import React, { useEffect, useState } from 'react';
8
- import { IoMdContract, IoMdExpand } from 'react-icons/io';
9
- import { RxCross2, RxMagnifyingGlass } from 'react-icons/rx';
10
- import styled, { css } from 'styled-components';
11
- import { uiColors } from '../../constants/uiColors';
12
- import { uiFonts } from '../../constants/uiFonts';
13
- import { Chat, IStyles } from '../Chat/Chat';
14
- import { Ellipsis } from '../shared/Ellipsis';
15
- import { SearchCharacter } from './SearchCharacter';
16
-
17
- export type PrivateChatCharacter = Pick<ICharacter, '_id' | 'name'>;
18
-
19
- export type ChatMessage =
20
- | IChatMessage
21
- | IPrivateChatMessage
22
- | ITradeChatMessage;
23
- export interface IChatRevampProps {
24
- chatMessages: ChatMessage[];
25
- onSendGlobalChatMessage: (message: string) => void;
26
- onCloseButton: () => void;
27
- onFocus?: () => void;
28
- onBlur?: () => void;
29
- styles?: IStyles;
30
- tabs: { label: string; id: string }[];
31
- activeTab: string;
32
- onChangeTab: (tabId: string) => void;
33
- privateChatCharacters?: PrivateChatCharacter[];
34
- onChangeCharacterName: (characterName: string) => void;
35
- onCharacterClick?: (character: PrivateChatCharacter) => void;
36
- onSendPrivateChatMessage: (message: string) => void;
37
- recentChatCharacters?: PrivateChatCharacter[];
38
- recentSelectedChatCharacterId?: string;
39
- onPreviousChatCharacterClick?: (character: PrivateChatCharacter) => void;
40
- onRemoveRecentChatCharacter?: (character: PrivateChatCharacter) => void;
41
- unseenMessageCharacterIds?: string[];
42
- onSendTradeMessage: (message: string) => void;
43
- searchCharacterUI: boolean;
44
- hideSearchCharacterUI: () => void;
45
- showSearchCharacterUI: () => void;
46
- minimizedByDefault?: boolean;
47
- autoCloseOnSend?: boolean;
48
- }
49
-
50
- export const ChatRevamp: React.FC<IChatRevampProps> = ({
51
- chatMessages,
52
- onSendGlobalChatMessage,
53
- onChangeCharacterName,
54
- onFocus,
55
- onBlur,
56
- onCloseButton,
57
- styles,
58
- tabs,
59
- onChangeTab,
60
- activeTab,
61
- privateChatCharacters,
62
- onCharacterClick,
63
- onSendPrivateChatMessage,
64
- recentChatCharacters,
65
- recentSelectedChatCharacterId = '',
66
- onPreviousChatCharacterClick,
67
- onRemoveRecentChatCharacter,
68
- unseenMessageCharacterIds = [],
69
- onSendTradeMessage,
70
- searchCharacterUI,
71
- hideSearchCharacterUI,
72
- showSearchCharacterUI,
73
- minimizedByDefault = false,
74
- autoCloseOnSend = false,
75
- }) => {
76
- const [showRecentChats, setShowRecentChats] = useState(false);
77
- const [isExpanded, setIsExpanded] = useState(!minimizedByDefault);
1
+ import React from 'react';
2
+ import styled from 'styled-components';
3
+ import { useChat } from '../../hooks/useChat';
4
+ import { Chat } from '../Chat/Chat';
5
+ import { ChatContent } from './ChatContent';
6
+ import { ChatTabs } from './ChatTabs';
7
+ import { ExpandButton } from './ExpandButton';
8
+ import { RecentChats } from './RecentChats';
9
+ import { IChatRevampProps } from './types';
10
+
11
+ export const ChatRevamp: React.FC<IChatRevampProps> = props => {
12
+ const {
13
+ chatMessages,
14
+ onSendGlobalChatMessage,
15
+ onChangeCharacterName,
16
+ onFocus,
17
+ onBlur,
18
+ onCloseButton,
19
+ styles,
20
+ tabs,
21
+ onChangeTab,
22
+ activeTab,
23
+ privateChatCharacters,
24
+ onCharacterClick,
25
+ onSendPrivateChatMessage,
26
+ recentChatCharacters,
27
+ recentSelectedChatCharacterId,
28
+ onPreviousChatCharacterClick,
29
+ onRemoveRecentChatCharacter,
30
+ unseenMessageCharacterIds,
31
+ onSendTradeMessage,
32
+ searchCharacterUI,
33
+ hideSearchCharacterUI,
34
+ showSearchCharacterUI,
35
+ minimizedByDefault,
36
+ autoCloseOnSend,
37
+ } = props;
78
38
 
79
39
  const isPrivate = activeTab === 'private';
80
40
  const isTrade = activeTab === 'trade';
81
41
 
82
- useEffect(() => {
83
- if (isPrivate) {
84
- setIsExpanded(true);
85
- }
86
- }, [isPrivate]);
87
-
88
- const toggleExpand = () => setIsExpanded(prev => !prev);
89
-
90
- const toggleRecentChats = () => setShowRecentChats(prev => !prev);
91
-
92
- const handleTabChange = (tabId: string) => {
93
- if (tabId === 'private') {
94
- setIsExpanded(true);
95
- }
96
- onChangeTab(tabId);
97
- };
98
-
99
- const handlePreviousChatCharacterClick = (
100
- character: PrivateChatCharacter
101
- ) => {
102
- onPreviousChatCharacterClick?.(character);
103
- hideSearchCharacterUI();
104
- };
105
-
106
- const renderTabs = () => (
107
- <TabContainer>
108
- {tabs.map((tab, index) => (
109
- <Tab
110
- key={`${tab.label}_${index}`}
111
- active={tab.id === activeTab}
112
- onPointerDown={() => handleTabChange(tab.id)}
113
- >
114
- {tab.label}
115
- </Tab>
116
- ))}
117
- </TabContainer>
118
- );
119
-
120
- const renderRecentChatTopBar = () => (
121
- <RecentChatTopBar>
122
- <BurgerIconContainer
123
- onPointerDown={toggleRecentChats}
124
- hasUnseenMessages={unseenMessageCharacterIds.length > 0}
125
- >
126
- <BurgerLineIcon />
127
- <BurgerLineIcon />
128
- <BurgerLineIcon />
129
- </BurgerIconContainer>
130
- {showRecentChats && (
131
- <SearchButton onPointerDown={showSearchCharacterUI}>
132
- <RxMagnifyingGlass size={16} color={uiColors.white} />
133
- </SearchButton>
134
- )}
135
- </RecentChatTopBar>
136
- );
137
-
138
- const renderRecentChatList = () => (
139
- <RecentChatLogContainer isOpen={showRecentChats}>
140
- {recentChatCharacters?.map(character => (
141
- <ListElementContainer key={character._id}>
142
- <ListElement
143
- active={character._id === recentSelectedChatCharacterId}
144
- onPointerDown={() => handlePreviousChatCharacterClick(character)}
145
- >
146
- <StatusDot
147
- isUnseen={unseenMessageCharacterIds.includes(character._id)}
148
- />
149
- <Ellipsis maxWidth="140px" maxLines={1}>
150
- {character.name}
151
- </Ellipsis>
152
- </ListElement>
153
- <CloseButton
154
- className="close-button"
155
- onPointerDown={() => onRemoveRecentChatCharacter?.(character)}
156
- >
157
- <RxCross2 size={16} />
158
- </CloseButton>
159
- </ListElementContainer>
160
- ))}
161
- </RecentChatLogContainer>
162
- );
163
-
164
- const renderChatContent = () => {
165
- if (isPrivate && searchCharacterUI) {
166
- return (
167
- <SearchCharacter
168
- onFocus={onFocus}
169
- onBlur={onBlur}
170
- onChangeCharacterName={onChangeCharacterName}
171
- styles={styles}
172
- recentCharacters={privateChatCharacters}
173
- hideSearchCharacterUI={hideSearchCharacterUI}
174
- onCharacterClick={onCharacterClick}
175
- />
176
- );
177
- }
178
-
179
- return (
180
- <Chat
181
- chatMessages={chatMessages}
182
- onSendChatMessage={() => {
183
- if (autoCloseOnSend) {
184
- onCloseButton();
185
- }
186
-
187
- if (isPrivate) {
188
- return onSendPrivateChatMessage;
189
- } else if (isTrade) {
190
- return onSendTradeMessage;
191
- } else {
192
- return onSendGlobalChatMessage;
193
- }
194
- }}
195
- sendMessage={true}
196
- onCloseButton={onCloseButton}
197
- styles={styles}
198
- onFocus={onFocus}
199
- onBlur={onBlur}
200
- isExpanded={isExpanded}
201
- />
202
- );
203
- };
42
+ const chatHook = useChat({
43
+ activeTab,
44
+ minimizedByDefault,
45
+ isPrivate,
46
+ onChangeTab,
47
+ onPreviousChatCharacterClick,
48
+ hideSearchCharacterUI,
49
+ unseenMessageCharacterIds,
50
+ });
204
51
 
205
52
  return (
206
53
  <ChatRevampContainer>
207
- <TopBar isExpanded={isExpanded}>
208
- {isExpanded && renderTabs()}
209
- <ExpandButton onClick={toggleExpand} isExpanded={isExpanded}>
210
- {isExpanded ? <IoMdContract size={20} /> : <IoMdExpand size={20} />}
211
- </ExpandButton>
54
+ <TopBar isExpanded={chatHook.isExpanded}>
55
+ {chatHook.isExpanded && (
56
+ <ChatTabs
57
+ tabs={tabs}
58
+ activeTab={activeTab}
59
+ onChangeTab={chatHook.handleTabChange}
60
+ />
61
+ )}
62
+ <ExpandButton
63
+ isExpanded={chatHook.isExpanded}
64
+ onClick={chatHook.toggleExpand}
65
+ />
212
66
  </TopBar>
213
67
  <PrivateChatContainer
214
68
  width={styles?.width || '80%'}
215
69
  height={styles?.height || 'auto'}
216
- isExpanded={isExpanded}
70
+ isExpanded={chatHook.isExpanded}
217
71
  >
218
- {isExpanded && (
219
- <RecentChatTabContainer
220
- isPrivate={isPrivate}
221
- isOpen={showRecentChats}
222
- >
223
- {renderRecentChatTopBar()}
224
- {renderRecentChatList()}
225
- </RecentChatTabContainer>
72
+ {chatHook.isExpanded ? (
73
+ <>
74
+ {isPrivate && (
75
+ <RecentChats
76
+ showRecentChats={chatHook.showRecentChats}
77
+ toggleRecentChats={chatHook.toggleRecentChats}
78
+ hasUnseenMessages={chatHook.hasUnseenMessages || false}
79
+ showSearchCharacterUI={showSearchCharacterUI}
80
+ recentChatCharacters={recentChatCharacters}
81
+ recentSelectedChatCharacterId={recentSelectedChatCharacterId}
82
+ unseenMessageCharacterIds={unseenMessageCharacterIds}
83
+ onPreviousChatCharacterClick={character =>
84
+ chatHook.handlePreviousChatCharacterClick(character)
85
+ }
86
+ onRemoveRecentChatCharacter={onRemoveRecentChatCharacter}
87
+ isPrivate={isPrivate}
88
+ />
89
+ )}
90
+ <ChatContentWrapper isPrivate={isPrivate}>
91
+ <ChatContent
92
+ isPrivate={isPrivate}
93
+ isTrade={isTrade}
94
+ searchCharacterUI={searchCharacterUI}
95
+ chatMessages={chatMessages}
96
+ onSendGlobalChatMessage={onSendGlobalChatMessage}
97
+ onSendPrivateChatMessage={onSendPrivateChatMessage}
98
+ onSendTradeMessage={onSendTradeMessage}
99
+ onCloseButton={onCloseButton}
100
+ styles={styles}
101
+ onFocus={onFocus}
102
+ onBlur={onBlur}
103
+ isExpanded={chatHook.isExpanded}
104
+ autoCloseOnSend={autoCloseOnSend || false}
105
+ onChangeCharacterName={onChangeCharacterName}
106
+ privateChatCharacters={privateChatCharacters}
107
+ hideSearchCharacterUI={hideSearchCharacterUI}
108
+ onCharacterClick={onCharacterClick}
109
+ />
110
+ </ChatContentWrapper>
111
+ </>
112
+ ) : (
113
+ <CollapsedChatInput>
114
+ <Chat
115
+ chatMessages={[]}
116
+ onSendChatMessage={onSendGlobalChatMessage}
117
+ sendMessage={true}
118
+ onCloseButton={onCloseButton}
119
+ styles={styles}
120
+ onFocus={onFocus}
121
+ onBlur={onBlur}
122
+ isExpanded={false}
123
+ />
124
+ </CollapsedChatInput>
226
125
  )}
227
- <ChatWrapper>{renderChatContent()}</ChatWrapper>
228
126
  </PrivateChatContainer>
229
127
  </ChatRevampContainer>
230
128
  );
@@ -237,68 +135,11 @@ const ChatRevampContainer = styled.div`
237
135
  position: relative;
238
136
  `;
239
137
 
240
- interface ITopBarProps {
241
- isExpanded: boolean;
242
- }
243
-
244
- const TopBar = styled.div<ITopBarProps>`
138
+ const TopBar = styled.div<{ isExpanded: boolean }>`
245
139
  display: flex;
246
140
  align-items: center;
247
141
  justify-content: flex-start;
248
-
249
- ${({ isExpanded }) =>
250
- !isExpanded &&
251
- css`
252
- min-height: 32px; // Ensure there's always space for the expand button when its collapsed
253
- `}
254
- `;
255
-
256
- const TabContainer = styled.div`
257
- display: flex;
258
- gap: 10px;
259
- align-items: center;
260
- flex-grow: 1;
261
- `;
262
-
263
- const Tab = styled.button<{ active: boolean }>`
264
- width: 120px;
265
- color: white;
266
- font-size: 0.8rem;
267
- all: unset;
268
- padding: 0.6rem;
269
- font-size: 0.8rem;
270
-
271
- border-radius: 5px 5px 0 0;
272
- border-width: 0.25rem 0.25rem 0 0.25rem;
273
- border-style: solid;
274
- border-color: ${props =>
275
- props.active ? 'rgba(198, 81, 2, 0.5)' : 'rgba(128, 128, 128, 0.5)'};
276
-
277
- background-color: ${props =>
278
- props.active ? uiColors.orange : 'rgba(0, 0, 0, 0.2)'};
279
- color: ${props => (props.active ? 'white' : uiColors.darkGray)};
280
- `;
281
-
282
- const ExpandButton = styled.button<{ isExpanded: boolean }>`
283
- position: absolute;
284
- top: 0;
285
- ${({ isExpanded }) => (isExpanded ? 'right: 0' : 'left: 0')};
286
- width: 30px;
287
- height: 30px;
288
- background-color: ${uiColors.orange};
289
- color: white;
290
- border: none;
291
- border-radius: 50%;
292
- display: flex;
293
- justify-content: center;
294
- align-items: center;
295
- cursor: pointer;
296
- transition: all 0.3s ease;
297
- z-index: 10;
298
-
299
- &:hover {
300
- background-color: ${uiColors.orange};
301
- }
142
+ min-height: ${({ isExpanded }) => (isExpanded ? 'auto' : '32px')};
302
143
  `;
303
144
 
304
145
  const PrivateChatContainer = styled.div<{
@@ -315,173 +156,18 @@ const PrivateChatContainer = styled.div<{
315
156
  flex-wrap: wrap;
316
157
  `;
317
158
 
318
- const RecentChatTabContainer = styled.div<{
319
- isPrivate: boolean;
320
- isOpen: boolean;
321
- }>`
322
- display: ${props => (props.isPrivate ? 'flex' : 'none')};
323
- flex-direction: column;
324
- border-right: 1px solid ${uiColors.gray};
325
- outline: none;
326
- width: ${props => (props.isOpen ? '25%' : '30px')};
327
- max-width: 200px;
328
- min-width: ${props => (props.isOpen ? '180px' : '30px')};
329
- transition: all 0.3s ease-in-out;
159
+ const ChatContentWrapper = styled.div<{ isPrivate: boolean }>`
160
+ flex-grow: 1;
330
161
  overflow: hidden;
331
- height: 100%;
332
- @media (max-width: 768px) {
333
- width: ${props => (props.isOpen ? '50%' : '30px')};
334
- min-width: ${props => (props.isOpen ? '150px' : '30px')};
335
- }
336
- `;
337
-
338
- const RecentChatTopBar = styled.div`
339
- display: flex;
340
- align-items: center;
341
- justify-content: space-between;
342
- height: 30px;
343
- flex-shrink: 0;
344
- `;
345
-
346
- const SearchButton = styled.button`
347
- border: none;
348
- background-color: transparent;
349
- display: flex;
350
- flex-direction: column;
351
- align-items: flex-end;
352
- gap: 2px;
353
- padding: 4px;
354
- position: relative;
355
- `;
356
-
357
- const BurgerIconContainer = styled.button<{ hasUnseenMessages: boolean }>`
358
- border: none;
359
- background-color: transparent;
360
162
  display: flex;
361
163
  flex-direction: column;
362
- align-items: flex-end;
363
- padding: 4px;
364
- gap: 2px;
365
164
  position: relative;
366
-
367
- &:after {
368
- content: '';
369
- width: 6px;
370
- height: 6px;
371
- position: absolute;
372
- top: 0;
373
- right: 2px;
374
- border-radius: 50%;
375
- background-color: ${uiColors.lightGreen};
376
- display: ${props => (props.hasUnseenMessages ? 'block' : 'none')};
377
- }
378
- `;
379
-
380
- const BurgerLineIcon = styled.span`
381
- width: 1rem;
382
- height: 2px;
383
- background-color: #ffffff;
384
- `;
385
-
386
- const RecentChatLogContainer = styled.div<{ isOpen: boolean }>`
387
- display: ${props => (props.isOpen ? 'flex' : 'none')};
388
- opacity: ${props => (props.isOpen ? 1 : 0)};
389
- flex-direction: column;
390
- gap: 0.25rem; // Reduce this from 0.5rem to 0.25rem
391
- transition: opacity 0.3s ease-in-out;
392
- padding: 0;
393
- margin: 0;
394
- overflow-y: auto;
395
- flex-grow: 1;
396
- height: 0;
397
-
398
- /* Firefox */
399
- scrollbar-width: thin;
400
- scrollbar-color: rgba(51, 51, 51, 0.4) rgba(30, 30, 30, 0.4);
401
-
402
- /* WebKit and Chromium-based browsers */
403
- &::-webkit-scrollbar {
404
- width: 8px;
405
- height: 8px;
406
- }
407
-
408
- &::-webkit-scrollbar-track {
409
- background: rgba(30, 30, 30, 0.2);
410
- border-radius: 4px;
411
- }
412
-
413
- &::-webkit-scrollbar-thumb {
414
- background-color: rgba(255, 102, 0, 0.5);
415
- border-radius: 4px;
416
- border: 2px solid rgba(30, 30, 30, 0.2);
417
- }
418
-
419
- &::-webkit-scrollbar-thumb:hover {
420
- background-color: rgba(255, 102, 0, 0.7);
421
- }
422
- `;
423
-
424
- const ListElementContainer = styled.div`
425
- display: flex;
426
- justify-content: space-between;
427
- align-items: center;
428
- padding: 2px 0; // Add small vertical padding
165
+ width: ${props => (props.isPrivate ? 'calc(75% - 10px)' : '100%')};
429
166
  `;
430
167
 
431
- const ListElement = styled.button<{ active: boolean }>`
432
- margin: 0 !important; // Remove vertical margins
433
- font-size: ${uiFonts.size.small} !important;
434
- padding: 2px;
435
- all: unset;
436
- color: ${props => (props.active ? uiColors.yellow : uiColors.white)};
168
+ const CollapsedChatInput = styled.div`
437
169
  width: 100%;
438
- position: relative;
439
- display: flex;
440
- align-items: center;
441
- gap: 4px;
442
-
443
- &:hover {
444
- color: #ff0;
445
- }
446
- max-width: calc(100% - 24px);
447
- overflow: hidden;
448
- text-overflow: ellipsis;
449
- white-space: nowrap;
450
- `;
451
-
452
- const StatusDot = styled.span<{ isUnseen: boolean }>`
453
- width: 6px;
454
- height: 6px;
455
- border-radius: 50%;
456
- background-color: ${props =>
457
- props.isUnseen ? uiColors.lightGreen : uiColors.gray};
458
- display: inline-block;
459
- margin-right: 6px;
460
- `;
461
-
462
- const CloseButton = styled.button`
463
- all: unset;
464
- font-size: ${uiFonts.size.xxsmall};
465
- margin: 0 0.5rem;
466
- transition: all 0.2s ease-in-out;
467
- background-color: ${uiColors.red};
468
- color: ${uiColors.white};
469
- width: 16px;
470
- height: 16px;
471
- border-radius: 50%;
170
+ height: 100%;
472
171
  display: flex;
473
- justify-content: center;
474
172
  align-items: center;
475
- &:hover {
476
- background-color: ${uiColors.white};
477
- color: ${uiColors.red};
478
- }
479
- `;
480
-
481
- const ChatWrapper = styled.div`
482
- flex-grow: 1;
483
- overflow: hidden;
484
- display: flex;
485
- flex-direction: column;
486
- position: relative;
487
173
  `;
@@ -0,0 +1,51 @@
1
+ import React from 'react';
2
+ import styled from 'styled-components';
3
+ import { uiColors } from '../../constants/uiColors';
4
+
5
+ interface ChatTabsProps {
6
+ tabs: { label: string; id: string }[];
7
+ activeTab: string;
8
+ onChangeTab: (tabId: string) => void;
9
+ }
10
+
11
+ export const ChatTabs: React.FC<ChatTabsProps> = ({
12
+ tabs,
13
+ activeTab,
14
+ onChangeTab,
15
+ }) => (
16
+ <TabContainer>
17
+ {tabs.map((tab, index) => (
18
+ <Tab
19
+ key={`${tab.label}_${index}`}
20
+ active={tab.id === activeTab}
21
+ onPointerDown={() => onChangeTab(tab.id)}
22
+ >
23
+ {tab.label}
24
+ </Tab>
25
+ ))}
26
+ </TabContainer>
27
+ );
28
+
29
+ const TabContainer = styled.div`
30
+ display: flex;
31
+ gap: 10px;
32
+ align-items: center;
33
+ flex-grow: 1;
34
+ `;
35
+
36
+ const Tab = styled.button<{ active: boolean }>`
37
+ width: 120px;
38
+ color: white;
39
+ font-size: 0.8rem;
40
+ all: unset;
41
+ padding: 0.6rem;
42
+ font-size: 0.8rem;
43
+ border-radius: 5px 5px 0 0;
44
+ border-width: 0.25rem 0.25rem 0 0.25rem;
45
+ border-style: solid;
46
+ border-color: ${props =>
47
+ props.active ? 'rgba(198, 81, 2, 0.5)' : 'rgba(128, 128, 128, 0.5)'};
48
+ background-color: ${props =>
49
+ props.active ? uiColors.orange : 'rgba(0, 0, 0, 0.2)'};
50
+ color: ${props => (props.active ? 'white' : uiColors.darkGray)};
51
+ `;
@@ -0,0 +1,40 @@
1
+ import React from 'react';
2
+ import { IoMdContract, IoMdExpand } from 'react-icons/io';
3
+ import styled from 'styled-components';
4
+ import { uiColors } from '../../constants/uiColors';
5
+
6
+ interface ExpandButtonProps {
7
+ isExpanded: boolean;
8
+ onClick: () => void;
9
+ }
10
+
11
+ export const ExpandButton: React.FC<ExpandButtonProps> = ({
12
+ isExpanded,
13
+ onClick,
14
+ }) => (
15
+ <StyledExpandButton isExpanded={isExpanded} onClick={onClick}>
16
+ {isExpanded ? <IoMdContract size={20} /> : <IoMdExpand size={20} />}
17
+ </StyledExpandButton>
18
+ );
19
+
20
+ const StyledExpandButton = styled.button<{ isExpanded: boolean }>`
21
+ position: absolute;
22
+ top: 0;
23
+ ${({ isExpanded }) => (isExpanded ? 'right: 0' : 'left: 0')};
24
+ width: 30px;
25
+ height: 30px;
26
+ background-color: ${uiColors.orange};
27
+ color: white;
28
+ border: none;
29
+ border-radius: 50%;
30
+ display: flex;
31
+ justify-content: center;
32
+ align-items: center;
33
+ cursor: pointer;
34
+ transition: all 0.3s ease;
35
+ z-index: 10;
36
+
37
+ &:hover {
38
+ background-color: ${uiColors.orange};
39
+ }
40
+ `;