From 491b70fae985fac40e299d339e79e1658b782f34 Mon Sep 17 00:00:00 2001 From: Maciej Hirsz <1096222+maciejhirsz@users.noreply.github.com> Date: Wed, 10 Oct 2018 15:01:28 +0200 Subject: [PATCH] Click to copy address or block hash (#82) --- packages/frontend/src/components/Node/Row.tsx | 6 +-- .../frontend/src/components/Node/Truncate.tsx | 9 ++-- packages/frontend/src/components/Tooltip.css | 7 +++ packages/frontend/src/components/Tooltip.tsx | 51 +++++++++++++++++-- 4 files changed, 63 insertions(+), 10 deletions(-) diff --git a/packages/frontend/src/components/Node/Row.tsx b/packages/frontend/src/components/Node/Row.tsx index a603b61..eb9c2ed 100644 --- a/packages/frontend/src/components/Node/Row.tsx +++ b/packages/frontend/src/components/Node/Row.tsx @@ -92,10 +92,10 @@ export default class Row extends React.Component { { label: 'Validator', icon: nodeValidatorIcon, - width: 26, + width: 16, setting: 'validator', render: ({ validator }) => { - return validator ? : '-'; + return validator ? : '-'; } }, { @@ -179,7 +179,7 @@ export default class Row extends React.Component { icon: blockHashIcon, width: 154, setting: 'blockhash', - render: ({ hash }) => + render: ({ hash }) => }, { label: 'Block Time', diff --git a/packages/frontend/src/components/Node/Truncate.tsx b/packages/frontend/src/components/Node/Truncate.tsx index f84fa4f..a57a051 100644 --- a/packages/frontend/src/components/Node/Truncate.tsx +++ b/packages/frontend/src/components/Node/Truncate.tsx @@ -3,17 +3,18 @@ import { Tooltip } from '../'; namespace Truncate { export interface Props { - text: string, - position?: Tooltip.Props['position'] + text: string; + copy?: boolean; + position?: Tooltip.Props['position']; } } class Truncate extends React.Component { public render() { - const { text, position } = this.props; + const { text, position, copy } = this.props; return ( - +
{text}
); diff --git a/packages/frontend/src/components/Tooltip.css b/packages/frontend/src/components/Tooltip.css index 2de568e..10b0b62 100644 --- a/packages/frontend/src/components/Tooltip.css +++ b/packages/frontend/src/components/Tooltip.css @@ -13,6 +13,8 @@ transform: translateX(-50%); display: none; box-shadow: 0 2px 10px rgba(0,0,0,0.5); + pointer-events: none; + transition: color 0.15s ease-in-out; } .Tooltip::after { @@ -27,6 +29,7 @@ border-top: 6px #000 solid; border-left: 6px transparent solid; border-right: 6px transparent solid; + pointer-events: none; } .Tooltip-left { @@ -51,6 +54,10 @@ margin: 0; } +.Tooltip.Tooltip-copied { + color: #888; +} + .Tooltip-container { position: relative; } diff --git a/packages/frontend/src/components/Tooltip.tsx b/packages/frontend/src/components/Tooltip.tsx index 82e0381..9208260 100644 --- a/packages/frontend/src/components/Tooltip.tsx +++ b/packages/frontend/src/components/Tooltip.tsx @@ -5,17 +5,34 @@ import './Tooltip.css'; export namespace Tooltip { export interface Props { text: string; + copy?: boolean; inline?: boolean; className?: string; position?: 'left' | 'right' | 'center'; onInit?: (update: UpdateCallback) => void; } + export interface State { + copied: boolean; + } + export type UpdateCallback = (text: string) => void; } -export class Tooltip extends React.Component { +function copyToClipboard(text: string) { + const el = document.createElement('textarea'); + el.value = text; + document.body.appendChild(el); + el.select(); + document.execCommand('copy'); + document.body.removeChild(el); +}; + +export class Tooltip extends React.Component { + public state = { copied: false }; + private el: HTMLDivElement; + private timer: NodeJS.Timer; public componentDidMount() { if (this.props.onInit) { @@ -23,8 +40,13 @@ export class Tooltip extends React.Component { } } + public componentWillUnmount() { + clearTimeout(this.timer); + } + public render() { const { text, inline, className, position } = this.props; + const { copied } = this.state; let containerClass = 'Tooltip-container'; let tooltipClass = 'Tooltip'; @@ -41,9 +63,13 @@ export class Tooltip extends React.Component { tooltipClass += ` Tooltip-${position}`; } + if (copied) { + tooltipClass += ' Tooltip-copied'; + } + return ( -
-
{text}
+
+
{copied ? 'Copied to clipboard!' : text}
{this.props.children}
); @@ -56,4 +82,23 @@ export class Tooltip extends React.Component { private update = (text: string) => { this.el.textContent = text; } + + private onClick = (event: React.MouseEvent) => { + if (this.props.copy !== true) { + return; + } + + copyToClipboard(this.props.text); + + event.stopPropagation(); + + clearTimeout(this.timer); + + this.setState({ copied: true }); + this.timer = setTimeout(this.restore, 2000); + } + + private restore = () => { + this.setState({ copied: false }); + } }