@apify/ui-library 0.71.1-featcolortokens-178953.63 → 0.71.1-featcolortokens-178953.67
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/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +3 -2
- package/src/codemods/generate_typograpy_tokens_files.mjs +137 -0
- package/src/components/action_link.tsx +60 -0
- package/src/components/actor_template_card.tsx +116 -0
- package/src/components/badge.tsx +148 -0
- package/src/components/banner.tsx +94 -0
- package/src/components/blog_article.tsx +85 -0
- package/src/components/box.tsx +127 -0
- package/src/components/button.tsx +305 -0
- package/src/components/chip.tsx +128 -0
- package/src/components/code/action_button.tsx +96 -0
- package/src/components/code/code_block/code_block.styled.tsx +180 -0
- package/src/components/code/code_block/code_block.tsx +224 -0
- package/src/components/code/code_block/code_block_with_tabs.tsx +257 -0
- package/src/components/code/code_block/utils.tsx +67 -0
- package/src/components/code/index.ts +5 -0
- package/src/components/code/inline_code/inline_code.tsx +62 -0
- package/src/components/code/one_line_code/one_line_code.tsx +228 -0
- package/src/components/code/prism_highlighter.tsx +180 -0
- package/src/components/color_wheel_gradient.tsx +31 -0
- package/src/components/floating/index.ts +3 -0
- package/src/components/floating/menu.tsx +189 -0
- package/src/components/floating/menu_common.tsx +31 -0
- package/src/components/floating/menu_components.tsx +99 -0
- package/src/components/image.tsx +24 -0
- package/src/components/index.ts +22 -0
- package/src/components/link.tsx +114 -0
- package/src/components/message.tsx +153 -0
- package/src/components/rating.tsx +106 -0
- package/src/components/readme_renderer/index.ts +3 -0
- package/src/components/readme_renderer/pythonize_value.ts +76 -0
- package/src/components/readme_renderer/table_of_contents.tsx +272 -0
- package/src/components/readme_renderer/utils.tsx +46 -0
- package/src/components/simple_markdown/index.ts +2 -0
- package/src/components/simple_markdown/simple_markdown.tsx +214 -0
- package/src/components/simple_markdown/simple_markdown_components.tsx +293 -0
- package/src/components/tabs/index.ts +2 -0
- package/src/components/tabs/tab.tsx +217 -0
- package/src/components/tabs/tabs.tsx +169 -0
- package/src/components/tag.tsx +196 -0
- package/src/components/text/heading_content.tsx +56 -0
- package/src/components/text/heading_marketing.tsx +55 -0
- package/src/components/text/heading_shared.tsx +55 -0
- package/src/components/text/index.ts +19 -0
- package/src/components/text/text_base.tsx +52 -0
- package/src/components/text/text_content.tsx +104 -0
- package/src/components/text/text_marketing.tsx +152 -0
- package/src/components/text/text_shared.tsx +95 -0
- package/src/components/tile/horizontal_tile.tsx +77 -0
- package/src/components/tile/index.ts +2 -0
- package/src/components/tile/shared.ts +27 -0
- package/src/components/tile/vertical_tile.tsx +59 -0
- package/src/components/to_consolidate/card.tsx +141 -0
- package/src/components/to_consolidate/index.ts +4 -0
- package/src/components/to_consolidate/markdown.tsx +609 -0
- package/src/components/to_consolidate/pagination.tsx +136 -0
- package/src/components/to_consolidate/tab_number_chip.tsx +31 -0
- package/src/design_system/colors/build_color_tokens.js +183 -0
- package/src/design_system/colors/figma_color_tokens.dark.json +886 -0
- package/src/design_system/colors/figma_color_tokens.light.json +886 -0
- package/src/design_system/colors/generated/colors_theme.dark.ts +110 -0
- package/src/design_system/colors/generated/colors_theme.light.ts +110 -0
- package/src/design_system/colors/generated/css_variables.dark.ts +147 -0
- package/src/design_system/colors/generated/css_variables.light.ts +147 -0
- package/src/design_system/colors/generated/css_variables_palette.dark.ts +74 -0
- package/src/design_system/colors/generated/css_variables_palette.light.ts +74 -0
- package/src/design_system/colors/generated/properties_theme.ts +179 -0
- package/src/design_system/colors/index.ts +7 -0
- package/src/design_system/supernova_typography_tokens.json +657 -0
- package/src/design_system/theme.ts +25 -0
- package/src/design_system/tokens/index.ts +5 -0
- package/src/design_system/tokens/layouts.ts +29 -0
- package/src/design_system/tokens/radiuses.ts +22 -0
- package/src/design_system/tokens/shadows.ts +22 -0
- package/src/design_system/tokens/spaces.ts +15 -0
- package/src/design_system/tokens/transitions.ts +19 -0
- package/src/design_system/typography_theme.ts +197 -0
- package/src/index.ts +8 -0
- package/src/type_utils.ts +7 -0
- package/src/ui_dependency_provider.tsx +58 -0
- package/src/utils/copy_to_clipboard.ts +24 -0
- package/src/utils/image_color.ts +42 -0
- package/src/utils/index.ts +4 -0
- package/src/utils/resize_observer.ts +18 -0
- package/src/utils/sanitization.ts +14 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@apify/ui-library",
|
|
3
|
-
"version": "0.71.1-featcolortokens-178953.
|
|
3
|
+
"version": "0.71.1-featcolortokens-178953.67+5454a7d7f71",
|
|
4
4
|
"description": "React UI library used by apify.com",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -69,7 +69,8 @@
|
|
|
69
69
|
},
|
|
70
70
|
"files": [
|
|
71
71
|
"dist",
|
|
72
|
+
"src",
|
|
72
73
|
"style"
|
|
73
74
|
],
|
|
74
|
-
"gitHead": "
|
|
75
|
+
"gitHead": "5454a7d7f71ea2968f86171b9e587910bdee5bdc"
|
|
75
76
|
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
+
|
|
3
|
+
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
4
|
+
import { print, types } from 'recast';
|
|
5
|
+
|
|
6
|
+
const { builders } = types;
|
|
7
|
+
|
|
8
|
+
const code = readFileSync('./src/design_system/supernova_typography_tokens.json', 'utf-8');
|
|
9
|
+
|
|
10
|
+
const fontFamilies = {
|
|
11
|
+
inter: `Inter, sans-serif`,
|
|
12
|
+
gtWalsheim: `'GT-Walsheim-Regular', sans-serif`,
|
|
13
|
+
sfPro: `-apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji'`,
|
|
14
|
+
ibmPlexMono: "'IBM Plex Mono', Consolas, 'Liberation Mono', Menlo, monospace",
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const transformTokenProperties = (token) => {
|
|
18
|
+
const {
|
|
19
|
+
fontWeight,
|
|
20
|
+
fontSize,
|
|
21
|
+
lineHeight,
|
|
22
|
+
fontFamily,
|
|
23
|
+
} = token.value;
|
|
24
|
+
|
|
25
|
+
// Convert font family name to font family value
|
|
26
|
+
let fontFamilyValue;
|
|
27
|
+
const fontFamilyNameParts = fontFamily.split(' '); // each word in font family name is a separate part
|
|
28
|
+
|
|
29
|
+
if (fontFamilyNameParts.length === 1) {
|
|
30
|
+
fontFamilyValue = fontFamilies[fontFamilyNameParts[0].toLowerCase()];
|
|
31
|
+
} else {
|
|
32
|
+
const fontFamilyIndex = fontFamilyNameParts.map((fontFamilyNamePart, i) => {
|
|
33
|
+
if (i === 0) return fontFamilyNamePart.toLowerCase();
|
|
34
|
+
return fontFamilyNamePart;
|
|
35
|
+
}).join('');
|
|
36
|
+
|
|
37
|
+
fontFamilyValue = fontFamilies[fontFamilyIndex];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return `font-size: ${Number(fontSize) / 10}rem; line-height: ${Number(lineHeight) / 10}rem; font-weight: ${fontWeight}; font-family: ${fontFamilyValue};`;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const transformTokenName = (tokenName) => {
|
|
44
|
+
const [token, variant] = tokenName.split('-');
|
|
45
|
+
return (variant ? `${token}${variant.charAt(0).toUpperCase() + variant.slice(1)}` : token);
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const extractDeviceTokensDefinitions = (tokens) => {
|
|
49
|
+
return Object.keys(tokens).reduce((acc, tokenName) => {
|
|
50
|
+
const properTokenName = transformTokenName(tokenName);
|
|
51
|
+
acc[properTokenName] = transformTokenProperties(tokens[tokenName], fontFamilies);
|
|
52
|
+
return acc;
|
|
53
|
+
}, {});
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const extractTokensDefinitions = (sharedTokens) => {
|
|
57
|
+
const sharedTokensDefinition = {
|
|
58
|
+
mobile: {},
|
|
59
|
+
tablet: {},
|
|
60
|
+
desktop: {},
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
Object.entries(sharedTokens).forEach(([tokenName, tokenValue]) => {
|
|
64
|
+
if ((tokenName === 'mobile' || tokenName === 'tablet') && typeof tokenValue !== 'string') {
|
|
65
|
+
sharedTokensDefinition[tokenName] = extractDeviceTokensDefinitions(tokenValue, fontFamilies);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const properTokenName = transformTokenName(tokenName);
|
|
70
|
+
const transformedTokenProperties = transformTokenProperties(tokenValue, fontFamilies);
|
|
71
|
+
sharedTokensDefinition.desktop[properTokenName] = transformedTokenProperties;
|
|
72
|
+
sharedTokensDefinition.mobile[properTokenName] ||= transformedTokenProperties;
|
|
73
|
+
sharedTokensDefinition.tablet[properTokenName] ||= transformedTokenProperties;
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
return sharedTokensDefinition;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const globalTokens = JSON.parse(code).global;
|
|
80
|
+
|
|
81
|
+
const sharedTokens = extractTokensDefinitions(globalTokens.shared);
|
|
82
|
+
const marketingTokens = extractTokensDefinitions(globalTokens.marketing);
|
|
83
|
+
const contentTokens = extractTokensDefinitions(globalTokens.content);
|
|
84
|
+
|
|
85
|
+
const tokensForCodeGeneration = {
|
|
86
|
+
shared: sharedTokens,
|
|
87
|
+
marketing: marketingTokens,
|
|
88
|
+
content: contentTokens,
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
const createTokensCode = (tokens) => {
|
|
92
|
+
const variantsArray = [];
|
|
93
|
+
for (const [tokenVariant, tokenVariantItems] of Object.entries(tokens)) {
|
|
94
|
+
const devicesArray = [];
|
|
95
|
+
|
|
96
|
+
for (const [device, deviceTokens] of Object.entries(tokenVariantItems)) {
|
|
97
|
+
const deviceItemsArray = [];
|
|
98
|
+
|
|
99
|
+
for (const [tokenName, tokenValue] of Object.entries(deviceTokens)) {
|
|
100
|
+
deviceItemsArray.push(builders.property(
|
|
101
|
+
'init',
|
|
102
|
+
builders.identifier(tokenName),
|
|
103
|
+
builders.literal(tokenValue),
|
|
104
|
+
));
|
|
105
|
+
}
|
|
106
|
+
devicesArray.push(builders.property(
|
|
107
|
+
'init',
|
|
108
|
+
builders.identifier(device),
|
|
109
|
+
builders.objectExpression(deviceItemsArray),
|
|
110
|
+
));
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
variantsArray.push(builders.property(
|
|
114
|
+
'init',
|
|
115
|
+
builders.identifier(tokenVariant),
|
|
116
|
+
builders.objectExpression(devicesArray),
|
|
117
|
+
));
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const exportDeclaration = builders.exportNamedDeclaration(
|
|
121
|
+
builders.variableDeclaration('const', [
|
|
122
|
+
builders.variableDeclarator(
|
|
123
|
+
builders.identifier('typographyTokens'),
|
|
124
|
+
builders.tsAsExpression(builders.objectExpression(variantsArray), builders.tsTypeReference(builders.identifier('const'))),
|
|
125
|
+
)]),
|
|
126
|
+
[],
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
// Add a comment to the export declaration
|
|
130
|
+
exportDeclaration.comments = [builders.commentBlock(' eslint-disable max-len ')];
|
|
131
|
+
|
|
132
|
+
return exportDeclaration;
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
const printedCode = print(builders.program([createTokensCode(tokensForCodeGeneration)])).code;
|
|
136
|
+
|
|
137
|
+
writeFileSync('./src/design_system/typography_theme.ts', printedCode);
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import styled from 'styled-components';
|
|
3
|
+
|
|
4
|
+
import { ArrowLeftIcon, ArrowRightIcon } from '@apify/ui-icons';
|
|
5
|
+
|
|
6
|
+
import { theme } from '../design_system/theme.js';
|
|
7
|
+
import { Box } from './box.js';
|
|
8
|
+
import { Link, type LinkProps } from './link.js';
|
|
9
|
+
import { Heading } from './text/index.js';
|
|
10
|
+
|
|
11
|
+
const StyledGuidepost = styled(Box)<{ $isBackLink: boolean }>`
|
|
12
|
+
display: inline-flex;
|
|
13
|
+
align-items: center;
|
|
14
|
+
color: ${theme.color.neutral.text};
|
|
15
|
+
|
|
16
|
+
svg {
|
|
17
|
+
transition: transform 0.2s ease-in-out;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
&:hover {
|
|
21
|
+
svg {
|
|
22
|
+
transform: translate(${({ $isBackLink }) => ($isBackLink ? -3 : 3)}px, 0);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
`;
|
|
26
|
+
|
|
27
|
+
export const ActionLink: React.FC<LinkProps & { contentProps?: object }> = ({
|
|
28
|
+
children,
|
|
29
|
+
as = Link,
|
|
30
|
+
contentProps,
|
|
31
|
+
...rest
|
|
32
|
+
}) => {
|
|
33
|
+
return (
|
|
34
|
+
<StyledGuidepost
|
|
35
|
+
forwardedAs={as}
|
|
36
|
+
$isBackLink={false}
|
|
37
|
+
{...rest}
|
|
38
|
+
>
|
|
39
|
+
<Heading as='span' type='titleM' {...contentProps}>{children}</Heading>
|
|
40
|
+
<ArrowRightIcon size="16" />
|
|
41
|
+
</StyledGuidepost>
|
|
42
|
+
);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export const BackLink: React.FC<LinkProps> = ({
|
|
46
|
+
children,
|
|
47
|
+
as,
|
|
48
|
+
...rest
|
|
49
|
+
}) => {
|
|
50
|
+
return (
|
|
51
|
+
<StyledGuidepost
|
|
52
|
+
forwardedAs={as || Link}
|
|
53
|
+
$isBackLink={true}
|
|
54
|
+
{...rest}
|
|
55
|
+
>
|
|
56
|
+
<ArrowLeftIcon size="16" />
|
|
57
|
+
<Heading as='span' type='titleM'>{children}</Heading>
|
|
58
|
+
</StyledGuidepost>
|
|
59
|
+
);
|
|
60
|
+
};
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import styled from 'styled-components';
|
|
3
|
+
|
|
4
|
+
import { theme } from '../design_system/theme.js';
|
|
5
|
+
import { Badge } from './badge.js';
|
|
6
|
+
import { TextMarketing } from './text/text_marketing.js';
|
|
7
|
+
import { VerticalTile } from './tile/index.js';
|
|
8
|
+
|
|
9
|
+
interface ActorTemplateCardProps {
|
|
10
|
+
id: string;
|
|
11
|
+
label: string;
|
|
12
|
+
description: string;
|
|
13
|
+
icons: React.ReactNode[];
|
|
14
|
+
useCases?: string[];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const WrapperClasses = {
|
|
18
|
+
TEMPLATE_CARD_IMAGES: 'TemplateCard-Images',
|
|
19
|
+
TEMPLATE_CARD_TEXT: 'TemplateCard-Text',
|
|
20
|
+
TEMPLATE_CARD_DESCRIPTION: 'TemplateCard-Description',
|
|
21
|
+
TEMPLATE_CARD_BADGES: 'TemplateCard-Badges',
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const TemplateCardContentWrapper = styled.div`
|
|
25
|
+
display: flex;
|
|
26
|
+
flex-direction: column;
|
|
27
|
+
align-items: flex-start;
|
|
28
|
+
align-self: stretch;
|
|
29
|
+
flex: 1 0 0;
|
|
30
|
+
gap: ${theme.space.space16};
|
|
31
|
+
color: ${theme.color.neutral.text};
|
|
32
|
+
|
|
33
|
+
.${WrapperClasses.TEMPLATE_CARD_IMAGES} {
|
|
34
|
+
display: flex;
|
|
35
|
+
align-items: flex-start;
|
|
36
|
+
gap: ${theme.space.space16};
|
|
37
|
+
flex-wrap: wrap;
|
|
38
|
+
img,
|
|
39
|
+
svg {
|
|
40
|
+
max-width: ${theme.space.space40};
|
|
41
|
+
max-height: ${theme.space.space40};
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.${WrapperClasses.TEMPLATE_CARD_TEXT} {
|
|
46
|
+
display: flex;
|
|
47
|
+
flex-direction: column;
|
|
48
|
+
align-items: flex-start;
|
|
49
|
+
align-self: stretch;
|
|
50
|
+
gap: ${theme.space.space4};
|
|
51
|
+
|
|
52
|
+
.${WrapperClasses.TEMPLATE_CARD_DESCRIPTION} {
|
|
53
|
+
color: ${theme.color.neutral.textMuted};
|
|
54
|
+
overflow: hidden;
|
|
55
|
+
text-overflow: ellipsis;
|
|
56
|
+
display: -webkit-box;
|
|
57
|
+
-webkit-line-clamp: 3;
|
|
58
|
+
-webkit-box-orient: vertical;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.${WrapperClasses.TEMPLATE_CARD_BADGES} {
|
|
63
|
+
display: flex;
|
|
64
|
+
gap: ${theme.space.space4};
|
|
65
|
+
}
|
|
66
|
+
`;
|
|
67
|
+
|
|
68
|
+
export const ActorTemplateCard: React.FC<ActorTemplateCardProps> = ({
|
|
69
|
+
id,
|
|
70
|
+
label,
|
|
71
|
+
description,
|
|
72
|
+
icons,
|
|
73
|
+
useCases,
|
|
74
|
+
}) => {
|
|
75
|
+
const templateCardContent = (
|
|
76
|
+
<TemplateCardContentWrapper>
|
|
77
|
+
<div className={WrapperClasses.TEMPLATE_CARD_IMAGES}>{icons}</div>
|
|
78
|
+
<div className={WrapperClasses.TEMPLATE_CARD_TEXT}>
|
|
79
|
+
<TextMarketing size="regular" weight="bold">
|
|
80
|
+
{label}
|
|
81
|
+
</TextMarketing>
|
|
82
|
+
<TextMarketing
|
|
83
|
+
size="small"
|
|
84
|
+
className={WrapperClasses.TEMPLATE_CARD_DESCRIPTION}
|
|
85
|
+
>
|
|
86
|
+
{description}
|
|
87
|
+
</TextMarketing>
|
|
88
|
+
</div>
|
|
89
|
+
<div className={WrapperClasses.TEMPLATE_CARD_BADGES}>
|
|
90
|
+
{useCases?.includes('STARTER') && (
|
|
91
|
+
<Badge variant="success">Starter</Badge>
|
|
92
|
+
)}
|
|
93
|
+
{useCases?.includes('AI') && (
|
|
94
|
+
<Badge
|
|
95
|
+
variant="success"
|
|
96
|
+
style={{
|
|
97
|
+
color: '#6E00F4',
|
|
98
|
+
fill: '#6E00F4',
|
|
99
|
+
background: '#E4D4F7',
|
|
100
|
+
}}
|
|
101
|
+
>
|
|
102
|
+
AI Agent
|
|
103
|
+
</Badge>
|
|
104
|
+
)}
|
|
105
|
+
</div>
|
|
106
|
+
</TemplateCardContentWrapper>
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
return (
|
|
110
|
+
<VerticalTile
|
|
111
|
+
id={`actor-template-card-${id}`}
|
|
112
|
+
content={templateCardContent}
|
|
113
|
+
isClickable
|
|
114
|
+
/>
|
|
115
|
+
);
|
|
116
|
+
};
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import React, { forwardRef } from 'react';
|
|
2
|
+
import styled, { css, type FlattenSimpleInterpolation } from 'styled-components';
|
|
3
|
+
|
|
4
|
+
import type { IconComponent, IconSize } from '@apify/ui-icons';
|
|
5
|
+
|
|
6
|
+
import { theme } from '../design_system/theme.js';
|
|
7
|
+
import type { WithTransientProps } from '../type_utils.js';
|
|
8
|
+
import { Box, type MarginSpacingProps, type RegularBoxProps } from './box.js';
|
|
9
|
+
import { Text } from './text/index.js';
|
|
10
|
+
import type { SharedTextSize, SharedTextType } from './text/text_shared.js';
|
|
11
|
+
|
|
12
|
+
export type BadgeSize = 'regular' | 'small' | 'extra_small';
|
|
13
|
+
export const BADGE_SIZES: BadgeSize[] = ['regular', 'small'];
|
|
14
|
+
|
|
15
|
+
const BADGE_ICON_SIZES = {
|
|
16
|
+
regular: '16',
|
|
17
|
+
small: '12',
|
|
18
|
+
extra_small: '12',
|
|
19
|
+
} satisfies Record<BadgeSize, IconSize>;
|
|
20
|
+
|
|
21
|
+
const BADGE_TEXT_SIZES = {
|
|
22
|
+
regular: 'regular',
|
|
23
|
+
small: 'small',
|
|
24
|
+
extra_small: 'small',
|
|
25
|
+
} satisfies Record<BadgeSize, SharedTextSize>;
|
|
26
|
+
|
|
27
|
+
export const BADGE_VARIANTS = ['neutral', 'neutral_muted', 'neutral_subtle', 'primary_black', 'primary_blue', 'success', 'warning', 'danger'] as const;
|
|
28
|
+
type BadgeVariant = typeof BADGE_VARIANTS[number];
|
|
29
|
+
|
|
30
|
+
type SharedBadgeProps = Omit<RegularBoxProps, 'as' | 'onClick'> & MarginSpacingProps;
|
|
31
|
+
export type BadgeProps = SharedBadgeProps & {
|
|
32
|
+
as?: Exclude<React.ElementType, 'a' | 'button'>;
|
|
33
|
+
size?: BadgeSize;
|
|
34
|
+
type?: SharedTextType;
|
|
35
|
+
variant?: BadgeVariant;
|
|
36
|
+
LeadingIcon?: IconComponent;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const badgeSizeStyle = {
|
|
40
|
+
regular: css`
|
|
41
|
+
padding: ${theme.space.space4} ${theme.space.space8};
|
|
42
|
+
border-radius: ${theme.radius.radius6};
|
|
43
|
+
`,
|
|
44
|
+
small: css`
|
|
45
|
+
height: 2rem;
|
|
46
|
+
padding: ${theme.space.space2} ${theme.space.space6};
|
|
47
|
+
border-radius: ${theme.radius.radius4};
|
|
48
|
+
`,
|
|
49
|
+
extra_small: css`
|
|
50
|
+
height: ${theme.space.space16};
|
|
51
|
+
padding: ${theme.space.space2} ${theme.space.space4};
|
|
52
|
+
border-radius: ${theme.radius.radius4};
|
|
53
|
+
`,
|
|
54
|
+
} satisfies Record<BadgeSize, FlattenSimpleInterpolation>;
|
|
55
|
+
|
|
56
|
+
const badgeVariantStyle = {
|
|
57
|
+
neutral: css`
|
|
58
|
+
color: ${theme.color.neutral.text};
|
|
59
|
+
fill: ${theme.color.neutral.text};
|
|
60
|
+
background: ${theme.color.neutral.background};
|
|
61
|
+
box-shadow: inset 0 0 0 1px ${theme.color.neutral.border};
|
|
62
|
+
`,
|
|
63
|
+
neutral_muted: css`
|
|
64
|
+
color: ${theme.color.neutral.text};
|
|
65
|
+
fill: ${theme.color.neutral.text};
|
|
66
|
+
background: ${theme.color.neutral.chipBackground};
|
|
67
|
+
`,
|
|
68
|
+
neutral_subtle: css`
|
|
69
|
+
color: ${theme.color.neutral.textSubtle};
|
|
70
|
+
fill: ${theme.color.neutral.textSubtle};
|
|
71
|
+
background: ${theme.color.neutral.backgroundSubtle};
|
|
72
|
+
`,
|
|
73
|
+
primary_black: css`
|
|
74
|
+
color: ${theme.color.primaryBlack.chipText};
|
|
75
|
+
fill: ${theme.color.primaryBlack.chipText};
|
|
76
|
+
background: ${theme.color.primaryBlack.background};
|
|
77
|
+
`,
|
|
78
|
+
primary_blue: css`
|
|
79
|
+
color: ${theme.color.primary.chipText};
|
|
80
|
+
fill: ${theme.color.primaryBlack.chipText};
|
|
81
|
+
background: ${theme.color.primary.background};
|
|
82
|
+
`,
|
|
83
|
+
success: css`
|
|
84
|
+
color: ${theme.color.success.chipText};
|
|
85
|
+
fill: ${theme.color.success.chipText};
|
|
86
|
+
background: ${theme.color.success.background};
|
|
87
|
+
`,
|
|
88
|
+
warning: css`
|
|
89
|
+
color: ${theme.color.warning.chipText};
|
|
90
|
+
fill: ${theme.color.warning.chipText};
|
|
91
|
+
background: ${theme.color.warning.background};
|
|
92
|
+
`,
|
|
93
|
+
danger: css`
|
|
94
|
+
color: ${theme.color.danger.chipText};
|
|
95
|
+
fill: ${theme.color.danger.chipText};
|
|
96
|
+
background: ${theme.color.danger.background};
|
|
97
|
+
`,
|
|
98
|
+
} satisfies Record<BadgeVariant, FlattenSimpleInterpolation>;
|
|
99
|
+
|
|
100
|
+
type StyledBadgeProps = WithTransientProps<
|
|
101
|
+
Required<Pick<BadgeProps, 'size' | 'variant'>>
|
|
102
|
+
>;
|
|
103
|
+
|
|
104
|
+
const StyledBadge = styled(Box)<StyledBadgeProps>`
|
|
105
|
+
${({ $size }) => badgeSizeStyle[$size]};
|
|
106
|
+
${({ $variant }) => badgeVariantStyle[$variant]};
|
|
107
|
+
|
|
108
|
+
/* Static styles */
|
|
109
|
+
width: fit-content;
|
|
110
|
+
border: none;
|
|
111
|
+
outline: none;
|
|
112
|
+
display: flex;
|
|
113
|
+
flex-direction: row;
|
|
114
|
+
justify-content: center;
|
|
115
|
+
align-items: center;
|
|
116
|
+
white-space: nowrap;
|
|
117
|
+
gap: ${theme.space.space4};
|
|
118
|
+
`;
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Component for displaying non-interactive chip descendant.
|
|
122
|
+
*/
|
|
123
|
+
export const Badge = forwardRef(
|
|
124
|
+
({
|
|
125
|
+
size = 'small',
|
|
126
|
+
type = 'body',
|
|
127
|
+
variant = 'neutral',
|
|
128
|
+
LeadingIcon,
|
|
129
|
+
children,
|
|
130
|
+
...props
|
|
131
|
+
}: BadgeProps,
|
|
132
|
+
ref,
|
|
133
|
+
) => {
|
|
134
|
+
return (
|
|
135
|
+
<StyledBadge
|
|
136
|
+
ref={ref}
|
|
137
|
+
$size={size}
|
|
138
|
+
$variant={variant}
|
|
139
|
+
{...props}
|
|
140
|
+
>
|
|
141
|
+
{LeadingIcon && <LeadingIcon size={BADGE_ICON_SIZES[size]} />}
|
|
142
|
+
{children && (<Text size={BADGE_TEXT_SIZES[size]} type={type} weight="medium">{children}</Text>)}
|
|
143
|
+
</StyledBadge>
|
|
144
|
+
);
|
|
145
|
+
},
|
|
146
|
+
);
|
|
147
|
+
|
|
148
|
+
Badge.displayName = 'Badge';
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import styled, { css } from 'styled-components';
|
|
3
|
+
|
|
4
|
+
import { theme } from '../design_system/theme.js';
|
|
5
|
+
|
|
6
|
+
const BANNER_GRADIENT_BACKGROUND_SVG = `<svg width="1200" height="148" viewBox="0 0 1200 148" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
7
|
+
<g clip-path="url(#clip0_2285_34756)">
|
|
8
|
+
<g filter="url(#filter0_f_2285_34756)">
|
|
9
|
+
<path d="M-39.7702 191.085C-55.0622 193.205 -68.8864 201.311 -78.2029 213.621C-87.5194 225.932 -91.5654 241.438 -89.4512 256.731L-55.0077 502.652L89.8852 173L-39.7702 191.085Z" fill="url(#paint0_linear_2285_34756)"/>
|
|
10
|
+
</g>
|
|
11
|
+
<g filter="url(#filter1_f_2285_34756)">
|
|
12
|
+
<path d="M1267.53 398.062L1253.99 209.002C1252.85 193.626 1245.67 179.327 1234.01 169.234C1222.36 159.14 1207.18 154.073 1191.8 155.14C1190.5 155.19 1189.2 155.331 1187.92 155.564L1132 163.289L1254.84 438.685C1264.05 427.236 1268.59 412.721 1267.53 398.062Z" fill="url(#paint1_linear_2285_34756)"/>
|
|
13
|
+
</g>
|
|
14
|
+
<g filter="url(#filter2_f_2285_34756)">
|
|
15
|
+
<path d="M561 29.7691C570.917 30.4746 580.956 29.5571 590.142 27.1057L801.075 -28.7862L700.682 -170L561 29.7691Z" fill="url(#paint2_linear_2285_34756)"/>
|
|
16
|
+
</g>
|
|
17
|
+
</g>
|
|
18
|
+
<defs>
|
|
19
|
+
<filter id="filter0_f_2285_34756" x="-170" y="93" width="339.885" height="489.652" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
|
20
|
+
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
|
21
|
+
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
|
22
|
+
<feGaussianBlur stdDeviation="40" result="effect1_foregroundBlur_2285_34756"/>
|
|
23
|
+
</filter>
|
|
24
|
+
<filter id="filter1_f_2285_34756" x="1052" y="75" width="295.683" height="443.686" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
|
25
|
+
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
|
26
|
+
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
|
27
|
+
<feGaussianBlur stdDeviation="40" result="effect1_foregroundBlur_2285_34756"/>
|
|
28
|
+
</filter>
|
|
29
|
+
<filter id="filter2_f_2285_34756" x="481" y="-250" width="400.074" height="360" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
|
30
|
+
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
|
31
|
+
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
|
32
|
+
<feGaussianBlur stdDeviation="40" result="effect1_foregroundBlur_2285_34756"/>
|
|
33
|
+
</filter>
|
|
34
|
+
<linearGradient id="paint0_linear_2285_34756" x1="-0.0574112" y1="173" x2="-0.0574112" y2="502.652" gradientUnits="userSpaceOnUse">
|
|
35
|
+
<stop stop-color="#00FF85"/>
|
|
36
|
+
<stop offset="1" stop-color="#00FF47" stop-opacity="0"/>
|
|
37
|
+
</linearGradient>
|
|
38
|
+
<linearGradient id="paint1_linear_2285_34756" x1="1146.02" y1="174.549" x2="1333.1" y2="293.915" gradientUnits="userSpaceOnUse">
|
|
39
|
+
<stop stop-color="#00FFF0"/>
|
|
40
|
+
<stop offset="1" stop-color="#1672EB"/>
|
|
41
|
+
</linearGradient>
|
|
42
|
+
<linearGradient id="paint2_linear_2285_34756" x1="681.037" y1="-170" x2="681.037" y2="30" gradientUnits="userSpaceOnUse">
|
|
43
|
+
<stop stop-color="#F5B315"/>
|
|
44
|
+
<stop offset="1" stop-color="#FF2CC4"/>
|
|
45
|
+
</linearGradient>
|
|
46
|
+
<clipPath id="clip0_2285_34756">
|
|
47
|
+
<rect width="1200" height="1791.08" rx="16" fill="white"/>
|
|
48
|
+
</clipPath>
|
|
49
|
+
</defs>
|
|
50
|
+
</svg>
|
|
51
|
+
`;
|
|
52
|
+
|
|
53
|
+
interface BannerProps {
|
|
54
|
+
background?: string,
|
|
55
|
+
useGradientBackground?: boolean,
|
|
56
|
+
width?: string,
|
|
57
|
+
className?: string,
|
|
58
|
+
children: React.ReactNode,
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const getBannerBackground = (background?: string, useGradientBackground?: boolean) => {
|
|
62
|
+
return css`
|
|
63
|
+
background-color: ${background || theme.color.neutral.backgroundSubtle};
|
|
64
|
+
${useGradientBackground && `
|
|
65
|
+
background-image: url("data:image/svg+xml,${encodeURIComponent(BANNER_GRADIENT_BACKGROUND_SVG)}");
|
|
66
|
+
background-position: center;
|
|
67
|
+
background-repeat: no-repeat;
|
|
68
|
+
background-size: cover;
|
|
69
|
+
`}
|
|
70
|
+
`;
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const StyledBanner = styled.div<{ $background?: string, $useGradientBackground?: boolean, width?: string }>`
|
|
74
|
+
width: ${(props) => props.width || '100%'};
|
|
75
|
+
padding: ${theme.space.space40} ${theme.space.space80};
|
|
76
|
+
border-radius: ${theme.radius.radius16};
|
|
77
|
+
|
|
78
|
+
${({ $background, $useGradientBackground }) => getBannerBackground($background, $useGradientBackground)};
|
|
79
|
+
`;
|
|
80
|
+
|
|
81
|
+
export const Banner: React.FC<BannerProps> = ({
|
|
82
|
+
useGradientBackground = true,
|
|
83
|
+
background,
|
|
84
|
+
children,
|
|
85
|
+
...otherProps
|
|
86
|
+
}) => (
|
|
87
|
+
<StyledBanner
|
|
88
|
+
$background={background}
|
|
89
|
+
$useGradientBackground={useGradientBackground}
|
|
90
|
+
{...otherProps}
|
|
91
|
+
>
|
|
92
|
+
{children}
|
|
93
|
+
</StyledBanner>
|
|
94
|
+
);
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import styled from 'styled-components';
|
|
3
|
+
|
|
4
|
+
import { ArrowRightIcon } from '@apify/ui-icons';
|
|
5
|
+
|
|
6
|
+
import { theme } from '../design_system/theme.js';
|
|
7
|
+
|
|
8
|
+
const classNames = {
|
|
9
|
+
IMAGE_WRAPPER: 'ImageWrapper',
|
|
10
|
+
TEXT: 'Text',
|
|
11
|
+
READ_POST: 'ReadPost',
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const BlogArticleWrapper = styled.div`
|
|
15
|
+
display: flex;
|
|
16
|
+
flex-direction: column;
|
|
17
|
+
|
|
18
|
+
&:hover {
|
|
19
|
+
.${classNames.READ_POST} {
|
|
20
|
+
color: ${theme.color.primary.action};
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.${classNames.IMAGE_WRAPPER} {
|
|
25
|
+
margin-bottom: ${theme.space.space16};
|
|
26
|
+
border-radius: ${theme.radius.radius12};
|
|
27
|
+
border: 1px solid ${theme.color.neutral.backgroundSubtle};
|
|
28
|
+
aspect-ratio: 16/9;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.${classNames.TEXT} {
|
|
32
|
+
padding-bottom: ${theme.space.space16};
|
|
33
|
+
color: ${theme.color.neutral.text};
|
|
34
|
+
${theme.typography.shared.mobile.titleL}
|
|
35
|
+
|
|
36
|
+
@media (min-width: ${theme.layout.tablet}) {
|
|
37
|
+
${theme.typography.shared.tablet.titleL}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@media (min-width: ${theme.layout.desktop}) {
|
|
41
|
+
${theme.typography.shared.desktop.titleL}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.${classNames.READ_POST} {
|
|
46
|
+
display: flex;
|
|
47
|
+
align-items: center;
|
|
48
|
+
gap: ${theme.space.space4};
|
|
49
|
+
color: ${theme.color.neutral.textMuted};
|
|
50
|
+
${theme.typography.shared.mobile.titleM}
|
|
51
|
+
|
|
52
|
+
@media (min-width: ${theme.layout.tablet}) {
|
|
53
|
+
${theme.typography.shared.tablet.titleM}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
@media (min-width: ${theme.layout.desktop}) {
|
|
57
|
+
${theme.typography.shared.desktop.titleM}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
svg {
|
|
62
|
+
transition: margin-right .5s;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
&:hover svg {
|
|
66
|
+
margin-right: ${theme.space.space4};
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
`;
|
|
70
|
+
|
|
71
|
+
interface BlogArticleProps {
|
|
72
|
+
imageNode: React.ReactNode;
|
|
73
|
+
title: string;
|
|
74
|
+
ctaTitle?: string;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function BlogArticle({ imageNode, title, ctaTitle = 'Read more' }: BlogArticleProps) {
|
|
78
|
+
return (
|
|
79
|
+
<BlogArticleWrapper>
|
|
80
|
+
<div className={classNames.IMAGE_WRAPPER}>{imageNode}</div>
|
|
81
|
+
<div className={classNames.TEXT}>{title}</div>
|
|
82
|
+
<div className={classNames.READ_POST}>{ctaTitle}<ArrowRightIcon size="16" title="" titleId="" /></div>
|
|
83
|
+
</BlogArticleWrapper>
|
|
84
|
+
);
|
|
85
|
+
}
|