@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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redocly/theme",
3
- "version": "0.59.0-next.0",
3
+ "version": "0.59.0-next.2",
4
4
  "description": "Shared UI components lib",
5
5
  "keywords": [
6
6
  "theme",
@@ -63,10 +63,10 @@
63
63
  "styled-system": "5.1.5",
64
64
  "ts-node": "10.9.2",
65
65
  "ts-node-dev": "2.0.0",
66
- "tsc-alias": "1.8.10",
66
+ "tsc-alias": "1.8.16",
67
67
  "tsconfig-paths": "4.2.0",
68
68
  "tsconfig-paths-webpack-plugin": "3.5.2",
69
- "typescript": "5.6.2",
69
+ "typescript": "5.9.3",
70
70
  "vitest": "3.2.4",
71
71
  "vitest-when": "0.6.2",
72
72
  "webpack": "5.94.0"
@@ -84,10 +84,10 @@
84
84
  "lodash.debounce": "^4.0.8",
85
85
  "lodash.throttle": "4.1.1",
86
86
  "nprogress": "0.2.0",
87
- "openapi-sampler": "1.6.1",
87
+ "openapi-sampler": "1.6.2",
88
88
  "react-calendar": "5.1.0",
89
89
  "react-date-picker": "11.0.0",
90
- "@redocly/config": "0.35.1",
90
+ "@redocly/config": "0.36.0",
91
91
  "@redocly/realm-asyncapi-sdk": "0.5.0-next.0"
92
92
  },
93
93
  "scripts": {
@@ -0,0 +1,100 @@
1
+ import React, { useEffect, useState } from 'react';
2
+ import styled from 'styled-components';
3
+
4
+ import type { BaseSyntheticEvent, PropsWithChildren, ReactNode, JSX } from 'react';
5
+ import type { AccordionHeaderProps } from '@redocly/theme/components/Accordion/AccordionHeader';
6
+
7
+ import { AccordionBody } from '@redocly/theme/components/Accordion/AccordionBody';
8
+ import { AccordionHeader } from '@redocly/theme/components/Accordion/AccordionHeader';
9
+ import { AccordionTitle } from '@redocly/theme/components/Accordion/AccordionTitle';
10
+ import { ChevronDownIcon } from '@redocly/theme/icons/ChevronDownIcon/ChevronDownIcon';
11
+ import { ChevronRightIcon } from '@redocly/theme/icons/ChevronRightIcon/ChevronRightIcon';
12
+
13
+ export type AccordionProps = {
14
+ expanded?: boolean;
15
+ isExpandable?: boolean;
16
+ className?: string;
17
+ renderChildrenHidden?: boolean;
18
+ header?: ReactNode | ((props: AccordionHeaderProps) => ReactNode);
19
+ onToggle?: (expanded: boolean) => void;
20
+ dataTestId?: string;
21
+ };
22
+
23
+ export function Accordion({
24
+ expanded = true,
25
+ isExpandable = true,
26
+ renderChildrenHidden = false,
27
+ header,
28
+ className,
29
+ children,
30
+ onToggle,
31
+ dataTestId,
32
+ }: PropsWithChildren<AccordionProps>): JSX.Element {
33
+ const [isExpanded, setExpanded] = useState(expanded);
34
+ const [animate, setAnimate] = useState(false);
35
+
36
+ const toggle = ({ target }: BaseSyntheticEvent): void => {
37
+ if (target instanceof HTMLAnchorElement || !isExpandable) return;
38
+ setAnimate(true);
39
+ setExpanded(!isExpanded);
40
+ onToggle?.(!isExpanded);
41
+ };
42
+
43
+ useEffect(() => setExpanded(expanded), [expanded]);
44
+
45
+ return (
46
+ <AccordionWrapper
47
+ className={className}
48
+ data-testid={dataTestId}
49
+ data-component-name="Accordion/Accordion"
50
+ >
51
+ {header &&
52
+ (typeof header === 'function' ? (
53
+ header({ expanded: isExpanded })
54
+ ) : (
55
+ <AccordionHeader
56
+ data-testid="accordion-header"
57
+ onClick={toggle}
58
+ expanded={isExpanded}
59
+ isExpandable={isExpandable}
60
+ >
61
+ <HeaderContent>
62
+ <AccordionTitle data-testid="title">{header}</AccordionTitle>
63
+ {isExpandable &&
64
+ (isExpanded ? (
65
+ <ChevronDownIcon color="--accordion-chevron-icon-color" />
66
+ ) : (
67
+ <ChevronRightIcon color="--accordion-chevron-icon-color" />
68
+ ))}
69
+ </HeaderContent>
70
+ </AccordionHeader>
71
+ ))}
72
+
73
+ {(isExpanded || renderChildrenHidden) && (
74
+ <AccordionBody data-testid="accordion-body" hidden={!isExpanded} animate={animate}>
75
+ {children}
76
+ </AccordionBody>
77
+ )}
78
+ </AccordionWrapper>
79
+ );
80
+ }
81
+
82
+ const AccordionWrapper = styled.div`
83
+ background-color: transparent;
84
+ font-family: var(--accordion-font-family);
85
+ font-size: var(--accordion-font-size);
86
+ font-weight: var(--accordion-font-weight);
87
+ border-radius: var(--accordion-border-radius);
88
+ border: var(--accordion-border);
89
+
90
+ &:not(:last-child) {
91
+ margin-bottom: var(--accordion-gap);
92
+ }
93
+ `;
94
+
95
+ const HeaderContent = styled.div`
96
+ display: flex;
97
+ align-items: center;
98
+ width: 100%;
99
+ gap: var(--spacing-xs);
100
+ `;
@@ -0,0 +1,65 @@
1
+ import React from 'react';
2
+ import styled, { keyframes, css } from 'styled-components';
3
+
4
+ import type { JSX, ReactNode } from 'react';
5
+
6
+ type AccordionBodyWrapperProps = {
7
+ $animate?: boolean;
8
+ $hidden?: boolean;
9
+ };
10
+
11
+ export type AccordionBodyProps = {
12
+ animate?: boolean;
13
+ hidden?: boolean;
14
+ children?: ReactNode;
15
+ className?: string;
16
+ };
17
+
18
+ export function AccordionBody({
19
+ animate,
20
+ hidden,
21
+ children,
22
+ className,
23
+ }: AccordionBodyProps): JSX.Element {
24
+ return (
25
+ <AccordionBodyWrapper
26
+ className={className}
27
+ $animate={animate}
28
+ $hidden={hidden}
29
+ data-component-name="Accordion/AccordionBody"
30
+ >
31
+ {children}
32
+ </AccordionBodyWrapper>
33
+ );
34
+ }
35
+
36
+ const showAccordion = keyframes`
37
+ 0% {
38
+ opacity: 0;
39
+ transform: translateY(-5px);
40
+ }
41
+ 100% {
42
+ opacity: 1;
43
+ transform: translateY(0);
44
+ }
45
+ `;
46
+
47
+ const showAccordionAnimation = css`
48
+ animation: ${showAccordion} 0.15s ease-out;
49
+ `;
50
+
51
+ const AccordionBodyWrapper = styled.div<AccordionBodyWrapperProps>`
52
+ ${({ $animate }) => $animate && showAccordionAnimation};
53
+ ${({ $hidden }) => $hidden && 'visibility: hidden'};
54
+
55
+ background-color: var(--accordion-body-bg-color);
56
+
57
+ font-family: var(--accordion-body-font-family);
58
+ font-size: var(--accordion-body-font-size);
59
+ font-weight: var(--accordion-body-font-weight);
60
+ border: var(--accordion-body-border);
61
+ padding: var(--accordion-body-padding);
62
+ color: var(--accordion-body-text-color);
63
+
64
+ border-radius: var(--accordion-border-radius);
65
+ `;
@@ -0,0 +1,68 @@
1
+ import React from 'react';
2
+ import styled from 'styled-components';
3
+
4
+ import type { BaseSyntheticEvent, JSX, ReactNode } from 'react';
5
+
6
+ export type AccordionHeaderProps = {
7
+ isExpandable?: boolean;
8
+ expanded?: boolean;
9
+ disabled?: boolean;
10
+ children?: ReactNode;
11
+ className?: string;
12
+ onClick?: (e: BaseSyntheticEvent) => void;
13
+ };
14
+
15
+ type AccordionHeaderWrapperProps = {
16
+ $isExpandable?: boolean;
17
+ $expanded?: boolean;
18
+ $disabled?: boolean;
19
+ };
20
+
21
+ export function AccordionHeader({
22
+ isExpandable,
23
+ expanded,
24
+ disabled,
25
+ children,
26
+ className,
27
+ onClick,
28
+ }: AccordionHeaderProps): JSX.Element {
29
+ return (
30
+ <AccordionHeaderWrapper
31
+ className={className}
32
+ $isExpandable={isExpandable}
33
+ $expanded={expanded}
34
+ $disabled={disabled}
35
+ onClick={onClick}
36
+ data-component-name="Accordion/AccordionHeader"
37
+ >
38
+ {children}
39
+ </AccordionHeaderWrapper>
40
+ );
41
+ }
42
+
43
+ const AccordionHeaderWrapper = styled.div<AccordionHeaderWrapperProps>`
44
+ display: flex;
45
+ gap: var(--spacing-xs);
46
+ align-items: center;
47
+ justify-content: space-between;
48
+ min-height: 32px;
49
+ color: var(--accordion-header-text-color);
50
+
51
+ cursor: ${({ $isExpandable = true }) => ($isExpandable ? 'pointer' : 'default')};
52
+
53
+ line-height: var(--accordion-header-line-height);
54
+ font-size: var(--accordion-header-font-size);
55
+ font-family: var(--accordion-header-font-family);
56
+ font-weight: var(--accordion-header-font-weight);
57
+ padding: var(--accordion-header-padding);
58
+ border: var(--accordion-header-border);
59
+ background-color: var(--accordion-header-bg-color);
60
+ border-radius: var(--accordion-border-radius);
61
+
62
+ pointer-events: ${({ $disabled }) => ($disabled ? 'none' : 'auto')};
63
+
64
+ &:hover {
65
+ color: ${({ $isExpandable = true }) =>
66
+ $isExpandable ? 'var(--text-color-primary)' : 'var(--accordion-header-text-color)'};
67
+ }
68
+ `;
@@ -0,0 +1,26 @@
1
+ import React from 'react';
2
+ import styled from 'styled-components';
3
+
4
+ import type { JSX, ReactNode } from 'react';
5
+
6
+ export type AccordionTitleProps = {
7
+ children?: ReactNode;
8
+ className?: string;
9
+ };
10
+
11
+ export function AccordionTitle({ children, className }: AccordionTitleProps): JSX.Element {
12
+ return (
13
+ <AccordionTitleWrapper className={className} data-component-name="Accordion/AccordionTitle">
14
+ {children}
15
+ </AccordionTitleWrapper>
16
+ );
17
+ }
18
+
19
+ const AccordionTitleWrapper = styled.span`
20
+ font-weight: var(--accordion-header-font-weight);
21
+ line-height: var(--line-height-base);
22
+ overflow: hidden;
23
+ text-overflow: ellipsis;
24
+ color: var(--accordion-header-text-color);
25
+ flex: 1;
26
+ `;
@@ -0,0 +1,56 @@
1
+ import { css } from 'styled-components';
2
+
3
+ export const accordion = css`
4
+ /**
5
+ * @tokens Accordion spacing
6
+ * @presenter Spacing
7
+ */
8
+
9
+ --accordion-gap: var(--spacing-base);
10
+
11
+ /**
12
+ * @tokens Accordion common
13
+ */
14
+
15
+ --accordion-border-radius: var(--border-radius); // @presenter BorderRadius
16
+ --accordion-border: none; // @presenter Border
17
+
18
+ --accordion-line-height: var(--line-height-base); // @presenter LineHeight
19
+ --accordion-font-size: var(--font-size-base); // @presenter FontSize
20
+ --accordion-font-family: var(--font-family-base); // @presenter FontFamily
21
+ --accordion-font-weight: var(--font-weight-regular); // @presenter FontWeight
22
+
23
+ /**
24
+ * @tokens Accordion header common
25
+ */
26
+
27
+ --accordion-header-font-family: var(--font-family-base); // @presenter FontFamily
28
+ --accordion-header-font-size: var(--font-size-base); // @presenter FontSize
29
+ --accordion-header-font-weight: var(--font-weight-medium, 500); // @presenter FontWeight
30
+ --accordion-header-text-color: var(--text-color-primary);
31
+ --accordion-header-padding: var(--spacing-sm) var(--spacing-base);
32
+ --accordion-header-line-height: var(--line-height-base); // @presenter LineHeight
33
+ --accordion-header-bg-color: transparent; // @presenter Color
34
+ --accordion-header-border: none; // @presenter Border
35
+
36
+ /**
37
+ * @tokens Accordion body common
38
+ */
39
+
40
+ --accordion-body-font-family: var(--font-family-base); // @presenter FontFamily
41
+ --accordion-body-font-size: var(--font-size-base); // @presenter FontSize
42
+ --accordion-body-font-weight: var(--font-weight-regular); // @presenter FontWeight
43
+ --accordion-body-text-color: var(--text-color-secondary);
44
+ --accordion-body-padding: 0 var(--spacing-xs) var(--spacing-sm);
45
+ --accordion-body-bg-color: transparent; // @presenter Color
46
+ --accordion-body-border: none; // @presenter Border
47
+
48
+ /**
49
+ * @tokens Accordion chevron icon
50
+ */
51
+
52
+ --accordion-chevron-icon-color: var(--text-color-secondary); // @presenter Color
53
+ --accordion-chevron-icon-size: 16px;
54
+
55
+ // @tokens End
56
+ `;
@@ -0,0 +1,141 @@
1
+ import * as React from 'react';
2
+ import { useState } from 'react';
3
+ import styled from 'styled-components';
4
+
5
+ import { Button } from '@redocly/theme/components/Button/Button';
6
+ import { SearchDialog } from '@redocly/theme/components/Search/SearchDialog';
7
+ import { useThemeConfig, useThemeHooks } from '@redocly/theme/core/hooks';
8
+ import { ChatIcon } from '@redocly/theme/icons/ChatIcon/ChatIcon';
9
+ import { AiStarsGradientIcon } from '@redocly/theme/icons/AiStarsGradientIcon/AiStarsGradientIcon';
10
+ import { RedoclyIcon } from '@redocly/theme/icons/RedoclyIcon/RedoclyIcon';
11
+
12
+ type AIAssistantButtonIconType = 'chat' | 'sparkles' | 'redocly';
13
+ type AIAssistantButtonType = 'button' | 'icon';
14
+
15
+ interface AIAssistantButtonConfig {
16
+ hide?: boolean;
17
+ inputType?: AIAssistantButtonType;
18
+ inputIcon?: AIAssistantButtonIconType;
19
+ }
20
+
21
+ const defaultConfig: Required<AIAssistantButtonConfig> = {
22
+ hide: false,
23
+ inputType: 'button',
24
+ inputIcon: 'redocly',
25
+ };
26
+
27
+ const getIcon = (
28
+ iconType: AIAssistantButtonIconType,
29
+ inputType: AIAssistantButtonType = 'button',
30
+ ) => {
31
+ const iconSize =
32
+ inputType === 'icon'
33
+ ? 'var(--ai-assistant-button-icon-icon-size)'
34
+ : 'var(--ai-assistant-button-text-icon-size)';
35
+
36
+ const redoclyIcon = (
37
+ <RedoclyIcon size={iconSize} color="var(--ai-assistant-button-redocly-icon-color)" />
38
+ );
39
+ const sparklesIcon = (
40
+ <AiStarsGradientIcon size={iconSize} color="var(--search-ai-button-icon-color)" />
41
+ );
42
+ const chatIcon = <ChatIcon size={iconSize} />;
43
+
44
+ switch (iconType) {
45
+ case 'chat':
46
+ return chatIcon;
47
+ case 'sparkles':
48
+ return sparklesIcon;
49
+ case 'redocly':
50
+ return redoclyIcon;
51
+ default:
52
+ return redoclyIcon;
53
+ }
54
+ };
55
+
56
+ export function AIAssistantButton() {
57
+ const [isOpen, setIsOpen] = useState(false);
58
+ const themeConfig = useThemeConfig();
59
+ const { useTranslate } = useThemeHooks();
60
+ const { translate } = useTranslate();
61
+
62
+ const buttonConfig = {
63
+ ...defaultConfig,
64
+ ...(themeConfig.aiAssistant?.trigger ?? {}),
65
+ };
66
+
67
+ const { hide, inputIcon, inputType } = buttonConfig;
68
+
69
+ if (hide) {
70
+ return null;
71
+ }
72
+
73
+ const icon = getIcon(inputIcon, inputType);
74
+ const text = translate('aiAssistant.trigger', 'Ask AI');
75
+
76
+ const handleOpen = () => {
77
+ setIsOpen(true);
78
+ };
79
+
80
+ const handleClose = () => {
81
+ setIsOpen(false);
82
+ };
83
+
84
+ return (
85
+ <>
86
+ <StyledAIAssistantButton
87
+ variant="outlined"
88
+ size="medium"
89
+ $inputType={inputType}
90
+ onClick={handleOpen}
91
+ aria-label={`AI Assistant button - ${inputIcon}`}
92
+ data-component-name="Buttons/AIAssistantButton"
93
+ >
94
+ {icon}
95
+ {inputType === 'button' && text}
96
+ </StyledAIAssistantButton>
97
+
98
+ {isOpen && <SearchDialog onClose={handleClose} initialMode="ai-dialog" />}
99
+ </>
100
+ );
101
+ }
102
+
103
+ const StyledAIAssistantButton = styled(Button)<{ $inputType?: AIAssistantButtonType }>`
104
+ position: fixed;
105
+ bottom: var(--ai-assistant-button-bottom);
106
+ right: var(--ai-assistant-button-right);
107
+ ${({ $inputType }) =>
108
+ $inputType === 'icon'
109
+ ? `
110
+ border-radius: var(--ai-assistant-button-border-radius-icon);
111
+ width: var(--ai-assistant-button-icon-size);
112
+ height: var(--ai-assistant-button-icon-size);
113
+ `
114
+ : `
115
+ border-radius: var(--ai-assistant-button-border-radius-text);
116
+ padding: var(--ai-assistant-button-text-padding);
117
+ height: var(--ai-assistant-button-text-height);
118
+ `}
119
+ min-width: var(--ai-assistant-button-min-width);
120
+ font-size: var(--ai-assistant-button-font-size);
121
+ font-weight: var(--ai-assistant-button-font-weight);
122
+ box-shadow: var(--bg-raised-shadow);
123
+ z-index: var(--ai-assistant-button-z-index);
124
+ display: flex;
125
+ align-items: center;
126
+ justify-content: center;
127
+ gap: var(--ai-assistant-button-gap);
128
+ background-color: var(--ai-assistant-button-bg-color) !important;
129
+
130
+ transition: var(--ai-assistant-button-transition);
131
+
132
+ &:hover {
133
+ box-shadow: var(--ai-assistant-button-shadow-hover);
134
+ transform: var(--ai-assistant-button-transform-hover);
135
+ }
136
+
137
+ &:active {
138
+ transform: var(--bg-raised-shadow);
139
+ box-shadow: var(--ai-assistant-button-shadow-active);
140
+ }
141
+ `;
@@ -0,0 +1,7 @@
1
+ import { css } from 'styled-components';
2
+
3
+ export const aiAssistantButtonDarkMode = css`
4
+
5
+ /* Background color */
6
+ --ai-assistant-button-bg-color: var(--color-warm-grey-4);
7
+ `;
@@ -0,0 +1,48 @@
1
+ import { css } from 'styled-components';
2
+
3
+ export const aiAssistantButton = css`
4
+ /**
5
+ * @tokens AI Assistant Button
6
+ * @presenter Color
7
+ */
8
+
9
+ /* Button sizing */
10
+ --ai-assistant-button-icon-size: 40px;
11
+ --ai-assistant-button-text-height: 40px;
12
+ --ai-assistant-button-text-padding: var(--spacing-sm) var(--spacing-md);
13
+ --ai-assistant-button-border-radius-icon: 50%;
14
+ --ai-assistant-button-border-radius-text: 1.75rem;
15
+ --ai-assistant-button-min-width: auto;
16
+
17
+ /* Icon sizing */
18
+ --ai-assistant-button-icon-icon-size: 18px;
19
+ --ai-assistant-button-text-icon-size: 20px;
20
+
21
+ /* Positioning */
22
+ --ai-assistant-button-bottom: var(--spacing-xl);
23
+ --ai-assistant-button-right: var(--spacing-xl);
24
+ --ai-assistant-button-z-index: 1000;
25
+
26
+ /* Typography */
27
+ --ai-assistant-button-font-size: var(--font-size-base);
28
+ --ai-assistant-button-font-weight: var(--font-weight-medium);
29
+ --ai-assistant-button-gap: var(--spacing-xs);
30
+
31
+ /* Background color */
32
+ --ai-assistant-button-bg-color: var(--color-static-white);
33
+
34
+ /* Icon colors */
35
+ --ai-assistant-button-redocly-icon-color: #297AFE;
36
+
37
+ /* Transform */
38
+ --ai-assistant-button-transform-hover: none;
39
+ --ai-assistant-button-transform-active: translateY(0);
40
+
41
+ /* Shadow */
42
+ --ai-assistant-button-shadow-hover:
43
+ 2px 1px 12px 4px rgba(143, 98, 254, 0.2),
44
+ -3px -2px 24px 0px rgba(41, 122, 254, 0.2);
45
+
46
+ /* Transition */
47
+ --ai-assistant-button-transition: box-shadow 0.3s ease, transform 0.2s ease;
48
+ `;
@@ -10,7 +10,7 @@ import {
10
10
  import { breakpoints } from '@redocly/theme/core/utils';
11
11
  import { useThemeHooks } from '@redocly/theme/core/hooks';
12
12
  import { H3 } from '@redocly/theme/components/Typography/H3';
13
- import { FilterContent } from '@redocly/theme/components/Filter/FilterContent';
13
+ import { CatalogFilterContent } from '@redocly/theme/components/Catalog/CatalogFilter/CatalogFilterContent';
14
14
  import { Sidebar, SidebarHeader } from '@redocly/theme/components/Sidebar/Sidebar';
15
15
  import { CatalogSelector } from '@redocly/theme/components/Catalog/CatalogSelector';
16
16
  import { SidebarActions } from '@redocly/theme/components/SidebarActions/SidebarActions';
@@ -20,8 +20,11 @@ import { CatalogViewModeToggle } from '@redocly/theme/components/Catalog/Catalog
20
20
  import { CatalogSortButton } from '@redocly/theme/components/Catalog/CatalogSortButton';
21
21
  import { CatalogEntities } from '@redocly/theme/components/Catalog/CatalogEntities';
22
22
 
23
+ type CatalogFiltersWithCounts = Record<string, { value: string; count: number }[]>;
24
+
23
25
  export type CatalogProps = {
24
26
  catalogConfig: CatalogEntityConfig;
27
+ filters?: CatalogFiltersWithCounts;
25
28
  entitiesTypes: string[];
26
29
  initialEntitiesList?: BffCatalogEntityList;
27
30
  catalogSwitcherItems: CatalogSwitcherItem[];
@@ -29,9 +32,11 @@ export type CatalogProps = {
29
32
  };
30
33
 
31
34
  const customCatalogOptionsCasing = (str: string): string => {
32
- if (!str) return str;
35
+ const trimmedStr = str.trim();
36
+ if (!trimmedStr) return trimmedStr;
37
+
38
+ const words = trimmedStr.split(/[\s-_]+/);
33
39
 
34
- const words = str.split(/[\s-_]+/);
35
40
  return words
36
41
  .map((word, index) => {
37
42
  if (index === 0 && word.toLowerCase() === 'api') {
@@ -45,6 +50,7 @@ const customCatalogOptionsCasing = (str: string): string => {
45
50
  export function Catalog(props: CatalogProps): JSX.Element {
46
51
  const {
47
52
  catalogConfig,
53
+ filters: serverFilters,
48
54
  entitiesTypes,
49
55
  initialEntitiesList,
50
56
  catalogSwitcherItems,
@@ -72,7 +78,12 @@ export function Catalog(props: CatalogProps): JSX.Element {
72
78
  onChangeCollapseSidebarClick,
73
79
  layout,
74
80
  collapsedSidebar,
75
- } = useCatalog(catalogConfig, initialEntitiesList?.page.total || 0, initialViewMode);
81
+ } = useCatalog(
82
+ catalogConfig,
83
+ serverFilters,
84
+ initialEntitiesList?.page.total || 0,
85
+ initialViewMode,
86
+ );
76
87
 
77
88
  return (
78
89
  <>
@@ -89,12 +100,12 @@ export function Catalog(props: CatalogProps): JSX.Element {
89
100
  )
90
101
  }
91
102
  menu={
92
- <FilterContent
103
+ <CatalogFilterContent
93
104
  setFilterTerm={setSearchQuery}
94
105
  filters={filters}
95
106
  filterTerm={searchQuery}
96
107
  hideSearch={true}
97
- showCounter={false}
108
+ showCounter={true}
98
109
  filterValuesCasing={customCatalogOptionsCasing}
99
110
  />
100
111
  }
@@ -128,6 +139,7 @@ export function Catalog(props: CatalogProps): JSX.Element {
128
139
  <FilterInput
129
140
  value={searchQuery}
130
141
  onChange={(updatedTerm) => setSearchQuery(updatedTerm)}
142
+ dataTestId="catalog-search-input"
131
143
  />
132
144
  </CatalogSearchInputWrapper>
133
145
 
@@ -46,7 +46,7 @@ export function CatalogEntityApiDescriptionRelations({
46
46
  }: CatalogEntityApiDescriptionRelationsProps): JSX.Element {
47
47
  return (
48
48
  <div data-component-name="Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityApiDescriptionRelations">
49
- <Tabs key={entity.id} size={TabsSize.MEDIUM}>
49
+ <Tabs key={entity.id} forceReady={relations.length > 0} size={TabsSize.MEDIUM}>
50
50
  <TabItem
51
51
  label="Operations"
52
52
  icon={<MoleculesIcon />}
@@ -74,7 +74,7 @@ export function CatalogEntityTeamRelations({
74
74
  }: CatalogEntityTeamRelationsProps): JSX.Element {
75
75
  return (
76
76
  <div data-component-name="Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityTeamRelations">
77
- <Tabs size={TabsSize.MEDIUM}>
77
+ <Tabs forceReady={relations.length > 0} size={TabsSize.MEDIUM}>
78
78
  <TabItem label="Members" icon={<PeopleIcon />} onClick={() => setFilter('type:user')}>
79
79
  <CatalogEntityRelationsTable
80
80
  key="members-table"