Adapt to the mobile mode of the new official website (#39043)

* feat: add basic css for title
feat: add basic Carousel structure
feat: modify some card with mobile mode
feat: style change for theme
feat: Extract public styles and improve some styles
fix: Fix code loss caused by handling conflicts

* feat: change the theme to carousel with image
This commit is contained in:
PCCCCCCC 2022-12-11 20:39:46 +08:00 committed by GitHub
parent 5552571131
commit 53470fc476
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 512 additions and 193 deletions

View File

@ -1,10 +1,13 @@
import * as React from 'react'; import * as React from 'react';
import { Button, Space, Typography } from 'antd'; import { Button, Space, Typography } from 'antd';
import { Link, useLocation } from 'dumi'; import { Link, useLocation } from 'dumi';
import { css } from '@emotion/react';
import useLocale from '../../../hooks/useLocale'; import useLocale from '../../../hooks/useLocale';
import useSiteToken from '../../../hooks/useSiteToken'; import useSiteToken from '../../../hooks/useSiteToken';
import { GroupMask } from './Group'; import { GroupMask } from './Group';
import * as utils from '../../../theme/utils'; import * as utils from '../../../theme/utils';
import SiteContext from './SiteContext';
import topicImage from './images/topic.png';
const locales = { const locales = {
cn: { cn: {
@ -20,6 +23,35 @@ const locales = {
}, },
}; };
const useStyle = () => {
const { token } = useSiteToken();
const { isMobile } = React.useContext(SiteContext);
return {
titleBase: css`
h1& {
font-family: AliPuHui, ${token.fontFamily};
}
`,
title: isMobile
? css`
h1& {
margin-bottom: ${token.margin}px;
font-weight: normal;
font-size: ${token.fontSizeHeading1 + 2}px;
line-height: ${token.lineHeightHeading2};
}
`
: css`
h1& {
margin-bottom: ${token.marginMD}px;
font-weight: 900;
font-size: 68px;
}
`,
};
};
export interface BannerProps { export interface BannerProps {
children?: React.ReactNode; children?: React.ReactNode;
} }
@ -28,12 +60,17 @@ export default function Banner({ children }: BannerProps) {
const [locale] = useLocale(locales); const [locale] = useLocale(locales);
const { pathname, search } = useLocation(); const { pathname, search } = useLocation();
const { token } = useSiteToken(); const { token } = useSiteToken();
const styles = useStyle();
const { isMobile } = React.useContext(SiteContext);
const isZhCN = utils.isZhCN(pathname); const isZhCN = utils.isZhCN(pathname);
return ( return (
<> <>
{/* Banner Placeholder Motion */} {/* Banner Placeholder Motion */}
{isMobile ? (
<img src={topicImage} alt="" style={{ width: '100%' }} />
) : (
<div <div
style={{ style={{
height: 320, height: 320,
@ -75,6 +112,7 @@ export default function Banner({ children }: BannerProps) {
}} }}
/> />
</div> </div>
)}
{/* Logo */} {/* Logo */}
<div style={{ position: 'relative', background: '#fff' }}> <div style={{ position: 'relative', background: '#fff' }}>
@ -94,34 +132,26 @@ export default function Banner({ children }: BannerProps) {
> >
{/* Image Left Top */} {/* Image Left Top */}
<img <img
style={{ position: 'absolute', left: 0, top: 0, width: 240 }} style={{ position: 'absolute', left: isMobile ? -120 : 0, top: 0, width: 240 }}
src="https://gw.alipayobjects.com/zos/bmw-prod/49f963db-b2a8-4f15-857a-270d771a1204.svg" src="https://gw.alipayobjects.com/zos/bmw-prod/49f963db-b2a8-4f15-857a-270d771a1204.svg"
alt="bg" alt="bg"
/> />
{/* Image Left Top */} {/* Image Right Top */}
<img <img
style={{ position: 'absolute', right: 120, top: 0, width: 240 }} style={{ position: 'absolute', right: isMobile ? 0 : 120, top: 0, width: 240 }}
src="https://gw.alipayobjects.com/zos/bmw-prod/e152223c-bcae-4913-8938-54fda9efe330.svg" src="https://gw.alipayobjects.com/zos/bmw-prod/e152223c-bcae-4913-8938-54fda9efe330.svg"
alt="bg" alt="bg"
/> />
<Typography.Title <Typography.Title level={1} css={[styles.titleBase, styles.title]}>
level={1}
style={{
fontFamily: `AliPuHui, ${token.fontFamily}`,
fontSize: token.fontSizes[9],
lineHeight: token.lineHeights[9],
fontWeight: 900,
marginBottom: token.marginMD,
}}
>
Ant Design 5.0 Ant Design 5.0
</Typography.Title> </Typography.Title>
<Typography.Paragraph <Typography.Paragraph
style={{ style={{
fontSize: token.fontSizeHeading5, fontSize: isMobile ? token.fontSizeHeading5 - 2 : token.fontSizeHeading5,
lineHeight: token.lineHeightHeading5, lineHeight: isMobile ? token.lineHeightSM : token.lineHeightHeading5,
marginBottom: token.marginMD * 2, marginBottom: token.marginMD * 2,
padding: isMobile ? `0 ${token.paddingLG + 2}px` : 0,
}} }}
> >
<div>{locale.slogan}</div> <div>{locale.slogan}</div>

View File

@ -1,75 +1,122 @@
import * as React from 'react'; import * as React from 'react';
import { Skeleton, Typography } from 'antd'; import { Typography, Skeleton, Carousel } from 'antd';
import type { SerializedStyles } from '@emotion/react';
import { css } from '@emotion/react'; import { css } from '@emotion/react';
import type { Extra, Icon } from './util'; import type { Extra, Icon } from './util';
import useSiteToken from '../../../hooks/useSiteToken'; import useSiteToken from '../../../hooks/useSiteToken';
import SiteContext from './SiteContext';
import { useCarouselStyle } from './util';
const useStyle = () => { const useStyle = () => {
const { token } = useSiteToken(); const { token } = useSiteToken();
const { carousel } = useCarouselStyle();
return { return {
card: css` itemBase: css`
border: ${token.lineWidth}px solid ${token.colorBorderSecondary};
border-radius: ${token.borderRadiusLG}px;
padding-block: ${token.paddingMD}px;
padding-inline: ${token.paddingLG}px;
flex: 1 1 0;
width: 33%;
display: flex; display: flex;
flex: 1 1 0;
flex-direction: column; flex-direction: column;
align-items: stretch; align-items: stretch;
text-decoration: none; text-decoration: none;
transition: all ${token.motionDurationSlow};
background: ${token.colorBgContainer}; background: ${token.colorBgContainer};
border: ${token.lineWidth}px solid ${token.colorBorderSecondary};
border-radius: ${token.borderRadiusLG}px;
transition: all ${token.motionDurationSlow};
padding-block: ${token.paddingMD}px;
padding-inline: ${token.paddingLG}px;
`,
cardItem: css`
width: 33%;
&:hover { &:hover {
box-shadow: ${token.boxShadowCard}; box-shadow: ${token.boxShadowCard};
} }
`, `,
sliderItem: css`
margin: 0 ${token.margin}px;
text-align: start;
`,
container: css`
display: flex;
max-width: 1208px;
margin-inline: auto;
box-sizing: border-box;
padding-inline: ${token.marginXXL}px;
column-gap: ${token.paddingMD * 2}px;
align-items: stretch;
text-align: start;
`,
carousel,
}; };
}; };
interface RecommendItemProps {
extra: Extra;
index: number;
icons: Icon[];
itemCss: SerializedStyles;
}
const RecommendItem = ({ extra, index, icons, itemCss }: RecommendItemProps) => {
const style = useStyle();
const { token } = useSiteToken();
if (!extra) {
return <Skeleton key={index} />;
}
const icon = icons.find((i) => i.name === extra.source);
return (
<a key={extra?.title} href={extra.href} target="_blank" css={[style.itemBase, itemCss]} rel="noreferrer">
<Typography.Title level={5}>{extra?.title}</Typography.Title>
<Typography.Paragraph type="secondary" style={{ flex: 'auto' }}>
{extra.description}
</Typography.Paragraph>
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
<Typography.Text>{extra.date}</Typography.Text>
{icon && <img src={icon.href} style={{ height: token.fontSize }} alt="banner"/>}
</div>
</a>
);
};
export interface BannerRecommendsProps { export interface BannerRecommendsProps {
extras?: Extra[]; extras?: Extra[];
icons?: Icon[]; icons?: Icon[];
} }
export default function BannerRecommends({ extras = [], icons = [] }: BannerRecommendsProps) { export default function BannerRecommends({ extras = [], icons = [] }: BannerRecommendsProps) {
const style = useStyle(); const styles = useStyle();
const { isMobile } = React.useContext(SiteContext);
const first3 = extras.length === 0 ? Array(3).fill(null) : extras.slice(0, 3); const first3 = extras.length === 0 ? Array(3).fill(null) : extras.slice(0, 3);
const { token } = useSiteToken();
return ( return (
<div <div>
style={{ {isMobile ? (
maxWidth: 1208, <Carousel css={styles.carousel}>
marginInline: 'auto', {first3.map((extra, index) => (
boxSizing: 'border-box', <div key={index}>
paddingInline: token.marginXXL, <RecommendItem
display: 'flex', extra={extra}
columnGap: token.paddingMD * 2, index={index}
alignItems: 'stretch', icons={icons}
textAlign: 'start', itemCss={styles.sliderItem}
}} />
>
{first3.map((extra, index) => {
if (!extra) {
return <Skeleton key={index} />;
}
const icon = icons.find((i) => i.name === extra.source);
return (
<a key={extra?.title} href={extra.href} target="_blank" css={style.card} rel="noreferrer">
<Typography.Title level={5}>{extra?.title}</Typography.Title>
<Typography.Paragraph type="secondary" style={{ flex: 'auto' }}>
{extra.description}
</Typography.Paragraph>
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
<Typography.Text>{extra.date}</Typography.Text>
{icon && <img src={icon.href} style={{ height: token.fontSize }} alt="banner" />}
</div> </div>
</a> ))}
); </Carousel>
})} ) : (
<div css={styles.container}>
{first3.map((extra, index) => (
<RecommendItem
extra={extra}
index={index}
icons={icons}
itemCss={styles.cardItem}
key={index}
/>
))}
</div>
)}
</div> </div>
); );
} }

View File

@ -1,5 +1,5 @@
/* eslint-disable react/jsx-pascal-case */ /* eslint-disable react/jsx-pascal-case */
import React from 'react'; import React, { useContext } from 'react';
import { import {
Space, Space,
Typography, Typography,
@ -10,12 +10,15 @@ import {
Modal, Modal,
FloatButton, FloatButton,
Progress, Progress,
Carousel,
} from 'antd'; } from 'antd';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import { CustomerServiceOutlined, QuestionCircleOutlined, SyncOutlined } from '@ant-design/icons'; import { CustomerServiceOutlined, QuestionCircleOutlined, SyncOutlined } from '@ant-design/icons';
import { css } from '@emotion/react'; import { css } from '@emotion/react';
import useSiteToken from '../../../hooks/useSiteToken'; import useSiteToken from '../../../hooks/useSiteToken';
import useLocale from '../../../hooks/useLocale'; import useLocale from '../../../hooks/useLocale';
import SiteContext from './SiteContext';
import { useCarouselStyle } from './util';
const SAMPLE_CONTENT_EN = const SAMPLE_CONTENT_EN =
'Ant Design 5.0 use CSS-in-JS technology to provide dynamic & mix theme ability. And which use component level CSS-in-JS solution get your application a better performance.'; 'Ant Design 5.0 use CSS-in-JS technology to provide dynamic & mix theme ability. And which use component level CSS-in-JS solution get your application a better performance.';
@ -54,6 +57,7 @@ const locales = {
const useStyle = () => { const useStyle = () => {
const { token } = useSiteToken(); const { token } = useSiteToken();
const { carousel } = useCarouselStyle();
return { return {
card: css` card: css`
@ -80,13 +84,25 @@ const useStyle = () => {
filter: blur(40px); filter: blur(40px);
opacity: 0.1; opacity: 0.1;
`, `,
mobileCard: css`
height: 395px;
`,
carousel,
}; };
}; };
interface ComponentItemProps {
title: React.ReactNode;
node: React.ReactNode;
type: 'new' | 'update';
index: number;
}
export default function ComponentsList() { export default function ComponentsList() {
const { token } = useSiteToken(); const { token } = useSiteToken();
const styles = useStyle(); const styles = useStyle();
const [locale] = useLocale(locales); const [locale] = useLocale(locales);
const { isMobile } = useContext(SiteContext);
const COMPONENTS: { const COMPONENTS: {
title: React.ReactNode; title: React.ReactNode;
@ -110,12 +126,16 @@ export default function ComponentsList() {
node: ( node: (
<DatePicker._InternalPanelDoNotUseOrYouWillBeFired <DatePicker._InternalPanelDoNotUseOrYouWillBeFired
showToday={false} showToday={false}
presets={[ presets={
isMobile
? []
: [
{ label: locale.yesterday, value: dayjs().add(-1, 'd') }, { label: locale.yesterday, value: dayjs().add(-1, 'd') },
{ label: locale.lastWeek, value: dayjs().add(-7, 'd') }, { label: locale.lastWeek, value: dayjs().add(-7, 'd') },
{ label: locale.lastMonth, value: dayjs().add(-1, 'month') }, { label: locale.lastMonth, value: dayjs().add(-1, 'month') },
{ label: locale.lastYear, value: dayjs().add(-1, 'year') }, { label: locale.lastYear, value: dayjs().add(-1, 'year') },
]} ]
}
value={dayjs('2022-11-18 14:00:00')} value={dayjs('2022-11-18 14:00:00')}
/> />
), ),
@ -149,7 +169,7 @@ export default function ComponentsList() {
<Tour._InternalPanelDoNotUseOrYouWillBeFired <Tour._InternalPanelDoNotUseOrYouWillBeFired
title="Ant Design 5.0" title="Ant Design 5.0"
description={locale.tour} description={locale.tour}
style={{ width: 350 }} style={{ width: isMobile ? 'auto' : 350 }}
current={3} current={3}
total={9} total={9}
/> />
@ -211,18 +231,15 @@ export default function ComponentsList() {
), ),
}, },
], ],
[], [isMobile],
); );
return ( const ComponentItem = ({ title, node, type, index }: ComponentItemProps) => {
<div style={{ width: '100%', overflow: 'hidden', display: 'flex', justifyContent: 'center' }}>
<div style={{ display: 'flex', alignItems: 'stretch', columnGap: token.paddingLG }}>
{COMPONENTS.map(({ title, node, type }, index) => {
const tagColor = type === 'new' ? 'processing' : 'warning'; const tagColor = type === 'new' ? 'processing' : 'warning';
const tagText = type === 'new' ? locale.new : locale.update; const tagText = type === 'new' ? locale.new : locale.update;
return ( return (
<div key={index} css={styles.card}> <div key={index} css={[styles.card, isMobile && styles.mobileCard]}>
{/* Decorator */} {/* Decorator */}
<div <div
css={styles.cardCircle} css={styles.cardCircle}
@ -253,7 +270,22 @@ export default function ComponentsList() {
</div> </div>
</div> </div>
); );
})} };
return isMobile ? (
<div style={{ margin: '0 16px' }}>
<Carousel css={styles.carousel}>
{COMPONENTS.map(({ title, node, type }, index) => (
<ComponentItem title={title} node={node} type={type} index={index} key={index} />
))}
</Carousel>
</div>
) : (
<div style={{ width: '100%', overflow: 'hidden', display: 'flex', justifyContent: 'center' }}>
<div style={{ display: 'flex', alignItems: 'stretch', columnGap: token.paddingLG }}>
{COMPONENTS.map(({ title, node, type }, index) => (
<ComponentItem title={title} node={node} type={type} index={index} key={index} />
))}
</div> </div>
</div> </div>
); );

View File

@ -1,10 +1,11 @@
import { Col, Row, Typography } from 'antd'; import { Col, Row, Typography } from 'antd';
import React from 'react'; import React, { useContext } from 'react';
import { css } from '@emotion/react'; import { css } from '@emotion/react';
import { Link, useLocation } from 'dumi'; import { Link, useLocation } from 'dumi';
import useLocale from '../../../hooks/useLocale'; import useLocale from '../../../hooks/useLocale';
import useSiteToken from '../../../hooks/useSiteToken'; import useSiteToken from '../../../hooks/useSiteToken';
import * as utils from '../../../theme/utils'; import * as utils from '../../../theme/utils';
import SiteContext from './SiteContext';
const SECONDARY_LIST = [ const SECONDARY_LIST = [
{ {
@ -98,6 +99,8 @@ export default function DesignFramework() {
const style = useStyle(); const style = useStyle();
const { pathname, search } = useLocation(); const { pathname, search } = useLocation();
const isZhCN = utils.isZhCN(pathname); const isZhCN = utils.isZhCN(pathname);
const { isMobile } = useContext(SiteContext);
const colSpan = isMobile ? 24 : 8;
const MAINLY_LIST = [ const MAINLY_LIST = [
{ {
@ -124,7 +127,7 @@ export default function DesignFramework() {
const desc = locale[`${key}Desc` as keyof typeof locale]; const desc = locale[`${key}Desc` as keyof typeof locale];
return ( return (
<Col key={index} span={8}> <Col key={index} span={colSpan}>
<Link to={path}> <Link to={path}>
<div css={style.card}> <div css={style.card}>
<img alt={title} src={img} /> <img alt={title} src={img} />
@ -149,7 +152,7 @@ export default function DesignFramework() {
const desc = locale[`${key}Desc` as keyof typeof locale]; const desc = locale[`${key}Desc` as keyof typeof locale];
return ( return (
<Col key={index} span={8}> <Col key={index} span={colSpan}>
<a css={style.cardMini} target="_blank" href={url} rel="noreferrer"> <a css={style.cardMini} target="_blank" href={url} rel="noreferrer">
<img alt={title} src={img} style={{ transform: `scale(${imgScale})` }} /> <img alt={title} src={img} style={{ transform: `scale(${imgScale})` }} />

View File

@ -1,6 +1,8 @@
import * as React from 'react'; import * as React from 'react';
import { useContext } from 'react';
import { Typography } from 'antd'; import { Typography } from 'antd';
import useSiteToken from '../../../hooks/useSiteToken'; import useSiteToken from '../../../hooks/useSiteToken';
import SiteContext from './SiteContext';
export interface GroupMaskProps { export interface GroupMaskProps {
style?: React.CSSProperties; style?: React.CSSProperties;
@ -49,6 +51,7 @@ export interface GroupProps {
export default function Group(props: GroupProps) { export default function Group(props: GroupProps) {
const { id, title, titleColor, description, children, decoration, background, collapse } = props; const { id, title, titleColor, description, children, decoration, background, collapse } = props;
const { token } = useSiteToken(); const { token } = useSiteToken();
const { isMobile } = useContext(SiteContext);
const marginStyle: React.CSSProperties = collapse const marginStyle: React.CSSProperties = collapse
? {} ? {}
@ -56,7 +59,7 @@ export default function Group(props: GroupProps) {
maxWidth: 1208, maxWidth: 1208,
marginInline: 'auto', marginInline: 'auto',
boxSizing: 'border-box', boxSizing: 'border-box',
paddingInline: token.marginXXL, paddingInline: isMobile ? token.margin : token.marginXXL,
}; };
const childNode = ( const childNode = (
<> <>
@ -69,11 +72,17 @@ export default function Group(props: GroupProps) {
color: titleColor, color: titleColor,
// Special for the title // Special for the title
fontFamily: `AliPuHui, ${token.fontFamily}`, fontFamily: `AliPuHui, ${token.fontFamily}`,
fontSize: isMobile ? token.fontSizeHeading2 : token.fontSizeHeading1,
}} }}
> >
{title} {title}
</Typography.Title> </Typography.Title>
<Typography.Paragraph style={{ marginBottom: token.marginFarXS, color: titleColor }}> <Typography.Paragraph
style={{
marginBottom: isMobile ? token.marginXXL : token.marginFarXS,
color: titleColor,
}}
>
{description} {description}
</Typography.Paragraph> </Typography.Paragraph>
</div> </div>

View File

@ -0,0 +1,11 @@
import * as React from 'react';
export interface SiteContextProps {
isMobile: boolean;
}
const SiteContext = React.createContext<SiteContextProps>({
isMobile: false,
});
export default SiteContext;

View File

@ -0,0 +1,119 @@
import * as React from 'react';
import { useState } from 'react';
import { css } from '@emotion/react';
import { Typography, Carousel } from 'antd';
import { useCarouselStyle } from '../util';
import useSiteToken from '../../../../hooks/useSiteToken';
const useStyle = () => {
const { carousel } = useCarouselStyle();
return {
carousel,
container: css`
position: relative;
`,
title: css`
position: absolute;
top: 15%;
z-index: 1;
width: 100%;
text-align: center;
`,
};
};
const mobileImageConfigList = [
{
imageSrc:
'https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*KsMrRZaciFcAAAAAAAAAAAAADrJ8AQ/original',
titleColor: 'rgba(0,0,0,.88)',
},
{
imageSrc:
'https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*3FkqR6XRNgoAAAAAAAAAAAAADrJ8AQ/original',
titleColor: '#fff',
},
{
imageSrc:
'https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*cSX_RbD3k9wAAAAAAAAAAAAADrJ8AQ/original',
titleColor: '#fff',
},
{
imageSrc:
'https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*MldsRZeax6EAAAAAAAAAAAAADrJ8AQ/original',
titleColor: '#fff',
},
{
imageSrc:
'https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*xCAmSL0xlZ8AAAAAAAAAAAAADrJ8AQ/original',
titleColor: '#fff',
},
{
imageSrc:
'https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*vCfCSbiI_VIAAAAAAAAAAAAADrJ8AQ/original',
titleColor: '#fff',
},
{
imageSrc:
'https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*xCAmSL0xlZ8AAAAAAAAAAAAADrJ8AQ/original',
titleColor: '#fff',
},
{
imageSrc:
'https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*BeDBTY9UnXIAAAAAAAAAAAAADrJ8AQ/original',
titleColor: '#fff',
},
{
imageSrc:
'https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*Q63XTbk8YaMAAAAAAAAAAAAADrJ8AQ/original',
titleColor: '#fff',
},
];
export interface MobileCarouselProps {
id?: string;
title?: React.ReactNode;
description?: React.ReactNode;
}
export default function MobileCarousel(props: MobileCarouselProps) {
const styles = useStyle();
const { id, title, description } = props;
const { token } = useSiteToken();
const [currentSlider, setCurrentSlider] = useState<number>(0);
return (
<div css={styles.container}>
<div css={styles.title}>
<Typography.Title
id={id}
level={1}
style={{
fontWeight: 900,
color: mobileImageConfigList[currentSlider].titleColor,
// Special for the title
fontFamily: `AliPuHui, ${token.fontFamily}`,
fontSize: token.fontSizeHeading2,
}}
>
{title}
</Typography.Title>
<Typography.Paragraph
style={{
marginBottom: token.marginXXL,
color: mobileImageConfigList[currentSlider].titleColor,
}}
>
{description}
</Typography.Paragraph>
</div>
<Carousel css={styles.carousel} afterChange={setCurrentSlider}>
{mobileImageConfigList.map((item, index) => (
<div key={index}>
<img src={item.imageSrc} alt="" style={{ width: '100%' }} />
</div>
))}
</Carousel>
</div>
);
}

View File

@ -30,6 +30,9 @@ import RadiusPicker from './RadiusPicker';
import Group from '../Group'; import Group from '../Group';
import BackgroundImage from './BackgroundImage'; import BackgroundImage from './BackgroundImage';
import { DEFAULT_COLOR, getAvatarURL, getClosetColor, PINK_COLOR } from './colorUtil'; import { DEFAULT_COLOR, getAvatarURL, getClosetColor, PINK_COLOR } from './colorUtil';
import SiteContext from '../SiteContext';
import { useCarouselStyle } from '../util';
import MobileCarousel from './MobileCarousel';
const { Header, Content, Sider } = Layout; const { Header, Content, Sider } = Layout;
@ -81,6 +84,7 @@ const locales = {
// ============================= Style ============================= // ============================= Style =============================
const useStyle = () => { const useStyle = () => {
const { token } = useSiteToken(); const { token } = useSiteToken();
const { carousel } = useCarouselStyle();
return { return {
demo: css` demo: css`
@ -177,6 +181,7 @@ const useStyle = () => {
width: 800px; width: 800px;
margin: 0 auto; margin: 0 auto;
`, `,
carousel,
}; };
}; };
@ -278,6 +283,7 @@ export default function Theme() {
const { compact, themeType, ...themeToken } = themeData; const { compact, themeType, ...themeToken } = themeData;
const isLight = themeType !== 'dark'; const isLight = themeType !== 'dark';
const [form] = Form.useForm(); const [form] = Form.useForm();
const { isMobile } = React.useContext(SiteContext);
// const algorithmFn = isLight ? theme.defaultAlgorithm : theme.darkAlgorithm; // const algorithmFn = isLight ? theme.defaultAlgorithm : theme.darkAlgorithm;
const algorithmFn = React.useMemo(() => { const algorithmFn = React.useMemo(() => {
@ -487,8 +493,22 @@ export default function Theme() {
const posStyle: React.CSSProperties = { const posStyle: React.CSSProperties = {
position: 'absolute', position: 'absolute',
}; };
const leftTopImageStyle = {
left: '50%',
transform: 'translate3d(-900px, 0, 0)',
top: -100,
height: 500,
};
const rightBottomImageStyle = {
right: '50%',
transform: 'translate3d(750px, 0, 0)',
bottom: -100,
height: 287,
};
return ( return isMobile ? (
<MobileCarousel title={locale.themeTitle} description={locale.themeDesc} id="flexible" />
) : (
<Group <Group
title={locale.themeTitle} title={locale.themeTitle}
titleColor={getTitleColor(themeData.colorPrimary, isLight)} titleColor={getTitleColor(themeData.colorPrimary, isLight)}
@ -509,10 +529,7 @@ export default function Theme() {
<img <img
style={{ style={{
...posStyle, ...posStyle,
left: '50%', ...leftTopImageStyle,
transform: 'translate3d(-900px, 0, 0)',
top: -100,
height: 500,
}} }}
src="https://gw.alipayobjects.com/zos/bmw-prod/bd71b0c6-f93a-4e52-9c8a-f01a9b8fe22b.svg" src="https://gw.alipayobjects.com/zos/bmw-prod/bd71b0c6-f93a-4e52-9c8a-f01a9b8fe22b.svg"
alt="" alt=""
@ -521,10 +538,7 @@ export default function Theme() {
<img <img
style={{ style={{
...posStyle, ...posStyle,
right: '50%', ...rightBottomImageStyle,
transform: 'translate3d(750px, 0, 0)',
bottom: -100,
height: 287,
}} }}
src="https://gw.alipayobjects.com/zos/bmw-prod/84ad805a-74cb-4916-b7ba-9cdc2bdec23a.svg" src="https://gw.alipayobjects.com/zos/bmw-prod/84ad805a-74cb-4916-b7ba-9cdc2bdec23a.svg"
alt="" alt=""

Binary file not shown.

After

Width:  |  Height:  |  Size: 196 KiB

View File

@ -1,5 +1,6 @@
/* eslint-disable import/prefer-default-export */ /* eslint-disable import/prefer-default-export */
import * as React from 'react'; import * as React from 'react';
import { css } from '@emotion/react';
export interface Author { export interface Author {
avatar: string; avatar: string;
@ -98,3 +99,28 @@ export function useSiteData(): [Partial<SiteData>, boolean] {
return [data, loading]; return [data, loading];
} }
export const useCarouselStyle = () => ({
carousel: css`
.slick-dots.slick-dots-bottom {
bottom: -22px;
li {
width: 6px;
height: 6px;
background: #e1eeff;
border-radius: 50%;
button {
height: 6px;
background: #e1eeff;
border-radius: 50%;
}
&.slick-active {
background: #4b9cff;
button {
background: #4b9cff;
}
}
}
}
`,
});

View File

@ -1,4 +1,4 @@
import React from 'react'; import React, { useEffect, useMemo } from 'react';
import { useLocale as useDumiLocale } from 'dumi'; import { useLocale as useDumiLocale } from 'dumi';
import { ConfigProvider } from 'antd'; import { ConfigProvider } from 'antd';
import useLocale from '../../hooks/useLocale'; import useLocale from '../../hooks/useLocale';
@ -9,6 +9,7 @@ import Theme from './components/Theme';
import BannerRecommends from './components/BannerRecommends'; import BannerRecommends from './components/BannerRecommends';
import ComponentsList from './components/ComponentsList'; import ComponentsList from './components/ComponentsList';
import DesignFramework from './components/DesignFramework'; import DesignFramework from './components/DesignFramework';
import SiteContext from './components/SiteContext';
const locales = { const locales = {
cn: { cn: {
@ -33,9 +34,25 @@ const Homepage: React.FC = () => {
const localeStr = localeId === 'zh-CN' ? 'cn' : 'en'; const localeStr = localeId === 'zh-CN' ? 'cn' : 'en';
const [siteData] = useSiteData(); const [siteData] = useSiteData();
const [isMobile, setIsMobile] = React.useState<boolean>(false);
const updateMobileMode = () => {
setIsMobile(window.innerWidth < 768);
};
useEffect(() => {
updateMobileMode();
window.addEventListener('resize', updateMobileMode);
return () => {
window.removeEventListener('resize', updateMobileMode);
};
}, []);
const siteValue = useMemo(() => ({ isMobile }), [isMobile]);
return ( return (
<ConfigProvider theme={{ algorithm: undefined }}> <ConfigProvider theme={{ algorithm: undefined }}>
<SiteContext.Provider value={siteValue}>
<section> <section>
<Banner> <Banner>
<BannerRecommends extras={siteData?.extras?.[localeStr]} icons={siteData?.icons} /> <BannerRecommends extras={siteData?.extras?.[localeStr]} icons={siteData?.icons} />
@ -71,6 +88,7 @@ const Homepage: React.FC = () => {
</Group> </Group>
</div> </div>
</section> </section>
</SiteContext.Provider>
</ConfigProvider> </ConfigProvider>
); );
}; };

View File

@ -1,4 +1,4 @@
import React from 'react'; import React, { useContext } from 'react';
import RcFooter from 'rc-footer'; import RcFooter from 'rc-footer';
import { Link, FormattedMessage } from 'dumi'; import { Link, FormattedMessage } from 'dumi';
import type { FooterColumn } from 'rc-footer/lib/column'; import type { FooterColumn } from 'rc-footer/lib/column';
@ -23,6 +23,7 @@ import useLocation from '../../../hooks/useLocation';
import useLocale from '../../../hooks/useLocale'; import useLocale from '../../../hooks/useLocale';
import useSiteToken from '../../../hooks/useSiteToken'; import useSiteToken from '../../../hooks/useSiteToken';
import AdditionalInfo from './AdditionalInfo'; import AdditionalInfo from './AdditionalInfo';
import SiteContext from '../SiteContext';
const locales = { const locales = {
cn: { cn: {
@ -35,6 +36,7 @@ const locales = {
const useStyle = () => { const useStyle = () => {
const { token } = useSiteToken(); const { token } = useSiteToken();
const { isMobile } = useContext(SiteContext);
const background = new TinyColor(getAlphaColor('#f0f3fa', '#fff')) const background = new TinyColor(getAlphaColor('#f0f3fa', '#fff'))
.onBackground(token.colorBgContainer) .onBackground(token.colorBgContainer)
.toHexString(); .toHexString();
@ -59,7 +61,10 @@ const useStyle = () => {
} }
.rc-footer-column { .rc-footer-column {
margin-bottom: 0; margin-bottom: ${isMobile ? 60 : 0}px;
:last-child {
margin-bottom: ${isMobile ? 20 : 0}px;
}
} }
.rc-footer-container { .rc-footer-container {
@ -69,8 +74,10 @@ const useStyle = () => {
} }
.rc-footer-bottom { .rc-footer-bottom {
font-size: ${token.fontSize}px;
box-shadow: inset 0 106px 36px -116px rgba(0, 0, 0, 0.14); box-shadow: inset 0 106px 36px -116px rgba(0, 0, 0, 0.14);
.rc-footer-bottom-container {
font-size: ${token.fontSize}px;
}
} }
`, `,
}; };
@ -369,7 +376,10 @@ const Footer = () => {
css={style.footer} css={style.footer}
bottom={ bottom={
<> <>
Made with <span style={{ color: '#fff' }}></span> by {locale.owner} <div style={{ opacity: '0.4' }}>
Made with <span style={{ color: '#fff' }}></span> by
</div>
<div>{locale.owner}</div>
</> </>
} }
/> />

View File

@ -116,6 +116,7 @@
"@babel/runtime": "^7.18.3", "@babel/runtime": "^7.18.3",
"@ctrl/tinycolor": "^3.4.0", "@ctrl/tinycolor": "^3.4.0",
"@rc-component/tour": "~1.0.1-2", "@rc-component/tour": "~1.0.1-2",
"antd-token-previewer": "^1.1.0-21",
"classnames": "^2.2.6", "classnames": "^2.2.6",
"copy-to-clipboard": "^3.2.0", "copy-to-clipboard": "^3.2.0",
"dayjs": "^1.11.1", "dayjs": "^1.11.1",
@ -193,7 +194,6 @@
"@typescript-eslint/eslint-plugin": "^5.40.0", "@typescript-eslint/eslint-plugin": "^5.40.0",
"@typescript-eslint/parser": "^5.40.0", "@typescript-eslint/parser": "^5.40.0",
"antd-img-crop": "^4.2.8", "antd-img-crop": "^4.2.8",
"antd-token-previewer": "^1.1.0-6",
"array-move": "^4.0.0", "array-move": "^4.0.0",
"bundlesize2": "^0.0.31", "bundlesize2": "^0.0.31",
"chalk": "^4.0.0", "chalk": "^4.0.0",