Skip to content

Commit fd1e0ff

Browse files
committed
feat(Search): make icons be configurable
1 parent de23a24 commit fd1e0ff

File tree

6 files changed

+62
-15
lines changed

6 files changed

+62
-15
lines changed

src/search/Search.jsx

+33-15
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React from 'react';
1+
import React, { isValidElement } from 'react';
22
import PropTypes from 'prop-types';
33
import classNames from 'classnames';
44
import { polyfill } from 'react-lifecycles-compat';
@@ -126,6 +126,10 @@ class Search extends React.Component {
126126
disabled: PropTypes.bool,
127127
locale: PropTypes.object,
128128
rtl: PropTypes.bool,
129+
/**
130+
* 可配置的icons,包括 search 等
131+
*/
132+
icons: PropTypes.object,
129133
};
130134

131135
static defaultProps = {
@@ -142,6 +146,7 @@ class Search extends React.Component {
142146
onFilterChange: func.noop,
143147
hasClear: false,
144148
disabled: false,
149+
icons: {},
145150
};
146151

147152
constructor(props) {
@@ -237,6 +242,7 @@ class Search extends React.Component {
237242
visible,
238243
locale,
239244
rtl,
245+
icons,
240246
...others
241247
} = this.props;
242248

@@ -250,26 +256,31 @@ class Search extends React.Component {
250256

251257
let searchIcon = null,
252258
filterSelect = null,
253-
searchBtn = null;
259+
searchBtn = null,
260+
iconsSearch = icons.search;
261+
262+
if (!isValidElement(icons.search) && icons.search) {
263+
iconsSearch = <span>{icons.search}</span>;
264+
}
254265

255266
if (shape === 'simple') {
256267
const cls = classNames({
257268
[`${prefix}search-icon`]: true,
258269
[buttonProps.className]: !!buttonProps.className,
270+
[`${prefix}search-symbol-icon`]: !iconsSearch,
259271
});
260272
hasIcon &&
261-
(searchIcon = (
262-
<Icon
263-
type="search"
264-
tabIndex="0"
265-
role="button"
266-
aria-disabled={disabled}
267-
aria-label={locale.buttonText}
268-
{...buttonProps}
269-
className={cls}
270-
onClick={this.onSearch}
271-
onKeyDown={this.onKeyDown}
272-
/>
273+
(searchIcon = React.cloneElement(
274+
iconsSearch || <Icon type="search" />,
275+
{
276+
role: 'button',
277+
'aria-disabled': disabled,
278+
'aria-label': locale.buttonText,
279+
...buttonProps,
280+
className: cls,
281+
onClick: this.onSearch,
282+
onKeyDown: this.onKeyDown,
283+
}
273284
));
274285
} else {
275286
const cls = classNames({
@@ -287,7 +298,14 @@ class Search extends React.Component {
287298
onClick={this.onSearch}
288299
onKeyDown={this.onKeyDown}
289300
>
290-
{hasIcon ? <Icon type="search" /> : null}
301+
{hasIcon
302+
? iconsSearch || (
303+
<Icon
304+
type="search"
305+
className={`${prefix}search-symbol-icon`}
306+
/>
307+
)
308+
: null}
291309
{searchText ? (
292310
<span className={`${prefix}search-btn-text`}>
293311
{searchText}

src/search/main.scss

+5
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@
5858
#{$search-prefix}-btn {
5959
box-shadow: none;
6060
}
61+
62+
#{$search-prefix}-symbol-icon::before {
63+
content: $search-search-icon-content;
64+
}
65+
6166
&-normal {
6267
width: 600px;
6368

src/search/scss/variable.scss

+5
Original file line numberDiff line numberDiff line change
@@ -329,5 +329,10 @@ $search-simple-dark-l-icon-size: $icon-m !default;
329329
/// @namespace size/simple
330330
$search-simple-dark-m-icon-size: $icon-xs !default;
331331

332+
/// search icon
333+
/// @namespace statement/normal
334+
/// @type icon
335+
$search-search-icon-content: $icon-content-search !default;
336+
332337
$color-calculate-search-normal-dark-bg: transparentize($search-normal-dark-bg-color, 1 - $search-normal-dark-bg-opacity) !default;
333338
$color-calculate-search-simple-dark-bg: transparentize($search-simple-dark-bg-color, 1 - $search-simple-dark-bg-opacity) !default;

test/search/index-spec.js

+5
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@ describe('Search', () => {
6565
assert(wrapper.dive().find(`[aria-label="${enUS.Search.buttonText}"]`).length === 0);
6666
assert(wrapper.dive().find(`[aria-label="a11y search"]`).length === 1);
6767
});
68+
69+
it('should support icons', () => {
70+
const wrapper = mount(<Search icons={{search: <span id="icon-text">sc</span>}} aria-label="a11y search"/>);
71+
assert(wrapper.find('.next-search-btn span').at(0).text() === 'sc');
72+
});
6873
});
6974

7075
describe('behavior', () => {

types/search/index.d.ts

+3
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,9 @@ export interface SearchProps extends HTMLAttributesWeak, CommonProps {
203203
* 是否显示搜索按钮
204204
*/
205205
hasIcon?: boolean;
206+
icons?: {
207+
search?: React.ReactNode;
208+
};
206209
}
207210

208211
export default class Search extends React.Component<SearchProps, any> {}

types/util.d.ts

+11
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
import { ReactNode } from "react";
2+
3+
export interface IconsType {
4+
[key: string]: ReactNode;
5+
}
6+
17
export default interface CommonProps {
28
/**
39
* 样式类名的品牌前缀
@@ -9,6 +15,11 @@ export default interface CommonProps {
915
*/
1016
locale?: {};
1117

18+
/**
19+
* 组件上可配置的icons变量
20+
*/
21+
icons?: IconsType;
22+
1223
/**
1324
* 是否开启 Pure Render 模式,会提高性能,但是也会带来副作用
1425
*/

0 commit comments

Comments
 (0)