Sign In Block
The SignIn Component is a fully customizable and accessible sign-in form built with React and TypeScript. It provides a complete authentication interface with modern design patterns, form validation, and flexible customization options.
π Installationβ
npm install @nodeblocks/frontend-signin-block@0.2.2
π Usageβ
import {SignIn} from '@nodeblocks/frontend-signin-block';
- Basic Usage
- Advanced Usage
function BasicSignIn() {
return (
<SignIn
onChange={(setError, getValues, clearErrors) => {
console.log('Form values:', getValues());
const values = getValues();
if (!values.email) {
setError('email', {message: 'Email is required', type: 'required'});
} else {
clearErrors('email');
}
}}
onSubmit={formData => {
console.log('Form submitted:', formData);
}}
style={{display: 'flex', flexDirection: 'column', gap: '16px'}}>
<SignIn.SignInTitle>Welcome Back</SignIn.SignInTitle>
<SignIn.EmailField label="Email Address" placeholder="Enter your email" />
<SignIn.PasswordField label="Password" placeholder="Enter your password" />
<SignIn.SignInButton>Sign In</SignIn.SignInButton>
<SignIn.GotoSignUp>
<a href="#signup">Create an account</a>
</SignIn.GotoSignUp>
<SignIn.ResetPassword>
<a href="#reset-password">Forgot password?</a>
</SignIn.ResetPassword>
</SignIn>
);
}
function AdvancedSignIn() {
return (
<SignIn
style={{
maxWidth: '550px',
margin: '0 auto',
borderRadius: '20px',
border: '1px solid #e2e8f0',
padding: '40px',
boxShadow: '0 25px 50px rgba(102, 126, 234, 0.3)',
}}
onChange={(setError, getValues, clearErrors) => {
const values = getValues();
if (!values.email) {
setError('email', {message: 'γ‘γΌγ«γ’γγ¬γΉγεΏ
θ¦γ§γ', type: 'required'});
} else {
clearErrors('email');
}
if (!values.password) {
setError('password', {message: 'γγΉγ―γΌγγεΏ
θ¦γ§γ', type: 'required'});
} else {
clearErrors('password');
}
}}
onSubmit={formData => {
console.log('γγ°γ€γ³:', formData);
}}
>
{({defaultBlocks, defaultBlockOrder}) => {
return {
blocks: {
...defaultBlocks,
signInTitle: {
...defaultBlocks.signInTitle,
props: {
...defaultBlocks.signInTitle.props,
style: {
color: 'white',
fontSize: '2.5rem',
fontWeight: 'bold',
textAlign: 'center',
marginBottom: '8px',
textShadow: '0 2px 4px rgba(0, 0, 0, 0.3)',
},
children: (
<div style={{display: 'flex', alignItems: 'center', justifyContent: 'center', gap: '12px'}}>
<svg style={{width: '36px', height: '36px'}} fill="currentColor" viewBox="0 0 24 24">
<path d="M12 2C13.1 2 14 2.9 14 4C14 5.1 13.1 6 12 6C10.9 6 10 5.1 10 4C10 2.9 10.9 2 12 2ZM21 9V7L15 4L13 5.3V3.07C13 3.03 13 3 13 3H11C11 3 11 3.03 11 3.07V5.3L9 4L3 7V9H5C5.6 9 6 9.4 6 10V16C6 16.6 6.4 17 7 17H10V19H14V17H17C17.6 17 18 16.6 18 16V10C18 9.4 18.4 9 19 9H21Z" />
</svg>
<span>δΌζ₯γγ°γ€γ³</span>
</div>
),
},
},
emailField: {
...defaultBlocks.emailField,
props: {
...defaultBlocks.emailField.props,
label: 'γ‘γΌγ«γ’γγ¬γΉ',
placeholder: 'δΎ: user@company.com',
style: {
background: 'rgba(255, 255, 255, 0.95)',
borderRadius: '12px',
fontSize: '16px',
},
},
},
passwordField: {
...defaultBlocks.passwordField,
props: {
...defaultBlocks.passwordField.props,
label: 'γγΉγ―γΌγ',
placeholder: 'γγΉγ―γΌγγε
₯εγγ¦γγ γγ',
style: {
background: 'rgba(255, 255, 255, 0.95)',
borderRadius: '12px',
fontSize: '16px',
},
},
},
signInButton: {
...defaultBlocks.signInButton,
props: {
...defaultBlocks.signInButton.props,
children: (
<div>γγ°γ€γ³</div>
),
},
},
gotoSignUp: {
...defaultBlocks.gotoSignUp,
props: {
...defaultBlocks.gotoSignUp.props,
style: {
textAlign: 'center',
},
children: (
<div style={{color: 'black', fontSize: '14px'}}>
<span>γ’γ«γ¦γ³γγγζγ‘γ§γͺγζΉγ― </span>
<a
href="#signup"
style={{
color: 'rgb(105, 124, 213)',
textDecoration: 'none',
fontWeight: 'bold',
}}
>
ζ°θ¦η»ι²
</a>
</div>
),
},
},
resetPassword: {
...defaultBlocks.resetPassword,
props: {
...defaultBlocks.resetPassword.props,
style: {
textAlign: 'center',
},
children: (
<div style={{color: 'black', fontSize: '14px'}}>
<a
href="#reset-password"
style={{
color: 'rgb(105, 124, 213)',
textDecoration: 'none',
}}
>
γγΉγ―γΌγγγεΏγγ§γγοΌ
</a>
</div>
),
},
},
},
blockOrder: defaultBlockOrder,
};
}}
</SignIn>
);
}
π§ Props Referenceβ
Main Component Propsβ
| Prop | Type | Default | Description |
|---|---|---|---|
onSubmit | SubmitHandler<T> | Required | Callback function triggered when form is submitted with valid data |
onChange | (setError, getValues, clearErrors) => void | Required | Callback function triggered when form values change. Provides form control functions for validation |
defaultData | DefaultValues<T> | undefined | Default form values to populate fields on initial render |
data | T | undefined | Controlled form values - use this for external form state management |
children | BlocksOverride | undefined | Custom block components to override default rendering |
className | string | undefined | Additional CSS class name for styling the form container |
Note: This component additional inherits some common HTML form element props.
Sub-Componentsβ
The SignIn component provides several sub-components. All sub-components receive their default values from the main component's context and can override these values through props.
SignIn.SignInTitleβ
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | "Sign In to App" | Title content |
size | enum | "2XL" | Typography size for the title |
type | enum | "heading" | Typography type |
color | enum | "low-emphasis" | Color theme for the title |
weight | enum | "bold" | Weight of the title |
className | string | undefined | Additional CSS class name for styling |
SignIn.EmailFieldβ
| Prop | Type | Default | Description |
|---|---|---|---|
name | string | "email" | Field name used for form data and validation |
label | string | "Email" | Field label displayed above the input |
placeholder | string | "Please enter your email" | Placeholder text shown when field is empty |
inputType | string | "email" | Input type - typically "email" or "text" |
isRequired | boolean | true | Whether the field is required (shows red asterisk) |
isDisabled | boolean | undefined | Whether the input is disabled |
errorText | string | undefined | Error text for the input |
className | string | undefined | Additional CSS class name for styling |
Note: This component additional inherits some common HTML input element props.
SignIn.PasswordFieldβ
| Prop | Type | Default | Description |
|---|---|---|---|
name | string | "password" | Field name used for form data and validation |
label | string | "Password" | Field label displayed above the input |
placeholder | string | "Please enter your password" | Placeholder text shown when field is empty |
inputType | string | "password" | Input type - typically "password" or "text" |
isRequired | boolean | true | Whether the field is required (shows red asterisk) |
isDisabled | boolean | undefined | Whether the input is disabled |
errorText | string | undefined | Error text for the input |
className | string | undefined | Additional CSS class name for styling |
Note: This component additional inherits some common HTML input element props.
SignIn.SignInButtonβ
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | "Login" | Button text content |
className | string | undefined | Additional CSS class name for styling |
fill | enum | "fill" | Button fill style |
icon | enum | undefined | Optional icon for the left-hand side of the button |
iconColor | enum | undefined | Color for the left-hand side icon. When not provided, a default color for the fill type will be used. |
isDisabled | boolean | false | Whether the button is disabled and cannot be used |
onClick | function | undefined | Function to handle button click |
size | enum | "M" | Button vertical size |
textAlign | enum | "center" | Button icon and text positioning within the button |
textColor | enum | "default" | Button text color |
textEmphasis | boolean | false | Button text weight |
textSize | enum | "M" | Button text size |
type | enum | "submit" | Button purpose (affects html type) |
SignIn.GotoSignUpβ
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | Default signup link | Content for the signup link section - typically contains an anchor tag |
className | string | undefined | Additional CSS class name for styling |
SignIn.ResetPasswordβ
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | Default reset link | Content for the reset password link section - typically contains an anchor tag |
className | string | undefined | Additional CSS class name for styling |
π§ TypeScript Supportβ
Full TypeScript support with comprehensive type definitions:
import {SignIn} from '@nodeblocks/frontend-signin-block';
//in future we will not use react-hook-form, we will use our own form handling
import {UseFormClearErrors, UseFormGetValues, UseFormSetError} from 'react-hook-form';
// Default form data structure
interface DefaultSignInFormData extends Record<string, unknown> {
email?: string;
password?: string;
}
// Extend with custom fields
interface CustomSignInFormData extends DefaultSignInFormData {
rememberMe?: boolean;
customField?: string;
}
const MySignInForm = () => {
const handleSubmit = (formData: CustomSignInFormData) => {
console.log('Form submitted:', formData);
// Handle form submission
};
const handleChange = (
setError: UseFormSetError<CustomSignInFormData>,
getValues: UseFormGetValues<CustomSignInFormData>,
clearErrors: UseFormClearErrors<CustomSignInFormData>,
) => {
const values = getValues();
// Custom validation
if (values.email && !values.email.includes('@')) {
setError('email', {message: 'Invalid email format'});
} else {
clearErrors('email');
}
};
return (
<SignIn<CustomSignInFormData>
onSubmit={handleSubmit}
onChange={handleChange}
defaultData={{email: 'user@example.com'}}>
<SignIn.SignInTitle>Welcome Back</SignIn.SignInTitle>
<SignIn.EmailField />
<SignIn.PasswordField />
<SignIn.SignInButton>Login</SignIn.SignInButton>
<SignIn.GotoSignUp>
<span>
Don't have an account? <a href="#signup">Sign Up</a>
</span>
</SignIn.GotoSignUp>
<SignIn.ResetPassword>
<span>
<a href="#reset-password">Forgot password?</a>
</span>
</SignIn.ResetPassword>
</SignIn>
);
};
Built with β€οΈ using React, TypeScript, and modern web standards.