@redocly/theme 0.58.0 → 0.59.0-next.0

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 (33) hide show
  1. package/lib/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityApiDescriptionRelations.js +1 -1
  2. package/lib/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityTeamRelations.js +1 -1
  3. package/lib/components/Panel/variables.js +1 -0
  4. package/lib/components/Tag/Tag.d.ts +3 -2
  5. package/lib/components/Tag/Tag.js +21 -5
  6. package/lib/components/Tag/variables.dark.js +135 -0
  7. package/lib/components/Tag/variables.js +120 -58
  8. package/lib/core/hooks/use-tabs.d.ts +11 -6
  9. package/lib/core/hooks/use-tabs.js +117 -207
  10. package/lib/core/utils/index.d.ts +1 -0
  11. package/lib/core/utils/index.js +1 -0
  12. package/lib/core/utils/tabs.d.ts +1 -0
  13. package/lib/core/utils/tabs.js +8 -0
  14. package/lib/markdoc/components/Tabs/Tab.js +1 -1
  15. package/lib/markdoc/components/Tabs/TabList.d.ts +2 -14
  16. package/lib/markdoc/components/Tabs/TabList.js +63 -16
  17. package/lib/markdoc/components/Tabs/Tabs.d.ts +2 -2
  18. package/lib/markdoc/components/Tabs/Tabs.js +11 -87
  19. package/lib/markdoc/tags/tabs.js +5 -0
  20. package/package.json +3 -3
  21. package/src/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityApiDescriptionRelations.tsx +1 -1
  22. package/src/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityTeamRelations.tsx +1 -1
  23. package/src/components/Panel/variables.ts +1 -0
  24. package/src/components/Tag/Tag.tsx +33 -8
  25. package/src/components/Tag/variables.dark.ts +135 -0
  26. package/src/components/Tag/variables.ts +120 -58
  27. package/src/core/hooks/use-tabs.ts +160 -238
  28. package/src/core/utils/index.ts +1 -0
  29. package/src/core/utils/tabs.ts +4 -0
  30. package/src/markdoc/components/Tabs/Tab.tsx +1 -0
  31. package/src/markdoc/components/Tabs/TabList.tsx +84 -30
  32. package/src/markdoc/components/Tabs/Tabs.tsx +12 -125
  33. package/src/markdoc/tags/tabs.ts +5 -0
@@ -1,10 +1,11 @@
1
- import React, { useRef, useState, useEffect } from 'react';
2
- import styled, { css } from 'styled-components';
1
+ import React, { useState, useEffect } from 'react';
2
+ import styled from 'styled-components';
3
3
 
4
4
  import type { JSX } from 'react';
5
5
 
6
- import { useTabs } from '@redocly/theme/core/hooks';
6
+ import { useActiveTab } from '@redocly/theme/core/hooks';
7
7
  import { TabList } from '@redocly/theme/markdoc/components/Tabs/TabList';
8
+ import { getTabId } from '@redocly/theme/core/utils';
8
9
 
9
10
  export enum TabsSize {
10
11
  SMALL = 'small',
@@ -20,140 +21,38 @@ export type TabItemProps = {
20
21
  };
21
22
 
22
23
  type TabsProps = {
24
+ id?: string;
23
25
  children: React.ReactElement<TabItemProps>[];
24
26
  className?: string;
25
27
  size: TabsSize;
26
- forceReady?: boolean;
27
28
  initialTab?: string;
28
29
  };
29
30
 
30
31
  export function Tabs({
32
+ id,
31
33
  children,
32
34
  className,
33
35
  size,
34
- forceReady = false,
35
36
  initialTab: propInitialTab,
36
37
  }: TabsProps): JSX.Element {
37
38
  const [childrenArray, setChildrenArray] = useState<React.ReactElement<TabItemProps>[]>(
38
39
  React.Children.toArray(children) as React.ReactElement<TabItemProps>[],
39
40
  );
40
41
 
42
+ const initialTab = propInitialTab ?? childrenArray[0]?.props.label ?? '';
43
+ const { activeTab, setActiveTab } = useActiveTab({ tabsId: id, initialTab });
44
+
41
45
  useEffect(() => {
42
46
  setChildrenArray(React.Children.toArray(children) as React.ReactElement<TabItemProps>[]);
43
47
  }, [children]);
44
- const tabsContainerRef = useRef<HTMLUListElement>(null);
45
- const [isAnimating, setIsAnimating] = useState<boolean>(false);
46
- const defaultInitialTab = childrenArray[0]?.props.label ?? '';
47
- const initialTab = propInitialTab ?? defaultInitialTab;
48
- const {
49
- activeTab,
50
- setTabRef,
51
- onTabClick,
52
- handleKeyboard,
53
- getTabId,
54
- visibleTabs,
55
- overflowTabs,
56
- ready,
57
- allTabsHidden,
58
- } = useTabs({
59
- initialTab,
60
- totalTabs: childrenArray.length,
61
- containerRef: tabsContainerRef,
62
- });
63
-
64
- const [prevTab, setPrevTab] = React.useState(initialTab);
65
- const [highlightStyle, setHighlightStyle] = React.useState<{ left: number; width: number }>({
66
- left: 0,
67
- width: 0,
68
- });
69
-
70
- useEffect(() => {
71
- setPrevTab(activeTab);
72
- setIsAnimating(true);
73
-
74
- const activeIndex = childrenArray.findIndex((child) => child.props.label === activeTab);
75
- const container = tabsContainerRef.current;
76
-
77
- if (container) {
78
- container.querySelectorAll('[data-label]').forEach((el) => {
79
- el.classList.remove('active');
80
- });
81
-
82
- container.getBoundingClientRect();
83
-
84
- requestAnimationFrame(() => {
85
- if (activeIndex >= 0) {
86
- let activeTabElement: HTMLElement | null = null;
87
- let startPosition = { left: 0, width: 0 };
88
-
89
- if (visibleTabs.includes(activeIndex)) {
90
- activeTabElement = container.querySelector(
91
- `[data-label="${activeTab}"]`,
92
- ) as HTMLElement;
93
- } else if (overflowTabs.includes(activeIndex)) {
94
- const moreButton = container.querySelector('button') as HTMLElement;
95
- if (moreButton) {
96
- const moreButtonRect = moreButton.getBoundingClientRect();
97
- const containerRect = container.getBoundingClientRect();
98
- startPosition = {
99
- left: moreButtonRect.left - containerRect.left,
100
- width: moreButtonRect.width,
101
- };
102
- }
103
- }
104
-
105
- if (activeTabElement) {
106
- const { offsetLeft, offsetWidth } = activeTabElement;
107
-
108
- if (overflowTabs.includes(activeIndex)) {
109
- setHighlightStyle(startPosition);
110
- requestAnimationFrame(() => {
111
- setHighlightStyle({ left: offsetLeft, width: offsetWidth });
112
- });
113
- } else {
114
- setHighlightStyle({ left: offsetLeft, width: offsetWidth });
115
- }
116
-
117
- if (visibleTabs.includes(activeIndex)) {
118
- activeTabElement?.classList.add('active');
119
- }
120
-
121
- return () => {
122
- container.querySelectorAll('[data-label]').forEach((el) => {
123
- el.classList.remove('active');
124
- });
125
- };
126
- }
127
- }
128
- setHighlightStyle({ left: 0, width: 0 });
129
- setIsAnimating(false);
130
- });
131
- } else {
132
- setHighlightStyle({ left: 0, width: 0 });
133
- setIsAnimating(false);
134
- }
135
- }, [activeTab, prevTab, childrenArray, visibleTabs, overflowTabs]);
136
48
 
137
49
  return (
138
- <TabsContainer
139
- data-component-name="Markdoc/Tabs/Tabs"
140
- className={className}
141
- isReady={ready || forceReady}
142
- >
50
+ <TabsContainer data-component-name="Markdoc/Tabs/Tabs" className={className} key={id}>
143
51
  <TabList
144
52
  size={size}
145
53
  childrenArray={childrenArray}
146
- overflowTabs={overflowTabs}
147
- setTabRef={setTabRef}
148
- onTabClick={onTabClick}
149
- handleKeyboard={handleKeyboard}
150
- getTabId={getTabId}
151
54
  activeTab={activeTab}
152
- isAnimating={isAnimating}
153
- highlightStyle={highlightStyle}
154
- visibleTabs={visibleTabs}
155
- allTabsHidden={allTabsHidden}
156
- tabsContainerRef={tabsContainerRef}
55
+ onTabChange={setActiveTab}
157
56
  />
158
57
  {childrenArray.map((child, index) => {
159
58
  const { label } = child.props;
@@ -173,8 +72,7 @@ export function Tabs({
173
72
  </TabsContainer>
174
73
  );
175
74
  }
176
-
177
- const TabsContainer = styled.div<{ isReady: boolean }>`
75
+ const TabsContainer = styled.div`
178
76
  position: relative;
179
77
  color: var(--md-tabs-container-text-color);
180
78
  font-size: var(--md-tabs-container-font-size);
@@ -186,17 +84,6 @@ const TabsContainer = styled.div<{ isReady: boolean }>`
186
84
  padding: var(--md-tabs-container-padding);
187
85
  border: var(--md-tabs-container-border);
188
86
 
189
- ${({ isReady }) =>
190
- !isReady
191
- ? css`
192
- visibility: hidden;
193
- overflow: hidden;
194
- `
195
- : css`
196
- visibility: visible;
197
- overflow: visible;
198
- `}
199
-
200
87
  ol[class^='Tabs__TabList'] {
201
88
  margin: 0;
202
89
  padding: 0;
@@ -22,6 +22,11 @@ export const tabs: MarkdocSchemaWrapper = {
22
22
  return new markdoc.Tag('Tabs', attributes, tabsContent);
23
23
  },
24
24
  attributes: {
25
+ /*
26
+ A unique persistent identifier assigned to a component.
27
+ This value is used as a key for the query parameter that stores the active tab to enable deep linking.
28
+ */
29
+ id: { type: String },
25
30
  size: { type: String, matches: ['small', 'medium'], default: 'medium' },
26
31
  },
27
32
  },