@redocly/theme 0.69.0-next.4 → 0.69.0-next.6

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 (177) hide show
  1. package/lib/components/Accordion/variables.js +1 -1
  2. package/lib/components/Admonition/variables.js +1 -1
  3. package/lib/components/Banner/variables.dark.js +2 -0
  4. package/lib/components/Banner/variables.js +3 -1
  5. package/lib/components/Breadcrumbs/Breadcrumb.js +1 -1
  6. package/lib/components/Breadcrumbs/variables.js +1 -1
  7. package/lib/components/Button/ButtonGroup.d.ts +3 -5
  8. package/lib/components/Button/ButtonGroup.js +25 -5
  9. package/lib/components/Button/variables.js +27 -4
  10. package/lib/components/Buttons/ConnectMCPButton.js +15 -128
  11. package/lib/components/Buttons/CopyButton.js +12 -1
  12. package/lib/components/Buttons/variables.d.ts +0 -1
  13. package/lib/components/Buttons/variables.js +3 -44
  14. package/lib/components/Catalog/CatalogEntity/CatalogEntityLinks.js +1 -1
  15. package/lib/components/Catalog/CatalogEntity/CatalogEntityMetadata.js +1 -1
  16. package/lib/components/Catalog/CatalogEntity/CatalogEntityMethodAndPath.js +1 -1
  17. package/lib/components/Catalog/CatalogEntity/CatalogEntitySchema.js +1 -1
  18. package/lib/components/Catalog/CatalogFilter/CatalogFilterSelect.js +1 -0
  19. package/lib/components/Catalog/variables.js +5 -5
  20. package/lib/components/CatalogClassic/variables.js +2 -2
  21. package/lib/components/CodeBlock/CodeBlock.js +2 -1
  22. package/lib/components/CodeBlock/CodeBlockContainer.js +1 -0
  23. package/lib/components/Dropdown/Dropdown.d.ts +10 -20
  24. package/lib/components/Dropdown/Dropdown.js +13 -2
  25. package/lib/components/Dropdown/DropdownMenuItemContent.d.ts +9 -0
  26. package/lib/components/Dropdown/DropdownMenuItemContent.js +56 -0
  27. package/lib/components/Dropdown/variables.js +19 -2
  28. package/lib/components/Feedback/Mood.js +18 -14
  29. package/lib/components/Feedback/Rating.js +18 -13
  30. package/lib/components/Feedback/Scale.js +27 -22
  31. package/lib/components/Feedback/Sentiment.js +17 -13
  32. package/lib/components/Filter/FilterSelect.js +1 -0
  33. package/lib/components/Filter/variables.js +2 -2
  34. package/lib/components/Image/variables.js +5 -3
  35. package/lib/components/LanguagePicker/variables.js +1 -1
  36. package/lib/components/Markdown/variables.js +1 -1
  37. package/lib/components/Menu/MenuItem.js +1 -1
  38. package/lib/components/Menu/variables.js +1 -1
  39. package/lib/components/Navbar/variables.js +1 -1
  40. package/lib/components/PageActions/PageActions.js +4 -6
  41. package/lib/components/PageActions/PageActionsMenuItem.d.ts +4 -4
  42. package/lib/components/PageActions/PageActionsMenuItem.js +27 -43
  43. package/lib/components/Panel/variables.js +1 -1
  44. package/lib/components/Product/variables.js +2 -1
  45. package/lib/components/ReplayGate/ReplayGate.d.ts +1 -0
  46. package/lib/components/Search/SearchAiMessage.js +1 -1
  47. package/lib/components/Search/SearchAiNegativeFeedbackForm.js +2 -2
  48. package/lib/components/Search/SearchDialog.js +1 -1
  49. package/lib/components/Search/SearchItem.js +1 -0
  50. package/lib/components/Search/SearchRecent.js +1 -0
  51. package/lib/components/Search/SearchSuggestedPages.js +1 -0
  52. package/lib/components/Search/variables.js +8 -5
  53. package/lib/components/Segmented/Segmented.js +3 -3
  54. package/lib/components/Select/Select.js +20 -18
  55. package/lib/components/Select/variables.js +3 -3
  56. package/lib/components/SplitButton/SplitButton.d.ts +21 -0
  57. package/lib/components/SplitButton/SplitButton.js +37 -0
  58. package/lib/components/Switch/variables.dark.js +2 -2
  59. package/lib/components/Switch/variables.js +2 -2
  60. package/lib/components/Tag/variables.js +2 -2
  61. package/lib/components/Tags/variables.js +1 -1
  62. package/lib/components/Toast/variables.js +1 -1
  63. package/lib/components/Tooltip/AnchorTooltip.js +2 -2
  64. package/lib/components/Tooltip/JsTooltip.js +2 -2
  65. package/lib/components/UserMenu/variables.js +1 -1
  66. package/lib/core/constants/mcp.d.ts +2 -0
  67. package/lib/core/constants/mcp.js +3 -1
  68. package/lib/core/hooks/use-control.js +3 -0
  69. package/lib/core/hooks/use-mcp-config.d.ts +2 -0
  70. package/lib/core/hooks/use-mcp-config.js +14 -4
  71. package/lib/core/styles/global.js +11 -11
  72. package/lib/core/styles/palette.js +2 -0
  73. package/lib/core/types/button-group.d.ts +2 -0
  74. package/lib/core/types/button-group.js +3 -0
  75. package/lib/core/types/catalog.d.ts +2 -6
  76. package/lib/core/types/common.d.ts +2 -0
  77. package/lib/core/types/hooks.d.ts +1 -0
  78. package/lib/core/types/index.d.ts +1 -0
  79. package/lib/core/types/l10n.d.ts +1 -1
  80. package/lib/core/utils/RenderWithLink.d.ts +2 -0
  81. package/lib/core/utils/RenderWithLink.js +20 -0
  82. package/lib/core/utils/index.d.ts +1 -0
  83. package/lib/core/utils/index.js +1 -0
  84. package/lib/icons/LinkIcon/LinkIcon.js +1 -1
  85. package/lib/index.d.ts +2 -0
  86. package/lib/index.js +2 -0
  87. package/lib/layouts/McpNotAllowed.js +5 -7
  88. package/lib/markdoc/components/Cards/variables.js +6 -4
  89. package/lib/markdoc/components/CodeWalkthrough/CodePanel.js +1 -0
  90. package/lib/markdoc/components/CodeWalkthrough/CodeStep.js +1 -1
  91. package/lib/markdoc/components/CodeWalkthrough/variables.js +2 -1
  92. package/lib/markdoc/components/Tabs/TabList.js +6 -2
  93. package/lib/markdoc/components/Tabs/Tabs.js +4 -2
  94. package/lib/markdoc/components/Tabs/variables.js +4 -4
  95. package/package.json +12 -3
  96. package/src/components/Accordion/variables.ts +1 -1
  97. package/src/components/Admonition/variables.ts +1 -1
  98. package/src/components/Banner/variables.dark.ts +2 -0
  99. package/src/components/Banner/variables.ts +3 -1
  100. package/src/components/Breadcrumbs/Breadcrumb.tsx +1 -1
  101. package/src/components/Breadcrumbs/variables.ts +1 -1
  102. package/src/components/Button/ButtonGroup.tsx +28 -10
  103. package/src/components/Button/variables.ts +27 -4
  104. package/src/components/Buttons/ConnectMCPButton.tsx +63 -150
  105. package/src/components/Buttons/CopyButton.tsx +14 -2
  106. package/src/components/Buttons/variables.ts +2 -44
  107. package/src/components/Catalog/CatalogEntity/CatalogEntityLinks.tsx +1 -1
  108. package/src/components/Catalog/CatalogEntity/CatalogEntityMetadata.tsx +1 -1
  109. package/src/components/Catalog/CatalogEntity/CatalogEntityMethodAndPath.tsx +1 -1
  110. package/src/components/Catalog/CatalogEntity/CatalogEntitySchema.tsx +1 -1
  111. package/src/components/Catalog/CatalogFilter/CatalogFilterSelect.tsx +1 -0
  112. package/src/components/Catalog/variables.ts +5 -5
  113. package/src/components/CatalogClassic/variables.ts +2 -2
  114. package/src/components/CodeBlock/CodeBlock.tsx +2 -1
  115. package/src/components/CodeBlock/CodeBlockContainer.tsx +1 -0
  116. package/src/components/Dropdown/Dropdown.tsx +25 -4
  117. package/src/components/Dropdown/DropdownMenuItemContent.tsx +72 -0
  118. package/src/components/Dropdown/variables.ts +19 -2
  119. package/src/components/Feedback/Mood.tsx +22 -15
  120. package/src/components/Feedback/Rating.tsx +22 -14
  121. package/src/components/Feedback/Scale.tsx +40 -32
  122. package/src/components/Feedback/Sentiment.tsx +21 -14
  123. package/src/components/Filter/FilterSelect.tsx +1 -0
  124. package/src/components/Filter/variables.ts +2 -2
  125. package/src/components/Image/variables.ts +5 -3
  126. package/src/components/LanguagePicker/variables.ts +1 -1
  127. package/src/components/Markdown/variables.ts +1 -1
  128. package/src/components/Menu/MenuItem.tsx +2 -2
  129. package/src/components/Menu/variables.ts +1 -1
  130. package/src/components/Navbar/variables.ts +1 -1
  131. package/src/components/PageActions/PageActions.tsx +22 -23
  132. package/src/components/PageActions/PageActionsMenuItem.tsx +41 -55
  133. package/src/components/Panel/variables.ts +1 -1
  134. package/src/components/Product/variables.ts +2 -1
  135. package/src/components/ReplayGate/ReplayGate.tsx +3 -0
  136. package/src/components/Search/SearchAiMessage.tsx +1 -1
  137. package/src/components/Search/SearchAiNegativeFeedbackForm.tsx +2 -2
  138. package/src/components/Search/SearchDialog.tsx +1 -1
  139. package/src/components/Search/SearchItem.tsx +1 -0
  140. package/src/components/Search/SearchRecent.tsx +1 -0
  141. package/src/components/Search/SearchSuggestedPages.tsx +1 -0
  142. package/src/components/Search/variables.ts +8 -5
  143. package/src/components/Segmented/Segmented.tsx +6 -3
  144. package/src/components/Select/Select.tsx +24 -16
  145. package/src/components/Select/variables.ts +3 -3
  146. package/src/components/SplitButton/SplitButton.tsx +95 -0
  147. package/src/components/Switch/variables.dark.ts +2 -2
  148. package/src/components/Switch/variables.ts +2 -2
  149. package/src/components/Tag/variables.ts +2 -2
  150. package/src/components/Tags/variables.ts +1 -1
  151. package/src/components/Toast/variables.ts +1 -1
  152. package/src/components/Tooltip/AnchorTooltip.tsx +2 -2
  153. package/src/components/Tooltip/JsTooltip.tsx +2 -2
  154. package/src/components/UserMenu/variables.ts +1 -1
  155. package/src/core/constants/mcp.ts +4 -0
  156. package/src/core/hooks/use-control.ts +5 -1
  157. package/src/core/hooks/use-mcp-config.ts +15 -4
  158. package/src/core/styles/global.ts +12 -12
  159. package/src/core/styles/palette.ts +2 -0
  160. package/src/core/types/button-group.ts +2 -0
  161. package/src/core/types/catalog.ts +2 -7
  162. package/src/core/types/common.ts +3 -0
  163. package/src/core/types/hooks.ts +1 -0
  164. package/src/core/types/index.ts +1 -0
  165. package/src/core/types/l10n.ts +5 -0
  166. package/src/core/utils/RenderWithLink.tsx +19 -0
  167. package/src/core/utils/index.ts +1 -0
  168. package/src/icons/LinkIcon/LinkIcon.tsx +1 -1
  169. package/src/index.ts +2 -0
  170. package/src/layouts/McpNotAllowed.tsx +33 -9
  171. package/src/markdoc/components/Cards/variables.ts +6 -4
  172. package/src/markdoc/components/CodeWalkthrough/CodePanel.tsx +1 -0
  173. package/src/markdoc/components/CodeWalkthrough/CodeStep.tsx +1 -1
  174. package/src/markdoc/components/CodeWalkthrough/variables.ts +2 -1
  175. package/src/markdoc/components/Tabs/TabList.tsx +6 -2
  176. package/src/markdoc/components/Tabs/Tabs.tsx +4 -2
  177. package/src/markdoc/components/Tabs/variables.ts +4 -4
@@ -10,7 +10,8 @@ import React, {
10
10
  import { createPortal } from 'react-dom';
11
11
  import styled, { css } from 'styled-components';
12
12
 
13
- import type { CSSProperties, PropsWithChildren, ReactElement } from 'react';
13
+ import type { CSSProperties, ReactElement } from 'react';
14
+ import type { RenderableChildren } from '@redocly/theme/core/types';
14
15
 
15
16
  import { useOutsideClick, useControlledState } from '@redocly/theme/core/hooks';
16
17
  import { ChevronDownIcon } from '@redocly/theme/icons/ChevronDownIcon/ChevronDownIcon';
@@ -26,8 +27,14 @@ interface TriggerProps {
26
27
  [key: string]: unknown;
27
28
  }
28
29
 
29
- export type DropdownProps = PropsWithChildren<{
30
+ type DropdownMenuContext = {
31
+ close: () => void;
32
+ isOpen: boolean;
33
+ };
34
+
35
+ export type DropdownProps = {
30
36
  trigger: React.ReactNode;
37
+ children: RenderableChildren<DropdownMenuContext>;
31
38
  triggerEvent?: 'click' | 'hover';
32
39
  placement?: 'top' | 'bottom';
33
40
  alignment?: 'start' | 'end';
@@ -43,7 +50,7 @@ export type DropdownProps = PropsWithChildren<{
43
50
  onClick?: (event: React.UIEvent) => void;
44
51
  onClose?: () => void;
45
52
  onOpen?: () => void;
46
- }>;
53
+ };
47
54
 
48
55
  export const Dropdown = forwardRef<HTMLDivElement, DropdownProps>(
49
56
  (
@@ -78,6 +85,9 @@ export const Dropdown = forwardRef<HTMLDivElement, DropdownProps>(
78
85
  };
79
86
 
80
87
  const handleClose = () => {
88
+ if (!isOpen) {
89
+ return;
90
+ }
81
91
  setIsOpen(false);
82
92
  onClose?.();
83
93
  };
@@ -137,10 +147,14 @@ export const Dropdown = forwardRef<HTMLDivElement, DropdownProps>(
137
147
 
138
148
  useOutsideClick(portalled ? [wrapperRef, menuRef] : wrapperRef, handleClose);
139
149
 
150
+ const menuContent =
151
+ typeof children === 'function' ? children({ close: handleClose, isOpen }) : children;
152
+
140
153
  const triggerChild = React.Children.only(trigger) as ReactElement<TriggerProps>;
141
154
 
142
155
  const dropdownTrigger = cloneElement(triggerChild, {
143
156
  onClick: triggerEvent === 'click' ? handleToggle : undefined,
157
+ 'aria-expanded': isOpen,
144
158
  icon: withArrow ? isOpen ? <ChevronUpIcon /> : <ChevronDownIcon /> : undefined,
145
159
  ...(withArrow ? { iconPosition: 'right' } : {}),
146
160
  ...triggerChild.props,
@@ -157,7 +171,7 @@ export const Dropdown = forwardRef<HTMLDivElement, DropdownProps>(
157
171
  style={portalled ? menuStyle : undefined}
158
172
  onClick={closeOnClick ? handleChildClick : undefined}
159
173
  >
160
- {children}
174
+ {menuContent}
161
175
  </ChildrenWrapper>
162
176
  );
163
177
 
@@ -198,6 +212,13 @@ const DropdownWrapper = styled.div`
198
212
  position: relative;
199
213
 
200
214
  text-decoration: none;
215
+
216
+ /* The trigger keeps its hovered appearance while the menu is open. */
217
+ > .button[aria-expanded='true'] {
218
+ background-color: var(--button-bg-color-hover);
219
+ color: var(--button-color-hover);
220
+ border-color: var(--button-border-color-hover);
221
+ }
201
222
  `;
202
223
 
203
224
  const ChildrenWrapper = styled.div<{
@@ -0,0 +1,72 @@
1
+ import React from 'react';
2
+ import styled from 'styled-components';
3
+
4
+ import type { JSX } from 'react';
5
+
6
+ export type DropdownMenuItemContentProps = {
7
+ title: React.ReactNode;
8
+ icon?: React.ReactNode;
9
+ description?: React.ReactNode;
10
+ className?: string;
11
+ };
12
+
13
+ export function DropdownMenuItemContent(props: DropdownMenuItemContentProps): JSX.Element {
14
+ const { title, icon, description, className } = props;
15
+
16
+ return (
17
+ <MenuItemContentWrapper
18
+ data-component-name="Dropdown/DropdownMenuItemContent"
19
+ className={className}
20
+ >
21
+ {icon ? <IconWrapper>{icon}</IconWrapper> : null}
22
+ <TextWrapper>
23
+ <TitleWrapper>{title}</TitleWrapper>
24
+ {description ? <DescriptionWrapper>{description}</DescriptionWrapper> : null}
25
+ </TextWrapper>
26
+ </MenuItemContentWrapper>
27
+ );
28
+ }
29
+
30
+ const MenuItemContentWrapper = styled.div`
31
+ display: flex;
32
+ flex-direction: row;
33
+ align-items: center;
34
+ gap: var(--dropdown-menu-item-content-gap);
35
+ padding: var(--dropdown-menu-item-content-padding);
36
+ `;
37
+
38
+ const IconWrapper = styled.div`
39
+ display: flex;
40
+ align-items: center;
41
+ justify-content: center;
42
+ flex-shrink: 0;
43
+ width: var(--dropdown-menu-item-content-icon-size);
44
+ height: var(--dropdown-menu-item-content-icon-size);
45
+ color: var(--dropdown-menu-item-content-icon-color);
46
+ border: var(--dropdown-menu-item-content-icon-border);
47
+ border-radius: var(--dropdown-menu-item-content-icon-border-radius);
48
+ `;
49
+
50
+ const TextWrapper = styled.div`
51
+ display: flex;
52
+ flex-direction: column;
53
+ flex: 1;
54
+ gap: var(--dropdown-menu-item-content-text-gap);
55
+ `;
56
+
57
+ const TitleWrapper = styled.div`
58
+ display: flex;
59
+ align-items: center;
60
+ gap: var(--dropdown-menu-item-content-title-icon-gap);
61
+ font-weight: var(--dropdown-menu-item-content-title-font-weight);
62
+ font-size: var(--dropdown-menu-item-content-title-font-size);
63
+ line-height: var(--dropdown-menu-item-content-title-line-height);
64
+ color: var(--dropdown-menu-item-content-title-color);
65
+ `;
66
+
67
+ const DescriptionWrapper = styled.div`
68
+ font-weight: var(--dropdown-menu-item-content-description-font-weight);
69
+ font-size: var(--dropdown-menu-item-content-description-font-size);
70
+ line-height: var(--dropdown-menu-item-content-description-line-height);
71
+ color: var(--dropdown-menu-item-content-description-color);
72
+ `;
@@ -17,7 +17,7 @@ export const dropdown = css`
17
17
  --dropdown-menu-max-width: 424px;
18
18
  --dropdown-menu-max-height: 300px;
19
19
  --dropdown-menu-padding: var(--spacing-xxs); // @presenter Spacing
20
- --dropdown-menu-border-radius: var(--border-radius-lg); // @presenter BorderRadius
20
+ --dropdown-menu-border-radius: var(--border-radius-xl); // @presenter BorderRadius
21
21
  --dropdown-menu-box-shadow: var(--bg-raised-shadow); // @presenter Shadow
22
22
  --dropdown-menu-border-color: var(--border-color-secondary); // @presenter Color
23
23
  --dropdown-menu-bg-color: var(--bg-color-raised); // @presenter Color
@@ -27,7 +27,7 @@ export const dropdown = css`
27
27
  --dropdown-menu-item-padding-vertical: 5px; // @presenter Spacing
28
28
  --dropdown-menu-item-separator-padding-top: var(--spacing-xs); // @presenter Spacing
29
29
  --dropdown-menu-item-separator-padding-bottom: var(--spacing-xxs); // @presenter Spacing
30
- --dropdown-menu-item-border-radius: var(--border-radius); // @presenter BorderRadius
30
+ --dropdown-menu-item-border-radius: var(--border-radius-lg); // @presenter BorderRadius
31
31
  --dropdown-menu-item-bg-color: transparent;
32
32
  --dropdown-menu-item-bg-color-active: var(--bg-color-hover); // @presenter Color
33
33
  --dropdown-menu-item-bg-color-hover: var(--bg-color-hover); // @presenter Color
@@ -45,5 +45,22 @@ export const dropdown = css`
45
45
  --dropdown-menu-item-color-dangerous: var(--color-error-base);
46
46
 
47
47
  --dropdown-menu-item-border-color-focused: var(--button-border-color-focused);
48
+
49
+ --dropdown-menu-item-content-gap: var(--spacing-sm); // @presenter Spacing
50
+ --dropdown-menu-item-content-padding: var(--spacing-xxs) 0; // @presenter Spacing
51
+ --dropdown-menu-item-content-icon-size: 32px;
52
+ --dropdown-menu-item-content-icon-color: var(--icon-color-secondary); // @presenter Color
53
+ --dropdown-menu-item-content-icon-border: 1px solid var(--border-color-secondary); // @presenter Border
54
+ --dropdown-menu-item-content-icon-border-radius: var(--border-radius); // @presenter BorderRadius
55
+ --dropdown-menu-item-content-text-gap: var(--spacing-xxs); // @presenter Spacing
56
+ --dropdown-menu-item-content-title-icon-gap: var(--spacing-xxs); // @presenter Spacing
57
+ --dropdown-menu-item-content-title-font-weight: var(--font-weight-regular); // @presenter FontWeight
58
+ --dropdown-menu-item-content-title-font-size: var(--font-size-base); // @presenter FontSize
59
+ --dropdown-menu-item-content-title-line-height: var(--line-height-base); // @presenter LineHeight
60
+ --dropdown-menu-item-content-title-color: var(--text-color-secondary); // @presenter Color
61
+ --dropdown-menu-item-content-description-font-weight: var(--font-weight-regular); // @presenter FontWeight
62
+ --dropdown-menu-item-content-description-font-size: var(--font-size-sm); // @presenter FontSize
63
+ --dropdown-menu-item-content-description-line-height: var(--line-height-sm); // @presenter LineHeight
64
+ --dropdown-menu-item-content-description-color: var(--text-color-description); // @presenter Color
48
65
  // @tokens End
49
66
  `;
@@ -1,5 +1,4 @@
1
1
  import * as React from 'react';
2
- import { useEffect } from 'react';
3
2
  import styled, { css } from 'styled-components';
4
3
 
5
4
  import type { JSX } from 'react';
@@ -130,16 +129,19 @@ export function Mood({ settings, onSubmit, className }: MoodProps): JSX.Element
130
129
  return reasonsSettings[score as MOOD_STATES]?.component;
131
130
  };
132
131
 
132
+ const hasComment = !commentSettings?.hide;
133
+ const hasOptionalEmail = !optionalEmailSettings?.hide && !userData?.isAuthenticated;
134
+
133
135
  const displayReasons = checkIfShouldDisplayReasons(score);
134
- const displayComment = !!(score && !commentSettings?.hide);
136
+ const displayComment = !!score && hasComment;
135
137
  const displaySubmitBnt = !!(score && (displayReasons || displayComment));
136
- const displayFeedbackEmail = !!score && !optionalEmailSettings?.hide && !userData.isAuthenticated;
138
+ const displayFeedbackEmail = !!score && hasOptionalEmail;
137
139
 
138
- const onSubmitMoodForm = () => {
140
+ const submitMood = (moodScore: string) => {
139
141
  const trimmedComment = comment?.trim() || undefined;
140
142
  const trimmedEmail = email?.trim() || undefined;
141
143
  onSubmit({
142
- score: remapScore(score),
144
+ score: remapScore(moodScore),
143
145
  comment: trimmedComment,
144
146
  reasons,
145
147
  email: trimmedEmail,
@@ -147,6 +149,18 @@ export function Mood({ settings, onSubmit, className }: MoodProps): JSX.Element
147
149
  setIsSubmitted(true);
148
150
  };
149
151
 
152
+ const onSubmitMoodForm = () => {
153
+ submitMood(score);
154
+ };
155
+
156
+ const onScoreChange = (newScore: string) => {
157
+ setScore(newScore);
158
+
159
+ if (newScore && !checkIfShouldDisplayReasons(newScore) && !hasComment && !hasOptionalEmail) {
160
+ submitMood(newScore);
161
+ }
162
+ };
163
+
150
164
  const onCancelMoodForm = () => {
151
165
  setScore('');
152
166
  setComment('');
@@ -154,13 +168,6 @@ export function Mood({ settings, onSubmit, className }: MoodProps): JSX.Element
154
168
  setEmail(undefined);
155
169
  };
156
170
 
157
- useEffect(() => {
158
- if (score && !displayComment && !displayReasons && !displayFeedbackEmail) {
159
- onSubmitMoodForm();
160
- }
161
- // eslint-disable-next-line react-hooks/exhaustive-deps
162
- }, [score, displayComment, displayReasons, displayFeedbackEmail]);
163
-
164
171
  if (isSubmitted) {
165
172
  return (
166
173
  <MoodWrapper data-component-name="Feedback/Mood">
@@ -193,7 +200,7 @@ export function Mood({ settings, onSubmit, className }: MoodProps): JSX.Element
193
200
  variant={score === MOOD_STATES.DISSATISFIED ? 'primary' : 'secondary'}
194
201
  tone={score === MOOD_STATES.DISSATISFIED ? 'danger' : 'default'}
195
202
  onClick={() => {
196
- setScore(MOOD_STATES.DISSATISFIED);
203
+ onScoreChange(MOOD_STATES.DISSATISFIED);
197
204
  }}
198
205
  icon={<FaceDissatisfiedIcon />}
199
206
  />
@@ -203,7 +210,7 @@ export function Mood({ settings, onSubmit, className }: MoodProps): JSX.Element
203
210
  variant={score === MOOD_STATES.NEUTRAL ? 'primary' : 'secondary'}
204
211
  size="medium"
205
212
  onClick={() => {
206
- setScore(MOOD_STATES.NEUTRAL);
213
+ onScoreChange(MOOD_STATES.NEUTRAL);
207
214
  }}
208
215
  icon={<FaceNeutralIcon />}
209
216
  />
@@ -213,7 +220,7 @@ export function Mood({ settings, onSubmit, className }: MoodProps): JSX.Element
213
220
  variant={score === MOOD_STATES.SATISFIED ? 'primary' : 'secondary'}
214
221
  size="medium"
215
222
  onClick={() => {
216
- setScore(MOOD_STATES.SATISFIED);
223
+ onScoreChange(MOOD_STATES.SATISFIED);
217
224
  }}
218
225
  icon={<FaceSatisfiedIcon />}
219
226
  />
@@ -1,5 +1,4 @@
1
1
  import * as React from 'react';
2
- import { useEffect } from 'react';
3
2
  import styled from 'styled-components';
4
3
 
5
4
  import type { JSX } from 'react';
@@ -59,16 +58,20 @@ export function Rating({ settings, onSubmit, className }: RatingProps): JSX.Elem
59
58
  const { userData } = useUserMenu();
60
59
  const { translate } = useTranslate();
61
60
 
61
+ const hasReasons = !!(reasonsSettings && !reasonsSettings.hide);
62
+ const hasComment = !commentSettings?.hide;
63
+ const hasOptionalEmail = !optionalEmailSettings?.hide && !userData?.isAuthenticated;
64
+
62
65
  const onEmailChange = (e: React.ChangeEvent<HTMLInputElement>) => {
63
66
  const value = e.target.value;
64
67
  setEmail(value || undefined);
65
68
  };
66
69
 
67
- const onSubmitRatingForm = () => {
70
+ const submitRating = (ratingScore: number) => {
68
71
  const trimmedComment = comment?.trim() || undefined;
69
72
  const trimmedEmail = email?.trim() || undefined;
70
73
  onSubmit({
71
- score,
74
+ score: ratingScore,
72
75
  comment: trimmedComment,
73
76
  reasons,
74
77
  max: FEEDBACK_MAX_RATING,
@@ -77,6 +80,18 @@ export function Rating({ settings, onSubmit, className }: RatingProps): JSX.Elem
77
80
  setIsSubmitted(true);
78
81
  };
79
82
 
83
+ const onSubmitRatingForm = () => {
84
+ submitRating(score);
85
+ };
86
+
87
+ const onScoreChange = (newScore: number) => {
88
+ setScore(newScore);
89
+
90
+ if (newScore && !hasReasons && !hasComment && !hasOptionalEmail) {
91
+ submitRating(newScore);
92
+ }
93
+ };
94
+
80
95
  const onCancelRatingForm = () => {
81
96
  setScore(0);
82
97
  setComment('');
@@ -84,17 +99,10 @@ export function Rating({ settings, onSubmit, className }: RatingProps): JSX.Elem
84
99
  setEmail(undefined);
85
100
  };
86
101
 
87
- const displayReasons = !!(score && reasonsSettings && !reasonsSettings.hide);
88
- const displayComment = !!(score && !commentSettings?.hide);
102
+ const displayReasons = !!score && hasReasons;
103
+ const displayComment = !!score && hasComment;
89
104
  const displaySubmitBnt = !!(score && (displayReasons || displayComment));
90
- const displayFeedbackEmail = !!score && !optionalEmailSettings?.hide && !userData.isAuthenticated;
91
-
92
- useEffect(() => {
93
- if (score && !displayComment && !displayReasons && !displayFeedbackEmail) {
94
- onSubmitRatingForm();
95
- }
96
- // eslint-disable-next-line react-hooks/exhaustive-deps
97
- }, [score, displayComment, displayReasons, displayFeedbackEmail]);
105
+ const displayFeedbackEmail = !!score && hasOptionalEmail;
98
106
 
99
107
  if (isSubmitted) {
100
108
  return (
@@ -122,7 +130,7 @@ export function Rating({ settings, onSubmit, className }: RatingProps): JSX.Elem
122
130
  </Label>
123
131
 
124
132
  <StyledMandatoryFieldContainer>
125
- <Stars max={FEEDBACK_MAX_RATING} onChange={setScore} value={score} />
133
+ <Stars max={FEEDBACK_MAX_RATING} onChange={onScoreChange} value={score} />
126
134
  </StyledMandatoryFieldContainer>
127
135
  </StyledFormMandatoryFields>
128
136
  {(displayReasons || displayComment) && (
@@ -1,5 +1,4 @@
1
1
  import * as React from 'react';
2
- import { useEffect } from 'react';
3
2
  import styled from 'styled-components';
4
3
 
5
4
  import type { JSX } from 'react';
@@ -68,6 +67,42 @@ export function Scale({ settings, onSubmit, className }: ScaleProps): JSX.Elemen
68
67
  setEmail(value || undefined);
69
68
  };
70
69
 
70
+ const hasReasons = !!(reasonsSettings && !reasonsSettings.hide);
71
+ const hasComment = !commentSettings?.hide;
72
+ const hasOptionalEmail = !optionalEmailSettings?.hide && !userData?.isAuthenticated;
73
+
74
+ const submitScale = (scaleScore: number) => {
75
+ const trimmedComment = comment?.trim() || undefined;
76
+ const trimmedEmail = email?.trim() || undefined;
77
+ onSubmit({
78
+ score: scaleScore,
79
+ comment: trimmedComment,
80
+ reasons,
81
+ max: MAX_SCALE,
82
+ email: trimmedEmail,
83
+ });
84
+ setIsSubmitted(true);
85
+ };
86
+
87
+ const onSubmitScaleForm = () => {
88
+ submitScale(score);
89
+ };
90
+
91
+ const onScoreChange = (newScore: number) => {
92
+ setScore(newScore);
93
+
94
+ if (newScore && !hasReasons && !hasComment && !hasOptionalEmail) {
95
+ submitScale(newScore);
96
+ }
97
+ };
98
+
99
+ const handleCancel = () => {
100
+ setScore(0);
101
+ setComment('');
102
+ setReasons([]);
103
+ setEmail(undefined);
104
+ };
105
+
71
106
  const scaleOptions = [];
72
107
 
73
108
  for (let i = 1; i <= MAX_SCALE; i++) {
@@ -76,7 +111,7 @@ export function Scale({ settings, onSubmit, className }: ScaleProps): JSX.Elemen
76
111
  id={`scale-option-${i}`}
77
112
  key={`scale-option-${i}`}
78
113
  type="button"
79
- onClick={() => setScore(i)}
114
+ onClick={() => onScoreChange(i)}
80
115
  className={`${score === i ? 'active' : ''}`}
81
116
  >
82
117
  {i}
@@ -84,37 +119,10 @@ export function Scale({ settings, onSubmit, className }: ScaleProps): JSX.Elemen
84
119
  );
85
120
  }
86
121
 
87
- const displayReasons = !!score && reasonsSettings && !reasonsSettings.hide;
88
- const displayComment = !!(score && !commentSettings?.hide);
122
+ const displayReasons = !!score && hasReasons;
123
+ const displayComment = !!score && hasComment;
89
124
  const displaySubmitBnt = !!score && (displayReasons || displayComment);
90
- const displayFeedbackEmail = !!score && !optionalEmailSettings?.hide && !userData.isAuthenticated;
91
-
92
- const handleCancel = () => {
93
- setScore(0);
94
- setComment('');
95
- setReasons([]);
96
- setEmail(undefined);
97
- };
98
-
99
- const onSubmitScaleForm = () => {
100
- const trimmedComment = comment?.trim() || undefined;
101
- const trimmedEmail = email?.trim() || undefined;
102
- onSubmit({
103
- score,
104
- comment: trimmedComment,
105
- reasons,
106
- max: MAX_SCALE,
107
- email: trimmedEmail,
108
- });
109
- setIsSubmitted(true);
110
- };
111
-
112
- useEffect(() => {
113
- if (score && !displayComment && !displayReasons && !displayFeedbackEmail) {
114
- onSubmitScaleForm();
115
- }
116
- // eslint-disable-next-line react-hooks/exhaustive-deps
117
- }, [score, displayComment, displayReasons, displayFeedbackEmail]);
125
+ const displayFeedbackEmail = !!score && hasOptionalEmail;
118
126
 
119
127
  if (isSubmitted) {
120
128
  return (
@@ -1,5 +1,4 @@
1
1
  import * as React from 'react';
2
- import { useEffect } from 'react';
3
2
  import styled from 'styled-components';
4
3
 
5
4
  import type { JSX } from 'react';
@@ -86,10 +85,13 @@ export function Sentiment({ settings, onSubmit, className }: SentimentProps): JS
86
85
  return !scoreSpecificReasonsSettings?.hide;
87
86
  };
88
87
 
88
+ const hasComment = !commentSettings?.hide;
89
+ const hasOptionalEmail = !optionalEmailSettings?.hide && !userData?.isAuthenticated;
90
+
89
91
  const displayReasons = checkIfShouldDisplayReasons(score);
90
- const displayComment = !!(score && !commentSettings?.hide);
92
+ const displayComment = !!score && hasComment;
91
93
  const displaySubmitBnt = !!(score && (displayReasons || displayComment));
92
- const displayFeedbackEmail = !!score && !optionalEmailSettings?.hide && !userData.isAuthenticated;
94
+ const displayFeedbackEmail = !!score && hasOptionalEmail;
93
95
 
94
96
  const commentLabel =
95
97
  score === 1
@@ -117,11 +119,11 @@ export function Sentiment({ settings, onSubmit, className }: SentimentProps): JS
117
119
  return scoreSpecificReasonSettings?.component;
118
120
  };
119
121
 
120
- const onSubmitSentimentForm = () => {
122
+ const submitSentiment = (sentimentScore: number) => {
121
123
  const trimmedComment = comment?.trim() || undefined;
122
124
  const trimmedEmail = email?.trim() || undefined;
123
125
  onSubmit({
124
- score,
126
+ score: sentimentScore,
125
127
  comment: trimmedComment,
126
128
  reasons,
127
129
  email: trimmedEmail,
@@ -129,6 +131,18 @@ export function Sentiment({ settings, onSubmit, className }: SentimentProps): JS
129
131
  setIsSubmitted(true);
130
132
  };
131
133
 
134
+ const onSubmitSentimentForm = () => {
135
+ submitSentiment(score);
136
+ };
137
+
138
+ const onScoreChange = (newScore: number) => {
139
+ setScore(newScore);
140
+
141
+ if (newScore && !checkIfShouldDisplayReasons(newScore) && !hasComment && !hasOptionalEmail) {
142
+ submitSentiment(newScore);
143
+ }
144
+ };
145
+
132
146
  const onCancelSentimentForm = () => {
133
147
  setScore(0);
134
148
  setComment('');
@@ -136,13 +150,6 @@ export function Sentiment({ settings, onSubmit, className }: SentimentProps): JS
136
150
  setEmail(undefined);
137
151
  };
138
152
 
139
- useEffect(() => {
140
- if (score && !displayComment && !displayReasons && !displayFeedbackEmail) {
141
- onSubmitSentimentForm();
142
- }
143
- // eslint-disable-next-line react-hooks/exhaustive-deps
144
- }, [score, displayComment, displayReasons, displayFeedbackEmail]);
145
-
146
153
  if (isSubmitted) {
147
154
  return (
148
155
  <SentimentWrapper data-component-name="Feedback/Sentiment">
@@ -174,7 +181,7 @@ export function Sentiment({ settings, onSubmit, className }: SentimentProps): JS
174
181
  size="medium"
175
182
  variant={score === 1 ? 'primary' : 'secondary'}
176
183
  onClick={() => {
177
- setScore(1);
184
+ onScoreChange(1);
178
185
  }}
179
186
  aria-label={translate('feedback.sentiment.thumbUp', 'Like')}
180
187
  icon={<ThumbUpIcon />}
@@ -185,7 +192,7 @@ export function Sentiment({ settings, onSubmit, className }: SentimentProps): JS
185
192
  variant={score === -1 ? 'primary' : 'secondary'}
186
193
  tone={score === -1 ? 'danger' : 'default'}
187
194
  onClick={() => {
188
- setScore(-1);
195
+ onScoreChange(-1);
189
196
  }}
190
197
  aria-label={translate('feedback.sentiment.thumbDown', 'Dislike')}
191
198
  icon={<ThumbDownIcon />}
@@ -77,6 +77,7 @@ const StyledSelect = styled(Select)<SelectProps>`
77
77
  --select-text-color: var(--filter-select-color);
78
78
  border: 1px solid var(--filter-select-border-color);
79
79
  --select-border-radius: var(--filter-select-border-radius);
80
+ --select-input-border-radius: var(--filter-select-border-radius);
80
81
  padding: var(--filter-select-padding);
81
82
 
82
83
  &:hover {
@@ -72,7 +72,7 @@ export const filter = css`
72
72
  --filter-select-max-width: 100%;
73
73
  --filter-select-color: var(--text-color-primary);
74
74
  --filter-select-border-color: var(--border-color-primary);
75
- --filter-select-border-radius: calc(var(--spacing-unit) * 1.5);
75
+ --filter-select-border-radius: var(--input-border-radius);
76
76
  --filter-select-padding: 0;
77
77
  --filter-select-border-color-hover: var(--text-color-primary);
78
78
  --filter-select-option-margin: 0;
@@ -92,7 +92,7 @@ export const filter = css`
92
92
  --filter-date-picker-icon-width: var(--spacing-sm);
93
93
  --filter-date-picker-icon-stroke-hover: var(--text-color-primary);
94
94
  --filter-date-picker-wrapper-border-color: var(--border-color-primary);
95
- --filter-date-picker-wrapper-radius: calc(var(--spacing-unit) * 1.5);
95
+ --filter-date-picker-wrapper-radius: var(--border-radius-md);
96
96
  --filter-date-picker-wrapper-padding: calc(var(--spacing-xxs) / 2) var(--spacing-xs);
97
97
 
98
98
  // @tokens End
@@ -10,7 +10,7 @@ export const image = css`
10
10
  --image-frame-border-color: var(--border-color-secondary);
11
11
  --image-frame-border-radius: var(--border-radius-xxl);
12
12
  --image-frame-bg-color: var(--bg-color-raised);
13
- --image-frame-image-border-radius: var(--border-radius-lg);
13
+ --image-frame-image-border-radius: var(--border-radius-xl);
14
14
 
15
15
  /**
16
16
  * @tokens Image caption
@@ -24,7 +24,7 @@ export const image = css`
24
24
  /**
25
25
  * @tokens Image gallery
26
26
  */
27
- --image-gallery-border-radius: var(--border-radius-lg);
27
+ --image-gallery-border-radius: var(--border-radius-xl);
28
28
  --image-gallery-image-bg-color: var(--bg-color-tonal);
29
29
 
30
30
  /**
@@ -49,8 +49,10 @@ export const image = css`
49
49
  --image-lightbox-close-size: 40px;
50
50
  --image-lightbox-close-icon-size: 18px;
51
51
  --image-lightbox-close-offset: var(--spacing-base);
52
- --image-lightbox-close-border-radius: var(--border-radius-lg);
52
+ --image-lightbox-close-border-radius: var(--border-radius-xl);
53
53
  --image-lightbox-side-gutter: calc(
54
54
  var(--image-lightbox-close-size) + var(--image-lightbox-close-offset) + var(--spacing-sm)
55
55
  );
56
+
57
+ // @tokens End
56
58
  `;
@@ -22,7 +22,7 @@ export const languagePicker = css`
22
22
  --language-picker-dropdown-item-padding-vertical: var(--dropdown-menu-item-padding-vertical); // @presenter Spacing
23
23
  --language-picker-dropdown-item-separator-padding-top: var(--dropdown-menu-item-separator-padding-top ); // @presenter Spacing
24
24
  --language-picker-dropdown-item-separator-padding-bottom: var(--dropdown-menu-item-separator-padding-bottom ); // @presenter Spacing
25
- --language-picker-dropdown-item-border-radius: var(--dropdown-menu-item-border-radius ); // @presenter BorderRadius
25
+ --language-picker-dropdown-item-border-radius: var(--dropdown-menu-item-border-radius); // @presenter BorderRadius
26
26
  --language-picker-dropdown-item-bg-color-active: var(--dropdown-menu-item-bg-color-active); // @presenter Color
27
27
  --language-picker-dropdown-item-bg-color-hover: var(--dropdown-menu-item-bg-color-hover); // @presenter Color
28
28
  --language-picker-dropdown-item-bg-color-disabled: var(--dropdown-menu-item-bg-color-disabled); // @presenter Color
@@ -40,7 +40,7 @@ export const markdown = css`
40
40
  --md-table-line-height: var(--line-height-md); // @presenter FontSize
41
41
  --md-table-margin-vertical: 20px; // @presenter Spacing
42
42
  --md-table-bg-color: transparent; // @presenter Color
43
- --md-table-border-radius: var(--border-radius);
43
+ --md-table-border-radius: var(--border-radius-xl);
44
44
 
45
45
  --md-table-border-width: 1px;
46
46
  --md-table-header-bg-color: var(--layer-color);
@@ -122,8 +122,8 @@ function MenuItemImpl(props: React.PropsWithChildren<MenuItemProps>): JSX.Elemen
122
122
  onClick={handleOnClick}
123
123
  onKeyDown={handleExpandOnEnter}
124
124
  ref={labelRef}
125
- role={item.link ? 'none' : 'link'}
126
- tabIndex={!item.link ? 0 : undefined}
125
+ role={item.link || isSeparator ? 'none' : 'link'}
126
+ tabIndex={!item.link && !isSeparator ? 0 : undefined}
127
127
  data-testid="menu-item-label"
128
128
  data-active={item.active}
129
129
  >
@@ -56,7 +56,7 @@ export const menu = css`
56
56
  --menu-item-label-margin: var(--menu-item-label-margin-vertical) var(--menu-item-label-margin-horizontal);
57
57
  --menu-item-label-padding: var(--menu-item-padding-vertical) var(--menu-item-padding-horizontal);
58
58
  --menu-item-label-gap: var(--spacing-xxs);
59
- --menu-item-label-border-radius: 6px;
59
+ --menu-item-label-border-radius: var(--border-radius-lg);
60
60
  --menu-item-label-chevron-size: 12px;
61
61
  --menu-item-label-chevron-offset: calc(var(--menu-item-label-gap) + var(--menu-item-label-chevron-size));
62
62
 
@@ -27,7 +27,7 @@ export const navbar = css`
27
27
 
28
28
  --navbar-item-line-height: var(--line-height-base);
29
29
  --navbar-item-bg-color-active: var(--bg-color-active);
30
- --navbar-item-border-radius: var(--border-radius);
30
+ --navbar-item-border-radius: var(--border-radius-lg);
31
31
  --navbar-item-bottom-border: none;
32
32
 
33
33
  --navbar-item-text-color-hover: var(--text-color-primary);