Sign Up Block
The SignUp Component is a fully customizable and accessible sign-up form built with React and TypeScript. It provides a complete user registration interface with modern design patterns, form validation, terms acceptance, and flexible customization options.
๐ Installationโ
npm install @nodeblocks/frontend-signup-block
๐ Usageโ
import {SignUp} from '@nodeblocks/frontend-signup-block';
- Basic Usage
- Advanced Usage
function BasicSignUp() { return ( <SignUp 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'}}> <SignUp.SignUpTitle>Create Your Account</SignUp.SignUpTitle> <SignUp.EmailField label="Email Address" placeholder="Enter your email" /> <SignUp.PasswordField label="Password" placeholder="Enter your password" /> <SignUp.TermsOfUse name="agreesUserAgreement" label="I agree to the terms of use" /> <SignUp.PrivacyPolicy name="agreesPrivacyPolicy" label="I agree to the privacy policy" /> <SignUp.SignUpButton>Sign Up</SignUp.SignUpButton> <SignUp.GotoSignIn> <span>Already have an account? <a href="#signin">Sign In</a></span> </SignUp.GotoSignIn> </SignUp> ); }
function AdvancedSignUp() { return ( <SignUp 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'); } if (!values.agreesUserAgreement) { setError('agreesUserAgreement', {message: 'ๅฉ็จ่ฆ็ดใธใฎๅๆใๅฟ ่ฆใงใ', type: 'required'}); } else { clearErrors('agreesUserAgreement'); } if (!values.agreesPrivacyPolicy) { setError('agreesPrivacyPolicy', {message: 'ใใฉใคใใทใผใใชใทใผใธใฎๅๆใๅฟ ่ฆใงใ', type: 'required'}); } else { clearErrors('agreesPrivacyPolicy'); } }} onSubmit={formData => { console.log('ๆฐ่ฆ็ป้ฒ:', formData); }} > {({defaultBlocks, defaultBlockOrder}) => { return { blocks: { ...defaultBlocks, signUpTitle: { ...defaultBlocks.signUpTitle, props: { ...defaultBlocks.signUpTitle.props, style: { color: 'black', fontSize: '2.5rem', fontWeight: 'bold', textAlign: 'center', marginBottom: '8px', }, children: ( <div style={{display: 'flex', alignItems: 'center', justifyContent: 'center', gap: '12px'}}> <svg style={{width: '36px', height: '36px', color: 'rgb(105, 124, 213)'}} 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: '8ๆๅญไปฅไธใฎๅฎๅ จใชใในใฏใผใ', style: { background: 'rgba(255, 255, 255, 0.95)', borderRadius: '12px', fontSize: '16px', }, }, }, termsOfUse: { ...defaultBlocks.termsOfUse, props: { ...defaultBlocks.termsOfUse.props, name: 'agreesUserAgreement', label: ( <span style={{color: 'black', fontSize: '14px'}}> <a href="#terms" style={{ color: 'rgb(105, 124, 213)', textDecoration: 'none', fontWeight: 'bold', }} > ๅฉ็จ่ฆ็ด </a> ใซๅๆใใพใ </span> ), }, }, privacyPolicy: { ...defaultBlocks.privacyPolicy, props: { ...defaultBlocks.privacyPolicy.props, name: 'agreesPrivacyPolicy', label: ( <span style={{color: 'black', fontSize: '14px'}}> <a href="#privacy" style={{ color: 'rgb(105, 124, 213)', textDecoration: 'none', fontWeight: 'bold', }} > ใใฉใคใใทใผใใชใทใผ </a> ใซๅๆใใพใ </span> ), }, }, signUpButton: { ...defaultBlocks.signUpButton, props: { ...defaultBlocks.signUpButton.props, children: ( <div>ใขใซใฆใณใใไฝๆ</div> ), }, }, gotoSignIn: { ...defaultBlocks.gotoSignIn, props: { ...defaultBlocks.gotoSignIn.props, style: { textAlign: 'center', }, children: ( <div style={{color: 'black', fontSize: '14px'}}> <span>ๆขใซใขใซใฆใณใใใๆใกใฎๆนใฏ </span> <a href="#signin" style={{ color: 'rgb(105, 124, 213)', textDecoration: 'none', fontWeight: 'bold', }} > ใญใฐใคใณ </a> </div> ), }, }, }, blockOrder: defaultBlockOrder, }; }} </SignUp> ); }
๐ง 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 SignUp 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.
SignUp.SignUpTitleโ
Prop | Type | Default | Description |
---|---|---|---|
children | ReactNode | From context | 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 |
SignUp.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 |
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.
SignUp.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.
SignUp.TermsOfUseโ
Inherits all props from the HTML input
element and adds:
Prop | Type | Default | Description |
---|---|---|---|
name | string | "agreesUserAgreement" | Field name used for form data and validation |
label | ReactNode | Default terms link | Content for the terms of use checkbox label - typically contains a link |
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 |
SignUp.PrivacyPolicyโ
Inherits all props from the HTML input
element and adds:
Prop | Type | Default | Description |
---|---|---|---|
name | string | "agreesPrivacyPolicy" | Field name used for form data and validation |
label | ReactNode | Default privacy policy link | Content for the privacy policy checkbox label - typically contains a link |
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 |
SignUp.SignUpButtonโ
Prop | Type | Default | Description |
---|---|---|---|
children | ReactNode | "Sign Up" | 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) |
SignUp.GotoSignInโ
Inherits all props from the HTML div
element (except children
) and adds:
Prop | Type | Default | Description |
---|---|---|---|
children | ReactNode | Default signin link | Content for the signin 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 {SignUp} from '@nodeblocks/frontend-signup-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 DefaultSignUpFormData {
email?: string;
password?: string;
agreesPrivacyPolicy?: boolean;
agreesUserAgreement?: boolean;
}
// Extend with custom fields
interface CustomSignUpFormData extends DefaultSignUpFormData {
firstName?: string;
lastName?: string;
phone?: string;
}
const MySignUpForm = () => {
const handleSubmit = (formData: CustomSignUpFormData) => {
console.log('Form submitted:', formData);
// Handle form submission
};
const handleChange = (
setError: UseFormSetError<CustomSignUpFormData>,
getValues: UseFormGetValues<CustomSignUpFormData>,
clearErrors: UseFormClearErrors<CustomSignUpFormData>,
) => {
const values = getValues();
// Custom validation
if (values.email && !values.email.includes('@')) {
setError('email', {message: 'Invalid email format'});
} else {
clearErrors('email');
}
};
return (
<SignUp<DefaultSignUpFormData>
onSubmit={handleSubmit}
onChange={handleChange}
defaultData={{email: 'user@example.com'}}>
<SignUp.SignUpTitle>Create Account</SignUp.SignUpTitle>
<SignUp.EmailField />
<SignUp.PasswordField />
<SignUp.TermsOfUse
name="agreesUserAgreement"
label={
<span>
I agree to the <a href="/terms">Terms of Service</a>
</span>
}
/>
<SignUp.PrivacyPolicy
name="agreesPrivacyPolicy"
label={
<span>
I agree to the <a href="/privacy">Privacy Policy</a>
</span>
}
/>
<SignUp.SignUpButton>Register</SignUp.SignUpButton>
<SignUp.GotoSignIn>
<span>
Already have an account? <a href="/signin">Sign In</a>
</span>
</SignUp.GotoSignIn>
</SignUp>
);
};
Built with โค๏ธ using React, TypeScript, and modern web standards.