Skip to content

Commit

Permalink
docs: revamp library website (#166)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
YumoImer authored Nov 21, 2024
1 parent 7f19776 commit 8d021b6
Show file tree
Hide file tree
Showing 115 changed files with 7,483 additions and 2,280 deletions.
80 changes: 80 additions & 0 deletions .dumi/hooks/useLottie.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import lottie, { type AnimationConfig, type AnimationItem } from 'lottie-web';
import React from 'react';

interface UseLottieOptions extends Omit<AnimationConfig, 'container' | 'renderer'> {
renderer?: 'svg' | 'canvas' | 'html';
lazyLoad?: boolean;
disabled?: boolean;
rootMargin?: string;
path?: string;
}

const useLottie = (options: UseLottieOptions) => {
const { lazyLoad = true, rootMargin = '200px', disabled = false, ...lottieOptions } = options;
const stableLottieOptions = React.useMemo(() => lottieOptions, []);

const containerRef = React.useRef<HTMLDivElement>(null);
const [isIntersected, setIsIntersected] = React.useState(!lazyLoad);
const [animationInstance, setAnimationInstance] = React.useState<AnimationItem | null>(null);

React.useEffect(() => {
if (disabled) return;

let animation: AnimationItem | undefined;

if (!animationInstance) {
if (!lazyLoad || isIntersected) {
if (containerRef.current) {
animation = lottie.loadAnimation({
container: containerRef.current,
...stableLottieOptions,
});

setAnimationInstance(animation);
}
}
} else {
return () => {
if (animation) {
animation.destroy();
setAnimationInstance(null);
}
};
}
}, [isIntersected, lazyLoad, stableLottieOptions, animationInstance, disabled]);

React.useEffect(() => {
if (disabled) return;

if (lazyLoad) {
const observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) {
setIsIntersected(true);
}
},
{ root: null, rootMargin, threshold: 0 },
);

if (containerRef.current) {
observer.observe(containerRef.current);
}

return () => {
if (containerRef.current) {
observer.unobserve(containerRef.current);
}
};
}
}, [lazyLoad, rootMargin, disabled]);

return [
containerRef,
animationInstance,
{
isIntersected,
},
] as const;
};

export default useLottie;
40 changes: 40 additions & 0 deletions .dumi/hooks/useScrollY.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React from 'react';

const getSnapshot = () => window.scrollY;

const getServerSnapshot = () => 0;

const useScrollY = () => {
const [scrollYDirection, setScrollYDirection] = React.useState<'down' | 'up'>();

const subscribe = React.useCallback((callback: () => void) => {
let ticking = false;
let scrollY = window.scrollY;

const handleScroll = () => {
if (!ticking) {
requestAnimationFrame(() => {
callback();
setScrollYDirection(scrollY > window.scrollY ? 'up' : 'down');
scrollY = window.scrollY;
ticking = false;
});

ticking = true;
}
};

window.addEventListener('scroll', handleScroll);

return () => window.removeEventListener('scroll', handleScroll);
}, []);

const scrollY = React.useSyncExternalStore<number>(subscribe, getSnapshot, getServerSnapshot);

return {
scrollY,
scrollYDirection,
};
};

export default useScrollY;
58 changes: 58 additions & 0 deletions .dumi/pages/index/common/Container.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { createStyles } from 'antd-style';
import classnames from 'classnames';
import React from 'react';

const useStyle = createStyles(({ token, css }) => {
return {
container: css`
width: 100%;
margin: 0 auto;
max-width: ${token.pcMaxWidth - token.pcContainerMargin * 2}px;
font-family: AlibabaPuHuiTi, ${token.fontFamily}, sans-serif;
@media only screen and (max-width: ${token.pcMaxWidth}px) {
max-width: calc(100vw - ${token.pcContainerMargin * 2}px);
}
@media only screen and (max-width: ${token.mobileMaxWidth}px) {
max-width: calc(100vw - ${token.marginLG * 2}px);
}
`,
title: css`
font-size: 48px;
color: #fff;
text-align: center;
padding-bottom: ${token.padding}px;
`,
desc: css`
color: ${token.colorTextSecondary};
max-width: 880px !important;
margin: 0 auto;
text-align: center;
padding-bottom: ${token.padding}px;
`,
};
});

export interface ContainerProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'title'> {
children?: React.ReactNode;
title?: React.ReactNode;
desc?: React.ReactNode;
}

const Container: React.FC<ContainerProps> = (props) => {
const { styles } = useStyle();
return (
<div
className={classnames(styles.container, props.className)}
style={props.style}
onClick={props.onClick}
>
{props.title && <h2 className={styles.title}>{props.title}</h2>}
{props.desc && <p className={styles.desc}>{props.desc}</p>}
{props.children}
</div>
);
};

export default Container;
198 changes: 198 additions & 0 deletions .dumi/pages/index/common/CustomizationProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
import { XProvider } from '@ant-design/x';
import { createStyles } from 'antd-style';
import React from 'react';

export const useCustomizationBgStyle = createStyles(({ token, css }) => {
return {
background: css`
background: linear-gradient(135deg, #ffffff26 14%, #ffffff0d 59%) !important;
overflow: hidden;
position: auto;
&::after {
content: '';
width: 100%;
height: 100%;
box-sizing: border-box;
border-radius: inherit;
pointer-events: none;
position: absolute;
top: 0;
bottom: 0;
inset-inline-start: 0;
inset-inline-end: 0;
padding: ${token.lineWidth}px;
background: linear-gradient(180deg, #ffffff26 0%, #ffffff00 100%);
mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
mask-composite: exclude;
};
`,
};
});

export const LOCALES = {
cn: {
greeting: '你好, 我是全新 AI 产品创造助手',
greeting_short: '你好, 我是 Ant Design X',
description: '基于 Ant Design 的 AGI 产品智能解决方案, 创造更美好的智能视界',
description_short: '基于 Ant Design 的 AGI 产品智能解决方案, 创造更美好的智能视界',
help_text: '我可以帮您: ',

conversations_group: '最近对话',
send_placeholder: '输入 / 获取建议',

hot_question: '热门话题',

question1: 'Ant Design X 全新升级了什么? ',
question2: 'Ant Design X 推出全新 RICH 设计规范 ',
question3: 'Ant Design X 组件资产有哪些? ',
question4: '快来了解全新AI时代的设计范式! ',

design_guide: 'Rich 设计指南',

empathy: 'AI 理解用户诉求并解决',
persona: 'AI 对外的人设及形象',
conversation: 'AI 如何表达用户能听懂',
interface: 'AI 兼顾“chat” & “do” 行为',
},
en: {
greeting: 'Hello, I am your AI Product Design Assistant',
greeting_short: 'Hello, I am Ant Design X',
description:
"Powered by Ant Design's AGI solution to enhance intelligent, aesthetic visual experiences",
description_short: 'Aesthetic visual experiences',
help_text: 'I can assist you with:',

conversations_group: 'History',
send_placeholder: 'Type / to get suggestions',

hot_question: 'Hot Topics',

question1: 'What are the new upgrades in X?',
question2: 'X has introduced the new RICH design guide.',
question3: 'What are the component assets in X?',
question4: 'Discover new design for the AI!',

design_guide: 'Rich Design Guidelines',

empathy: 'AI that understands and addresses user needs',
persona: "Defining AI's persona and presentation",
conversation: 'Ensuring AI communicates clearly',
interface: "Balancing 'chat' & 'do' functionalities",
},
};

export const DESIGN_STAGE_COLOR = {
AWAKE: {
START: '#6fb3e2',
END: '#6c57ff',
},
EXPRESS: {
START: '#6dd6f5',
END: '#108c44',
},
CONFIRM: {
START: '#ba2cb8',
END: '#6c37e8',
},
FEEDBACK: {
START: '#f7c348',
END: '#f75972',
},
COMMON: {
START: '#d857ff',
END: '#8594ff',
},
};

const useStyle = createStyles(({ token, css }) => {
const borderRadius = 20;

return {
welcome: css`
display: flex;
align-items: center;
gap: ${token.paddingXS}px;
position: relative;
box-sizing: border-box;
border-radius: ${borderRadius}px;
padding: 18px;
.ant-welcome-title {
font-size: ${token.fontSize}px;
font-weight: 400;
}
.ant-welcome-description {
font-size: ${token.fontSizeSM - 1}px;
opacity: 0.65;
}
`,
prompts: css`
border-radius: ${borderRadius}px !important;
position: relative;
.ant-prompts-desc {
font-size: ${token.fontSizeSM}px !important;
opacity: 0.9;
}
.ant-prompts-label {
font-size: ${token.fontSize}px !important;
font-weight: 400;
}
.ant-prompts-title {
font-size: ${token.fontSize}px !important;
padding-bottom: ${token.paddingXS}px;
}
`,
sender: css`
border-radius: ${borderRadius * 2}px;
height: 44px;
display: flex;
align-items: center;
.ant-sender-content {
padding: 0px ${token.paddingSM}px;
}
`,
conversations: css`
padding: ${token.padding}px;
padding-top: 0;
border-radius: ${borderRadius}px;
position: relative;
`,
suggestion: css`
border-radius: ${borderRadius}px;
position: relative;
`,
};
});

const CustomizationProvider: React.FC<{ children: React.ReactNode }> = (props) => {
const { styles } = useStyle();

return (
<XProvider
conversations={{
className: styles.conversations,
}}
sender={{
className: styles.sender,
}}
prompts={{
className: styles.prompts,
}}
welcome={{
className: styles.welcome,
}}
suggestion={{
className: styles.suggestion,
}}
>
{props.children}
</XProvider>
);
};

export default CustomizationProvider;
Loading

0 comments on commit 8d021b6

Please sign in to comment.