@redocly/theme 0.61.0 → 0.62.0-custom.0

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 (199) hide show
  1. package/lib/components/Admonition/Admonition.js +14 -18
  2. package/lib/components/Admonition/variables.dark.d.ts +1 -0
  3. package/lib/components/Admonition/variables.dark.js +18 -0
  4. package/lib/components/Admonition/variables.js +24 -28
  5. package/lib/components/AsyncApiDocs/hooks/AfterAsyncApiChannelDescription.d.ts +1 -0
  6. package/lib/components/AsyncApiDocs/hooks/AfterAsyncApiChannelDescription.js +12 -0
  7. package/lib/components/Badge/Badge.d.ts +2 -1
  8. package/lib/components/Badge/Badge.js +24 -2
  9. package/lib/components/Banner/Banner.js +19 -1
  10. package/lib/components/Banner/variables.js +1 -0
  11. package/lib/components/Breadcrumbs/Breadcrumb.js +1 -1
  12. package/lib/components/Breadcrumbs/BreadcrumbDropdown.js +9 -6
  13. package/lib/components/Breadcrumbs/Breadcrumbs.js +24 -15
  14. package/lib/components/Buttons/AIAssistantButton.js +7 -4
  15. package/lib/components/Catalog/CatalogEntities.js +10 -8
  16. package/lib/components/Catalog/CatalogEntity/CatalogEntity.js +2 -2
  17. package/lib/components/Catalog/CatalogEntity/CatalogEntityHistory/CatalogEntityHistorySidebar.js +5 -3
  18. package/lib/components/Catalog/CatalogEntity/CatalogEntityProperties/TagsProperty.js +2 -2
  19. package/lib/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityRelationsTable.js +13 -11
  20. package/lib/components/Catalog/CatalogEntity/CatalogEntitySchema.js +7 -5
  21. package/lib/components/Catalog/CatalogFilter/CatalogFilterCheckboxes.js +9 -7
  22. package/lib/components/Catalog/CatalogTableView/CatalogTableViewRow.js +1 -1
  23. package/lib/components/Catalog/CatalogTagsWithTooltip.js +2 -2
  24. package/lib/components/CatalogClassic/CatalogClassicInfoBlock.js +1 -1
  25. package/lib/components/CodeBlock/CodeBlockControls.js +8 -6
  26. package/lib/components/Filter/FilterCheckboxes.js +1 -1
  27. package/lib/components/JsonViewer/JsonViewer.js +2 -2
  28. package/lib/components/JsonViewer/{Helpers.js → helpers.js} +2 -1
  29. package/lib/components/LanguagePicker/LanguagePicker.js +1 -1
  30. package/lib/components/Markdown/Markdown.js +2 -2
  31. package/lib/components/Menu/MenuItem.js +41 -15
  32. package/lib/components/Navbar/NavbarItem.js +1 -1
  33. package/lib/components/OpenApiDocs/hooks/AdditionalOverviewInfo.d.ts +1 -0
  34. package/lib/components/OpenApiDocs/hooks/AdditionalOverviewInfo.js +12 -0
  35. package/lib/components/OpenApiDocs/hooks/AfterOpenApiDescription.d.ts +1 -0
  36. package/lib/components/OpenApiDocs/hooks/AfterOpenApiDescription.js +6 -0
  37. package/lib/components/PageActions/PageActions.js +25 -8
  38. package/lib/components/Search/SearchAiDialog.d.ts +4 -2
  39. package/lib/components/Search/SearchAiDialog.js +23 -4
  40. package/lib/components/Search/SearchAiMessage.d.ts +4 -2
  41. package/lib/components/Search/SearchAiMessage.js +82 -23
  42. package/lib/components/Search/SearchDialog.js +50 -25
  43. package/lib/components/Select/variables.js +2 -2
  44. package/lib/components/SvgViewer/SvgViewer.d.ts +15 -0
  45. package/lib/components/SvgViewer/SvgViewer.js +312 -0
  46. package/lib/components/SvgViewer/variables.d.ts +1 -0
  47. package/lib/components/SvgViewer/variables.dark.d.ts +1 -0
  48. package/lib/components/SvgViewer/variables.dark.js +8 -0
  49. package/lib/components/SvgViewer/variables.js +17 -0
  50. package/lib/components/Tag/Tag.js +1 -1
  51. package/lib/components/Tag/variables.dark.js +6 -0
  52. package/lib/components/Tag/variables.js +6 -0
  53. package/lib/components/Tooltip/Tooltip.d.ts +2 -3
  54. package/lib/components/Tooltip/Tooltip.js +66 -113
  55. package/lib/components/Tooltip/variables.dark.js +4 -0
  56. package/lib/components/Tooltip/variables.js +3 -3
  57. package/lib/components/UserMenu/LoginButton.d.ts +8 -2
  58. package/lib/components/UserMenu/LoginButton.js +4 -3
  59. package/lib/core/constants/search.d.ts +5 -1
  60. package/lib/core/constants/search.js +24 -1
  61. package/lib/core/hooks/search/use-search-dialog.js +2 -2
  62. package/lib/core/hooks/use-color-switcher.d.ts +1 -0
  63. package/lib/core/hooks/use-color-switcher.js +8 -1
  64. package/lib/core/hooks/use-mcp-config.js +2 -1
  65. package/lib/core/hooks/use-modal-scroll-lock.js +24 -10
  66. package/lib/core/hooks/use-outside-click.d.ts +3 -1
  67. package/lib/core/hooks/use-outside-click.js +8 -4
  68. package/lib/core/hooks/use-page-actions.d.ts +1 -1
  69. package/lib/core/hooks/use-page-actions.js +44 -11
  70. package/lib/core/hooks/use-product-picker.js +1 -1
  71. package/lib/core/hooks/use-unique-svg-ids.d.ts +6 -0
  72. package/lib/core/hooks/use-unique-svg-ids.js +15 -0
  73. package/lib/core/openapi/index.d.ts +1 -0
  74. package/lib/core/openapi/index.js +3 -1
  75. package/lib/core/styles/dark.js +4 -0
  76. package/lib/core/styles/global.js +31 -15
  77. package/lib/core/types/catalog.d.ts +1 -1
  78. package/lib/core/types/hooks.d.ts +23 -2
  79. package/lib/core/types/l10n.d.ts +1 -1
  80. package/lib/core/types/search.d.ts +24 -0
  81. package/lib/core/types/search.js +9 -1
  82. package/lib/core/utils/content-segments.d.ts +2 -0
  83. package/lib/core/utils/content-segments.js +22 -0
  84. package/lib/core/utils/index.d.ts +1 -0
  85. package/lib/core/utils/index.js +1 -0
  86. package/lib/core/utils/transform-revisions-to-version-history.js +8 -51
  87. package/lib/ext/process-scorecard.d.ts +5 -0
  88. package/lib/ext/process-scorecard.js +11 -0
  89. package/lib/icons/FitToViewIcon/FitToViewIcon.d.ts +9 -0
  90. package/lib/icons/FitToViewIcon/FitToViewIcon.js +25 -0
  91. package/lib/icons/WarningCycleIcon/WarningCycleIcon.d.ts +9 -0
  92. package/lib/icons/WarningCycleIcon/WarningCycleIcon.js +24 -0
  93. package/lib/index.d.ts +9 -0
  94. package/lib/index.js +9 -0
  95. package/lib/layouts/DocumentationLayout.js +4 -25
  96. package/lib/layouts/DocumentationLayoutBottom.d.ts +11 -0
  97. package/lib/layouts/DocumentationLayoutBottom.js +28 -0
  98. package/lib/layouts/DocumentationLayoutTop.d.ts +13 -0
  99. package/lib/layouts/DocumentationLayoutTop.js +33 -0
  100. package/lib/layouts/Forbidden.js +22 -18
  101. package/lib/markdoc/components/Cards/Card.js +1 -0
  102. package/lib/markdoc/components/CodeWalkthrough/CodeFilters.js +1 -1
  103. package/lib/markdoc/components/Heading/Heading.js +40 -2
  104. package/lib/markdoc/components/LoginButton/LoginButton.d.ts +9 -0
  105. package/lib/markdoc/components/LoginButton/LoginButton.js +48 -0
  106. package/lib/markdoc/components/Mermaid/Mermaid.js +70 -2
  107. package/lib/markdoc/components/default.d.ts +1 -0
  108. package/lib/markdoc/components/default.js +1 -0
  109. package/lib/markdoc/default.d.ts +6 -0
  110. package/lib/markdoc/default.js +2 -0
  111. package/lib/markdoc/tags/login-button.d.ts +2 -0
  112. package/lib/markdoc/tags/login-button.js +32 -0
  113. package/package.json +9 -9
  114. package/src/components/Admonition/Admonition.tsx +14 -18
  115. package/src/components/Admonition/variables.dark.ts +15 -0
  116. package/src/components/Admonition/variables.ts +24 -28
  117. package/src/components/AsyncApiDocs/hooks/AfterAsyncApiChannelDescription.tsx +10 -0
  118. package/src/components/Badge/Badge.tsx +18 -2
  119. package/src/components/Banner/Banner.tsx +23 -1
  120. package/src/components/Banner/variables.ts +1 -0
  121. package/src/components/Breadcrumbs/Breadcrumb.tsx +3 -3
  122. package/src/components/Breadcrumbs/BreadcrumbDropdown.tsx +11 -8
  123. package/src/components/Breadcrumbs/Breadcrumbs.tsx +24 -15
  124. package/src/components/Buttons/AIAssistantButton.tsx +7 -4
  125. package/src/components/Catalog/CatalogEntities.tsx +10 -8
  126. package/src/components/Catalog/CatalogEntity/CatalogEntity.tsx +1 -1
  127. package/src/components/Catalog/CatalogEntity/CatalogEntityHistory/CatalogEntityHistorySidebar.tsx +7 -4
  128. package/src/components/Catalog/CatalogEntity/CatalogEntityProperties/TagsProperty.tsx +1 -1
  129. package/src/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityRelationsTable.tsx +13 -11
  130. package/src/components/Catalog/CatalogEntity/CatalogEntitySchema.tsx +7 -5
  131. package/src/components/Catalog/CatalogFilter/CatalogFilterCheckboxes.tsx +9 -7
  132. package/src/components/Catalog/CatalogTableView/CatalogTableViewRow.tsx +1 -2
  133. package/src/components/Catalog/CatalogTagsWithTooltip.tsx +9 -5
  134. package/src/components/CatalogClassic/CatalogClassicInfoBlock.tsx +3 -1
  135. package/src/components/CodeBlock/CodeBlockControls.tsx +16 -10
  136. package/src/components/Filter/FilterCheckboxes.tsx +1 -1
  137. package/src/components/JsonViewer/JsonViewer.tsx +1 -2
  138. package/src/components/JsonViewer/{Helpers.tsx → helpers.tsx} +1 -0
  139. package/src/components/LanguagePicker/LanguagePicker.tsx +1 -1
  140. package/src/components/Markdown/Markdown.tsx +2 -2
  141. package/src/components/Menu/MenuItem.tsx +61 -16
  142. package/src/components/Navbar/NavbarItem.tsx +3 -1
  143. package/src/components/OpenApiDocs/hooks/AdditionalOverviewInfo.tsx +10 -0
  144. package/src/components/OpenApiDocs/hooks/AfterOpenApiDescription.tsx +2 -0
  145. package/src/components/PageActions/PageActions.tsx +38 -15
  146. package/src/components/Search/SearchAiDialog.tsx +31 -2
  147. package/src/components/Search/SearchAiMessage.tsx +103 -17
  148. package/src/components/Search/SearchDialog.tsx +70 -37
  149. package/src/components/Select/variables.ts +2 -2
  150. package/src/components/SvgViewer/SvgViewer.tsx +405 -0
  151. package/src/components/SvgViewer/variables.dark.ts +5 -0
  152. package/src/components/SvgViewer/variables.ts +14 -0
  153. package/src/components/Tag/Tag.tsx +2 -1
  154. package/src/components/Tag/variables.dark.ts +6 -0
  155. package/src/components/Tag/variables.ts +6 -0
  156. package/src/components/Tooltip/Tooltip.tsx +77 -120
  157. package/src/components/Tooltip/variables.dark.ts +4 -0
  158. package/src/components/Tooltip/variables.ts +3 -3
  159. package/src/components/UserMenu/LoginButton.tsx +23 -8
  160. package/src/core/constants/search.ts +27 -1
  161. package/src/core/hooks/__mocks__/use-theme-hooks.ts +10 -1
  162. package/src/core/hooks/search/use-search-dialog.ts +2 -2
  163. package/src/core/hooks/use-color-switcher.ts +10 -2
  164. package/src/core/hooks/use-mcp-config.ts +2 -1
  165. package/src/core/hooks/use-modal-scroll-lock.ts +29 -10
  166. package/src/core/hooks/use-outside-click.ts +16 -5
  167. package/src/core/hooks/use-page-actions.ts +66 -25
  168. package/src/core/hooks/use-product-picker.ts +1 -1
  169. package/src/core/hooks/use-unique-svg-ids.ts +12 -0
  170. package/src/core/openapi/index.ts +1 -0
  171. package/src/core/styles/dark.ts +4 -0
  172. package/src/core/styles/global.ts +31 -15
  173. package/src/core/types/catalog.ts +1 -1
  174. package/src/core/types/hooks.ts +29 -1
  175. package/src/core/types/l10n.ts +12 -1
  176. package/src/core/types/search.ts +19 -0
  177. package/src/core/utils/content-segments.ts +27 -0
  178. package/src/core/utils/index.ts +1 -0
  179. package/src/core/utils/transform-revisions-to-version-history.ts +8 -80
  180. package/src/ext/process-scorecard.ts +14 -0
  181. package/src/icons/FitToViewIcon/FitToViewIcon.tsx +26 -0
  182. package/src/icons/WarningCycleIcon/WarningCycleIcon.tsx +32 -0
  183. package/src/index.ts +9 -0
  184. package/src/layouts/DocumentationLayout.tsx +4 -30
  185. package/src/layouts/DocumentationLayoutBottom.tsx +42 -0
  186. package/src/layouts/DocumentationLayoutTop.tsx +52 -0
  187. package/src/layouts/Forbidden.tsx +36 -21
  188. package/src/markdoc/components/Cards/Card.tsx +1 -0
  189. package/src/markdoc/components/CodeWalkthrough/CodeFilters.tsx +1 -1
  190. package/src/markdoc/components/Heading/Heading.tsx +52 -4
  191. package/src/markdoc/components/LoginButton/LoginButton.tsx +38 -0
  192. package/src/markdoc/components/Mermaid/Mermaid.tsx +57 -8
  193. package/src/markdoc/components/default.ts +1 -0
  194. package/src/markdoc/default.ts +2 -0
  195. package/src/markdoc/tags/login-button.ts +30 -0
  196. package/lib/components/Tooltip/TooltipWrapper.d.ts +0 -12
  197. package/lib/components/Tooltip/TooltipWrapper.js +0 -34
  198. package/src/components/Tooltip/TooltipWrapper.tsx +0 -70
  199. /package/lib/components/JsonViewer/{Helpers.d.ts → helpers.d.ts} +0 -0
@@ -3,7 +3,13 @@ import styled from 'styled-components';
3
3
 
4
4
  import type { JSX } from 'react';
5
5
 
6
- import { FeedbackType, type SearchAiMessageResource } from '@redocly/theme/core/types';
6
+ import {
7
+ FeedbackType,
8
+ type SearchAiMessageResource,
9
+ type ToolCall,
10
+ type ContentSegment,
11
+ } from '@redocly/theme/core/types';
12
+ import { TOOL_CALL_DISPLAY_TEXT } from '@redocly/theme/core/constants';
7
13
  import { Link } from '@redocly/theme/components/Link/Link';
8
14
  import { Tag } from '@redocly/theme/components/Tag/Tag';
9
15
  import { AiSearchConversationRole } from '@redocly/theme/core/constants';
@@ -12,9 +18,14 @@ import { Markdown } from '@redocly/theme/components/Markdown/Markdown';
12
18
  import { DocumentIcon } from '@redocly/theme/icons/DocumentIcon/DocumentIcon';
13
19
  import { AiStarsIcon } from '@redocly/theme/icons/AiStarsIcon/AiStarsIcon';
14
20
  import { CheckmarkOutlineIcon } from '@redocly/theme/icons/CheckmarkOutlineIcon/CheckmarkOutlineIcon';
21
+ import { SearchAiActionButtons } from '@redocly/theme/components/Search/SearchAiActionButtons';
22
+ import { SearchAiNegativeFeedbackForm } from '@redocly/theme/components/Search/SearchAiNegativeFeedbackForm';
15
23
 
16
- import { SearchAiActionButtons } from './SearchAiActionButtons';
17
- import { SearchAiNegativeFeedbackForm } from './SearchAiNegativeFeedbackForm';
24
+ function MarkdownSegment({ text }: { text: string }): JSX.Element {
25
+ const { useMarkdownText } = useThemeHooks();
26
+ const markdown = useMarkdownText(text);
27
+ return <ResponseText as="div" children={markdown} data-testid="response-text" />;
28
+ }
18
29
 
19
30
  export type SearchAiMessageProps = {
20
31
  role: AiSearchConversationRole;
@@ -25,6 +36,8 @@ export type SearchAiMessageProps = {
25
36
  messageId?: string;
26
37
  feedback?: FeedbackType;
27
38
  onFeedbackChange: (messageId: string, feedback: FeedbackType | undefined) => void;
39
+ toolCalls?: ToolCall[];
40
+ contentSegments?: ContentSegment[];
28
41
  };
29
42
 
30
43
  function SearchAiMessageComponent({
@@ -36,9 +49,10 @@ function SearchAiMessageComponent({
36
49
  messageId,
37
50
  feedback,
38
51
  onFeedbackChange,
52
+ toolCalls = [],
53
+ contentSegments = [{ type: 'text' as const, text: content }],
39
54
  }: SearchAiMessageProps): JSX.Element {
40
- const { useMarkdownText, useTranslate, useTelemetry } = useThemeHooks();
41
- const markDownContent = useMarkdownText(content || '');
55
+ const { useTranslate, useTelemetry } = useThemeHooks();
42
56
  const { translate } = useTranslate();
43
57
  const telemetry = useTelemetry();
44
58
  const [feedbackSent, setFeedbackSent] = useState(false);
@@ -48,15 +62,20 @@ function SearchAiMessageComponent({
48
62
 
49
63
  const showSuccessMessage = feedbackSent && feedback;
50
64
 
65
+ const isLoading = isThinking && content.length === 0 && toolCalls.length === 0;
66
+
51
67
  const sendFeedbackTelemetry = (feedbackValue: FeedbackType, dislikeReason?: string) => {
52
68
  if (!messageId) return;
53
69
 
54
70
  try {
55
- telemetry.sendSearchAIFeedbackMessage({
56
- feedback: feedbackValue,
57
- messageId,
58
- reason: dislikeReason,
59
- });
71
+ telemetry.sendSearchAIFeedbackMessage([
72
+ {
73
+ object: 'feedback',
74
+ feedback: feedbackValue,
75
+ messageId,
76
+ reason: dislikeReason,
77
+ },
78
+ ]);
60
79
  } catch (error) {
61
80
  console.error('Error sending feedback', error);
62
81
  }
@@ -98,7 +117,36 @@ function SearchAiMessageComponent({
98
117
  {role === AiSearchConversationRole.ASSISTANT ? (
99
118
  <>
100
119
  <MessageWrapper role={role}>
101
- <ResponseText as="div" children={markDownContent} data-testid="response-text" />
120
+ {contentSegments.map((segment, index) => {
121
+ if (segment.type === 'tool') {
122
+ const toolCallCompleted = Boolean(segment.toolCall.result);
123
+
124
+ const toolCallCompletedText =
125
+ TOOL_CALL_DISPLAY_TEXT[segment.toolCall.name]?.completedText ??
126
+ `${translate('search.ai.toolResult.found', 'Found')} ${segment.toolCall.result?.documentCount ?? 0} ${translate('search.ai.toolResult.found.documents', 'documents')}`;
127
+
128
+ const toolCallInProgressText =
129
+ TOOL_CALL_DISPLAY_TEXT[segment.toolCall.name]?.inProgressText ??
130
+ translate('search.ai.toolCall.searching', 'Searching...');
131
+
132
+ const toolCallDisplayText = toolCallCompleted
133
+ ? toolCallCompletedText
134
+ : toolCallInProgressText;
135
+
136
+ return (
137
+ <ToolCallsInfoWrapper key={`tool-${index}`} data-testid="tool-calls-info">
138
+ <ToolCallInfoItem>
139
+ <DocumentIcon size="14px" color="--search-ai-text-color" />
140
+ <ToolCallText $isSearching={!toolCallCompleted}>
141
+ {toolCallDisplayText}
142
+ </ToolCallText>
143
+ </ToolCallInfoItem>
144
+ </ToolCallsInfoWrapper>
145
+ );
146
+ }
147
+
148
+ return <MarkdownSegment key={`text-${index}`} text={segment.text} />;
149
+ })}
102
150
  {hasResources && (
103
151
  <>
104
152
  <ResourcesWrapper data-testid="resources-wrapper">
@@ -107,8 +155,8 @@ function SearchAiMessageComponent({
107
155
  {translate('search.ai.resourcesFound.resources', 'resources')}
108
156
  </ResourcesTitle>
109
157
  <ResourceTagsWrapper>
110
- {resources?.map((resource, idx) => (
111
- <Link key={`${resource.url}-${idx}`} to={resource.url} target="_blank">
158
+ {resources?.map((resource, index) => (
159
+ <Link key={`${resource.url}-${index}`} to={resource.url} target="_blank">
112
160
  <ResourceTag
113
161
  borderless
114
162
  icon={<DocumentIcon color="--search-ai-resource-tag-icon-color" />}
@@ -121,7 +169,7 @@ function SearchAiMessageComponent({
121
169
  </ResourcesWrapper>
122
170
  </>
123
171
  )}
124
- {isThinking && content.length === 0 && (
172
+ {isLoading && (
125
173
  <ThinkingDotsWrapper data-testid="thinking-dots-wrapper">
126
174
  <ThinkingDot />
127
175
  <ThinkingDot />
@@ -188,7 +236,9 @@ export const SearchAiMessage = memo(SearchAiMessageComponent, (prevProps, nextPr
188
236
  prevProps.messageId === nextProps.messageId &&
189
237
  prevProps.feedback === nextProps.feedback &&
190
238
  prevProps.onFeedbackChange === nextProps.onFeedbackChange &&
191
- areResourcesEqual(prevProps.resources, nextProps.resources)
239
+ areResourcesEqual(prevProps.resources, nextProps.resources) &&
240
+ prevProps.toolCalls?.length === nextProps.toolCalls?.length &&
241
+ prevProps.contentSegments === nextProps.contentSegments
192
242
  );
193
243
  });
194
244
 
@@ -228,8 +278,9 @@ const ResponseText = styled(Markdown)`
228
278
 
229
279
  const MessageWrapper = styled.div<{ role: string }>`
230
280
  padding: ${({ role }) =>
231
- role === AiSearchConversationRole.USER ? 'var(--spacing-sm)' : 'var(--spacing-xs)'}
232
- var(--spacing-sm);
281
+ role === AiSearchConversationRole.USER
282
+ ? 'var(--spacing-sm)'
283
+ : 'var(--spacing-sm) var(--spacing-sm) var(--spacing-xs) var(--spacing-sm)'};
233
284
  border-radius: var(--border-radius-lg);
234
285
  width: fit-content;
235
286
  max-width: 100%;
@@ -344,3 +395,38 @@ const SuccessMessageText = styled.div`
344
395
  font-size: var(--font-size-base);
345
396
  color: var(--color-success-darker);
346
397
  `;
398
+
399
+ const ToolCallsInfoWrapper = styled.div`
400
+ display: flex;
401
+ flex-direction: column;
402
+ gap: var(--spacing-xxs);
403
+ margin: 0 0 var(--spacing-sm) 0;
404
+ font-size: var(--font-size-xs);
405
+ color: var(--search-ai-text-color);
406
+ opacity: 0.6;
407
+ `;
408
+
409
+ const ToolCallInfoItem = styled.div`
410
+ display: flex;
411
+ align-items: center;
412
+ gap: var(--spacing-xxs);
413
+ `;
414
+
415
+ const ToolCallText = styled.span<{ $isSearching?: boolean }>`
416
+ font-weight: var(--font-weight-regular);
417
+
418
+ ${({ $isSearching }) =>
419
+ $isSearching &&
420
+ `
421
+ animation: pulse 1.5s ease-in-out infinite;
422
+
423
+ @keyframes pulse {
424
+ 0%, 100% {
425
+ opacity: 1;
426
+ }
427
+ 50% {
428
+ opacity: 0.4;
429
+ }
430
+ }
431
+ `}
432
+ `;
@@ -16,6 +16,7 @@ import {
16
16
  useDialogHotKeys,
17
17
  useSearchFilter,
18
18
  useRecentSearches,
19
+ useModalScrollLock,
19
20
  } from '@redocly/theme/core/hooks';
20
21
  import { Tag } from '@redocly/theme/components/Tag/Tag';
21
22
  import { CloseIcon } from '@redocly/theme/icons/CloseIcon/CloseIcon';
@@ -75,7 +76,7 @@ export function SearchDialog({
75
76
  } = useSearchFilter(filter, setFilter);
76
77
  const { addSearchHistoryItem } = useRecentSearches();
77
78
  const aiSearch = useAiSearch({ filter });
78
-
79
+ useModalScrollLock(true);
79
80
  const searchInputRef = useRef<HTMLInputElement>(null);
80
81
  const modalRef = useRef<HTMLDivElement>(null);
81
82
 
@@ -163,14 +164,17 @@ export function SearchDialog({
163
164
  innerRef={innerRef}
164
165
  onClick={() => {
165
166
  addSearchHistoryItem(query);
166
- telemetry.sendSearchResultClickedMessage({
167
- query,
168
- url: item.document.url,
169
- totalResults: results.length.toString(),
170
- index: index.toString(),
171
- searchEngine: mode,
172
- searchSessionId,
173
- });
167
+ telemetry.sendSearchResultClickedMessage([
168
+ {
169
+ object: 'search',
170
+ query: query,
171
+ url: item.document.url,
172
+ totalResults: results.length.toString(),
173
+ index: index.toString(),
174
+ searchEngine: mode,
175
+ searchSessionId,
176
+ },
177
+ ]);
174
178
  onClose();
175
179
  }}
176
180
  />
@@ -246,9 +250,12 @@ export function SearchDialog({
246
250
  if (query.trim()) {
247
251
  aiSearch.askQuestion(query);
248
252
  }
249
- telemetry.sendSearchAiOpenedMessage({
250
- method: 'ai_search_button',
251
- });
253
+ telemetry.sendSearchAiOpenedMessage([
254
+ {
255
+ object: 'search',
256
+ method: 'ai_search_button',
257
+ },
258
+ ]);
252
259
  }}
253
260
  >
254
261
  {translate('search.ai.button', 'Search with AI')}
@@ -262,20 +269,27 @@ export function SearchDialog({
262
269
  </>
263
270
  ) : (
264
271
  <AiDialogHeaderWrapper>
265
- <Button
266
- variant="secondary"
267
- onClick={() => {
268
- setMode('search');
269
- aiSearch.clearConversation();
270
- focusSearchInput();
271
- }}
272
- tabIndex={0}
273
- icon={<ChevronLeftIcon />}
274
- >
275
- {isMobile
276
- ? translate('search.ai.back', 'Back')
277
- : translate('search.ai.backToSearch', 'Back to search')}
278
- </Button>
272
+ {initialMode === 'ai-dialog' ? (
273
+ <AiDialogHeaderTitle>
274
+ <AiStarsGradientIcon color="var(--search-ai-button-icon-color)" size="1.25rem" />
275
+ {translate('search.ai.assistant', 'Assistant')}
276
+ </AiDialogHeaderTitle>
277
+ ) : (
278
+ <Button
279
+ variant="secondary"
280
+ onClick={() => {
281
+ setMode('search');
282
+ aiSearch.clearConversation();
283
+ focusSearchInput();
284
+ }}
285
+ tabIndex={0}
286
+ icon={<ChevronLeftIcon />}
287
+ >
288
+ {isMobile
289
+ ? translate('search.ai.back', 'Back')
290
+ : translate('search.ai.backToSearch', 'Back to search')}
291
+ </Button>
292
+ )}
279
293
  <AiDialogHeaderActionsWrapper>
280
294
  <Button
281
295
  variant="secondary"
@@ -327,9 +341,12 @@ export function SearchDialog({
327
341
  if (query.trim()) {
328
342
  aiSearch.askQuestion(query);
329
343
  }
330
- telemetry.sendSearchAiOpenedMessage({
331
- method: 'ai_search_input',
332
- });
344
+ telemetry.sendSearchAiOpenedMessage([
345
+ {
346
+ object: 'search',
347
+ method: 'ai_search_input',
348
+ },
349
+ ]);
333
350
  }}
334
351
  onKeyDown={(e) => {
335
352
  if (e.key === 'Enter') {
@@ -337,9 +354,12 @@ export function SearchDialog({
337
354
  if (query.trim()) {
338
355
  aiSearch.askQuestion(query);
339
356
  }
340
- telemetry.sendSearchAiOpenedMessage({
341
- method: 'ai_search_input',
342
- });
357
+ telemetry.sendSearchAiOpenedMessage([
358
+ {
359
+ object: 'search',
360
+ method: 'ai_search_input',
361
+ },
362
+ ]);
343
363
  }
344
364
  }}
345
365
  ref={aiQueryRef}
@@ -423,11 +443,14 @@ export function SearchDialog({
423
443
  <>
424
444
  <SearchRecent
425
445
  onSelect={(query, index) => {
426
- telemetry.sendSearchRecentClickedMessage({
427
- query,
428
- index: index.toString(),
429
- searchSessionId,
430
- });
446
+ telemetry.sendSearchRecentClickedMessage([
447
+ {
448
+ object: 'search',
449
+ query,
450
+ index: index.toString(),
451
+ searchSessionId,
452
+ },
453
+ ]);
431
454
  setQuery(query);
432
455
  focusSearchInput();
433
456
  }}
@@ -447,6 +470,8 @@ export function SearchDialog({
447
470
  conversation={aiSearch.conversation}
448
471
  setConversation={aiSearch.setConversation}
449
472
  onMessageSent={aiSearch.askQuestion}
473
+ toolCalls={aiSearch.toolCalls}
474
+ contentSegments={aiSearch.contentSegments}
450
475
  />
451
476
  )}
452
477
  </SearchDialogBody>
@@ -567,6 +592,14 @@ const AiDialogHeaderActionsWrapper = styled.div`
567
592
  gap: var(--spacing-xxs);
568
593
  `;
569
594
 
595
+ const AiDialogHeaderTitle = styled.span`
596
+ display: flex;
597
+ align-items: center;
598
+ gap: var(--spacing-xs);
599
+ font-weight: var(--font-weight-semibold);
600
+ font-size: var(--font-size-lg);
601
+ `;
602
+
570
603
  const SearchDialogBody = styled.div`
571
604
  display: flex;
572
605
  flex-direction: row-reverse;
@@ -10,7 +10,7 @@ export const select = css`
10
10
  --select-text-color: var(--text-color-secondary); // @presenter Color
11
11
  --select-border-radius: var(--border-radius); // @presenter BorderRadius
12
12
  --select-border: var(--border-width) var(--border-style) var(--border-color-primary); // @presenter Border
13
-
13
+
14
14
  --select-input-padding-vertical: 6px; // @presenter Spacing
15
15
  --select-input-padding-horizontal: 6px; // @presenter Spacing
16
16
  --select-input-padding: var(--select-input-padding-vertical) var(--select-input-padding-horizontal);
@@ -38,7 +38,7 @@ export const select = css`
38
38
  --select-list-item-border-radius: var(--border-radius); // @presenter BorderRadius
39
39
  --select-list-item-bg-color-active: transparent; // @presenter Color
40
40
  --select-list-item-bg-color-hover: var(--menu-item-bg-color-hover); // @presenter Color
41
- --select-list-item-font-weight-active: var(--font-weight-medium); // @presenter Color
41
+ --select-list-item-font-weight-active: var(--font-weight-medium); // @presenter Color
42
42
 
43
43
  --select-placeholder-color: var(--color-warm-grey-6); // @presenter Color
44
44
  // @tokens End