@redocly/theme 0.67.0-next.3 → 0.67.0-next.5
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.
- package/lib/components/Breadcrumbs/BreadcrumbDropdown.d.ts +2 -1
- package/lib/components/Breadcrumbs/BreadcrumbDropdown.js +9 -10
- package/lib/components/Breadcrumbs/Breadcrumbs.js +5 -22
- package/lib/components/Buttons/AIAssistantButton.js +2 -6
- package/lib/components/Buttons/EditPageButton.js +2 -1
- package/lib/components/Catalog/CatalogCardView/CatalogCard.js +1 -1
- package/lib/components/CatalogClassic/CatalogClassicActions.js +3 -1
- package/lib/components/CatalogClassic/CatalogClassicCard.js +1 -1
- package/lib/components/CatalogClassic/CatalogClassicInfoBlock.js +2 -1
- package/lib/components/Dropdown/Dropdown.d.ts +2 -0
- package/lib/components/Dropdown/Dropdown.js +8 -2
- package/lib/components/Feedback/ReportDialog.js +4 -1
- package/lib/components/Filter/FilterCheckboxes.js +3 -1
- package/lib/components/Footer/FooterItem.js +1 -1
- package/lib/components/LanguagePicker/LanguagePicker.js +3 -1
- package/lib/components/Logo/Logo.js +2 -1
- package/lib/components/Menu/MenuContainer.js +1 -0
- package/lib/components/Menu/MenuItem.js +21 -7
- package/lib/components/Navbar/Navbar.js +6 -2
- package/lib/components/Navbar/NavbarItem.js +3 -1
- package/lib/components/Search/SearchAiMessage.js +23 -5
- package/lib/components/Search/SearchDialog.js +5 -33
- package/lib/components/Search/SearchInput.js +4 -1
- package/lib/components/Search/SearchRecent.js +3 -1
- package/lib/components/SidebarActions/SidebarActions.js +10 -3
- package/lib/components/TableOfContent/TableOfContent.js +1 -1
- package/lib/components/UserMenu/LoginButton.js +2 -1
- package/lib/components/UserMenu/LogoutMenuItem.js +2 -1
- package/lib/core/hooks/search/use-search-dialog.js +7 -2
- package/lib/core/hooks/use-banner-telemetry.js +2 -11
- package/lib/core/hooks/use-color-switcher.js +2 -1
- package/lib/core/hooks/use-page-actions.js +12 -21
- package/lib/core/hooks/use-product-picker.js +14 -4
- package/lib/core/hooks/use-telemetry-fallback.d.ts +45 -37
- package/lib/core/hooks/use-telemetry-fallback.js +47 -39
- package/lib/core/types/search.d.ts +2 -1
- package/lib/core/types/search.js +1 -0
- package/lib/core/utils/index.d.ts +2 -0
- package/lib/core/utils/index.js +2 -0
- package/lib/core/utils/telemetry/generate-before-after-context.d.ts +37 -0
- package/lib/core/utils/telemetry/generate-before-after-context.js +32 -0
- package/lib/core/utils/telemetry/generate-resource-urn.d.ts +7 -0
- package/lib/core/utils/telemetry/generate-resource-urn.js +13 -0
- package/lib/core/utils/telemetry/get-base-data-attributes.d.ts +14 -0
- package/lib/core/utils/telemetry/get-base-data-attributes.js +17 -0
- package/package.json +3 -3
- package/src/components/Breadcrumbs/BreadcrumbDropdown.tsx +18 -4
- package/src/components/Breadcrumbs/Breadcrumbs.tsx +5 -6
- package/src/components/Buttons/AIAssistantButton.tsx +2 -3
- package/src/components/Buttons/EditPageButton.tsx +4 -1
- package/src/components/Catalog/CatalogCardView/CatalogCard.tsx +2 -2
- package/src/components/CatalogClassic/CatalogClassicActions.tsx +4 -2
- package/src/components/CatalogClassic/CatalogClassicCard.tsx +9 -2
- package/src/components/CatalogClassic/CatalogClassicInfoBlock.tsx +2 -1
- package/src/components/Dropdown/Dropdown.tsx +8 -1
- package/src/components/Feedback/ReportDialog.tsx +4 -1
- package/src/components/Filter/FilterCheckboxes.tsx +4 -2
- package/src/components/Footer/FooterItem.tsx +4 -2
- package/src/components/LanguagePicker/LanguagePicker.tsx +9 -2
- package/src/components/Logo/Logo.tsx +7 -1
- package/src/components/Menu/MenuContainer.tsx +1 -0
- package/src/components/Menu/MenuItem.tsx +35 -4
- package/src/components/Navbar/Navbar.tsx +7 -3
- package/src/components/Navbar/NavbarItem.tsx +7 -1
- package/src/components/Search/SearchAiMessage.tsx +25 -5
- package/src/components/Search/SearchDialog.tsx +6 -13
- package/src/components/Search/SearchInput.tsx +4 -1
- package/src/components/Search/SearchRecent.tsx +4 -2
- package/src/components/SidebarActions/SidebarActions.tsx +10 -3
- package/src/components/TableOfContent/TableOfContent.tsx +7 -2
- package/src/components/UserMenu/LoginButton.tsx +4 -1
- package/src/components/UserMenu/LogoutMenuItem.tsx +2 -1
- package/src/core/hooks/search/use-search-dialog.ts +13 -2
- package/src/core/hooks/use-banner-telemetry.ts +5 -4
- package/src/core/hooks/use-color-switcher.ts +7 -1
- package/src/core/hooks/use-page-actions.ts +17 -28
- package/src/core/hooks/use-product-picker.ts +19 -5
- package/src/core/hooks/use-telemetry-fallback.ts +47 -39
- package/src/core/types/search.ts +1 -0
- package/src/core/utils/index.ts +2 -0
- package/src/core/utils/telemetry/generate-before-after-context.ts +59 -0
- package/src/core/utils/telemetry/generate-resource-urn.ts +9 -0
- package/src/core/utils/telemetry/get-base-data-attributes.ts +27 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@redocly/theme",
|
|
3
|
-
"version": "0.67.0-next.
|
|
3
|
+
"version": "0.67.0-next.5",
|
|
4
4
|
"description": "Shared UI components lib",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"theme",
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"vitest": "4.1.8",
|
|
64
64
|
"vitest-when": "0.6.2",
|
|
65
65
|
"webpack": "5.105.2",
|
|
66
|
-
"@redocly/realm-asyncapi-sdk": "0.13.0-next.
|
|
66
|
+
"@redocly/realm-asyncapi-sdk": "0.13.0-next.4"
|
|
67
67
|
},
|
|
68
68
|
"dependencies": {
|
|
69
69
|
"@tanstack/react-query": "5.62.3",
|
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
"openapi-sampler": "^1.7.2",
|
|
82
82
|
"react-calendar": "5.1.0",
|
|
83
83
|
"react-date-picker": "11.0.0",
|
|
84
|
-
"@redocly/config": "0.49.
|
|
84
|
+
"@redocly/config": "0.49.1"
|
|
85
85
|
},
|
|
86
86
|
"scripts": {
|
|
87
87
|
"watch": "tsgo -p tsconfig.build.json && (concurrently \"tsgo -w -p tsconfig.build.json\" \"tsc-alias -w -p tsconfig.build.json\")",
|
|
@@ -12,6 +12,7 @@ import { Tooltip } from '@redocly/theme/components/Tooltip/Tooltip';
|
|
|
12
12
|
import { GenericIcon } from '@redocly/theme/icons/GenericIcon/GenericIcon';
|
|
13
13
|
import { BREADCRUMB_MAX_LENGTH } from '@redocly/theme/core/constants';
|
|
14
14
|
import { BreadcrumbIcon } from '@redocly/theme/components/Breadcrumbs/BreadcrumbIcon';
|
|
15
|
+
import { getBaseDataAttributes } from '@redocly/theme/core/utils';
|
|
15
16
|
|
|
16
17
|
type BreadcrumbDropdownProps = {
|
|
17
18
|
children?: React.ReactNode;
|
|
@@ -19,6 +20,7 @@ type BreadcrumbDropdownProps = {
|
|
|
19
20
|
items: (BreadcrumbItem & { isActive?: boolean })[];
|
|
20
21
|
onItemClick?: (item: BreadcrumbItem, index: number) => void;
|
|
21
22
|
className?: string;
|
|
23
|
+
withChevron?: boolean;
|
|
22
24
|
};
|
|
23
25
|
|
|
24
26
|
export function BreadcrumbDropdown({
|
|
@@ -27,10 +29,12 @@ export function BreadcrumbDropdown({
|
|
|
27
29
|
items,
|
|
28
30
|
onItemClick,
|
|
29
31
|
className,
|
|
32
|
+
withChevron,
|
|
30
33
|
}: BreadcrumbDropdownProps): JSX.Element | null {
|
|
31
34
|
const { useTelemetry, useTranslate } = useThemeHooks();
|
|
32
35
|
const telemetry = useTelemetry();
|
|
33
36
|
const { translate } = useTranslate();
|
|
37
|
+
const [isOpen, setIsOpen] = React.useState(false);
|
|
34
38
|
|
|
35
39
|
if (!items || items.length === 0) {
|
|
36
40
|
return null;
|
|
@@ -46,7 +50,12 @@ export function BreadcrumbDropdown({
|
|
|
46
50
|
children
|
|
47
51
|
);
|
|
48
52
|
|
|
49
|
-
const trigger =
|
|
53
|
+
const trigger = (
|
|
54
|
+
<StyledDropdownTrigger>
|
|
55
|
+
{triggerContent}
|
|
56
|
+
{withChevron && <GenericIcon icon={isOpen ? 'chevron-up' : 'chevron-down'} />}
|
|
57
|
+
</StyledDropdownTrigger>
|
|
58
|
+
);
|
|
50
59
|
|
|
51
60
|
return (
|
|
52
61
|
<BreadcrumbDropdownWrapper
|
|
@@ -54,7 +63,12 @@ export function BreadcrumbDropdown({
|
|
|
54
63
|
className={className}
|
|
55
64
|
data-testid="breadcrumb-dropdown"
|
|
56
65
|
>
|
|
57
|
-
<Dropdown
|
|
66
|
+
<Dropdown
|
|
67
|
+
trigger={trigger}
|
|
68
|
+
closeOnClick={true}
|
|
69
|
+
onOpen={() => setIsOpen(true)}
|
|
70
|
+
onClose={() => setIsOpen(false)}
|
|
71
|
+
>
|
|
58
72
|
<DropdownMenu>
|
|
59
73
|
{items.map((item, index) => {
|
|
60
74
|
const isActive = Boolean(item?.isActive);
|
|
@@ -68,7 +82,7 @@ export function BreadcrumbDropdown({
|
|
|
68
82
|
onItemClick?.(item, index);
|
|
69
83
|
telemetry.sendBreadcrumbClickedMessage([
|
|
70
84
|
{
|
|
71
|
-
|
|
85
|
+
...getBaseDataAttributes('breadcrumbId', 'breadcrumb'),
|
|
72
86
|
link: item.link,
|
|
73
87
|
position: index + 1,
|
|
74
88
|
totalBreadcrumbs: items.length,
|
|
@@ -117,7 +131,7 @@ const StyledDropdownTrigger = styled.button`
|
|
|
117
131
|
background-color: var(--breadcrumbs-background-color-hover);
|
|
118
132
|
}
|
|
119
133
|
|
|
120
|
-
&:focus {
|
|
134
|
+
&:focus-visible {
|
|
121
135
|
box-shadow: var(--breadcrumbs-box-shadow-focus);
|
|
122
136
|
outline: none;
|
|
123
137
|
}
|
|
@@ -8,9 +8,8 @@ import { useThemeHooks } from '@redocly/theme/core/hooks';
|
|
|
8
8
|
import { Breadcrumb } from '@redocly/theme/components/Breadcrumbs/Breadcrumb';
|
|
9
9
|
import { BreadcrumbDropdown } from '@redocly/theme/components/Breadcrumbs/BreadcrumbDropdown';
|
|
10
10
|
import { BreadcrumbIcon } from '@redocly/theme/components/Breadcrumbs/BreadcrumbIcon';
|
|
11
|
-
import { trimText } from '@redocly/theme/core/utils';
|
|
11
|
+
import { trimText, getBaseDataAttributes } from '@redocly/theme/core/utils';
|
|
12
12
|
import { BREADCRUMB_MAX_LENGTH } from '@redocly/theme/core/constants';
|
|
13
|
-
import { GenericIcon } from '@redocly/theme/icons/GenericIcon/GenericIcon';
|
|
14
13
|
|
|
15
14
|
export function Breadcrumbs(props: {
|
|
16
15
|
className?: string;
|
|
@@ -65,10 +64,11 @@ export function Breadcrumbs(props: {
|
|
|
65
64
|
<BreadcrumbDropdown
|
|
66
65
|
label={translatedLabel}
|
|
67
66
|
items={siblingsWithActive}
|
|
67
|
+
withChevron
|
|
68
68
|
onItemClick={(item, itemIdx) =>
|
|
69
69
|
telemetry.sendBreadcrumbClickedMessage([
|
|
70
70
|
{
|
|
71
|
-
|
|
71
|
+
...getBaseDataAttributes('breadcrumbId', 'breadcrumb'),
|
|
72
72
|
link: item.link,
|
|
73
73
|
position: itemIdx + 1,
|
|
74
74
|
totalBreadcrumbs: siblingsWithActive.length,
|
|
@@ -78,7 +78,6 @@ export function Breadcrumbs(props: {
|
|
|
78
78
|
>
|
|
79
79
|
<BreadcrumbIcon icon={breadcrumb.icon} />
|
|
80
80
|
{trimText(translatedLabel, BREADCRUMB_MAX_LENGTH)}
|
|
81
|
-
<GenericIcon icon="chevron-down" />
|
|
82
81
|
</BreadcrumbDropdown>
|
|
83
82
|
);
|
|
84
83
|
}
|
|
@@ -92,7 +91,7 @@ export function Breadcrumbs(props: {
|
|
|
92
91
|
onClick={() =>
|
|
93
92
|
telemetry.sendBreadcrumbClickedMessage([
|
|
94
93
|
{
|
|
95
|
-
|
|
94
|
+
...getBaseDataAttributes('breadcrumbId', 'breadcrumb'),
|
|
96
95
|
link: breadcrumb.link,
|
|
97
96
|
position: idx + 1,
|
|
98
97
|
totalBreadcrumbs: breadcrumbs.length,
|
|
@@ -120,7 +119,7 @@ export function Breadcrumbs(props: {
|
|
|
120
119
|
onItemClick={(item, itemIdx) =>
|
|
121
120
|
telemetry.sendBreadcrumbClickedMessage([
|
|
122
121
|
{
|
|
123
|
-
|
|
122
|
+
...getBaseDataAttributes('breadcrumbId', 'breadcrumb'),
|
|
124
123
|
link: item.link,
|
|
125
124
|
position: itemIdx + 1,
|
|
126
125
|
totalBreadcrumbs: breadcrumbs.length,
|
|
@@ -9,6 +9,7 @@ import { ChatIcon } from '@redocly/theme/icons/ChatIcon/ChatIcon';
|
|
|
9
9
|
import { AiStarsGradientIcon } from '@redocly/theme/icons/AiStarsGradientIcon/AiStarsGradientIcon';
|
|
10
10
|
import { RedoclyIcon } from '@redocly/theme/icons/RedoclyIcon/RedoclyIcon';
|
|
11
11
|
import { SearchSessionProvider } from '@redocly/theme/core/contexts';
|
|
12
|
+
import { getBaseDataAttributes } from '@redocly/theme/core/utils';
|
|
12
13
|
|
|
13
14
|
type AIAssistantButtonIconType = 'chat' | 'sparkles' | 'redocly';
|
|
14
15
|
type AIAssistantButtonType = 'button' | 'icon';
|
|
@@ -79,9 +80,7 @@ export function AIAssistantButton() {
|
|
|
79
80
|
setIsOpen(true);
|
|
80
81
|
telemetry.sendSearchAiOpenedMessage([
|
|
81
82
|
{
|
|
82
|
-
|
|
83
|
-
object: 'search',
|
|
84
|
-
uri: 'urn:redocly:realm:ui:search:aiAssistantTriggerButton',
|
|
83
|
+
...getBaseDataAttributes('aiAssistantTriggerButton', 'search'),
|
|
85
84
|
method: 'ai_trigger_button',
|
|
86
85
|
},
|
|
87
86
|
]);
|
|
@@ -6,6 +6,7 @@ import type { JSX } from 'react';
|
|
|
6
6
|
import { useThemeHooks } from '@redocly/theme/core/hooks';
|
|
7
7
|
import { EditIcon } from '@redocly/theme/icons/EditIcon/EditIcon';
|
|
8
8
|
import { Button } from '@redocly/theme/components/Button/Button';
|
|
9
|
+
import { getBaseDataAttributes } from '@redocly/theme/core/utils';
|
|
9
10
|
|
|
10
11
|
export type EditPageButtonProps = {
|
|
11
12
|
to: string;
|
|
@@ -24,7 +25,9 @@ export function EditPageButton({ to }: EditPageButtonProps): JSX.Element {
|
|
|
24
25
|
variant="ghost"
|
|
25
26
|
size="small"
|
|
26
27
|
icon={<EditIcon />}
|
|
27
|
-
onClick={() =>
|
|
28
|
+
onClick={() =>
|
|
29
|
+
telemetry.sendPageEditClickedMessage([getBaseDataAttributes('pageEdit', 'button')])
|
|
30
|
+
}
|
|
28
31
|
data-translation-key="markdown.editPage.text"
|
|
29
32
|
>
|
|
30
33
|
{translate('markdown.editPage.text', 'Edit')}
|
|
@@ -11,7 +11,7 @@ import { ArrowRightIcon } from '@redocly/theme/icons/ArrowRightIcon/ArrowRightIc
|
|
|
11
11
|
import { ArrowUpRightIcon } from '@redocly/theme/icons/ArrowUpRightIcon/ArrowUpRightIcon';
|
|
12
12
|
import { CatalogTags } from '@redocly/theme/components/Catalog/CatalogTags';
|
|
13
13
|
import { CatalogEntityIcon } from '@redocly/theme/components/Catalog/CatalogEntityIcon';
|
|
14
|
-
import { getPathPrefix } from '@redocly/theme/core/utils';
|
|
14
|
+
import { getPathPrefix, getBaseDataAttributes } from '@redocly/theme/core/utils';
|
|
15
15
|
|
|
16
16
|
export type CatalogCardProps = {
|
|
17
17
|
entity: BffCatalogEntity;
|
|
@@ -31,7 +31,7 @@ export function CatalogCard({ entity, catalogConfig }: CatalogCardProps): JSX.El
|
|
|
31
31
|
window.location.assign(
|
|
32
32
|
`${pathPrefix}/catalogs/${catalogConfig.slug}/entities/${entity.key}`,
|
|
33
33
|
);
|
|
34
|
-
telemetry.sendCatalogItemClickedMessage();
|
|
34
|
+
telemetry.sendCatalogItemClickedMessage([getBaseDataAttributes('catalogItem', 'card')]);
|
|
35
35
|
}}
|
|
36
36
|
>
|
|
37
37
|
<CardContent>
|
|
@@ -4,7 +4,7 @@ import styled from 'styled-components';
|
|
|
4
4
|
import type { JSX } from 'react';
|
|
5
5
|
import type { ResolvedFilter } from '@redocly/theme/core/types';
|
|
6
6
|
|
|
7
|
-
import { breakpoints } from '@redocly/theme/core/utils';
|
|
7
|
+
import { breakpoints, getBaseDataAttributes } from '@redocly/theme/core/utils';
|
|
8
8
|
import { useThemeHooks } from '@redocly/theme/core/hooks';
|
|
9
9
|
import { Button } from '@redocly/theme/components/Button/Button';
|
|
10
10
|
import { FilterIcon } from '@redocly/theme/icons/FilterIcon/FilterIcon';
|
|
@@ -42,7 +42,9 @@ export function CatalogClassicActions(props: CatalogClassicActionsProps): JSX.El
|
|
|
42
42
|
iconPosition="left"
|
|
43
43
|
onClick={() => {
|
|
44
44
|
onOpenFilter();
|
|
45
|
-
telemetry.
|
|
45
|
+
telemetry.sendCatalogActionsClickedMessage([
|
|
46
|
+
getBaseDataAttributes('catalogActions', 'button'),
|
|
47
|
+
]);
|
|
46
48
|
}}
|
|
47
49
|
data-translation-key="catalog.filters.title"
|
|
48
50
|
>
|
|
@@ -4,7 +4,12 @@ import styled from 'styled-components';
|
|
|
4
4
|
import type { JSX } from 'react';
|
|
5
5
|
import type { CatalogItem } from '@redocly/theme/core/types';
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
slug,
|
|
9
|
+
capitalize,
|
|
10
|
+
getScorecardColorVariable,
|
|
11
|
+
getBaseDataAttributes,
|
|
12
|
+
} from '@redocly/theme/core/utils';
|
|
8
13
|
import { useThemeHooks } from '@redocly/theme/core/hooks';
|
|
9
14
|
import { ArrowRightIcon } from '@redocly/theme/icons/ArrowRightIcon/ArrowRightIcon';
|
|
10
15
|
import { Link } from '@redocly/theme/components/Link/Link';
|
|
@@ -38,7 +43,9 @@ export function CatalogClassicCard({ item }: CatalogClassicCardProps): JSX.Eleme
|
|
|
38
43
|
<Link key={item.docsLink || item.link} to={item.docsLink || item.link}>
|
|
39
44
|
<StyledCard
|
|
40
45
|
data-component-name="CatalogClassic/CatalogClassicCard"
|
|
41
|
-
onClick={() =>
|
|
46
|
+
onClick={() =>
|
|
47
|
+
telemetry.sendCatalogItemClickedMessage([getBaseDataAttributes('catalogItem', 'card')])
|
|
48
|
+
}
|
|
42
49
|
>
|
|
43
50
|
<CardContent>
|
|
44
51
|
<CardTitleWrapper>
|
|
@@ -7,6 +7,7 @@ import { useThemeHooks } from '@redocly/theme/core/hooks';
|
|
|
7
7
|
import { getScorecardColorVariable } from '@redocly/theme/core/utils';
|
|
8
8
|
import { Tag } from '@redocly/theme/components/Tag/Tag';
|
|
9
9
|
import { Link } from '@redocly/theme/components/Link/Link';
|
|
10
|
+
import { getBaseDataAttributes } from '@redocly/theme/core/utils';
|
|
10
11
|
|
|
11
12
|
export type CatalogClassicInfoBlockProps = {
|
|
12
13
|
metadata?: {
|
|
@@ -53,7 +54,7 @@ function ScorecardBadge(props: {
|
|
|
53
54
|
<Link to={slug}>
|
|
54
55
|
<Tag
|
|
55
56
|
onClick={() =>
|
|
56
|
-
telemetry.sendScorecardLinkClickedMessage([
|
|
57
|
+
telemetry.sendScorecardLinkClickedMessage([getBaseDataAttributes('scorecardLink', 'tag')])
|
|
57
58
|
}
|
|
58
59
|
withStatusDot
|
|
59
60
|
statusDotColor={`var(${colorVariable})`}
|
|
@@ -30,6 +30,7 @@ export type DropdownProps = PropsWithChildren<{
|
|
|
30
30
|
|
|
31
31
|
onClick?: (event: React.UIEvent) => void;
|
|
32
32
|
onClose?: () => void;
|
|
33
|
+
onOpen?: () => void;
|
|
33
34
|
}>;
|
|
34
35
|
|
|
35
36
|
export const Dropdown = forwardRef<HTMLDivElement, DropdownProps>(
|
|
@@ -47,6 +48,7 @@ export const Dropdown = forwardRef<HTMLDivElement, DropdownProps>(
|
|
|
47
48
|
alignment,
|
|
48
49
|
onClick,
|
|
49
50
|
onClose,
|
|
51
|
+
onOpen,
|
|
50
52
|
},
|
|
51
53
|
ref,
|
|
52
54
|
) => {
|
|
@@ -55,6 +57,7 @@ export const Dropdown = forwardRef<HTMLDivElement, DropdownProps>(
|
|
|
55
57
|
|
|
56
58
|
const handleOpen = () => {
|
|
57
59
|
setIsOpen(true);
|
|
60
|
+
onOpen?.();
|
|
58
61
|
};
|
|
59
62
|
|
|
60
63
|
const handleClose = () => {
|
|
@@ -69,7 +72,11 @@ export const Dropdown = forwardRef<HTMLDivElement, DropdownProps>(
|
|
|
69
72
|
const handleToggle = (event: React.UIEvent) => {
|
|
70
73
|
event.stopPropagation();
|
|
71
74
|
event.preventDefault();
|
|
72
|
-
|
|
75
|
+
if (isOpen) {
|
|
76
|
+
handleClose();
|
|
77
|
+
} else {
|
|
78
|
+
handleOpen();
|
|
79
|
+
}
|
|
73
80
|
};
|
|
74
81
|
|
|
75
82
|
const handleKeyDown = (event: React.KeyboardEvent) => {
|
|
@@ -8,6 +8,7 @@ import type { SubmitFeedbackParams } from '@redocly/theme/core/types';
|
|
|
8
8
|
import { useThemeHooks } from '@redocly/theme/core/hooks';
|
|
9
9
|
import { Comment } from '@redocly/theme/components/Feedback/Comment';
|
|
10
10
|
import { Portal } from '@redocly/theme/components/Portal/Portal';
|
|
11
|
+
import { getBaseDataAttributes } from '@redocly/theme/core/utils';
|
|
11
12
|
|
|
12
13
|
export type ReportDialogProps = {
|
|
13
14
|
location: string;
|
|
@@ -47,7 +48,9 @@ export function ReportDialog({
|
|
|
47
48
|
path: pathname,
|
|
48
49
|
lang,
|
|
49
50
|
});
|
|
50
|
-
telemetry.sendCodeSnippetReportedMessage(
|
|
51
|
+
telemetry.sendCodeSnippetReportedMessage([
|
|
52
|
+
getBaseDataAttributes('codeSnippet', 'markdocTag'),
|
|
53
|
+
]);
|
|
51
54
|
onSubmit();
|
|
52
55
|
}}
|
|
53
56
|
isDialog={true}
|
|
@@ -11,7 +11,7 @@ import { FilterOptionLabel } from '@redocly/theme/components/Filter/FilterOption
|
|
|
11
11
|
import { useThemeHooks } from '@redocly/theme/core/hooks';
|
|
12
12
|
import { CheckboxIcon } from '@redocly/theme/icons/CheckboxIcon/CheckboxIcon';
|
|
13
13
|
import { CounterTag } from '@redocly/theme/components/Tags/CounterTag';
|
|
14
|
-
import { changeTextCasing } from '@redocly/theme/core/utils';
|
|
14
|
+
import { changeTextCasing, getBaseDataAttributes } from '@redocly/theme/core/utils';
|
|
15
15
|
|
|
16
16
|
export function FilterCheckboxes({
|
|
17
17
|
filter,
|
|
@@ -36,7 +36,9 @@ export function FilterCheckboxes({
|
|
|
36
36
|
role="link"
|
|
37
37
|
onClick={() => {
|
|
38
38
|
filter.toggleOption(value);
|
|
39
|
-
telemetry.sendFilterCheckboxToggledMessage([
|
|
39
|
+
telemetry.sendFilterCheckboxToggledMessage([
|
|
40
|
+
getBaseDataAttributes('filterId', 'checkbox'),
|
|
41
|
+
]);
|
|
40
42
|
}}
|
|
41
43
|
>
|
|
42
44
|
<CheckboxIcon
|
|
@@ -7,7 +7,7 @@ import type { ResolvedNavItem } from '@redocly/config';
|
|
|
7
7
|
import { useThemeHooks } from '@redocly/theme/core/hooks';
|
|
8
8
|
import { LaunchIcon } from '@redocly/theme/icons/LaunchIcon/LaunchIcon';
|
|
9
9
|
import { Link } from '@redocly/theme/components/Link/Link';
|
|
10
|
-
import { breakpoints } from '@redocly/theme/core/utils';
|
|
10
|
+
import { breakpoints, getBaseDataAttributes } from '@redocly/theme/core/utils';
|
|
11
11
|
import { GenericIcon } from '@redocly/theme/icons/GenericIcon/GenericIcon';
|
|
12
12
|
|
|
13
13
|
export type FooterItemProps = {
|
|
@@ -44,7 +44,9 @@ export function FooterItem({ item, iconsOnly, className }: FooterItemProps): JSX
|
|
|
44
44
|
external={item.external}
|
|
45
45
|
target={item.target}
|
|
46
46
|
data-testid={item.label}
|
|
47
|
-
onClick={() =>
|
|
47
|
+
onClick={() =>
|
|
48
|
+
telemetry.sendFooterItemClickedMessage([getBaseDataAttributes('footerItem', 'footer')])
|
|
49
|
+
}
|
|
48
50
|
data-translation-key={item.labelTranslationKey}
|
|
49
51
|
>
|
|
50
52
|
{hasIcon ? (
|
|
@@ -4,7 +4,7 @@ import styled from 'styled-components';
|
|
|
4
4
|
import type { JSX } from 'react';
|
|
5
5
|
|
|
6
6
|
import { DropdownMenu } from '@redocly/theme/components/Dropdown/DropdownMenu';
|
|
7
|
-
import { breakpoints } from '@redocly/theme/core/utils';
|
|
7
|
+
import { breakpoints, generateBeforeAfterContext } from '@redocly/theme/core/utils';
|
|
8
8
|
import { useLanguagePicker, useThemeHooks } from '@redocly/theme/core/hooks';
|
|
9
9
|
import { GlobalOutlinedIcon } from '@redocly/theme/icons/GlobalOutlinedIcon/GlobalOutlinedIcon';
|
|
10
10
|
import { Button } from '@redocly/theme/components/Button/Button';
|
|
@@ -41,7 +41,14 @@ export function LanguagePicker(props: LanguagePickerProps): JSX.Element | null {
|
|
|
41
41
|
languageInsensitive: true,
|
|
42
42
|
onAction: () => {
|
|
43
43
|
props.onChangeLanguage(locale.code);
|
|
44
|
-
telemetry.
|
|
44
|
+
telemetry.sendLanguagePickerChangedMessage([
|
|
45
|
+
...generateBeforeAfterContext<'sendLanguagePickerChangedMessage'>(
|
|
46
|
+
'languagePicker',
|
|
47
|
+
'dropdown',
|
|
48
|
+
{ locale: currentLocale.code },
|
|
49
|
+
{ locale: locale.code },
|
|
50
|
+
),
|
|
51
|
+
]);
|
|
45
52
|
},
|
|
46
53
|
active: locale.code === currentLocale.code,
|
|
47
54
|
suffix: locale.code === currentLocale.code && <CheckmarkIcon />,
|
|
@@ -7,6 +7,7 @@ import type { LogoConfig } from '@redocly/theme/core/types';
|
|
|
7
7
|
import { useThemeHooks } from '@redocly/theme/core/hooks';
|
|
8
8
|
import { Link } from '@redocly/theme/components/Link/Link';
|
|
9
9
|
import { Image } from '@redocly/theme/components/Image/Image';
|
|
10
|
+
import { getBaseDataAttributes } from '@redocly/theme/core/utils';
|
|
10
11
|
|
|
11
12
|
export type LogoProps = {
|
|
12
13
|
config: LogoConfig;
|
|
@@ -27,7 +28,12 @@ export function Logo({ config, className, ...otherProps }: LogoProps): JSX.Eleme
|
|
|
27
28
|
return (
|
|
28
29
|
<LogoWrapper data-component-name="Logo/Logo" className={className} {...otherProps}>
|
|
29
30
|
{config.link ? (
|
|
30
|
-
<Link
|
|
31
|
+
<Link
|
|
32
|
+
to={config.link}
|
|
33
|
+
onClick={() =>
|
|
34
|
+
telemetry.sendLogoClickedMessage([getBaseDataAttributes('logo', 'navbar')])
|
|
35
|
+
}
|
|
36
|
+
>
|
|
31
37
|
{image}
|
|
32
38
|
</Link>
|
|
33
39
|
) : (
|
|
@@ -67,6 +67,7 @@ const MenuContainerComponent = styled.div.attrs<{
|
|
|
67
67
|
animation-timing-function: ease;
|
|
68
68
|
position: relative;
|
|
69
69
|
overflow-y: auto;
|
|
70
|
+
scrollbar-gutter: stable;
|
|
70
71
|
flex-grow: ${({ $growContent }) => ($growContent ? 1 : 0)};
|
|
71
72
|
padding-top: var(--menu-container-padding-top);
|
|
72
73
|
display: ${({ $hidden }) => ($hidden ? 'none' : 'block')};
|
|
@@ -11,7 +11,11 @@ import { ChevronDownIcon } from '@redocly/theme/icons/ChevronDownIcon/ChevronDow
|
|
|
11
11
|
import { ChevronRightIcon } from '@redocly/theme/icons/ChevronRightIcon/ChevronRightIcon';
|
|
12
12
|
import { HttpTag } from '@redocly/theme/components/Tags/HttpTag';
|
|
13
13
|
import { MenuItemType } from '@redocly/theme/core/constants';
|
|
14
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
getBaseDataAttributes,
|
|
16
|
+
getMenuItemType,
|
|
17
|
+
getOperationColor,
|
|
18
|
+
} from '@redocly/theme/core/utils';
|
|
15
19
|
import { ArrowRightIcon } from '@redocly/theme/icons/ArrowRightIcon/ArrowRightIcon';
|
|
16
20
|
import { GenericIcon } from '@redocly/theme/icons/GenericIcon/GenericIcon';
|
|
17
21
|
import { Tag, ContentWrapper } from '@redocly/theme/components/Tag/Tag';
|
|
@@ -39,7 +43,7 @@ export function MenuItem(props: React.PropsWithChildren<MenuItemProps>): JSX.Ele
|
|
|
39
43
|
const handleOnClick = () => {
|
|
40
44
|
telemetry.sendSidebarItemClickedMessage([
|
|
41
45
|
{
|
|
42
|
-
|
|
46
|
+
...getBaseDataAttributes('sidebarItem', 'sidebar'),
|
|
43
47
|
label: item.label,
|
|
44
48
|
type: item.type === 'link' || item.type === 'group' ? item.type : undefined,
|
|
45
49
|
},
|
|
@@ -107,7 +111,13 @@ export function MenuItem(props: React.PropsWithChildren<MenuItemProps>): JSX.Ele
|
|
|
107
111
|
{name}
|
|
108
112
|
</SidebarTag>
|
|
109
113
|
))}
|
|
110
|
-
<
|
|
114
|
+
<MenuItemLabelText
|
|
115
|
+
$active={item.active}
|
|
116
|
+
$isSeparator={isSeparator}
|
|
117
|
+
data-text={translate(item.labelTranslationKey, item.label)}
|
|
118
|
+
>
|
|
119
|
+
{translate(item.labelTranslationKey, item.label)}
|
|
120
|
+
</MenuItemLabelText>
|
|
111
121
|
{item.badges
|
|
112
122
|
?.filter(({ position }) => position !== 'before')
|
|
113
123
|
.map(({ name, color, icon }) => (
|
|
@@ -308,7 +318,6 @@ const MenuItemLabelWrapper = styled.li<{
|
|
|
308
318
|
css`
|
|
309
319
|
color: ${$deprecated ? 'var(--menu-content-color-disabled)' : 'var(--menu-item-color-active)'};
|
|
310
320
|
background-color: var(--menu-item-bg-color-active);
|
|
311
|
-
font-weight: var(--menu-item-font-weight-active);
|
|
312
321
|
|
|
313
322
|
${ChevronDownIcon} path {
|
|
314
323
|
fill: var(--menu-item-color-active);
|
|
@@ -386,6 +395,28 @@ const MenuItemLabel = styled.span`
|
|
|
386
395
|
}
|
|
387
396
|
`;
|
|
388
397
|
|
|
398
|
+
const MenuItemLabelText = styled.span<{ $active?: boolean; $isSeparator?: boolean }>`
|
|
399
|
+
display: inline-block;
|
|
400
|
+
max-width: 100%;
|
|
401
|
+
font-weight: var(--menu-item-font-weight);
|
|
402
|
+
|
|
403
|
+
&::before {
|
|
404
|
+
content: attr(data-text);
|
|
405
|
+
display: block;
|
|
406
|
+
height: 0;
|
|
407
|
+
overflow: hidden;
|
|
408
|
+
visibility: hidden;
|
|
409
|
+
font-weight: ${({ $isSeparator }) =>
|
|
410
|
+
$isSeparator ? 'var(--menu-item-font-weight)' : 'var(--menu-item-font-weight-active)'};
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
${({ $active }) =>
|
|
414
|
+
$active &&
|
|
415
|
+
css`
|
|
416
|
+
font-weight: var(--menu-item-font-weight-active);
|
|
417
|
+
`}
|
|
418
|
+
`;
|
|
419
|
+
|
|
389
420
|
const SidebarTag = styled(Tag)<{ $bgColor?: string; icon?: React.ReactNode }>`
|
|
390
421
|
${({ $bgColor }) => $bgColor && `background-color: ${$bgColor};`} /* for backward compatibility */
|
|
391
422
|
margin-left: 0;
|
|
@@ -4,7 +4,7 @@ import styled from 'styled-components';
|
|
|
4
4
|
import type { JSX } from 'react';
|
|
5
5
|
import type { ResolvedConfigLinks } from '@redocly/config';
|
|
6
6
|
|
|
7
|
-
import { breakpoints } from '@redocly/theme/core/utils';
|
|
7
|
+
import { breakpoints, getBaseDataAttributes } from '@redocly/theme/core/utils';
|
|
8
8
|
import { useThemeHooks, useThemeConfig, useMobileMenu } from '@redocly/theme/core/hooks';
|
|
9
9
|
import { NavbarLogo } from '@redocly/theme/components/Navbar/NavbarLogo';
|
|
10
10
|
import { NavbarMenu } from '@redocly/theme/components/Navbar/NavbarMenu';
|
|
@@ -60,11 +60,15 @@ export function Navbar({ className }: NavbarProps): JSX.Element | null {
|
|
|
60
60
|
isOpen
|
|
61
61
|
? () => {
|
|
62
62
|
closeMobileMenu();
|
|
63
|
-
telemetry.
|
|
63
|
+
telemetry.sendMobileMenuClosedMessage([
|
|
64
|
+
getBaseDataAttributes('mobileMenuClose', 'button'),
|
|
65
|
+
]);
|
|
64
66
|
}
|
|
65
67
|
: () => {
|
|
66
68
|
openMobileMenu();
|
|
67
|
-
telemetry.
|
|
69
|
+
telemetry.sendMobileMenuOpenedMessage([
|
|
70
|
+
getBaseDataAttributes('mobileMenuOpen', 'button'),
|
|
71
|
+
]);
|
|
68
72
|
}
|
|
69
73
|
}
|
|
70
74
|
icon={isOpen ? <CloseIcon /> : <MenuIcon />}
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
getPathnameForLocale,
|
|
13
13
|
withPathPrefix,
|
|
14
14
|
removeTrailingSlash,
|
|
15
|
+
getBaseDataAttributes,
|
|
15
16
|
} from '@redocly/theme/core/utils';
|
|
16
17
|
import { useThemeHooks } from '@redocly/theme/core/hooks';
|
|
17
18
|
import { LaunchIcon } from '@redocly/theme/icons/LaunchIcon/LaunchIcon';
|
|
@@ -48,7 +49,12 @@ export function NavbarItem({ navItem, className }: NavbarItemProps): JSX.Element
|
|
|
48
49
|
$active={isActive}
|
|
49
50
|
className={className}
|
|
50
51
|
onClick={() =>
|
|
51
|
-
telemetry.sendNavbarMenuItemClickedMessage([
|
|
52
|
+
telemetry.sendNavbarMenuItemClickedMessage([
|
|
53
|
+
{
|
|
54
|
+
...getBaseDataAttributes('navbarItem', 'navbar'),
|
|
55
|
+
type: item.type,
|
|
56
|
+
},
|
|
57
|
+
])
|
|
52
58
|
}
|
|
53
59
|
external={item.external}
|
|
54
60
|
target={item.target}
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
type ContentSegment,
|
|
11
11
|
} from '@redocly/theme/core/types';
|
|
12
12
|
import { TOOL_CALL_DISPLAY_TEXT } from '@redocly/theme/core/constants';
|
|
13
|
+
import { ToolCallName } from '@redocly/theme/core/types';
|
|
13
14
|
import { Link } from '@redocly/theme/components/Link/Link';
|
|
14
15
|
import { Tag } from '@redocly/theme/components/Tag/Tag';
|
|
15
16
|
import { AiSearchConversationRole } from '@redocly/theme/core/constants';
|
|
@@ -26,14 +27,33 @@ function MarkdownSegment({ text }: { text: string }): JSX.Element {
|
|
|
26
27
|
const markdown = useMarkdownText(text);
|
|
27
28
|
return <ResponseText as="div" children={markdown} data-testid="response-text" />;
|
|
28
29
|
}
|
|
29
|
-
|
|
30
|
+
// The codemode `execute` tool passes a human-readable `description` of what its code
|
|
31
|
+
// does; show that instead of a generic "Executing execute..." label.
|
|
32
|
+
function getExecuteDescription(args: unknown): string | undefined {
|
|
33
|
+
if (args && typeof args === 'object' && 'description' in args) {
|
|
34
|
+
const { description } = args as { description?: unknown };
|
|
35
|
+
if (typeof description === 'string' && description.trim().length > 0) {
|
|
36
|
+
return description.trim();
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function getToolCallDisplayText(toolCall: ToolCall): {
|
|
30
43
|
inProgressText: string;
|
|
31
44
|
completedText: string;
|
|
32
45
|
} {
|
|
46
|
+
if (toolCall.name === ToolCallName.Execute) {
|
|
47
|
+
const description = getExecuteDescription(toolCall.args);
|
|
48
|
+
if (description) {
|
|
49
|
+
return { inProgressText: description, completedText: description };
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
33
53
|
return (
|
|
34
|
-
TOOL_CALL_DISPLAY_TEXT[
|
|
35
|
-
inProgressText: `Executing ${
|
|
36
|
-
completedText: `${
|
|
54
|
+
TOOL_CALL_DISPLAY_TEXT[toolCall.name] ?? {
|
|
55
|
+
inProgressText: `Executing ${toolCall.name}...`,
|
|
56
|
+
completedText: `${toolCall.name} executed`,
|
|
37
57
|
}
|
|
38
58
|
);
|
|
39
59
|
}
|
|
@@ -135,7 +155,7 @@ function SearchAiMessageComponent({
|
|
|
135
155
|
const toolCallCompleted = Boolean(segment.toolCall.result);
|
|
136
156
|
|
|
137
157
|
const { inProgressText, completedText } = getToolCallDisplayText(
|
|
138
|
-
segment.toolCall
|
|
158
|
+
segment.toolCall,
|
|
139
159
|
);
|
|
140
160
|
|
|
141
161
|
const toolCallDisplayText = toolCallCompleted ? completedText : inProgressText;
|