-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* 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
Showing
115 changed files
with
7,483 additions
and
2,280 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
Oops, something went wrong.