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

copy button that copies text to clipboard #1112

Merged
merged 11 commits into from
Aug 14, 2018
Merged

Conversation

nreese
Copy link
Contributor

@nreese nreese commented Aug 10, 2018

Kibana uses this in the home page tutorials and needs the component in am more generic location so it can be used in other places. Figured the best place for it is in EUI.

Copy link
Contributor

@cchaos cchaos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are some issues with the tooltip rendering:

content={this.state.tooltipText}
onMouseOut={this.resetTooltipText}
>
<EuiButton
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we may want to pull this out into a more generic service so that they can pass any type of child node (any button or link) that gets wrapped in this functionality. As it stands, you can't use EuiButtonEmpty or EuiButtonIcon.

I would also like to look into creating a "disappearing" tooltip to use here. Where there is no tooltip on hover, but then when you click the trigger element, the tooltip only stays up for a short period of time. I'll look into this in another branch.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe use a toast instead, which will auto dismiss itself and is good for this action (as well as for accessibility because it'll announce itself). The button will likely have the action in it so the tooltip on hover is likely unnecessary. Agree it should be more generic and accept any child element, not just a regular button.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My concern with a toast, is that it's not very tied to the button itself and can be easily overlooked. For small actions like this, maybe we should consider a new type of tooltip that reads out like a toast, but whose proximity is much closer to the triggering element?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are some issues with the tooltip rendering

is a known bug, #996 ; coincidentally this exact use case

@chandlerprall
Copy link
Contributor

Related to #594 , echoing what @cchaos said that this should be a service in EUI that can be used in buttons and anything else.

@nreese
Copy link
Contributor Author

nreese commented Aug 13, 2018

@cchaos @chandlerprall I have moved the component under utilities and now anything can be used as the child.

@elasticdog
Copy link

Jenkins, test this please.


<EuiSpacer size="m" />

<EuiCopy textToCopy={this.state.copyText}>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about making this a render prop instead of adding a span with its own onClick?

<EuiCopy textToCopy={this.state.copyText}>
  {(copyFn) => (
      <EuiButton onClick={copyFn}>Click to copy input text</EuiButton>
  )}
</EuiCopy>

That keeps the utility component from affecting DOM and makes it more re-useable in other places.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

++

@nreese
Copy link
Contributor Author

nreese commented Aug 13, 2018

Should textToCopy prop be a function?

@chandlerprall
Copy link
Contributor

Should textToCopy prop be a function?

I think leaving it as a string makes sense; the parent is still in control, and the copy operation uses the current value on props, there's no caching happening.

import { EuiToolTip } from '../tool_tip';

const UNCOPIED_MSG = 'Copy';
const COPIED_MSG = 'Copied';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you make these messages customizable via props?

Copy link
Contributor

@cchaos cchaos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a couple nit things, but thank you so much for adding this in. I'm excited to be able to start using it in our docs!

}],
text: (
<p>
The <EuiCode>EuiCopy</EuiCode> component is a simplified utility for copying text to clipboard.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you give more description on how it's used?

}

EuiCopy.propTypes = {
textToCopy: PropTypes.string.isRequired,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add comments to each prop type to populate the props list table in the docs?

Also, you may want to consider add TS def's ;)

};

EuiCopy.defaultProps = {
beforeCopyMsg: 'Copy',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's most likely that by default we won't need a before message (That'll also give us a quick fix for the tooltip positioning issue that probably won't be fixed relatively soon). Can you remove the before message default and in the component make the tooltip dependent on having either of these messages?

Also, since we've been being pretty verbose with our props, I think we can change these to "beforeMessage" and "afterMessage" ("Copy" is redundant of the component name and "Msg" can be remembered easily).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem with not having a default before message is that then the toolip is displayed with no text. I am not sure how this should work without a before and after message

screen shot 2018-08-14 at 9 40 02 am

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah you would need to conditionally wrap the child in a tooltip when one or both messages exist.

} = this.props;

return (
<EuiToolTip
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May want consider passing down {...rest} to the tooltip so consumers can customize it even more and pass down something like 'data-test-subj'.

@@ -146,7 +146,7 @@ export class EuiToolTip extends Component {
);

let tooltip;
if (visible) {
if (visible && content) {
Copy link
Contributor

@cchaos cchaos Aug 14, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, one last thing, but because tooltips accept title's as well can you change this to be if (visible && (content || title))

Copy link
Contributor

@cchaos cchaos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! LGTM

@nreese nreese merged commit 8391daf into elastic:master Aug 14, 2018
This was referenced Aug 14, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants