Skip to content

Commit

Permalink
Textarea copy text button (#238)
Browse files Browse the repository at this point in the history
  • Loading branch information
quietbits authored Apr 22, 2024
1 parent 165eef8 commit 7af35f4
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -125,5 +125,20 @@ export const textareaPreview: ComponentPreview = {
},
],
},
{
type: "select",
prop: "hasCopyButton",
customValue: true,
options: [
{
value: "",
label: "No copy button",
},
{
value: "copy",
label: "Copy button",
},
],
},
],
};
23 changes: 6 additions & 17 deletions @stellar/design-system/src/components/Input/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import React, { cloneElement, useState } from "react";
import CopyToClipboard from "react-copy-to-clipboard";
import { Button } from "../Button";
import { Label } from "../Label";
import { Icon } from "../../icons";
import { FieldNote } from "../utils/FieldNote";
import { InputCopyButton } from "../utils/InputCopyButton";
import "./styles.scss";

/** Including all valid [input attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attributes). */
Expand Down Expand Up @@ -87,21 +86,11 @@ export const Input: React.FC<Props> = ({
};

const renderCopyButton = () => (
<CopyToClipboard text={props.value ? props.value.toString() : ""}>
<Button
variant="tertiary"
size={fieldSize}
icon={<Icon.Copy01 />}
iconPosition="left"
disabled={!props.value}
type="button"
onClick={(e) => {
e.preventDefault();
}}
>
{copyButton?.showLabel ? "Copy" : ""}
</Button>
</CopyToClipboard>
<InputCopyButton
fieldSize={fieldSize}
textToCopy={props.value ? props.value.toString() : ""}
showLabel={copyButton?.showLabel}
/>
);

return (
Expand Down
33 changes: 22 additions & 11 deletions @stellar/design-system/src/components/Textarea/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { cloneElement } from "react";
import { Label } from "../Label";
import { FieldNote } from "../utils/FieldNote";
import { InputCopyButton } from "../utils/InputCopyButton";
import "./styles.scss";

/** Including all valid [textarea attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea#attributes) */
Expand All @@ -26,6 +27,8 @@ export interface TextareaProps {
isError?: boolean;
/** Make label uppercase */
isLabelUppercase?: boolean;
/** Show copy text button */
hasCopyButton?: boolean;
/** Use a specific textarea rather than a generic HTML textarea (useful for Formik or otherwise controlled inputs) */
customTextarea?: React.ReactElement;
}
Expand All @@ -51,6 +54,7 @@ export const Textarea: React.FC<Props> = ({
success,
isError,
isLabelUppercase,
hasCopyButton,
customTextarea,
spellCheck = false,
autoComplete = "off",
Expand Down Expand Up @@ -90,17 +94,24 @@ export const Textarea: React.FC<Props> = ({
</textarea>
)}

{note && <FieldNote size={fieldSize}>{note}</FieldNote>}
{error && (
<FieldNote size={fieldSize} variant="error">
{error}
</FieldNote>
)}
{success && (
<FieldNote size={fieldSize} variant="success">
{success}
</FieldNote>
)}
<div className="Textarea__footer">
<div className="Textarea__footer__notes">
{note && <FieldNote size={fieldSize}>{note}</FieldNote>}
{error && (
<FieldNote size={fieldSize} variant="error">
{error}
</FieldNote>
)}
{success && (
<FieldNote size={fieldSize} variant="success">
{success}
</FieldNote>
)}
</div>
{hasCopyButton ? (
<InputCopyButton fieldSize={fieldSize} textToCopy={children} />
) : null}
</div>
</div>
);
};
Expand Down
12 changes: 12 additions & 0 deletions @stellar/design-system/src/components/Textarea/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,18 @@
}
}

&__footer {
display: flex;
justify-content: space-between;
gap: var(--Textarea-gap);

&__notes {
display: flex;
flex-direction: column;
gap: var(--Textarea-gap);
}
}

&--error {
--Textarea-color-background: var(--sds-input-color-background-error);
--Textarea-color-border: var(--sds-input-color-border-error);
Expand Down
34 changes: 34 additions & 0 deletions @stellar/design-system/src/components/utils/InputCopyButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import CopyToClipboard from "react-copy-to-clipboard";
import { Button } from "../Button";
import { Icon } from "../../icons";

export type InputCopyButtonProps = {
/** Text to copy */
textToCopy: string;
/** Size of the button */
fieldSize: "sm" | "md" | "lg";
/** Show "Copy" label */
showLabel?: boolean;
};

export const InputCopyButton = ({
textToCopy,
fieldSize,
showLabel,
}: InputCopyButtonProps) => (
<CopyToClipboard text={textToCopy}>
<Button
variant="tertiary"
size={fieldSize}
icon={<Icon.Copy01 />}
iconPosition="left"
disabled={!textToCopy}
type="button"
onClick={(e) => {
e.preventDefault();
}}
>
{showLabel ? "Copy" : ""}
</Button>
</CopyToClipboard>
);

0 comments on commit 7af35f4

Please sign in to comment.