パスワードリセットブロック
ResetPassword コンポーネント は、React と TypeScript で構築された、完全にカスタマイズ可能でアクセシブルなパスワードリセットフォームです。リクエストと確認フローの両方に対応する2つのビュー、モダンなデザインパターン、柔軟なカスタマイズオプションを備えた、完全なパスワードリセット UI を提供します。
🚀 インストール
npm install @nodeblocks/frontend-reset-password-block@0.1.1
📖 使用方法
import {ResetPassword} from '@nodeblocks/frontend-reset-password-block';
- Basic Usage
- Advanced Usage
function BasicResetPassword() {
const [view, setView] = useState<'request' | 'confirm_password'>('request');
return (
<ResetPassword
view={view}
onSendRequest={formData => {
console.log('Reset request sent:', formData);
setView('confirm_password');
}}
onResetPassword={formData => {
console.log('Password reset:', formData);
setView('request');
}}>
<ResetPassword.Title>
{view === 'request' ? 'Reset Your Password' : 'Confirm Password'}
</ResetPassword.Title>
<ResetPassword.Description>
{view === 'request' ? 'Enter your email to receive reset instructions' : 'Enter your new password'}
</ResetPassword.Description>
<ResetPassword.Form>
<ResetPassword.Form.EmailField label="Email Address" placeholder="Enter your email" />
<ResetPassword.Form.PasswordField label="New Password" placeholder="Enter new password" />
<ResetPassword.Form.ConfirmPasswordField label="Confirm Password" placeholder="Confirm new password" />
<ResetPassword.Form.ResetPasswordButton>Reset Password</ResetPassword.Form.ResetPasswordButton>
</ResetPassword.Form>
<ResetPassword.Goto>
<a href="#signin">Back to Sign In</a>
</ResetPassword.Goto>
</ResetPassword>
);
}
function AdvancedResetPassword() {
const [view, setView] = useState('request');
return (
<ResetPassword
style={{
maxWidth: '500px',
margin: '0 auto',
background: 'linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%)',
borderRadius: '16px',
padding: '32px',
boxShadow: '0 20px 40px rgba(0, 0, 0, 0.1)',
}}
view={view}>
{({defaultBlocks, defaultBlockOrder}) => {
console.log(defaultBlocks, defaultBlockOrder);
return {
blocks: {
...defaultBlocks,
title: {
...defaultBlocks.title,
props: {
...defaultBlocks.title.props,
style: {
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
WebkitBackgroundClip: 'text',
WebkitTextFillColor: 'transparent',
backgroundClip: 'text',
fontSize: '2.5rem',
fontWeight: 'bold',
textAlign: 'center',
marginBottom: '16px',
},
children: (
<div style={{display: 'flex', alignItems: 'center', justifyContent: 'center', gap: '12px'}}>
<svg style={{width: '32px', height: '32px', color: '#667eea'}} fill="currentColor" viewBox="0 0 24 24">
<path d="M12 1L3 5V11C3 16.55 6.84 21.74 12 23C17.16 21.74 21 16.55 21 11V5L12 1M12 7C13.11 7 14 7.9 14 9S13.11 11 12 11 10 10.11 10 9 10.9 7 12 7M18 14.2C16.69 16.92 14.5 19.13 11.8 20.4C14.5 19.13 16.69 16.92 18 14.2Z" />
</svg>
<span>{view === 'request' ? 'パスワードリセット' : '新しいパスワード設定'}</span>
</div>
),
},
},
description: {
...defaultBlocks.description,
props: {
...defaultBlocks.description.props,
style: {
textAlign: 'center',
color: '#64748b',
fontSize: '16px',
lineHeight: '1.6',
marginBottom: '32px',
padding: '16px',
background: 'white',
borderRadius: '8px',
border: '1px solid #e2e8f0',
},
children: view === 'request'
? 'ご登録いただいたメールアドレスを入力してください。パスワードリセット用のリンクをお送りします。'
: '新しいパスワードを入力してください。セキュリティのため、8文字以上の強固なパスワードを設定してください。',
},
},
form: {
...defaultBlocks.form,
props: {
...defaultBlocks.form.props,
onSubmit: (e) => {
e.preventDefault();
if (view === 'request') {
setView('confirm_password');
} else {
setView('request');
}
},
style: {
background: 'white',
borderRadius: '12px',
padding: '24px',
marginBottom: '24px',
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.05)',
border: '1px solid #e2e8f0',
},
children: (
<>
<ResetPassword.Form.EmailField
label="メールアドレス"
placeholder="例: user@company.com"
style={{
marginBottom: '20px',
background: 'linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%)',
borderRadius: '8px',
border: '2px solid #e2e8f0',
padding: '12px',
transition: 'all 0.2s ease',
}}
/>
<ResetPassword.Form.PasswordField
label="新しいパスワード"
placeholder="8文字以上の安全なパスワード"
style={{
marginBottom: '20px',
background: 'linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%)',
borderRadius: '8px',
border: '2px solid #e2e8f0',
padding: '12px',
transition: 'all 0.2s ease',
}}
/>
<ResetPassword.Form.ConfirmPasswordField
label="パスワード確認"
placeholder="パスワードを再入力してください"
style={{
marginBottom: '24px',
background: 'linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%)',
borderRadius: '8px',
border: '2px solid #e2e8f0',
padding: '12px',
transition: 'all 0.2s ease',
}}
/>
<ResetPassword.Form.ResetPasswordButton type="">
{view === 'request' ? 'リセットリンクを送信' : 'パスワードを更新'}
</ResetPassword.Form.ResetPasswordButton>
</>
),
},
},
goto: {
...defaultBlocks.goto,
props: {
...defaultBlocks.goto.props,
style: {
textAlign: 'center',
padding: '16px',
background: 'rgba(255, 255, 255, 0.7)',
borderRadius: '8px',
border: '1px solid #e2e8f0',
},
children: (
<div style={{color: '#64748b', fontSize: '14px'}}>
<span>パスワードを思い出しましたか? </span>
<a
href="#signin"
style={{
color: '#667eea',
textDecoration: 'none',
fontWeight: '500',
transition: 'color 0.2s ease',
}}
onMouseEnter={e => e.target.style.color = '#5a6fd8'}
onMouseLeave={e => e.target.style.color = '#667eea'}
>
ログインページに戻る
</a>
</div>
),
},
},
},
blockOrder: defaultBlockOrder,
};
}}
</ResetPassword>
);
}
🔧 Props リファレンス
メインコンポーネントの props
メインの ResetPassword コンポーネントは、children と onSubmit を除いて HTML div 要素のすべての props を継承し、さらに次を追加します:
| Prop | Type | Default | Description |
|---|---|---|---|
view | 'request' | 'confirm_password' | Required | Determines which view to display - either email request form or password confirmation form |
onSendRequest | (data: T) => void | Required | Callback function triggered when reset request is submitted |
onResetPassword | (data: T) => void | Required | Callback function triggered when new password is submitted |
resetPasswordTitle | ReactNode | "Reset Password" | Title content for the reset password form |
description | ReactNode | "Please enter your email address you registered" | Description text displayed below the title |
gotoSigninMessage | ReactNode | デフォルトのサインインリンク | ナビゲーションリンクセクションの内容 |
className | string | undefined | Additional CSS class name for styling the form container |
direction | enum | "column" | Flex direction for action buttons |
alignItems | enum | "stretch" | Alignment of items in the container |
gapSize | enum | "S" | Gap between items in the container |
children | BlocksOverride | undefined | Custom block components to override default rendering |
サブコンポーネント
ResetPassword コンポーネントには、いくつかのサブコンポーネントがあります。すべてのサブコンポーネントはメインコンポーネントのコンテキストからデフォルト値を受け取り、props でそれらを上書きできます。
ResetPassword.Title
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | コンテキストから | タイトルコンテンツ。コンテキストの errorTitle を上書きします |
size | enum | "2XL" | タイトルの Typography サイズ |
type | enum | "heading" | Typography の type |
color | enum | "low-emphasis" | タイトルのカラーテーマ |
weight | enum | "bold" | タイトルの weight |
className | string | undefined | スタイル用の追加 CSS クラス名 |
ResetPassword.Description
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | コンテキストから | タイトルコンテンツ。コンテキストの errorTitle を上書きします |
size | enum | "M" | 説明の Typography サイズ |
type | enum | "paragraph" | Typography の type |
color | enum | "low-emphasis" | 説明のカラーテーマ |
weight | enum | "regular" | 説明の weight |
className | string | undefined | スタイル用の追加 CSS クラス名 |
ResetPassword.Form
| Prop | Type | Default | Description |
|---|---|---|---|
view | 'request' | 'confirm_password' | 親から継承 | 表示するフィールドを決定します |
onSendRequest | (data: T) => void | 親から継承 | メール送信のコールバック |
onResetPassword | (data: T) => void | 親から継承 | パスワード確認のコールバック |
className | string | undefined | スタイル用の追加 CSS クラス名 |
children | ReactNode | コンテキストから | カスタムのフォーム内容 |
ResetPassword.Form.EmailField
| Prop | Type | Default | Description |
|---|---|---|---|
name | string | "email" | フォーム data に使用されるフィールド名 |
errorText | string | undefined | 入力欄のエラーテキスト |
isDisabled | boolean | undefined | 入力欄が無効かどうか |
isRequired | boolean | undefined | 入力欄が必須かどうか |
label | string | "Email" | 入力欄のラベル |
labelWeight | enum | "bold" | ラベルの weight |
className | string | undefined | スタイル用の追加 CSS クラス名 |
Note: このコンポーネントは、一般的な HTML input 要素の props も追加で継承します。
ResetPassword.Form.PasswordField
| Prop | Type | Default | Description |
|---|---|---|---|
name | string | "password" | フォーム data に使用されるフィールド名 |
errorText | string | undefined | 入力欄のエラーテキスト |
isDisabled | boolean | undefined | 入力欄が無効かどうか |
isRequired | boolean | undefined | 入力欄が必須かどうか |
label | string | "Password" | 入力欄のラベル |
labelWeight | enum | "bold" | ラベルの weight |
className | string | undefined | スタイル用の追加 CSS クラス名 |
showPassword | boolean | undefined | パスワードを表示するかどうか |
onShowPasswordClick | function | undefined | パスワード表示切り替えを処理する関数 |
Note: このコンポーネントは、一般的な HTML input 要素の props も追加で継承します。
ResetPassword.Form.ConfirmPasswordField
| Prop | Type | Default | Description |
|---|---|---|---|
name | string | "confirmPassword" | Field name used for form data |
errorText | string | undefined | Error text for the input |
isDisabled | boolean | undefined | Whether the input is disabled |
isRequired | boolean | undefined | Whether the input is required |
label | string | "Confirm Password" | Label of the input field |
labelWeight | enum | "bold" | Label weight |
className | string | undefined | Additional CSS class name for styling |
showPassword | boolean | undefined | Whether to show password |
onShowPasswordClick | function | undefined | Function to handle password visibility toggle |
Note: This component additional inherits some common HTML input element props.
ResetPassword.Form.ResetPasswordButton
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | コンテキストから | ボタン内に配置するテキスト |
className | string | undefined | スタイル用の追加 CSS クラス名 |
fill | enum | "fill" | ボタンの塗りつぶしスタイル |
icon | enum | undefined | ボタン左側に表示する任意のアイコン |
iconColor | enum | undefined | ボタン左側のアイコンの色。指定しない場合は、fill の種類に応じたデフォルト色が使われます。 |
isDisabled | boolean | false | ボタンが無効で使用できないかどうか |
onClick | function | undefined | ボタンのクリックを処理する関数 |
size | enum | "M" | ボタンの縦方向のサイズ |
textAlign | enum | "center" | ボタン内でのアイコンとテキストの配置 |
textColor | enum | "default" | ボタンのテキスト色 |
textEmphasis | boolean | false | ボタンのテキストの太さ |
textSize | enum | "M" | ボタンのテキストサイズ |
type | enum | "submit" | ボタンの用途(HTML type に影響します) |
Note: このコンポーネントは、一般的な HTML button 要素の props も追加で継承します。
ResetPassword.Goto
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | デフォルトのサインインリンク | ナビゲーションリンクセクションの内容。通常はアンカータグを含みます |
className | string | undefined | スタイル用の追加 CSS クラス名 |
🔧 TypeScript サポート
包括的な型定義を備えた完全な TypeScript サポート:
import {ResetPassword} from '@nodeblocks/frontend-reset-password-block';
// Default form data structure for email request
interface ResetPasswordEmailData {
email?: string;
}
// Default form data structure for password confirmation
interface ResetPasswordConfirmData {
password?: string;
confirmPassword?: string;
}
// Combined form data type
type ResetPasswordFormData = ResetPasswordEmailData | ResetPasswordConfirmData;
// Extend with custom fields
interface CustomResetPasswordFormData extends ResetPasswordFormData {
customField?: string;
}
const MyResetPasswordForm = () => {
const handleSendRequest = (formData: ResetPasswordFormData) => {
console.log('Reset request sent:', formData);
// Handle email submission
};
const handleResetPassword = (formData: ResetPasswordFormData) => {
console.log('Password reset:', formData);
// Handle password reset
};
return (
<ResetPassword<CustomResetPasswordFormData>
view="request"
onSendRequest={handleSendRequest}
onResetPassword={handleResetPassword}
resetPasswordTitle="Forgot Your Password?"
description="Enter your email address and we'll send you reset instructions">
<ResetPassword.Title>Reset Your Password</ResetPassword.Title>
<ResetPassword.Description>
Don't worry, it happens to everyone. Enter your email below.
</ResetPassword.Description>
<ResetPassword.Form>
<ResetPassword.Form.EmailField />
<ResetPassword.Form.PasswordField />
<ResetPassword.Form.ConfirmPasswordField />
<ResetPassword.Form.ResetPasswordButton>Send Reset Link</ResetPassword.Form.ResetPasswordButton>
</ResetPassword.Form>
<ResetPassword.Goto>
<span>
Remember your password? <a href="#signin">Sign In</a>
</span>
</ResetPassword.Goto>
</ResetPassword>
);
};
React、TypeScript、そして最新の Web 標準を使用して構築されています。