Skip to content

Commit

Permalink
feat(react-media): Media component rendered in jsx
Browse files Browse the repository at this point in the history
- Only takes images for now, we'll have separate stories for icons, svg,
  video once those components are built

[Finishes #84493762]

Signed-off-by: Geoff Pleiss <gpleiss@pivotal.io>
  • Loading branch information
stubbornella committed Dec 17, 2014
1 parent 836594f commit b7b1853
Show file tree
Hide file tree
Showing 4 changed files with 295 additions and 0 deletions.
36 changes: 36 additions & 0 deletions src/pivotal-ui/components/media.scss
Original file line number Diff line number Diff line change
Expand Up @@ -233,3 +233,39 @@ For example, `.media-stackable-xs` is stacked on screen sizes from 0-480px and t
width: 1000000px;
}
}


/*doc
---
title: React Media
name: media_react
category: Beta
---
The images or other media can be aligned top, middle, or bottom. The default is top aligned.
The base button renderer. You won't really interact with this directly.
```html_example
<div id="media-example"></div>
```
```jsx_example
React.render(
<Media
leftImageHref='http://www.google.com'
leftImageSource='http://placehold.it/50x50'
leftImageAlignment='middle'
rightImageHref='http://www.google.com'
rightImageSource='http://placehold.it/50x50'
rightImageAlignment='middle'
bodyAlignment='middle'
stackSize='medium'>
something
</Media>,
document.getElementById('media-example')
);
```
*/
80 changes: 80 additions & 0 deletions src/pivotal-ui/javascripts/media.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
'use strict';

var React = require('react/addons');
var _ = require('lodash');
var setClass = React.addons.classSet;

var MediaObject = React.createClass({
render: function () {
var leftClasses = setClass({
'media-left': this.props.horizontalAlignment === 'left',
'media-right': this.props.horizontalAlignment === 'right',
'media-middle': this.props.verticalAlignment == 'middle',
'media-bottom': this.props.verticalAlignment == 'bottom'
});

return (
<a className={leftClasses} href={this.props.imageHref}>
<img alt="..." className="media-object" src={this.props.imageSource} />
</a>
);
}
});

var Media = React.createClass({

render: function () {
var leftMedia,
rightMedia = '';

var classes = setClass({
'media': true,
'media-stackable-xs': this.props.stackSize == 'xsmall',
'media-stackable-sm': this.props.stackSize == 'small',
'media-stackable-md': this.props.stackSize == 'medium',
'media-stackable-lg': this.props.stackSize == 'large'
});

var bodyClasses = setClass({
'media-body': true,
'media-middle': this.props.bodyAlignment == 'middle',
'media-bottom': this.props.bodyAlignment == 'bottom'
});

if (this.props.leftImageSource) {
leftMedia = (
<MediaObject
horizontalAlignment='left'
verticalAlignment={this.props.leftImageAlignment}
imageHref={this.props.leftImageHref}
imageSource={this.props.leftImageSource}>
</MediaObject>
);
}

if (this.props.rightImageSource) {
rightMedia = (
<MediaObject
horizontalAlignment='right'
verticalAlignment={this.props.rightImageAlignment}
imageHref={this.props.rightImageHref}
imageSource={this.props.rightImageSource}>
</MediaObject>
);
}

return (
<div {...this.props} className={classes}>
{leftMedia}
<div className={bodyClasses}>
{this.props.children}
</div>
{rightMedia}
</div>
);
}
});

module.exports = {
Media: Media
};
2 changes: 2 additions & 0 deletions src/pivotal-ui/javascripts/pivotal-ui-react.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ global.DividerInverse = require('./dividers.jsx').DividerInverse;
global.Row = require('./grids.jsx').Row;
global.Col = require('./grids.jsx').Col;

global.Media = require('./media.jsx').Media;

global.PivnetHomepage = require('./pivnet_homepage.jsx').PivnetHomepage;

global.Panel = require('./panels.jsx').Panel;
Expand Down
177 changes: 177 additions & 0 deletions test/spec/javascripts/media_spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
'use strict';

var $ = require('jquery');
var React = require('react/addons');
var TestUtils = React.addons.TestUtils;

var Media = React.createFactory(require('../../../src/pivotal-ui/javascripts/media.jsx').Media);

describe('Media', function() {
beforeEach(function() {
this.node = $('<div id="container"></div>').appendTo('body').get(0);

React.render(
Media({
children: "fop"
}),
this.node
);
});

afterEach(function() {
React.unmountComponentAtNode(this.node);
document.body.removeChild(this.node);
});

it("creates a Media component", function() {
expect($('#container .media .media-body')).toContainText('fop');
});

describe("when left image src is set", function() {
beforeEach(function() {
React.render(
Media({
children: "fop",
leftImageSource: "http://placehold.it/20x20",
leftImageHref: "http://www.google.com"
}),
this.node
);
});

it("displays the media-left link with an image inside", function() {
expect($('#container .media .media-left .media-object').attr('src')).toEqual('http://placehold.it/20x20');
});

it("links to it's href (google, in this case)", function(){
expect($('#container .media .media-left').attr('href')).toEqual('http://www.google.com');
});
});

describe("when left image src is not set", function() {
beforeEach(function() {
React.render(
Media({
children: "fop"
}),
this.node
);
});

it("does not display the media-left link or image inside", function() {
expect($('#container .media')).not.toContainElement('.media-left');
});
});

describe("when right image src is set", function() {
beforeEach(function() {
React.render(
Media({
children: "fop",
rightImageSource: "http://placehold.it/20x20",
rightImageHref: "http://www.google.com"
}),
this.node
);
});

it("displays the media-right link with an image inside", function() {
expect($('#container .media .media-right .media-object').attr('src')).toEqual('http://placehold.it/20x20');
});

it("links to it's href (google, in this case)", function(){
expect($('#container .media .media-right').attr('href')).toEqual('http://www.google.com');
});
});

describe("when image alignment is set to middle", function() {
beforeEach(function() {
React.render(
Media({
children: "fop",
leftImageSource: "http://placehold.it/20x20",
leftImageHref: "http://www.google.com",
leftImageAlignment: "middle"
}),
this.node
);
});

it("displays the media-middle class", function() {
expect($('#container .media .media-left')).toHaveClass('media-middle');
});
});

describe("when image alignment is set to bottom", function() {
beforeEach(function() {
React.render(
Media({
children: "fop",
leftImageSource: "http://placehold.it/20x20",
leftImageHref: "http://www.google.com",
leftImageAlignment: "bottom"
}),
this.node
);
});

it("displays the media-middle class", function() {
expect($('#container .media .media-left')).toHaveClass('media-bottom');
});
});

describe("when body alignment is set to middle", function() {
beforeEach(function() {
React.render(
Media({
children: "fop",
bodyAlignment: "middle"
}),
this.node
);
});

it("displays the media-middle class", function() {
expect($('#container .media .media-body')).toHaveClass('media-middle');
});
});

describe("when media block is set to stack on small screens", function() {
beforeEach(function() {
React.render(
Media({
children: "fop",
leftImageSource: "http://placehold.it/20x20",
leftImageHref: "http://www.google.com",
leftImageAlignment: "middle",
stackSize: "small"
}),
this.node
);
});

it("the media-stackable-sm class is applied to the media element", function() {
expect($('#container .media')).toHaveClass('media-stackable-sm');
});
});

describe("when media block is set to stack on medium screens", function() {
beforeEach(function() {
React.render(
Media({
children: "fop",
leftImageSource: "http://placehold.it/20x20",
leftImageHref: "http://www.google.com",
leftImageAlignment: "middle",
stackSize: "medium"
}),
this.node
);
});

it("the media-stackable-md class is applied to the media element", function() {
expect($('#container .media')).toHaveClass('media-stackable-md');
});
});

});

0 comments on commit b7b1853

Please sign in to comment.