@redocly/theme 0.66.0 → 0.67.0-next.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 (201) hide show
  1. package/lib/components/Admonition/Admonition.js +9 -9
  2. package/lib/components/Badge/Badge.d.ts +1 -1
  3. package/lib/components/Badge/Badge.js +4 -4
  4. package/lib/components/Button/Button.d.ts +1 -1
  5. package/lib/components/Button/Button.js +16 -17
  6. package/lib/components/Buttons/AIAssistantButton.js +2 -0
  7. package/lib/components/Catalog/CatalogActionsRow.js +3 -1
  8. package/lib/components/Catalog/CatalogAvatar.d.ts +3 -1
  9. package/lib/components/Catalog/CatalogAvatar.js +3 -3
  10. package/lib/components/Catalog/CatalogCardView/CatalogCard.js +4 -4
  11. package/lib/components/Catalog/CatalogEntity/CatalogEntityGraph/CatalogEntityRelationsNodeContent.js +7 -7
  12. package/lib/components/Catalog/CatalogEntity/CatalogEntityInfoBar.js +6 -6
  13. package/lib/components/Catalog/CatalogEntity/CatalogEntityProperties/CatalogEntityPropertyCard.js +2 -2
  14. package/lib/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityApiDescriptionRelations.js +4 -6
  15. package/lib/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityTeamRelations.js +3 -5
  16. package/lib/components/Catalog/CatalogEntityTypeIcon.js +15 -11
  17. package/lib/components/Catalog/CatalogEntityTypeTag.js +5 -5
  18. package/lib/components/Catalog/CatalogTableView/CatalogTableView.js +5 -3
  19. package/lib/components/CatalogClassic/CatalogClassic.d.ts +4 -2
  20. package/lib/components/CatalogClassic/CatalogClassic.js +3 -1
  21. package/lib/components/CodeBlock/CodeBlockContainer.js +16 -4
  22. package/lib/components/CodeBlock/CodeBlockControls.d.ts +2 -1
  23. package/lib/components/CodeBlock/CodeBlockControls.js +9 -7
  24. package/lib/components/CodeBlock/CodeBlockTabs.js +2 -2
  25. package/lib/components/Dropdown/Dropdown.js +6 -6
  26. package/lib/components/Dropdown/DropdownMenuItem.d.ts +1 -1
  27. package/lib/components/Feedback/Comment.js +3 -3
  28. package/lib/components/Feedback/Mood.js +3 -3
  29. package/lib/components/Filter/FilterContent.js +2 -2
  30. package/lib/components/Footer/Footer.js +2 -2
  31. package/lib/components/Footer/FooterColumn.js +2 -2
  32. package/lib/components/Footer/FooterItem.js +5 -5
  33. package/lib/components/Image/Image.js +2 -2
  34. package/lib/components/LastUpdated/LastUpdated.js +2 -2
  35. package/lib/components/Link/Link.d.ts +2 -19
  36. package/lib/components/Link/Link.js +2 -9
  37. package/lib/components/Loaders/Loading.js +2 -2
  38. package/lib/components/Loaders/SpinnerLoader.js +4 -4
  39. package/lib/components/Markdown/Markdown.d.ts +7 -10
  40. package/lib/components/Markdown/Markdown.js +6 -3
  41. package/lib/components/Marker/Marker.js +3 -3
  42. package/lib/components/Menu/MenuContainer.d.ts +2 -2
  43. package/lib/components/Menu/MenuContainer.js +9 -11
  44. package/lib/components/Menu/MenuItem.js +14 -14
  45. package/lib/components/Menu/MenuMobile.js +8 -8
  46. package/lib/components/Navbar/NavbarItem.js +7 -7
  47. package/lib/components/PageNavigation/NavigationButton.js +3 -3
  48. package/lib/components/Panel/PanelBody.d.ts +5 -5
  49. package/lib/components/Panel/PanelBody.js +6 -3
  50. package/lib/components/Panel/PanelHeader.d.ts +2 -5
  51. package/lib/components/Panel/PanelHeader.js +6 -2
  52. package/lib/components/Search/SearchAiMessage.js +10 -8
  53. package/lib/components/Search/SearchDialog.js +6 -0
  54. package/lib/components/Search/SearchSuggestedPages.js +2 -2
  55. package/lib/components/Select/Select.js +3 -1
  56. package/lib/components/Select/SelectInput.d.ts +1 -0
  57. package/lib/components/Select/SelectInput.js +8 -8
  58. package/lib/components/Sidebar/Sidebar.d.ts +4 -2
  59. package/lib/components/Sidebar/Sidebar.js +10 -8
  60. package/lib/components/SidebarActions/styled.d.ts +6 -6
  61. package/lib/components/SidebarActions/styled.js +12 -4
  62. package/lib/components/StatusCode/StatusCode.d.ts +6 -4
  63. package/lib/components/StatusCode/StatusCode.js +8 -2
  64. package/lib/components/Switch/Switch.js +13 -13
  65. package/lib/components/TableOfContent/TableOfContent.js +2 -2
  66. package/lib/components/Tag/Tag.js +11 -11
  67. package/lib/components/Tooltip/AnchorTooltip.js +26 -25
  68. package/lib/components/Tooltip/JsTooltip.js +5 -5
  69. package/lib/components/Typography/CompactTypography.d.ts +27 -11
  70. package/lib/components/Typography/CompactTypography.js +2 -2
  71. package/lib/components/Typography/Typography.d.ts +6 -2
  72. package/lib/components/Typography/Typography.js +18 -3
  73. package/lib/components/UserMenu/UserAvatar.js +5 -5
  74. package/lib/core/contexts/ThemeDataContext.d.ts +1 -1
  75. package/lib/core/hooks/feedback/use-report-dialog.d.ts +8 -5
  76. package/lib/core/styles/global.js +1 -0
  77. package/lib/core/templates/Markdown.js +5 -6
  78. package/lib/core/types/index.d.ts +1 -0
  79. package/lib/core/types/link.d.ts +19 -0
  80. package/lib/core/types/link.js +3 -0
  81. package/lib/core/utils/details.d.ts +1 -1
  82. package/lib/core/utils/details.js +3 -0
  83. package/lib/core/utils/dom.d.ts +0 -1
  84. package/lib/core/utils/dom.js +0 -9
  85. package/lib/core/utils/index.d.ts +0 -1
  86. package/lib/core/utils/index.js +0 -1
  87. package/lib/icons/AiStarsGradientIcon/AiStarsGradientIcon.d.ts +1 -1
  88. package/lib/icons/AiStarsGradientIcon/AiStarsGradientIcon.js +6 -1
  89. package/lib/icons/AiStarsIcon/AiStarsIcon.d.ts +1 -1
  90. package/lib/icons/AiStarsIcon/AiStarsIcon.js +6 -1
  91. package/lib/icons/MagicWandIcon/MagicWandIcon.d.ts +23 -0
  92. package/lib/icons/MagicWandIcon/MagicWandIcon.js +25 -0
  93. package/lib/icons/ReturnKeyIcon/ReturnKeyIcon.d.ts +25 -5
  94. package/lib/index.d.ts +1 -0
  95. package/lib/index.js +1 -0
  96. package/lib/layouts/DocumentationLayout.js +2 -2
  97. package/lib/layouts/ThreePanelLayout.d.ts +27 -7
  98. package/lib/layouts/ThreePanelLayout.js +11 -8
  99. package/lib/markdoc/components/CodeWalkthrough/CodeContainer.js +2 -2
  100. package/lib/markdoc/components/CodeWalkthrough/CodePanelHeader.js +2 -2
  101. package/lib/markdoc/components/CodeWalkthrough/CodePanelPreview.js +2 -2
  102. package/lib/markdoc/components/CodeWalkthrough/CodeStep.d.ts +4 -2
  103. package/lib/markdoc/components/CodeWalkthrough/CodeStep.js +6 -2
  104. package/lib/markdoc/components/Image/Image.js +3 -3
  105. package/lib/markdoc/components/Tabs/TabItemFragment.d.ts +9 -0
  106. package/lib/markdoc/components/Tabs/TabItemFragment.js +11 -0
  107. package/lib/markdoc/components/Tabs/TabList.d.ts +7 -4
  108. package/lib/markdoc/components/Tabs/TabList.js +6 -4
  109. package/lib/markdoc/components/Tabs/Tabs.d.ts +3 -9
  110. package/lib/markdoc/components/Tabs/Tabs.js +12 -5
  111. package/lib/markdoc/components/default.d.ts +1 -0
  112. package/lib/markdoc/components/default.js +1 -0
  113. package/lib/markdoc/tags/tab.js +1 -1
  114. package/lib/markdoc/tags/tabs.js +1 -1
  115. package/package.json +2 -3
  116. package/src/components/Admonition/Admonition.tsx +11 -11
  117. package/src/components/Badge/Badge.tsx +11 -6
  118. package/src/components/Button/Button.tsx +51 -21
  119. package/src/components/Buttons/AIAssistantButton.tsx +2 -0
  120. package/src/components/Catalog/CatalogActionsRow.tsx +3 -1
  121. package/src/components/Catalog/CatalogAvatar.tsx +6 -10
  122. package/src/components/Catalog/CatalogCardView/CatalogCard.tsx +6 -6
  123. package/src/components/Catalog/CatalogEntity/CatalogEntityGraph/CatalogEntityRelationsNodeContent.tsx +14 -14
  124. package/src/components/Catalog/CatalogEntity/CatalogEntityInfoBar.tsx +11 -11
  125. package/src/components/Catalog/CatalogEntity/CatalogEntityProperties/CatalogEntityPropertyCard.tsx +4 -4
  126. package/src/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityApiDescriptionRelations.tsx +8 -11
  127. package/src/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityTeamRelations.tsx +10 -9
  128. package/src/components/Catalog/CatalogEntityTypeIcon.tsx +22 -16
  129. package/src/components/Catalog/CatalogEntityTypeTag.tsx +8 -8
  130. package/src/components/Catalog/CatalogTableView/CatalogTableView.tsx +8 -6
  131. package/src/components/CatalogClassic/CatalogClassic.tsx +3 -1
  132. package/src/components/CodeBlock/CodeBlockContainer.tsx +23 -7
  133. package/src/components/CodeBlock/CodeBlockControls.tsx +16 -10
  134. package/src/components/CodeBlock/CodeBlockTabs.tsx +4 -4
  135. package/src/components/Dropdown/Dropdown.tsx +9 -9
  136. package/src/components/Dropdown/DropdownMenuItem.tsx +1 -1
  137. package/src/components/Feedback/Comment.tsx +5 -5
  138. package/src/components/Feedback/Mood.tsx +5 -5
  139. package/src/components/Filter/FilterContent.tsx +4 -4
  140. package/src/components/Filter/FilterPopover.tsx +1 -1
  141. package/src/components/Footer/Footer.tsx +4 -4
  142. package/src/components/Footer/FooterColumn.tsx +3 -3
  143. package/src/components/Footer/FooterItem.tsx +9 -9
  144. package/src/components/Image/Image.tsx +3 -3
  145. package/src/components/LastUpdated/LastUpdated.tsx +4 -4
  146. package/src/components/Link/Link.tsx +6 -51
  147. package/src/components/Loaders/Loading.tsx +3 -3
  148. package/src/components/Loaders/SpinnerLoader.tsx +5 -5
  149. package/src/components/Markdown/Markdown.tsx +7 -7
  150. package/src/components/Marker/Marker.tsx +4 -4
  151. package/src/components/Menu/MenuContainer.tsx +32 -16
  152. package/src/components/Menu/MenuItem.tsx +34 -29
  153. package/src/components/Menu/MenuMobile.tsx +12 -12
  154. package/src/components/Navbar/NavbarItem.tsx +13 -13
  155. package/src/components/PageNavigation/NavigationButton.tsx +4 -4
  156. package/src/components/Panel/PanelBody.tsx +7 -4
  157. package/src/components/Panel/PanelHeader.tsx +9 -4
  158. package/src/components/Search/SearchAiMessage.tsx +17 -15
  159. package/src/components/Search/SearchDialog.tsx +6 -0
  160. package/src/components/Search/SearchSuggestedPages.tsx +20 -5
  161. package/src/components/Select/Select.tsx +3 -1
  162. package/src/components/Select/SelectInput.tsx +10 -9
  163. package/src/components/Sidebar/Sidebar.tsx +15 -13
  164. package/src/components/SidebarActions/styled.ts +12 -4
  165. package/src/components/StatusCode/StatusCode.tsx +12 -4
  166. package/src/components/Switch/Switch.tsx +21 -21
  167. package/src/components/TableOfContent/TableOfContent.tsx +3 -3
  168. package/src/components/Tag/Tag.tsx +34 -27
  169. package/src/components/Tooltip/AnchorTooltip.tsx +50 -42
  170. package/src/components/Tooltip/JsTooltip.tsx +14 -13
  171. package/src/components/Typography/CompactTypography.tsx +4 -4
  172. package/src/components/Typography/Typography.tsx +21 -5
  173. package/src/components/UserMenu/UserAvatar.tsx +7 -7
  174. package/src/core/contexts/ThemeDataContext.tsx +1 -1
  175. package/src/core/hooks/feedback/use-report-dialog.ts +1 -5
  176. package/src/core/styles/dark.ts +1 -1
  177. package/src/core/styles/global.ts +1 -0
  178. package/src/core/templates/Markdown.tsx +6 -7
  179. package/src/core/types/index.ts +1 -0
  180. package/src/core/types/link.ts +20 -0
  181. package/src/core/utils/details.ts +4 -0
  182. package/src/core/utils/dom.ts +0 -8
  183. package/src/core/utils/index.ts +0 -1
  184. package/src/icons/AiStarsGradientIcon/AiStarsGradientIcon.tsx +9 -3
  185. package/src/icons/AiStarsIcon/AiStarsIcon.tsx +9 -3
  186. package/src/icons/MagicWandIcon/MagicWandIcon.tsx +26 -0
  187. package/src/icons/ReturnKeyIcon/ReturnKeyIcon.tsx +1 -1
  188. package/src/index.ts +1 -0
  189. package/src/layouts/DocumentationLayout.tsx +3 -3
  190. package/src/layouts/ThreePanelLayout.tsx +27 -14
  191. package/src/markdoc/components/CodeWalkthrough/CodeContainer.tsx +4 -4
  192. package/src/markdoc/components/CodeWalkthrough/CodePanelHeader.tsx +4 -4
  193. package/src/markdoc/components/CodeWalkthrough/CodePanelPreview.tsx +3 -3
  194. package/src/markdoc/components/CodeWalkthrough/CodeStep.tsx +6 -2
  195. package/src/markdoc/components/Image/Image.tsx +4 -4
  196. package/src/markdoc/components/Tabs/TabItemFragment.tsx +15 -0
  197. package/src/markdoc/components/Tabs/TabList.tsx +9 -6
  198. package/src/markdoc/components/Tabs/Tabs.tsx +21 -15
  199. package/src/markdoc/components/default.ts +1 -0
  200. package/src/markdoc/tags/tab.ts +1 -1
  201. package/src/markdoc/tags/tabs.ts +1 -1
@@ -1,7 +1,6 @@
1
- import React from 'react';
1
+ import React, { type JSX, type PropsWithChildren } from 'react';
2
2
  import styled, { keyframes } from 'styled-components';
3
3
 
4
- import type { JSX, PropsWithChildren } from 'react';
5
4
  import type { MenuItemsAnimation } from '@redocly/theme/core/types';
6
5
 
7
6
  export type MenuContainerProps = PropsWithChildren<{
@@ -11,8 +10,24 @@ export type MenuContainerProps = PropsWithChildren<{
11
10
  animation?: MenuItemsAnimation;
12
11
  }>;
13
12
 
14
- export function MenuContainer(props: MenuContainerProps): JSX.Element {
15
- return <MenuContainerComponent {...props} data-component-name="Menu/MenuContainer" />;
13
+ export function MenuContainer({
14
+ growContent,
15
+ className,
16
+ hidden,
17
+ animation,
18
+ children,
19
+ }: MenuContainerProps): JSX.Element {
20
+ return (
21
+ <MenuContainerComponent
22
+ data-component-name="Menu/MenuContainer"
23
+ $growContent={growContent === undefined ? true : growContent}
24
+ $animation={animation}
25
+ $hidden={hidden}
26
+ className={className}
27
+ >
28
+ {children}
29
+ </MenuContainerComponent>
30
+ );
16
31
  }
17
32
 
18
33
  const slideInRightAnimation = keyframes`
@@ -33,17 +48,18 @@ const slideInLeftAnimation = keyframes`
33
48
  }
34
49
  `;
35
50
 
36
- const MenuContainerComponent = styled.div.attrs<MenuContainerProps>(
37
- ({ growContent, className, animation }) => ({
38
- growContent: growContent === undefined ? true : growContent,
39
- className,
40
- animation,
41
- }),
42
- )<MenuContainerProps>`
43
- animation-name: ${({ animation }) =>
44
- animation === 'slideInRight'
51
+ const MenuContainerComponent = styled.div.attrs<{
52
+ 'data-component-name': string;
53
+ $growContent: boolean;
54
+ $animation: MenuItemsAnimation;
55
+ $hidden: boolean;
56
+ }>({
57
+ 'data-component-name': 'Menu/MenuContainer',
58
+ })`
59
+ animation-name: ${({ $animation }) =>
60
+ $animation === 'slideInRight'
45
61
  ? slideInRightAnimation
46
- : animation === 'slideInLeft'
62
+ : $animation === 'slideInLeft'
47
63
  ? slideInLeftAnimation
48
64
  : 'none'};
49
65
  animation-fill-mode: forwards;
@@ -51,8 +67,8 @@ const MenuContainerComponent = styled.div.attrs<MenuContainerProps>(
51
67
  animation-timing-function: ease;
52
68
  position: relative;
53
69
  overflow-y: auto;
54
- flex-grow: ${({ growContent }) => (growContent ? 1 : 0)};
70
+ flex-grow: ${({ $growContent }) => ($growContent ? 1 : 0)};
55
71
  padding-top: var(--menu-container-padding-top);
56
- display: ${({ hidden }) => (hidden ? 'none' : 'block')};
72
+ display: ${({ $hidden }) => ($hidden ? 'none' : 'block')};
57
73
  overscroll-behavior: contain;
58
74
  `;
@@ -78,11 +78,11 @@ export function MenuItem(props: React.PropsWithChildren<MenuItemProps>): JSX.Ele
78
78
 
79
79
  const label = item.label && (
80
80
  <MenuItemLabelWrapper
81
- active={item.active}
82
- deprecated={item.deprecated}
83
- depth={depth}
84
- withChevron={hasChevron}
85
- isSeparator={isSeparator}
81
+ $active={item.active}
82
+ $deprecated={item.deprecated}
83
+ $depth={depth}
84
+ $withChevron={hasChevron}
85
+ $isSeparator={isSeparator}
86
86
  onClick={handleOnClick}
87
87
  onKeyDown={handleExpandOnEnter}
88
88
  ref={labelRef}
@@ -158,12 +158,17 @@ export function MenuItem(props: React.PropsWithChildren<MenuItemProps>): JSX.Ele
158
158
  label
159
159
  )}
160
160
  {isNested ? (
161
- <MenuItemNestedWrapper depth={depth} ref={nestedMenuRef} style={style}>
161
+ <MenuItemNestedWrapper
162
+ $isExpanded={isExpanded}
163
+ $depth={depth}
164
+ ref={nestedMenuRef}
165
+ style={style}
166
+ >
162
167
  {isExpanded || !canUnmount ? props.children : null}
163
168
  </MenuItemNestedWrapper>
164
169
  ) : null}
165
170
  {item.separatorLine ? (
166
- <MenuItemSeparatorLine depth={depth} linePosition={item.linePosition} />
171
+ <MenuItemSeparatorLine $depth={depth} $linePosition={item.linePosition} />
167
172
  ) : null}
168
173
  </MenuItemWrapper>
169
174
  );
@@ -233,8 +238,8 @@ const MenuItemWrapper = styled.div`
233
238
  `;
234
239
 
235
240
  const MenuItemNestedWrapper = styled.div<{
236
- isExpanded?: boolean;
237
- depth?: number;
241
+ $isExpanded?: boolean;
242
+ $depth?: number;
238
243
  }>`
239
244
  order: 1;
240
245
  position: relative;
@@ -249,23 +254,23 @@ const MenuItemNestedWrapper = styled.div<{
249
254
  bottom: var(--spacing-unit);
250
255
  top: 0;
251
256
  z-index: var(--z-index-surface);
252
- left: ${({ depth }) =>
257
+ left: ${({ $depth }) =>
253
258
  `calc(
254
259
  var(--menu-item-label-margin-horizontal) +
255
260
  var(--menu-item-padding-horizontal) +
256
261
  (var(--menu-item-label-chevron-size) / 2 - 1px) +
257
- var(--menu-item-nested-offset) * ${depth})
262
+ var(--menu-item-nested-offset) * ${$depth})
258
263
  `};
259
264
  border: 0.5px solid var(--menu-item-border-color-hover);
260
265
  }
261
266
  `;
262
267
 
263
268
  const MenuItemLabelWrapper = styled.li<{
264
- active?: boolean;
265
- depth?: number;
266
- withChevron?: boolean;
267
- deprecated?: boolean;
268
- isSeparator?: boolean;
269
+ $active?: boolean;
270
+ $depth?: number;
271
+ $withChevron?: boolean;
272
+ $deprecated?: boolean;
273
+ $isSeparator?: boolean;
269
274
  }>`
270
275
  display: flex;
271
276
  position: relative;
@@ -279,11 +284,11 @@ const MenuItemLabelWrapper = styled.li<{
279
284
  padding: var(--menu-item-label-padding);
280
285
  gap: var(--menu-item-label-gap);
281
286
 
282
- padding-left: ${({ withChevron, depth, isSeparator }) =>
287
+ padding-left: ${({ $withChevron, $depth, $isSeparator }) =>
283
288
  `calc(
284
289
  var(--menu-item-padding-horizontal) +
285
- ${!withChevron ? 'var(--menu-item-label-chevron-offset) + ' + (isSeparator ? 'var(--menu-item-separator-offest)' : '0px') : '0px'} +
286
- ${depth ? 'var(--menu-item-nested-offset) * ' + depth : '0px'}
290
+ ${!$withChevron ? 'var(--menu-item-label-chevron-offset) + ' + ($isSeparator ? 'var(--menu-item-separator-offest)' : '0px') : '0px'} +
291
+ ${$depth ? 'var(--menu-item-nested-offset) * ' + $depth : '0px'}
287
292
  )`};
288
293
 
289
294
  &:hover {
@@ -298,10 +303,10 @@ const MenuItemLabelWrapper = styled.li<{
298
303
  }
299
304
  }
300
305
 
301
- ${({ active, deprecated }) =>
302
- active &&
306
+ ${({ $active, $deprecated }) =>
307
+ $active &&
303
308
  css`
304
- color: ${deprecated ? 'var(--menu-content-color-disabled)' : 'var(--menu-item-color-active)'};
309
+ color: ${$deprecated ? 'var(--menu-content-color-disabled)' : 'var(--menu-item-color-active)'};
305
310
  background-color: var(--menu-item-bg-color-active);
306
311
  font-weight: var(--menu-item-font-weight-active);
307
312
 
@@ -318,8 +323,8 @@ const MenuItemLabelWrapper = styled.li<{
318
323
  }
319
324
  `};
320
325
 
321
- ${({ deprecated }) =>
322
- deprecated &&
326
+ ${({ $deprecated }) =>
327
+ $deprecated &&
323
328
  css`
324
329
  color: var(--menu-content-color-disabled);
325
330
 
@@ -360,19 +365,19 @@ const MenuItemLink = styled(Link)`
360
365
  `;
361
366
 
362
367
  const MenuItemSeparatorLine = styled.div<{
363
- depth?: number;
364
- linePosition?: string;
368
+ $depth?: number;
369
+ $linePosition?: string;
365
370
  }>`
366
371
  height: var(--menu-item-separator-line-height);
367
372
  background-color: var(--menu-item-separator-line-bg-color);
368
- margin: ${({ depth }) => `
373
+ margin: ${({ $depth }) => `
369
374
  var(--menu-item-padding-vertical)
370
375
  var(--sidebar-margin-horizontal)
371
376
  var(--menu-item-padding-vertical)
372
377
  calc(var(--sidebar-margin-horizontal) +
373
- ${depth ? 'var(--menu-item-nested-offset) * ' + depth : '0px'})
378
+ ${$depth ? 'var(--menu-item-nested-offset) * ' + $depth : '0px'})
374
379
  `};
375
- order: ${({ linePosition }) => (linePosition === 'top' ? 0 : 1)};
380
+ order: ${({ $linePosition }) => ($linePosition === 'top' ? 0 : 1)};
376
381
  `;
377
382
 
378
383
  const MenuItemLabel = styled.span`
@@ -48,9 +48,9 @@ export function MenuMobile({ className, hideUserProfile }: MobileMenuProps): JSX
48
48
 
49
49
  return (
50
50
  <MobileMenuWrapper data-component-name="Menu/MenuMobile" className={className}>
51
- <ScrollableArea isButtonsSectionVisible={!!isButtonsSectionVisible}>
51
+ <ScrollableArea $isButtonsSectionVisible={!!isButtonsSectionVisible}>
52
52
  {isButtonsSectionVisible && (
53
- <ButtonsSection alignRight={!prevLevelName && !!nextLevelName}>
53
+ <ButtonsSection $alignRight={!prevLevelName && !!nextLevelName}>
54
54
  {prevLevelName && (
55
55
  <ControlButton
56
56
  data-testid="control-button"
@@ -60,7 +60,7 @@ export function MenuMobile({ className, hideUserProfile }: MobileMenuProps): JSX
60
60
  }}
61
61
  >
62
62
  <ChevronLeftIcon size="12px" color="--tree-content-color-default" />
63
- <ControlButtonLabel paddingDirection="left">{prevLevelName}</ControlButtonLabel>
63
+ <ControlButtonLabel $paddingDirection="left">{prevLevelName}</ControlButtonLabel>
64
64
  </ControlButton>
65
65
  )}
66
66
  {nextLevelName && (
@@ -68,7 +68,7 @@ export function MenuMobile({ className, hideUserProfile }: MobileMenuProps): JSX
68
68
  data-testid="control-button"
69
69
  onClick={() => setMenuLevel(menuLevel + 1)}
70
70
  >
71
- <ControlButtonLabel paddingDirection="right">{nextLevelName}</ControlButtonLabel>
71
+ <ControlButtonLabel $paddingDirection="right">{nextLevelName}</ControlButtonLabel>
72
72
  <ChevronRightIcon size="12px" color="--tree-content-color-default" />
73
73
  </ControlButton>
74
74
  )}
@@ -117,14 +117,14 @@ const MobileMenuWrapper = styled.div`
117
117
  }
118
118
  `;
119
119
 
120
- const ScrollableArea = styled.div<{ isButtonsSectionVisible: boolean }>`
121
- padding-top: ${({ isButtonsSectionVisible }) =>
122
- isButtonsSectionVisible ? '0px' : 'var(--menu-mobile-padding-top)'};
120
+ const ScrollableArea = styled.div<{ $isButtonsSectionVisible: boolean }>`
121
+ padding-top: ${({ $isButtonsSectionVisible }) =>
122
+ $isButtonsSectionVisible ? '0px' : 'var(--menu-mobile-padding-top)'};
123
123
  overflow-y: scroll;
124
124
  flex-grow: 1;
125
125
  `;
126
126
 
127
- const ButtonsSection = styled.div<{ alignRight: boolean }>`
127
+ const ButtonsSection = styled.div<{ $alignRight: boolean }>`
128
128
  align-items: center;
129
129
  display: flex;
130
130
  justify-content: space-between;
@@ -132,7 +132,7 @@ const ButtonsSection = styled.div<{ alignRight: boolean }>`
132
132
  margin: 0 0 var(--spacing-sm) 0;
133
133
  background: var(--layer-color);
134
134
  gap: var(--spacing-xs);
135
- ${({ alignRight }) => alignRight && 'justify-content: flex-end'};
135
+ ${({ $alignRight }) => $alignRight && 'justify-content: flex-end'};
136
136
  `;
137
137
 
138
138
  const MenuWrapper = styled.div`
@@ -166,10 +166,10 @@ const ControlButton = styled.li`
166
166
  }
167
167
  `;
168
168
 
169
- const ControlButtonLabel = styled.span<{ paddingDirection: 'right' | 'left' }>`
169
+ const ControlButtonLabel = styled.span<{ $paddingDirection: 'right' | 'left' }>`
170
170
  vertical-align: middle;
171
- ${({ paddingDirection }) => paddingDirection === 'left' && 'padding-left: 8px'};
172
- ${({ paddingDirection }) => paddingDirection === 'right' && 'padding-right: 8px'};
171
+ ${({ $paddingDirection }) => $paddingDirection === 'left' && 'padding-left: 8px'};
172
+ ${({ $paddingDirection }) => $paddingDirection === 'right' && 'padding-right: 8px'};
173
173
  `;
174
174
 
175
175
  const ProductNameWrapper = styled.div`
@@ -4,7 +4,7 @@ import { useLocation } from 'react-router-dom';
4
4
 
5
5
  import type { JSX } from 'react';
6
6
  import type { ResolvedNavItem, ResolvedNavLinkItem, ResolvedNavGroupItem } from '@redocly/config';
7
- import type { LinkProps } from '@redocly/theme/components/Link/Link';
7
+ import type { LinkProps } from '@redocly/theme/core/types';
8
8
 
9
9
  import { DropdownMenu } from '@redocly/theme/components/Dropdown/DropdownMenu';
10
10
  import { DropdownMenuItem } from '@redocly/theme/components/Dropdown/DropdownMenuItem';
@@ -45,7 +45,7 @@ export function NavbarItem({ navItem, className }: NavbarItemProps): JSX.Element
45
45
  const itemContent = (
46
46
  <NavbarMenuItem
47
47
  as={item.link ? Link : undefined}
48
- active={isActive}
48
+ $active={isActive}
49
49
  className={className}
50
50
  onClick={() =>
51
51
  telemetry.sendNavbarMenuItemClickedMessage([{ object: 'menu_item', type: item.type }])
@@ -103,7 +103,7 @@ const NavbarMenuItemDropdown = styled(Dropdown)`
103
103
  --dropdown-menu-item-separator-line-height: var(--navbar-separator-line-height);
104
104
  `;
105
105
 
106
- const NavbarMenuItem = styled.li<LinkProps & { active?: boolean }>`
106
+ const NavbarMenuItem = styled.li<LinkProps & { $active: boolean }>`
107
107
  display: inline-block;
108
108
  padding: var(--navbar-item-padding);
109
109
  text-align: center;
@@ -111,21 +111,21 @@ const NavbarMenuItem = styled.li<LinkProps & { active?: boolean }>`
111
111
  font-weight: var(--navbar-item-font-weight);
112
112
 
113
113
  border-radius: var(--navbar-item-border-radius);
114
- border-bottom: ${({ active }) =>
115
- active ? 'var(--navbar-item-bottom-border-active)' : 'var(--navbar-item-bottom-border)'};
114
+ border-bottom: ${({ $active }) =>
115
+ $active ? 'var(--navbar-item-bottom-border-active)' : 'var(--navbar-item-bottom-border)'};
116
116
 
117
- background: ${({ active }) => active && 'var(--navbar-item-bg-color-active)'};
118
- color: ${({ active }) =>
119
- active ? 'var(--navbar-item-text-color-active)' : 'var(--navbar-text-color)'};
120
- text-decoration: ${({ active }) =>
121
- active ? 'var(--navbar-item-text-decoration-active)' : 'none'};
117
+ background: ${({ $active }) => $active && 'var(--navbar-item-bg-color-active)'};
118
+ color: ${({ $active }) =>
119
+ $active ? 'var(--navbar-item-text-color-active)' : 'var(--navbar-text-color)'};
120
+ text-decoration: ${({ $active }) =>
121
+ $active ? 'var(--navbar-item-text-decoration-active)' : 'none'};
122
122
 
123
123
  &:hover {
124
124
  color: var(--navbar-item-text-color-hover);
125
125
  text-decoration: var(--navbar-item-text-decoration-hover);
126
- border-bottom: ${({ active }) => !active && 'var(--navbar-item-bottom-border-hover)'};
127
- background: ${({ active }) =>
128
- active ? 'var(--navbar-item-bg-color-active)' : 'var(--navbar-item-bg-color-hover)'};
126
+ border-bottom: ${({ $active }) => !$active && 'var(--navbar-item-bottom-border-hover)'};
127
+ background: ${({ $active }) =>
128
+ $active ? 'var(--navbar-item-bg-color-active)' : 'var(--navbar-item-bg-color-hover)'};
129
129
  }
130
130
  `;
131
131
 
@@ -33,7 +33,7 @@ export function NavigationButton({
33
33
  <NavigationButtonWrapper
34
34
  data-component-name="PageNavigation/NavigationButton"
35
35
  data-translation-key={translationKey}
36
- position={position}
36
+ $position={position}
37
37
  >
38
38
  <PageNavigationTitle>{label}</PageNavigationTitle>
39
39
  <Button to={link} extraClass={className} variant="link" icon={icon} iconPosition={position}>
@@ -44,13 +44,13 @@ export function NavigationButton({
44
44
  }
45
45
 
46
46
  const NavigationButtonWrapper = styled.div<{
47
- position: NavigationButtonPosition;
47
+ $position: NavigationButtonPosition;
48
48
  }>`
49
49
  display: flex;
50
50
  flex-direction: column;
51
51
  width: var(--page-navigation-button-width);
52
- text-align: ${({ position }) => position};
53
- margin: ${({ position }) => (position === 'right' ? '0 0 0 auto' : '0 auto 0 0')};
52
+ text-align: ${({ $position }) => $position};
53
+ margin: ${({ $position }) => ($position === 'right' ? '0 0 0 auto' : '0 auto 0 0')};
54
54
  padding: var(--page-navigation-button-padding);
55
55
  gap: var(--page-navigation-button-gap);
56
56
  border: var(--page-navigation-button-border);
@@ -18,10 +18,13 @@ export type PanelBodyProps = {
18
18
  hidden?: boolean;
19
19
  };
20
20
 
21
- export const PanelBody = styled.div.attrs<{ className?: string }>(({ className }) => ({
22
- 'data-component-name': 'Panel/PanelBody',
23
- className,
24
- }))<PanelBodyProps>`
21
+ export const PanelBody = styled.div
22
+ .withConfig({
23
+ shouldForwardProp: (prop) => !['animate', 'hidden'].includes(prop),
24
+ })
25
+ .attrs<{ 'data-component-name': string }>({
26
+ 'data-component-name': 'Panel/PanelBody',
27
+ })<PanelBodyProps>`
25
28
  ${({ animate }) => animate && showPanelAnimation};
26
29
  ${({ hidden }) => hidden && 'visibility: hidden'};
27
30
 
@@ -7,12 +7,17 @@ export type PanelHeaderProps = {
7
7
  expanded?: boolean;
8
8
  disabled?: boolean;
9
9
  toggle?: (e: BaseSyntheticEvent) => void;
10
+ className?: string;
10
11
  };
11
12
 
12
- export const PanelHeader = styled.div.attrs<{ className?: string }>(({ className }) => ({
13
- 'data-component-name': 'Panel/PanelHeader',
14
- className,
15
- }))<PanelHeaderProps>`
13
+ export const PanelHeader = styled.div
14
+ .withConfig({
15
+ shouldForwardProp: (prop) => !['isExpandable', 'expanded', 'disabled', 'toggle'].includes(prop),
16
+ })
17
+ .attrs<PanelHeaderProps>(({ toggle }) => ({
18
+ 'data-component-name': 'Panel/PanelHeader',
19
+ onClick: toggle,
20
+ }))`
16
21
  display: flex;
17
22
  flex-wrap: wrap;
18
23
  gap: var(--spacing-unit);
@@ -81,7 +81,9 @@ function SearchAiMessageComponent({
81
81
  try {
82
82
  telemetry.sendSearchAIFeedbackMessage([
83
83
  {
84
+ id: messageId,
84
85
  object: 'feedback',
86
+ uri: `urn:redocly:realm:ui:feedback:${messageId}`,
85
87
  feedback: feedbackValue,
86
88
  messageId,
87
89
  reason: dislikeReason,
@@ -111,7 +113,7 @@ function SearchAiMessageComponent({
111
113
  return (
112
114
  <SearchAiMessageWrapper
113
115
  data-component-name="Search/SearchAiMessage"
114
- role={role}
116
+ $role={role}
115
117
  className={className}
116
118
  data-testid="search-ai-message"
117
119
  >
@@ -127,7 +129,7 @@ function SearchAiMessageComponent({
127
129
  <MessageContentWrapper>
128
130
  {role === AiSearchConversationRole.ASSISTANT ? (
129
131
  <>
130
- <MessageWrapper role={role}>
132
+ <MessageWrapper $role={role}>
131
133
  {contentSegments.map((segment, index) => {
132
134
  if (segment.type === 'tool') {
133
135
  const toolCallCompleted = Boolean(segment.toolCall.result);
@@ -212,7 +214,7 @@ function SearchAiMessageComponent({
212
214
  )}
213
215
  </>
214
216
  ) : (
215
- <MessageWrapper role={role}>{content}</MessageWrapper>
217
+ <MessageWrapper $role={role}>{content}</MessageWrapper>
216
218
  )}
217
219
  </MessageContentWrapper>
218
220
  </SearchAiMessageWrapper>
@@ -247,13 +249,13 @@ export const SearchAiMessage = memo(SearchAiMessageComponent, (prevProps, nextPr
247
249
  );
248
250
  });
249
251
 
250
- const SearchAiMessageWrapper = styled.div<{ role: string }>`
252
+ const SearchAiMessageWrapper = styled.div<{ $role: string }>`
251
253
  display: flex;
252
254
  flex-direction: row;
253
255
  align-items: flex-start;
254
256
  width: 100%;
255
- justify-content: ${({ role }) =>
256
- role === AiSearchConversationRole.USER ? 'flex-end' : 'flex-start'};
257
+ justify-content: ${({ $role }) =>
258
+ $role === AiSearchConversationRole.USER ? 'flex-end' : 'flex-start'};
257
259
  `;
258
260
 
259
261
  const MessageContentWrapper = styled.div`
@@ -281,9 +283,9 @@ const ResponseText = styled(Markdown)`
281
283
  }
282
284
  `;
283
285
 
284
- const MessageWrapper = styled.div<{ role: string }>`
285
- padding: ${({ role }) =>
286
- role === AiSearchConversationRole.USER
286
+ const MessageWrapper = styled.div<{ $role: string }>`
287
+ padding: ${({ $role }) =>
288
+ $role === AiSearchConversationRole.USER
287
289
  ? 'var(--spacing-sm)'
288
290
  : 'var(--spacing-sm) var(--spacing-sm) var(--spacing-xs) var(--spacing-sm)'};
289
291
  border-radius: var(--border-radius-lg);
@@ -291,14 +293,14 @@ const MessageWrapper = styled.div<{ role: string }>`
291
293
  max-width: 100%;
292
294
  word-wrap: break-word;
293
295
  white-space: pre-wrap;
294
- background-color: ${({ role }) =>
295
- role === AiSearchConversationRole.USER
296
+ background-color: ${({ $role }) =>
297
+ $role === AiSearchConversationRole.USER
296
298
  ? 'var(--search-ai-user-bg-color)'
297
299
  : 'var(--search-ai-assistant-bg-color)'};
298
- border: ${({ role }) =>
299
- role === AiSearchConversationRole.USER ? 'none' : 'var(--search-ai-assistant-border)'};
300
- color: ${({ role }) =>
301
- role === AiSearchConversationRole.USER
300
+ border: ${({ $role }) =>
301
+ $role === AiSearchConversationRole.USER ? 'none' : 'var(--search-ai-assistant-border)'};
302
+ color: ${({ $role }) =>
303
+ $role === AiSearchConversationRole.USER
302
304
  ? 'var(--search-ai-user-text-color)'
303
305
  : 'var(--search-ai-assistant-text-color)'};
304
306
  `;
@@ -259,7 +259,9 @@ export function SearchDialog({
259
259
  }
260
260
  telemetry.sendSearchAiOpenedMessage([
261
261
  {
262
+ id: 'searchAiButton',
262
263
  object: 'search',
264
+ uri: 'urn:redocly:realm:ui:search:searchAiButton',
263
265
  method: 'ai_search_button',
264
266
  },
265
267
  ]);
@@ -353,7 +355,9 @@ export function SearchDialog({
353
355
  }
354
356
  telemetry.sendSearchAiOpenedMessage([
355
357
  {
358
+ id: 'searchAiInput',
356
359
  object: 'search',
360
+ uri: 'urn:redocly:realm:ui:search:searchAiInput',
357
361
  method: 'ai_search_input',
358
362
  },
359
363
  ]);
@@ -366,7 +370,9 @@ export function SearchDialog({
366
370
  }
367
371
  telemetry.sendSearchAiOpenedMessage([
368
372
  {
373
+ id: 'searchAiInput',
369
374
  object: 'search',
375
+ uri: 'urn:redocly:realm:ui:search:searchAiInput',
370
376
  method: 'ai_search_input',
371
377
  },
372
378
  ]);
@@ -11,8 +11,17 @@ export type SearchSuggestedPagesProps = {
11
11
  className?: string;
12
12
  };
13
13
 
14
+ type SuggestedPage = {
15
+ link?: string;
16
+ label?: string;
17
+ labelTranslationKey?: string;
18
+ external?: boolean;
19
+ target?: '_self' | '_blank';
20
+ languageInsensitive?: boolean;
21
+ };
22
+
14
23
  export function SearchSuggestedPages({ className }: SearchSuggestedPagesProps): JSX.Element | null {
15
- const pages = useSuggestedPages();
24
+ const pages: SuggestedPage[] = useSuggestedPages();
16
25
  const { useTranslate } = useThemeHooks();
17
26
  const { translate } = useTranslate();
18
27
  if (!pages.length) return null;
@@ -23,12 +32,18 @@ export function SearchSuggestedPages({ className }: SearchSuggestedPagesProps):
23
32
  {translate('search.suggested', 'Suggested pages')}
24
33
  </SearchSuggestedTitle>
25
34
  <SearchSuggestedItems>
26
- {pages.map((page) =>
27
- page.link ? (
28
- <SearchSuggestedItem key={page.label} to={page.link} {...page}>
35
+ {pages.map(({ link, label, external, target, languageInsensitive, labelTranslationKey }) =>
36
+ link ? (
37
+ <SearchSuggestedItem
38
+ key={label ?? link}
39
+ to={link}
40
+ external={external}
41
+ target={target}
42
+ languageInsensitive={languageInsensitive}
43
+ >
29
44
  <SearchSuggestedItemWrapper>
30
45
  <RecentlyViewedIcon color="--search-item-text-color" />
31
- {page.label}
46
+ {translate(labelTranslationKey, label)}
32
47
  </SearchSuggestedItemWrapper>
33
48
  </SearchSuggestedItem>
34
49
  ) : null,
@@ -270,7 +270,9 @@ export function Select<T>(props: SelectProps<T>): JSX.Element {
270
270
  );
271
271
  }
272
272
 
273
- export const SelectWrapper = styled.div<{ disabled?: boolean }>`
273
+ export const SelectWrapper = styled.div.withConfig({
274
+ shouldForwardProp: (prop) => prop !== 'disabled',
275
+ })<{ disabled?: boolean }>`
274
276
  display: flex;
275
277
  position: relative;
276
278
  font-size: var(--select-font-size);
@@ -17,6 +17,7 @@ type SelectInputProps<T> = {
17
17
  stickyValue: any;
18
18
  onlyIcon?: boolean;
19
19
  icon?: React.ReactNode;
20
+ iconPosition?: string;
20
21
  customIcon?: React.ReactNode;
21
22
  placeholder?: string;
22
23
  multiple?: boolean;
@@ -54,6 +55,7 @@ export function SelectInput<T>(props: SelectInputProps<T>): React.ReactNode {
54
55
  searchValue,
55
56
  inputBlurHandler,
56
57
  inputFocusHandler,
58
+ inputRef: forwardedInputRef,
57
59
  } = props;
58
60
  const inputRef = useRef<HTMLInputElement | null>(null);
59
61
 
@@ -122,15 +124,15 @@ export function SelectInput<T>(props: SelectInputProps<T>): React.ReactNode {
122
124
 
123
125
  inputRef.current = input;
124
126
 
125
- if (!props.inputRef) return;
127
+ if (!forwardedInputRef) return;
126
128
 
127
- if (typeof props.inputRef === 'function') {
128
- props.inputRef(input);
129
+ if (typeof forwardedInputRef === 'function') {
130
+ forwardedInputRef(input);
129
131
  } else {
130
- props.inputRef.current = input;
132
+ forwardedInputRef.current = input;
131
133
  }
132
134
  }}
133
- width={multiple ? (!searchValue && selectedOptions.length ? '10px' : 'auto') : '100%'}
135
+ $width={multiple ? (!searchValue && selectedOptions.length ? '10px' : 'auto') : '100%'}
134
136
  tabIndex={0}
135
137
  onFocus={(e) => {
136
138
  e.stopPropagation();
@@ -155,7 +157,6 @@ export function SelectInput<T>(props: SelectInputProps<T>): React.ReactNode {
155
157
 
156
158
  return (
157
159
  <SelectInputWrapper
158
- {...props}
159
160
  id={id}
160
161
  onFocus={onFocusHandler}
161
162
  onClick={onClickHandler}
@@ -218,9 +219,9 @@ const SelectInputTag = styled(Tag)`
218
219
  --tag-content-padding: 0;
219
220
  `;
220
221
 
221
- const SelectInternalInput = styled.input.attrs<{ width?: string }>({
222
+ const SelectInternalInput = styled.input.attrs({
222
223
  type: 'text',
223
- })`
224
+ })<{ $width?: string }>`
224
225
  outline: none;
225
226
  border-radius: var(--select-input-border-radius);
226
227
  border: none;
@@ -233,7 +234,7 @@ const SelectInternalInput = styled.input.attrs<{ width?: string }>({
233
234
  color: var(--select-input-placeholder-color);
234
235
  }
235
236
 
236
- width: ${({ width }) => width || 'auto'};
237
+ width: ${({ $width }) => $width || 'auto'};
237
238
  `;
238
239
 
239
240
  const SelectInternalInputPlaceholder = styled.div`