Skip to content

Commit 0356e7f

Browse files
authored
Merge pull request #451 from buildo/text-field-right-accessory
2 parents 7d89f8b + d0128ae commit 0356e7f

File tree

3 files changed

+35
-15
lines changed

3 files changed

+35
-15
lines changed

packages/bento-design-system/src/TextField/TextField.tsx

+28-15
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,22 @@
11
import { useTextField } from "@react-aria/textfield";
22
import { useRef, useState } from "react";
3-
import { Box, IconButton, Field } from "..";
3+
import { Box, IconButton, Field, Children, Columns } from "..";
44
import { LocalizedString } from "../util/LocalizedString";
55
import { inputRecipe } from "../Field/Field.css";
66
import { FieldProps } from "../Field/FieldProps";
77
import { bodyRecipe } from "../Typography/Body/Body.css";
88
import useDimensions from "react-cool-dimensions";
99
import { defaultMessages } from "../../test/util/defaultMessages";
1010
import { useBentoConfig } from "../BentoConfigContext";
11+
import { match } from "ts-pattern";
1112

1213
type Props = FieldProps<string> & {
1314
placeholder: LocalizedString;
14-
type?: "text" | "email" | "url" | "password";
1515
isReadOnly?: boolean;
16-
showPasswordLabel?: LocalizedString;
17-
hidePasswordLabel?: LocalizedString;
16+
type?: "text" | "email" | "url" | "password";
17+
rightAccessory?: Children;
18+
showPasswordLabel?: never;
19+
hidePasswordLabel?: never;
1820
};
1921

2022
export function TextField(props: Props) {
@@ -47,6 +49,24 @@ export function TextField(props: Props) {
4749

4850
const type = props.type === "password" && !showPassword ? "password" : "text";
4951

52+
const rightAccessory = match(props.type ?? "text")
53+
.with("password", () => (
54+
// if we have both a rightAccessory and type='password', display the accessory on the left of the password toggle field
55+
<Columns space={config.paddingX} alignY="center">
56+
<IconButton
57+
size={config.passwordIconSize}
58+
icon={passwordIcon}
59+
onPress={() => setShowPassword((prevValue) => !prevValue)}
60+
kind="transparent"
61+
hierarchy="secondary"
62+
label={passwordIconLabel}
63+
/>
64+
{props.rightAccessory}
65+
</Columns>
66+
))
67+
.with("email", "text", "url", () => props.rightAccessory)
68+
.exhaustive();
69+
5070
return (
5171
<Field
5272
{...props}
@@ -75,28 +95,21 @@ export function TextField(props: Props) {
7595
size: config.fontSize,
7696
}),
7797
]}
78-
style={{ paddingRight: rightAccessoryWidth, flexGrow: 1 }}
98+
style={{ paddingRight: rightAccessory ? rightAccessoryWidth : undefined, flexGrow: 1 }}
7999
/>
80-
{props.type === "password" && (
100+
{rightAccessory && (
81101
<Box
82102
ref={rightAccessoryRef}
83103
position="absolute"
84104
display="flex"
85105
justifyContent="center"
86106
alignItems="center"
87-
paddingX={16}
107+
paddingX={config.paddingX}
88108
top={0}
89109
bottom={0}
90110
right={0}
91111
>
92-
<IconButton
93-
size={config.passwordIconSize}
94-
icon={passwordIcon}
95-
onPress={() => setShowPassword((prevValue) => !prevValue)}
96-
kind="transparent"
97-
hierarchy="secondary"
98-
label={passwordIconLabel}
99-
/>
112+
{rightAccessory}
100113
</Box>
101114
)}
102115
</Box>

packages/storybook/stories/Components/ReadonlyField.stories.tsx

+2
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,5 @@ export default defaultExport;
1919
export const Default = createStory({});
2020

2121
export const Password = createStory({ type: "password" });
22+
23+
export const RightAccessory = createStory({ rightAccessory: "👍" });

packages/storybook/stories/Components/TextField.stories.tsx

+5
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,8 @@ export const ReadOnly = createStory({
3131
value: "MyNickname",
3232
isReadOnly: true,
3333
});
34+
35+
export const CustomAccessory = createStory({
36+
value: "With a custom accessory",
37+
rightAccessory: "👍",
38+
});

0 commit comments

Comments
 (0)