mirror of
https://github.com/Stremio/stremio-web.git
synced 2026-03-29 18:08:49 +00:00
Merge branch 'master' of github.com:Stremio/stremio-web into user-notifications-menu
This commit is contained in:
commit
cf49d2fc7b
12 changed files with 226 additions and 202 deletions
|
|
@ -12,6 +12,7 @@
|
|||
--scroll-bar-width: 6px;
|
||||
--focus-outline-size: 2px;
|
||||
--color-facebook: #4267b2;
|
||||
--color-twitter: #1DA1F2;
|
||||
--color-placeholder: #60606080;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,66 +0,0 @@
|
|||
import React, { useRef } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
import { Input, Modal } from 'stremio/common';
|
||||
import Icon from 'stremio-icons/dom';
|
||||
import styles from './styles';
|
||||
|
||||
const renderInput = ({ className, href, icon, label }) => {
|
||||
return (
|
||||
<Input className={classnames(styles['button'], className)} type={'link'} href={href} target={'_blank'}>
|
||||
<Icon className={styles['icon']} icon={icon} />{label}
|
||||
</Input>
|
||||
);
|
||||
};
|
||||
|
||||
const renderUrl = (url) => {
|
||||
const inputRef = useRef(null);
|
||||
const copyToClipboard = () => {
|
||||
inputRef.current.select();
|
||||
document.execCommand('copy');
|
||||
};
|
||||
|
||||
if (url.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={styles['url-container']}>
|
||||
<input ref={inputRef} className={styles['url']} type={'text'} tabIndex={'-1'} defaultValue={url} readOnly />
|
||||
<Input className={styles['copy-button']} type={'button'} onClick={copyToClipboard}>
|
||||
<Icon className={styles['icon']} icon={'ic_link'} />
|
||||
<div className={styles['label']}>Copy</div>
|
||||
</Input>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const ShareModal = (props) => {
|
||||
return (
|
||||
<Modal>
|
||||
<div className={styles['share-modal']}>
|
||||
<Input className={styles['x-container']} type={'button'}>
|
||||
<Icon className={styles['icon']} icon={'ic_x'} onClick={props.onClose} />
|
||||
</Input>
|
||||
<div className={styles['info-container']}>
|
||||
<div className={styles['share-label']}>Share</div>
|
||||
<div className={styles['buttons']}>
|
||||
{renderInput({ className: styles['facebook-button'], href: `https://www.facebook.com/sharer/sharer.php?u=${props.url}`, icon: 'ic_facebook', label: 'FACEBOOK' })}
|
||||
{renderInput({ className: styles['twitter-button'], href: `https://twitter.com/home?status=${props.url}`, icon: 'ic_twitter', label: 'TWITTER' })}
|
||||
</div>
|
||||
{renderUrl(props.url)}
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
ShareModal.propTypes = {
|
||||
url: PropTypes.string.isRequired,
|
||||
onClose: PropTypes.func
|
||||
};
|
||||
ShareModal.defaultProps = {
|
||||
url: ''
|
||||
};
|
||||
|
||||
export default ShareModal;
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
import ShareModal from './ShareModal';
|
||||
|
||||
export default ShareModal;
|
||||
|
|
@ -1,131 +0,0 @@
|
|||
.share-modal {
|
||||
--share-modal-width: 350px;
|
||||
--spacing: 20px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.share-modal {
|
||||
padding: calc(var(--spacing) * 0.5);
|
||||
width: var(--share-modal-width);
|
||||
color: var(--color-surfacelighter);
|
||||
background-color: var(--color-surfacelighter);
|
||||
|
||||
.x-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-end;
|
||||
|
||||
.icon {
|
||||
padding: 0.2em;
|
||||
width: 1.2em;
|
||||
height: 1.2em;
|
||||
fill: var(--color-surfacedark);
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
fill: var(--color-surface);
|
||||
}
|
||||
}
|
||||
|
||||
&:focus {
|
||||
.icon {
|
||||
background-color: var(--color-surfacelight);
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.icon {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.info-container {
|
||||
padding: 0 var(--spacing) calc(var(--spacing) * 1.2) var(--spacing);
|
||||
|
||||
.share-label {
|
||||
font-size: 1.1em;
|
||||
color: var(--color-backgrounddarker);
|
||||
}
|
||||
|
||||
.buttons {
|
||||
padding: var(--spacing) 0;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
.button {
|
||||
flex: 1;
|
||||
height: 3.2em;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 0.8em;
|
||||
color: var(--color-surfacelighter);
|
||||
cursor: pointer;
|
||||
|
||||
.icon {
|
||||
margin-right: 0.6em;
|
||||
width: 1.4em;
|
||||
height: 1.4em;
|
||||
fill: var(--color-surfacelighter);
|
||||
}
|
||||
|
||||
&:focus, &:hover {
|
||||
filter: brightness(1.2);
|
||||
}
|
||||
|
||||
&:not(:last-child) {
|
||||
margin-right: 2em;
|
||||
}
|
||||
}
|
||||
|
||||
.facebook-button {
|
||||
background-color: var(--color-secondary);
|
||||
}
|
||||
|
||||
.twitter-button {
|
||||
background-color: var(--color-secondarylighter);
|
||||
}
|
||||
}
|
||||
|
||||
.url-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
border: calc(var(--focusable-border-size) * 0.5) solid var(--color-surface);
|
||||
|
||||
.url {
|
||||
flex: 4;
|
||||
padding: calc(var(--spacing) * 0.5);
|
||||
font-size: 0.9em;
|
||||
text-align: center;
|
||||
color: var(--color-surfacedark);
|
||||
}
|
||||
|
||||
.copy-button {
|
||||
flex: 1;
|
||||
padding: calc(var(--spacing) * 0.5);
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
background-color: var(--color-surface);
|
||||
cursor: pointer;
|
||||
|
||||
.icon {
|
||||
margin-right: 0.4em;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
fill: var(--color-surfacedarker);
|
||||
}
|
||||
|
||||
.label {
|
||||
color: var(--color-surfacedarker);
|
||||
}
|
||||
|
||||
&:focus, &:hover {
|
||||
background-color: var(--color-surface60);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
66
src/common/SharePrompt/SharePrompt.js
Normal file
66
src/common/SharePrompt/SharePrompt.js
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
const React = require('react');
|
||||
const PropTypes = require('prop-types');
|
||||
const classnames = require('classnames');
|
||||
const Icon = require('stremio-icons/dom');
|
||||
const { useFocusable } = require('stremio-router');
|
||||
const Button = require('stremio/common/Button');
|
||||
const TextInput = require('stremio/common/TextInput');
|
||||
const styles = require('./styles');
|
||||
|
||||
const SharePrompt = ({ className, label, url, close }) => {
|
||||
const inputRef = React.useRef(null);
|
||||
const focusable = useFocusable();
|
||||
const copyToClipboard = React.useCallback(() => {
|
||||
inputRef.current.select();
|
||||
document.execCommand('copy');
|
||||
}, []);
|
||||
React.useEffect(() => {
|
||||
const onKeyUp = (event) => {
|
||||
if (event.key === 'Escape' && typeof close === 'function') {
|
||||
close();
|
||||
}
|
||||
};
|
||||
if (focusable) {
|
||||
window.addEventListener('keyup', onKeyUp);
|
||||
}
|
||||
return () => {
|
||||
window.removeEventListener('keyup', onKeyUp);
|
||||
};
|
||||
}, [close, focusable]);
|
||||
return (
|
||||
<div className={classnames(className, styles['share-prompt-container'])}>
|
||||
<Button className={styles['close-button-container']}>
|
||||
<Icon className={styles['icon']} icon={'ic_x'} onClick={close} />
|
||||
</Button>
|
||||
<div className={styles['share-prompt-content']}>
|
||||
<div className={styles['share-prompt-label']}>{label}</div>
|
||||
<div className={styles['buttons-container']}>
|
||||
<Button className={classnames(styles['button-container'], styles['facebook-button'])} href={`https://www.facebook.com/sharer/sharer.php?u=${url}`} target={'_blank'}>
|
||||
<Icon className={styles['icon']} icon={'ic_facebook'} />
|
||||
<div className={styles['label']}>FACEBOOK</div>
|
||||
</Button>
|
||||
<Button className={classnames(styles['button-container'], styles['twitter-button'])} href={`https://twitter.com/home?status=${url}`} target={'_blank'}>
|
||||
<Icon className={styles['icon']} icon={'ic_twitter'} />
|
||||
<div className={styles['label']}>TWITTER</div>
|
||||
</Button>
|
||||
</div>
|
||||
<div className={styles['url-container']}>
|
||||
<TextInput ref={inputRef} className={styles['url-content']} type={'text'} tabIndex={'-1'} defaultValue={url} readOnly />
|
||||
<Button className={styles['copy-button']} onClick={copyToClipboard}>
|
||||
<Icon className={styles['icon']} icon={'ic_link'} />
|
||||
<div className={styles['label']}>Copy</div>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
SharePrompt.propTypes = {
|
||||
className: PropTypes.string,
|
||||
label: PropTypes.string.isRequired,
|
||||
url: PropTypes.string.isRequired,
|
||||
close: PropTypes.func
|
||||
};
|
||||
|
||||
module.exports = SharePrompt;
|
||||
3
src/common/SharePrompt/index.js
Normal file
3
src/common/SharePrompt/index.js
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
const SharePrompt = require('./SharePrompt');
|
||||
|
||||
module.exports = SharePrompt;
|
||||
134
src/common/SharePrompt/styles.less
Normal file
134
src/common/SharePrompt/styles.less
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
.share-prompt-container {
|
||||
position: relative;
|
||||
z-index: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 2.4rem 0;
|
||||
background-color: var(--color-surfacelighter);
|
||||
|
||||
.close-button-container {
|
||||
position: absolute;
|
||||
top: 0.4rem;
|
||||
right: 0.4rem;
|
||||
z-index: 1;
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
padding: 0.4rem;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--color-surfacelight);
|
||||
}
|
||||
|
||||
.icon {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
fill: var(--color-backgrounddarker);
|
||||
}
|
||||
}
|
||||
|
||||
.share-prompt-content {
|
||||
padding: 0 2.4rem;
|
||||
|
||||
.share-prompt-label {
|
||||
font-size: 1.3rem;
|
||||
color: var(--color-backgrounddarker);
|
||||
}
|
||||
|
||||
.buttons-container {
|
||||
flex: none;
|
||||
align-self: stretch;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
margin: 1.4rem 0;
|
||||
|
||||
.button-container {
|
||||
flex-grow: 0;
|
||||
flex-shrink: 1;
|
||||
flex-basis: 14rem;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0.6rem 1rem;
|
||||
|
||||
.icon {
|
||||
flex: none;
|
||||
width: 1.4rem;
|
||||
height: 1.4rem;
|
||||
margin-right: 0.6rem;
|
||||
fill: var(--color-surfacelighter);
|
||||
}
|
||||
|
||||
.label {
|
||||
flex-grow: 0;
|
||||
flex-shrink: 1;
|
||||
flex-basis: auto;
|
||||
font-size: 0.8rem;
|
||||
font-weight: 500;
|
||||
color: var(--color-surfacelighter);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
&:hover, &:focus {
|
||||
filter: brightness(1.2);
|
||||
}
|
||||
|
||||
&:not(:last-child) {
|
||||
margin-right: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
.facebook-button {
|
||||
background-color: var(--color-facebook);
|
||||
}
|
||||
|
||||
.twitter-button {
|
||||
background-color: var(--color-twitter);
|
||||
}
|
||||
}
|
||||
|
||||
.url-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
border: thin solid var(--color-surface);
|
||||
|
||||
.url-content {
|
||||
flex: 1;
|
||||
min-width: 12rem;
|
||||
padding: 0.6rem 1rem;
|
||||
font-size: 0.9rem;
|
||||
color: var(--color-surfacedark);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.copy-button {
|
||||
flex-grow: 0;
|
||||
flex-shrink: 1;
|
||||
flex-basis: auto;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0.6rem 1rem;
|
||||
background-color: var(--color-surface);
|
||||
|
||||
.icon {
|
||||
flex: none;
|
||||
width: 1.4rem;
|
||||
height: 1.4rem;
|
||||
margin-right: 0.6rem;
|
||||
fill: var(--color-surfacedarker);
|
||||
}
|
||||
|
||||
.label {
|
||||
color: var(--color-surfacedarker);
|
||||
}
|
||||
|
||||
&:hover, &:focus {
|
||||
filter: brightness(1.2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -12,7 +12,7 @@ const MetaRowPlaceholder = require('./MetaRowPlaceholder');
|
|||
const NavBar = require('./NavBar');
|
||||
const PlayIconCircleCentered = require('./PlayIconCircleCentered');
|
||||
const Popup = require('./Popup');
|
||||
const ShareModal = require('./ShareModal');
|
||||
const SharePrompt = require('./SharePrompt');
|
||||
const Slider = require('./Slider');
|
||||
const TextInput = require('./TextInput');
|
||||
const routesRegexp = require('./routesRegexp');
|
||||
|
|
@ -37,7 +37,7 @@ module.exports = {
|
|||
NavBar,
|
||||
PlayIconCircleCentered,
|
||||
Popup,
|
||||
ShareModal,
|
||||
SharePrompt,
|
||||
Slider,
|
||||
TextInput,
|
||||
routesRegexp,
|
||||
|
|
|
|||
14
storybook/stories/SharePrompt/SharePrompt.js
Normal file
14
storybook/stories/SharePrompt/SharePrompt.js
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
const React = require('react');
|
||||
const { storiesOf } = require('@storybook/react');
|
||||
const { action } = require('@storybook/addon-actions');
|
||||
const { SharePrompt } = require('stremio/common');
|
||||
const styles = require('./styles');
|
||||
|
||||
storiesOf('SharePrompt', module).add('SharePrompt', () => (
|
||||
<SharePrompt
|
||||
className={styles['share-prompt-container']}
|
||||
label={'Demo label'}
|
||||
url={'Demo url'}
|
||||
close={action('Demo item closed')}
|
||||
/>
|
||||
));
|
||||
1
storybook/stories/SharePrompt/index.js
Normal file
1
storybook/stories/SharePrompt/index.js
Normal file
|
|
@ -0,0 +1 @@
|
|||
require('./SharePrompt');
|
||||
4
storybook/stories/SharePrompt/styles.less
Normal file
4
storybook/stories/SharePrompt/styles.less
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
.share-prompt-container {
|
||||
width: 24rem;
|
||||
margin: 1rem;
|
||||
}
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
require('./Addon');
|
||||
require('./MetaItem');
|
||||
require('./ColorPicker');
|
||||
require('./SharePrompt');
|
||||
|
|
|
|||
Loading…
Reference in a new issue