diff --git a/karma.conf.js b/karma.conf.js index 87cd0a5cc94..6361fb2c41f 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -46,6 +46,15 @@ const newWebpackConfig = Object.assign({}, webpackConfigProd, { }, { test: /\.svg$/, loader: 'url?limit=10000&mimetype=image/svg+xml', + }, { + test: /\.jpg$/, + loader: 'url?limit=10000&mimetype=image/jpeg', + }, { + test: /\.webm$/, + loader: 'url?limit=10000&mimetype=video/webm', + }, { + test: /\.mp4$/, + loader: 'url?limit=10000&mimetype=video/mp4', }], }, output: undefined, diff --git a/src/disco/containers/DiscoPane.js b/src/disco/containers/DiscoPane.js index 9a40471983e..4857dcbb0b9 100644 --- a/src/disco/containers/DiscoPane.js +++ b/src/disco/containers/DiscoPane.js @@ -5,29 +5,62 @@ import { gettext as _, camelCaseProps } from 'core/utils'; import Addon from 'disco/components/Addon'; +import videoPoster from 'disco/img/AddOnsPoster.jpg'; +import videoMp4 from 'disco/video/AddOns.mp4'; +import videoWebm from 'disco/video/AddOns.webm'; + class DiscoPane extends React.Component { static propTypes = { results: PropTypes.arrayOf(PropTypes.object), } + constructor() { + super(); + this.state = {showVideo: false}; + } + + showVideo = (e) => { + e.preventDefault(); + this.setState({showVideo: true}); + this.refs.video.play(); + } + + closeVideo = (e) => { + e.preventDefault(); + this.setState({showVideo: false}); + this.refs.video.pause(); + } + render() { const { results } = this.props; + const { showVideo } = this.state; + return (
-
-
-

{_('Personalize Your Firefox')}

-

{_(dedent`There are thousands of add-ons that let you make Firefox all your - own—everything from fun visual themes to powerful tools and features. - Here are a few great ones to check out.`)}

+
+
+
+

{_('Personalize Your Firefox')}

+

{_(dedent`There are thousands of add-ons that let you make Firefox all your + own—everything from fun visual themes to powerful tools and features. + Here are a few great ones to check out.`)}

+
+
- -

- {_('Click to play')} - {_('to find out more about add-ons')} -

-
{results.map((item, i) => )}
diff --git a/src/disco/css/App.scss b/src/disco/css/App.scss index 140265378aa..ffce4ad7c46 100644 --- a/src/disco/css/App.scss +++ b/src/disco/css/App.scss @@ -23,22 +23,16 @@ img { .disco-pane { box-sizing: content-box; - padding: 50px 20px; margin: 0 auto; max-width: 680px; + padding: 50px 20px; } header { - display: flex; border-bottom: 1px solid $header-border-color; - flex-direction: row; margin-bottom: 40px; padding-bottom: 40px; - .content { - flex-grow: 1; - } - h1 { color: $primary-font-color; display: block; @@ -47,38 +41,109 @@ header { line-height: 1.5; margin: 0 0 20px; } +} - p { - color: $header-copy-font-color; - font-size: 14px; - line-height: 1.28; - } +.disco-content { + color: $header-copy-font-color; + font-size: 14px; + line-height: 1.28; + margin-right: 50px; + width: 415px; - p:last-child { + &:last-child { display: block; margin-bottom: 0; } +} - .play-video { - background: #ccc; +.disco-header, +.disco-content, +.disco-video { + transition: 300ms; +} + +.disco-header { + display: flex; + width: 100%; + + .disco-video { border-radius: 5px; + height: 120px; + width: 215px; + } +} + +.show-video { + padding-bottom: 0; + + .disco-header { + transform: translateX(-465px); + width: 1145px; + } + .disco-content { + opacity: 0; + visibility: hidden; + } + + .disco-video { + margin: 0 84px; + height: 288px; + width: 512px; + } + + .play-video { + display: none; + } + + .close-video { display: block; - flex-grow: 0; - margin-left: 50px; - min-height: 120px; - min-width: 215px; + } +} - &:hover { - color: #fff; - background: #666; - } +.video-wrapper { + position: relative; +} - p { - align-items: center; - display: flex; - height: 100%; - justify-content: center; - margin-top: 0; +.play-video { + align-items: center; + bottom: 0; + display: flex; + justify-content: center; + left: 0; + position: absolute; + right: 0; + text-decoration: none; + top: 0; +} + +.play-video-text { + background: rgba(0, 0, 0, 0.5); + color: #fff; + display: inline-block; + padding: 10px; + transition: background 300ms; + + &::before { + content: "\25BA "; + } +} + +.play-video:hover .play-video-text { + background: rgba(0, 0, 0, 0.3); +} + +.close-video { + display: none; + text-align: center; + + a { + color: #0996F8; + height: 40px; + line-height: 40px; + text-decoration: none; + + &:hover { + text-decoration: underline; } } } diff --git a/src/disco/img/AddOnsPoster.jpg b/src/disco/img/AddOnsPoster.jpg new file mode 100644 index 00000000000..342fe5bb3d3 Binary files /dev/null and b/src/disco/img/AddOnsPoster.jpg differ diff --git a/src/disco/video/AddOns.mp4 b/src/disco/video/AddOns.mp4 new file mode 100644 index 00000000000..520e3f5362f Binary files /dev/null and b/src/disco/video/AddOns.mp4 differ diff --git a/src/disco/video/AddOns.webm b/src/disco/video/AddOns.webm new file mode 100644 index 00000000000..8c008dfac78 Binary files /dev/null and b/src/disco/video/AddOns.webm differ diff --git a/tests/client/disco/containers/TestDiscoPane.js b/tests/client/disco/containers/TestDiscoPane.js index f9926c27d1f..5d4686c2a8d 100644 --- a/tests/client/disco/containers/TestDiscoPane.js +++ b/tests/client/disco/containers/TestDiscoPane.js @@ -1,5 +1,5 @@ import React from 'react'; -import { renderIntoDocument } from 'react-addons-test-utils'; +import { Simulate, renderIntoDocument } from 'react-addons-test-utils'; import { findDOMNode } from 'react-dom'; import { Provider } from 'react-redux'; import createStore from 'disco/store'; @@ -11,11 +11,10 @@ describe('AddonPage', () => { stubAddonManager(); }); - function render({props, state}) { - const store = createStore(state); + function render() { return findDOMNode(renderIntoDocument( - - + + )); } @@ -24,11 +23,26 @@ describe('AddonPage', () => { let root; beforeEach(() => { - root = render({state: {}, props: {}}); + root = render(); }); it('renders an addon', () => { assert.ok(root.querySelector('.addon')); }); }); + + describe('video', () => { + it('is small by default', () => { + const root = render(); + assert.notOk(root.querySelector('.show-video')); + }); + + it('gets bigger and smaller when clicked', () => { + const root = render(); + Simulate.click(root.querySelector('.play-video')); + assert.ok(root.querySelector('.show-video')); + Simulate.click(root.querySelector('.close-video a')); + assert.notOk(root.querySelector('.show-video')); + }); + }); }); diff --git a/webpack-isomorphic-tools-config.js b/webpack-isomorphic-tools-config.js index 18d33b829a7..e3953ed37d0 100644 --- a/webpack-isomorphic-tools-config.js +++ b/webpack-isomorphic-tools-config.js @@ -60,5 +60,12 @@ module.exports = { } }, }, + videos: { + extensions: [ + 'mp4', + 'webm', + ], + parser: WebpackIsomorphicToolsPlugin.url_loader_parser, + }, }, }; diff --git a/webpack.dev.config.babel.js b/webpack.dev.config.babel.js index 53dd0a5f929..772c189bbbd 100644 --- a/webpack.dev.config.babel.js +++ b/webpack.dev.config.babel.js @@ -73,6 +73,15 @@ export default Object.assign({}, webpackConfig, { }, { test: /\.svg$/, loader: 'url?limit=10000&mimetype=image/svg+xml', + }, { + test: /\.jpg$/, + loader: 'url?limit=10000&mimetype=image/jpeg', + }, { + test: /\.webm$/, + loader: 'url?limit=10000&mimetype=video/webm', + }, { + test: /\.mp4$/, + loader: 'url?limit=10000&mimetype=video/mp4', }], }, plugins: [ diff --git a/webpack.prod.config.babel.js b/webpack.prod.config.babel.js index c0b9d5603e7..e3d8e0c5df1 100644 --- a/webpack.prod.config.babel.js +++ b/webpack.prod.config.babel.js @@ -46,6 +46,15 @@ export default { }, { test: /\.svg$/, loader: 'url?limit=10000&mimetype=image/svg+xml', + }, { + test: /\.jpg$/, + loader: 'url?limit=10000&mimetype=image/jpeg', + }, { + test: /\.webm$/, + loader: 'url?limit=10000&mimetype=video/webm', + }, { + test: /\.mp4$/, + loader: 'url?limit=10000&mimetype=video/mp4', }, ], },