Skip to content

Commit

Permalink
[added] 'Responsive embed' component
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexKVal committed Sep 27, 2015
1 parent 4005c21 commit ac37698
Show file tree
Hide file tree
Showing 10 changed files with 627 additions and 0 deletions.
451 changes: 451 additions & 0 deletions docs/assets/TheresaKnott_castle.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions docs/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import './assets/logo.png';
import './assets/favicon.ico';
import './assets/thumbnail.png';
import './assets/thumbnaildiv.png';
import './assets/TheresaKnott_castle.svg';

import 'codemirror/mode/htmlmixed/htmlmixed';
import 'codemirror/mode/javascript/javascript';
Expand Down
1 change: 1 addition & 0 deletions docs/examples/.eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
"PanelGroup",
"Popover",
"ProgressBar",
"ResponsiveEmbed",
"Row",
"SplitButton",
"Tab",
Expand Down
9 changes: 9 additions & 0 deletions docs/examples/ResponsiveEmbed.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const responsiveEmbedInstance = (
<div style={{width: 660, height: 'auto'}}>
<ResponsiveEmbed a16by9>
<embed type="image/svg+xml" src="/assets/TheresaKnott_castle.svg" />
</ResponsiveEmbed>
</div>
);

React.render(responsiveEmbedInstance, mountNode);
14 changes: 14 additions & 0 deletions docs/src/ComponentsPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -807,6 +807,19 @@ const ComponentsPage = React.createClass({
<ReactPlayground codeText={Samples.PageHeader} />
</div>

{/* Responsive embed */}
<div className="bs-docs-section">
<h1 className="page-header"><Anchor id="responsive-embed">Responsive embed</Anchor></h1>

<p>Allow browsers to determine video or slideshow dimensions based on the width of their containing block by creating an intrinsic ratio that will properly scale on any device.</p>
<p>You don't need to include <code>frameborder="0"</code> in your <code>iframe</code>s.</p>
<p className="bg-warning">Either <b>16by9</b> or <b>4by3</b> aspect ratio via <code>a16by9</code> or <code>a4by3</code> attribute must be set.</p>
<ReactPlayground codeText={Samples.ResponsiveEmbed} />

<h3><Anchor id="responsive-embed-props">Props</Anchor></h3>
<PropTable component="ResponsiveEmbed"/>
</div>

{/* Wells */}
<div className="bs-docs-section">
<h1 className="page-header"><Anchor id="wells">Wells</Anchor></h1>
Expand Down Expand Up @@ -977,6 +990,7 @@ const ComponentsPage = React.createClass({
<NavItem href="#badges" key={20}>Badges</NavItem>
<NavItem href="#jumbotron" key={21}>Jumbotron</NavItem>
<NavItem href="#page-header" key={22}>Page Header</NavItem>
<NavItem href="#responsive-embed" key={31}>Responsive embed</NavItem>
<NavItem href="#wells" key={23}>Wells</NavItem>
<NavItem href="#glyphicons" key={24}>Glyphicons</NavItem>
<NavItem href="#tables" key={25}>Tables</NavItem>
Expand Down
1 change: 1 addition & 0 deletions docs/src/ReactPlayground.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ const Panel = require('../../src/Panel');
const PanelGroup = require('../../src/PanelGroup');
const Popover = require('../../src/Popover');
const ProgressBar = require('../../src/ProgressBar');
const ResponsiveEmbed = require('../../src/ResponsiveEmbed');
const Row = require('../../src/Row');
const SplitButton = require('../../src/SplitButton');
const Tab = require('../../src/Tab');
Expand Down
1 change: 1 addition & 0 deletions docs/src/Samples.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ export default {
MenuItem: require('fs').readFileSync(__dirname + '/../examples/MenuItem.js', 'utf8'),
ImageResponsive: require('fs').readFileSync(__dirname + '/../examples/ImageResponsive.js', 'utf8'),
ImageShape: require('fs').readFileSync(__dirname + '/../examples/ImageShape.js', 'utf8'),
ResponsiveEmbed: require('fs').readFileSync(__dirname + '/../examples/ResponsiveEmbed.js', 'utf8'),

Overlay: require('fs').readFileSync(__dirname + '/../examples/Overlay.js', 'utf8'),
OverlayCustom: require('fs').readFileSync(__dirname + '/../examples/OverlayCustom.js', 'utf8')
Expand Down
56 changes: 56 additions & 0 deletions src/ResponsiveEmbed.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import React, { PropTypes, cloneElement } from 'react';
import warning from 'react/lib/warning';
import classNames from 'classnames';

class ResponsiveEmbed extends React.Component {
render() {
const { bsClass, className, a16by9, a4by3, ...props } = this.props;
warning(!(!a16by9 && !a4by3), '`a16by9` or `a4by3` attribute must be set.');
warning(!(a16by9 && a4by3), 'Either `a16by9` or `a4by3` attribute can be set. Not both.');

const aspectRatio = {
'embed-responsive-16by9': a16by9,
'embed-responsive-4by3': a4by3
};

return (
<div className={classNames(bsClass, aspectRatio)}>
{cloneElement(
this.props.children,
{
...props,
className: classNames(className, 'embed-responsive-item')
}
)}
</div>
);
}
}

ResponsiveEmbed.defaultProps = {
bsClass: 'embed-responsive',
a16by9: false,
a4by3: false
};

ResponsiveEmbed.propTypes = {
/**
* bootstrap className
* @private
*/
bsClass: PropTypes.string,
/**
* This component accepts only one child element
*/
children: PropTypes.element.isRequired,
/**
* 16by9 aspect ratio
*/
a16by9: PropTypes.bool,
/**
* 4by3 aspect ratio
*/
a4by3: PropTypes.bool
};

export default ResponsiveEmbed;
1 change: 1 addition & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ export Panel from './Panel';
export PanelGroup from './PanelGroup';
export Popover from './Popover';
export ProgressBar from './ProgressBar';
export ResponsiveEmbed from './ResponsiveEmbed';
export Row from './Row';
export SafeAnchor from './SafeAnchor';
export SplitButton from './SplitButton';
Expand Down
92 changes: 92 additions & 0 deletions test/ResponsiveEmbedSpec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import React from 'react';
import ReactTestUtils from 'react/lib/ReactTestUtils';
import ResponsiveEmbed from '../src/ResponsiveEmbed';
import { shouldWarn } from './helpers';

describe('ResponsiveEmbed', () => {
it('should contain `embed-responsive` class', () => {
let instance = ReactTestUtils.renderIntoDocument(
<ResponsiveEmbed a16by9>
<div />
</ResponsiveEmbed>
);

let instanceClassName = React.findDOMNode(instance).className;
assert.ok(instanceClassName, 'embed-responsive');
});

it('should warn if neither `a16by9` nor `a4by3` attribute is set', () => {
ReactTestUtils.renderIntoDocument(
<ResponsiveEmbed>
<div />
</ResponsiveEmbed>
);

shouldWarn('`a16by9` or `a4by3` attribute must be set.');
});

it('should warn about both `a16by9` or `a4by3` attributes set', () => {
ReactTestUtils.renderIntoDocument(
<ResponsiveEmbed a16by9 a4by3>
<div />
</ResponsiveEmbed>
);

shouldWarn('Either `a16by9` or `a4by3` attribute can be set. Not both.');
});

it('should add `embed-responsive-item` class to child element', () => {
const instance = ReactTestUtils.renderIntoDocument(
<ResponsiveEmbed a16by9>
<div />
</ResponsiveEmbed>
);

let child = React.findDOMNode(instance).firstChild;
assert.ok(child.className.match(/\bembed-responsive-item\b/));
});

it('should add custom classes to child element', () => {
const instance = ReactTestUtils.renderIntoDocument(
<ResponsiveEmbed a16by9 className='custom-class'>
<div />
</ResponsiveEmbed>
);

let child = React.findDOMNode(instance).firstChild;
assert.ok(child.className.match(/\bcustom-class\b/));
});

it('should pass custom attributes to child element', () => {
const instance = ReactTestUtils.renderIntoDocument(
<ResponsiveEmbed a16by9 style={{color: 'white'}}>
<div />
</ResponsiveEmbed>
);

let child = React.findDOMNode(instance).firstChild;
assert.equal(child.style.color, 'white');
});

it('should add `embed-responsive-16by9` class with `a16by9` attribute set', () => {
const instance = ReactTestUtils.renderIntoDocument(
<ResponsiveEmbed a16by9>
<div />
</ResponsiveEmbed>
);

let wrapper = React.findDOMNode(instance);
assert.ok(wrapper.className.match(/\bembed-responsive-16by9\b/));
});

it('should add `embed-responsive-4by3` class with `a4by3` attribute set', () => {
const instance = ReactTestUtils.renderIntoDocument(
<ResponsiveEmbed a4by3>
<div />
</ResponsiveEmbed>
);

let wrapper = React.findDOMNode(instance);
assert.ok(wrapper.className.match(/\bembed-responsive-4by3\b/));
});
});

0 comments on commit ac37698

Please sign in to comment.