Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add tooltip to shareable urls copy button #1614

Merged
merged 6 commits into from
Nov 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions RELEASE.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ Please follow the established format:
- Use present tense (e.g. 'Add new feature')
- Include the ID number for the related PR (or PRs) in parentheses
-->

# Upcoming Release

## Bug fixes and other changes

- Fix dataset factory patterns in Experiment Tracking. (#1588)
- Improved feedback for copy to clipboard feature. (#1614)

# Release 6.6.1

Expand Down
6 changes: 5 additions & 1 deletion src/components/flowchart/flowchart.js
Original file line number Diff line number Diff line change
Expand Up @@ -658,7 +658,11 @@ export class FlowChart extends Component {
})}
ref={this.layerNamesRef}
/>
<Tooltip chartSize={chartSize} {...this.state.tooltip} />
<Tooltip
chartSize={chartSize}
{...this.state.tooltip}
style={{ fontSize: '1.5em' }}
/>
</div>
);
}
Expand Down
31 changes: 16 additions & 15 deletions src/components/shareable-url-modal/shareable-url-modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import React, { useEffect, useState } from 'react';
import { connect } from 'react-redux';
import classnames from 'classnames';
import { toggleShareableUrlModal } from '../../actions';
import modifiers from '../../utils/modifiers';
import { s3BucketRegions } from '../../config';

import Button from '../ui/button';
Expand All @@ -13,6 +12,7 @@ import Input from '../ui/input';
import LoadingIcon from '../icons/loading';
import Modal from '../ui/modal';
import MenuOption from '../ui/menu-option';
import Tooltip from '../ui/tooltip';

import './shareable-url-modal.scss';

Expand Down Expand Up @@ -117,7 +117,10 @@ const ShareableUrlModal = ({ onToggleModal, visible }) => {
const onCopyClick = () => {
window.navigator.clipboard.writeText(responseUrl);
setShowCopied(true);
setTimeout(() => setShowCopied(false), 1500);

setTimeout(() => {
setShowCopied(false);
}, 1500);
};

const handleModalClose = () => {
Expand Down Expand Up @@ -246,32 +249,30 @@ const ShareableUrlModal = ({ onToggleModal, visible }) => {
<div className="shareable-url-modal__label">Hosted link</div>
<div className="shareable-url-modal__url-wrapper">
<a
className={modifiers('shareable-url-modal__result-url', {
visible: !showCopied,
})}
href={responseUrl}
className="shareable-url-modal__result-url"
href="/"
target="_blank"
rel="noopener noreferrer"
>
{responseUrl}
</a>
{window.navigator.clipboard && (
<>
<span
className={modifiers('copy-message', {
visible: showCopied,
})}
>
Copied to clipboard.
</span>
<div className="shareable-url-modal__result-action">
<IconButton
ariaLabel="Copy run command to clipboard."
className="copy-button"
dataHeapEvent={`clicked.run_command`}
icon={CopyIcon}
onClick={onCopyClick}
/>
</>
<Tooltip
text="Copied!"
visible={showCopied}
noDelay
centerArrow
arrowSize="small"
/>
</div>
)}
</div>
</div>
Expand Down
7 changes: 5 additions & 2 deletions src/components/shareable-url-modal/shareable-url-modal.scss
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,6 @@

.pipeline-icon--container {
display: block;
margin: 0 12px 0 16px;
position: absolute;
right: 6px;
}
}
Expand All @@ -161,6 +159,11 @@
font-size: 16px;
line-height: 20px;
}

&__result-action {
position: relative;
margin: 0 12px 0 16px;
}
}

.shareable-url-timestamp {
Expand Down
41 changes: 19 additions & 22 deletions src/components/ui/command-copier/command-copier.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useState } from 'react';
import modifiers from '../../../utils/modifiers';
import MetaDataValue from '../../metadata/metadata-value';
import IconButton from '../../ui/icon-button';
import Tooltip from '../tooltip';
import CopyIcon from '../../icons/copy';
import './command-copier.scss';

Expand All @@ -11,37 +11,34 @@ const CommandCopier = ({ command, isCommand }) => {
const onCopyClick = () => {
window.navigator.clipboard.writeText(command);
setShowCopied(true);

setTimeout(() => setShowCopied(false), 1500);
};

return (
<div className="container">
<MetaDataValue
container={'code'}
className={modifiers('command-value', {
visible: !showCopied,
})}
className="command-value"
value={command}
/>
{window.navigator.clipboard && isCommand && (
<>
<span
className={modifiers('copy-message', {
visible: showCopied,
})}
>
Copied to clipboard.
</span>
<ul className="toolbox">
<IconButton
ariaLabel="Copy run command to clipboard."
className="copy-button"
dataHeapEvent={`clicked.run_command`}
icon={CopyIcon}
onClick={onCopyClick}
/>
</ul>
</>
<ul className="toolbox">
<IconButton
ariaLabel="Copy run command to clipboard."
className="copy-button"
dataHeapEvent={`clicked.run_command`}
icon={CopyIcon}
onClick={onCopyClick}
/>
<Tooltip
text="Copied!"
visible={showCopied}
noDelay
centerArrow
arrowSize="small"
/>
</ul>
)}
</div>
);
Expand Down
1 change: 1 addition & 0 deletions src/components/ui/command-copier/command-copier.scss
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
}

.toolbox {
position: relative;
display: block;
width: 26px;
height: 34px;
Expand Down
57 changes: 46 additions & 11 deletions src/components/ui/tooltip/tooltip.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,39 +14,74 @@ export const insertZeroWidthSpace = (text) =>

/**
* Display flowchart node tooltip
* @param {string} arrowSize Tooltip arrow size regular | small
* @param {boolean} centerArrow Where to center tooltip arrow or not
* @param {Object} chartSize Chart dimensions in pixels
* @param {boolean} noDelay Where to show the tooltip immediately or after 1 sec delay
* @param {Object} style Tooltip custom css
* @param {Object} targetRect event.target.getBoundingClientRect()
* @param {Boolean} visible Whether to show the tooltip
* @param {String} text Tooltip display label
* @param {Boolean} visible Whether to show the tooltip
*/
const Tooltip = ({ chartSize, targetRect, visible, text }) => {
const { left, top, width, height, outerWidth, sidebarWidth } = chartSize;
const isRight = targetRect.left - sidebarWidth > width / 2;
const isTop = targetRect.top < height / 2;
const xOffset = isRight ? targetRect.left - outerWidth : targetRect.left;
const yOffset = isTop ? targetRect.top + targetRect.height : targetRect.top;
const x = xOffset - left + targetRect.width / 2;
const y = yOffset - top;
const Tooltip = ({
arrowSize,
centerArrow,
chartSize,
noDelay,
style,
targetRect,
text,
visible,
}) => {
let isTop = false,
isRight = false;
const isFlowchartTooltip = chartSize && Object.keys(chartSize).length;
const styles = { ...style };

if (isFlowchartTooltip) {
let x = 0,
y = 0;
const { left, top, width, height, outerWidth, sidebarWidth } = chartSize;

isRight = targetRect.left - sidebarWidth > width / 2;
isTop = targetRect.top < height / 2;

const xOffset = isRight ? targetRect.left - outerWidth : targetRect.left;
const yOffset = isTop ? targetRect.top + targetRect.height : targetRect.top;

x = xOffset - left + targetRect.width / 2;
y = yOffset - top;

styles.transform = `translate(${x}px, ${y}px)`;
}

return (
<div
className={classnames('pipeline-tooltip', {
'pipeline-tooltip--visible': visible,
'pipeline-tooltip--right': isRight,
'pipeline-tooltip--top': isTop,
'pipeline-tooltip--chart': isFlowchartTooltip,
'pipeline-tooltip--no-delay': noDelay,
'pipeline-tooltip--center-arrow': centerArrow,
'pipeline-tooltip--small-arrow': arrowSize === 'small',
})}
style={{ transform: `translate(${x}px, ${y}px)` }}
style={styles}
>
<div className="pipeline-tooltip__text">{insertZeroWidthSpace(text)}</div>
</div>
);
};

Tooltip.defaultProps = {
arrowSize: 'regular',
centerArrow: false,
chartSize: {},
noDelay: false,
style: {},
targetRect: {},
visible: false,
text: '',
visible: false,
};

export default Tooltip;
Loading