Skip to content

Commit 9fdf98e

Browse files
author
Jimmy Jia
committed
Support panel-filling tables and list groups
For react-bootstrap#228
1 parent 04797a7 commit 9fdf98e

4 files changed

Lines changed: 91 additions & 7 deletions

File tree

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
var panelInstance = (
2+
<Panel header="Panel heading">
3+
Some default panel content here.
4+
<ListGroup fill>
5+
<ListGroupItem>Item 1</ListGroupItem>
6+
<ListGroupItem>Item 2</ListGroupItem>
7+
<ListGroupItem>&hellip;</ListGroupItem>
8+
</ListGroup>
9+
Some more panel content here.
10+
</Panel>
11+
);
12+
13+
React.render(panelInstance, mountNode);

docs/src/ComponentsPage.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,10 @@ var ComponentsPage = React.createClass({
188188
<p>Like other components, easily make a panel more meaningful to a particular context by adding a <code>bsStyle</code> prop.</p>
189189
<ReactPlayground codeText={fs.readFileSync(__dirname + '/../examples/PanelContextual.js', 'utf8')} />
190190

191+
<h3 id="panels-contextual">With tables and list groups</h3>
192+
<p>Add the <code>fill</code> prop to <code>&lt;Table /&gt;</code> or <code>&lt;ListGroup /&gt;</code> elements to make them fill the panel.</p>
193+
<ReactPlayground codeText={fs.readFileSync(__dirname + '/../examples/PanelListGroupFill.js', 'utf8')} />
194+
191195
<h3 id="panels-controlled">Controlled PanelGroups</h3>
192196
<p><code>PanelGroup</code>s can be controlled by a parent component. The <code>activeKey</code> prop dictates which panel is open.</p>
193197
<ReactPlayground codeText={fs.readFileSync(__dirname + '/../examples/PanelGroupControlled.js', 'utf8')} />

src/Panel.jsx

Lines changed: 57 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,62 @@ var Panel = React.createClass({
7676
},
7777

7878
renderBody: function () {
79-
return (
80-
<div className="panel-body" ref="body">
81-
{this.props.children}
82-
</div>
83-
);
79+
var allChildren = this.props.children;
80+
var bodyElements = [];
81+
82+
function getProps() {
83+
var index = bodyElements.length;
84+
var props = {key: index};
85+
86+
// Arbitrarily assign the body ref to the first element. We can't wrap
87+
// all body elements in a single DOM node anyway, because the fill
88+
// styling depends on the table or list group element being a direct
89+
// descendant of the panel.
90+
if (index == 0) {
91+
props.ref = 'body';
92+
}
93+
94+
return props;
95+
}
96+
97+
function addPanelBody (children) {
98+
bodyElements.push(
99+
<div className="panel-body" {...getProps()}>
100+
{children}
101+
</div>
102+
);
103+
}
104+
105+
// Handle edge cases where we should not iterate through children.
106+
if (!Array.isArray(allChildren) || allChildren.length == 0) {
107+
addPanelBody(allChildren);
108+
} else {
109+
var panelBodyChildren = [];
110+
111+
function maybeRenderPanelBody () {
112+
if (panelBodyChildren.length == 0) {
113+
return;
114+
}
115+
116+
addPanelBody(panelBodyChildren);
117+
panelBodyChildren = [];
118+
}
119+
120+
allChildren.forEach(function(child) {
121+
if (React.isValidElement(child) && child.props.fill != null) {
122+
maybeRenderPanelBody();
123+
124+
// Separately add the filled element.
125+
bodyElements.push(cloneWithProps(child, getProps()));
126+
} else {
127+
panelBodyChildren.push(child);
128+
}
129+
});
130+
131+
maybeRenderPanelBody();
132+
}
133+
134+
return bodyElements;
84135
},
85136

86137
renderHeading: function () {
@@ -143,4 +194,4 @@ var Panel = React.createClass({
143194
}
144195
});
145196

146-
module.exports = Panel;
197+
module.exports = Panel;

test/PanelSpec.jsx

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
var React = require('react');
44
var ReactTestUtils = require('react/lib/ReactTestUtils');
55
var Panel = require('../cjs/Panel');
6+
var Table = require('../cjs/Table');
67

78
describe('Panel', function () {
89
it('Should have class and body', function () {
@@ -137,4 +138,19 @@ describe('Panel', function () {
137138

138139
assert.ok(instance.state.expanded);
139140
});
140-
});
141+
142+
it('Should not wrap panel-filling tables in a panel body', function () {
143+
var instance = ReactTestUtils.renderIntoDocument(
144+
<Panel>
145+
Panel content
146+
<Table fill />
147+
More panel content
148+
</Panel>
149+
);
150+
151+
var children = instance.getDOMNode().children;
152+
assert.equal(children[0].nodeName, 'DIV');
153+
assert.equal(children[1].nodeName, 'TABLE');
154+
assert.equal(children[2].nodeName, 'DIV');
155+
})
156+
});

0 commit comments

Comments
 (0)