Change Password Block
ChangePassword is a controlled change-password form block built on MUI.
Installationโ
- npm
- yarn
- pnpm
- bun
npm install @nodeblocks/frontend-change-password-block
yarn add @nodeblocks/frontend-change-password-block
pnpm add @nodeblocks/frontend-change-password-block
bun add @nodeblocks/frontend-change-password-block
What You Needโ
| Item | Why it matters |
|---|---|
data | Single source of truth for form state (currentPassword, newPassword, confirmPassword) |
onDataChange | Receives updated state + metadata on field changes; meta includes name, value, cause (input, change, blur, clear, reset, programmatic), optional event |
errors (optional) | Displays field-level error feedback |
resetPasswordUrl (optional) | Target URL for the forgot-password link |
ChangePassword does not own form state. Keep state in your app and pass it through data.
Code Examplesโ
- Quick Start
- Labels and URLs
- Form Errors
- Compound Components
- Block Override
function Example() { const defaultData = { currentPassword: '', newPassword: '', confirmPassword: '', }; const [data, setData] = React.useState(defaultData); return ( <ChangePassword data={data} onDataChange={setData} onSubmit={e => { e.preventDefault(); alert(`Submit:\n${JSON.stringify(data, null, 2)}`); }} /> ); }
Customize the forgot-password URL and subcomponent copy.
function Example() { const defaultData = { currentPassword: '', newPassword: '', confirmPassword: '', }; const [data, setData] = React.useState(defaultData); return ( <ChangePassword data={data} onDataChange={setData} resetPasswordUrl="/auth/resetpassword" onSubmit={e => { e.preventDefault(); alert(`Submit:\n${JSON.stringify(data, null, 2)}`); }} > <ChangePassword.Title>Change your password</ChangePassword.Title> <ChangePassword.Form> <ChangePassword.Form.CurrentPasswordField label="Current password" placeholder="Enter your current password" /> <ChangePassword.Form.ResetPasswordLink> <a href="#auth/resetpassword" style={{color: '#007ADD'}}> Forgot password? </a> </ChangePassword.Form.ResetPasswordLink> <ChangePassword.Form.NewPasswordField label="New password" placeholder="Enter a new password" /> <ChangePassword.Form.ConfirmPasswordField label="Confirm new password" placeholder="Re-enter the new password" /> <ChangePassword.Form.ChangePasswordButton>Update password</ChangePassword.Form.ChangePasswordButton> </ChangePassword.Form> </ChangePassword> ); }
There is no root labels prop. Set resetPasswordUrl on the root; override title, fields, and button via subcomponent props, and pass children to ChangePassword.Form.ResetPasswordLink if you need custom link markup. Link default text: ใในใฏใผใใๅฟใใๆน.
Validate and display field errors while keeping the form controlled.
function Example() { const defaultData = { currentPassword: '', newPassword: '', confirmPassword: '', }; const [data, setData] = React.useState(defaultData); const [errors, setErrors] = React.useState({}); const handleDataChange = (nextData, meta) => { const {[meta.name]: _removed, ...restErrors} = errors; let nextErrors = restErrors; // Validate required fields on blur (same pattern as storybook) if (meta.cause === 'blur') { nextErrors = {...restErrors}; if (meta.name === 'currentPassword' && !nextData.currentPassword) { nextErrors.currentPassword = 'Current password is required.'; } if (meta.name === 'newPassword' && !nextData.newPassword) { nextErrors.newPassword = 'New password is required.'; } if (meta.name === 'confirmPassword') { if (!nextData.confirmPassword) { nextErrors.confirmPassword = 'Please confirm your new password.'; } else if (nextData.newPassword && nextData.confirmPassword !== nextData.newPassword) { nextErrors.confirmPassword = 'Passwords do not match.'; } } } setErrors(nextErrors); setData(nextData); }; return ( <ChangePassword data={data} errors={Object.keys(errors).length ? errors : undefined} onDataChange={handleDataChange} onSubmit={e => { e.preventDefault(); alert(`Submit:\n${JSON.stringify(data, null, 2)}`); }} /> ); }
Use child blocks to customize layout while keeping controlled state behavior.
function Example() { const defaultData = { currentPassword: '', newPassword: '', confirmPassword: '', }; const [data, setData] = React.useState(defaultData); return ( <ChangePassword data={data} onDataChange={setData} resetPasswordUrl="/auth/resetpassword" onSubmit={e => { e.preventDefault(); alert(`Submit:\n${JSON.stringify(data, null, 2)}`); }} > <ChangePassword.Title>Change your password</ChangePassword.Title> <ChangePassword.Form> <ChangePassword.Form.CurrentPasswordField label="Current password" placeholder="Enter your current password" /> <ChangePassword.Form.ResetPasswordLink> <a href="#auth/resetpassword" style={{color: '#007ADD'}}> Forgot password? </a> </ChangePassword.Form.ResetPasswordLink> <ChangePassword.Form.NewPasswordField label="New password" placeholder="Enter a new password" /> <ChangePassword.Form.ConfirmPasswordField label="Confirm new password" placeholder="Re-enter the new password" /> <ChangePassword.Form.ChangePasswordButton>Update password</ChangePassword.Form.ChangePasswordButton> </ChangePassword.Form> </ChangePassword> ); }
Use function children to override default blocks and order.
function Example() { const defaultData = { currentPassword: '', newPassword: '', confirmPassword: '', }; const [data, setData] = React.useState(defaultData); return ( <ChangePassword data={data} onDataChange={setData} onSubmit={e => { e.preventDefault(); alert(`Submit:\n${JSON.stringify(data, null, 2)}`); }} > {({defaultBlocks, defaultBlockOrder}) => ({ blocks: { ...defaultBlocks, notice: ( <div style={{ background: '#eef4ff', border: '1px solid #cddcff', borderRadius: '8px', padding: '12px', fontSize: '14px', textAlign: 'center', width: '100%', maxWidth: 684, }} > Custom notification or help text </div> ), }, blockOrder: ['notice', ...defaultBlockOrder], })} </ChangePassword> ); }
When to use block overrides
Use overrides when you need to change order, replace default UI blocks, or inject custom content while preserving shared state handling. Default order is title, form.
Important Propsโ
Core Propsโ
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
data | ChangePasswordFormData ({ currentPassword?, newPassword?, confirmPassword? } or extended Record<string, unknown>) | Yes | - | Current form data object |
onDataChange | (data, meta) => void | Yes | - | Called on updates; meta includes name, value, cause (input, change, blur, clear, reset, programmatic), optional event |
errors | { [fieldName: string]: string | string[] } | No | undefined | Field errors keyed by data field name (currentPassword, newPassword, confirmPassword) |
Content Propsโ
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
resetPasswordUrl | string | No | /auth/resetpassword | URL for Form.ResetPasswordLink (link text default: ใในใฏใผใใๅฟใใๆน) |
Layout and Composition Propsโ
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
children | BlocksOverride | ReactNode | No | undefined | Override default blocks or provide custom JSX children |
component | React.ElementType | No | 'form' | Root element type |
className | string | No | undefined | Class name for the root container |
sx | SxProps | No | undefined | MUI system styles for the root container |
ChangePassword also inherits StackProps<'form'> (except children), so standard form props like onSubmit, id, and noValidate are supported. Default block order without overrides: title, form (defaultBlockOrder).
Default UI Blocksโ
| Block | Built on | Notes |
|---|---|---|
ChangePassword (root) | Stack (component="form") | Controlled form container; inner content max width 684px |
ChangePassword.Title | Typography | Title (variant="h6"); default ใในใฏใผใใๅคๆด |
ChangePassword.Form | Stack | Form fields container (submit handled by root form) |
ChangePassword.Form.CurrentPasswordField | TextField + IconButton | Default label/placeholder ็พๅจใฎใในใฏใผใ / ็พๅจใฎใในใฏใผใใๅ
ฅๅ |
ChangePassword.Form.ResetPasswordLink | Box + Link | Default link text ใในใฏใผใใๅฟใใๆน; href falls back to resetPasswordUrl or /auth/resetpassword |
ChangePassword.Form.NewPasswordField | TextField + IconButton | Default ๆฐใใใในใฏใผใ / ๆฐใใใในใฏใผใใๅ
ฅๅ |
ChangePassword.Form.ConfirmPasswordField | TextField + IconButton | Default ๆฐใใใในใฏใผใใๅๅ
ฅๅ (label and placeholder) |
ChangePassword.Form.ChangePasswordButton | Button | Submit (variant="contained", type="submit"); default ใในใฏใผใใๅคๆด |
TypeScriptโ
import {ChangePassword, ChangePasswordFormData} from '@nodeblocks/frontend-change-password-block';
type MyChangePasswordData = ChangePasswordFormData & {
userId?: string;
};