Skip to content

Commit

Permalink
feat: Add 'Copy link to clipboard' action (#110)
Browse files Browse the repository at this point in the history
  • Loading branch information
michaeltaranto committed Dec 20, 2019
1 parent 14e114c commit d57e538
Show file tree
Hide file tree
Showing 9 changed files with 133 additions and 12 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@
"codemirror": "^5.49.2",
"command-line-args": "^5.1.1",
"command-line-usage": "^6.1.0",
"copy-to-clipboard": "^3.2.0",
"css-loader": "^3.3.2",
"current-git-branch": "^1.1.0",
"dedent": "^0.7.0",
Expand Down
4 changes: 2 additions & 2 deletions src/Playroom/CodeEditor/CodeEditor.less
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
margin: 0;
padding: 0;
box-shadow: @shadow-small;
border-radius: 3px;
border-radius: @radius-medium;
background-color: @code-background;
font-size: 90%;
line-height: 150%;
Expand All @@ -70,7 +70,7 @@
.CodeMirror-hint {
margin: 0;
padding: 4px 8px;
border-radius: 2px;
border-radius: @radius-small;
white-space: pre;
color: @black;
cursor: pointer;
Expand Down
2 changes: 1 addition & 1 deletion src/Playroom/Playroom.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const getThemeVariable = (name: string) => {

const MIN_HEIGHT =
getThemeVariable('toolbar-item-size') *
getThemeVariable('toolbar-item-count');
getThemeVariable('toolbar-max-item-count');
const MIN_WIDTH =
getThemeVariable('toolbar-open-size') +
getThemeVariable('toolbar-closed-size');
Expand Down
43 changes: 39 additions & 4 deletions src/Playroom/Toolbar/Toolbar.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React, { useContext, useReducer, ReactChild } from 'react';
import React, { useContext, useReducer, ReactChild, useEffect } from 'react';
import copy from 'copy-to-clipboard';
import classnames from 'classnames';
import { PlayroomProps } from '../Playroom';
import ViewPreference from '../ViewPreference/ViewPreference';
Expand All @@ -9,6 +10,7 @@ import ToolbarItem from '../ToolbarItem/ToolbarItem';
import EditorUndockedSvg from './icons/EditorUndockedSvg';
import EditorBottomSvg from './icons/EditorBottomSvg';
import EditorRightSvg from './icons/EditorRightSvg';
import ShareSvg from './icons/ShareSvg';

// @ts-ignore
import styles from './Toolbar.less';
Expand All @@ -21,18 +23,21 @@ interface Props {
interface State {
open: boolean;
activePreference: 'theme' | 'width' | 'position' | null;
copying: boolean;
}

const initialState: State = {
open: false,
activePreference: null
activePreference: null,
copying: false
};

type Action =
| { type: 'toggleThemes' }
| { type: 'toggleWidths' }
| { type: 'togglePosition' }
| { type: 'closeToolbar' };
| { type: 'closeToolbar' }
| { type: 'copyLink'; payload: { active: boolean } };

const reducer = (state: State, action: Action): State => {
switch (action.type) {
Expand Down Expand Up @@ -74,6 +79,15 @@ const reducer = (state: State, action: Action): State => {
};
}

case 'copyLink': {
return {
...state,
open: false,
activePreference: null,
copying: action.payload.active
};
}

default:
return state;
}
Expand Down Expand Up @@ -105,11 +119,20 @@ export default ({ themes: allThemes, widths: allWidths }: Props) => {
dispatchPreference
] = useContext(StoreContext);

const [{ open, activePreference }, dispatch] = useReducer(
const [{ open, activePreference, copying }, dispatch] = useReducer(
reducer,
initialState
);

useEffect(() => {
if (copying) {
copy(window.location.href);
setTimeout(() => {
dispatch({ type: 'copyLink', payload: { active: false } });
}, 2000);
}
}, [copying]);

const isThemeOpen = activePreference === 'theme' && open;
const isWidthOpen = activePreference === 'width' && open;
const isPositionOpen = activePreference === 'position';
Expand Down Expand Up @@ -162,6 +185,18 @@ export default ({ themes: allThemes, widths: allWidths }: Props) => {
>
<WidthsSvg />
</ToolbarItem>

<ToolbarItem
active={copying}
title="Copy link to clipboard"
statusMessage="Link copied to clipboard"
showStatus={copying}
onClick={() =>
dispatch({ type: 'copyLink', payload: { active: true } })
}
>
<ShareSvg />
</ToolbarItem>
</div>

<ToolbarItem
Expand Down
47 changes: 47 additions & 0 deletions src/Playroom/Toolbar/icons/ShareSvg.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import React, { SVGProps } from 'react';

export default (props: SVGProps<SVGSVGElement>) => (
<svg
viewBox="0 0 24 24"
focusable="false"
fill="currentColor"
width="24"
height="24"
{...props}
>
<circle
cx={18}
cy={6}
r={2}
fill="none"
stroke="currentColor"
strokeWidth={2}
strokeMiterlimit={10}
/>
<circle
cx={6}
cy={12}
r={2}
fill="none"
stroke="currentColor"
strokeWidth={2}
strokeMiterlimit={10}
/>
<circle
cx={18}
cy={18}
r={2}
fill="none"
stroke="currentColor"
strokeWidth={2}
strokeMiterlimit={10}
/>
<path
fill="none"
stroke="currentColor"
strokeWidth={2}
strokeLinejoin="round"
d="M8 13l8 4m0-10l-8 4"
/>
</svg>
);
23 changes: 22 additions & 1 deletion src/Playroom/ToolbarItem/ToolbarItem.less
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
width: @toolbar-closed-size;
border: 0;
padding: 0;
background-color: transparent;
background-color: @toolbar-background;
appearance: none;
outline: none;
display: flex;
Expand Down Expand Up @@ -91,3 +91,24 @@
opacity: 0;
}
}

.status {
@height: 30px;
position: absolute;
top: (@toolbar-item-size - @height) /2;
right: @toolbar-closed-size + 10px;
height: @height;
border-radius: 4px;
padding: 0 10px;
display: flex;
align-items: center;
font: @text-standard;
white-space: nowrap;
background-color: @green-1;
transition: @transition-medium;

&:not(.status_show) {
opacity: 0;
transform: translateX(10px);
}
}
11 changes: 11 additions & 0 deletions src/Playroom/ToolbarItem/ToolbarItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,17 @@ interface Props {
active?: boolean;
title: string;
count?: number;
statusMessage?: string;
showStatus?: boolean;
onClick: () => void;
}
export default ({
children,
active = false,
title,
count = 0,
statusMessage,
showStatus = false,
onClick
}: Props) => {
const hasSelection = count > 0;
Expand Down Expand Up @@ -45,6 +49,13 @@ export default ({
>
{count || ''}
</div>
<div
className={classnames(styles.status, {
[styles.status_show]: showStatus && statusMessage // eslint-disable-line css-modules/no-undef-class
})}
>
{statusMessage}
</div>
</div>
);
};
6 changes: 3 additions & 3 deletions src/Playroom/ViewPreference/ViewPreference.less
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
bottom: 0;
left: 0;
right: 0;
border-radius: 6px;
border-radius: @radius-large;
background-color: currentColor;
cursor: pointer;
opacity: 0;
Expand Down Expand Up @@ -85,7 +85,7 @@
padding: @padding-size;
margin-right: 15px;
position: relative;
border-radius: 6px;
border-radius: @radius-large;
box-shadow: inset 0 0 0px 1px currentColor;

&::after {
Expand All @@ -95,7 +95,7 @@
bottom: 0;
left: 0;
right: 0;
border-radius: 4px;
border-radius: @radius-medium;
box-shadow: 0 0 0 4px currentColor;
transition: @transition-fast;
opacity: 0;
Expand Down
8 changes: 7 additions & 1 deletion src/Playroom/variables.less
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
@blue-2: #005ad2;
@blue-3: #00439c;
@blue-4: #040080;
@green-1: #c5f5e9;
@white: #fff;
@gray-1: #f4f4f4;
@gray-2: #e8e8e8;
Expand All @@ -28,6 +29,11 @@
// Box Shadow:
@shadow-small: 0 2px 8px rgba(18, 21, 26, 0.3);

// Border radii
@radius-small: 2px;
@radius-medium: 4px;
@radius-large: 6px;

// Transitions
@transition-speed-fast: 100ms;
@transition-speed-medium: 200ms;
Expand Down Expand Up @@ -62,7 +68,7 @@
@toolbar-closed-size: 60px;
@toolbar-open-size: 300px;
@toolbar-item-size: 60px;
@toolbar-item-count: 5;
@toolbar-max-item-count: 4;
@toolbar-foregound: @gray-4;
@toolbar-background: @white;
@toolbar-highlight: @blue-2;
Expand Down

0 comments on commit d57e538

Please sign in to comment.