Skip to content

Commit 50f203f

Browse files
committed
support custom arrow icon
1 parent 46d0bf0 commit 50f203f

File tree

6 files changed

+244
-2
lines changed

6 files changed

+244
-2
lines changed

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,12 @@ ReactDOM.render(collapse, container);
109109
<th>noop</th>
110110
<td>called when collapse Panel is changed</td>
111111
</tr>
112+
<tr>
113+
<td>arrowIcon</td>
114+
<td>React.Node</td>
115+
<th>''</th>
116+
<td>specific the custom arrow icon.</td>
117+
</tr>
112118
</tbody>
113119
</table>
114120

assets/custom-icon.less

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
@prefixCls: rc-collapse;
2+
@text-color: #666;
3+
@borderStyle: 1px solid #d9d9d9;
4+
5+
#arrow {
6+
.common(){
7+
width: 0;
8+
height: 0;
9+
font-size: 0;
10+
line-height: 0;
11+
}
12+
.right(@w, @h, @color) {
13+
border-top: @w solid transparent;
14+
border-bottom: @w solid transparent;
15+
border-left: @h solid @color;
16+
}
17+
18+
.bottom(@w, @h, @color) {
19+
border-left: @w solid transparent;
20+
border-right: @w solid transparent;
21+
border-top: @h solid @color;
22+
}
23+
}
24+
25+
.@{prefixCls} {
26+
background-color: #f7f7f7;
27+
border-radius: 3px;
28+
border: @borderStyle;
29+
30+
&-anim-active {
31+
transition: height .2s ease-out;
32+
}
33+
34+
& > &-item {
35+
border-top: @borderStyle;
36+
&:first-child {
37+
border-top: none;
38+
}
39+
40+
> .@{prefixCls}-header {
41+
height: 38px;
42+
line-height: 38px;
43+
text-indent: 8px;
44+
color: #666;
45+
cursor: pointer;
46+
.arrow {
47+
display: inline-flex;
48+
justify-content: center;
49+
align-items: center;
50+
transition: all .3s;
51+
vertical-align: -.125em;
52+
margin-right: 6px;
53+
}
54+
}
55+
}
56+
57+
& > &-item-disabled > .@{prefixCls}-header {
58+
cursor: not-allowed;
59+
color: #999;
60+
background-color: #f3f3f3;
61+
}
62+
63+
&-content {
64+
overflow: hidden;
65+
color: @text-color;
66+
padding: 0 16px;
67+
background-color: #fff;
68+
69+
& > &-box {
70+
margin-top: 16px;
71+
margin-bottom: 16px;
72+
}
73+
74+
&-inactive {
75+
display: none;
76+
}
77+
}
78+
79+
&-item:last-child {
80+
> .@{prefixCls}-content {
81+
border-radius: 0 0 3px 3px;
82+
}
83+
}
84+
85+
& > &-item-active {
86+
> .@{prefixCls}-header {
87+
88+
.arrow {
89+
transform: rotate(90deg);
90+
margin-right: 6px;
91+
}
92+
}
93+
}
94+
}

examples/custom-icon.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
placeholder

examples/custom-icon.js

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
import 'rc-collapse/assets/custom-icon.less';
2+
import 'string.prototype.repeat';
3+
import Collapse, { Panel } from 'rc-collapse';
4+
import React from 'react';
5+
import ReactDOM from 'react-dom';
6+
7+
const text = `
8+
A dog is a type of domesticated animal.
9+
Known for its loyalty and faithfulness,
10+
it can be found as a welcome guest in many households across the world.
11+
`;
12+
13+
function random() {
14+
return parseInt(Math.random() * 10, 10) + 1;
15+
}
16+
17+
const arrowPath = 'M869 487.8L491.2 159.9c-2.9-2.5-6.6-3.9-10.5-3.9h-88' +
18+
'.5c-7.4 0-10.8 9.2-5.2 14l350.2 304H152c-4.4 0-8 3.6-8 8v60c0 4.4 3.' +
19+
'6 8 8 8h585.1L386.9 854c-5.6 4.9-2.2 14 5.2 14h91.5c1.9 0 3.8-0.7 5.' +
20+
'2-2L869 536.2c14.7-12.8 14.7-35.6 0-48.4z';
21+
22+
class Test extends React.Component {
23+
state = {
24+
time: random(),
25+
accordion: false,
26+
activeKey: ['4'],
27+
useIcon: true,
28+
}
29+
30+
onChange = (activeKey) => {
31+
this.setState({
32+
activeKey,
33+
});
34+
}
35+
36+
getItems() {
37+
const items = [];
38+
const icon = this.state.useIcon ? this.getSvgIcon(arrowPath) : undefined;
39+
for (let i = 0, len = 3; i < len; i++) {
40+
const key = i + 1;
41+
items.push(
42+
<Panel header={`This is panel header ${key}`} key={key} disabled={i === 0}>
43+
<p>{text.repeat(this.state.time)}</p>
44+
</Panel>
45+
);
46+
}
47+
items.push(
48+
<Panel header={`This is panel header 4`} key="4">
49+
<Collapse defaultActiveKey="1" arrowIcon={icon}>
50+
<Panel header={`This is panel nest panel`} key="1" id="header-test">
51+
<p>{text}</p>
52+
</Panel>
53+
</Collapse>
54+
</Panel>
55+
);
56+
57+
items.push(
58+
<Panel header={`This is panel header 5`} key="5">
59+
<Collapse defaultActiveKey="1">
60+
<Panel header={`This is panel nest panel`} key="1" id="another-test">
61+
<form>
62+
<label htmlFor="test">Name:&nbsp;</label>
63+
<input type="text" id="test"/>
64+
</form>
65+
</Panel>
66+
</Collapse>
67+
</Panel>
68+
);
69+
70+
return items;
71+
}
72+
73+
setActivityKey = () => {
74+
this.setState({
75+
activeKey: ['2'],
76+
});
77+
}
78+
79+
reRender = () => {
80+
this.setState({
81+
time: random(),
82+
});
83+
}
84+
85+
toggle = () => {
86+
this.setState({
87+
accordion: !this.state.accordion,
88+
});
89+
}
90+
91+
toggleCustomIcon = () => {
92+
this.setState({
93+
useIcon: !this.state.useIcon,
94+
});
95+
}
96+
97+
getSvgIcon = (path) => {
98+
return (
99+
<svg
100+
viewBox="0 0 1024 1024"
101+
width="1em"
102+
height="1em"
103+
fill="currentColor"
104+
style={{ verticalAlign: '-.125em' }}
105+
>
106+
<path d={path} p-id="5827"></path>
107+
</svg>
108+
);
109+
}
110+
111+
render() {
112+
const accordion = this.state.accordion;
113+
const btn = accordion ? 'Mode: accordion' : 'Mode: collapse';
114+
const activeKey = this.state.activeKey;
115+
const icon = this.state.useIcon ? this.getSvgIcon(arrowPath) : undefined;
116+
return (<div style={{ margin: 20, width: 400 }}>
117+
<button onClick={this.reRender}>reRender</button>
118+
<button onClick={this.toggle}>{btn}</button>
119+
<br/><br/>
120+
<button onClick={this.setActivityKey}>active header 2</button>
121+
<br/><br/>
122+
{/* <button onClick={this.toggleCustomIcon}>toggle custom icon</button> */}
123+
<br/><br/>
124+
<Collapse
125+
accordion={accordion}
126+
onChange={this.onChange}
127+
activeKey={activeKey}
128+
arrowIcon={icon}
129+
>
130+
{this.getItems()}
131+
</Collapse>
132+
</div>);
133+
}
134+
}
135+
136+
ReactDOM.render(<Test/>, document.getElementById('__react-content'));

src/Collapse.jsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ class Collapse extends Component {
6161

6262
getItems() {
6363
const activeKey = this.state.activeKey;
64-
const { prefixCls, accordion, destroyInactivePanel } = this.props;
64+
const { prefixCls, accordion, destroyInactivePanel, arrowIcon } = this.props;
6565
const newChildren = [];
6666

6767
Children.forEach(this.props.children, (child, index) => {
@@ -87,6 +87,7 @@ class Collapse extends Component {
8787
accordion,
8888
children: child.props.children,
8989
onItemClick: disabled ? null : () => this.onClickItem(key),
90+
arrowIcon,
9091
};
9192

9293
newChildren.push(React.cloneElement(child, props));
@@ -133,13 +134,15 @@ Collapse.propTypes = {
133134
className: PropTypes.string,
134135
style: PropTypes.object,
135136
destroyInactivePanel: PropTypes.bool,
137+
arrowIcon: PropTypes.node,
136138
};
137139

138140
Collapse.defaultProps = {
139141
prefixCls: 'rc-collapse',
140142
onChange() {},
141143
accordion: false,
142144
destroyInactivePanel: false,
145+
arrowIcon: '',
143146
};
144147

145148
Collapse.Panel = CollapsePanel;

src/Panel.jsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ class CollapsePanel extends Component {
3232
disabled,
3333
accordion,
3434
forceRender,
35+
arrowIcon,
3536
} = this.props;
3637
const headerCls = classNames(`${prefixCls}-header`, {
3738
[headerClass]: headerClass,
@@ -51,7 +52,7 @@ class CollapsePanel extends Component {
5152
aria-expanded={`${isActive}`}
5253
onKeyPress={this.handleKeyPress}
5354
>
54-
{showArrow && <i className="arrow" />}
55+
{showArrow && <i className="arrow" >{arrowIcon}</i>}
5556
{header}
5657
</div>
5758
<Animate
@@ -98,6 +99,7 @@ CollapsePanel.propTypes = {
9899
disabled: PropTypes.bool,
99100
accordion: PropTypes.bool,
100101
forceRender: PropTypes.bool,
102+
arrowIcon: PropTypes.node,
101103
};
102104

103105
CollapsePanel.defaultProps = {

0 commit comments

Comments
 (0)