@redocly/theme 0.25.1 → 0.25.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 (74) hide show
  1. package/lib/components/Catalog/Catalog.js +1 -4
  2. package/lib/components/CopyButton/CopyButton.js +2 -7
  3. package/lib/components/EditPageButton/EditPageButton.js +1 -4
  4. package/lib/components/Feedback/Comment.js +4 -10
  5. package/lib/components/Feedback/Mood.js +6 -13
  6. package/lib/components/Feedback/Rating.js +2 -6
  7. package/lib/components/Feedback/Reasons.js +4 -9
  8. package/lib/components/Feedback/Sentiment.js +4 -10
  9. package/lib/components/Feedback/Thumbs.js +2 -8
  10. package/lib/components/Feedback/useReportDialog.js +3 -8
  11. package/lib/components/Filter/Filter.js +1 -5
  12. package/lib/components/Filter/FilterContent.js +2 -6
  13. package/lib/components/Filter/FilterPopover.js +2 -6
  14. package/lib/components/Footer/FooterCopyright.js +2 -5
  15. package/lib/components/LastUpdated/LastUpdated.js +1 -1
  16. package/lib/components/Markdown/styledVariables.js +54 -0
  17. package/lib/components/Menu/hooks/use-mobile-menu-items.js +1 -4
  18. package/lib/components/Menu/hooks/use-mobile-menu-levels.js +2 -6
  19. package/lib/components/Menu/utils.d.ts +2 -1
  20. package/lib/components/Profile/LoginLink.js +2 -5
  21. package/lib/components/Profile/MobileUserProfile.js +1 -4
  22. package/lib/components/Profile/UserProfile.js +3 -7
  23. package/lib/components/Search/CancelSearch.js +1 -4
  24. package/lib/components/Search/RecentSearches.js +1 -4
  25. package/lib/components/Search/SearchDialog.js +4 -10
  26. package/lib/components/Search/SearchTrigger.js +1 -4
  27. package/lib/components/Search/SuggestedPages.js +1 -4
  28. package/lib/components/Sidebar/DrilldownMenu.js +2 -5
  29. package/lib/components/Sidebar/VersionPicker.js +2 -6
  30. package/lib/components/TableOfContent/TableOfContent.js +1 -4
  31. package/lib/components/Tabs/Tab.js +30 -6
  32. package/lib/components/Tabs/Tabs.js +22 -8
  33. package/lib/layouts/Forbidden.js +2 -6
  34. package/lib/layouts/NotFound.js +2 -6
  35. package/lib/layouts/OIDCForbidden.js +1 -4
  36. package/lib/mocks/hooks/index.d.ts +3 -2
  37. package/lib/mocks/hooks/index.js +3 -4
  38. package/package.json +2 -2
  39. package/src/components/Catalog/Catalog.tsx +1 -4
  40. package/src/components/CopyButton/CopyButton.tsx +3 -8
  41. package/src/components/EditPageButton/EditPageButton.tsx +2 -5
  42. package/src/components/Feedback/Comment.tsx +14 -14
  43. package/src/components/Feedback/Mood.tsx +14 -15
  44. package/src/components/Feedback/Rating.tsx +4 -8
  45. package/src/components/Feedback/Reasons.tsx +6 -11
  46. package/src/components/Feedback/Sentiment.tsx +6 -12
  47. package/src/components/Feedback/Thumbs.tsx +2 -9
  48. package/src/components/Feedback/useReportDialog.ts +3 -8
  49. package/src/components/Filter/Filter.tsx +3 -5
  50. package/src/components/Filter/FilterContent.tsx +2 -6
  51. package/src/components/Filter/FilterPopover.tsx +2 -6
  52. package/src/components/Footer/FooterCopyright.tsx +2 -5
  53. package/src/components/LastUpdated/LastUpdated.tsx +1 -1
  54. package/src/components/Markdown/styledVariables.ts +54 -0
  55. package/src/components/Menu/hooks/use-mobile-menu-items.ts +1 -5
  56. package/src/components/Menu/hooks/use-mobile-menu-levels.ts +2 -7
  57. package/src/components/Menu/utils.ts +2 -1
  58. package/src/components/Profile/LoginLink.tsx +2 -5
  59. package/src/components/Profile/MobileUserProfile.tsx +1 -4
  60. package/src/components/Profile/UserProfile.tsx +5 -8
  61. package/src/components/Search/CancelSearch.tsx +2 -5
  62. package/src/components/Search/RecentSearches.tsx +2 -5
  63. package/src/components/Search/SearchDialog.tsx +8 -15
  64. package/src/components/Search/SearchTrigger.tsx +3 -5
  65. package/src/components/Search/SuggestedPages.tsx +2 -6
  66. package/src/components/Sidebar/DrilldownMenu.tsx +2 -5
  67. package/src/components/Sidebar/VersionPicker.tsx +3 -7
  68. package/src/components/TableOfContent/TableOfContent.tsx +2 -5
  69. package/src/components/Tabs/Tab.tsx +30 -6
  70. package/src/components/Tabs/Tabs.tsx +22 -8
  71. package/src/layouts/Forbidden.tsx +4 -13
  72. package/src/layouts/NotFound.tsx +4 -13
  73. package/src/layouts/OIDCForbidden.tsx +2 -6
  74. package/src/mocks/hooks/index.ts +7 -6
@@ -9,11 +9,6 @@ export const Reasons = ({ settings, onSubmit, className }: ReasonsProps): JSX.El
9
9
  const { label, multi, buttonText, items = [] } = settings;
10
10
  const [checkedState, setCheckedState] = React.useState(new Array(items.length).fill(false));
11
11
  const { translate } = useTranslate();
12
- const translationKeys = {
13
- label: 'theme.feedback.settings.reasons.label',
14
- items: 'theme.feedback.settings.reasons.items',
15
- send: 'theme.feedback.settings.reasons.send',
16
- };
17
12
 
18
13
  if (!items.length) {
19
14
  return <></>;
@@ -36,12 +31,12 @@ export const Reasons = ({ settings, onSubmit, className }: ReasonsProps): JSX.El
36
31
  return (
37
32
  <Wrapper
38
33
  data-component-name="Feedback/Reasons"
39
- data-translation-key={translationKeys.label}
34
+ data-translation-key="theme.feedback.settings.reasons.label"
40
35
  className={className}
41
36
  >
42
37
  <Label>
43
38
  {translate(
44
- translationKeys.label,
39
+ 'theme.feedback.settings.reasons.label',
45
40
  label || 'Which statement describes your thoughts about this page?',
46
41
  )}
47
42
  </Label>
@@ -55,16 +50,16 @@ export const Reasons = ({ settings, onSubmit, className }: ReasonsProps): JSX.El
55
50
  onChange={() => handleOptionChange(idx)}
56
51
  />
57
52
  <label
58
- data-translation-key={`${translationKeys.items}.${idx + 1}`}
53
+ data-translation-key={`theme.feedback.settings.reasons.items.${idx + 1}`}
59
54
  id={reason}
60
55
  onClick={() => handleOptionChange(idx)}
61
56
  >
62
- {translate(`${translationKeys.items}.${idx + 1}`, reason)}
57
+ {translate(`theme.feedback.settings.reasons.items.${idx + 1}`, reason)}
63
58
  </label>
64
59
  </OptionWrapper>
65
60
  ))}
66
- <SendButton data-translation-key={translationKeys.send} onClick={submitForm}>
67
- {translate(translationKeys.send, buttonText || 'Send')}
61
+ <SendButton data-translation-key="theme.feedback.settings.reasons.send" onClick={submitForm}>
62
+ {translate('theme.feedback.settings.reasons.send', buttonText || 'Send')}
68
63
  </SendButton>
69
64
  </Wrapper>
70
65
  );
@@ -13,12 +13,6 @@ export const Sentiment = ({ settings, onSubmit, className }: SentimentProps): JS
13
13
  const [comment, setComment] = React.useState('');
14
14
  const [reasons, setReasons] = React.useState([] as ReasonsProps['settings']['items']);
15
15
  const { translate } = useTranslate();
16
- const translationKeys = {
17
- submitText: 'theme.feedback.settings.submitText',
18
- label: 'theme.feedback.settings.label',
19
- likeLabel: 'theme.feedback.settings.comment.likeLabel',
20
- dislikeLabel: 'theme.feedback.settings.comment.dislikeLabel',
21
- };
22
16
 
23
17
  if (score && reasonsSettings?.enable && !reasons.length) {
24
18
  const { label: reasonsLabel, items, multi } = reasonsSettings;
@@ -35,11 +29,11 @@ export const Sentiment = ({ settings, onSubmit, className }: SentimentProps): JS
35
29
  const commentLabel =
36
30
  score === 1
37
31
  ? translate(
38
- translationKeys.likeLabel,
32
+ 'theme.feedback.settings.comment.likeLabel',
39
33
  commentSettings.likeLabel || 'What was most helpful?',
40
34
  )
41
35
  : translate(
42
- translationKeys.dislikeLabel,
36
+ 'theme.feedback.settings.comment.dislikeLabel',
43
37
  commentSettings.dislikeLabel || 'What can we improve?',
44
38
  );
45
39
  return (
@@ -58,9 +52,9 @@ export const Sentiment = ({ settings, onSubmit, className }: SentimentProps): JS
58
52
  }
59
53
  return (
60
54
  <Wrapper>
61
- <Label data-translation-key={translationKeys.submitText}>
55
+ <Label data-translation-key="theme.feedback.settings.submitText">
62
56
  {translate(
63
- translationKeys.submitText,
57
+ 'theme.feedback.settings.submitText',
64
58
  submitText || 'Thank you for helping improve our documentation!',
65
59
  )}
66
60
  </Label>
@@ -70,8 +64,8 @@ export const Sentiment = ({ settings, onSubmit, className }: SentimentProps): JS
70
64
 
71
65
  return (
72
66
  <Wrapper data-component-name="Feedback/Sentiment" className={className}>
73
- <Label data-translation-key={translationKeys.label}>
74
- {translate(translationKeys.label, label || 'Was this page helpful?')}
67
+ <Label data-translation-key="theme.feedback.settings.label">
68
+ {translate('theme.feedback.settings.label', label || 'Was this page helpful?')}
75
69
  </Label>
76
70
  <Vote
77
71
  onClick={() => {
@@ -5,10 +5,6 @@ import { useTranslate } from '@portal/hooks';
5
5
 
6
6
  export const ThumbUp = ({ text }: { text?: string }) => {
7
7
  const { translate } = useTranslate();
8
- const translationKeys = {
9
- thumbUp: 'theme.feedback.sentiment.thumbUp',
10
- };
11
-
12
8
  return (
13
9
  <Wrapper style={{ alignItems: 'normal' }}>
14
10
  <Icon>
@@ -50,16 +46,13 @@ export const ThumbUp = ({ text }: { text?: string }) => {
50
46
  </g>
51
47
  </svg>
52
48
  </Icon>
53
- <span>{translate(translationKeys.thumbUp, text || 'Yes')}</span>
49
+ <span>{translate('theme.feedback.sentiment.thumbUp', text || 'Yes')}</span>
54
50
  </Wrapper>
55
51
  );
56
52
  };
57
53
 
58
54
  export const ThumbDown = ({ text }: { text?: string }) => {
59
55
  const { translate } = useTranslate();
60
- const translationKeys = {
61
- thumbDown: 'theme.feedback.sentiment.thumbDown',
62
- };
63
56
  return (
64
57
  <Wrapper style={{ alignItems: 'end' }}>
65
58
  <Icon>
@@ -100,7 +93,7 @@ export const ThumbDown = ({ text }: { text?: string }) => {
100
93
  </g>
101
94
  </svg>
102
95
  </Icon>
103
- <span>{translate(translationKeys.thumbDown, text || 'No')}</span>
96
+ <span>{translate('theme.feedback.sentiment.thumbDown', text || 'No')}</span>
104
97
  </Wrapper>
105
98
  );
106
99
  };
@@ -22,11 +22,6 @@ export function useReportDialog(): Record<string, ReportComponentsProps> {
22
22
  const isReportButtonShown = report?.hide === false; // TODO: report temporary disabled by default
23
23
  const { translate } = useTranslate();
24
24
  const { submitFeedback } = useSubmitFeedback();
25
- const translationKeys = {
26
- buttonText: 'theme.codeSnippet.report.buttonText',
27
- tooltipText: 'theme.codeSnippet.report.tooltipText',
28
- label: 'theme.codeSnippet.report.label',
29
- };
30
25
 
31
26
  const showReportDialog = () => {
32
27
  setIsReportDialogShown(true);
@@ -36,13 +31,13 @@ export function useReportDialog(): Record<string, ReportComponentsProps> {
36
31
  };
37
32
  const reportButtonProps: ReportButtonProps = {
38
33
  onClick: showReportDialog,
39
- buttonText: translate(translationKeys.buttonText, 'Report'),
40
- tooltip: translate(translationKeys.tooltipText, 'Report a problem'),
34
+ buttonText: translate('theme.codeSnippet.report.buttonText', 'Report'),
35
+ tooltip: translate('theme.codeSnippet.report.tooltipText', 'Report a problem'),
41
36
  visible: isReportButtonShown,
42
37
  };
43
38
  const reportDialogProps: Partial<ReportDialogProps> = {
44
39
  settings: {
45
- label: translate(translationKeys.label, 'What is wrong with this code?'),
40
+ label: translate('theme.codeSnippet.report.label', 'What is wrong with this code?'),
46
41
  },
47
42
  onSubmit: hideReportDialog,
48
43
  onCancel: hideReportDialog,
@@ -16,10 +16,6 @@ export function Filter({
16
16
  filterValuesCasing?: NonNullable<ThemeConfig['catalog']>[string]['filterValuesCasing'];
17
17
  }) {
18
18
  const { translate } = useTranslate();
19
- const translationKeys = {
20
- selectAll: 'theme.catalog.filters.select.all',
21
- clear: 'theme.catalog.filters.clear',
22
- };
23
19
 
24
20
  if (!filter.parentUsed) return null;
25
21
 
@@ -34,7 +30,9 @@ export function Filter({
34
30
  value: '',
35
31
  element: (
36
32
  <FilterOption key="all" onClick={() => filter.selectOption('')}>
37
- <FilterOptionLabel>{translate(translationKeys.selectAll, 'All')}</FilterOptionLabel>
33
+ <FilterOptionLabel>
34
+ {translate('theme.catalog.filters.select.all', 'All')}
35
+ </FilterOptionLabel>
38
36
  <FilterOptionCount>{defaultOptionCount}</FilterOptionCount>
39
37
  </FilterOption>
40
38
  ),
@@ -26,10 +26,6 @@ export function FilterContent({
26
26
  filterValuesCasing,
27
27
  }: FilterContentProps) {
28
28
  const { translate } = useTranslate();
29
- const translationKeys = {
30
- placeholder: 'theme.catalog.filters.placeholder',
31
- clearAll: 'theme.catalog.filters.clearAll',
32
- };
33
29
 
34
30
  const hasActiveFilters = filters.some((filter) => {
35
31
  if (filterTerm) return true;
@@ -49,7 +45,7 @@ export function FilterContent({
49
45
  <FilterContentWrapper isMobile={isMobile}>
50
46
  <FilterControls>
51
47
  <StyledInput
52
- placeholder={translate(translationKeys.placeholder, 'Type to filter...')}
48
+ placeholder={translate('theme.catalog.filters.placeholder', 'Type to filter...')}
53
49
  value={filterTerm}
54
50
  onChange={(e) => setFilterTerm(e.target.value)}
55
51
  />
@@ -66,7 +62,7 @@ export function FilterContent({
66
62
  {hasActiveFilters && (
67
63
  <ActionsContainer>
68
64
  <ClearAllButton size="default" variant="outlined" onClick={handleClearAll}>
69
- {translate(translationKeys.placeholder, 'Clear all filters')}
65
+ {translate('theme.catalog.filters.clearAll', 'Clear all filters')}
70
66
  </ClearAllButton>
71
67
  </ActionsContainer>
72
68
  )}
@@ -34,10 +34,6 @@ export function FilterPopover({
34
34
  })
35
35
  .filter(Boolean) as ResolvedFilter[];
36
36
 
37
- const translationKeys = {
38
- placeholder: 'theme.catalog.filters.placeholder',
39
- done: 'theme.catalog.filters.done',
40
- };
41
37
  const { translate } = useTranslate();
42
38
 
43
39
  return (
@@ -45,7 +41,7 @@ export function FilterPopover({
45
41
  <FilterPopoverHeader>
46
42
  <FilterPopoverHeaderLabel>Add Filter</FilterPopoverHeaderLabel>
47
43
  <FilterPopoverHeaderButton onClick={() => setIsAddingFilter(false)}>
48
- {translate(translationKeys.placeholder, 'Done')}
44
+ {translate('theme.catalog.filters.done', 'Done')}
49
45
  </FilterPopoverHeaderButton>
50
46
  </FilterPopoverHeader>
51
47
  <FilterContent
@@ -57,7 +53,7 @@ export function FilterPopover({
57
53
  />
58
54
  <FilterControls>
59
55
  <StyledInput
60
- placeholder={translate(translationKeys.placeholder, 'Type to filter...')}
56
+ placeholder={translate('theme.catalog.filters.placeholder', 'Type to filter...')}
61
57
  value={filterTerm}
62
58
  onChange={(e) => setFilterTerm(e.target.value)}
63
59
  />
@@ -16,16 +16,13 @@ export function FooterCopyright({
16
16
  const { translate } = useTranslate();
17
17
  const { changeLanguage } = useI18n();
18
18
 
19
- const translationKeys = {
20
- copyrightText: 'theme.footer.copyrightText',
21
- };
22
19
  return copyrightText ? (
23
20
  <Wrapper
24
21
  className={className}
25
22
  data-component-name="Footer/FooterCopyright"
26
- data-translation-key={translationKeys.copyrightText}
23
+ data-translation-key="theme.footer.copyrightText"
27
24
  >
28
- <Label>{translate(translationKeys.copyrightText, copyrightText)}</Label>
25
+ <Label>{translate('theme.footer.copyrightText', copyrightText)}</Label>
29
26
  <LanguagePicker onChangeLanguage={changeLanguage} placement="top" alignment="end" />
30
27
  </Wrapper>
31
28
  ) : null;
@@ -40,7 +40,7 @@ export function LastUpdated(props: LastUpdatedProps): JSX.Element | null {
40
40
 
41
41
  const text =
42
42
  format === 'timeago'
43
- ? translate(translationKey, 'Last updated ')
43
+ ? translate(translationKey, 'Last updated') + ' '
44
44
  : translate(translationKey, 'Last updated on');
45
45
 
46
46
  return (
@@ -210,10 +210,64 @@ export const markdown = css`
210
210
  /**
211
211
  * @tokens Markdown Tabs
212
212
  */
213
+
214
+ --md-tabs-container-text-color: inherit; // @presenter Color
215
+ --md-tabs-container-font-size: var(--font-size-base); // @presenter FontSize
216
+ --md-tabs-container-font-family: var(--font-size-base); // @presenter FontFamily
217
+ --md-tabs-container-font-style: normal; // @presenter FontStyle
218
+ --md-tabs-container-font-weight: var(--font-weight-regular); // @presenter FontWeight
219
+ --md-tabs-container-background-color: inherit; // @presenter Color
220
+ --md-tabs-container-margin: 10px 0; // @presenter Spacing
221
+ --md-tabs-container-padding: 0; // @presenter Spacing
222
+ --md-tabs-container-border: none; // @presenter Border
223
+
224
+ --md-tabs-border: solid var(--border-primary); // @presenter Color
225
+ --md-tabs-border-width: 0 0 1px 0; // @presenter Spacing
226
+ --md-tabs-padding: 0; // @presenter Spacing
227
+
228
+ --md-tabs-content-text-color: inherit; // @presenter Color
229
+ --md-tabs-content-font-size: var(--font-size-base); // @presenter FontSize
230
+ --md-tabs-content-font-family: var(--font-size-base); // @presenter FontFamily
231
+ --md-tabs-content-font-style: normal; // @presenter FontStyle
232
+ --md-tabs-content-font-weight: var(--font-weight-regular); // @presenter FontWeight
233
+ --md-tabs-content-background-color: inherit; // @presenter Color
234
+ --md-tabs-content-margin: 0; // @presenter Spacing
235
+ --md-tabs-content-padding: var(--spacing-base) 0; // @presenter Spacing
236
+ --md-tabs-content-border: none; // @presenter Border
213
237
 
214
238
  --md-tabs-tab-text-color: var(--text-secondary); // @presenter Color
239
+ --md-tabs-tab-font-size: var(--font-size-base); // @presenter FontSize
240
+ --md-tabs-tab-font-family: var(--font-size-base); // @presenter FontFamily
241
+ --md-tabs-tab-font-style: normal; // @presenter FontStyle
242
+ --md-tabs-tab-font-weight: var(--font-weight-regular); // @presenter FontWeight
243
+ --md-tabs-tab-background-color: none; // @presenter Color
244
+ --md-tabs-tab-margin: 0 0 -1px 0; // @presenter Spacing
245
+ --md-tabs-tab-padding: var(--spacing-sm) var(--spacing-base); // @presenter Spacing
246
+ --md-tabs-tab-border: none; // @presenter Color
247
+ --md-tabs-tab-border-width: 0; // @presenter Spacing
248
+ --md-tabs-tab-border-radius: 0; // @presenter BorderRadius
249
+
250
+ --md-tabs-active-tab-text-color: var(--text-primary); // @presenter Color
251
+ --md-tabs-active-tab-font-size: var(--md-tabs-tab-font-size); // @presenter FontSize
252
+ --md-tabs-active-tab-font-family: var(--md-tabs-tab-font-family); // @presenter FontFamily
253
+ --md-tabs-active-tab-font-style: normal; // @presenter FontStyle
254
+ --md-tabs-active-tab-font-weight: var(--md-tabs-tab-font-weight); // @presenter FontWeight
255
+ --md-tabs-active-tab-background-color: var(--background-color); // @presenter Color
256
+ --md-tabs-active-tab-padding: var(--md-tabs-tab-padding); // @presenter Spacing
215
257
  --md-tabs-active-tab-border-color: var(--border-primary); // @presenter Color
258
+ --md-tabs-active-tab-border-width: 0 0 1px 0; // @presenter Spacing
259
+ --md-tabs-active-tab-border-radius: var(--md-tabs-tab-border-radius); // @presenter BorderRadius
260
+
261
+ --md-tabs-hover-tab-text-color: var(--md-tabs-tab-text-color); // @presenter Color
262
+ --md-tabs-hover-tab-font-size: var(--md-tabs-tab-font-size); // @presenter FontSize
263
+ --md-tabs-hover-tab-font-family: var(--md-tabs-tab-font-family); // @presenter FontFamily
264
+ --md-tabs-hover-tab-font-style: normal; // @presenter FontStyle
265
+ --md-tabs-hover-tab-font-weight: var(--md-tabs-tab-font-weight); // @presenter FontWeight
266
+ --md-tabs-hover-tab-background-color: var(--md-tabs-tab-background-color); // @presenter Color
267
+ --md-tabs-hover-tab-padding: var(--md-tabs-tab-padding); // @presenter Spacing
216
268
  --md-tabs-hover-tab-border-color: var(--border-secondary); // @presenter Color
269
+ --md-tabs-hover-tab-border-width: 0 0 1px 0; // @presenter Spacing
270
+ --md-tabs-hover-tab-border-radius: var(--md-tabs-tab-border-radius); // @presenter BorderRadius
217
271
 
218
272
  // @tokens End
219
273
  `;
@@ -13,10 +13,6 @@ const MENU_SEPARATOR: ResolvedNavItem = {
13
13
  separatorLine: true,
14
14
  };
15
15
 
16
- const TRANSLATION_KEYS = {
17
- products: 'theme.mobileMenu.products',
18
- };
19
-
20
16
  export const useMobileMenuItems = (menuType: MenuType) => {
21
17
  const { versions = [] } = usePageVersions() || {};
22
18
  const { defaultLocale, currentLocale, locales } = useI18nConfig();
@@ -71,7 +67,7 @@ export const useMobileMenuItems = (menuType: MenuType) => {
71
67
  if (productMenuItems.length) {
72
68
  menuItems.push({
73
69
  type: 'separator',
74
- label: translate(TRANSLATION_KEYS.products, 'Products'),
70
+ label: translate('theme.mobileMenu.products', 'Products'),
75
71
  });
76
72
 
77
73
  menuItems.push(...productMenuItems);
@@ -7,11 +7,6 @@ import { MenuType } from '@theme/components/Menu/constants';
7
7
  import { useThemeConfig } from '@theme/hooks';
8
8
  import type { ResolvedNavItem } from '@theme/types/portal';
9
9
 
10
- const TRANSLATION_KEYS = {
11
- mainMenu: 'theme.mobileMenu.mainMenu',
12
- previous: 'theme.mobileMenu.previous',
13
- };
14
-
15
10
  export const useMobileMenuLevels = () => {
16
11
  const { versions = [] } = usePageVersions() || {};
17
12
  const activeVersion = versions.find((version) => version?.active);
@@ -29,7 +24,7 @@ export const useMobileMenuLevels = () => {
29
24
  const menuLevels = useMemo(() => {
30
25
  const menuLevels = [
31
26
  {
32
- label: translate(TRANSLATION_KEYS.mainMenu, 'Main Menu'),
27
+ label: translate('theme.mobileMenu.mainMenu', 'Main Menu'),
33
28
  type: MenuType.MAIN_MENU,
34
29
  },
35
30
  ];
@@ -43,7 +38,7 @@ export const useMobileMenuLevels = () => {
43
38
 
44
39
  if (sidebarItems.length || activeVersion) {
45
40
  menuLevels.push({
46
- label: translate(TRANSLATION_KEYS.previous, 'Previous'),
41
+ label: translate('theme.mobileMenu.previous', 'Previous'),
47
42
  type: MenuType.PAGE,
48
43
  });
49
44
  }
@@ -1,7 +1,8 @@
1
1
  import type { Location } from 'react-router-dom';
2
+ import type { TFunction } from '@redocly/portal-types';
2
3
 
3
4
  import type { ItemState } from '@theme/components/Sidebar/types';
4
- import type { Locale, ResolvedNavItem, TFunction, Version } from '@theme/types/portal';
5
+ import type { Locale, ResolvedNavItem, Version } from '@theme/types/portal';
5
6
  import { getPathnameForLocale } from '@portal/utils';
6
7
  import { withPathPrefix } from '@theme/utils/urls';
7
8
 
@@ -12,19 +12,16 @@ export interface LoginLinkProps {
12
12
  export function LoginLink({ href }: LoginLinkProps): JSX.Element {
13
13
  const { userProfile } = useThemeConfig();
14
14
  const { translate } = useTranslate();
15
- const translationKeys = {
16
- login: 'theme.profile.login',
17
- };
18
15
 
19
16
  return (
20
17
  <StyledLink
21
18
  href={href}
22
- data-translation-key={translationKeys.login}
19
+ data-translation-key="theme.profile.login"
23
20
  onClick={() => {
24
21
  telemetry.send('login_button_clicked', {});
25
22
  }}
26
23
  >
27
- {translate(translationKeys.login, userProfile?.loginLabel || 'Login')}
24
+ {translate('theme.profile.login', userProfile?.loginLabel || 'Login')}
28
25
  </StyledLink>
29
26
  );
30
27
  }
@@ -12,9 +12,6 @@ export function MobileUserProfile() {
12
12
  const { userProfile } = useThemeConfig();
13
13
  const { userData, handleLogout, loginUrl } = useProfileProps();
14
14
  const { translate } = useTranslate();
15
- const translationKeys = {
16
- login: 'theme.profile.login',
17
- };
18
15
 
19
16
  if (!userData?.isAuthenticated && !loginUrl) return null;
20
17
 
@@ -26,7 +23,7 @@ export function MobileUserProfile() {
26
23
  data-cy="login-btn"
27
24
  onClick={() => telemetry.send('login_button_clicked', {})}
28
25
  >
29
- {translate(translationKeys.login, userProfile?.loginLabel || 'Login')}
26
+ {translate('theme.profile.login', userProfile?.loginLabel || 'Login')}
30
27
  </LoginButton>
31
28
  ) : (
32
29
  <>
@@ -18,18 +18,15 @@ export function UserProfile({
18
18
  }: UserProfileProps): JSX.Element {
19
19
  const { userProfile } = useThemeConfig();
20
20
  const { translate } = useTranslate();
21
- const translationKeys = {
22
- myApps: 'theme.profile.myApps',
23
- logout: 'theme.profile.logout',
24
- };
21
+
25
22
  const [isOpened, setIsOpened] = useState<boolean>(false);
26
23
 
27
24
  const menuItems: JSX.Element[] = [<UserProfileData key={userData.name} userData={userData} />];
28
25
 
29
26
  if (hasDeveloperOnboarding) {
30
27
  menuItems.push(
31
- <Link to="/apps" data-translation-key={translationKeys.myApps}>
32
- {translate(translationKeys.myApps, 'My Apps')}
28
+ <Link to="/apps" data-translation-key="theme.profile.myApps">
29
+ {translate('theme.profile.myApps', 'My Apps')}
33
30
  </Link>,
34
31
  );
35
32
  }
@@ -55,11 +52,11 @@ export function UserProfile({
55
52
  handleLogout();
56
53
  telemetry.send('logout_menu_item_clicked', {});
57
54
  }}
58
- data-translation-key={translationKeys.logout}
55
+ data-translation-key="theme.profile.logout"
59
56
  role="link"
60
57
  >
61
58
  <LogoutIcon />
62
- {translate(translationKeys.logout, userProfile?.logoutLabel || 'Log out')}
59
+ {translate('theme.profile.logout', userProfile?.logoutLabel || 'Log out')}
63
60
  </Logout>,
64
61
  );
65
62
 
@@ -12,14 +12,11 @@ export function CancelSearch({
12
12
  className?: string;
13
13
  }): JSX.Element {
14
14
  const { translate } = useTranslate();
15
- const translationKeys = {
16
- cancel: 'theme.search.cancel',
17
- };
18
15
 
19
16
  return (
20
17
  <Wrapper data-component-name="Search/CancelSearch" onClick={onClick} className={className}>
21
- <Button data-translation-keys={translationKeys.cancel} fullWidth variant="outlined">
22
- {translate(translationKeys.cancel, 'Cancel')}
18
+ <Button data-translation-keys="theme.search.cancel" fullWidth variant="outlined">
19
+ {translate('theme.search.cancel', 'Cancel')}
23
20
  </Button>
24
21
  </Wrapper>
25
22
  );
@@ -15,9 +15,6 @@ export function RecentSearches({
15
15
  }) {
16
16
  const { items, removeSearchHistoryItem } = useRecentSearches();
17
17
  const { translate } = useTranslate();
18
- const translationKeys = {
19
- title: 'theme.search.recent',
20
- };
21
18
 
22
19
  if (!items || !items.length) return null;
23
20
 
@@ -34,8 +31,8 @@ export function RecentSearches({
34
31
 
35
32
  return (
36
33
  <Wrapper data-component-name="Search/RecentSearches" className={className}>
37
- <Title data-translation-key={translationKeys.title}>
38
- {translate(translationKeys.title, 'Recent searches')}
34
+ <Title data-translation-key="theme.search.recent">
35
+ {translate('theme.search.recent', 'Recent searches')}
39
36
  </Title>
40
37
  <RecentItems>
41
38
  {items.map((item) => (
@@ -39,13 +39,6 @@ export const SearchDialog = ({
39
39
  }
40
40
  };
41
41
 
42
- const translationKeys = {
43
- noResults: 'theme.search.noResults',
44
- navigate: 'theme.search.keys.navigate',
45
- select: 'theme.search.keys.select',
46
- exit: 'theme.search.keys.exit',
47
- };
48
-
49
42
  const mapItem = (item: SearchDocument) => {
50
43
  return (
51
44
  <SearchItem key={item.id} item={item} product={!product ? item.product?.name : undefined} />
@@ -74,8 +67,8 @@ export const SearchDialog = ({
74
67
  items.length ? (
75
68
  items.map(mapItem)
76
69
  ) : (
77
- <Message data-translation-key={translationKeys.noResults}>
78
- {translate(translationKeys.noResults, 'No results')}
70
+ <Message data-translation-key="theme.search.noResults">
71
+ {translate('theme.search.noResults', 'No results')}
79
72
  </Message>
80
73
  )
81
74
  ) : (
@@ -88,19 +81,19 @@ export const SearchDialog = ({
88
81
  <BottomContainer>
89
82
  <Shortcuts>
90
83
  <Shortcut
91
- data-translation-key={translationKeys.navigate}
84
+ data-translation-key="theme.search.keys.navigate"
92
85
  combination="Tab"
93
- text={translate(translationKeys.navigate, 'to navigate')}
86
+ text={translate('theme.search.keys.navigate', 'to navigate')}
94
87
  />
95
88
  <Shortcut
96
- data-translation-key={translationKeys.select}
89
+ data-translation-key="theme.search.keys.select"
97
90
  combination="↵"
98
- text={translate(translationKeys.select, 'to select')}
91
+ text={translate('theme.search.keys.select', 'to select')}
99
92
  />
100
93
  <Shortcut
101
- data-translation-key={translationKeys.exit}
94
+ data-translation-key="theme.search.keys.exit"
102
95
  combination="Esc"
103
- text={translate(translationKeys.exit, 'to exit')}
96
+ text={translate('theme.search.keys.exit', 'to exit')}
104
97
  />
105
98
  </Shortcuts>
106
99
  <CancelSearch onClick={onClose} />
@@ -15,16 +15,14 @@ export function SearchTrigger({
15
15
  }): JSX.Element {
16
16
  const themeSettings = useThemeConfig();
17
17
  const { translate } = useTranslate();
18
- const translationKeys = {
19
- label: 'theme.search.navbar.label',
20
- };
18
+
21
19
  const keyShortcuts = themeSettings?.search?.shortcuts ?? ['/'];
22
20
 
23
21
  return (
24
22
  <Wrapper data-component-name="Search/SearchTrigger" onClick={onClick} className={className}>
25
23
  <SearchIconSmall />
26
- <Label data-translation-key={translationKeys.label}>
27
- {translate(translationKeys.label, 'Search')}
24
+ <Label data-translation-key="theme.search.navbar.label">
25
+ {translate('theme.search.navbar.label', 'Search')}
28
26
  </Label>
29
27
  <ShortcutKey keyShortcuts={keyShortcuts} />
30
28
  </Wrapper>
@@ -9,16 +9,12 @@ import { useTranslate } from '@portal/hooks';
9
9
  export function SuggestedPages({ className }: { className?: string }) {
10
10
  const pages = useSuggestedPages();
11
11
  const { translate } = useTranslate();
12
- const translationKeys = {
13
- title: 'theme.search.suggested',
14
- };
15
-
16
12
  if (!pages.length) return null;
17
13
 
18
14
  return (
19
15
  <Wrapper data-component-name="Search/SuggestedPages" className={className}>
20
- <Title data-translation-key={translationKeys.title}>
21
- {translate(translationKeys.title, 'Suggested pages')}
16
+ <Title data-translation-key="theme.search.suggested">
17
+ {translate('theme.search.suggested', 'Suggested pages')}
22
18
  </Title>
23
19
  <SuggestedItems>
24
20
  {pages.map(
@@ -15,19 +15,16 @@ export function DrilldownMenu({
15
15
  className,
16
16
  }: React.PropsWithChildren<DrilldownMenuProps>): JSX.Element {
17
17
  const { translate } = useTranslate();
18
- const translationKeys = {
19
- backLabel: 'theme.sidebar.menu.backLabel',
20
- };
21
18
  const label =
22
19
  item.label === prevActiveItem?.label || !prevActiveItem?.label
23
- ? translate(translationKeys.backLabel, 'Back')
20
+ ? translate('theme.sidebar.menu.backLabel', 'Back')
24
21
  : prevActiveItem?.label;
25
22
 
26
23
  return (
27
24
  <MenuContainer data-component-name="Sidebar/DrilldownMenu" className={className}>
28
25
  <MenuContent>
29
26
  <MenuWrapper>
30
- <BackButton back={back} data-translation-key={translationKeys.backLabel}>
27
+ <BackButton back={back} data-translation-key="theme.sidebar.menu.backLabel">
31
28
  {label}
32
29
  </BackButton>
33
30
  <MenuLinkItem item={item}>