Skip to content

Commit 3e6b1b7

Browse files
authored
Merge pull request #452 from buildo/readonly-copy
2 parents 0356e7f + 3a4671d commit 3e6b1b7

File tree

7 files changed

+86
-2
lines changed

7 files changed

+86
-2
lines changed

Diff for: packages/bento-design-system/src/BentoConfig.ts

+2
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import { MenuConfig } from "./Menu/Config";
2525
import { ModalConfig } from "./Modal/Config";
2626
import { NavigationConfig } from "./Navigation/Config";
2727
import { ProgressBarConfig } from "./ProgressBar/Config";
28+
import { ReadOnlyFieldConfig } from "./ReadOnlyField/Config";
2829
import { SearchBarConfig } from "./SearchBar/Config";
2930
import { DropdownConfig } from "./SelectField/Config";
3031
import { SliderConfig } from "./Slider/Config";
@@ -62,6 +63,7 @@ export type BentoConfig = {
6263
menu: MenuConfig;
6364
modal: ModalConfig;
6465
navigation: NavigationConfig;
66+
readOnlyField: ReadOnlyFieldConfig;
6567
searchBar: SearchBarConfig;
6668
dropdown: DropdownConfig;
6769
table: TableConfig;
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { IconProps } from "./IconProps";
2+
import { svgIconProps } from "./svgIconProps";
3+
4+
export function IconCopyLight(props: IconProps) {
5+
return (
6+
<svg {...svgIconProps(props)}>
7+
<path d="M23.234 0L6.89362 0C6.69047 9.07076e-16 6.49565 0.0806988 6.352 0.224344C6.20836 0.367989 6.12766 0.562813 6.12766 0.765957L6.12766 6.12766L0.765957 6.12766C0.562813 6.12766 0.367989 6.20836 0.224344 6.352C0.0806988 6.49565 9.07076e-16 6.69047 0 6.89362L0 23.234C9.07076e-16 23.4372 0.0806988 23.632 0.224344 23.7757C0.367989 23.9193 0.562813 24 0.765957 24L17.1064 24C17.3095 24 17.5044 23.9193 17.648 23.7757C17.7916 23.632 17.8723 23.4372 17.8723 23.234L17.8723 17.8723L23.234 17.8723C23.4372 17.8723 23.632 17.7916 23.7757 17.648C23.9193 17.5044 24 17.3095 24 17.1064L24 0.765957C24 0.562813 23.9193 0.367989 23.7757 0.224344C23.632 0.0806988 23.4372 9.07076e-16 23.234 0ZM16.3404 22.4681L1.53191 22.4681L1.53191 7.65957L16.3404 7.65957L16.3404 22.4681ZM22.4681 16.3404L17.8723 16.3404L17.8723 6.89362C17.8723 6.69047 17.7916 6.49565 17.648 6.352C17.5044 6.20836 17.3095 6.12766 17.1064 6.12766L7.65957 6.12766L7.65957 1.53191L22.4681 1.53191L22.4681 16.3404Z" />
8+
</svg>
9+
);
10+
}

Diff for: packages/bento-design-system/src/Icons/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ export * from "./IconChevronLeft";
44
export * from "./IconChevronRight";
55
export * from "./IconChevronUp";
66
export * from "./IconClose";
7+
export * from "./IconCopyLight";
78
export * from "./IconEdit";
89
export * from "./IconEye";
910
export * from "./IconEyeClosed";
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { IconProps } from "../Icons";
2+
import { Children } from "../util/Children";
3+
4+
export type ReadOnlyFieldConfig = {
5+
copyIcon: (props: IconProps) => Children;
6+
copyIconSize: IconProps["size"];
7+
};
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,25 @@
1+
import { useBentoConfig } from "../BentoConfigContext";
2+
import { IconButton } from "../IconButton/IconButton";
13
import { TextField, TextFieldProps } from "../TextField/TextField";
4+
import { useToast } from "../Toast/useToast";
5+
import { LocalizedString } from "../util/ConfigurableTypes";
26
import { Omit } from "../util/Omit";
37

48
type Props = Omit<
59
TextFieldProps,
610
"onChange" | "onBlur" | "disabled" | "isReadOnly" | "placeholder" | "issues"
7-
>;
11+
> &
12+
(
13+
| {
14+
withCopyButton: true;
15+
copyButtonLabel: LocalizedString;
16+
copySuccessMessage: LocalizedString;
17+
showToastOnCopy?: boolean;
18+
}
19+
| {
20+
withCopyButton?: false;
21+
}
22+
);
823

924
const constVoid = () => {};
1025

@@ -13,7 +28,43 @@ const constVoid = () => {};
1328
* and doesn't require all those props that don't make sense for a read-only field (onChange, onBlur, placeholder, ...)
1429
*/
1530
export function ReadOnlyField(props: Props) {
16-
return <TextField {...props} onChange={constVoid} onBlur={constVoid} placeholder="" isReadOnly />;
31+
const { showToast } = useToast();
32+
const config = useBentoConfig().readOnlyField;
33+
34+
const rightAccessory = props.withCopyButton ? (
35+
<IconButton
36+
icon={config.copyIcon}
37+
onPress={async () => {
38+
if (props.showToastOnCopy ?? true) {
39+
try {
40+
await navigator.clipboard.writeText(props.value);
41+
showToast({
42+
kind: "informative",
43+
message: props.copySuccessMessage,
44+
dismissable: true,
45+
});
46+
} catch {
47+
console.error("Could not copy to clipboard");
48+
}
49+
}
50+
}}
51+
kind="transparent"
52+
hierarchy="secondary"
53+
label={props.copyButtonLabel}
54+
size={config.copyIconSize}
55+
/>
56+
) : undefined;
57+
58+
return (
59+
<TextField
60+
{...props}
61+
onChange={constVoid}
62+
onBlur={constVoid}
63+
placeholder=""
64+
isReadOnly
65+
rightAccessory={rightAccessory}
66+
/>
67+
);
1768
}
1869

1970
export type { Props as ReadOnlyFieldProps };

Diff for: packages/bento-design-system/src/util/defaultConfigs.tsx

+7
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
IconSpinner,
2121
IconEyeClosed,
2222
IconEye,
23+
IconCopyLight,
2324
} from "../Icons";
2425
import type { ButtonConfig } from "../Button/Config";
2526
import type { CardConfig } from "../Card/Config";
@@ -52,6 +53,7 @@ import type { TooltipConfig } from "../Tooltip/Config";
5253
import type { InlineLoaderConfig } from "../InlineLoader/Config";
5354
import type { DecorativeDividerConfig } from "../Divider/Config";
5455
import type { DateFieldConfig } from "../DateField/Config";
56+
import { ReadOnlyFieldConfig } from "../ReadOnlyField/Config";
5557

5658
export const actions: ActionsConfig = {
5759
primaryActionButtonKind: "solid",
@@ -389,6 +391,11 @@ export const navigation: NavigationConfig = {
389391
uppercaseLabel: false,
390392
};
391393

394+
export const readOnlyField: ReadOnlyFieldConfig = {
395+
copyIcon: IconCopyLight,
396+
copyIconSize: 24,
397+
};
398+
392399
export const searchBar: SearchBarConfig = {
393400
...input,
394401
clearIcon: IconClose,

Diff for: packages/storybook/stories/Components/ReadonlyField.stories.tsx

+6
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,9 @@ export const Default = createStory({});
2121
export const Password = createStory({ type: "password" });
2222

2323
export const RightAccessory = createStory({ rightAccessory: "👍" });
24+
25+
export const WithCopyButton = createStory({
26+
withCopyButton: true,
27+
copyButtonLabel: "Copy to clipboard",
28+
copySuccessMessage: "Copied to clipboard",
29+
});

0 commit comments

Comments
 (0)