Skip to content

Commit

Permalink
Merge pull request #28 from user-interviews/feature/UIDS-27-copy-to-c…
Browse files Browse the repository at this point in the history
…lipboard-component

UIDS-27 Add CopyToClipboard and TrackedButton components
  • Loading branch information
rsaris authored Mar 25, 2020
2 parents 02cbdfd + 5c7371d commit 5dcbc04
Show file tree
Hide file tree
Showing 15 changed files with 396 additions and 145 deletions.
7 changes: 7 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,20 @@
"name": "ui-design-system",
"version": "1.0.3",
"dependencies": {
"@fortawesome/fontawesome-svg-core": "^1.2.27",
"@fortawesome/free-regular-svg-icons": "^5.12.1",
"@fortawesome/free-solid-svg-icons": "^5.12.1",
"@fortawesome/react-fontawesome": "^0.1.9",
"bootstrap": "^4.3.1",
"classnames": "^2.2.6",
"node-sass": "^4.13.1",
"polished": "^3.4.2",
"prop-types": "^15.7.2",
"react-bootstrap": "^1.0.0-beta.16",
"react-transition-group": "^4.3.0",
"react-copy-to-clipboard": "^5.0.2",
"react-popper": "^1.3.7",
"react-tracking": "^7.3.0",
"uuid": "^7.0.2"
},
"scripts": {
Expand Down
1 change: 1 addition & 0 deletions scss/borders.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
$ux-border-radius: 0.25rem;
9 changes: 9 additions & 0 deletions scss/buttons.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
@import './palette';

.btn-link--neutral {
color: $ux-gray-500;

&:hover {
color: $ux-gray-700;
}
}
1 change: 1 addition & 0 deletions scss/theme.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
@import './box_shadow';
@import './buttons';
@import './lists';
@import './navbar';
@import './palette';
Expand Down
99 changes: 88 additions & 11 deletions spec/__snapshots__/Storyshots.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ exports[`Storyshots Design System/Card all cards 1`] = `
</div>
`;

exports[`Storyshots Design System/Flash Flash Message 1`] = `
exports[`Storyshots Design System/Copy To Clipboard Default 1`] = `
<div
style={
Object {
Expand All @@ -74,24 +74,49 @@ exports[`Storyshots Design System/Flash Flash Message 1`] = `
}
>
<div
className="container Flash"
/>
<div>
<p>
Click the button to see a flash message. Use the knobs to try different types!
</p>
className="CopyToClipboard"
>
<span
className="CopyToClipboard__copy-text"
>
Copy me!
</span>
<button
className="btn btn-primary"
className="btn btn-link btn-link--neutral"
onClick={[Function]}
tracking={
Object {
"getTrackingData": [Function],
"trackEvent": [Function],
}
}
type="button"
>
Submit
<div>
<svg
aria-hidden="true"
className="svg-inline--fa fa-copy fa-w-14 "
data-icon="copy"
data-prefix="far"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 448 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M433.941 65.941l-51.882-51.882A48 48 0 0 0 348.118 0H176c-26.51 0-48 21.49-48 48v48H48c-26.51 0-48 21.49-48 48v320c0 26.51 21.49 48 48 48h224c26.51 0 48-21.49 48-48v-48h80c26.51 0 48-21.49 48-48V99.882a48 48 0 0 0-14.059-33.941zM266 464H54a6 6 0 0 1-6-6V150a6 6 0 0 1 6-6h74v224c0 26.51 21.49 48 48 48h96v42a6 6 0 0 1-6 6zm128-96H182a6 6 0 0 1-6-6V54a6 6 0 0 1 6-6h106v88c0 13.255 10.745 24 24 24h88v202a6 6 0 0 1-6 6zm6-256h-64V48h9.632c1.591 0 3.117.632 4.243 1.757l48.368 48.368a6 6 0 0 1 1.757 4.243V112z"
fill="currentColor"
style={Object {}}
/>
</svg>
</div>
</button>
</div>
</div>
`;

exports[`Storyshots Design System/Flash flash message 1`] = `
exports[`Storyshots Design System/Flash Flash Message 1`] = `
<div
style={
Object {
Expand All @@ -100,7 +125,7 @@ exports[`Storyshots Design System/Flash flash message 1`] = `
}
>
<div
className="container flash"
className="container Flash"
/>
<div>
<p>
Expand Down Expand Up @@ -615,3 +640,55 @@ exports[`Storyshots Design System/Pill Small 1`] = `
</div>
</div>
`;

exports[`Storyshots Design System/Popper Dark 1`] = `
<div
style={
Object {
"padding": "1rem",
}
}
>
<div />
<div
className="Popper Popper--dark"
style={
Object {
"left": 0,
"opacity": 0,
"pointerEvents": "none",
"position": "absolute",
"top": 0,
}
}
>
Dark Popper
</div>
</div>
`;

exports[`Storyshots Design System/Popper Default 1`] = `
<div
style={
Object {
"padding": "1rem",
}
}
>
<div />
<div
className="Popper"
style={
Object {
"left": 0,
"opacity": 0,
"pointerEvents": "none",
"position": "absolute",
"top": 0,
}
}
>
Default Popper
</div>
</div>
`;
51 changes: 51 additions & 0 deletions src/CopyToClipboard/CopyToClipboard.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import React, { useState } from 'react';
import PropTypes from 'prop-types';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faCopy } from '@fortawesome/free-regular-svg-icons';
import { CopyToClipboard as ReactCopyToClipboard } from 'react-copy-to-clipboard';

import Popper from '../Popper/Popper';
import TrackedButton from '../TrackedButton/TrackedButton';

import './CopyToClipboard.scss';

function CopyToClipboard(props) {
const [copied, setCopied] = useState(false);

const handleClickCopy = () => {
setCopied(true);
setTimeout(() => setCopied(false), 1000);
};

return (
<div className="CopyToClipboard">
<span className="CopyToClipboard__copy-text">{props.copyText}</span>
<ReactCopyToClipboard text={props.copyText} onCopy={handleClickCopy}>
<TrackedButton
className="btn btn-link btn-link--neutral"
event={props.trackingEvent}
type="button"
>
<Popper
dark
text="Copied!"
visible={copied}
>
<FontAwesomeIcon icon={faCopy} />
</Popper>
</TrackedButton>
</ReactCopyToClipboard>
</div>
);
}

CopyToClipboard.propTypes = {
copyText: PropTypes.string,
trackingEvent: PropTypes.string.isRequired,
};

CopyToClipboard.defaultProps = {
copyText: '',
};

export default CopyToClipboard;
19 changes: 19 additions & 0 deletions src/CopyToClipboard/CopyToClipboard.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
@import '../../scss/theme';

.CopyToClipboard {
align-items: center;
border: 1px solid $ux-gray-400;
border-radius: .25rem;
color: $ux-gray-800;
display: flex;
font-weight: $font-weight-bold;
justify-content: space-between;
min-height: 2rem;
padding: 0 0 0 .375rem;

&__copy-text {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
49 changes: 49 additions & 0 deletions src/Popper/Popper.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { Manager, Popper as ReactPopper, Reference } from 'react-popper';

import './Popper.scss';

function Popper(props) {
return (
<Manager>
<Reference>
{({ ref }) => <div ref={ref}>{props.children}</div>}
</Reference>
{
props.visible && (
<ReactPopper placement={props.placement}>
{
({ placement, ref, style }) => (
<div
className={classNames('Popper', { 'Popper--dark': props.dark })}
data-placement={placement}
ref={ref}
style={style}
>
{props.text}
</div>
)
}
</ReactPopper>
)
}
</Manager>
);
}

Popper.propTypes = {
dark: PropTypes.bool,
placement: PropTypes.string,
text: PropTypes.string.isRequired,
visible: PropTypes.bool,
};

Popper.defaultProps = {
dark: false,
placement: 'top',
visible: false,
};

export default Popper;
19 changes: 19 additions & 0 deletions src/Popper/Popper.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
@import '../../scss/borders';
@import '../../scss/box_shadow';
@import '../../scss/palette';
@import '../../scss/typography';

.Popper {
background-color: $ux-white;
border-radius: $ux-border-radius;
border: 1px solid $ux-gray-300;
box-shadow: $ux-box-shadow-card;
max-width: 15rem;
padding: .25rem .5rem;

&--dark {
background-color: $ux-gray-800;
color: $ux-gray-100;
font-weight: $font-weight-bold;
}
}
3 changes: 3 additions & 0 deletions src/TrackedButton/TrackedButton.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import withTrackedClick from '../hoc/withTrackedClick';

export default withTrackedClick('button');
38 changes: 38 additions & 0 deletions src/hoc/withTrackedClick.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React from 'react';
import PropTypes from 'prop-types';
import track from 'react-tracking';

export default function withTrackedClick(Target) {
const TrackedComponent = (props) => {
TrackedComponent.displayName = `${Target.displayName || Target.name}WithTrackedClick`;

const { eventData, event, ...rest } = props;

function handleClick(clickEvent) {
props.tracking.trackEvent({ ...eventData, event });

if (props.onClick) {
props.onClick(clickEvent);
}
}

return <Target {...rest} onClick={handleClick} />;
};

TrackedComponent.propTypes = {
event: PropTypes.string.isRequired,
eventData: PropTypes.object,
tracking: PropTypes.shape({
getTrackingData: PropTypes.func,
trackEvent: PropTypes.func,
}).isRequired,
onClick: PropTypes.func,
};

TrackedComponent.defaultProps = {
eventData: {},
onClick: undefined,
};

return track()(TrackedComponent);
}
12 changes: 9 additions & 3 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,32 @@
import Card from './Card/Card';
import CopyToClipboard from './CopyToClipboard/CopyToClipboard';
import {
Flash, MessageTypes, withFlash, withFlashPropTypes, useFlash,
} from './Flash';
import Form from './Form/Form';
import FormControlLabel from './FormControlLabel/FormControlLabel';
import FormGroup from './FormGroup/FormGroup';
import InputLabel from './InputLabel/InputLabel';
import Pill from './Pill/Pill';
import Popper from './Popper/Popper';
import RadioButton from './RadioButton/RadioButton';
import RadioButtonGroup from './RadioButtonGroup/RadioButtonGroup';
import {
Flash, MessageTypes, withFlash, withFlashPropTypes, useFlash,
} from './Flash';
import TrackedButton from './TrackedButton/TrackedButton';

export {
Card,
CopyToClipboard,
Flash,
Form,
FormControlLabel,
FormGroup,
InputLabel,
MessageTypes,
Pill,
Popper,
RadioButton,
RadioButtonGroup,
TrackedButton,
useFlash,
withFlash,
withFlashPropTypes,
Expand Down
Loading

0 comments on commit 5dcbc04

Please sign in to comment.