@redocly/theme 0.59.0-next.2 → 0.59.0-rc.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 (53) hide show
  1. package/lib/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityApiDescriptionRelations.js +1 -1
  2. package/lib/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityTeamRelations.js +1 -1
  3. package/lib/components/Catalog/CatalogTagsWithTooltip.js +1 -1
  4. package/lib/components/Dropdown/Dropdown.d.ts +2 -16
  5. package/lib/components/Dropdown/Dropdown.js +5 -5
  6. package/lib/components/Menu/MenuItem.js +1 -1
  7. package/lib/components/OpenApiDocs/hooks/AdditionalOverviewInfo.d.ts +1 -0
  8. package/lib/components/OpenApiDocs/hooks/AdditionalOverviewInfo.js +11 -0
  9. package/lib/components/OpenApiDocs/hooks/AfterOpenApiDescription.d.ts +1 -0
  10. package/lib/components/OpenApiDocs/hooks/AfterOpenApiDescription.js +5 -0
  11. package/lib/components/Search/SearchAiConversationInput.d.ts +1 -2
  12. package/lib/components/Search/SearchAiConversationInput.js +3 -11
  13. package/lib/components/Search/SearchDialog.js +3 -6
  14. package/lib/components/Search/variables.js +1 -5
  15. package/lib/components/Select/variables.js +2 -2
  16. package/lib/components/Tag/Tag.js +4 -4
  17. package/lib/core/constants/search.d.ts +4 -5
  18. package/lib/core/constants/search.js +5 -4
  19. package/lib/core/hooks/use-tabs.d.ts +2 -3
  20. package/lib/core/hooks/use-tabs.js +57 -115
  21. package/lib/core/types/hooks.d.ts +2 -2
  22. package/lib/ext/process-scorecard.d.ts +5 -0
  23. package/lib/ext/process-scorecard.js +11 -0
  24. package/lib/icons/AiStarsIcon/AiStarsIcon.js +2 -11
  25. package/lib/icons/RedoclyIcon/RedoclyIcon.js +7 -4
  26. package/lib/index.d.ts +2 -0
  27. package/lib/index.js +2 -0
  28. package/lib/markdoc/components/Tabs/TabList.d.ts +1 -3
  29. package/lib/markdoc/components/Tabs/TabList.js +47 -197
  30. package/lib/markdoc/components/Tabs/Tabs.d.ts +1 -2
  31. package/lib/markdoc/components/Tabs/Tabs.js +12 -57
  32. package/package.json +3 -3
  33. package/src/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityApiDescriptionRelations.tsx +1 -1
  34. package/src/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityTeamRelations.tsx +1 -1
  35. package/src/components/Catalog/CatalogTagsWithTooltip.tsx +5 -1
  36. package/src/components/Dropdown/Dropdown.tsx +79 -84
  37. package/src/components/Menu/MenuItem.tsx +0 -1
  38. package/src/components/OpenApiDocs/hooks/AdditionalOverviewInfo.tsx +9 -0
  39. package/src/components/OpenApiDocs/hooks/AfterOpenApiDescription.tsx +1 -0
  40. package/src/components/Search/SearchAiConversationInput.tsx +2 -12
  41. package/src/components/Search/SearchDialog.tsx +3 -6
  42. package/src/components/Search/variables.ts +1 -5
  43. package/src/components/Select/variables.ts +2 -2
  44. package/src/components/Tag/Tag.tsx +6 -6
  45. package/src/core/constants/search.ts +4 -8
  46. package/src/core/hooks/use-tabs.ts +86 -168
  47. package/src/core/types/hooks.ts +1 -5
  48. package/src/ext/process-scorecard.ts +13 -0
  49. package/src/icons/AiStarsIcon/AiStarsIcon.tsx +2 -11
  50. package/src/icons/RedoclyIcon/RedoclyIcon.tsx +22 -4
  51. package/src/index.ts +2 -0
  52. package/src/markdoc/components/Tabs/TabList.tsx +105 -312
  53. package/src/markdoc/components/Tabs/Tabs.tsx +11 -136
@@ -1,7 +1,7 @@
1
- import React, { cloneElement, useRef, forwardRef } from 'react';
1
+ import React, { cloneElement, useRef } from 'react';
2
2
  import styled from 'styled-components';
3
3
 
4
- import type { PropsWithChildren, ReactElement } from 'react';
4
+ import type { PropsWithChildren, ReactElement, JSX } 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,89 +32,84 @@ export type DropdownProps = PropsWithChildren<{
32
32
  onClose?: () => void;
33
33
  }>;
34
34
 
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}
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}
103
107
  >
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
- );
108
+ {children}
109
+ </ChildrenWrapper>
110
+ </DropdownWrapper>
111
+ );
112
+ }
118
113
 
119
114
  const DropdownWrapper = styled.div`
120
115
  --button-gap: var(--spacing-xxs);
@@ -82,7 +82,6 @@ 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}
86
85
  >
87
86
  {hasChevron ? <ChevronWrapper>{chevron}</ChevronWrapper> : null}
88
87
  <MenuItemIcon icon={item.icon} srcSet={item.srcSet} />
@@ -0,0 +1,9 @@
1
+ // interface AdditionalOverviewInfoProps {
2
+ // info: any;
3
+ // }
4
+
5
+ // export function AdditionalOverviewInfo(_props: AdditionalOverviewInfoProps) {
6
+ // return null;
7
+ // }
8
+
9
+ export const AdditionalOverviewInfo: any = null;
@@ -0,0 +1 @@
1
+ export const AfterOpenApiDescription: any = null;
@@ -13,7 +13,6 @@ type SearchAiConversationInputProps = {
13
13
  isGeneratingResponse: boolean;
14
14
  placeholder?: string;
15
15
  className?: string;
16
- disabled?: boolean;
17
16
  };
18
17
 
19
18
  export function SearchAiConversationInput({
@@ -21,7 +20,6 @@ export function SearchAiConversationInput({
21
20
  onMessageSent,
22
21
  className,
23
22
  placeholder,
24
- disabled,
25
23
  }: SearchAiConversationInputProps): JSX.Element {
26
24
  const { useTranslate } = useThemeHooks();
27
25
  const { translate } = useTranslate();
@@ -38,8 +36,6 @@ export function SearchAiConversationInput({
38
36
  }, [isGeneratingResponse]);
39
37
 
40
38
  const handleSendMessage = () => {
41
- if (disabled) return;
42
-
43
39
  setQuery('');
44
40
  onMessageSent(query);
45
41
  };
@@ -50,7 +46,7 @@ export function SearchAiConversationInput({
50
46
  }
51
47
  };
52
48
 
53
- const isDisabled = disabled || isGeneratingResponse || query.trim().length === 0;
49
+ const isDisabled = isGeneratingResponse || query.trim().length === 0;
54
50
 
55
51
  return (
56
52
  <SearchAiConversationInputWrapper
@@ -66,7 +62,7 @@ export function SearchAiConversationInput({
66
62
  onChange={(e) => setQuery(e.target.value)}
67
63
  onKeyUp={handleOnKeyUp}
68
64
  value={query}
69
- disabled={disabled || isGeneratingResponse}
65
+ disabled={isGeneratingResponse}
70
66
  maxLength={AI_SEARCH_MAX_MESSAGE_LENGTH}
71
67
  />
72
68
 
@@ -115,10 +111,6 @@ const ConversationInput = styled.input`
115
111
  border-color: var(--search-ai-conversation-input-border-color-focus);
116
112
  }
117
113
 
118
- &:disabled {
119
- background-color: var(--search-ai-conversation-input-bg-color-disabled);
120
- }
121
-
122
114
  &:focus:disabled {
123
115
  border-color: var(--search-ai-conversation-input-border-color-disabled);
124
116
  }
@@ -134,8 +126,6 @@ const SendButton = styled(Button)`
134
126
  display: flex;
135
127
  align-items: center;
136
128
  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);
139
129
 
140
130
  &:hover {
141
131
  background-color: var(--search-ai-conversation-input-send-button-bg-color-hover);
@@ -48,7 +48,6 @@ export function SearchDialog({
48
48
  const products = useProducts();
49
49
  const currentProduct = useCurrentProduct();
50
50
  const [product, setProduct] = useState(currentProduct);
51
- const searchSessionId = `search-${Date.now()}-${Math.random().toString(36).substring(2, 8)}`;
52
51
  const [mode, setMode] = useState<'search' | 'ai-dialog'>(initialMode);
53
52
  const autoSearchDisabled = mode !== 'search';
54
53
  const {
@@ -63,7 +62,7 @@ export function SearchDialog({
63
62
  advancedSearch,
64
63
  askAi,
65
64
  groupField,
66
- } = useSearch(product?.name, autoSearchDisabled, searchSessionId);
65
+ } = useSearch(product?.name, autoSearchDisabled);
67
66
  const {
68
67
  isFilterOpen,
69
68
  onFilterToggle,
@@ -73,7 +72,7 @@ export function SearchDialog({
73
72
  onQuickFilterReset,
74
73
  } = useSearchFilter(filter, setFilter);
75
74
  const { addSearchHistoryItem } = useRecentSearches();
76
- const aiSearch = useAiSearch({ filter }, searchSessionId);
75
+ const aiSearch = useAiSearch({ filter });
77
76
 
78
77
  const searchInputRef = useRef<HTMLInputElement>(null);
79
78
  const modalRef = useRef<HTMLDivElement>(null);
@@ -151,14 +150,13 @@ export function SearchDialog({
151
150
  totalResults: results.length.toString(),
152
151
  index: index.toString(),
153
152
  searchEngine: mode,
154
- searchSessionId,
155
153
  });
156
154
  onClose();
157
155
  }}
158
156
  />
159
157
  );
160
158
  },
161
- [onClose, product, products, addSearchHistoryItem, query, telemetry, mode, searchSessionId],
159
+ [onClose, product, products, addSearchHistoryItem, query, telemetry, mode],
162
160
  );
163
161
 
164
162
  const showLoadMore = useCallback(
@@ -391,7 +389,6 @@ export function SearchDialog({
391
389
  telemetry.sendSearchRecentClickedMessage({
392
390
  query,
393
391
  index: index.toString(),
394
- searchSessionId,
395
392
  });
396
393
  setQuery(query);
397
394
  focusSearchInput();
@@ -171,7 +171,6 @@ 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%;
175
174
 
176
175
  --search-ai-resources-gap: var(--spacing-base);
177
176
  --search-ai-resources-title-font-weight: var(--font-weight-medium);
@@ -233,7 +232,6 @@ export const search = css`
233
232
  * @tokens AI Search Conversation Input
234
233
  */
235
234
  --search-ai-conversation-input-bg-color: var(--bg-color);
236
- --search-ai-conversation-input-bg-color-disabled: var(--color-warm-grey-1);
237
235
  --search-ai-conversation-input-padding: var(--spacing-sm) var(--spacing-md);
238
236
  --search-ai-conversation-input-border: 1px solid var(--border-color-secondary);
239
237
  --search-ai-conversation-input-border-radius: var(--border-radius-lg);
@@ -243,12 +241,10 @@ export const search = css`
243
241
  --search-ai-conversation-input-border-color-disabled: var(--border-color-secondary);
244
242
 
245
243
  --search-ai-conversation-input-send-button-right: 12px;
246
- --search-ai-conversation-input-send-button-padding: 5px;
247
244
  --search-ai-conversation-input-send-button-bg-color: var(--button-bg-color-primary);
248
245
  --search-ai-conversation-input-send-button-bg-color-hover: var(--button-bg-color-primary-hover);
249
246
  --search-ai-conversation-input-send-button-bg-color-disabled: var(--button-bg-color-disabled);
250
247
  --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);
252
248
 
253
249
  /**
254
250
  * @tokens AI Search Response
@@ -281,7 +277,7 @@ export const search = css`
281
277
 
282
278
  --search-ai-suggestions-gap: var(--spacing-sm);
283
279
  --search-ai-suggestions-margin-left: var(--spacing-xs);
284
- --search-ai-suggestion-item-gap: var(--spacing-xxs);
280
+ --search-ai-suggestion-item-gap: var(--spacing-xs);
285
281
 
286
282
  --search-ai-suggestions-title-text-color: var(--text-color-description);
287
283
  --search-ai-suggestions-title-font-size: var(--font-size-base);
@@ -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
@@ -229,23 +229,23 @@ const TagWrapper = styled.div.attrs(({ className, color, size }: TagProps) => ({
229
229
  color: var(--tag-color);
230
230
  background-color: ${({ variant }) =>
231
231
  variant === 'filled' ? 'var(--tag-bg-color)' : 'transparent'};
232
- ${({ borderless, variant }) =>
232
+ ${({ borderless }) =>
233
233
  borderless
234
234
  ? ''
235
- : `border: var(--tag-border-width) var(--tag-border-style) ${variant === 'filled' ? 'transparent' : 'var(--tag-border-color)'};`}
235
+ : `border: var(--tag-border-width) var(--tag-border-style) var(--tag-border-color);`}
236
236
  border-radius: var(--tag-border-radius);
237
237
 
238
238
  svg {
239
239
  width: var(--tag-icon-width);
240
240
  height: var(--tag-icon-height);
241
241
  }
242
-
242
+ /*
243
243
  &:hover {
244
244
  background-color: ${({ variant }) =>
245
- variant === 'filled' ? 'var(--tag-bg-color-hover)' : 'transparent'};
245
+ variant === 'filled' ? 'var(--tag-bg-color-hover)' : 'transparent'};
246
246
  border-color: ${({ variant }) =>
247
- variant === 'outline' ? 'var(--tag-border-color-hover)' : 'transparent'};
248
- }
247
+ variant === 'outline' ? 'var(--tag-border-color-hover)' : 'transparent'};
248
+ } */
249
249
 
250
250
  &:focus-visible {
251
251
  outline: 1px solid var(--tag-border-color-focused);
@@ -7,14 +7,10 @@ export enum AiSearchError {
7
7
  EmptyResponse = 'empty_response',
8
8
  ErrorProcessingResponse = 'error_processing_response',
9
9
  }
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];
10
+ export const enum AiSearchConversationRole {
11
+ USER = 'user',
12
+ ASSISTANT = 'assistant',
13
+ }
18
14
 
19
15
  const defaultErrorConfig: AiSearchErrorConfig = {
20
16
  headerKey: 'search.ai.error.header',