diff --git a/docs/src/app/components/pages/components/cards.jsx b/docs/src/app/components/pages/components/cards.jsx index e8ff67845e3145..41e0e3eebb11b1 100644 --- a/docs/src/app/components/pages/components/cards.jsx +++ b/docs/src/app/components/pages/components/cards.jsx @@ -6,6 +6,7 @@ let { Avatar, Card, CardActions, + CardExpandable, CardHeader, CardMedia, CardText, @@ -43,6 +44,30 @@ class CardPage extends React.Component { Donec vulputate interdum sollicitudin. Nunc lacinia auctor quam sed pellentesque. Aliquam dui mauris, mattis quis lacus id, pellentesque lobortis odio. + + + A} + showExpandableButton={true}> + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit. + Donec mattis pretium massa. Aliquam erat volutpat. Nulla facilisi. + Donec vulputate interdum sollicitudin. Nunc lacinia auctor quam sed pellentesque. + Aliquam dui mauris, mattis quis lacus id, pellentesque lobortis odio. + + + + + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit. + Donec mattis pretium massa. Aliquam erat volutpat. Nulla facilisi. + Donec vulputate interdum sollicitudin. Nunc lacinia auctor quam sed pellentesque. + Aliquam dui mauris, mattis quis lacus id, pellentesque lobortis odio. + `; this.desc = @@ -56,7 +81,38 @@ class CardPage extends React.Component { 'Cards do not flip over to reveal information on the back.'; - this.componentInfo = []; + this.componentInfo = [ + { + name: 'Card.Props', + infoArray: [ + { + name: 'initiallyExpanded', + type: 'bool', + header: 'optional', + desc: 'Whether this card is initially expanded.', + }, + ], + }, + { + name: 'Props', + infoArray: [ + { + name: 'expandable', + type: 'bool', + header: 'optional', + desc: 'Whether this card component is expandable. Can be set on any child of the Card component.', + }, + { + name: 'showExpandableButton', + type: 'bool', + header: 'optional', + desc: 'Whether this card component include a button to expand the card. CardTitle, CardHeader ' + + 'and CardActions implement showExpandableButton. Any child component of Card can implements ' + + 'showExpandableButton or forwards the property to a child component supporting it.', + }, + ], + }, + ]; } render() { @@ -90,6 +146,31 @@ class CardPage extends React.Component { Aliquam dui mauris, mattis quis lacus id, pellentesque lobortis odio. +
+ + A} + showExpandableButton={true}> + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit. + Donec mattis pretium massa. Aliquam erat volutpat. Nulla facilisi. + Donec vulputate interdum sollicitudin. Nunc lacinia auctor quam sed pellentesque. + Aliquam dui mauris, mattis quis lacus id, pellentesque lobortis odio. + + + + + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit. + Donec mattis pretium massa. Aliquam erat volutpat. Nulla facilisi. + Donec vulputate interdum sollicitudin. Nunc lacinia auctor quam sed pellentesque. + Aliquam dui mauris, mattis quis lacus id, pellentesque lobortis odio. + + ); } diff --git a/src/card/card-actions.jsx b/src/card/card-actions.jsx index 2aa120d7e64b69..235836475e9ff2 100644 --- a/src/card/card-actions.jsx +++ b/src/card/card-actions.jsx @@ -5,10 +5,16 @@ let CardActions = React.createClass({ return { root: { padding: 8, + position: 'relative', }, }; }, + propTypes: { + expandable: React.PropTypes.bool, + showExpandableButton: React.PropTypes.bool, + }, + render() { let styles = this.getStyles(); diff --git a/src/card/card-expandable.jsx b/src/card/card-expandable.jsx new file mode 100644 index 00000000000000..8931c4ce8fefd8 --- /dev/null +++ b/src/card/card-expandable.jsx @@ -0,0 +1,53 @@ +let React = require('react'); +let OpenIcon = require('../svg-icons/hardware/keyboard-arrow-up'); +let CloseIcon = require('../svg-icons/hardware/keyboard-arrow-down'); +let IconButton = require('../icon-button'); + +let CardExpandable = React.createClass({ + getStyles() { + return { + root: { + right: 4, + top: 0, + bottom: 0, + margin: 'auto', + position: 'absolute', + }, + }; + }, + + propTypes: { + onExpanding: React.PropTypes.func.isRequired, + expanded: React.PropTypes.bool, + }, + + _onExpanding() { + if (this.props.expanded === true) + this.props.onExpanding(false); + else + this.props.onExpanding(true); + }, + + render() { + let styles = this.getStyles(); + + let expandable; + if (this.props.expanded === true) + expandable = ; + else + expandable = ; + + let expandableBtn = ( + + {expandable} + + ); + + + return expandableBtn; + }, +}); + +module.exports = CardExpandable; diff --git a/src/card/card-header.jsx b/src/card/card-header.jsx index 7b0016e2041e0c..0e4018b23ebfc2 100644 --- a/src/card/card-header.jsx +++ b/src/card/card-header.jsx @@ -16,6 +16,8 @@ let CardHeader = React.createClass({ subtitleColor: React.PropTypes.string, subtitleStyle: React.PropTypes.object, textStyle: React.PropTypes.object, + expandable: React.PropTypes.bool, + showExpandableButton: React.PropTypes.bool, }, getDefaultProps() { @@ -32,6 +34,7 @@ let CardHeader = React.createClass({ padding: 16, fontWeight: Styles.Typography.fontWeightMedium, boxSizing: 'border-box', + position: 'relative', }, text: { display: 'inline-block', @@ -75,6 +78,7 @@ let CardHeader = React.createClass({ {this.props.title} {this.props.subtitle} + {this.props.children} ); }, diff --git a/src/card/card-media.jsx b/src/card/card-media.jsx index 6dfd8b4a5b6fec..f2395cfcc0f3a3 100644 --- a/src/card/card-media.jsx +++ b/src/card/card-media.jsx @@ -14,6 +14,7 @@ let CardMedia = React.createClass({ overlayContainerStyle: React.PropTypes.object, overlayContentStyle: React.PropTypes.object, mediaStyle: React.PropTypes.object, + expandable: React.PropTypes.bool, }, getStyles() { diff --git a/src/card/card-text.jsx b/src/card/card-text.jsx index b5cc8bc3440074..1c2235a71d937d 100644 --- a/src/card/card-text.jsx +++ b/src/card/card-text.jsx @@ -10,6 +10,7 @@ let CardText = React.createClass({ propTypes: { color: React.PropTypes.string, style: React.PropTypes.object, + expandable: React.PropTypes.bool, }, getDefaultProps() { diff --git a/src/card/card-title.jsx b/src/card/card-title.jsx index 8ed497b6690f16..630400536e4f63 100644 --- a/src/card/card-title.jsx +++ b/src/card/card-title.jsx @@ -14,6 +14,8 @@ let CardTitle = React.createClass({ subtitle: React.PropTypes.string, subtitleColor: React.PropTypes.string, subtitleStyle: React.PropTypes.object, + expandable: React.PropTypes.bool, + showExpandableButton: React.PropTypes.bool, }, getDefaultProps() { @@ -27,6 +29,7 @@ let CardTitle = React.createClass({ return { root: { padding: 16, + position: 'relative', }, title: { fontSize: 24, @@ -52,6 +55,7 @@ let CardTitle = React.createClass({
{this.props.title} {this.props.subtitle} + {this.props.children}
); }, diff --git a/src/card/card.jsx b/src/card/card.jsx index 6b61e2357974fd..3ebb6d6b450751 100644 --- a/src/card/card.jsx +++ b/src/card/card.jsx @@ -1,24 +1,47 @@ let React = require('react'); let Paper = require('../paper'); let StylePropable = require('../mixins/style-propable'); - +let CardExpandable = require('./card-expandable'); let Card = React.createClass({ mixins:[StylePropable], + getInitialState() { + return { expanded: this.props.initiallyExpanded ? true : false }; + }, + propTypes: { style: React.PropTypes.object, + expandable: React.PropTypes.bool, + initiallyExpanded: React.PropTypes.bool, + }, + + _onExpandable(value) { + this.setState({expanded: value}); }, render() { - let lastElement = React.Children.count(this.props.children) > 1 ? - this.props.children[this.props.children.length - 1] - : this.props.children; + let lastElement; + let newChildren = React.Children.map(this.props.children, (currentChild) => { + if (!currentChild) { + return null; + } + if (this.state.expanded === false && currentChild.props.expandable === true) + return; + if (currentChild.props.showExpandableButton === true) { + lastElement = React.cloneElement(currentChild, {}, + currentChild.props.children, + ); + } else { + lastElement = currentChild; + } + return lastElement; + }, this); // If the last element is text or a title we should add // 8px padding to the bottom of the card - let addBottomPadding = (lastElement.type.displayName === "CardText" || - lastElement.type.displayName === "CardTitle"); + let addBottomPadding = (lastElement && (lastElement.type.displayName === "CardText" || + lastElement.type.displayName === "CardTitle")); let { style, ...other, @@ -32,7 +55,7 @@ let Card = React.createClass({ return (
- {this.props.children} + {newChildren}
); diff --git a/src/card/index.js b/src/card/index.js index bb3d87a7c8c726..2a2b72585cf6e1 100644 --- a/src/card/index.js +++ b/src/card/index.js @@ -5,4 +5,5 @@ module.exports = { CardMedia: require('./card-media'), CardText: require('./card-text'), CardActions: require('./card-actions'), + CardExpandable: require('./card-expandable'), }; diff --git a/src/index.js b/src/index.js index f6bc3ca08ecc02..fc0fba747a3b15 100644 --- a/src/index.js +++ b/src/index.js @@ -5,6 +5,7 @@ module.exports = { BeforeAfterWrapper: require('./before-after-wrapper'), Card: require('./card/card'), CardActions: require('./card/card-actions'), + CardExpandable: require('./card/card-expandable'), CardHeader: require('./card/card-header'), CardMedia: require('./card/card-media'), CardText: require('./card/card-text'),