@redocly/theme 0.59.0-next.0 → 0.59.0-next.2

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 (196) hide show
  1. package/lib/components/Accordion/Accordion.d.ts +12 -0
  2. package/lib/components/Accordion/Accordion.js +85 -0
  3. package/lib/components/Accordion/AccordionBody.d.ts +8 -0
  4. package/lib/components/Accordion/AccordionBody.js +73 -0
  5. package/lib/components/Accordion/AccordionHeader.d.ts +10 -0
  6. package/lib/components/Accordion/AccordionHeader.js +37 -0
  7. package/lib/components/Accordion/AccordionTitle.d.ts +6 -0
  8. package/lib/components/Accordion/AccordionTitle.js +20 -0
  9. package/lib/components/Accordion/variables.d.ts +1 -0
  10. package/lib/components/Accordion/variables.js +59 -0
  11. package/lib/components/Admonition/Admonition.js +17 -7
  12. package/lib/components/Badge/Badge.js +17 -7
  13. package/lib/components/Breadcrumbs/Breadcrumb.js +17 -7
  14. package/lib/components/Breadcrumbs/BreadcrumbDropdown.js +17 -7
  15. package/lib/components/Button/Button.js +17 -7
  16. package/lib/components/Buttons/AIAssistantButton.d.ts +2 -0
  17. package/lib/components/Buttons/AIAssistantButton.js +135 -0
  18. package/lib/components/Buttons/CopyButton.js +17 -7
  19. package/lib/components/Buttons/variables.d.ts +1 -0
  20. package/lib/components/Buttons/variables.dark.d.ts +1 -0
  21. package/lib/components/Buttons/variables.dark.js +10 -0
  22. package/lib/components/Buttons/variables.js +51 -0
  23. package/lib/components/Catalog/Catalog.d.ts +6 -0
  24. package/lib/components/Catalog/Catalog.js +9 -8
  25. package/lib/components/Catalog/CatalogEntities.js +17 -7
  26. package/lib/components/Catalog/CatalogEntity/CatalogEntityGraph/CatalogEntityRelationsGraph.js +17 -7
  27. package/lib/components/Catalog/CatalogEntity/CatalogEntityGraph/CatalogEntityRelationsGraph.lazy.js +17 -7
  28. package/lib/components/Catalog/CatalogEntity/CatalogEntityMetadata.js +17 -7
  29. package/lib/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityApiDescriptionRelations.js +1 -1
  30. package/lib/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityRelations.js +17 -7
  31. package/lib/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityTeamRelations.js +1 -1
  32. package/lib/components/Catalog/CatalogEntity/CatalogEntitySchema.js +17 -7
  33. package/lib/components/Catalog/CatalogFilter/CatalogFilter.d.ts +6 -0
  34. package/lib/components/Catalog/CatalogFilter/CatalogFilter.js +35 -0
  35. package/lib/components/Catalog/CatalogFilter/CatalogFilterCheckboxes.d.ts +6 -0
  36. package/lib/components/Catalog/CatalogFilter/CatalogFilterCheckboxes.js +152 -0
  37. package/lib/components/Catalog/CatalogFilter/CatalogFilterContent.d.ts +13 -0
  38. package/lib/components/Catalog/CatalogFilter/CatalogFilterContent.js +102 -0
  39. package/lib/components/Catalog/CatalogFilter/CatalogFilterDateRange.d.ts +6 -0
  40. package/lib/components/Catalog/CatalogFilter/CatalogFilterDateRange.js +121 -0
  41. package/lib/components/Catalog/CatalogFilter/CatalogFilterSelect.d.ts +6 -0
  42. package/lib/components/Catalog/CatalogFilter/CatalogFilterSelect.js +126 -0
  43. package/lib/components/Catalog/CatalogSelector.js +0 -1
  44. package/lib/components/Catalog/CatalogSortButton.js +17 -7
  45. package/lib/components/Catalog/CatalogTableView/CatalogTableHeaderCell.js +17 -7
  46. package/lib/components/Catalog/CatalogViewModeToggle.js +17 -7
  47. package/lib/components/Catalog/variables.js +0 -1
  48. package/lib/components/CatalogClassic/CatalogClassicActions.js +17 -7
  49. package/lib/components/CatalogClassic/CatalogClassicCard.js +17 -7
  50. package/lib/components/CatalogClassic/CatalogClassicHighlight.js +17 -7
  51. package/lib/components/CatalogClassic/CatalogClassicVirtualizedGroups.js +17 -7
  52. package/lib/components/CodeBlock/CodeBlock.js +17 -7
  53. package/lib/components/CodeBlock/CodeBlockContainer.js +17 -7
  54. package/lib/components/CodeBlock/CodeBlockTabs.js +17 -7
  55. package/lib/components/Dropdown/Dropdown.d.ts +16 -2
  56. package/lib/components/Dropdown/Dropdown.js +22 -12
  57. package/lib/components/Dropdown/DropdownMenuItem.js +17 -7
  58. package/lib/components/Feedback/Comment.js +17 -7
  59. package/lib/components/Feedback/Feedback.js +17 -7
  60. package/lib/components/Feedback/Mood.js +17 -7
  61. package/lib/components/Feedback/Rating.js +17 -7
  62. package/lib/components/Feedback/Reasons.js +17 -7
  63. package/lib/components/Feedback/Scale.js +17 -7
  64. package/lib/components/Feedback/Sentiment.js +17 -7
  65. package/lib/components/Feedback/Stars.js +17 -7
  66. package/lib/components/Filter/FilterContent.js +17 -7
  67. package/lib/components/Filter/FilterInput.d.ts +1 -0
  68. package/lib/components/Filter/FilterInput.js +19 -9
  69. package/lib/components/Filter/FilterOptions.js +2 -0
  70. package/lib/components/Filter/variables.js +7 -4
  71. package/lib/components/Image/Image.js +17 -7
  72. package/lib/components/JsonViewer/JsonViewer.js +17 -7
  73. package/lib/components/JsonViewer/helpers.js +17 -7
  74. package/lib/components/LastUpdated/LastUpdated.js +17 -7
  75. package/lib/components/Link/Link.js +17 -7
  76. package/lib/components/Markdown/Markdown.js +17 -7
  77. package/lib/components/Marker/Marker.js +17 -7
  78. package/lib/components/Menu/MenuContainer.js +17 -7
  79. package/lib/components/Menu/MenuItem.js +18 -8
  80. package/lib/components/Menu/MenuMobile.js +17 -7
  81. package/lib/components/PageActions/PageActions.js +17 -7
  82. package/lib/components/PageNavigation/NextButton.js +17 -7
  83. package/lib/components/Panel/Panel.js +17 -7
  84. package/lib/components/Panel/PanelBody.js +17 -7
  85. package/lib/components/Search/FilterFields/SearchFilterFieldSelect.js +17 -7
  86. package/lib/components/Search/SearchAiConversationInput.d.ts +2 -1
  87. package/lib/components/Search/SearchAiConversationInput.js +28 -10
  88. package/lib/components/Search/SearchAiDialog.js +19 -10
  89. package/lib/components/Search/SearchAiResponse.js +2 -3
  90. package/lib/components/Search/SearchDialog.d.ts +2 -1
  91. package/lib/components/Search/SearchDialog.js +25 -12
  92. package/lib/components/Search/SearchFilter.js +17 -7
  93. package/lib/components/Search/SearchGroups.js +17 -7
  94. package/lib/components/Search/SearchHighlight.js +17 -7
  95. package/lib/components/Search/SearchItem.js +17 -7
  96. package/lib/components/Search/SearchRecent.js +17 -7
  97. package/lib/components/Search/SearchShortcut.js +17 -7
  98. package/lib/components/Search/SearchSuggestedPages.js +17 -7
  99. package/lib/components/Search/SearchTrigger.js +17 -7
  100. package/lib/components/Search/variables.js +5 -1
  101. package/lib/components/Segmented/Segmented.js +17 -7
  102. package/lib/components/Select/Select.js +17 -7
  103. package/lib/components/Select/SelectInput.js +17 -7
  104. package/lib/components/Sidebar/Sidebar.js +17 -7
  105. package/lib/components/SidebarActions/styled.js +17 -7
  106. package/lib/components/SkipContent/SkipContent.js +17 -7
  107. package/lib/components/Switch/Switch.js +17 -7
  108. package/lib/components/TableOfContent/TableOfContent.js +17 -7
  109. package/lib/components/Tag/variables.dark.js +2 -2
  110. package/lib/components/Tooltip/Tooltip.js +17 -7
  111. package/lib/components/VersionPicker/VersionPicker.js +17 -7
  112. package/lib/core/constants/search.d.ts +5 -4
  113. package/lib/core/constants/search.js +4 -5
  114. package/lib/core/contexts/CodeSnippetContext.js +17 -7
  115. package/lib/core/hooks/use-tabs.d.ts +3 -2
  116. package/lib/core/hooks/use-tabs.js +115 -57
  117. package/lib/core/styles/dark.js +29 -26
  118. package/lib/core/styles/global.js +64 -59
  119. package/lib/core/templates/Markdown.js +17 -7
  120. package/lib/core/types/hooks.d.ts +6 -3
  121. package/lib/core/types/l10n.d.ts +1 -1
  122. package/lib/core/utils/download-code-walkthrough.js +17 -7
  123. package/lib/core/utils/get-file-icon.js +17 -7
  124. package/lib/icons/AiStarsIcon/AiStarsIcon.js +11 -2
  125. package/lib/icons/GenericIcon/GenericIcon.js +17 -7
  126. package/lib/icons/RedoclyIcon/RedoclyIcon.d.ts +9 -0
  127. package/lib/icons/RedoclyIcon/RedoclyIcon.js +24 -0
  128. package/lib/icons/Spinner/Spinner.js +17 -7
  129. package/lib/index.d.ts +2 -0
  130. package/lib/index.js +19 -7
  131. package/lib/layouts/OIDCForbidden.js +17 -7
  132. package/lib/layouts/RootLayout.js +6 -1
  133. package/lib/layouts/ThreePanelLayout.js +17 -7
  134. package/lib/markdoc/components/Cards/Cards.js +17 -7
  135. package/lib/markdoc/components/CodeGroup/CodeGroup.js +17 -7
  136. package/lib/markdoc/components/CodeWalkthrough/CodeContainer.js +17 -7
  137. package/lib/markdoc/components/CodeWalkthrough/CodePanel.js +17 -7
  138. package/lib/markdoc/components/CodeWalkthrough/CodePanelHeader.js +17 -7
  139. package/lib/markdoc/components/CodeWalkthrough/CodePanelPreview.js +17 -7
  140. package/lib/markdoc/components/CodeWalkthrough/CodePanelToolbar.js +17 -7
  141. package/lib/markdoc/components/CodeWalkthrough/CodeStep.js +17 -7
  142. package/lib/markdoc/components/CodeWalkthrough/CodeToggle.js +17 -7
  143. package/lib/markdoc/components/CodeWalkthrough/CodeWalkthrough.js +17 -7
  144. package/lib/markdoc/components/CodeWalkthrough/Input.js +17 -7
  145. package/lib/markdoc/components/Heading/Heading.js +17 -7
  146. package/lib/markdoc/components/HtmlBlock/HtmlBlock.js +17 -7
  147. package/lib/markdoc/components/InlineSvg/InlineSvg.js +17 -7
  148. package/lib/markdoc/components/MarkdocExample/MarkdocExample.js +17 -7
  149. package/lib/markdoc/components/Tabs/TabList.d.ts +3 -1
  150. package/lib/markdoc/components/Tabs/TabList.js +214 -54
  151. package/lib/markdoc/components/Tabs/Tabs.d.ts +2 -1
  152. package/lib/markdoc/components/Tabs/Tabs.js +74 -19
  153. package/lib/markdoc/default.d.ts +104 -1
  154. package/lib/markdoc/default.js +17 -7
  155. package/package.json +5 -5
  156. package/src/components/Accordion/Accordion.tsx +100 -0
  157. package/src/components/Accordion/AccordionBody.tsx +65 -0
  158. package/src/components/Accordion/AccordionHeader.tsx +68 -0
  159. package/src/components/Accordion/AccordionTitle.tsx +26 -0
  160. package/src/components/Accordion/variables.ts +56 -0
  161. package/src/components/Buttons/AIAssistantButton.tsx +141 -0
  162. package/src/components/Buttons/variables.dark.ts +7 -0
  163. package/src/components/Buttons/variables.ts +48 -0
  164. package/src/components/Catalog/Catalog.tsx +18 -6
  165. package/src/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityApiDescriptionRelations.tsx +1 -1
  166. package/src/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityTeamRelations.tsx +1 -1
  167. package/src/components/Catalog/CatalogFilter/CatalogFilter.tsx +56 -0
  168. package/src/components/Catalog/CatalogFilter/CatalogFilterCheckboxes.tsx +169 -0
  169. package/src/components/Catalog/CatalogFilter/CatalogFilterContent.tsx +121 -0
  170. package/src/components/Catalog/CatalogFilter/CatalogFilterDateRange.tsx +147 -0
  171. package/src/components/Catalog/CatalogFilter/CatalogFilterSelect.tsx +136 -0
  172. package/src/components/Catalog/CatalogSelector.tsx +0 -1
  173. package/src/components/Catalog/variables.ts +0 -1
  174. package/src/components/Dropdown/Dropdown.tsx +84 -79
  175. package/src/components/Filter/FilterInput.tsx +3 -2
  176. package/src/components/Filter/FilterOptions.tsx +2 -0
  177. package/src/components/Filter/variables.ts +7 -4
  178. package/src/components/Menu/MenuItem.tsx +1 -0
  179. package/src/components/Search/SearchAiConversationInput.tsx +12 -2
  180. package/src/components/Search/SearchAiDialog.tsx +2 -2
  181. package/src/components/Search/SearchAiResponse.tsx +2 -2
  182. package/src/components/Search/SearchDialog.tsx +13 -5
  183. package/src/components/Search/variables.ts +5 -1
  184. package/src/components/Tag/variables.dark.ts +2 -2
  185. package/src/core/constants/search.ts +8 -4
  186. package/src/core/hooks/use-tabs.ts +168 -86
  187. package/src/core/styles/dark.ts +11 -8
  188. package/src/core/styles/global.ts +7 -2
  189. package/src/core/types/hooks.ts +6 -1
  190. package/src/core/types/l10n.ts +2 -0
  191. package/src/icons/AiStarsIcon/AiStarsIcon.tsx +11 -2
  192. package/src/icons/RedoclyIcon/RedoclyIcon.tsx +26 -0
  193. package/src/index.ts +2 -0
  194. package/src/layouts/RootLayout.tsx +6 -0
  195. package/src/markdoc/components/Tabs/TabList.tsx +312 -105
  196. package/src/markdoc/components/Tabs/Tabs.tsx +136 -11
@@ -1,7 +1,7 @@
1
- import React, { cloneElement, useRef } from 'react';
1
+ import React, { cloneElement, useRef, forwardRef } from 'react';
2
2
  import styled from 'styled-components';
3
3
 
4
- import type { PropsWithChildren, ReactElement, JSX } from 'react';
4
+ import type { PropsWithChildren, ReactElement } from 'react';
5
5
 
6
6
  import { useOutsideClick, useControlledState } from '@redocly/theme/core/hooks';
7
7
  import { ChevronDownIcon } from '@redocly/theme/icons/ChevronDownIcon/ChevronDownIcon';
@@ -32,84 +32,89 @@ export type DropdownProps = PropsWithChildren<{
32
32
  onClose?: () => void;
33
33
  }>;
34
34
 
35
- export function Dropdown({
36
- children,
37
- className,
38
- active,
39
- trigger,
40
- triggerEvent = 'click',
41
- closeOnClick = true,
42
- withArrow,
43
- dataAttributes,
44
- placement,
45
- alignment,
46
- onClick,
47
- onClose,
48
- }: DropdownProps): JSX.Element {
49
- const dropdownRef = useRef<HTMLDivElement | null>(null);
50
- const [isOpen, setIsOpen] = useControlledState<boolean>(false, active);
51
-
52
- const handleOpen = () => {
53
- setIsOpen(true);
54
- };
55
-
56
- const handleClose = () => {
57
- setIsOpen(false);
58
- onClose?.();
59
- };
60
-
61
- const handleChildClick = () => {
62
- handleClose();
63
- };
64
-
65
- const handleToggle = (event: React.UIEvent) => {
66
- event.stopPropagation();
67
- event.preventDefault();
68
- setIsOpen(!isOpen);
69
- };
70
-
71
- const handleKeyDown = (event: React.KeyboardEvent) => {
72
- if (event.key === 'Enter' || event.key === ' ') {
73
- handleToggle(event);
74
- }
75
- };
76
-
77
- useOutsideClick(dropdownRef, handleClose);
78
-
79
- const triggerChild = React.Children.only(trigger) as ReactElement<TriggerProps>;
80
-
81
- const dropdownTrigger = cloneElement(triggerChild, {
82
- onClick: triggerEvent === 'click' ? handleToggle : undefined,
83
- icon: withArrow ? isOpen ? <ChevronUpIcon /> : <ChevronDownIcon /> : undefined,
84
- ...(withArrow ? { iconPosition: 'right' } : {}),
85
- ...triggerChild.props,
86
- onKeyDown: triggerEvent === 'click' ? handleKeyDown : undefined,
87
- });
88
-
89
- return (
90
- <DropdownWrapper
91
- data-component-name="Dropdown/Dropdown"
92
- data-testid="dropdown"
93
- {...dataAttributes}
94
- className={className}
95
- ref={dropdownRef}
96
- onPointerEnter={triggerEvent === 'hover' ? handleOpen : undefined}
97
- onPointerLeave={triggerEvent === 'hover' ? handleClose : undefined}
98
- onClick={onClick}
99
- >
100
- {dropdownTrigger}
101
-
102
- <ChildrenWrapper
103
- placement={placement}
104
- alignment={alignment}
105
- isOpen={isOpen}
106
- onClick={closeOnClick ? handleChildClick : undefined}
35
+ export const Dropdown = forwardRef<HTMLDivElement, DropdownProps>(
36
+ (
37
+ {
38
+ children,
39
+ className,
40
+ active,
41
+ trigger,
42
+ triggerEvent = 'click',
43
+ closeOnClick = true,
44
+ withArrow,
45
+ dataAttributes,
46
+ placement,
47
+ alignment,
48
+ onClick,
49
+ onClose,
50
+ },
51
+ ref,
52
+ ) => {
53
+ const dropdownRef = useRef<HTMLDivElement | null>(null);
54
+ const [isOpen, setIsOpen] = useControlledState<boolean>(false, active);
55
+
56
+ const handleOpen = () => {
57
+ setIsOpen(true);
58
+ };
59
+
60
+ const handleClose = () => {
61
+ setIsOpen(false);
62
+ onClose?.();
63
+ };
64
+
65
+ const handleChildClick = () => {
66
+ handleClose();
67
+ };
68
+
69
+ const handleToggle = (event: React.UIEvent) => {
70
+ event.stopPropagation();
71
+ event.preventDefault();
72
+ setIsOpen(!isOpen);
73
+ };
74
+
75
+ const handleKeyDown = (event: React.KeyboardEvent) => {
76
+ if (event.key === 'Enter' || event.key === ' ') {
77
+ handleToggle(event);
78
+ }
79
+ };
80
+
81
+ useOutsideClick((ref as React.RefObject<HTMLElement | null>) || dropdownRef, handleClose);
82
+
83
+ const triggerChild = React.Children.only(trigger) as ReactElement<TriggerProps>;
84
+
85
+ const dropdownTrigger = cloneElement(triggerChild, {
86
+ onClick: triggerEvent === 'click' ? handleToggle : undefined,
87
+ icon: withArrow ? isOpen ? <ChevronUpIcon /> : <ChevronDownIcon /> : undefined,
88
+ ...(withArrow ? { iconPosition: 'right' } : {}),
89
+ ...triggerChild.props,
90
+ onKeyDown: triggerEvent === 'click' ? handleKeyDown : undefined,
91
+ });
92
+
93
+ return (
94
+ <DropdownWrapper
95
+ data-component-name="Dropdown/Dropdown"
96
+ data-testid="dropdown"
97
+ {...dataAttributes}
98
+ className={className}
99
+ ref={ref || dropdownRef}
100
+ onPointerEnter={triggerEvent === 'hover' ? handleOpen : undefined}
101
+ onPointerLeave={triggerEvent === 'hover' ? handleClose : undefined}
102
+ onClick={onClick}
107
103
  >
108
- {children}
109
- </ChildrenWrapper>
110
- </DropdownWrapper>
111
- );
112
- }
104
+ {dropdownTrigger}
105
+
106
+ <ChildrenWrapper
107
+ placement={placement}
108
+ alignment={alignment}
109
+ isOpen={isOpen}
110
+ onClick={closeOnClick ? handleChildClick : undefined}
111
+ >
112
+ {children}
113
+ </ChildrenWrapper>
114
+ </DropdownWrapper>
115
+ );
116
+ },
117
+ );
113
118
 
114
119
  const DropdownWrapper = styled.div`
115
120
  --button-gap: var(--spacing-xxs);
@@ -9,10 +9,11 @@ import { SearchIcon } from '@redocly/theme/icons/SearchIcon/SearchIcon';
9
9
  export type FilterInputProps = {
10
10
  value: string;
11
11
  onChange: (newValue: string) => void;
12
+ dataTestId?: string;
12
13
  };
13
14
 
14
15
  export function FilterInput(props: FilterInputProps): JSX.Element {
15
- const { value: initialValue, onChange } = props;
16
+ const { value: initialValue, onChange, dataTestId } = props;
16
17
 
17
18
  const [value, setValue] = useState(initialValue);
18
19
 
@@ -30,7 +31,7 @@ export function FilterInput(props: FilterInputProps): JSX.Element {
30
31
  const { translate } = useTranslate();
31
32
 
32
33
  return (
33
- <InputWrapper data-component-name="Filter/FilterInput">
34
+ <InputWrapper data-component-name="Filter/FilterInput" data-testid={dataTestId}>
34
35
  <InputIcon />
35
36
  <Input
36
37
  value={value}
@@ -16,4 +16,6 @@ const FilterOptionsComponent = styled.div`
16
16
  display: flex;
17
17
  flex-direction: column;
18
18
  gap: var(--filter-options-gap);
19
+ max-height: var(--filter-options-max-height);
20
+ overflow-y: scroll;
19
21
  `;
@@ -15,6 +15,7 @@ export const filter = css`
15
15
  --filter-options-padding-vertical: 0;
16
16
  --filter-options-padding-horizontal: 0;
17
17
  --filter-options-gap: var(--spacing-sm);
18
+ --filter-options-max-height: 350px;
18
19
 
19
20
  --filter-option-font-size: var(--font-size-base);
20
21
  --filter-option-gap: var(--spacing-xs);
@@ -25,12 +26,14 @@ export const filter = css`
25
26
 
26
27
  --filter-option-checkbox-padding-left: var(--spacing-xs);
27
28
 
28
- --filter-content-header-padding-vertical: 5px;
29
- --filter-content-header-padding-horizontal: 0;
29
+ --filter-content-header-padding-vertical: var(--spacing-xs) var(--spacing-sm);
30
+ --filter-content-header-padding-horizontal: var(--spacing-base);
30
31
 
31
- --filter-content-title-font-size: var(--font-size-base);
32
- --filter-content-title-line-height: var(--line-height-base);
32
+ --filter-content-title-font-size: var(--font-size-lg);
33
+ --filter-content-title-line-height: var(--line-height-lg);
33
34
  --filter-content-title-font-weight: var(--font-weight-semibold);
35
+
36
+ --filter-content-search-padding: 0 var(--spacing-xs) var(--spacing-sm);
34
37
 
35
38
  --filter-content-padding-vertical: var(--spacing-sm);
36
39
  --filter-content-padding-horizontal: var(--spacing-base);
@@ -82,6 +82,7 @@ export function MenuItem(props: React.PropsWithChildren<MenuItemProps>): JSX.Ele
82
82
  role={item.link ? 'none' : 'link'}
83
83
  tabIndex={!item.link ? 0 : undefined}
84
84
  data-testid="menu-item-label"
85
+ data-active={item.active}
85
86
  >
86
87
  {hasChevron ? <ChevronWrapper>{chevron}</ChevronWrapper> : null}
87
88
  <MenuItemIcon icon={item.icon} srcSet={item.srcSet} />
@@ -13,6 +13,7 @@ type SearchAiConversationInputProps = {
13
13
  isGeneratingResponse: boolean;
14
14
  placeholder?: string;
15
15
  className?: string;
16
+ disabled?: boolean;
16
17
  };
17
18
 
18
19
  export function SearchAiConversationInput({
@@ -20,6 +21,7 @@ export function SearchAiConversationInput({
20
21
  onMessageSent,
21
22
  className,
22
23
  placeholder,
24
+ disabled,
23
25
  }: SearchAiConversationInputProps): JSX.Element {
24
26
  const { useTranslate } = useThemeHooks();
25
27
  const { translate } = useTranslate();
@@ -36,6 +38,8 @@ export function SearchAiConversationInput({
36
38
  }, [isGeneratingResponse]);
37
39
 
38
40
  const handleSendMessage = () => {
41
+ if (disabled) return;
42
+
39
43
  setQuery('');
40
44
  onMessageSent(query);
41
45
  };
@@ -46,7 +50,7 @@ export function SearchAiConversationInput({
46
50
  }
47
51
  };
48
52
 
49
- const isDisabled = isGeneratingResponse || query.trim().length === 0;
53
+ const isDisabled = disabled || isGeneratingResponse || query.trim().length === 0;
50
54
 
51
55
  return (
52
56
  <SearchAiConversationInputWrapper
@@ -62,7 +66,7 @@ export function SearchAiConversationInput({
62
66
  onChange={(e) => setQuery(e.target.value)}
63
67
  onKeyUp={handleOnKeyUp}
64
68
  value={query}
65
- disabled={isGeneratingResponse}
69
+ disabled={disabled || isGeneratingResponse}
66
70
  maxLength={AI_SEARCH_MAX_MESSAGE_LENGTH}
67
71
  />
68
72
 
@@ -111,6 +115,10 @@ const ConversationInput = styled.input`
111
115
  border-color: var(--search-ai-conversation-input-border-color-focus);
112
116
  }
113
117
 
118
+ &:disabled {
119
+ background-color: var(--search-ai-conversation-input-bg-color-disabled);
120
+ }
121
+
114
122
  &:focus:disabled {
115
123
  border-color: var(--search-ai-conversation-input-border-color-disabled);
116
124
  }
@@ -126,6 +134,8 @@ const SendButton = styled(Button)`
126
134
  display: flex;
127
135
  align-items: center;
128
136
  justify-content: center;
137
+ border-radius: var(--search-ai-conversation-input-send-button-border-radius);
138
+ padding: var(--search-ai-conversation-input-send-button-padding);
129
139
 
130
140
  &:hover {
131
141
  background-color: var(--search-ai-conversation-input-send-button-bg-color-hover);
@@ -43,12 +43,12 @@ export function SearchAiDialog({
43
43
  setConversation,
44
44
  }: SearchAiDialogProps): JSX.Element {
45
45
  const { useTranslate } = useThemeHooks();
46
- const { search } = useThemeConfig();
46
+ const { aiAssistant } = useThemeConfig();
47
47
  const { translate } = useTranslate();
48
48
 
49
49
  const conversationEndRef = React.useRef<HTMLDivElement>(null);
50
50
 
51
- const suggestions = search?.ai?.suggestions;
51
+ const suggestions = aiAssistant?.suggestions;
52
52
 
53
53
  const placeholder = isGeneratingResponse
54
54
  ? translate('search.ai.generatingResponse', 'Generating response...')
@@ -34,7 +34,7 @@ export function SearchAiResponse(props: SearchAiResponseProps): JSX.Element {
34
34
  const { useMarkdownText } = useThemeHooks();
35
35
  const { question, response, isGeneratingResponse, resources, error, onSuggestionClick } = props;
36
36
 
37
- const { search } = useThemeConfig();
37
+ const { aiAssistant } = useThemeConfig();
38
38
  const { useTranslate } = useThemeHooks();
39
39
 
40
40
  const { translate } = useTranslate();
@@ -42,7 +42,7 @@ export function SearchAiResponse(props: SearchAiResponseProps): JSX.Element {
42
42
 
43
43
  let responseContainer = null;
44
44
 
45
- const suggestions = search?.ai?.suggestions;
45
+ const suggestions = aiAssistant?.suggestions;
46
46
 
47
47
  const hasPendingOrReceivedResponse = response || isGeneratingResponse || error;
48
48
  if (hasPendingOrReceivedResponse) {
@@ -34,16 +34,22 @@ import { AiStarsGradientIcon } from '@redocly/theme/icons/AiStarsGradientIcon/Ai
34
34
  export type SearchDialogProps = {
35
35
  onClose: () => void;
36
36
  className?: string;
37
+ initialMode?: 'search' | 'ai-dialog';
37
38
  };
38
39
 
39
- export function SearchDialog({ onClose, className }: SearchDialogProps): JSX.Element {
40
+ export function SearchDialog({
41
+ onClose,
42
+ className,
43
+ initialMode = 'search',
44
+ }: SearchDialogProps): JSX.Element {
40
45
  const { useTranslate, useCurrentProduct, useSearch, useProducts, useAiSearch, useTelemetry } =
41
46
  useThemeHooks();
42
47
  const telemetry = useTelemetry();
43
48
  const products = useProducts();
44
49
  const currentProduct = useCurrentProduct();
45
50
  const [product, setProduct] = useState(currentProduct);
46
- const [mode, setMode] = useState<'search' | 'ai-dialog'>('search');
51
+ const searchSessionId = `search-${Date.now()}-${Math.random().toString(36).substring(2, 8)}`;
52
+ const [mode, setMode] = useState<'search' | 'ai-dialog'>(initialMode);
47
53
  const autoSearchDisabled = mode !== 'search';
48
54
  const {
49
55
  query,
@@ -57,7 +63,7 @@ export function SearchDialog({ onClose, className }: SearchDialogProps): JSX.Ele
57
63
  advancedSearch,
58
64
  askAi,
59
65
  groupField,
60
- } = useSearch(product?.name, autoSearchDisabled);
66
+ } = useSearch(product?.name, autoSearchDisabled, searchSessionId);
61
67
  const {
62
68
  isFilterOpen,
63
69
  onFilterToggle,
@@ -67,7 +73,7 @@ export function SearchDialog({ onClose, className }: SearchDialogProps): JSX.Ele
67
73
  onQuickFilterReset,
68
74
  } = useSearchFilter(filter, setFilter);
69
75
  const { addSearchHistoryItem } = useRecentSearches();
70
- const aiSearch = useAiSearch({ filter });
76
+ const aiSearch = useAiSearch({ filter }, searchSessionId);
71
77
 
72
78
  const searchInputRef = useRef<HTMLInputElement>(null);
73
79
  const modalRef = useRef<HTMLDivElement>(null);
@@ -145,13 +151,14 @@ export function SearchDialog({ onClose, className }: SearchDialogProps): JSX.Ele
145
151
  totalResults: results.length.toString(),
146
152
  index: index.toString(),
147
153
  searchEngine: mode,
154
+ searchSessionId,
148
155
  });
149
156
  onClose();
150
157
  }}
151
158
  />
152
159
  );
153
160
  },
154
- [onClose, product, products, addSearchHistoryItem, query, telemetry, mode],
161
+ [onClose, product, products, addSearchHistoryItem, query, telemetry, mode, searchSessionId],
155
162
  );
156
163
 
157
164
  const showLoadMore = useCallback(
@@ -384,6 +391,7 @@ export function SearchDialog({ onClose, className }: SearchDialogProps): JSX.Ele
384
391
  telemetry.sendSearchRecentClickedMessage({
385
392
  query,
386
393
  index: index.toString(),
394
+ searchSessionId,
387
395
  });
388
396
  setQuery(query);
389
397
  focusSearchInput();
@@ -171,6 +171,7 @@ export const search = css`
171
171
  --search-ai-assistant-bg-color: var(--layer-color);
172
172
  --search-ai-assistant-text-color: var(--text-color-primary);
173
173
  --search-ai-assistant-border: 1px solid var(--border-color-primary);
174
+ --search-ai-assistant-message-max-width: 80%;
174
175
 
175
176
  --search-ai-resources-gap: var(--spacing-base);
176
177
  --search-ai-resources-title-font-weight: var(--font-weight-medium);
@@ -232,6 +233,7 @@ export const search = css`
232
233
  * @tokens AI Search Conversation Input
233
234
  */
234
235
  --search-ai-conversation-input-bg-color: var(--bg-color);
236
+ --search-ai-conversation-input-bg-color-disabled: var(--color-warm-grey-1);
235
237
  --search-ai-conversation-input-padding: var(--spacing-sm) var(--spacing-md);
236
238
  --search-ai-conversation-input-border: 1px solid var(--border-color-secondary);
237
239
  --search-ai-conversation-input-border-radius: var(--border-radius-lg);
@@ -241,10 +243,12 @@ export const search = css`
241
243
  --search-ai-conversation-input-border-color-disabled: var(--border-color-secondary);
242
244
 
243
245
  --search-ai-conversation-input-send-button-right: 12px;
246
+ --search-ai-conversation-input-send-button-padding: 5px;
244
247
  --search-ai-conversation-input-send-button-bg-color: var(--button-bg-color-primary);
245
248
  --search-ai-conversation-input-send-button-bg-color-hover: var(--button-bg-color-primary-hover);
246
249
  --search-ai-conversation-input-send-button-bg-color-disabled: var(--button-bg-color-disabled);
247
250
  --search-ai-conversation-input-send-button-border-disabled: 1px solid var(--button-border-color-disabled);
251
+ --search-ai-conversation-input-send-button-border-radius: var(--border-radius);
248
252
 
249
253
  /**
250
254
  * @tokens AI Search Response
@@ -277,7 +281,7 @@ export const search = css`
277
281
 
278
282
  --search-ai-suggestions-gap: var(--spacing-sm);
279
283
  --search-ai-suggestions-margin-left: var(--spacing-xs);
280
- --search-ai-suggestion-item-gap: var(--spacing-xs);
284
+ --search-ai-suggestion-item-gap: var(--spacing-xxs);
281
285
 
282
286
  --search-ai-suggestions-title-text-color: var(--text-color-description);
283
287
  --search-ai-suggestions-title-font-size: var(--font-size-base);
@@ -55,10 +55,10 @@ export const tagDarkMode = css`
55
55
  }
56
56
 
57
57
  .tag-green {
58
- --tag-color: var(--color-green-6); // @presenter Color
58
+ --tag-color: var(--color-green-7); // @presenter Color
59
59
  --tag-bg-color: var(--color-green-1); // @presenter Color
60
60
  --tag-border-color: var(--color-green-3); // @presenter Color
61
- --tag-border-color-hover: var(--color-green-4); // @presenter Color
61
+ --tag-border-color-hover: var(--color-green-5); // @presenter Color
62
62
  --tag-bg-color-hover: var(--color-green-2); // @presenter Color
63
63
  }
64
64
 
@@ -7,10 +7,14 @@ export enum AiSearchError {
7
7
  EmptyResponse = 'empty_response',
8
8
  ErrorProcessingResponse = 'error_processing_response',
9
9
  }
10
- export const enum AiSearchConversationRole {
11
- USER = 'user',
12
- ASSISTANT = 'assistant',
13
- }
10
+
11
+ export const AiSearchConversationRole = {
12
+ USER: 'user',
13
+ ASSISTANT: 'assistant',
14
+ } as const;
15
+
16
+ export type AiSearchConversationRole =
17
+ (typeof AiSearchConversationRole)[keyof typeof AiSearchConversationRole];
14
18
 
15
19
  const defaultErrorConfig: AiSearchErrorConfig = {
16
20
  headerKey: 'search.ai.error.header',