'Copy to Clipboard' functionality (#163)
* Adds 'Copy to Clipboard' functionality to all code blocks in readOnly
* Show on hover, move to SC
* 💚
* PR feedback
This commit is contained in:
@@ -77,24 +77,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
code,
|
||||
pre {
|
||||
background: #efefef;
|
||||
border-radius: 3px;
|
||||
border: 1px solid #dedede;
|
||||
}
|
||||
|
||||
pre {
|
||||
padding: 0 .5em;
|
||||
|
||||
code {
|
||||
background: none;
|
||||
border: 0;
|
||||
padding: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
}
|
||||
|
||||
blockquote {
|
||||
border-left: 3px solid #efefef;
|
||||
padding-left: 10px;
|
||||
|
||||
@@ -1,13 +1,40 @@
|
||||
// @flow
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import CopyButton from './CopyButton';
|
||||
import { color } from 'styles/constants';
|
||||
import type { Props } from '../types';
|
||||
|
||||
export default function Code({ children, attributes }: Props) {
|
||||
export default function Code({ children, node, readOnly, attributes }: Props) {
|
||||
return (
|
||||
<pre>
|
||||
<code {...attributes}>
|
||||
{children}
|
||||
</code>
|
||||
</pre>
|
||||
<Container>
|
||||
{readOnly && <CopyButton text={node.text} />}
|
||||
<Pre>
|
||||
<code {...attributes}>
|
||||
{children}
|
||||
</code>
|
||||
</Pre>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
const Pre = styled.pre`
|
||||
padding: .5em 1em;
|
||||
background: ${color.smoke};
|
||||
border-radius: 4px;
|
||||
border: 1px solid ${color.smokeDark};
|
||||
|
||||
code {
|
||||
padding: 0;
|
||||
}
|
||||
`;
|
||||
|
||||
const Container = styled.div`
|
||||
position: relative;
|
||||
|
||||
&:hover {
|
||||
> span {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
49
frontend/components/Editor/components/CopyButton.js
Normal file
49
frontend/components/Editor/components/CopyButton.js
Normal file
@@ -0,0 +1,49 @@
|
||||
// @flow
|
||||
import React, { Component } from 'react';
|
||||
import { observable } from 'mobx';
|
||||
import { observer } from 'mobx-react';
|
||||
import { color } from 'styles/constants';
|
||||
import styled from 'styled-components';
|
||||
import CopyToClipboard from 'components/CopyToClipboard';
|
||||
|
||||
@observer class CopyButton extends Component {
|
||||
@observable copied: boolean = false;
|
||||
copiedTimeout: ?number;
|
||||
|
||||
componentWillUnmount() {
|
||||
clearTimeout(this.copiedTimeout);
|
||||
}
|
||||
|
||||
handleCopy = () => {
|
||||
this.copied = true;
|
||||
this.copiedTimeout = setTimeout(() => (this.copied = false), 3000);
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<StyledCopyToClipboard onCopy={this.handleCopy} {...this.props}>
|
||||
<span>{this.copied ? 'Copied!' : 'Copy to clipboard'}</span>
|
||||
</StyledCopyToClipboard>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const StyledCopyToClipboard = styled(CopyToClipboard)`
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
|
||||
opacity: 0;
|
||||
transition: opacity 50ms ease-in-out;
|
||||
z-index: 1;
|
||||
font-size: 12px;
|
||||
background: ${color.slateLight};
|
||||
border-radius: 2px;
|
||||
padding: 1px 6px;
|
||||
|
||||
&:hover {
|
||||
background: ${color.slate};
|
||||
}
|
||||
`;
|
||||
|
||||
export default CopyButton;
|
||||
12
frontend/components/Editor/components/InlineCode.js
Normal file
12
frontend/components/Editor/components/InlineCode.js
Normal file
@@ -0,0 +1,12 @@
|
||||
// @flow
|
||||
import styled from 'styled-components';
|
||||
import { color } from 'styles/constants';
|
||||
|
||||
const InlineCode = styled.code`
|
||||
padding: .25em;
|
||||
background: ${color.smoke};
|
||||
border-radius: 4px;
|
||||
border: 1px solid ${color.smokeDark};
|
||||
`;
|
||||
|
||||
export default InlineCode;
|
||||
@@ -1,6 +1,7 @@
|
||||
// @flow
|
||||
import React from 'react';
|
||||
import Code from './components/Code';
|
||||
import InlineCode from './components/InlineCode';
|
||||
import Image from './components/Image';
|
||||
import Link from './components/Link';
|
||||
import ListItem from './components/ListItem';
|
||||
@@ -13,7 +14,7 @@ const createSchema = () => {
|
||||
return {
|
||||
marks: {
|
||||
bold: (props: Props) => <strong>{props.children}</strong>,
|
||||
code: (props: Props) => <code>{props.children}</code>,
|
||||
code: (props: Props) => <InlineCode>{props.children}</InlineCode>,
|
||||
italic: (props: Props) => <em>{props.children}</em>,
|
||||
underlined: (props: Props) => <u>{props.children}</u>,
|
||||
deleted: (props: Props) => <del>{props.children}</del>,
|
||||
|
||||
Reference in New Issue
Block a user