@redocly/theme 0.64.0-next.1 → 0.64.0-next.3

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 (223) hide show
  1. package/lib/components/Admonition/Admonition.d.ts +1 -1
  2. package/lib/components/Admonition/Admonition.js +2 -0
  3. package/lib/components/Admonition/variables.dark.js +3 -0
  4. package/lib/components/Admonition/variables.js +13 -0
  5. package/lib/components/Banner/Banner.js +3 -3
  6. package/lib/components/Button/variables.dark.js +2 -2
  7. package/lib/components/Button/variables.js +3 -3
  8. package/lib/components/Catalog/CatalogActionsRow.d.ts +3 -3
  9. package/lib/components/Catalog/CatalogCardView/CatalogCard.js +4 -6
  10. package/lib/components/Catalog/CatalogEntities.d.ts +2 -2
  11. package/lib/components/Catalog/CatalogEntities.js +1 -1
  12. package/lib/components/Catalog/CatalogEntity/CatalogEntity.d.ts +1 -8
  13. package/lib/components/Catalog/CatalogEntity/CatalogEntityHistory/CatalogEntityVersionItem.js +3 -1
  14. package/lib/components/Catalog/CatalogEntity/CatalogEntityMetadata.js +1 -1
  15. package/lib/components/Catalog/CatalogEntity/CatalogEntityMethodAndPath.js +1 -1
  16. package/lib/components/Catalog/CatalogEntity/CatalogEntityProperties/CatalogEntityProperties.js +1 -0
  17. package/lib/components/Catalog/CatalogEntity/CatalogEntityProperties/CatalogEntityPropertyCard.js +2 -1
  18. package/lib/components/Catalog/CatalogEntity/CatalogEntityProperties/ContactProperty.js +2 -6
  19. package/lib/components/Catalog/CatalogEntity/CatalogEntityProperties/DomainsProperty.js +5 -5
  20. package/lib/components/Catalog/CatalogEntity/CatalogEntityProperties/FormatProperty.js +1 -1
  21. package/lib/components/Catalog/CatalogEntity/CatalogEntityProperties/OwnersProperty.js +15 -7
  22. package/lib/components/Catalog/CatalogEntity/CatalogEntityProperties/TagsProperty.js +2 -2
  23. package/lib/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityApiDescriptionRelations.d.ts +3 -3
  24. package/lib/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityApiDescriptionRelations.js +4 -1
  25. package/lib/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityDefaultRelations.d.ts +3 -3
  26. package/lib/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityDefaultRelations.js +14 -2
  27. package/lib/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityRelations.js +1 -1
  28. package/lib/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityRelationsTable.d.ts +3 -3
  29. package/lib/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityRelationsTable.js +1 -1
  30. package/lib/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityRelationsTableContent.d.ts +2 -2
  31. package/lib/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityTeamRelations.d.ts +3 -3
  32. package/lib/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityTeamRelations.js +13 -3
  33. package/lib/components/Catalog/CatalogEntity/CatalogEntitySchema.js +4 -3
  34. package/lib/components/Catalog/CatalogEntityTypeIcon.d.ts +3 -2
  35. package/lib/components/Catalog/CatalogEntityTypeIcon.js +9 -9
  36. package/lib/components/Catalog/CatalogMobileTopBar/CatalogMobileTopBar.d.ts +2 -3
  37. package/lib/components/Catalog/CatalogMobileTopBar/CatalogMobileTopBarControls.d.ts +2 -3
  38. package/lib/components/Catalog/CatalogPageDescription.js +1 -1
  39. package/lib/components/Catalog/CatalogSortButton.d.ts +4 -5
  40. package/lib/components/Catalog/CatalogTableView/CatalogDomainsCell.js +6 -2
  41. package/lib/components/Catalog/CatalogTableView/CatalogEntityCell.js +2 -2
  42. package/lib/components/Catalog/CatalogTableView/CatalogLastUpdateCell.d.ts +5 -0
  43. package/lib/components/Catalog/CatalogTableView/CatalogLastUpdateCell.js +45 -0
  44. package/lib/components/Catalog/CatalogTableView/CatalogOwnersCell.js +5 -3
  45. package/lib/components/Catalog/CatalogTableView/CatalogTableHeaderCell.d.ts +2 -3
  46. package/lib/components/Catalog/CatalogTableView/CatalogTableHeaderCell.js +3 -2
  47. package/lib/components/Catalog/CatalogTableView/CatalogTableView.d.ts +1 -2
  48. package/lib/components/Catalog/CatalogTableView/CatalogTableView.js +15 -5
  49. package/lib/components/Catalog/CatalogTableView/CatalogTagsCell.js +3 -2
  50. package/lib/components/Catalog/CatalogTableView/CatalogUserEntityCell.js +2 -2
  51. package/lib/components/Catalog/CatalogTags.d.ts +11 -0
  52. package/lib/components/Catalog/CatalogTags.js +62 -0
  53. package/lib/components/Catalog/variables.js +22 -14
  54. package/lib/components/Filter/variables.js +1 -1
  55. package/lib/components/Link/Link.js +2 -2
  56. package/lib/components/Menu/MenuItem.js +1 -0
  57. package/lib/components/Menu/variables.dark.js +2 -0
  58. package/lib/components/Menu/variables.js +4 -3
  59. package/lib/components/Search/SearchDialog.js +118 -116
  60. package/lib/components/SvgViewer/variables.dark.js +1 -1
  61. package/lib/components/Switch/variables.dark.js +2 -2
  62. package/lib/components/Switch/variables.js +1 -1
  63. package/lib/components/TableOfContent/TableOfContent.js +1 -0
  64. package/lib/components/TableOfContent/variables.js +3 -2
  65. package/lib/components/Toast/Toast.d.ts +14 -0
  66. package/lib/components/Toast/Toast.js +239 -0
  67. package/lib/components/Toast/variables.d.ts +1 -0
  68. package/lib/components/Toast/variables.js +64 -0
  69. package/lib/components/Tooltip/JsTooltip.js +1 -1
  70. package/lib/core/constants/catalog.d.ts +1 -1
  71. package/lib/core/constants/catalog.js +1 -1
  72. package/lib/core/constants/toast.d.ts +1 -0
  73. package/lib/core/constants/toast.js +5 -0
  74. package/lib/core/contexts/Toast/ToastContext.d.ts +2 -0
  75. package/lib/core/contexts/Toast/ToastContext.js +6 -0
  76. package/lib/core/contexts/Toast/ToastProvider.d.ts +3 -0
  77. package/lib/core/contexts/Toast/ToastProvider.js +156 -0
  78. package/lib/core/contexts/index.d.ts +2 -0
  79. package/lib/core/contexts/index.js +2 -0
  80. package/lib/core/hooks/catalog/use-catalog-entity-link.d.ts +8 -0
  81. package/lib/core/hooks/catalog/use-catalog-entity-link.js +42 -0
  82. package/lib/core/hooks/catalog/use-catalog-table-header-cell-actions.d.ts +2 -1
  83. package/lib/core/hooks/catalog/use-catalog-table-header-cell-actions.js +5 -3
  84. package/lib/core/hooks/index.d.ts +3 -0
  85. package/lib/core/hooks/index.js +3 -0
  86. package/lib/core/hooks/use-toast-logic.d.ts +18 -0
  87. package/lib/core/hooks/use-toast-logic.js +141 -0
  88. package/lib/core/hooks/use-toast.d.ts +11 -0
  89. package/lib/core/hooks/use-toast.js +17 -0
  90. package/lib/core/styles/dark.d.ts +3 -1
  91. package/lib/core/styles/dark.js +37 -33
  92. package/lib/core/styles/global.d.ts +6 -2
  93. package/lib/core/styles/global.js +56 -46
  94. package/lib/core/styles/palette.d.ts +6 -0
  95. package/lib/core/styles/palette.dark.d.ts +3 -0
  96. package/lib/core/styles/palette.dark.js +201 -0
  97. package/lib/core/styles/palette.js +175 -0
  98. package/lib/core/types/catalog.d.ts +23 -7
  99. package/lib/core/types/hooks.d.ts +6 -4
  100. package/lib/core/types/index.d.ts +1 -0
  101. package/lib/core/types/search.d.ts +1 -0
  102. package/lib/core/types/toast.d.ts +23 -0
  103. package/lib/core/types/toast.js +3 -0
  104. package/lib/core/utils/get-auto-dismiss-duration.d.ts +2 -0
  105. package/lib/core/utils/get-auto-dismiss-duration.js +15 -0
  106. package/lib/core/utils/index.d.ts +1 -0
  107. package/lib/core/utils/index.js +1 -0
  108. package/lib/icons/CheckboxIcon/CheckboxIcon.js +6 -4
  109. package/lib/icons/CheckboxIcon/variables.dark.js +2 -1
  110. package/lib/icons/CheckboxIcon/variables.js +3 -3
  111. package/lib/icons/IdeaIcon/IdeaIcon.d.ts +9 -0
  112. package/lib/icons/IdeaIcon/IdeaIcon.js +24 -0
  113. package/lib/icons/NewChatIcon/NewChatIcon.d.ts +11 -0
  114. package/lib/icons/NewChatIcon/NewChatIcon.js +25 -0
  115. package/lib/index.d.ts +5 -1
  116. package/lib/index.js +5 -1
  117. package/lib/markdoc/components/Heading/Heading.js +2 -2
  118. package/lib/markdoc/components/Mermaid/Mermaid.js +0 -2
  119. package/lib/markdoc/components/Tabs/variables.js +3 -3
  120. package/lib/markdoc/components/default.d.ts +0 -1
  121. package/lib/markdoc/components/default.js +0 -1
  122. package/lib/markdoc/tags/admonition.js +1 -1
  123. package/package.json +2 -2
  124. package/src/components/Admonition/Admonition.tsx +3 -1
  125. package/src/components/Admonition/variables.dark.ts +3 -0
  126. package/src/components/Admonition/variables.ts +13 -0
  127. package/src/components/Banner/Banner.tsx +7 -7
  128. package/src/components/Button/variables.dark.ts +2 -2
  129. package/src/components/Button/variables.ts +3 -3
  130. package/src/components/Catalog/CatalogActionsRow.tsx +3 -3
  131. package/src/components/Catalog/CatalogCardView/CatalogCard.tsx +4 -6
  132. package/src/components/Catalog/CatalogEntities.tsx +3 -3
  133. package/src/components/Catalog/CatalogEntity/CatalogEntity.tsx +3 -24
  134. package/src/components/Catalog/CatalogEntity/CatalogEntityHistory/CatalogEntityVersionItem.tsx +3 -1
  135. package/src/components/Catalog/CatalogEntity/CatalogEntityMetadata.tsx +1 -1
  136. package/src/components/Catalog/CatalogEntity/CatalogEntityMethodAndPath.tsx +1 -1
  137. package/src/components/Catalog/CatalogEntity/CatalogEntityProperties/CatalogEntityProperties.tsx +1 -0
  138. package/src/components/Catalog/CatalogEntity/CatalogEntityProperties/CatalogEntityPropertyCard.tsx +2 -1
  139. package/src/components/Catalog/CatalogEntity/CatalogEntityProperties/ContactProperty.tsx +8 -10
  140. package/src/components/Catalog/CatalogEntity/CatalogEntityProperties/DomainsProperty.tsx +13 -8
  141. package/src/components/Catalog/CatalogEntity/CatalogEntityProperties/FormatProperty.tsx +1 -0
  142. package/src/components/Catalog/CatalogEntity/CatalogEntityProperties/OwnersProperty.tsx +27 -15
  143. package/src/components/Catalog/CatalogEntity/CatalogEntityProperties/TagsProperty.tsx +2 -2
  144. package/src/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityApiDescriptionRelations.tsx +9 -9
  145. package/src/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityDefaultRelations.tsx +17 -9
  146. package/src/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityRelations.tsx +1 -1
  147. package/src/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityRelationsTable.tsx +4 -8
  148. package/src/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityRelationsTableContent.tsx +2 -2
  149. package/src/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityTeamRelations.tsx +16 -10
  150. package/src/components/Catalog/CatalogEntity/CatalogEntitySchema.tsx +4 -3
  151. package/src/components/Catalog/CatalogEntityTypeIcon.tsx +18 -11
  152. package/src/components/Catalog/CatalogMobileTopBar/CatalogMobileTopBar.tsx +3 -3
  153. package/src/components/Catalog/CatalogMobileTopBar/CatalogMobileTopBarControls.tsx +2 -3
  154. package/src/components/Catalog/CatalogPageDescription.tsx +1 -1
  155. package/src/components/Catalog/CatalogSortButton.tsx +5 -6
  156. package/src/components/Catalog/CatalogTableView/CatalogDomainsCell.tsx +6 -2
  157. package/src/components/Catalog/CatalogTableView/CatalogEntityCell.tsx +2 -2
  158. package/src/components/Catalog/CatalogTableView/CatalogLastUpdateCell.tsx +54 -0
  159. package/src/components/Catalog/CatalogTableView/CatalogOwnersCell.tsx +5 -2
  160. package/src/components/Catalog/CatalogTableView/CatalogTableHeaderCell.tsx +4 -3
  161. package/src/components/Catalog/CatalogTableView/CatalogTableView.tsx +17 -7
  162. package/src/components/Catalog/CatalogTableView/CatalogTagsCell.tsx +3 -2
  163. package/src/components/Catalog/CatalogTableView/CatalogUserEntityCell.tsx +2 -2
  164. package/src/components/Catalog/CatalogTags.tsx +115 -0
  165. package/src/components/Catalog/variables.ts +22 -14
  166. package/src/components/Filter/variables.ts +1 -1
  167. package/src/components/Link/Link.tsx +1 -1
  168. package/src/components/Menu/MenuItem.tsx +5 -1
  169. package/src/components/Menu/variables.dark.ts +2 -0
  170. package/src/components/Menu/variables.ts +4 -3
  171. package/src/components/Search/SearchDialog.tsx +299 -293
  172. package/src/components/SvgViewer/variables.dark.ts +1 -1
  173. package/src/components/Switch/variables.dark.ts +2 -2
  174. package/src/components/Switch/variables.ts +1 -1
  175. package/src/components/TableOfContent/TableOfContent.tsx +1 -0
  176. package/src/components/TableOfContent/variables.ts +3 -2
  177. package/src/components/Toast/Toast.tsx +289 -0
  178. package/src/components/Toast/variables.ts +61 -0
  179. package/src/components/Tooltip/JsTooltip.tsx +1 -1
  180. package/src/core/constants/catalog.ts +1 -1
  181. package/src/core/constants/toast.ts +1 -0
  182. package/src/core/contexts/Toast/ToastContext.tsx +5 -0
  183. package/src/core/contexts/Toast/ToastProvider.tsx +206 -0
  184. package/src/core/contexts/index.ts +2 -0
  185. package/src/core/hooks/catalog/use-catalog-entity-link.ts +46 -0
  186. package/src/core/hooks/catalog/use-catalog-table-header-cell-actions.ts +10 -2
  187. package/src/core/hooks/index.ts +3 -0
  188. package/src/core/hooks/use-toast-logic.ts +203 -0
  189. package/src/core/hooks/use-toast.ts +47 -0
  190. package/src/core/styles/dark.ts +9 -4
  191. package/src/core/styles/global.ts +30 -20
  192. package/src/core/styles/palette.dark.ts +199 -0
  193. package/src/core/styles/palette.ts +173 -0
  194. package/src/core/types/catalog.ts +24 -8
  195. package/src/core/types/hooks.ts +5 -10
  196. package/src/core/types/index.ts +1 -0
  197. package/src/core/types/search.ts +1 -0
  198. package/src/core/types/toast.ts +28 -0
  199. package/src/core/utils/get-auto-dismiss-duration.ts +20 -0
  200. package/src/core/utils/index.ts +1 -0
  201. package/src/icons/CheckboxIcon/CheckboxIcon.tsx +26 -17
  202. package/src/icons/CheckboxIcon/variables.dark.ts +2 -1
  203. package/src/icons/CheckboxIcon/variables.ts +3 -3
  204. package/src/icons/IdeaIcon/IdeaIcon.tsx +32 -0
  205. package/src/icons/NewChatIcon/NewChatIcon.tsx +39 -0
  206. package/src/index.ts +5 -1
  207. package/src/markdoc/components/Heading/Heading.tsx +2 -1
  208. package/src/markdoc/components/Mermaid/Mermaid.tsx +0 -2
  209. package/src/markdoc/components/Tabs/variables.ts +3 -3
  210. package/src/markdoc/components/default.ts +0 -1
  211. package/src/markdoc/tags/admonition.ts +1 -1
  212. package/lib/components/Catalog/CatalogTagsWithTooltip.d.ts +0 -10
  213. package/lib/components/Catalog/CatalogTagsWithTooltip.js +0 -57
  214. package/lib/markdoc/components/ExcalidrawDiagram/ExcalidrawDiagram.d.ts +0 -7
  215. package/lib/markdoc/components/ExcalidrawDiagram/ExcalidrawDiagram.js +0 -95
  216. package/lib/markdoc/components/ExcalidrawDiagram/variables.d.ts +0 -1
  217. package/lib/markdoc/components/ExcalidrawDiagram/variables.dark.d.ts +0 -1
  218. package/lib/markdoc/components/ExcalidrawDiagram/variables.dark.js +0 -8
  219. package/lib/markdoc/components/ExcalidrawDiagram/variables.js +0 -15
  220. package/src/components/Catalog/CatalogTagsWithTooltip.tsx +0 -101
  221. package/src/markdoc/components/ExcalidrawDiagram/ExcalidrawDiagram.tsx +0 -85
  222. package/src/markdoc/components/ExcalidrawDiagram/variables.dark.ts +0 -5
  223. package/src/markdoc/components/ExcalidrawDiagram/variables.ts +0 -12
@@ -2,7 +2,7 @@ import { css } from 'styled-components';
2
2
 
3
3
  export const switcher = css`
4
4
  --switch-bg-color: var(--color-warm-grey-4); // @presenter Color
5
- --switch-bg-color-selected: var(--color-warm-grey-9); // @presenter Color
5
+ --switch-bg-color-selected: var(--color-primary-base, var(--switch-bg-color-selected-legacy)); // @presenter Color
6
6
  --switch-bg-color-hover: var(--color-warm-grey-5); // @presenter Color
7
7
  --switch-bg-color-pressed: var(--color-warm-grey-6); // @presenter Color
8
8
  --switch-bg-color-disabled: var(--color-warm-grey-3); // @presenter Color
@@ -128,6 +128,7 @@ const TableOfContentMenuItem = styled.a<{ depth: number }>`
128
128
  &.active {
129
129
  color: var(--toc-item-text-color-active);
130
130
  border-left: solid 2px var(--toc-item-border-color-active);
131
+ font-weight: var(--toc-item-font-weight-active);
131
132
  }
132
133
 
133
134
  :empty {
@@ -24,12 +24,13 @@ export const toc = css`
24
24
 
25
25
  --toc-item-font-weight: var(--font-weight-regular); // @presenter FontWeight
26
26
  --toc-item-text-color: var(--text-color-description); // @presenter Color
27
- --toc-item-text-color-active: var(--text-color-primary); // @presenter Color
27
+ --toc-item-text-color-active: var(--color-primary-text, var(--toc-item-text-color-active-legacy)); // @presenter Color
28
28
  --toc-item-bg-color: transparent; // @presenter Color
29
29
  --toc-item-nested-offset: calc(var(--toc-spacing-unit) * 2); // @presenter Spacing
30
30
  --toc-item-padding-vertical: calc(var(--toc-spacing-unit) / 2); // @presenter Spacing
31
31
  --toc-item-padding-horizontal: calc(var(--toc-spacing-unit) * 2); // @presenter Spacing
32
- --toc-item-border-color-active: var(--border-color-invers);
32
+ --toc-item-border-color-active: var(--color-primary-base, var(--toc-item-border-color-active-legacy));
33
+ --toc-item-font-weight-active: var(--font-weight-medium); // @presenter FontWeight
33
34
 
34
35
  /**
35
36
  * @tokens TOC header
@@ -0,0 +1,289 @@
1
+ import React, { memo } from 'react';
2
+ import styled, { css, keyframes } from 'styled-components';
3
+
4
+ import type { ReactElement } from 'react';
5
+ import type { ToastItem, ToastType } from '@redocly/theme/core/types';
6
+
7
+ import { CheckmarkFilledIcon } from '@redocly/theme/icons/CheckmarkFilledIcon/CheckmarkFilledIcon';
8
+ import { CircleDashIcon } from '@redocly/theme/icons/CircleDashIcon/CircleDashIcon';
9
+ import { CloseIcon } from '@redocly/theme/icons/CloseIcon/CloseIcon';
10
+ import { ErrorFilledIcon } from '@redocly/theme/icons/ErrorFilledIcon/ErrorFilledIcon';
11
+ import { InformationFilledIcon } from '@redocly/theme/icons/InformationFilledIcon/InformationFilledIcon';
12
+ import { WarningFilledIcon } from '@redocly/theme/icons/WarningFilledIcon/WarningFilledIcon';
13
+ import { useToastLogic } from '@redocly/theme/core/hooks';
14
+ import { Button } from '@redocly/theme/components/Button/Button';
15
+ import { TOAST_SLIDE_DURATION_MS } from '@redocly/theme/core/constants/toast';
16
+
17
+ function renderToastIcon(type: ToastType): ReactElement {
18
+ switch (type) {
19
+ case 'success':
20
+ return <CheckmarkFilledIcon size="--toast-icon-size" color="--toast-icon-color-success" />;
21
+ case 'warning':
22
+ return <WarningFilledIcon size="--toast-icon-size" color="--toast-icon-color-warning" />;
23
+ case 'error':
24
+ return <ErrorFilledIcon size="--toast-icon-size" color="--toast-icon-color-error" />;
25
+ case 'loading':
26
+ return <CircleDashIcon size="--toast-icon-size" color="--toast-icon-color-loading" />;
27
+ case 'info':
28
+ default:
29
+ return <InformationFilledIcon size="--toast-icon-size" color="--toast-icon-color-info" />;
30
+ }
31
+ }
32
+
33
+ function renderDismissButton(onClick: () => void): ReactElement {
34
+ return (
35
+ <CloseButton
36
+ aria-label="Dismiss notification"
37
+ title="Dismiss notification"
38
+ icon={
39
+ <CloseIcon size="--toast-close-button-icon-size" color="--toast-close-button-icon-color" />
40
+ }
41
+ onClick={onClick}
42
+ />
43
+ );
44
+ }
45
+
46
+ export interface ToastComponentProps {
47
+ toast: ToastItem;
48
+ onDismiss: (id: string) => void;
49
+ stackIndex: number;
50
+ stackZIndex?: number;
51
+ className?: string;
52
+ }
53
+
54
+ function ToastComponent({
55
+ toast,
56
+ onDismiss,
57
+ stackIndex,
58
+ stackZIndex = 1,
59
+ className,
60
+ }: ToastComponentProps): ReactElement {
61
+ const {
62
+ wrapperRef,
63
+ hasDetails,
64
+ dismissToast,
65
+ handleMouseEnter,
66
+ handleMouseLeave,
67
+ ariaRole,
68
+ ariaLive,
69
+ } = useToastLogic({
70
+ toast,
71
+ onDismiss,
72
+ stackIndex,
73
+ });
74
+
75
+ const icon = renderToastIcon(toast.type);
76
+ const content = !hasDetails ? (
77
+ <SimpleToastSurface $isExiting={toast.isExiting} aria-live={ariaLive} role={ariaRole}>
78
+ <ContentWrapper>
79
+ <IconWrapper>{icon}</IconWrapper>
80
+ <SimpleContent>
81
+ <SimpleText>{toast.title}</SimpleText>
82
+ </SimpleContent>
83
+ </ContentWrapper>
84
+ {renderDismissButton(dismissToast)}
85
+ </SimpleToastSurface>
86
+ ) : (
87
+ <DetailedToastSurface $isExiting={toast.isExiting} aria-live={ariaLive} role={ariaRole}>
88
+ <ContentWrapper>
89
+ <IconWrapper>{icon}</IconWrapper>
90
+ <Body>
91
+ <TitleRow>
92
+ <TitleText>{toast.title}</TitleText>
93
+ {renderDismissButton(dismissToast)}
94
+ </TitleRow>
95
+ {toast.description ? (
96
+ <DescriptionRow>
97
+ <DescriptionText>{toast.description}</DescriptionText>
98
+ </DescriptionRow>
99
+ ) : null}
100
+ </Body>
101
+ </ContentWrapper>
102
+ </DetailedToastSurface>
103
+ );
104
+
105
+ return (
106
+ <ToastWrapper
107
+ ref={wrapperRef}
108
+ $stackZIndex={stackZIndex}
109
+ className={className}
110
+ data-component-name="Toast/Toast"
111
+ data-testid={`toast-${toast.type}`}
112
+ onMouseEnter={handleMouseEnter}
113
+ onMouseLeave={handleMouseLeave}
114
+ >
115
+ {content}
116
+ </ToastWrapper>
117
+ );
118
+ }
119
+
120
+ export const Toast = memo(ToastComponent);
121
+
122
+ const slideIn = keyframes`
123
+ from {
124
+ opacity: 0;
125
+ transform: translateX(100%);
126
+ }
127
+
128
+ to {
129
+ opacity: 1;
130
+ transform: translateX(0);
131
+ }
132
+ `;
133
+
134
+ const slideOut = keyframes`
135
+ from {
136
+ opacity: 1;
137
+ transform: translateX(0);
138
+ }
139
+
140
+ to {
141
+ opacity: 0;
142
+ transform: translateX(100%);
143
+ }
144
+ `;
145
+
146
+ export const spin = keyframes`
147
+ from {
148
+ transform: rotate(0deg);
149
+ }
150
+
151
+ to {
152
+ transform: rotate(360deg);
153
+ }
154
+ `;
155
+
156
+ const ToastWrapper = styled.div<{ $stackZIndex: number }>`
157
+ position: relative;
158
+ z-index: ${({ $stackZIndex }) => $stackZIndex};
159
+ width: 100%;
160
+ pointer-events: auto;
161
+ will-change: transform;
162
+ `;
163
+
164
+ const ToastSurface = styled.div<{ $isExiting: boolean }>`
165
+ display: flex;
166
+ align-items: flex-start;
167
+ width: 100%;
168
+ min-width: var(--toast-min-width);
169
+ max-width: var(--toast-max-width);
170
+ background-color: var(--toast-bg-color);
171
+ border: var(--toast-border);
172
+ border-radius: var(--toast-border-radius);
173
+ box-shadow: var(--toast-box-shadow);
174
+ color: var(--toast-text-color);
175
+ font-family: var(--toast-font-family);
176
+ animation: ${({ $isExiting }) =>
177
+ $isExiting
178
+ ? css`
179
+ ${slideOut} ${TOAST_SLIDE_DURATION_MS}ms ease-in forwards
180
+ `
181
+ : css`
182
+ ${slideIn} ${TOAST_SLIDE_DURATION_MS}ms ease-out
183
+ `};
184
+
185
+ @media (max-width: 480px) {
186
+ min-width: 0;
187
+ max-width: none;
188
+ }
189
+ `;
190
+
191
+ const SimpleToastSurface = styled(ToastSurface)`
192
+ gap: var(--toast-simple-gap);
193
+ padding: var(--toast-simple-padding);
194
+ `;
195
+
196
+ const DetailedToastSurface = styled(ToastSurface)`
197
+ padding: var(--toast-detailed-padding);
198
+ `;
199
+
200
+ const ContentWrapper = styled.div`
201
+ display: flex;
202
+ flex: 1 1 auto;
203
+ gap: var(--toast-content-gap);
204
+ min-width: 0;
205
+ `;
206
+
207
+ const IconWrapper = styled.div`
208
+ display: flex;
209
+ align-items: center;
210
+ justify-content: center;
211
+ width: var(--toast-icon-size);
212
+ min-width: var(--toast-icon-size);
213
+ height: var(--toast-icon-line-height);
214
+
215
+ ${CircleDashIcon} {
216
+ animation: ${spin} var(--toast-loading-animation-duration) linear infinite;
217
+ }
218
+ `;
219
+
220
+ const flexItemStyles = css`
221
+ flex: 1 1 auto;
222
+ min-width: 0;
223
+ `;
224
+
225
+ const SimpleContent = styled.div`
226
+ ${flexItemStyles}
227
+ `;
228
+
229
+ const Body = styled.div`
230
+ display: flex;
231
+ ${flexItemStyles}
232
+ flex-direction: column;
233
+ `;
234
+
235
+ const TitleRow = styled.div`
236
+ display: flex;
237
+ align-items: center;
238
+ gap: var(--toast-title-gap);
239
+ min-width: 0;
240
+ `;
241
+
242
+ const DescriptionRow = styled.div`
243
+ display: flex;
244
+ flex-wrap: wrap;
245
+ align-items: center;
246
+ gap: var(--toast-description-gap);
247
+ min-width: 0;
248
+ `;
249
+
250
+ const textStyles = css`
251
+ margin: 0;
252
+ font-size: var(--toast-text-font-size);
253
+ line-height: var(--toast-text-line-height);
254
+ color: var(--toast-text-color);
255
+ overflow-wrap: anywhere;
256
+ `;
257
+
258
+ const TitleText = styled.p`
259
+ ${textStyles}
260
+ ${flexItemStyles}
261
+ font-weight: var(--toast-title-font-weight);
262
+ `;
263
+
264
+ const SimpleText = styled.p`
265
+ ${textStyles}
266
+ font-weight: var(--toast-body-font-weight);
267
+ `;
268
+
269
+ const DescriptionText = styled.p`
270
+ ${textStyles}
271
+ ${flexItemStyles}
272
+ font-weight: var(--toast-body-font-weight);
273
+ `;
274
+
275
+ const CloseButton = styled(Button).attrs({
276
+ variant: 'ghost',
277
+ size: 'small',
278
+ })`
279
+ flex: 0 0 auto;
280
+ min-height: unset;
281
+ margin: 0;
282
+ padding: var(--toast-close-button-padding);
283
+ color: var(--toast-close-button-icon-color);
284
+
285
+ &:hover,
286
+ &:focus-visible {
287
+ border: none;
288
+ }
289
+ `;
@@ -0,0 +1,61 @@
1
+ import { css } from 'styled-components';
2
+
3
+ /* eslint-disable theme/no-raw-colors-in-styles */
4
+ export const toast = css`
5
+ /**
6
+ * @tokens Toast
7
+ * @presenter BoxShadow
8
+ */
9
+
10
+ --toast-box-shadow: 2px 2px 12px 0 rgba(0, 0, 0, 0.04), 2px 2px 24px 8px rgba(0, 0, 0, 0.04);
11
+
12
+ /**
13
+ * @tokens Toast surface
14
+ */
15
+ --toast-min-width: 240px;
16
+ --toast-max-width: 360px;
17
+ --toast-bg-color: var(--layer-color); // @presenter Color
18
+ --toast-border: var(--border-width) var(--border-style) var(--border-color-secondary); // @presenter Border
19
+ --toast-border-radius: var(--border-radius-md); // @presenter BorderRadius
20
+ --toast-font-family: var(--font-family-base); // @presenter FontFamily
21
+
22
+ /**
23
+ * @tokens Toast spacing
24
+ */
25
+ --toast-simple-gap: var(--spacing-unit);
26
+ --toast-simple-padding: var(--spacing-xs) var(--spacing-sm);
27
+ --toast-detailed-padding: var(--spacing-sm);
28
+ --toast-content-gap: var(--spacing-xs);
29
+ --toast-title-gap: var(--spacing-xs);
30
+ --toast-description-gap: var(--spacing-xs);
31
+
32
+ /**
33
+ * @tokens Toast icon
34
+ */
35
+ --toast-icon-size: 14px;
36
+ --toast-icon-line-height: var(--line-height-base); // @presenter LineHeight
37
+ --toast-icon-color-info: var(--color-info-base); // @presenter Color
38
+ --toast-icon-color-success: var(--color-success-base); // @presenter Color
39
+ --toast-icon-color-warning: var(--color-warning-base); // @presenter Color
40
+ --toast-icon-color-error: var(--color-error-base); // @presenter Color
41
+ --toast-icon-color-loading: var(--loading-spinner-color); // @presenter Color
42
+ --toast-loading-animation-duration: 3s;
43
+
44
+ /**
45
+ * @tokens Toast typography
46
+ */
47
+ --toast-text-font-size: var(--font-size-base); // @presenter FontSize
48
+ --toast-text-line-height: var(--line-height-base); // @presenter LineHeight
49
+ --toast-text-color: var(--text-color-primary); // @presenter Color
50
+ --toast-title-font-weight: var(--font-weight-semibold); // @presenter FontWeight
51
+ --toast-body-font-weight: var(--font-weight-regular); // @presenter FontWeight
52
+
53
+ /**
54
+ * @tokens Toast close button
55
+ */
56
+ --toast-close-button-padding: 3px;
57
+ --toast-close-button-icon-size: 14px;
58
+ --toast-close-button-icon-color: var(--icon-color-secondary); // @presenter Color
59
+
60
+ // @tokens End
61
+ `;
@@ -289,7 +289,7 @@ const TooltipBody = styled.span<
289
289
  var(--tooltip-border-color, transparent);
290
290
  box-shadow: var(--bg-raised-shadow);
291
291
 
292
- width: ${({ width }) => width || 'auto'};
292
+ width: ${({ width }) => width || 'max-content'};
293
293
  ${({ placement }) => css`
294
294
  ${PLACEMENTS[placement]};
295
295
  `}
@@ -1,6 +1,6 @@
1
1
  import type { EntityRelationType } from '../types/catalog';
2
2
 
3
- export const CATALOG_TAG_MAX_LENGTH = 15;
3
+ export const CATALOG_TAG_MAX_LENGTH = 12;
4
4
 
5
5
  export const PREDEFINED_ENTITY_TYPES = [
6
6
  'service',
@@ -0,0 +1 @@
1
+ export const TOAST_SLIDE_DURATION_MS = 300;
@@ -0,0 +1,5 @@
1
+ import { createContext } from 'react';
2
+
3
+ import type { ToastContextValue } from '@redocly/theme/core/types';
4
+
5
+ export const ToastContext = createContext<ToastContextValue | null>(null);
@@ -0,0 +1,206 @@
1
+ import styled from 'styled-components';
2
+ import React, { useCallback, useEffect, useMemo, useReducer, useRef } from 'react';
3
+
4
+ import type { ReactElement } from 'react';
5
+ import type {
6
+ ToastContextValue,
7
+ ToastItem,
8
+ ToastOptions,
9
+ ToastProviderProps,
10
+ ToastType,
11
+ } from '../../../core/types/toast';
12
+
13
+ import { Portal } from '@redocly/theme/components/Portal/Portal';
14
+ import { Toast } from '@redocly/theme/components/Toast/Toast';
15
+
16
+ import { ToastContext } from '../../../core/contexts/Toast/ToastContext';
17
+ import { TOAST_SLIDE_DURATION_MS } from '../../../core/constants/toast';
18
+
19
+ type ToastState = ToastItem[];
20
+
21
+ type ToastReducerAction =
22
+ | {
23
+ type: 'add';
24
+ payload: ToastItem;
25
+ }
26
+ | {
27
+ type: 'startExit';
28
+ payload: {
29
+ id: string;
30
+ };
31
+ }
32
+ | {
33
+ type: 'remove';
34
+ payload: {
35
+ id: string;
36
+ };
37
+ }
38
+ | {
39
+ type: 'update';
40
+ payload: {
41
+ id: string;
42
+ updates: Partial<ToastOptions>;
43
+ };
44
+ };
45
+
46
+ function toastReducer(state: ToastState, action: ToastReducerAction): ToastState {
47
+ switch (action.type) {
48
+ case 'add':
49
+ return [action.payload, ...state];
50
+ case 'startExit':
51
+ return state.map((toast) =>
52
+ toast.id === action.payload.id ? { ...toast, isExiting: true } : toast,
53
+ );
54
+ case 'remove':
55
+ return state.filter((toast) => toast.id !== action.payload.id);
56
+ case 'update':
57
+ return state.map((toast) =>
58
+ toast.id === action.payload.id
59
+ ? {
60
+ ...toast,
61
+ ...action.payload.updates,
62
+ type: action.payload.updates.type ?? toast.type,
63
+ }
64
+ : toast,
65
+ );
66
+ default:
67
+ return state;
68
+ }
69
+ }
70
+
71
+ function getToastType(type?: ToastType): ToastType {
72
+ return type ?? 'info';
73
+ }
74
+
75
+ function createToastId(): string {
76
+ if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
77
+ return crypto.randomUUID();
78
+ }
79
+
80
+ return `toast-${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;
81
+ }
82
+
83
+ export function ToastProvider({ children, mountId }: ToastProviderProps): ReactElement {
84
+ const [toasts, dispatch] = useReducer(toastReducer, []);
85
+ const toastsRef = useRef<ToastItem[]>([]);
86
+ const removeTimeoutsRef = useRef<Map<string, ReturnType<typeof setTimeout>>>(new Map());
87
+
88
+ useEffect(() => {
89
+ toastsRef.current = toasts;
90
+ }, [toasts]);
91
+
92
+ useEffect(() => {
93
+ const timeoutsMap = removeTimeoutsRef.current;
94
+
95
+ return () => {
96
+ timeoutsMap.forEach((timeoutId) => {
97
+ clearTimeout(timeoutId);
98
+ });
99
+
100
+ timeoutsMap.clear();
101
+ };
102
+ }, []);
103
+
104
+ const dismissToast = useCallback((id: string): void => {
105
+ const currentToast = toastsRef.current.find((toast) => toast.id === id);
106
+
107
+ if (!currentToast || currentToast.isExiting) {
108
+ return;
109
+ }
110
+
111
+ currentToast.onClose?.();
112
+ dispatch({ type: 'startExit', payload: { id } });
113
+
114
+ const existingTimeout = removeTimeoutsRef.current.get(id);
115
+
116
+ if (existingTimeout) {
117
+ clearTimeout(existingTimeout);
118
+ }
119
+
120
+ const timeoutId = setTimeout(() => {
121
+ dispatch({ type: 'remove', payload: { id } });
122
+ removeTimeoutsRef.current.delete(id);
123
+ }, TOAST_SLIDE_DURATION_MS);
124
+
125
+ removeTimeoutsRef.current.set(id, timeoutId);
126
+ }, []);
127
+
128
+ const showToast = useCallback((options: ToastOptions): string => {
129
+ const id = createToastId();
130
+
131
+ dispatch({
132
+ type: 'add',
133
+ payload: {
134
+ ...options,
135
+ id,
136
+ type: getToastType(options.type),
137
+ isExiting: false,
138
+ },
139
+ });
140
+
141
+ return id;
142
+ }, []);
143
+
144
+ const updateToast = useCallback((id: string, updates: Partial<ToastOptions>): void => {
145
+ dispatch({
146
+ type: 'update',
147
+ payload: {
148
+ id,
149
+ updates,
150
+ },
151
+ });
152
+ }, []);
153
+
154
+ const contextValue = useMemo<ToastContextValue>(
155
+ () => ({
156
+ showToast,
157
+ dismissToast,
158
+ updateToast,
159
+ }),
160
+ [dismissToast, showToast, updateToast],
161
+ );
162
+
163
+ return (
164
+ <ToastContext.Provider value={contextValue}>
165
+ {children}
166
+ {toasts.length > 0 ? (
167
+ <Portal mountId={mountId}>
168
+ <ToastViewport aria-label="Notifications">
169
+ {toasts.map((toast, index) => (
170
+ <Toast
171
+ key={toast.id}
172
+ stackIndex={index}
173
+ stackZIndex={toasts.length - index}
174
+ toast={toast}
175
+ onDismiss={dismissToast}
176
+ />
177
+ ))}
178
+ </ToastViewport>
179
+ </Portal>
180
+ ) : null}
181
+ </ToastContext.Provider>
182
+ );
183
+ }
184
+
185
+ const ToastViewport = styled.div`
186
+ position: fixed;
187
+ right: var(--spacing-md);
188
+ bottom: var(--spacing-md);
189
+ z-index: 1100;
190
+ display: flex;
191
+ flex-direction: column-reverse;
192
+ gap: var(--spacing-sm);
193
+ width: 320px;
194
+ min-width: 240px;
195
+ max-width: 360px;
196
+ pointer-events: none;
197
+
198
+ @media (max-width: 480px) {
199
+ left: 50%;
200
+ right: auto;
201
+ transform: translateX(-50%);
202
+ width: calc(100vw - var(--spacing-md) * 2);
203
+ min-width: 0;
204
+ max-width: none;
205
+ }
206
+ `;
@@ -3,3 +3,5 @@ export * from './CodeWalkthrough/CodeWalkthroughControlsContext';
3
3
  export * from './CodeWalkthrough/CodeWalkthroughStepsContext';
4
4
  export * from './CodeSnippetContext';
5
5
  export * from './SearchContext';
6
+ export * from './Toast/ToastContext';
7
+ export * from './Toast/ToastProvider';
@@ -0,0 +1,46 @@
1
+ import { useMemo } from 'react';
2
+
3
+ import type { EntitiesCatalogConfig } from '@redocly/config';
4
+
5
+ export type EntityWithTypeAndKey = { type?: string; key?: string };
6
+
7
+ function isEntityExcluded(
8
+ excludes: Array<{ key: string }> | undefined,
9
+ entityKey: string,
10
+ ): boolean {
11
+ return excludes?.some((ex) => ex.key === entityKey) ?? false;
12
+ }
13
+
14
+ function doesCatalogIncludeEntityType(
15
+ config: { includes?: Array<{ type: string }> },
16
+ entityType: string,
17
+ ): boolean {
18
+ const hasNoIncludes = !config.includes || config.includes.length === 0;
19
+ if (hasNoIncludes) return true;
20
+ return config.includes?.some((inc) => inc.type === entityType) ?? false;
21
+ }
22
+
23
+ export function useCatalogEntityLink(entitiesCatalogConfig: EntitiesCatalogConfig | undefined) {
24
+ const catalogEntries = useMemo(() => {
25
+ const catalogs = entitiesCatalogConfig?.catalogs;
26
+ if (!catalogs) return [];
27
+ return Object.entries(catalogs)
28
+ .filter((entry): entry is [string, NonNullable<(typeof entry)[1]>] => entry[1] != null)
29
+ .sort(([keyA], [keyB]) => (keyA === 'all' ? 1 : 0) - (keyB === 'all' ? 1 : 0));
30
+ }, [entitiesCatalogConfig]);
31
+
32
+ const getEntityLink = (entity: EntityWithTypeAndKey): string | undefined => {
33
+ if (!entity?.key) return undefined;
34
+ const entityType = entity.type ?? '';
35
+
36
+ for (const [catalogKey, config] of catalogEntries) {
37
+ if (isEntityExcluded(config.excludes, entity.key)) continue;
38
+ if (!doesCatalogIncludeEntityType(config, entityType)) continue;
39
+ const slug = config.slug ?? catalogKey;
40
+ return `catalogs/${slug}/entities/${entity.key}`;
41
+ }
42
+ return undefined;
43
+ };
44
+
45
+ return { getEntityLink };
46
+ }