generated from arvinxx/npm-template
-
Notifications
You must be signed in to change notification settings - Fork 27
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* 📝 docs: update best practice docs * ✅ ci: fix ci lint * 📝 docs: update best practice docs * 📝 docs: 补充 antd 组件自定义实践案例
- Loading branch information
Showing
21 changed files
with
549 additions
and
13 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,8 @@ | ||
--- | ||
title: 🚧 基于 antd v5 二次封装组件库 | ||
group: | ||
title: 组件库研发 | ||
order: 2 | ||
--- | ||
|
||
# 基于 antd v5 二开的组件库,应该如何优雅书写样式? |
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,45 @@ | ||
--- | ||
title: 自定义 antd 组件样式 | ||
group: 主题定制 | ||
--- | ||
|
||
# 如何更加优雅地覆写 antd 组件样式? | ||
|
||
## 基于 ConfigProvider 自定义 | ||
|
||
antd 在 V5 提供了全新的 theme 属性用于自定义,因此如果需要自定义组件样式,建议优先采用 CP 上的 theme 字段。 | ||
|
||
示例 demo 如下: | ||
|
||
<code src="./demos/ConfigProviderOverride.tsx"></code> | ||
|
||
:::info | ||
更多基于 ConfigProvider 的主题定制能力,详见 [聊聊 Ant Design V5 的主题(上):CSSinJS 动态主题的花活](https://www.yuque.com/antfe/featured/durxuu94nvgvgmzq#vFlnd)。 | ||
::: | ||
|
||
antd-style 的 ThemeProvider 是基于 ConfigProvider 的业务层封装,提供业务友好的定制能力,查看:[自定义主题](/guide/custom-theme) | ||
|
||
## 基本覆写 | ||
|
||
`createStyles` 方法存在一个 `prefixCls` 参数,使用该参数可以传入组件的前缀,这样一来,任何的样式覆写都可以随着 prefixCls 的变化而自动变化。 | ||
|
||
<code src="./demos/DefaultOverride"></code> | ||
|
||
## 抬升权重覆写 | ||
|
||
在某些组件中,直接添加类名可能因为权重不够高,导致无法覆盖样式,此时可以通过 `&` 符号来抬升相应的权重。 | ||
|
||
<code src="./demos/OverrideWeight"></code> | ||
|
||
## 多 classNames 场景覆写 | ||
|
||
classNames 是 antd V5 的一个重头戏: [[RFC] Semantic DOM Structure for all Components](https://github.com/ant-design/ant-design/discussions/40221)。 | ||
在过去,我们要做样式定义,需要找很多 dom 节点进行大量的样式覆写,而 antd 版本升级的过程中,有时候会对 dom 结构进行调整。这样一来,我们覆写的样式就会出现问题。 | ||
|
||
而 classNames 将为我们提供一个稳定的 dom 结构 API ,我们可以通过 classNames 传入的类名,将会文档指向对应的 dom 节点,进而大大降低 DOM 变化带来的 Breaking Change 风险,同时也让我们不必再 hack 式地找样式类名。 | ||
|
||
<code src="./demos/InputclassNames.tsx"></code> | ||
|
||
## 相关讨论 | ||
|
||
- [样式权重问题](https://github.com/ant-design/antd-style/issues/24) |
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 |
---|---|---|
@@ -1,7 +1,6 @@ | ||
--- | ||
title: 黏土风 UI | ||
order: 10 | ||
group: 自定义主题 | ||
group: 样式案例 | ||
--- | ||
|
||
# 黏土风格 | ||
|
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,53 @@ | ||
--- | ||
title: 扩展自定义 Token 类型定义 | ||
group: | ||
title: 主题定制 | ||
order: 1 | ||
--- | ||
|
||
# 如何给 antd-style 扩展 CustomToken 对象类型定义? | ||
|
||
## 解决思路 | ||
|
||
通过给 `antd-style` 扩展 `CustomToken` 接口的类型定义,可以为 `useTheme` hooks 中增加相应的 token 类型定义。 | ||
|
||
同时,给 `ThemeProvider` 对象添加泛型,可以约束 `customToken` 的入参定义。 | ||
|
||
```tsx | pure | ||
import { ThemeProvider, useTheme } from 'antd-style'; | ||
|
||
interface NewToken { | ||
customBrandColor: string; | ||
} | ||
|
||
// 通过给 antd-style 扩展 CustomToken 对象类型定义,可以为 useTheme 中增加相应的 token 对象 | ||
declare module 'antd-style' { | ||
// eslint-disable-next-line @typescript-eslint/no-empty-interface | ||
export interface CustomToken extends NewToken {} | ||
} | ||
|
||
const App = () => { | ||
const token = useTheme(); | ||
return <div>{token.customBrandColor}</div>; | ||
}; | ||
|
||
export default () => ( | ||
// 给 ThemeProvider 对象添加泛型后可以约束 customToken 接口的入参定义 | ||
<ThemeProvider<NewToken> customToken={{ customBrandColor: '#c956df' }}> | ||
<App /> | ||
</ThemeProvider> | ||
); | ||
``` | ||
|
||
:::info | ||
由于 CustomToken 大概率是一个空 interface,如果在项目中有配置 ` @typescript-eslint/no-empty-interface` 的规则,就在代码格式化时导致接口定义被订正改为 type,而 type 是无法扩展的,会导致提示丢失(相关 issue: [#16](https://github.com/ant-design/antd-style/issues/16))。因此解决方案为如上述示例代码一样,添加禁用规则。 | ||
::: | ||
|
||
## 参考代码 | ||
|
||
- [dumi-theme-antd-style](https://github.com/arvinxx/dumi-theme-antd-style/blob/master/src/styles/customToken.ts) | ||
- [Ant Design 官网](https://github.com/ant-design/ant-design/blob/master/.dumi/theme/SiteThemeProvider.tsx) | ||
|
||
## 相关讨论 | ||
|
||
- [🧐[问题] 请问一下如何给 antd-style 扩展 CustomToken 对象类型定义](https://github.com/ant-design/antd-style/issues/16) |
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,48 @@ | ||
/** | ||
* iframe: true | ||
*/ | ||
|
||
import { Button, Checkbox, ConfigProvider, Popover, theme } from 'antd'; | ||
import { Flexbox } from 'react-layout-kit'; | ||
|
||
export default () => { | ||
const { token } = theme.useToken(); | ||
|
||
return ( | ||
<ConfigProvider | ||
theme={{ | ||
components: { | ||
Popover: { colorText: token.colorTextLightSolid }, | ||
Checkbox: { | ||
colorPrimary: token.blue7, | ||
colorText: token.colorTextLightSolid, | ||
}, | ||
Button: { colorPrimary: token.blue7 }, | ||
}, | ||
}} | ||
> | ||
<div style={{ marginBottom: 100 }}> | ||
<Popover | ||
open | ||
content={ | ||
<div style={{ width: 300 }}> | ||
<div>antd V5 的 Popup ,结合 结合 组件级 Token,可以非常简单地实现自定义样式</div> | ||
|
||
<Flexbox style={{ marginTop: 24 }} horizontal distribution={'space-between'} gap={8}> | ||
<Checkbox checked>不再显示</Checkbox> | ||
<Button type={'primary'} size={'small'}> | ||
我知道了 | ||
</Button> | ||
</Flexbox> | ||
</div> | ||
} | ||
color={'blue'} | ||
arrow={{ pointAtCenter: true }} | ||
trigger="hover" | ||
> | ||
antd v5 的组件级自定义样式,轻松又便捷 | ||
</Popover> | ||
</div> | ||
</ConfigProvider> | ||
); | ||
}; |
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,30 @@ | ||
/** | ||
* defaultShowCode: true | ||
*/ | ||
import { Button, Space } from 'antd'; | ||
import { ThemeProvider, createStyles } from 'antd-style'; | ||
|
||
const useStyles = createStyles(({ token, css, prefixCls }) => ({ | ||
override: css` | ||
&.${prefixCls}-btn { | ||
background-color: ${token.colorWarning}; | ||
} | ||
`, | ||
})); | ||
|
||
const Demo = ({ text }: { text?: string }) => { | ||
const { styles } = useStyles(); | ||
|
||
return <Button className={styles.override}>{text ?? 'override to warning color'}</Button>; | ||
}; | ||
|
||
export default () => { | ||
return ( | ||
<Space> | ||
<Demo /> | ||
<ThemeProvider prefixCls={'abc'}> | ||
<Demo text={'prefixCls to abc'} /> | ||
</ThemeProvider> | ||
</Space> | ||
); | ||
}; |
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,36 @@ | ||
/** | ||
* defaultShowCode: true | ||
*/ | ||
import { Input } from 'antd'; | ||
import { createStyles } from 'antd-style'; | ||
|
||
const useStyles = createStyles(({ token, css, prefixCls }) => ({ | ||
bg: css` | ||
background: ${token.colorBgLayout}; | ||
padding: 24px; | ||
`, | ||
input: css` | ||
background: transparent; | ||
`, | ||
wrapper: css` | ||
background: transparent; | ||
border: 2px solid ${token.colorBorder}; | ||
`, | ||
suffix: css` | ||
color: ${token.colorTextQuaternary}; | ||
`, | ||
})); | ||
|
||
export default () => { | ||
const { styles } = useStyles(); | ||
|
||
return ( | ||
<div className={styles.bg}> | ||
<Input | ||
placeholder={'自定义Input classNames'} | ||
suffix={'$'} | ||
classNames={{ affixWrapper: styles.wrapper, input: styles.input, suffix: styles.suffix }} | ||
/> | ||
</div> | ||
); | ||
}; |
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,36 @@ | ||
import { createStyles } from 'antd-style'; | ||
|
||
const useStyles = createStyles(({ css, cx }) => { | ||
// 使用 cx 包裹 css | ||
const child = cx(css` | ||
background: red; | ||
width: 100px; | ||
height: 100px; | ||
`); | ||
|
||
return { | ||
parent: css` | ||
cursor: pointer; | ||
&:hover { | ||
.${child} { | ||
background: blue; | ||
} | ||
} | ||
`, | ||
child, | ||
}; | ||
}); | ||
|
||
const Demo = () => { | ||
const { styles } = useStyles(); | ||
|
||
return ( | ||
<div className={styles.parent}> | ||
<div className={styles.child} /> | ||
hover to change color | ||
</div> | ||
); | ||
}; | ||
|
||
export default Demo; |
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,32 @@ | ||
/** | ||
* defaultShowCode: true | ||
*/ | ||
import { App, Layout } from 'antd'; | ||
import { createStyles } from 'antd-style'; | ||
|
||
const useStyles = createStyles(({ token, css, prefixCls }) => ({ | ||
default: css` | ||
.${prefixCls}-layout-header { | ||
background-color: ${token.colorPrimary}; | ||
} | ||
`, | ||
moreWeight: css` | ||
// ↓ | ||
&.${prefixCls}-layout-header { | ||
background-color: ${token.colorPrimary}; | ||
} | ||
`, | ||
})); | ||
|
||
export default () => { | ||
const { styles } = useStyles(); | ||
|
||
return ( | ||
<App> | ||
<Layout> | ||
<Layout.Header className={styles.default}>无法覆盖</Layout.Header> | ||
<Layout.Header className={styles.moreWeight}>可正常覆盖</Layout.Header> | ||
</Layout> | ||
</App> | ||
); | ||
}; |
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,20 @@ | ||
/** | ||
* iframe: 240 | ||
*/ | ||
import { Button, Space } from 'antd'; | ||
import Layout from './layout'; | ||
import { showMessage, showModal, showNotification } from './request'; | ||
|
||
const App = () => ( | ||
<Layout> | ||
<Space> | ||
<Button type={'primary'} onClick={showMessage}> | ||
Open message | ||
</Button> | ||
<Button onClick={showModal}>Open modal</Button> | ||
<Button onClick={showNotification}>Open notification</Button> | ||
</Space> | ||
</Layout> | ||
); | ||
|
||
export default App; |
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,32 @@ | ||
/** | ||
* iframe: 240 | ||
*/ | ||
import { ThemeProvider } from 'antd-style'; | ||
import { MessageInstance } from 'antd/es/message/interface'; | ||
import { ModalStaticFunctions } from 'antd/es/modal/confirm'; | ||
import { NotificationInstance } from 'antd/es/notification/interface'; | ||
import { PropsWithChildren } from 'react'; | ||
import { Center } from 'react-layout-kit'; | ||
|
||
export let message: MessageInstance, | ||
modal: Omit<ModalStaticFunctions, 'warn'>, | ||
notification: NotificationInstance; | ||
|
||
export default ({ children }: PropsWithChildren) => { | ||
return ( | ||
<Center style={{ height: '100vh', background: '#f5f5f5' }}> | ||
<ThemeProvider | ||
theme={{ | ||
token: { colorPrimary: '#5bdbe6', colorInfo: '#5bdbe6', borderRadius: 2 }, | ||
}} | ||
getStaticInstance={(instances) => { | ||
message = instances.message; | ||
modal = instances.modal; | ||
notification = instances.notification; | ||
}} | ||
> | ||
{children} | ||
</ThemeProvider> | ||
</Center> | ||
); | ||
}; |
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,24 @@ | ||
/** | ||
* iframe: 240 | ||
*/ | ||
import { message, modal, notification } from './layout'; | ||
|
||
export const showMessage = () => { | ||
message.success('Success!'); | ||
}; | ||
|
||
export const showNotification = () => { | ||
notification.info({ | ||
message: `Notification`, | ||
description: 'Hello, Ant Design Style', | ||
}); | ||
}; | ||
|
||
export const showModal = () => { | ||
modal.warning({ | ||
title: 'This is a warning message', | ||
content: 'some messages...some messages...', | ||
centered: true, | ||
maskClosable: true, | ||
}); | ||
}; |
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,15 @@ | ||
{ | ||
"include": ["**/*.tsx", "**/*.ts"], | ||
"compilerOptions": { | ||
"strict": true, | ||
"declaration": true, | ||
"skipLibCheck": true, | ||
"esModuleInterop": true, | ||
"jsx": "react-jsx", | ||
"lib": ["DOM", "ESNext"], | ||
"baseUrl": ".", | ||
"paths": { | ||
"antd-style": ["../../../es"] | ||
} | ||
} | ||
} |
Oops, something went wrong.