Skip to content

Commit a72f724

Browse files
committed
Merge pull request react-bootstrap#346 from taion/jjia/panel-table-fill
Support panel-filling tables and list groups
2 parents 0154ccf + 368d619 commit a72f724

4 files changed

Lines changed: 87 additions & 8 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 collapsable defaultExpanded 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
@@ -192,6 +192,10 @@ var ComponentsPage = React.createClass({
192192
<p>Like other components, easily make a panel more meaningful to a particular context by adding a <code>bsStyle</code> prop.</p>
193193
<ReactPlayground codeText={fs.readFileSync(__dirname + '/../examples/PanelContextual.js', 'utf8')} />
194194

195+
<h3 id="panels-contextual">With tables and list groups</h3>
196+
<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>
197+
<ReactPlayground codeText={fs.readFileSync(__dirname + '/../examples/PanelListGroupFill.js', 'utf8')} />
198+
195199
<h3 id="panels-controlled">Controlled PanelGroups</h3>
196200
<p><code>PanelGroup</code>s can be controlled by a parent component. The <code>activeKey</code> prop dictates which panel is open.</p>
197201
<ReactPlayground codeText={fs.readFileSync(__dirname + '/../examples/PanelGroupControlled.js', 'utf8')} />

src/Panel.jsx

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ var Panel = React.createClass({
4242
},
4343

4444
getCollapsableDimensionValue: function () {
45-
return this.refs.body.getDOMNode().offsetHeight;
45+
return this.refs.panel.getDOMNode().scrollHeight;
4646
},
4747

4848
getCollapsableDOMNode: function () {
@@ -76,11 +76,51 @@ 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+
return {key: bodyElements.length};
84+
}
85+
86+
function addPanelBody (children) {
87+
bodyElements.push(
88+
<div className="panel-body" {...getProps()}>
89+
{children}
90+
</div>
91+
);
92+
}
93+
94+
// Handle edge cases where we should not iterate through children.
95+
if (!Array.isArray(allChildren) || allChildren.length == 0) {
96+
addPanelBody(allChildren);
97+
} else {
98+
var panelBodyChildren = [];
99+
100+
function maybeRenderPanelBody () {
101+
if (panelBodyChildren.length == 0) {
102+
return;
103+
}
104+
105+
addPanelBody(panelBodyChildren);
106+
panelBodyChildren = [];
107+
}
108+
109+
allChildren.forEach(function(child) {
110+
if (React.isValidElement(child) && child.props.fill != null) {
111+
maybeRenderPanelBody();
112+
113+
// Separately add the filled element.
114+
bodyElements.push(cloneWithProps(child, getProps()));
115+
} else {
116+
panelBodyChildren.push(child);
117+
}
118+
});
119+
120+
maybeRenderPanelBody();
121+
}
122+
123+
return bodyElements;
84124
},
85125

86126
renderHeading: function () {
@@ -143,4 +183,4 @@ var Panel = React.createClass({
143183
}
144184
});
145185

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

test/PanelSpec.jsx

Lines changed: 23 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,25 @@ 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+
153+
assert.equal(children[0].nodeName, 'DIV');
154+
assert.ok(children[0].className.match(/\bpanel-body\b/));
155+
156+
assert.equal(children[1].nodeName, 'TABLE');
157+
assert.notOk(children[1].className.match(/\bpanel-body\b/));
158+
159+
assert.equal(children[2].nodeName, 'DIV');
160+
assert.ok(children[2].className.match(/\bpanel-body\b/));
161+
})
162+
});

0 commit comments

Comments
 (0)