@ndla/ui 26.1.0 → 27.0.1

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.
Files changed (75) hide show
  1. package/es/Breadcrumb/ActionBreadcrumb.js +10 -5
  2. package/es/Breadcrumb/Breadcrumb.js +3 -4
  3. package/es/MyNdla/Resource/Folder.js +29 -13
  4. package/es/Resource/BlockResource.js +42 -62
  5. package/es/Resource/ListResource.js +41 -22
  6. package/es/Resource/resourceComponents.js +64 -38
  7. package/es/TreeStructure/ComboboxButton.js +162 -0
  8. package/es/TreeStructure/FolderItem.js +98 -78
  9. package/es/TreeStructure/FolderItems.js +25 -14
  10. package/es/TreeStructure/FolderNameInput.js +40 -33
  11. package/es/TreeStructure/NavigationLink.js +18 -10
  12. package/es/TreeStructure/TreeStructure.js +92 -165
  13. package/es/TreeStructure/arrowNavigation.js +3 -3
  14. package/es/TreeStructure/helperFunctions.js +3 -0
  15. package/es/locale/messages-en.js +6 -1
  16. package/es/locale/messages-nb.js +6 -1
  17. package/es/locale/messages-nn.js +6 -1
  18. package/es/locale/messages-se.js +6 -1
  19. package/es/locale/messages-sma.js +6 -1
  20. package/lib/Breadcrumb/ActionBreadcrumb.js +8 -4
  21. package/lib/Breadcrumb/Breadcrumb.js +3 -5
  22. package/lib/MyNdla/Resource/Folder.js +34 -13
  23. package/lib/Resource/BlockResource.js +47 -62
  24. package/lib/Resource/ListResource.js +46 -22
  25. package/lib/Resource/resourceComponents.d.ts +6 -1
  26. package/lib/Resource/resourceComponents.js +64 -37
  27. package/lib/TreeStructure/ComboboxButton.d.ts +28 -0
  28. package/lib/TreeStructure/ComboboxButton.js +176 -0
  29. package/lib/TreeStructure/FolderItem.d.ts +1 -1
  30. package/lib/TreeStructure/FolderItem.js +99 -77
  31. package/lib/TreeStructure/FolderItems.d.ts +4 -2
  32. package/lib/TreeStructure/FolderItems.js +26 -14
  33. package/lib/TreeStructure/FolderNameInput.d.ts +3 -1
  34. package/lib/TreeStructure/FolderNameInput.js +41 -32
  35. package/lib/TreeStructure/NavigationLink.d.ts +1 -1
  36. package/lib/TreeStructure/NavigationLink.js +18 -10
  37. package/lib/TreeStructure/TreeStructure.d.ts +2 -2
  38. package/lib/TreeStructure/TreeStructure.js +92 -165
  39. package/lib/TreeStructure/arrowNavigation.d.ts +2 -1
  40. package/lib/TreeStructure/arrowNavigation.js +3 -3
  41. package/lib/TreeStructure/helperFunctions.d.ts +2 -1
  42. package/lib/TreeStructure/helperFunctions.js +8 -2
  43. package/lib/TreeStructure/types.d.ts +6 -7
  44. package/lib/locale/messages-en.d.ts +5 -0
  45. package/lib/locale/messages-en.js +6 -1
  46. package/lib/locale/messages-nb.d.ts +5 -0
  47. package/lib/locale/messages-nb.js +6 -1
  48. package/lib/locale/messages-nn.d.ts +5 -0
  49. package/lib/locale/messages-nn.js +6 -1
  50. package/lib/locale/messages-se.d.ts +5 -0
  51. package/lib/locale/messages-se.js +6 -1
  52. package/lib/locale/messages-sma.d.ts +5 -0
  53. package/lib/locale/messages-sma.js +6 -1
  54. package/package.json +11 -11
  55. package/src/Breadcrumb/ActionBreadcrumb.tsx +9 -3
  56. package/src/Breadcrumb/Breadcrumb.tsx +1 -2
  57. package/src/MyNdla/Resource/Folder.tsx +19 -4
  58. package/src/Resource/BlockResource.tsx +41 -33
  59. package/src/Resource/ListResource.tsx +35 -29
  60. package/src/Resource/resourceComponents.tsx +60 -26
  61. package/src/TreeStructure/ComboboxButton.tsx +189 -0
  62. package/src/TreeStructure/FolderItem.tsx +89 -70
  63. package/src/TreeStructure/FolderItems.tsx +36 -16
  64. package/src/TreeStructure/FolderNameInput.tsx +43 -18
  65. package/src/TreeStructure/NavigationLink.tsx +17 -10
  66. package/src/TreeStructure/TreeStructure.tsx +63 -139
  67. package/src/TreeStructure/arrowNavigation.ts +7 -6
  68. package/src/TreeStructure/helperFunctions.ts +5 -1
  69. package/src/TreeStructure/types.ts +6 -7
  70. package/src/locale/messages-en.ts +6 -0
  71. package/src/locale/messages-nb.ts +5 -0
  72. package/src/locale/messages-nn.ts +5 -0
  73. package/src/locale/messages-se.ts +6 -0
  74. package/src/locale/messages-sma.ts +6 -0
  75. package/src/.DS_Store +0 -0
@@ -7,12 +7,18 @@
7
7
  */
8
8
 
9
9
  import styled from '@emotion/styled';
10
- import React from 'react';
11
- import SafeLink from '@ndla/safelink';
10
+ import React, { useRef } from 'react';
12
11
  import { fonts, spacing, colors, breakpoints, mq } from '@ndla/core';
13
12
  import { MenuButton, MenuItemProps } from '@ndla/button';
14
13
  import Image from '../Image';
15
- import { CompressedTagList, ResourceImageProps, ResourceTitle, TopicList } from './resourceComponents';
14
+ import {
15
+ CompressedTagList,
16
+ ResourceImageProps,
17
+ ResourceTitle,
18
+ ResourceTitleLink,
19
+ TopicList,
20
+ LoaderProps,
21
+ } from './resourceComponents';
16
22
  import ContentLoader from '../ContentLoader';
17
23
 
18
24
  const StyledResourceDescription = styled.p`
@@ -31,7 +37,7 @@ const StyledResourceDescription = styled.p`
31
37
  -webkit-box-orient: vertical;
32
38
  `;
33
39
 
34
- const ResourceWrapper = styled(SafeLink)`
40
+ const ResourceWrapper = styled.div`
35
41
  flex: 1;
36
42
  display: grid;
37
43
  grid-template-columns: auto 1fr auto;
@@ -47,38 +53,38 @@ const ResourceWrapper = styled(SafeLink)`
47
53
  'tags tags';
48
54
  }
49
55
 
50
- text-decoration: none;
51
- box-shadow: none;
56
+ cursor: pointer;
52
57
  padding: ${spacing.small};
53
58
  border: 1px solid ${colors.brand.neutral7};
54
59
  border-radius: 2px;
55
- color: ${colors.brand.greyDark};
56
60
  gap: 0 ${spacing.small};
57
61
 
58
62
  &:hover {
59
63
  box-shadow: 1px 1px 6px 2px rgba(9, 55, 101, 0.08);
60
64
  transition-duration: 0.2s;
61
- ${ResourceTitle} {
65
+ ${() => ResourceTitleLink} {
62
66
  color: ${colors.brand.primary};
63
67
  text-decoration: underline;
64
68
  }
65
- a {
66
- display: flex;
67
- align-items: center;
68
- }
69
69
  }
70
70
  `;
71
71
 
72
72
  const TagsandActionMenu = styled.div`
73
+ box-sizing: content-box;
74
+ padding: 2px;
73
75
  grid-area: tags;
74
76
  display: flex;
75
77
  align-items: center;
76
78
  width: 100%;
77
79
  overflow: hidden;
78
- gap: ${spacing.small};
79
80
  align-self: flex-start;
80
81
  justify-self: flex-end;
81
82
  justify-content: flex-end;
83
+
84
+ ${mq.range({ from: breakpoints.mobileWide })} {
85
+ margin-top: -${spacing.xsmall};
86
+ margin-right: -${spacing.xxsmall};
87
+ }
82
88
  `;
83
89
 
84
90
  const StyledImageWrapper = styled.div<StyledImageProps>`
@@ -100,7 +106,7 @@ const StyledImage = styled(Image)`
100
106
 
101
107
  const TopicAndTitleWrapper = styled.div`
102
108
  grid-area: topicAndTitle;
103
- margin-top: ${spacing.xxsmall};
109
+ margin-top: 2px;
104
110
  `;
105
111
 
106
112
  interface StyledImageProps {
@@ -146,13 +152,7 @@ const ListResourceImage = ({ resourceImage, loading, type }: ListResourceImagePr
146
152
  );
147
153
  };
148
154
 
149
- interface TopicAndTitleProps {
150
- title: string;
151
- topics: string[];
152
- loading?: boolean;
153
- }
154
-
155
- const TopicAndTitle = ({ title, topics, loading }: TopicAndTitleProps) => {
155
+ const TopicAndTitleLoader = ({ loading, children }: LoaderProps) => {
156
156
  if (loading) {
157
157
  return (
158
158
  <ContentLoader height={'40px'} width={'100%'} viewBox={null} preserveAspectRatio="none">
@@ -162,12 +162,7 @@ const TopicAndTitle = ({ title, topics, loading }: TopicAndTitleProps) => {
162
162
  </ContentLoader>
163
163
  );
164
164
  }
165
- return (
166
- <>
167
- <ResourceTitle>{title}</ResourceTitle>
168
- <TopicList topics={topics} />
169
- </>
170
- );
165
+ return <>{children}</>;
171
166
  };
172
167
 
173
168
  interface ResourceDescriptionProps {
@@ -200,14 +195,25 @@ const ListResource = ({
200
195
  }: ListResourceProps) => {
201
196
  const showDescription = description !== undefined;
202
197
  const imageType = showDescription ? 'normal' : 'compact';
198
+ const linkRef = useRef<HTMLAnchorElement>(null);
199
+ const handleClick = () => {
200
+ if (linkRef.current) {
201
+ linkRef.current.click();
202
+ }
203
+ };
203
204
 
204
205
  return (
205
- <ResourceWrapper to={link} id={id}>
206
+ <ResourceWrapper onClick={handleClick} id={id}>
206
207
  <StyledImageWrapper imageSize={imageType}>
207
208
  <ListResourceImage resourceImage={resourceImage} loading={isLoading} type={imageType} />
208
209
  </StyledImageWrapper>
209
210
  <TopicAndTitleWrapper>
210
- <TopicAndTitle topics={topics} title={title} loading={isLoading} />
211
+ <TopicAndTitleLoader loading={isLoading}>
212
+ <ResourceTitleLink to={link} ref={linkRef}>
213
+ <ResourceTitle>{title}</ResourceTitle>
214
+ </ResourceTitleLink>
215
+ <TopicList topics={topics} />
216
+ </TopicAndTitleLoader>
211
217
  </TopicAndTitleWrapper>
212
218
  {showDescription && <ResourceDescription description={description} loading={isLoading} />}
213
219
  <TagsandActionMenu>
@@ -7,19 +7,25 @@
7
7
  */
8
8
 
9
9
  import styled from '@emotion/styled';
10
- import { colors, fonts, spacing } from '@ndla/core';
11
- import React, { MouseEvent } from 'react';
12
-
10
+ import { colors, fonts, misc, spacing } from '@ndla/core';
11
+ import React, { MouseEvent, ReactNode } from 'react';
12
+ import { useTranslation } from 'react-i18next';
13
13
  import { MenuButton } from '@ndla/button';
14
14
  import SafeLink from '@ndla/safelink';
15
15
  import { useNavigate } from 'react-router-dom';
16
+ import { HashTag } from '@ndla/icons/common';
16
17
 
17
18
  export interface ResourceImageProps {
18
19
  alt: string;
19
20
  src: string;
20
21
  }
21
22
 
22
- export const ResourceTitle = styled.h3`
23
+ export const ResourceTitleLink = styled(SafeLink)`
24
+ box-shadow: none;
25
+ color: ${colors.brand.primary};
26
+ `;
27
+
28
+ export const ResourceTitle = styled.h2`
23
29
  min-width: 50px;
24
30
  margin: 0;
25
31
  flex: 1;
@@ -32,13 +38,14 @@ export const ResourceTitle = styled.h3`
32
38
  line-clamp: 1;
33
39
  -webkit-box-orient: vertical;
34
40
  grid-area: resourceTitle;
41
+ ${fonts.sizes('18px', '18px')};
35
42
  `;
36
43
 
37
44
  const StyledTagList = styled.ul`
38
45
  list-style: none;
39
46
  display: flex;
40
47
  margin: 0;
41
- padding: 0;
48
+ padding: 2px;
42
49
  gap: ${spacing.xsmall};
43
50
  overflow: hidden;
44
51
  `;
@@ -49,11 +56,10 @@ const StyledTagListElement = styled.li`
49
56
  `;
50
57
 
51
58
  const StyledSafeLink = styled(SafeLink)`
59
+ display: flex;
60
+ align-items: center;
52
61
  box-shadow: none;
53
62
  color: ${colors.brand.grey};
54
- ::before {
55
- content: '#';
56
- }
57
63
  &:hover {
58
64
  color: ${colors.brand.primary};
59
65
  }
@@ -68,16 +74,18 @@ const StyledTopicList = styled.ul`
68
74
  grid-area: topicList;
69
75
  `;
70
76
 
77
+ const StyledTopicDivider = styled.span`
78
+ margin: 0;
79
+ padding: 0 ${spacing.xxsmall};
80
+ `;
81
+
71
82
  const StyledTopicListElement = styled.li`
72
83
  ${fonts.sizes(12)};
73
84
  margin: 0;
74
85
  line-height: 1.5;
75
86
  padding: 0;
76
- `;
77
-
78
- const StyledTopicDivider = styled.span`
79
- margin: 0;
80
- padding: 0 ${spacing.xxsmall};
87
+ display: flex;
88
+ align-items: center;
81
89
  `;
82
90
 
83
91
  export const Row = styled.div`
@@ -86,27 +94,36 @@ export const Row = styled.div`
86
94
  gap: ${spacing.xsmall};
87
95
  `;
88
96
 
89
- const TagCounterWrapper = styled.p`
90
- color: ${colors.brand.primary};
97
+ const TagCounterWrapper = styled.span`
98
+ color: ${colors.brand.secondary};
91
99
  box-shadow: none;
92
100
  margin: 0;
93
101
  font-weight: ${fonts.weight.semibold};
94
- ${fonts.sizes(16)}
102
+ ${fonts.sizes('14px', '14px')};
103
+ padding: 5px;
95
104
  `;
96
105
 
97
106
  interface TagListProps {
98
107
  tags?: string[];
99
108
  tagLinkPrefix?: string;
100
109
  }
110
+
111
+ export interface LoaderProps {
112
+ loading?: boolean;
113
+ children?: ReactNode;
114
+ }
115
+
101
116
  export const TagList = ({ tags, tagLinkPrefix }: TagListProps) => {
117
+ const { t } = useTranslation();
102
118
  if (!tags) return null;
103
119
  return (
104
- <StyledTagList>
120
+ <StyledTagList aria-label={t('myNdla.tagList')}>
105
121
  {tags.map((tag, i) => (
106
122
  <StyledTagListElement key={`tag-${i}`}>
107
123
  <StyledSafeLink
108
124
  onClick={(e: MouseEvent<HTMLAnchorElement | HTMLElement>) => e.stopPropagation()}
109
125
  to={`${tagLinkPrefix ? tagLinkPrefix : ''}/${tag}`}>
126
+ <HashTag />
110
127
  {tag}
111
128
  </StyledSafeLink>
112
129
  </StyledTagListElement>
@@ -120,25 +137,39 @@ interface CompressedTagListProps {
120
137
  tagLinkPrefix?: string;
121
138
  }
122
139
 
140
+ const TagMenuButton = styled(MenuButton)`
141
+ &:hover,
142
+ &:active,
143
+ &:focus {
144
+ transition: ${misc.transition.default};
145
+ border-radius: 100%;
146
+ background-color: ${colors.brand.light};
147
+ }
148
+ `;
149
+
123
150
  export const CompressedTagList = ({ tags, tagLinkPrefix }: CompressedTagListProps) => {
124
151
  const navigate = useNavigate();
152
+ const { t } = useTranslation();
125
153
  const visibleTags = tags.slice(0, 3);
126
154
  const remainingTags = tags.slice(3, tags.length).map((tag) => {
127
155
  return {
128
- text: '#' + tag,
156
+ icon: <HashTag />,
157
+ text: tag,
129
158
  onClick: () => {
130
159
  navigate(`${tagLinkPrefix ? tagLinkPrefix : ''}/${tag}`);
131
160
  },
132
161
  };
133
162
  });
134
-
135
163
  return (
136
164
  <>
137
165
  <TagList tagLinkPrefix={tagLinkPrefix} tags={visibleTags} />
138
166
  {remainingTags.length > 0 && (
139
- <MenuButton hideMenuIcon={true} menuItems={remainingTags}>
167
+ <TagMenuButton
168
+ hideMenuIcon={true}
169
+ menuItems={remainingTags}
170
+ aria-label={t('myNdla.moreTags', { count: remainingTags.length })}>
140
171
  <TagCounterWrapper>{`+${remainingTags.length}`}</TagCounterWrapper>
141
- </MenuButton>
172
+ </TagMenuButton>
142
173
  )}
143
174
  </>
144
175
  );
@@ -149,14 +180,17 @@ interface TopicListProps {
149
180
  }
150
181
 
151
182
  export const TopicList = ({ topics }: TopicListProps) => {
183
+ const { t } = useTranslation();
152
184
  if (!topics) return null;
153
185
  return (
154
- <StyledTopicList>
186
+ <StyledTopicList aria-label={t('navigation.topics')}>
155
187
  {topics.map((topic, i) => (
156
- <StyledTopicListElement key={topic}>
157
- {topic}
158
- {i !== topics.length - 1 && <StyledTopicDivider>•</StyledTopicDivider>}
159
- </StyledTopicListElement>
188
+ <>
189
+ <StyledTopicListElement key={topic}>
190
+ {topic}
191
+ {i !== topics.length - 1 && <StyledTopicDivider aria-hidden="true">•</StyledTopicDivider>}
192
+ </StyledTopicListElement>
193
+ </>
160
194
  ))}
161
195
  </StyledTopicList>
162
196
  );
@@ -0,0 +1,189 @@
1
+ /**
2
+ * Copyright (c) 2022-present, NDLA.
3
+ *
4
+ * This source code is licensed under the GPLv3 license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+
9
+ import React, { KeyboardEvent } from 'react';
10
+ import { useTranslation } from 'react-i18next';
11
+ import styled from '@emotion/styled';
12
+ import { useForwardedRef } from '@ndla/util';
13
+ import Tooltip from '@ndla/tooltip';
14
+ import { colors, spacing } from '@ndla/core';
15
+ import { IFolder } from '@ndla/types-learningpath-api';
16
+ import { Plus } from '@ndla/icons/action';
17
+ import { ChevronUp, ChevronDown } from '@ndla/icons/common';
18
+ import { forwardRef } from 'react';
19
+ import { ButtonV2 as Button, IconButtonV2 as IconButton } from '@ndla/button';
20
+ import { treestructureId } from './helperFunctions';
21
+ import { FolderType, TreeStructureType } from './types';
22
+ import { arrowNavigation } from './arrowNavigation';
23
+
24
+ interface StyledRowProps {
25
+ isOpen: boolean;
26
+ }
27
+
28
+ const StyledRow = styled.div<StyledRowProps>`
29
+ display: flex;
30
+ justify-content: space-between;
31
+ padding: ${spacing.xxsmall};
32
+ border-bottom: ${({ isOpen }) => isOpen && `1px solid ${colors.brand.tertiary}`};
33
+ `;
34
+ const StyledSelectedFolder = styled(Button)`
35
+ flex: 1;
36
+ justify-content: flex-start;
37
+ color: ${colors.black};
38
+ :hover,
39
+ :focus {
40
+ background: none;
41
+ box-shadow: none;
42
+ border-color: transparent;
43
+ }
44
+ :focus-visible {
45
+ outline: none;
46
+ }
47
+ `;
48
+
49
+ const StyledAddFolderButton = styled(Button)`
50
+ &,
51
+ &:disabled {
52
+ border-color: transparent;
53
+ }
54
+ `;
55
+
56
+ const StyledPlus = styled(Plus)`
57
+ height: 24px;
58
+ width: 24px;
59
+ `;
60
+
61
+ interface Props {
62
+ showTree: boolean;
63
+ type: TreeStructureType;
64
+ label?: string;
65
+ focusedFolder?: FolderType;
66
+ selectedFolder?: FolderType;
67
+ setSelectedFolder: (folder?: FolderType) => void;
68
+ onToggleTree: (open: boolean) => void;
69
+ flattenedFolders: FolderType[];
70
+ onOpenFolder: (id: string) => void;
71
+ onCloseFolder: (id: string) => void;
72
+ setFocusedFolder: (folder?: FolderType) => void;
73
+ onNewFolder?: (name: string, parentId: string) => Promise<IFolder>;
74
+ maxLevel: number;
75
+ setNewFolderParentId: (id?: string) => void;
76
+ }
77
+
78
+ const ComboboxButton = forwardRef<HTMLButtonElement, Props>(
79
+ (
80
+ {
81
+ showTree,
82
+ type,
83
+ label,
84
+ focusedFolder,
85
+ selectedFolder,
86
+ setSelectedFolder,
87
+ onToggleTree,
88
+ flattenedFolders,
89
+ setFocusedFolder,
90
+ onOpenFolder,
91
+ onCloseFolder,
92
+ onNewFolder,
93
+ maxLevel,
94
+ setNewFolderParentId,
95
+ },
96
+ ref,
97
+ ) => {
98
+ const { t } = useTranslation();
99
+ const innerRef = useForwardedRef(ref);
100
+
101
+ const onKeyDown = (e: KeyboardEvent<HTMLButtonElement>) => {
102
+ if (e.key === 'Enter') {
103
+ if (showTree) {
104
+ setSelectedFolder(focusedFolder);
105
+ }
106
+ return;
107
+ }
108
+ if (e.key === 'Escape') {
109
+ onToggleTree(false);
110
+ return;
111
+ }
112
+ if (['ArrowUp', 'ArrowDown'].includes(e.key) && !showTree) {
113
+ onToggleTree(true);
114
+ return;
115
+ }
116
+ if (focusedFolder) {
117
+ arrowNavigation(e, focusedFolder.id, flattenedFolders, setFocusedFolder, onOpenFolder, onCloseFolder);
118
+ }
119
+ };
120
+
121
+ const canAddFolder = selectedFolder && selectedFolder?.breadcrumbs.length < (maxLevel || 1);
122
+ return (
123
+ <StyledRow isOpen={showTree}>
124
+ <StyledSelectedFolder
125
+ ref={innerRef}
126
+ tabIndex={0}
127
+ id={treestructureId(type, 'combobox')}
128
+ role="combobox"
129
+ aria-controls={treestructureId(type, 'popup')}
130
+ aria-haspopup="tree"
131
+ aria-expanded={showTree}
132
+ aria-labelledby={label ? treestructureId(type, 'label') : undefined}
133
+ aria-activedescendant={focusedFolder ? treestructureId(type, focusedFolder.id) : undefined}
134
+ variant="ghost"
135
+ colorTheme="light"
136
+ fontWeight="normal"
137
+ shape="sharp"
138
+ onKeyDown={onKeyDown}
139
+ onClick={() => {
140
+ onToggleTree(!showTree);
141
+ }}>
142
+ {selectedFolder?.name}
143
+ </StyledSelectedFolder>
144
+ {onNewFolder && showTree && (
145
+ <Tooltip
146
+ tooltip={
147
+ canAddFolder
148
+ ? t('myNdla.newFolderUnder', {
149
+ folderName: selectedFolder?.name,
150
+ })
151
+ : t('treeStructure.maxFoldersAlreadyAdded')
152
+ }>
153
+ <StyledAddFolderButton
154
+ variant="outline"
155
+ shape="pill"
156
+ disabled={!canAddFolder}
157
+ aria-label={
158
+ canAddFolder
159
+ ? t('myNdla.newFolderUnder', {
160
+ folderName: selectedFolder?.name,
161
+ })
162
+ : t('treeStructure.maxFoldersAlreadyAdded')
163
+ }
164
+ onClick={() => setNewFolderParentId(focusedFolder?.id)}>
165
+ <StyledPlus /> {t('myNdla.newFolder')}
166
+ </StyledAddFolderButton>
167
+ </Tooltip>
168
+ )}
169
+ <IconButton
170
+ aria-hidden
171
+ aria-label=""
172
+ tabIndex={-1}
173
+ variant="ghost"
174
+ colorTheme="greyLighter"
175
+ size="small"
176
+ onClick={() => {
177
+ if (!showTree) {
178
+ innerRef.current?.focus();
179
+ }
180
+ onToggleTree(!showTree);
181
+ }}>
182
+ {showTree ? <ChevronUp /> : <ChevronDown />}
183
+ </IconButton>
184
+ </StyledRow>
185
+ );
186
+ },
187
+ );
188
+
189
+ export default ComboboxButton;