@apify/ui-library 0.71.1-featcolortokens-178953.56 → 0.71.1-featcolortokens-178953.63

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 (134) hide show
  1. package/dist/src/design_system/colors/generated/{dark.d.ts → css_variables.dark.d.ts} +1 -1
  2. package/dist/src/design_system/colors/generated/css_variables.dark.d.ts.map +1 -0
  3. package/dist/src/design_system/colors/generated/{dark.js → css_variables.dark.js} +1 -1
  4. package/dist/src/design_system/colors/generated/css_variables.dark.js.map +1 -0
  5. package/dist/src/design_system/colors/generated/{light.d.ts → css_variables.light.d.ts} +1 -1
  6. package/dist/src/design_system/colors/generated/css_variables.light.d.ts.map +1 -0
  7. package/{src/design_system/colors/generated/light.ts → dist/src/design_system/colors/generated/css_variables.light.js} +1 -1
  8. package/dist/src/design_system/colors/generated/css_variables.light.js.map +1 -0
  9. package/dist/src/design_system/colors/generated/{palette.dark.d.ts → css_variables_palette.dark.d.ts} +1 -1
  10. package/dist/src/design_system/colors/generated/css_variables_palette.dark.d.ts.map +1 -0
  11. package/dist/src/design_system/colors/generated/{palette.dark.js → css_variables_palette.dark.js} +1 -1
  12. package/dist/src/design_system/colors/generated/css_variables_palette.dark.js.map +1 -0
  13. package/dist/src/design_system/colors/generated/{palette.light.d.ts → css_variables_palette.light.d.ts} +1 -1
  14. package/dist/src/design_system/colors/generated/css_variables_palette.light.d.ts.map +1 -0
  15. package/{src/design_system/colors/generated/palette.light.ts → dist/src/design_system/colors/generated/css_variables_palette.light.js} +1 -1
  16. package/dist/src/design_system/colors/generated/css_variables_palette.light.js.map +1 -0
  17. package/dist/src/design_system/colors/index.d.ts +4 -4
  18. package/dist/src/design_system/colors/index.d.ts.map +1 -1
  19. package/dist/src/design_system/colors/index.js +4 -4
  20. package/dist/src/design_system/colors/index.js.map +1 -1
  21. package/dist/tsconfig.build.tsbuildinfo +1 -0
  22. package/package.json +7 -5
  23. package/.stylelintrc +0 -12
  24. package/CHANGELOG.md +0 -3334
  25. package/CODEOWNERS +0 -7
  26. package/dist/src/design_system/colors/generated/dark.d.ts.map +0 -1
  27. package/dist/src/design_system/colors/generated/dark.js.map +0 -1
  28. package/dist/src/design_system/colors/generated/light.d.ts.map +0 -1
  29. package/dist/src/design_system/colors/generated/light.js +0 -147
  30. package/dist/src/design_system/colors/generated/light.js.map +0 -1
  31. package/dist/src/design_system/colors/generated/palette.dark.d.ts.map +0 -1
  32. package/dist/src/design_system/colors/generated/palette.dark.js.map +0 -1
  33. package/dist/src/design_system/colors/generated/palette.light.d.ts.map +0 -1
  34. package/dist/src/design_system/colors/generated/palette.light.js +0 -74
  35. package/dist/src/design_system/colors/generated/palette.light.js.map +0 -1
  36. package/dist/src/design_system/colors_theme.d.ts +0 -213
  37. package/dist/src/design_system/colors_theme.d.ts.map +0 -1
  38. package/dist/src/design_system/colors_theme.js +0 -213
  39. package/dist/src/design_system/colors_theme.js.map +0 -1
  40. package/dist/src/design_system/properties_theme.d.ts +0 -175
  41. package/dist/src/design_system/properties_theme.d.ts.map +0 -1
  42. package/dist/src/design_system/properties_theme.js +0 -315
  43. package/dist/src/design_system/properties_theme.js.map +0 -1
  44. package/eslint.config.mjs +0 -44
  45. package/src/codemods/generate_typograpy_tokens_files.mjs +0 -137
  46. package/src/components/action_link.tsx +0 -60
  47. package/src/components/actor_template_card.tsx +0 -116
  48. package/src/components/badge.tsx +0 -148
  49. package/src/components/banner.tsx +0 -94
  50. package/src/components/blog_article.tsx +0 -85
  51. package/src/components/box.tsx +0 -127
  52. package/src/components/button.tsx +0 -305
  53. package/src/components/chip.tsx +0 -128
  54. package/src/components/code/action_button.tsx +0 -96
  55. package/src/components/code/code_block/code_block.styled.tsx +0 -180
  56. package/src/components/code/code_block/code_block.tsx +0 -224
  57. package/src/components/code/code_block/code_block_with_tabs.tsx +0 -257
  58. package/src/components/code/code_block/utils.tsx +0 -67
  59. package/src/components/code/index.ts +0 -5
  60. package/src/components/code/inline_code/inline_code.tsx +0 -62
  61. package/src/components/code/one_line_code/one_line_code.tsx +0 -228
  62. package/src/components/code/prism_highlighter.tsx +0 -180
  63. package/src/components/color_wheel_gradient.tsx +0 -31
  64. package/src/components/floating/index.ts +0 -3
  65. package/src/components/floating/menu.tsx +0 -189
  66. package/src/components/floating/menu_common.tsx +0 -31
  67. package/src/components/floating/menu_components.tsx +0 -99
  68. package/src/components/image.tsx +0 -24
  69. package/src/components/index.ts +0 -22
  70. package/src/components/link.tsx +0 -114
  71. package/src/components/message.tsx +0 -153
  72. package/src/components/rating.tsx +0 -106
  73. package/src/components/readme_renderer/index.ts +0 -3
  74. package/src/components/readme_renderer/pythonize_value.ts +0 -76
  75. package/src/components/readme_renderer/table_of_contents.tsx +0 -272
  76. package/src/components/readme_renderer/utils.tsx +0 -46
  77. package/src/components/simple_markdown/index.ts +0 -2
  78. package/src/components/simple_markdown/simple_markdown.tsx +0 -214
  79. package/src/components/simple_markdown/simple_markdown_components.tsx +0 -293
  80. package/src/components/tabs/index.ts +0 -2
  81. package/src/components/tabs/tab.tsx +0 -217
  82. package/src/components/tabs/tabs.tsx +0 -169
  83. package/src/components/tag.tsx +0 -196
  84. package/src/components/text/heading_content.tsx +0 -56
  85. package/src/components/text/heading_marketing.tsx +0 -55
  86. package/src/components/text/heading_shared.tsx +0 -55
  87. package/src/components/text/index.ts +0 -19
  88. package/src/components/text/text_base.tsx +0 -52
  89. package/src/components/text/text_content.tsx +0 -104
  90. package/src/components/text/text_marketing.tsx +0 -152
  91. package/src/components/text/text_shared.tsx +0 -95
  92. package/src/components/tile/horizontal_tile.tsx +0 -77
  93. package/src/components/tile/index.ts +0 -2
  94. package/src/components/tile/shared.ts +0 -27
  95. package/src/components/tile/vertical_tile.tsx +0 -59
  96. package/src/components/to_consolidate/card.tsx +0 -141
  97. package/src/components/to_consolidate/index.ts +0 -4
  98. package/src/components/to_consolidate/markdown.tsx +0 -609
  99. package/src/components/to_consolidate/pagination.tsx +0 -136
  100. package/src/components/to_consolidate/tab_number_chip.tsx +0 -31
  101. package/src/design_system/colors/build_color_tokens.js +0 -175
  102. package/src/design_system/colors/figma_color_tokens.dark.json +0 -886
  103. package/src/design_system/colors/figma_color_tokens.light.json +0 -886
  104. package/src/design_system/colors/generated/colors_theme.dark.ts +0 -110
  105. package/src/design_system/colors/generated/colors_theme.light.ts +0 -110
  106. package/src/design_system/colors/generated/dark.ts +0 -147
  107. package/src/design_system/colors/generated/palette.dark.ts +0 -74
  108. package/src/design_system/colors/generated/properties_theme.ts +0 -179
  109. package/src/design_system/colors/index.ts +0 -7
  110. package/src/design_system/colors_theme.ts +0 -213
  111. package/src/design_system/properties_theme.ts +0 -453
  112. package/src/design_system/supernova_typography_tokens.json +0 -657
  113. package/src/design_system/theme.ts +0 -25
  114. package/src/design_system/tokens/index.ts +0 -5
  115. package/src/design_system/tokens/layouts.ts +0 -29
  116. package/src/design_system/tokens/radiuses.ts +0 -22
  117. package/src/design_system/tokens/shadows.ts +0 -22
  118. package/src/design_system/tokens/spaces.ts +0 -15
  119. package/src/design_system/tokens/transitions.ts +0 -19
  120. package/src/design_system/typography_theme.ts +0 -197
  121. package/src/index.ts +0 -8
  122. package/src/type_utils.ts +0 -7
  123. package/src/ui_dependency_provider.tsx +0 -58
  124. package/src/utils/copy_to_clipboard.ts +0 -24
  125. package/src/utils/image_color.ts +0 -42
  126. package/src/utils/index.ts +0 -4
  127. package/src/utils/resize_observer.ts +0 -18
  128. package/src/utils/sanitization.ts +0 -14
  129. package/tsconfig.build.json +0 -17
  130. package/tsconfig.json +0 -10
  131. /package/{src/design_system/colors/generated → style/colors}/dark.scss +0 -0
  132. /package/{src/design_system/colors/generated → style/colors}/light.scss +0 -0
  133. /package/{src/design_system/colors/generated → style/colors}/palette.dark.scss +0 -0
  134. /package/{src/design_system/colors/generated → style/colors}/palette.light.scss +0 -0
@@ -1,293 +0,0 @@
1
- import qs from 'query-string';
2
- import React from 'react';
3
- import type { CodeProps, ReactMarkdownProps } from 'react-markdown/lib/ast-to-react';
4
- import styled from 'styled-components';
5
-
6
- import { CheckIcon, LinkIcon } from '@apify/ui-icons';
7
-
8
- import { theme } from '../../design_system/theme.js';
9
- import type { WithOptional } from '../../type_utils.js';
10
- import { useCopyToClipboard } from '../../utils/index.js';
11
- import { Box } from '../box.js';
12
- import { CodeBlock, InlineCode, OneLineCode } from '../code/index.js';
13
- import type { LinkProps } from '../link.js';
14
- import { Link } from '../link.js';
15
- import { slugifyHeadingChildren } from '../readme_renderer/utils.js';
16
- import type { HeadingSharedProps } from '../text/heading_shared.js';
17
- import { Heading } from '../text/index.js';
18
- import type { SharedTextProps, SharedTextSize } from '../text/text_shared.js';
19
-
20
- const simpleMarkdownClassNames = {
21
- HEADING_ICON_LINK: 'headingIconLink',
22
- } as const;
23
-
24
- export const MarkdownPlainHeading: React.FC<HeadingSharedProps> = ({
25
- children,
26
- ...rest
27
- }) => {
28
- const id = slugifyHeadingChildren(children);
29
-
30
- return (
31
- <Heading
32
- mt='space32'
33
- mb='space16'
34
- id={id}
35
- {...rest}
36
- >
37
- {children}
38
- </Heading>
39
- );
40
- };
41
-
42
- const StyledMarkdownHeading = styled(Box)`
43
- display: flex;
44
- align-items: center;
45
- gap: ${theme.space.space4};
46
-
47
- .${simpleMarkdownClassNames.HEADING_ICON_LINK} {
48
- height: 16px;
49
- display: none;
50
-
51
- svg {
52
- max-height: 1em !important;
53
- }
54
- }
55
-
56
- &:hover {
57
- .${simpleMarkdownClassNames.HEADING_ICON_LINK} {
58
- display: initial;
59
- }
60
- }
61
- `;
62
-
63
- /**
64
- * Default markdown heading that renders copy icon next to it.
65
- * Use `MarkdownPlainHeading` if you want to render simple heading instead
66
- */
67
- // TODO: This should be used for readmes
68
- export const MarkdownHeadingWrapper: React.FC<HeadingSharedProps> = ({
69
- children,
70
- ...rest
71
- }) => {
72
- const id = slugifyHeadingChildren(children);
73
-
74
- const [isCopied, handleClick] = useCopyToClipboard({
75
- text: id ?? '',
76
- // We want the whole URL to be copied, not just the ID
77
- transform: (text) => {
78
- const url = new URL(window.location.href);
79
- url.hash = `#${text}`;
80
- return url.toString();
81
- },
82
- });
83
-
84
- return (
85
- <StyledMarkdownHeading
86
- mt='space32'
87
- mb='space16'
88
- id={id}
89
- {...rest}
90
- >
91
- {children}
92
- <Link
93
- className={simpleMarkdownClassNames.HEADING_ICON_LINK}
94
- onClick={handleClick}
95
- to={`#${id}`}
96
- >
97
- {isCopied ? (
98
- <CheckIcon
99
- size="16"
100
- color={theme.color.success.action}
101
- />
102
- ) : (
103
- <LinkIcon
104
- size="16"
105
- color={theme.color.primary.text}
106
- />
107
- )}
108
- </Link>
109
- </StyledMarkdownHeading>
110
- );
111
- };
112
-
113
- const StyledInlineCode = styled(InlineCode)`
114
- /* If code is rendered within heading, it should inherit its font styles */
115
- /* TODO: Look at implementation of InlineCode - maybe we can live without it */
116
- h1 & code, h2 & code, h3 & code, h4 & code, h5 & code {
117
- font-size: inherit !important;
118
- line-height: inherit !important;
119
- }
120
-
121
- b & code, strong & code{
122
- font-weight: inherit !important;
123
- }
124
- `;
125
-
126
- type MarkdownCodeProps = Pick<CodeProps, 'inline' | 'className' | 'children'>
127
-
128
- export const MarkdownCode: React.FC<MarkdownCodeProps & { size: SharedTextSize }> = ({
129
- inline,
130
- className,
131
- children,
132
- size,
133
- }) => {
134
- if (inline) {
135
- return <StyledInlineCode size={size} className={className}>{children}</StyledInlineCode>;
136
- }
137
-
138
- const code = String(children).replace(/\n$/, '').trim();
139
- const match = /language-(\w+)/.exec(className || '');
140
- const language = match?.[1]?.toLowerCase();
141
- const isOneLineCode = code.split('\n').length <= 1;
142
-
143
- if (isOneLineCode) {
144
- return (
145
- <OneLineCode
146
- language={language}
147
- size={size}
148
- fullWidth
149
- >
150
- {code}
151
- </OneLineCode>
152
- );
153
- }
154
-
155
- return (
156
- <CodeBlock
157
- content={code}
158
- language={language}
159
- size={size}
160
- hideLineNumbers
161
- fullWidth
162
- hideBashHeader
163
- hideBashPromptPrefixes
164
- />
165
- );
166
- };
167
-
168
- const youtubeRegex = /^(?:https?:\/\/)?(?:www\.)?(?:m\.)?(?:youtube(?:-nocookie)?\.com|youtu\.be)\/(?:watch\?v=|embed\/|v\/)?([a-zA-Z0-9\-_]+)(?:\S*)?$/;
169
- const vimeoRegex = /^((?:https?:\/\/)?(?:player\.)?vimeo\.com(?:\/video)?\/(\d+))$/;
170
-
171
- const getVideoSrc = (link: string) => {
172
- const youtubeLink = link.match(youtubeRegex);
173
- const vimeoLink = link.match(vimeoRegex);
174
- let src;
175
- if (youtubeLink) {
176
- // add rel=0 to disable related videos from other channels at the end of the video
177
- // add enablejsapi=1 to enable tracking videos via API through Google Analytics
178
- src = qs.stringifyUrl({ url: `https://www.youtube.com/embed/${youtubeLink[1]}`, query: { rel: 0, enablejsapi: 1 } });
179
- }
180
- if (vimeoLink) src = `https://player.vimeo.com/video/${vimeoLink[2]}`;
181
-
182
- return src;
183
- };
184
-
185
- const StyledVideo = styled.div`
186
- width: 65%;
187
-
188
- & > div {
189
- position: relative;
190
- overflow: hidden;
191
- width: 100%;
192
- padding-top: 56.25%;
193
-
194
- & > iframe {
195
- position: absolute;
196
- top: 0;
197
- left: 0;
198
- bottom: 0;
199
- right: 0;
200
- width: 100%;
201
- height: 100%;
202
- border: 0px;
203
- }
204
- }
205
- `;
206
-
207
- interface MarkdownVideoProps {
208
- src: string;
209
- }
210
-
211
- const MarkdownVideo = ({ src }: MarkdownVideoProps) => {
212
- return (
213
- <StyledVideo>
214
- <div>
215
- <iframe loading="lazy" allowFullScreen src={src} />
216
- </div>
217
- </StyledVideo>
218
- );
219
- };
220
-
221
- const StyledMarkdownLink = styled(Link)`
222
- overflow-wrap: break-word;
223
-
224
- h1 &, h2 &, h3 &, h4 &, h5 & {
225
- overflow-wrap: normal;
226
- }
227
-
228
- &:hover {
229
- /* Links normally don't have underline, but in markdown we want to have it */
230
- text-decoration: underline;
231
- }
232
- `;
233
-
234
- export const MarkdownLink: React.FC<WithOptional<LinkProps, 'to'>> = ({
235
- to,
236
- children,
237
- rel,
238
- className,
239
- }) => {
240
- return (to && typeof to === 'string') ? (
241
- <StyledMarkdownLink to={to} hideExternalIcon={true} rel={rel} className={className}>{children}</StyledMarkdownLink>
242
- ) : (
243
- (<span>{children}</span>) // Invalid links can be rendered as a regular span instead
244
- );
245
- };
246
-
247
- export const MarkdownBlockQuote = styled(Box).attrs({
248
- my: 'space16',
249
- py: 'none',
250
- forwardedAs: 'blockquote',
251
- })`
252
- border-left: 2px solid ${theme.color.neutral.separatorSubtle};
253
- padding-left: ${theme.space.space16};
254
-
255
- color: ${theme.color.neutral.textMuted};
256
-
257
- & > p {
258
- margin: 0;
259
- }
260
- `;
261
-
262
- export const MarkdownTable = styled.table`
263
- display: block;
264
- overflow: auto;
265
- border-collapse: collapse;
266
-
267
- td, th {
268
- border: 1px solid ${theme.color.neutral.border};
269
- padding: ${theme.space.space16};
270
- text-align: left;
271
- }
272
-
273
- tr:nth-child(even):not([class]) {
274
- > th, > td {
275
- background-color: inherit;
276
- }
277
- }
278
- `;
279
-
280
- // TODO: This should be used for readmes
281
- export const MarkdownParagraphContent: React.FC<SharedTextProps & Pick<ReactMarkdownProps, 'node'>> = ({
282
- children,
283
- node,
284
- }) => {
285
- const child = node.children[0];
286
- const isText = child?.type === 'text';
287
-
288
- const videoSrc = isText && getVideoSrc(child.value);
289
- if (videoSrc) return <MarkdownVideo src={videoSrc} />;
290
-
291
- // the || null part is important because non-supported elements will fall back to this paragraph component;
292
- return children || null;
293
- };
@@ -1,2 +0,0 @@
1
- export * from './tabs.js';
2
- export * from './tab.js';
@@ -1,217 +0,0 @@
1
- import clsx from 'clsx';
2
- import { createPath } from 'history';
3
- import React from 'react';
4
- import type { FlattenSimpleInterpolation } from 'styled-components';
5
- import styled, { css } from 'styled-components';
6
-
7
- import type { IconComponent } from '@apify/ui-icons';
8
-
9
- import { theme } from '../../design_system/theme.js';
10
- import type { WithTransientProps } from '../../type_utils.js';
11
- import type { BadgeSize } from '../badge.js';
12
- import { Badge } from '../badge.js';
13
- import type { MarginSpacingProps, RegularBoxProps } from '../box.js';
14
- import type { RegularLinkProps } from '../link.js';
15
- import { Link } from '../link.js';
16
- import { Text } from '../text/index.js';
17
- import type { SharedTextSize } from '../text/text_shared.js';
18
-
19
- type SharedTabProps = Omit<RegularBoxProps, 'as' | 'onClick'> & MarginSpacingProps & Omit<RegularLinkProps, 'hideExternalIcon' | 'showExternalIcon'>;
20
-
21
- export type TabVariant = 'default' | 'boxed' | 'buttoned';
22
-
23
- export type TabData = SharedTabProps & {
24
- id: string;
25
- title: string;
26
- Icon?: IconComponent;
27
- chip?: number | string;
28
- rollout?: 'alpha' | 'beta';
29
- disabled?: boolean;
30
- };
31
-
32
- export type TabProps = TabData & {
33
- variant?: TabVariant;
34
- active?: boolean;
35
- onSelect?: (data: { id: string, href: string, event: React.MouseEvent }) => void;
36
- };
37
-
38
- const tabVariantTextSize = {
39
- default: 'regular',
40
- boxed: 'regular',
41
- buttoned: 'small',
42
- } satisfies Record<TabVariant, SharedTextSize>;
43
-
44
- const tabVariantBadgeSize = {
45
- default: 'small',
46
- boxed: 'small',
47
- buttoned: 'extra_small',
48
- } satisfies Record<TabVariant, BadgeSize>;
49
-
50
- const tabVariantStyle = {
51
- default: css`
52
- height: 3.6rem;
53
- padding: 0 ${theme.space.space8};
54
- color: ${theme.color.neutral.textSubtle};
55
-
56
- &:hover {
57
- color: ${theme.color.primaryBlack.actionHover}
58
- }
59
-
60
- &.active {
61
- color: ${theme.color.neutral.text};
62
-
63
- &::after {
64
- bottom: -${theme.space.space4};
65
- right: 0;
66
- left: 0;
67
- height: 2px;
68
- background-color: ${theme.color.primaryBlack.action};
69
- border-radius: ${theme.radius.radiusFull};
70
- content: '';
71
- display: block;
72
- pointer-events: none;
73
- position: absolute;
74
- }
75
-
76
- &.disabled::after {
77
- background-color: ${theme.color.neutral.textDisabled};
78
- }
79
- }
80
- `,
81
- boxed: css`
82
- height: 3.6rem;
83
- border: 1px solid transparent;
84
- border-top-right-radius: ${theme.radius.radius6};
85
- border-top-left-radius: ${theme.radius.radius6};
86
- padding: 0 ${theme.space.space12};
87
- color: ${theme.color.neutral.textMuted};
88
-
89
- &::after {
90
- inset: ${theme.space.space4};
91
- background-color: transparent;
92
- border-radius: ${theme.radius.radius6};
93
- content: '';
94
- display: block;
95
- pointer-events: none;
96
- position: absolute;
97
- transition: background-color ${theme.transition.fastEaseOut};
98
- z-index: -1;
99
- }
100
-
101
- &:hover {
102
- color: ${theme.color.neutral.text};
103
-
104
- &::after {
105
- background-color: ${theme.color.neutral.hover};
106
- }
107
- }
108
-
109
- &.active {
110
- color: ${theme.color.neutral.text};
111
- border-color: ${theme.color.neutral.border};
112
- border-bottom-color: ${theme.color.neutral.background};
113
-
114
- &::after {
115
- background-color: transparent;
116
- }
117
- }
118
- `,
119
- buttoned: css`
120
- height: 3.2rem;
121
- margin: 0 ${theme.space.space4};
122
- padding: 0 ${theme.space.space8};
123
- background-color: transparent;
124
- border: 1px solid transparent;
125
- border-radius: ${theme.radius.radius8};
126
- color: ${theme.color.neutral.textMuted};
127
-
128
- &:hover {
129
- background-color: ${theme.color.neutral.hover};
130
- color: ${theme.color.neutral.text};
131
- }
132
-
133
- &.active {
134
- background-color: transparent;
135
- border-color: ${theme.color.neutral.border};
136
- color: ${theme.color.neutral.text};
137
- }
138
- `,
139
- } satisfies Record<TabVariant, FlattenSimpleInterpolation>;
140
-
141
- type TabWrapperProps = WithTransientProps<Required<Pick<TabProps, 'variant'>>> & {
142
- role?: React.AriaRole;
143
- };
144
-
145
- export const TAB_CLASSNAMES = {
146
- ICON: 'Tab-icon',
147
- TITLE: 'Tab-title',
148
- BADGE: 'Tab-badge',
149
- };
150
-
151
- const TabWrapper = styled(Link)<TabWrapperProps>`
152
- display: inline-flex;
153
- align-items: center;
154
- justify-content: center;
155
- gap: ${theme.space.space4};
156
- flex-shrink: 0;
157
- cursor: pointer;
158
- position: relative;
159
- transition: background-color ${theme.transition.fastEaseOut}, border-color ${theme.transition.fastEaseOut}, color ${theme.transition.fastEaseOut};
160
- z-index: 1;
161
-
162
-
163
- ${({ $variant }) => tabVariantStyle[$variant]};
164
-
165
- &.disabled {
166
- color: ${theme.color.neutral.textDisabled};
167
- pointer-events: none;
168
- }
169
-
170
- .${TAB_CLASSNAMES.ICON} {
171
- color: inherit;
172
- flex-shrink: 0;
173
- transition: color ${theme.transition.fastEaseOut};
174
- }
175
-
176
- .${TAB_CLASSNAMES.TITLE} {
177
- overflow: hidden;
178
- text-overflow: ellipsis;
179
- white-space: nowrap;
180
- }
181
-
182
- .${TAB_CLASSNAMES.BADGE} {
183
- flex-shrink: 0;
184
- text-transform: uppercase;
185
- }
186
- `;
187
-
188
- export const Tab = ({ variant = 'default', id, to, Icon, title, chip, rollout, className, onSelect, active = false, disabled = false, ...props }: TabProps) => {
189
- const href = typeof (to) === 'string' ? to : createPath(to);
190
-
191
- return (
192
- <TabWrapper
193
- {...props}
194
- id={id}
195
- to={to}
196
- role="tab"
197
- data-test="tab"
198
- data-test-url={href}
199
- className={clsx(className, { active, disabled })}
200
- onClick={onSelect ? (event) => onSelect({ id, href, event }) : undefined}
201
- $variant={variant}
202
- >
203
- {Icon && <Icon size="16" className={TAB_CLASSNAMES.ICON} />}
204
- <Text size={tabVariantTextSize[variant]} className={TAB_CLASSNAMES.ICON} weight="bold" as="div">{title}</Text>
205
- {chip && (
206
- <Badge
207
- size={tabVariantBadgeSize[variant]}
208
- variant={active ? 'primary_black' : 'neutral_subtle'}
209
- className={TAB_CLASSNAMES.ICON}
210
- >
211
- {chip}
212
- </Badge>
213
- )}
214
- {rollout && <Badge size={tabVariantBadgeSize[variant]} variant="primary_blue" className={TAB_CLASSNAMES.ICON}>{rollout}</Badge>}
215
- </TabWrapper>
216
- );
217
- };
@@ -1,169 +0,0 @@
1
- import React, { useCallback, useRef, useState } from 'react';
2
- import type { FlattenSimpleInterpolation } from 'styled-components';
3
- import styled, { css } from 'styled-components';
4
-
5
- import { theme } from '../../design_system/theme.js';
6
- import type { WithTransientProps } from '../../type_utils.js';
7
- import { useResizeObserverSsr } from '../../utils/resize_observer.js';
8
- import type { MarginSpacingProps, RegularBoxProps } from '../box.js';
9
- import { Box } from '../box.js';
10
- import type { TabData, TabVariant } from './tab.js';
11
- import { Tab } from './tab.js';
12
-
13
- type SharedTabsProps = Omit<RegularBoxProps, 'as' | 'onClick'> & MarginSpacingProps;
14
- type TabsProps = SharedTabsProps & {
15
- variant?: TabVariant;
16
- tabs: TabData[];
17
- activeTab?: string;
18
- onSelect?: (data: { id: string, href: string, event: React.MouseEvent }) => void;
19
- };
20
-
21
- const tabsVariantStyle = {
22
- default: css`
23
- align-items: flex-start;
24
- gap: ${theme.space.space8};
25
-
26
- &::after {
27
- bottom: 0;
28
- right: 0;
29
- left: 0;
30
- height: 1px;
31
- background-color: ${theme.color.neutral.separatorSubtle};
32
- border-radius: ${theme.radius.radiusFull};
33
- content: '';
34
- display: block;
35
- pointer-events: none;
36
- position: absolute;
37
- }
38
- `,
39
- boxed: css`
40
- align-items: flex-end;
41
-
42
- &::after {
43
- bottom: 0;
44
- right: 0;
45
- left: 0;
46
- height: 1px;
47
- background-color: ${theme.color.neutral.border};
48
- content: '';
49
- display: block;
50
- pointer-events: none;
51
- position: absolute;
52
- }
53
- `,
54
- buttoned: css`
55
- align-items: center;
56
- `,
57
- } satisfies Record<TabVariant, FlattenSimpleInterpolation>;
58
-
59
- type TabsWrapperProps = WithTransientProps<Required<Pick<TabsProps, 'variant'>>> & {
60
- role?: React.AriaRole;
61
- };
62
-
63
- const TabsWrapper = styled(Box)<TabsWrapperProps>`
64
- height: 4rem;
65
- display: flex;
66
- position: relative;
67
-
68
- [role='tabpanel'] {
69
- min-width: 0;
70
- display: flex;
71
- flex-grow: 1;
72
- overflow-x: auto;
73
- ${({ $variant }) => tabsVariantStyle[$variant]};
74
-
75
- /* Scrollbar */
76
- -ms-overflow-style: none;
77
- scrollbar-width: none;
78
-
79
- &::-webkit-scrollbar {
80
- display: none; /* Chrome, Safari, Opera */
81
- }
82
- }
83
-
84
- & > [role="cell"] {
85
- position: sticky;
86
- top: 0;
87
- height: 100%;
88
- width: 0;
89
- margin-left: auto;
90
- opacity: 0;
91
- transition: opacity ${theme.transition.fastEaseOut};
92
- z-index: 2;
93
-
94
- &[aria-hidden="false"] {
95
- opacity: 1;
96
- }
97
-
98
- &::after {
99
- height: 100%;
100
- width: ${theme.space.space32};
101
- content: ' ';
102
- pointer-events: none;
103
- position: absolute;
104
- }
105
-
106
- &:first-of-type {
107
- left: 0;
108
-
109
- &::after {
110
- left: 0;
111
- background: linear-gradient(90deg, ${theme.color.neutral.background} 0%, rgba(255, 255, 255, 0) 100%);
112
- }
113
- }
114
-
115
- &:last-of-type {
116
- right: 0;
117
-
118
- &::after {
119
- right: 0;
120
- background: linear-gradient(90deg, rgba(255, 255, 255, 0) 0%, ${theme.color.neutral.background} 100%);
121
- }
122
- }
123
- }
124
- `;
125
-
126
- type TabOverflowState = {
127
- right: boolean;
128
- left: boolean;
129
- }
130
-
131
- const isTabsOverflowing = (node: HTMLDivElement): TabOverflowState => {
132
- if (node.scrollWidth > node.clientWidth) {
133
- return {
134
- right: node.clientWidth + node.scrollLeft < node.scrollWidth,
135
- left: node.scrollLeft > 0,
136
- };
137
- }
138
-
139
- return {
140
- right: false,
141
- left: false,
142
- };
143
- };
144
-
145
- export const Tabs = ({ variant = 'default', tabs, activeTab, onSelect, ...props }: TabsProps) => {
146
- const ref = useRef<HTMLDivElement>(null);
147
- const [overflowState, setOveflowState] = useState<TabOverflowState>();
148
-
149
- useResizeObserverSsr(ref, (entry) => setOveflowState(isTabsOverflowing(entry.target as HTMLDivElement)));
150
- const scrollHandler = useCallback((event: React.SyntheticEvent<HTMLDivElement>) => {
151
- setOveflowState(isTabsOverflowing(event.currentTarget as HTMLDivElement));
152
- }, []);
153
-
154
- return <TabsWrapper {...props} role="tablist" data-test="tabs-wrapper" $variant={variant}>
155
- <div role="cell" aria-hidden={!overflowState?.left} />
156
- <div ref={ref} role="tabpanel" onScroll={scrollHandler}>
157
- {tabs.map((tab) => (
158
- <Tab
159
- {...tab}
160
- key={tab.id}
161
- variant={variant}
162
- active={tab.id === activeTab}
163
- onSelect={onSelect}
164
- />
165
- ))}
166
- </div>
167
- <div role="cell" aria-hidden={!overflowState?.right} />
168
- </TabsWrapper>;
169
- };