Skip to content

Commit

Permalink
feat(share): add share component (#335)
Browse files Browse the repository at this point in the history
* refactor(compass): add new icon, rotate compass on hover

* refactor(navigation): add new icons

* refactor(button): remove focus style

* refactor(layer-info): add font, remove icon

* refactor(stories): add share button, fix styles

* refactor(play-button): disable button when no stories are selected

* refactor(button): add disabled property

* style(button): change classnames function

* feat(share): add share component

* refactor(share): add border radius

* refactor(share): add urls to config file

* feat(share): remove instagram and youtube share

* feat(share): add translation
  • Loading branch information
KatvonRivia committed Apr 22, 2020
1 parent 9d0a3ab commit 9fa16a9
Show file tree
Hide file tree
Showing 17 changed files with 251 additions and 38 deletions.
5 changes: 1 addition & 4 deletions i18n/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,8 @@
"modes": "Modi",
"offline": "Offline Modus",
"download": "Anwendung herunterladen",
"twitter": "Twitter",
"facebook": "Facebook",
"whatsApp": "WhatsApp",
"share": "Teile mit der Welt",
"copyLink": "Link kopieren",
"share": "Inhalt teilen",
"export": "Daten exportieren",
"info": "Weitere Informationen",
"about": "Über das Projekt",
Expand Down
5 changes: 1 addition & 4 deletions i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,8 @@
"modes": "Modes",
"offline": "Offline Mode",
"download": "Download App",
"twitter": "Twitter",
"facebook": "Facebook",
"whatsApp": "WhatsApp",
"share": "Share with the world",
"copyLink": "Copy Link",
"share": "Share Content",
"export": "Export Data",
"info": "More Information",
"about": "About this project",
Expand Down
11 changes: 11 additions & 0 deletions src/scripts/components/icons/copy-icon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React, {FunctionComponent} from 'react';

export const CopyIcon: FunctionComponent = () => (
<svg
width="24"
height="24"
viewBox="0 0 24 12"
xmlns="http://www.w3.org/2000/svg">
<path d="M2.3875 6.50006C2.3875 4.57631 3.95125 3.01256 5.875 3.01256H10.375V0.875061H5.875C2.77 0.875061 0.25 3.39506 0.25 6.50006C0.25 9.60506 2.77 12.1251 5.875 12.1251H10.375V9.98756H5.875C3.95125 9.98756 2.3875 8.42381 2.3875 6.50006ZM7 7.62506H16V5.37506H7V7.62506ZM17.125 0.875061H12.625V3.01256H17.125C19.0487 3.01256 20.6125 4.57631 20.6125 6.50006C20.6125 8.42381 19.0487 9.98756 17.125 9.98756H12.625V12.1251H17.125C20.23 12.1251 22.75 9.60506 22.75 6.50006C22.75 3.39506 20.23 0.875061 17.125 0.875061Z" />
</svg>
);
15 changes: 15 additions & 0 deletions src/scripts/components/icons/facebook-icon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React, {FunctionComponent} from 'react';

export const FacebookIcon: FunctionComponent = () => (
<svg
width="27"
height="27"
viewBox="0 0 27 27"
xmlns="http://www.w3.org/2000/svg">
<path
fillRule="evenodd"
clipRule="evenodd"
d="M27 13.5821C27 6.08149 20.9553 0 13.5 0C6.04473 0 0 6.08149 0 13.5821C0 20.3607 4.93606 25.9799 11.3908 27V17.5091H7.96216V13.5821H11.3908V10.5891C11.3908 7.18541 13.407 5.30404 16.4901 5.30404C17.9671 5.30404 19.5124 5.56953 19.5124 5.56953V8.9121H17.8095C16.1332 8.9121 15.6092 9.95879 15.6092 11.0341V13.582H19.3529L18.7549 17.509H15.6091V26.9999C22.0638 25.9817 26.9999 20.3625 26.9999 13.582L27 13.5821Z"
/>
</svg>
);
11 changes: 11 additions & 0 deletions src/scripts/components/icons/instagram-icon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React, {FunctionComponent} from 'react';

export const InstagramIcon: FunctionComponent = () => (
<svg
width="27"
height="27"
viewBox="0 0 27 27"
xmlns="http://www.w3.org/2000/svg">
<path d="M13.503 6.57607C9.67211 6.57607 6.5821 9.66609 6.5821 13.497C6.5821 17.3279 9.67211 20.4179 13.503 20.4179C17.3339 20.4179 20.4239 17.3279 20.4239 13.497C20.4239 9.66609 17.3339 6.57607 13.503 6.57607ZM13.503 17.9965C11.0274 17.9965 9.00351 15.9786 9.00351 13.497C9.00351 11.0153 11.0214 8.99749 13.503 8.99749C15.9847 8.99749 18.0025 11.0153 18.0025 13.497C18.0025 15.9786 15.9786 17.9965 13.503 17.9965ZM22.3213 6.29297C22.3213 7.19046 21.5985 7.90725 20.707 7.90725C19.8095 7.90725 19.0928 7.18444 19.0928 6.29297C19.0928 5.40151 19.8156 4.67869 20.707 4.67869C21.5985 4.67869 22.3213 5.40151 22.3213 6.29297ZM26.9051 7.93134C26.8027 5.76893 26.3088 3.85349 24.7247 2.27535C23.1465 0.697211 21.2311 0.203291 19.0687 0.0948689C16.84 -0.031623 10.16 -0.031623 7.93134 0.0948689C5.77496 0.197267 3.85951 0.691188 2.27535 2.26933C0.691188 3.84746 0.203291 5.76291 0.0948689 7.92532C-0.031623 10.154 -0.031623 16.834 0.0948689 19.0626C0.197267 21.225 0.691188 23.1405 2.27535 24.7186C3.85951 26.2968 5.76893 26.7907 7.93134 26.8991C10.16 27.0256 16.84 27.0256 19.0687 26.8991C21.2311 26.7967 23.1465 26.3028 24.7247 24.7186C26.3028 23.1405 26.7967 21.225 26.9051 19.0626C27.0316 16.834 27.0316 10.16 26.9051 7.93134ZM24.0259 21.4539C23.5561 22.6345 22.6466 23.5441 21.46 24.0199C19.683 24.7247 15.4666 24.562 13.503 24.562C11.5394 24.562 7.31695 24.7186 5.54607 24.0199C4.36548 23.5501 3.45594 22.6405 2.98009 21.4539C2.27535 19.677 2.43798 15.4606 2.43798 13.497C2.43798 11.5334 2.28137 7.31093 2.98009 5.54004C3.44992 4.35945 4.35945 3.44992 5.54607 2.97407C7.32298 2.26933 11.5394 2.43196 13.503 2.43196C15.4666 2.43196 19.6891 2.27535 21.46 2.97407C22.6405 3.44389 23.5501 4.35343 24.0259 5.54004C24.7307 7.31695 24.568 11.5334 24.568 13.497C24.568 15.4606 24.7307 19.683 24.0259 21.4539Z" />
</svg>
);
11 changes: 11 additions & 0 deletions src/scripts/components/icons/twitter-icon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React, {FunctionComponent} from 'react';

export const TwitterIcon: FunctionComponent = () => (
<svg
width="24"
height="24"
viewBox="0 0 24 20"
xmlns="http://www.w3.org/2000/svg">
<path d="M8.49096 22.3594C18.6797 22.3594 24.2525 13.8714 24.2525 6.51068C24.2525 6.26959 24.2525 6.0296 24.2363 5.79068C25.3204 5.00217 26.2563 4.02584 27 2.90742C25.989 3.35789 24.9165 3.6533 23.8183 3.7838C24.9747 3.08767 25.8402 1.99279 26.2537 0.702898C25.1663 1.35172 23.9767 1.80898 22.7362 2.05493C21.901 1.16192 20.7963 0.570592 19.5932 0.372451C18.3901 0.17431 17.1556 0.380404 16.0807 0.958841C15.0058 1.53728 14.1505 2.45581 13.6471 3.5723C13.1437 4.68878 13.0202 5.94098 13.2959 7.13512C11.0935 7.02409 8.93894 6.4486 6.97209 5.44598C5.00524 4.44337 3.27006 3.03605 1.8792 1.31539C1.17082 2.54163 0.953856 3.99325 1.27249 5.37469C1.59112 6.75613 2.42138 7.96352 3.59424 8.75104C2.71268 8.72477 1.85034 8.48565 1.08 8.05385C1.08 8.07665 1.08 8.10054 1.08 8.12444C1.08035 9.41047 1.52308 10.6568 2.3331 11.652C3.14313 12.6472 4.27057 13.3301 5.5242 13.5847C4.70866 13.8084 3.85299 13.841 3.02292 13.6803C3.3769 14.7871 4.06605 15.7549 4.994 16.4485C5.92194 17.1421 7.04226 17.5267 8.19828 17.5485C6.23671 19.0987 3.81354 19.9402 1.31868 19.9377C0.877936 19.9368 0.43762 19.91 0 19.8573C2.53329 21.492 5.48091 22.3591 8.49096 22.355" />
</svg>
);
11 changes: 11 additions & 0 deletions src/scripts/components/icons/youtube-icon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React, {FunctionComponent} from 'react';

export const YoutubeIcon: FunctionComponent = () => (
<svg
width="27"
height="27"
viewBox="0 0 27 27"
xmlns="http://www.w3.org/2000/svg">
<path d="M26.4358 6.97286C26.1253 5.80267 25.2104 4.88108 24.0487 4.56832C21.9431 4 13.5 4 13.5 4C13.5 4 5.05691 4 2.95128 4.56832C1.78962 4.88113 0.874714 5.80267 0.564191 6.97286C0 9.09388 0 13.5192 0 13.5192C0 13.5192 0 17.9445 0.564191 20.0655C0.874714 21.2357 1.78962 22.1189 2.95128 22.4317C5.05691 23 13.5 23 13.5 23C13.5 23 21.9431 23 24.0487 22.4317C25.2104 22.1189 26.1253 21.2357 26.4358 20.0655C27 17.9445 27 13.5192 27 13.5192C27 13.5192 27 9.09388 26.4358 6.97286ZM10.7386 17.5371V9.50134L17.7954 13.5193L10.7386 17.5371Z" />
</svg>
);
1 change: 1 addition & 0 deletions src/scripts/components/layer-info/layer-info.styl
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
display: flex
flex-direction: column
justify-content: center
width: 50%
font-family: NotesEsa

.layerType
Expand Down
10 changes: 3 additions & 7 deletions src/scripts/components/navigation/navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ import Menu from '../menu/menu';
import {LayersIcon} from '../icons/layers-icon';
import {StoryIcon} from '../icons/story-icon';
import showLayerSelectorAction from '../../actions/show-layer-selector';
import Share from '../share/share';
import {MenuIcon} from '../icons/menu-icon';

import styles from './navigation.styl';
import {MenuIcon} from '../icons/menu-icon';
import {ShareIcon} from '../icons/share-icon';

const Navigation: FunctionComponent = () => {
const [showMenu, setShowMenu] = useState(false);
Expand All @@ -30,11 +30,7 @@ const Navigation: FunctionComponent = () => {
onClick={() => dispatch(showLayerSelectorAction(true))}
icon={LayersIcon}
/>
<Button
className={styles.button}
icon={ShareIcon}
onClick={() => console.log('placeholder')}
/>
<Share />
<Button
className={styles.button}
icon={MenuIcon}
Expand Down
5 changes: 2 additions & 3 deletions src/scripts/components/overlay/overlay.styl
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,13 @@
align-items: center
width: 100%
height: 100%
background: $black
opacity: 0.9
background-color: rgba($black, 0.9)

.overlayContent
display: flex
justify-content: center
align-items: center
width: 60%
width: 100%
height: 70%

.closeButton
Expand Down
24 changes: 16 additions & 8 deletions src/scripts/components/overlay/overlay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,34 @@ import {CloseIcon} from '../icons/close-icon';
import styles from './overlay.styl';

interface Props {
onClose: () => void;
onClose?: () => void;
showCloseButton?: boolean;
}

const Overlay: FunctionComponent<Props> = ({children, onClose}) => {
const Overlay: FunctionComponent<Props> = ({
children,
onClose,
showCloseButton = true
}) => {
const modalElement = document.getElementById('modal');

const Content = (
<div className={styles.overlay} onClick={() => onClose()}>
<Button
icon={CloseIcon}
className={styles.closeButton}
onClick={() => onClose()}
/>
<div className={styles.overlay}>
{showCloseButton && (
<Button
icon={CloseIcon}
className={styles.closeButton}
onClick={() => onClose && onClose()}
/>
)}
<div className={styles.overlayContent}>{children}</div>
</div>
);

if (modalElement) {
return createPortal(Content, modalElement);
}

return null;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ import {useIntl} from 'react-intl';

import StoryList from '../story-list/story-list';
import Header from '../header/header';
import {ShareIcon} from '../icons/share-icon';
import Button from '../button/button';
import Share from '../share/share';

import {StoryMode} from '../../types/story-mode';

Expand All @@ -19,7 +18,7 @@ const PresentationSelector: FunctionComponent = () => {
backLink="/"
backButtonId="backToDataMode"
title={intl.formatMessage({id: 'presenter'})}>
<Button icon={ShareIcon} onClick={() => console.log('placeholder')} />
<Share />
</Header>
<StoryList mode={StoryMode.Present} />
</div>
Expand Down
63 changes: 63 additions & 0 deletions src/scripts/components/share/share.styl
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
@require '../../../variables.styl'

.share
display: flex

.shareOverlay
position: relative
display: flex
flex-direction: column
align-items: center
padding: emCalc(40px)
max-width: emCalc(450px)
width: 50%
border-radius: emCalc(4px)
background-color: $darkGrey4

.shareButton
padding-left: emCalc(30px)
font-size: emCalc(18px)
line-height: emCalc(22px)

.closeButton
position: absolute
top: emCalc(10px)
right: emCalc(10px)

.title
margin: 0
margin-bottom: emCalc(15px)
color: $textWhite
text-align: center
font-size: emCalc(36px)
font-family: NotesEsa

.shareButtons
display: flex
flex-wrap: wrap
justify-content: center
align-items: flex-end
width: 100%

.button
display: flex
flex-direction: column
align-items: center
padding: emCalc(15px) emCalc(20px)
outline: 0
border: none
background: none
color: $textColor
text-transform: uppercase
font-size: emCalc(12px)
font-family: NotesEsa

svg
padding-bottom: emCalc(10px)
fill: $main

&:hover
color: $textWhite

svg
fill: $textWhite
88 changes: 88 additions & 0 deletions src/scripts/components/share/share.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import React, {FunctionComponent, useState, useRef} from 'react';
import {FormattedMessage} from 'react-intl';

import {TwitterIcon} from '../icons/twitter-icon';
import {FacebookIcon} from '../icons/facebook-icon';
import {CopyIcon} from '../icons/copy-icon';
import {ShareIcon} from '../icons/share-icon';
import config from '../../config/main';
import Button from '../button/button';
import {CloseIcon} from '../icons/close-icon';
import Overlay from '../overlay/overlay';
import {replaceUrlPlaceholders} from '../../libs/replace-url-placeholders';

import styles from './share.styl';

const Share: FunctionComponent = () => {
const [showShare, setShowShare] = useState(false);
const currentUrl = window.location.href;
const facebookUrl = replaceUrlPlaceholders(config.share.facebook, {
currentUrl
});
const twitterUrl = replaceUrlPlaceholders(config.share.twitter, {
currentUrl
});
const ref = useRef<HTMLInputElement>(null);
const copyUrl = () => {
if (ref.current) {
if (navigator.clipboard) {
navigator.clipboard.writeText(currentUrl);
} else {
ref.current.value = currentUrl;
ref.current.focus();
ref.current.select();
document.execCommand('copy');
}
}
};
return (
<div className={styles.share}>
<Button
className={styles.shareButton}
icon={ShareIcon}
onClick={() => setShowShare(true)}
/>
{showShare && (
<Overlay showCloseButton={false}>
<div className={styles.shareOverlay}>
<Button
icon={CloseIcon}
className={styles.closeButton}
onClick={() => setShowShare(false)}
/>
<h1 className={styles.title}>
<FormattedMessage id="share" />
</h1>
<div className={styles.shareButtons}>
<a
href={twitterUrl}
target={'_blank'}
rel="noopener noreferrer"
className={styles.button}>
<TwitterIcon />
<span>Twitter</span>
</a>
<a
href={facebookUrl}
target={'_blank'}
rel="noopener noreferrer"
className={styles.button}>
<FacebookIcon />
<span>Facebook</span>
</a>
<div className={styles.button} onClick={() => copyUrl()}>
<input ref={ref} type="hidden" contentEditable="true" />
<CopyIcon />
<span>
<FormattedMessage id={'copyLink'} />
</span>
</div>
</div>
</div>
</Overlay>
)}
</div>
);
};

export default Share;
8 changes: 4 additions & 4 deletions src/scripts/components/stories-selector/stories-selector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ import {useIntl} from 'react-intl';

import StoryList from '../story-list/story-list';
import Header from '../header/header';
import Button from '../button/button';
import styles from './stories-selector.styl';
import Share from '../share/share';

import {StoryMode} from '../../types/story-mode';
import {ShareIcon} from '../icons/share-icon';

import styles from './stories-selector.styl';

const StoriesSelector: FunctionComponent = () => {
const intl = useIntl();
Expand All @@ -18,7 +18,7 @@ const StoriesSelector: FunctionComponent = () => {
backLink="/"
backButtonId="backToDataMode"
title={intl.formatMessage({id: 'storyMode'})}>
<Button icon={ShareIcon} onClick={() => console.log('placeholder')} />
<Share />
</Header>
<StoryList mode={StoryMode.Stories} />
</div>
Expand Down
Loading

0 comments on commit 9fa16a9

Please sign in to comment.