Skip to content

Commit ea7e68b

Browse files
committed
feat: DXDP-5242 | POC: Explore UDS components approach & Custom Variant
1 parent d864ca7 commit ea7e68b

File tree

6 files changed

+94
-10
lines changed

6 files changed

+94
-10
lines changed
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import React from "react";
2+
import { FormField, FormFieldProps } from "@/components/ui/form-field"; // Import the FormField component and its props
3+
import { cn } from "@/utils/helpers/cn"; // Utility function for conditional class names
4+
5+
// Extend FormFieldProps to include additional props for the wrapper component
6+
interface FormFieldWrapperProps extends FormFieldProps {
7+
className?: string; // Optional custom class for the wrapper
8+
errorMessage?: string; // Custom error message for the field
9+
forceFocusStyle?: boolean; // Flag to force focus styles
10+
}
11+
12+
// Wrapper component for FormField to add additional functionality or styling
13+
const FormFieldWrapper: React.FC<FormFieldWrapperProps> = ({
14+
className,
15+
label,
16+
error,
17+
errorMessage,
18+
helperText,
19+
startAdornment,
20+
endAdornment,
21+
size,
22+
variant = "default",
23+
forceFocusStyle = false,
24+
...props
25+
}) => {
26+
// Theme overrides for consistent styling
27+
const themeOverrides = "theme-universal:rounded-input theme-universal:bg-primary-button-label";
28+
29+
return (
30+
<FormField
31+
className={cn(className, themeOverrides)} // Combine custom class with theme overrides
32+
label={label}
33+
error={error} // Pass error state to FormField
34+
helperText={helperText || errorMessage} // Display helper text or custom error message
35+
startAdornment={startAdornment}
36+
endAdornment={endAdornment}
37+
size={size}
38+
variant={variant}
39+
{...props} // Spread additional props to FormField
40+
/>
41+
);
42+
};
43+
44+
export default FormFieldWrapper; // Export the wrapper component default FormFieldWrapper; // Export the wrapper component
45+

src/components/ui/form-field.tsx

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import * as React from "react";
33
import { cn } from "@/lib/utils";
44

55
const formFieldVariants = cva(
6-
"bg-input aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive theme-default:active:scale-[0.99] relative box-border inline-flex w-full shrink-0 cursor-text items-center justify-center gap-2 overflow-hidden text-sm transition-[color,box-shadow] duration-150 ease-in-out outline-none disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
6+
"theme-universal:rounded-input bg-input aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive theme-default:active:scale-[0.99] relative box-border inline-flex w-full shrink-0 cursor-text items-center justify-center gap-2 text-sm transition-[color,box-shadow] duration-150 ease-in-out outline-none disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
77
{
88
variants: {
99
variant: {
@@ -96,7 +96,7 @@ const FormField = React.forwardRef<HTMLInputElement, FormFieldProps>(
9696
startAdornment && "left-0",
9797
isLabelFloating && "top-4 text-xs",
9898
isLabelFloating && size === "sm" && "top-3.5 text-xs",
99-
error ? "text-destructive-foreground" : "text-muted-foreground",
99+
error ? "text-destructive-foreground theme-universal:text-error" : "text-muted-foreground",
100100
focused && !error && "text-primary",
101101
)}
102102
>
@@ -132,12 +132,7 @@ const FormField = React.forwardRef<HTMLInputElement, FormFieldProps>(
132132
)}
133133
</div>
134134
{helperText && (
135-
<p
136-
className={cn(
137-
"mt-1.5 text-xs",
138-
error ? "text-destructive-foreground" : "text-muted-foreground",
139-
)}
140-
>
135+
<p className={cn("mt-1.5 text-xs", error ? "theme-universal:text-error" : "text-muted-foreground")}>
141136
{helperText}
142137
</p>
143138
)}

src/components/ui/label.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ function Label({
1212
<LabelPrimitive.Root
1313
data-slot="label"
1414
className={cn(
15-
"flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50",
15+
"theme-universal:rounded-input flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50",
1616
className,
1717
)}
1818
{...props}

src/index.css

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,16 @@
8080
--max-w-md: 28rem;
8181
}
8282

83+
84+
85+
/* Define the custom variant using @custom-variant */
86+
@custom-variant theme-universal {
87+
&.theme-universal {
88+
@slot;
89+
}
90+
}
91+
92+
8393
:root {
8494
/* Colors */
8595
--ul-theme-color-primary-button: #635dff;

src/screens/login-id/components/IdentifierForm.tsx

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@ import Button from "@/common/Button";
44
import Alert from "@/common/Alert";
55
import CaptchaBox from "@/common/CaptchaBox";
66
import FormField from "@/common/FormField";
7+
// import { FormField as UDSFormField } from "@/components/ui/form-field";
78
import { getFieldError } from "@/utils/helpers/errorUtils";
89
import { rebaseLinkToCurrentOrigin } from "@/utils/helpers/urlUtils";
910
import { getIdentifierDetails } from "@/utils/helpers/identifierUtils";
1011
import { useLoginIdManager } from "../hooks/useLoginIdManager";
12+
import InputWrapper from "@/common/FormFieldWrapper";
1113

1214
interface LoginIdFormData {
1315
identifier: string;
@@ -60,6 +62,13 @@ const IdentifierForm: React.FC = () => {
6062
originalResetPasswordLink,
6163
);
6264

65+
const formError =
66+
formErrors.identifier?.message ||
67+
getFieldError("identifier", errors) ||
68+
getFieldError("email", errors) ||
69+
getFieldError("phone", errors) ||
70+
getFieldError("username", errors);
71+
6372
return (
6473
<form onSubmit={handleSubmit(onSubmit)} className="space-y-4">
6574
{/* General alerts at the top */}
@@ -71,6 +80,31 @@ const IdentifierForm: React.FC = () => {
7180
</div>
7281
)}
7382

83+
<InputWrapper
84+
className="mb-4"
85+
label={identifierLabel}
86+
id="identifier-login-id"
87+
type={identifierType}
88+
autoComplete={identifierAutoComplete}
89+
autoFocus
90+
{...register("identifier", {
91+
required: "This field is required",
92+
maxLength: {
93+
value: 100,
94+
message: "Maximum 100 characters allowed",
95+
},
96+
})}
97+
error={!!formError}
98+
errorMessage={formErrors.identifier?.message ||
99+
getFieldError("identifier", errors) ||
100+
getFieldError("email", errors) ||
101+
getFieldError("phone", errors) ||
102+
getFieldError("username", errors)}
103+
variant="default"
104+
/>
105+
106+
{/* <UDSFormField label={identifierLabel} variant="default" error={true} /> */}
107+
74108
<FormField
75109
className="mb-4"
76110
labelProps={{

src/screens/login-id/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ const LoginIdScreen: React.FC = () => {
3030

3131
return (
3232
<div
33-
className={`min-h-screen flex items-center p-5`}
33+
className={`min-h-screen flex items-center p-5 theme-universal`}
3434
style={{ justifyContent: pageLayout }}
3535
>
3636
<Card className="w-full max-w-sm">

0 commit comments

Comments
 (0)