Skip to content

Commit bfde19d

Browse files
EmilyyyLiu刘欢gemini-code-assist[bot]
authored
feat(Collapse configProvider): unified provision of custom prefixCls (#6961)
* feat(Collapse configProvider): unified provision of custom prefixCls * Update src/components/config-provider/index.zh.md Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * test: collapse test * test: collapse test * feat: add callback to getPrefixCls * feat: change context ts * feat: useConfig * test: add test --------- Co-authored-by: 刘欢 <lh01217311@antgroup.com> Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
1 parent c55c5a3 commit bfde19d

File tree

6 files changed

+91
-15
lines changed

6 files changed

+91
-15
lines changed

src/components/collapse/collapse.tsx

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@ import { mergeProp, mergeProps } from '../../utils/with-default-props'
1414
import { useConfig } from '../config-provider'
1515
import List from '../list'
1616

17-
const classPrefix = `adm-collapse`
18-
1917
export type CollapsePanelProps = {
2018
key: string
2119
title: ReactNode
@@ -40,8 +38,9 @@ const CollapsePanelContent: FC<{
4038
forceRender: boolean
4139
destroyOnClose: boolean
4240
children?: ReactNode
41+
prefixCls?: string
4342
}> = props => {
44-
const { visible } = props
43+
const { visible, prefixCls } = props
4544
const innerRef = useRef<HTMLDivElement>(null)
4645
const shouldRender = useShouldRender(
4746
visible,
@@ -103,8 +102,8 @@ const CollapsePanelContent: FC<{
103102

104103
return (
105104
<animated.div
106-
className={classNames(`${classPrefix}-panel-content`, {
107-
[`${classPrefix}-panel-content-active`]: visible,
105+
className={classNames(`${prefixCls}-panel-content`, {
106+
[`${prefixCls}-panel-content-active`]: visible,
108107
})}
109108
style={{
110109
height: height.to(v => {
@@ -116,7 +115,7 @@ const CollapsePanelContent: FC<{
116115
}),
117116
}}
118117
>
119-
<div className={`${classPrefix}-panel-content-inner`} ref={innerRef}>
118+
<div className={`${prefixCls}-panel-content-inner`} ref={innerRef}>
120119
<List.Item>{shouldRender && props.children}</List.Item>
121120
</div>
122121
</animated.div>
@@ -143,11 +142,14 @@ export type CollapseProps = (
143142
} & ValueProps<string | null>)
144143
) & {
145144
children?: ReactNode
145+
prefixCls?: string
146146
} & NativeProps
147147

148148
export const Collapse: FC<CollapseProps> = props => {
149-
const { collapse: componentConfig = {} } = useConfig()
149+
const { collapse: componentConfig = {}, getPrefixCls } = useConfig()
150150
const mergedProps = mergeProps(componentConfig, props)
151+
const prefixCls = getPrefixCls('collapse', props.prefixCls)
152+
151153
const panels: ReactElement<CollapsePanelProps>[] = []
152154
traverseReactNode(mergedProps.children, child => {
153155
if (!isValidElement<CollapsePanelProps>(child)) return
@@ -202,7 +204,7 @@ export const Collapse: FC<CollapseProps> = props => {
202204

203205
return withNativeProps(
204206
mergedProps,
205-
<div className={classPrefix}>
207+
<div className={prefixCls}>
206208
<List>
207209
{panels.map(panel => {
208210
const key = panel.key as string
@@ -238,8 +240,8 @@ export const Collapse: FC<CollapseProps> = props => {
238240
arrow(active)
239241
) : (
240242
<div
241-
className={classNames(`${classPrefix}-arrow`, {
242-
[`${classPrefix}-arrow-active`]: active,
243+
className={classNames(`${prefixCls}-arrow`, {
244+
[`${prefixCls}-arrow-active`]: active,
243245
})}
244246
>
245247
{arrow}
@@ -251,7 +253,7 @@ export const Collapse: FC<CollapseProps> = props => {
251253
{withNativeProps(
252254
panel.props,
253255
<List.Item
254-
className={`${classPrefix}-panel-header`}
256+
className={`${prefixCls}-panel-header`}
255257
onClick={handleClick}
256258
disabled={panel.props.disabled}
257259
arrowIcon={arrowIcon}
@@ -263,6 +265,7 @@ export const Collapse: FC<CollapseProps> = props => {
263265
visible={active}
264266
forceRender={!!panel.props.forceRender}
265267
destroyOnClose={!!panel.props.destroyOnClose}
268+
prefixCls={prefixCls}
266269
>
267270
{panel.props.children}
268271
</CollapsePanelContent>

src/components/collapse/tests/collapse.test.tsx

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import * as React from 'react'
22
import { fireEvent, render, screen, testA11y, waitFor } from 'testing'
33
import Collapse from '../'
4+
import ConfigProvider from '../../config-provider'
45

56
const classPrefix = `adm-collapse`
67

@@ -178,4 +179,44 @@ describe('arrow', () => {
178179
)
179180
expect(screen.getByText('bar')).toBeVisible()
180181
})
182+
183+
test('default adm class', () => {
184+
const { container } = render(
185+
<ConfigProvider>
186+
<Collapse defaultActiveKey={['1']}>
187+
<Collapse.Panel key='1' title='第一项'>
188+
第一项
189+
</Collapse.Panel>
190+
</Collapse>
191+
</ConfigProvider>
192+
)
193+
expect(container.querySelector('.adm-collapse')).toBeTruthy()
194+
})
195+
196+
test('should apply custom prefixCls(ConfigProvider)', () => {
197+
const { container } = render(
198+
<ConfigProvider prefixCls='custom-prefix'>
199+
<Collapse defaultActiveKey={['1']}>
200+
<Collapse.Panel key='1' title='第一项'>
201+
第一项
202+
</Collapse.Panel>
203+
</Collapse>
204+
</ConfigProvider>
205+
)
206+
expect(container.querySelector('.custom-prefix-collapse')).toBeTruthy()
207+
})
208+
209+
test('should apply custom prefixCls(component) ', () => {
210+
const { container } = render(
211+
<ConfigProvider prefixCls='custom-prefix'>
212+
<Collapse defaultActiveKey={['1']} prefixCls='another-prefix'>
213+
<Collapse.Panel key='1' title='第一项'>
214+
第一项
215+
</Collapse.Panel>
216+
</Collapse>
217+
</ConfigProvider>
218+
)
219+
expect(container.querySelector('.custom-prefix-collapse')).toBeFalsy()
220+
expect(container.querySelector('.another-prefix')).toBeTruthy()
221+
})
181222
})

src/components/config-provider/config-provider.tsx

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import React, { FC, ReactNode, useContext } from 'react'
22
import { Locale } from '../../locales/base'
33
import zhCN from '../../locales/zh-CN'
44

5+
type GetPrefixCls = (suffixCls?: string, customizePrefixCls?: string) => string
6+
57
type Config = {
68
locale: Locale
79
checkList?: {
@@ -42,7 +44,9 @@ type Config = {
4244
searchBar?: {
4345
searchIcon?: ReactNode
4446
}
47+
prefixCls?: string
4548
}
49+
export const defaultPrefixCls = 'adm'
4650

4751
export const defaultConfigRef: {
4852
current: Config
@@ -60,7 +64,9 @@ export function getDefaultConfig() {
6064
return defaultConfigRef.current
6165
}
6266

63-
const ConfigContext = React.createContext<Config | null>(null)
67+
const ConfigContext = React.createContext<
68+
(Config & { getPrefixCls: GetPrefixCls }) | null
69+
>(null)
6470

6571
export type ConfigProviderProps = Partial<Config> & {
6672
children?: ReactNode
@@ -70,11 +76,24 @@ export const ConfigProvider: FC<ConfigProviderProps> = props => {
7076
const { children, ...config } = props
7177
const parentConfig = useConfig()
7278

79+
const getPrefixCls = React.useCallback(
80+
(suffixCls?: string, customizePrefixCls?: string) => {
81+
if (customizePrefixCls) {
82+
return customizePrefixCls
83+
}
84+
const mergedPrefixCls =
85+
config.prefixCls || parentConfig.prefixCls || defaultPrefixCls
86+
return suffixCls ? `${mergedPrefixCls}-${suffixCls}` : mergedPrefixCls
87+
},
88+
[config.prefixCls, parentConfig.prefixCls]
89+
)
90+
7391
return (
7492
<ConfigContext.Provider
7593
value={{
7694
...parentConfig,
7795
...config,
96+
getPrefixCls,
7897
}}
7998
>
8099
{children}
@@ -83,5 +102,16 @@ export const ConfigProvider: FC<ConfigProviderProps> = props => {
83102
}
84103

85104
export function useConfig() {
86-
return useContext(ConfigContext) ?? getDefaultConfig()
105+
const context = useContext(ConfigContext)
106+
if (!context) {
107+
const defaultConfig = getDefaultConfig()
108+
return {
109+
...defaultConfig,
110+
getPrefixCls: (suffixCls?: string, customizePrefixCls?: string) => {
111+
if (customizePrefixCls) return customizePrefixCls
112+
return suffixCls ? `${defaultPrefixCls}-${suffixCls}` : defaultPrefixCls
113+
},
114+
}
115+
}
116+
return context
87117
}

src/components/config-provider/index.en.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ Configure locale messages and custom icons globally.
2929
| navBar | NavBar config | `{ backIcon?: ReactNode }` | - |
3030
| noticeBar | NoticeBar config | `{ icon?: ReactNode, closeIcon?: ReactNode }` | - |
3131
| popup | Popup config | `{ closeIcon?: ReactNode }` | - |
32+
| prefixCls | Set prefix className | string | `adm` |
3233
| result | Result config | `{ successIcon?: ReactNode, errorIcon?: ReactNode, infoIcon?: ReactNode, waitingIcon?: ReactNode, warningIcon?: ReactNode }` | - |
3334
| searchBar | SearchBar config | `{ searchIcon?: ReactNode }` | - |
3435

src/components/config-provider/index.zh.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
| navBar | NavBar 配置 | `{ backIcon?: ReactNode }` | - |
3030
| noticeBar | NoticeBar 配置 | `{ icon?: ReactNode, closeIcon?: ReactNode }` | - |
3131
| popup | Popup 配置 | `{ closeIcon?: ReactNode }` | - |
32+
| prefixCls | 设置统一样式前缀 | string | `adm` |
3233
| result | Result 配置 | `{ successIcon?: ReactNode, errorIcon?: ReactNode, infoIcon?: ReactNode, waitingIcon?: ReactNode, warningIcon?: ReactNode }` | - |
3334
| searchBar | SearchBar 配置 | `{ searchIcon?: ReactNode }` | - |
3435

src/components/config-provider/tests/config-provider.test.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ describe('ConfigProvider', () => {
118118
})
119119
})
120120

121-
test('useConfig should only has `locale`', () => {
121+
test('useConfig should only has `locale` and `getPrefixCls`', () => {
122122
let config: ReturnType<typeof useConfig>
123123

124124
const Demo = () => {
@@ -127,6 +127,6 @@ describe('ConfigProvider', () => {
127127
}
128128
render(<Demo />)
129129

130-
expect(Object.keys(config!)).toEqual(['locale'])
130+
expect(Object.keys(config!)).toEqual(['locale', 'getPrefixCls'])
131131
})
132132
})

0 commit comments

Comments
 (0)