Skip to content

Commit 8d021b6

Browse files
authored
docs: revamp library website (#166)
* feat: default theme use dark. * chore: update logo * feat: Logo style adjust. * docs: update * chore: add devDependencies lottie-web for site * feat: site header * feat: site main banner * feat: site main banner * fix: rtl style * chore: update bun.lockb * feat: design banner * refactor: add Container for homepage * feat: design guide * feat: Introduction * chore: delete unuse file * chore: delete unuse file * feat: Components Introduction * feat: Scene Introduction * fix: lint * chore: update bun.lockb and update test * fix: site build * docs: adjust the cn desc * docs: mod font-family * refactor: use svg instead png in lottie.json * refactor: useLottie to manage lottie lazyload * refactor: index load * refactor: css * refactor: Conversations Style * feat: playground * refactor: index page always use dark theme * refactor: fix style and replace img * fix: index page theme * feat: design spec * feat: design spec * refactor: navigate * chore: remove code about antd-with-locales issues #107 * feat: design freamwork * feat: design banner lottie * refactor: dasign guide lottie * chore: delete docs * docs: update readme
1 parent 7f19776 commit 8d021b6

File tree

115 files changed

+7483
-2280
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

115 files changed

+7483
-2280
lines changed

.dumi/hooks/useLottie.ts

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import lottie, { type AnimationConfig, type AnimationItem } from 'lottie-web';
2+
import React from 'react';
3+
4+
interface UseLottieOptions extends Omit<AnimationConfig, 'container' | 'renderer'> {
5+
renderer?: 'svg' | 'canvas' | 'html';
6+
lazyLoad?: boolean;
7+
disabled?: boolean;
8+
rootMargin?: string;
9+
path?: string;
10+
}
11+
12+
const useLottie = (options: UseLottieOptions) => {
13+
const { lazyLoad = true, rootMargin = '200px', disabled = false, ...lottieOptions } = options;
14+
const stableLottieOptions = React.useMemo(() => lottieOptions, []);
15+
16+
const containerRef = React.useRef<HTMLDivElement>(null);
17+
const [isIntersected, setIsIntersected] = React.useState(!lazyLoad);
18+
const [animationInstance, setAnimationInstance] = React.useState<AnimationItem | null>(null);
19+
20+
React.useEffect(() => {
21+
if (disabled) return;
22+
23+
let animation: AnimationItem | undefined;
24+
25+
if (!animationInstance) {
26+
if (!lazyLoad || isIntersected) {
27+
if (containerRef.current) {
28+
animation = lottie.loadAnimation({
29+
container: containerRef.current,
30+
...stableLottieOptions,
31+
});
32+
33+
setAnimationInstance(animation);
34+
}
35+
}
36+
} else {
37+
return () => {
38+
if (animation) {
39+
animation.destroy();
40+
setAnimationInstance(null);
41+
}
42+
};
43+
}
44+
}, [isIntersected, lazyLoad, stableLottieOptions, animationInstance, disabled]);
45+
46+
React.useEffect(() => {
47+
if (disabled) return;
48+
49+
if (lazyLoad) {
50+
const observer = new IntersectionObserver(
51+
([entry]) => {
52+
if (entry.isIntersecting) {
53+
setIsIntersected(true);
54+
}
55+
},
56+
{ root: null, rootMargin, threshold: 0 },
57+
);
58+
59+
if (containerRef.current) {
60+
observer.observe(containerRef.current);
61+
}
62+
63+
return () => {
64+
if (containerRef.current) {
65+
observer.unobserve(containerRef.current);
66+
}
67+
};
68+
}
69+
}, [lazyLoad, rootMargin, disabled]);
70+
71+
return [
72+
containerRef,
73+
animationInstance,
74+
{
75+
isIntersected,
76+
},
77+
] as const;
78+
};
79+
80+
export default useLottie;

.dumi/hooks/useScrollY.ts

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import React from 'react';
2+
3+
const getSnapshot = () => window.scrollY;
4+
5+
const getServerSnapshot = () => 0;
6+
7+
const useScrollY = () => {
8+
const [scrollYDirection, setScrollYDirection] = React.useState<'down' | 'up'>();
9+
10+
const subscribe = React.useCallback((callback: () => void) => {
11+
let ticking = false;
12+
let scrollY = window.scrollY;
13+
14+
const handleScroll = () => {
15+
if (!ticking) {
16+
requestAnimationFrame(() => {
17+
callback();
18+
setScrollYDirection(scrollY > window.scrollY ? 'up' : 'down');
19+
scrollY = window.scrollY;
20+
ticking = false;
21+
});
22+
23+
ticking = true;
24+
}
25+
};
26+
27+
window.addEventListener('scroll', handleScroll);
28+
29+
return () => window.removeEventListener('scroll', handleScroll);
30+
}, []);
31+
32+
const scrollY = React.useSyncExternalStore<number>(subscribe, getSnapshot, getServerSnapshot);
33+
34+
return {
35+
scrollY,
36+
scrollYDirection,
37+
};
38+
};
39+
40+
export default useScrollY;
+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import { createStyles } from 'antd-style';
2+
import classnames from 'classnames';
3+
import React from 'react';
4+
5+
const useStyle = createStyles(({ token, css }) => {
6+
return {
7+
container: css`
8+
width: 100%;
9+
margin: 0 auto;
10+
max-width: ${token.pcMaxWidth - token.pcContainerMargin * 2}px;
11+
font-family: AlibabaPuHuiTi, ${token.fontFamily}, sans-serif;
12+
13+
@media only screen and (max-width: ${token.pcMaxWidth}px) {
14+
max-width: calc(100vw - ${token.pcContainerMargin * 2}px);
15+
}
16+
17+
@media only screen and (max-width: ${token.mobileMaxWidth}px) {
18+
max-width: calc(100vw - ${token.marginLG * 2}px);
19+
}
20+
`,
21+
title: css`
22+
font-size: 48px;
23+
color: #fff;
24+
text-align: center;
25+
padding-bottom: ${token.padding}px;
26+
`,
27+
desc: css`
28+
color: ${token.colorTextSecondary};
29+
max-width: 880px !important;
30+
margin: 0 auto;
31+
text-align: center;
32+
padding-bottom: ${token.padding}px;
33+
`,
34+
};
35+
});
36+
37+
export interface ContainerProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'title'> {
38+
children?: React.ReactNode;
39+
title?: React.ReactNode;
40+
desc?: React.ReactNode;
41+
}
42+
43+
const Container: React.FC<ContainerProps> = (props) => {
44+
const { styles } = useStyle();
45+
return (
46+
<div
47+
className={classnames(styles.container, props.className)}
48+
style={props.style}
49+
onClick={props.onClick}
50+
>
51+
{props.title && <h2 className={styles.title}>{props.title}</h2>}
52+
{props.desc && <p className={styles.desc}>{props.desc}</p>}
53+
{props.children}
54+
</div>
55+
);
56+
};
57+
58+
export default Container;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
import { XProvider } from '@ant-design/x';
2+
import { createStyles } from 'antd-style';
3+
import React from 'react';
4+
5+
export const useCustomizationBgStyle = createStyles(({ token, css }) => {
6+
return {
7+
background: css`
8+
background: linear-gradient(135deg, #ffffff26 14%, #ffffff0d 59%) !important;
9+
overflow: hidden;
10+
position: auto;
11+
12+
&::after {
13+
content: '';
14+
width: 100%;
15+
height: 100%;
16+
box-sizing: border-box;
17+
border-radius: inherit;
18+
pointer-events: none;
19+
position: absolute;
20+
top: 0;
21+
bottom: 0;
22+
inset-inline-start: 0;
23+
inset-inline-end: 0;
24+
padding: ${token.lineWidth}px;
25+
background: linear-gradient(180deg, #ffffff26 0%, #ffffff00 100%);
26+
mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
27+
mask-composite: exclude;
28+
};
29+
`,
30+
};
31+
});
32+
33+
export const LOCALES = {
34+
cn: {
35+
greeting: '你好, 我是全新 AI 产品创造助手',
36+
greeting_short: '你好, 我是 Ant Design X',
37+
description: '基于 Ant Design 的 AGI 产品智能解决方案, 创造更美好的智能视界',
38+
description_short: '基于 Ant Design 的 AGI 产品智能解决方案, 创造更美好的智能视界',
39+
help_text: '我可以帮您: ',
40+
41+
conversations_group: '最近对话',
42+
send_placeholder: '输入 / 获取建议',
43+
44+
hot_question: '热门话题',
45+
46+
question1: 'Ant Design X 全新升级了什么? ',
47+
question2: 'Ant Design X 推出全新 RICH 设计规范 ',
48+
question3: 'Ant Design X 组件资产有哪些? ',
49+
question4: '快来了解全新AI时代的设计范式! ',
50+
51+
design_guide: 'Rich 设计指南',
52+
53+
empathy: 'AI 理解用户诉求并解决',
54+
persona: 'AI 对外的人设及形象',
55+
conversation: 'AI 如何表达用户能听懂',
56+
interface: 'AI 兼顾“chat” & “do” 行为',
57+
},
58+
en: {
59+
greeting: 'Hello, I am your AI Product Design Assistant',
60+
greeting_short: 'Hello, I am Ant Design X',
61+
description:
62+
"Powered by Ant Design's AGI solution to enhance intelligent, aesthetic visual experiences",
63+
description_short: 'Aesthetic visual experiences',
64+
help_text: 'I can assist you with:',
65+
66+
conversations_group: 'History',
67+
send_placeholder: 'Type / to get suggestions',
68+
69+
hot_question: 'Hot Topics',
70+
71+
question1: 'What are the new upgrades in X?',
72+
question2: 'X has introduced the new RICH design guide.',
73+
question3: 'What are the component assets in X?',
74+
question4: 'Discover new design for the AI!',
75+
76+
design_guide: 'Rich Design Guidelines',
77+
78+
empathy: 'AI that understands and addresses user needs',
79+
persona: "Defining AI's persona and presentation",
80+
conversation: 'Ensuring AI communicates clearly',
81+
interface: "Balancing 'chat' & 'do' functionalities",
82+
},
83+
};
84+
85+
export const DESIGN_STAGE_COLOR = {
86+
AWAKE: {
87+
START: '#6fb3e2',
88+
END: '#6c57ff',
89+
},
90+
EXPRESS: {
91+
START: '#6dd6f5',
92+
END: '#108c44',
93+
},
94+
CONFIRM: {
95+
START: '#ba2cb8',
96+
END: '#6c37e8',
97+
},
98+
FEEDBACK: {
99+
START: '#f7c348',
100+
END: '#f75972',
101+
},
102+
COMMON: {
103+
START: '#d857ff',
104+
END: '#8594ff',
105+
},
106+
};
107+
108+
const useStyle = createStyles(({ token, css }) => {
109+
const borderRadius = 20;
110+
111+
return {
112+
welcome: css`
113+
display: flex;
114+
align-items: center;
115+
gap: ${token.paddingXS}px;
116+
position: relative;
117+
box-sizing: border-box;
118+
border-radius: ${borderRadius}px;
119+
padding: 18px;
120+
121+
.ant-welcome-title {
122+
font-size: ${token.fontSize}px;
123+
font-weight: 400;
124+
}
125+
126+
.ant-welcome-description {
127+
font-size: ${token.fontSizeSM - 1}px;
128+
opacity: 0.65;
129+
}
130+
`,
131+
prompts: css`
132+
border-radius: ${borderRadius}px !important;
133+
position: relative;
134+
135+
.ant-prompts-desc {
136+
font-size: ${token.fontSizeSM}px !important;
137+
opacity: 0.9;
138+
}
139+
.ant-prompts-label {
140+
font-size: ${token.fontSize}px !important;
141+
font-weight: 400;
142+
}
143+
144+
.ant-prompts-title {
145+
font-size: ${token.fontSize}px !important;
146+
padding-bottom: ${token.paddingXS}px;
147+
}
148+
`,
149+
sender: css`
150+
border-radius: ${borderRadius * 2}px;
151+
height: 44px;
152+
display: flex;
153+
align-items: center;
154+
155+
.ant-sender-content {
156+
padding: 0px ${token.paddingSM}px;
157+
}
158+
`,
159+
conversations: css`
160+
padding: ${token.padding}px;
161+
padding-top: 0;
162+
border-radius: ${borderRadius}px;
163+
position: relative;
164+
`,
165+
suggestion: css`
166+
border-radius: ${borderRadius}px;
167+
position: relative;
168+
`,
169+
};
170+
});
171+
172+
const CustomizationProvider: React.FC<{ children: React.ReactNode }> = (props) => {
173+
const { styles } = useStyle();
174+
175+
return (
176+
<XProvider
177+
conversations={{
178+
className: styles.conversations,
179+
}}
180+
sender={{
181+
className: styles.sender,
182+
}}
183+
prompts={{
184+
className: styles.prompts,
185+
}}
186+
welcome={{
187+
className: styles.welcome,
188+
}}
189+
suggestion={{
190+
className: styles.suggestion,
191+
}}
192+
>
193+
{props.children}
194+
</XProvider>
195+
);
196+
};
197+
198+
export default CustomizationProvider;

0 commit comments

Comments
 (0)