Documentation LoginGen
Introduction
LoginGen est un site de modèles de pages de connexion. Ce projet a été développé car bien qu'il existe de nombreux sites de modèles sur le marché, la plupart manquent de support pour les pages de connexion ou n'offrent qu'un ou deux modèles simples, souvent sans logique frontale complète. Bien que l'importance interactionnelle d'une page de connexion ne soit peut-être pas aussi grande que celle d'une Landing Page, une belle page de connexion peut néanmoins renforcer la première impression des utilisateurs sur un site.
La stack technique est principalement basée sur Next.js et Shadcn/ui. En plus de fournir des modèles de conception, elle offre une logique frontale complète et utilise la capacité Server Actions de Next.js pour un traitement unifié de l'authentification côté serveur (à l'exception de la connexion sociale, qui est gérée côté client pour plus de commodité).
Tous les codes sont ouverts, comme Shadcn, et peuvent être copiés-collés pour une utilisation immédiate. Vous pouvez donc modifier librement le code selon les besoins de votre projet, ce qui est d'ailleurs recommandé. Pour plus de commodité, les composants de formulaire incluent également des propriétés couramment utilisées, permettant une utilisation prête à l'emploi.
D'autres modèles seront continuellement ajoutés, améliorés et optimisés à l'avenir. Restez à l'écoute.
Installation
Les modèles sont développés avec Next.js et Shadcn, vous devez donc d'abord disposer de cet environnement de projet :
- "next": "^14.2+"
- "tailwindcss": "^3.4+"
- "react-hook-form: 7.52.2" - N'utilisez pas de version supérieure pour le moment, car les versions plus récentes présentent des bugs de rendu (issues : https://github.com/react-hook-form/react-hook-form/issues/12518)
Composants shadcn
Si vous utilisez un autre outil de gestion de paquets ou souhaitez une installation manuelle, consultez la documentation de shadcn.
pnpm dlx shadcn@latest add card tabs form button input input-otp separator sonner
Ajoutez les animations CSS suivantes à votre fichier tailwind.config.js
// for input-otp
/** @type {import('tailwindcss').Config} */
module.exports = {
theme: {
extend: {
keyframes: {
'caret-blink': {
'0%,70%,100%': { opacity: '1' },
'20%,50%': { opacity: '0' }
}
},
animation: {
'caret-blink': 'caret-blink 1.25s ease-out infinite'
}
}
}
}
Pour sonner, vous devez ajouter le composant suivant :
import { Toaster } from '@/components/ui/sonner'
export default function RootLayout({ children }) {
return (
<html lang='en'>
<head />
<body>
<main>{children}</main>
<Toaster />
</body>
</html>
)
}
Bibliothèques tierces
pnpm add react-hook-form@7.52.2 zod motion @zxcvbn-ts/core @zxcvbn-ts/language-common @zxcvbn-ts/language-en embla-carousel-react embla-carousel-autoplay embla-carousel-fade lucide-react
pnpm add -D embla-carousel
react-hook-form
+zod
-- Validation côté client des formulairesmotion
-- Bibliothèque d'animation@zxcvbn-*
-- Bibliothèque de détection de force des mots de passeembla-carousel-*
-- Bibliothèque de carrousel (oùembla-carousel
doit être installé dansdevDependencies
pour obtenir correctement les types TypeScript)lucide-react
-- Bibliothèque d'icônes
Copier-coller le code
Chaque page de prévisualisation de modèle affiche le code complet. Il vous suffit de copier-coller le code nécessaire à l'emplacement correspondant de votre projet. Les images incluses dans les modèles peuvent être téléchargées directement, et les vidéos sont fournies via CDN.
Pour le moment, aucune fonctionnalité d'installation en un clic similaire à npx
n'est disponible, mais cela
pourrait être envisagé ultérieurement.
Thème
Chaque modèle contient un fichier de thème styles/theme.module.css
qui inclut toutes les variables de thème
ainsi que les styles et animations nécessaires pour le modèle. Vous pouvez modifier les styles dans ce fichier
pour adapter le thème ou le faire correspondre à l'esthétique UI de votre site.
Mode sombre
Configurez le mode sombre selon la documentation de shadcn. Dans
le fichier de thème theme.module.css
de chaque modèle, le thème sombre utilise le préfixe de sélecteur CSS
:global(.dark)
pour répondre au mode sombre global du site.
I18n (TODO)
La configuration multilingue n'est pas encore prise en charge, mais vous pouvez toujours l'ajouter manuellement, bien que cela puisse être un peu fastidieux. Cette fonctionnalité pourrait être ajoutée ultérieurement.
Propriétés des formulaires
Il existe cinq formulaires : connexion, inscription, mot de passe oublié, réinitialisation du mot de passe et vérification OTP (one-time password). Chaque formulaire possède des paramètres pour une utilisation prête à l'emploi, la plupart étant communs.
Bien que dans le code des modèles, chaque page de formulaire soit une route distincte avec une redirection côté serveur pour la navigation entre les pages de formulaire, tous les composants sont conçus pour être utilisés via des propriétés transmises. Cela signifie que vous pouvez parfaitement utiliser le routage côté client.
Connexion
L'interface est définie comme suit :
const _auths = ['social', 'email', 'password'] as const
type Auth = (typeof _auths)[number]
export interface SignInFormProps {
auths?: Readonly<Auth[]>
socials?: SocialKey[]
email?: string
emailStrategy?: 'magic-link' | 'one-time-pwd'
socialHandler?: (event: MouseEvent<HTMLButtonElement>, key: SocialKey) => void | Promise<void>
forgetHandler?: string | ((event: React.MouseEvent<HTMLAnchorElement>) => void | Promise<void>) // for more convenient use
serverAction?: (
formType: 'email' | 'password',
currentState: SignInActionState,
formData: FormData
) => Promise<SignInActionState>
serverStateSuccessHandler?: (formType: 'email' | 'password', email: string) => void | Promise<void>
}
Paramètre | Valeur par défaut | Explication |
---|---|---|
auths | ['social', 'password', 'email'] | Méthodes d'authentification : connexion sociale, par e-mail, par mot de passe |
socials | ['google', 'github'] | Types de connexion sociale (la mise en page s'adapte automatiquement en fonction du nombre choisi et de la largeur du formulaire) |
E-mail initial, également utilisé pour pré-remplir l'affichage après le retour depuis le formulaire de vérification OTP lors de la modification de l'e-mail | ||
emailStrategy | 'magic-link' | Type d'e-mail envoyé. Si 'magic-link', aucune redirection de page n'est effectuée, mais une notification sonner est déclenchée. Sinon, une redirection vers le formulaire de vérification OTP est nécessaire |
socialHandler | Fonction de rappel lors du clic sur un bouton de connexion sociale. Vous pouvez utiliser des bibliothèques comme Auth.js pour implémenter cette fonctionnalité | |
forgetHandler | '#' | Fonction de rappel lors du clic sur le bouton 'Mot de passe oublié'. Ce paramètre est principalement destiné à faciliter l'utilisation |
serverAction | Tous les formulaires, à l'exception de la connexion sociale, sont soumis au serveur via Server Actions | |
serverStateSuccessHandler | Généralement, une fois l'authentification côté serveur terminée, une redirection côté serveur est effectuée. Mais si vous souhaitez implémenter une logique de redirection côté client, vous pouvez le faire via ce rappel |
Remarques :
socials
-- Chaque modèle possède un fichier de configurationconfig/social.tsx
. Vous pouvez modifier ce fichier pour étendre les méthodes de connexion sociale dont vous avez besoin. Vous pouvez modifier librement lakey
pour l'adapter à votre framework d'authentification, ou remplacer l'icône SVG par celui que vous préférez.email
-- Dans l'interface du formulaireverify-otp
, un bouton permet de modifier l'e-mail. Lorsque l'utilisateur clique sur ce bouton, il doit être redirigé vers la page précédente pour corriger son e-mail. Le paramètreemail
est conçu pour pré-remplir l'affichage de l'e-mail après ce retour.
Inscription
L'interface est définie comme suit :
export interface SignUpFormProps {
email?: string
serverAction: (currentState: SignUpActionState, formData: FormData) => Promise<SignUpActionState>
serverStateSuccessHandler?: (email: string) => void | Promise<void>
}
Paramètre | Valeur par défaut | Explication |
---|---|---|
E-mail initial, également utilisé pour pré-remplir l'affichage après le retour depuis le formulaire de vérification OTP lors de la modification de l'e-mail | ||
serverAction | Soumission des données du formulaire au serveur via Server Actions | |
serverStateSuccessHandler | Généralement, une redirection côté serveur est effectuée après l'authentification. Si une logique de redirection côté client est nécessaire, utilisez ce rappel |
Mot de passe oublié
L'interface est définie comme suit :
export interface ForgetPasswordProps {
email?: string
emailStrategy?: 'magic-link' | 'one-time-pwd'
serverAction: (
currentState: ForgetPasswordActionState,
formData: FormData
) => Promise<ForgetPasswordActionState>
serverStateSuccessHandler?: (email: string) => void | Promise<void>
}
Paramètre | Valeur par défaut | Explication |
---|---|---|
E-mail initial, également utilisé pour pré-remplir l'affichage après le retour depuis le formulaire de vérification OTP lors de la modification de l'e-mail | ||
emailStrategy | 'magic-link' | Type d'e-mail envoyé. Si 'magic-link', une notification sonner est déclenchée. Sinon, redirection vers le formulaire OTP |
serverAction | Soumission des données du formulaire au serveur via Server Actions | |
serverStateSuccessHandler | Généralement, une redirection côté serveur est effectuée après l'authentification. Si une logique de redirection côté client est nécessaire, utilisez ce rappel |
Réinitialisation du mot de passe
L'interface est définie comme suit :
export interface ResetPasswordFormProps {
email?: string // Only used to test password strength
resetToken?: string
serverAction: (
resetToken: string,
currentState: ResetPasswordActionState,
formData: FormData
) => Promise<ResetPasswordActionState>
serverStateSuccessHandler?: () => void | Promise<void>
}
Paramètre | Valeur par défaut | Explication |
---|---|---|
Utilisé uniquement pour tester la force du mot de passe (recommandé pour améliorer la sécurité) | ||
resetToken | Token généré par le serveur pour suivre le processus du formulaire | |
serverAction | Soumission des données du formulaire au serveur via Server Actions | |
serverStateSuccessHandler | Généralement, une redirection côté serveur est effectuée après l'authentification. Si une logique de redirection côté client est nécessaire, utilisez ce rappel |
resetToken Dans le processus de réinitialisation du mot de passe, le serveur génère généralement un
token
pour suivre et confirmer de manière sécurisée l'expéditeur du formulaire et son état.Le serveur transmet généralement le
token
de deux manières : soit dans les paramètres de requête de l'URL, soit dans uncookie
, que le navigateur inclut automatiquement lors de la soumission du formulaire.Dans le premier cas, vous pouvez utiliser
searchParams
ouuseSearchParams()
pour récupérer leresetToken
dans les paramètres de requête et le transmettre au formulaire. Le formulaire enverra automatiquement ceresetToken
au Server Action du serveur lors de la soumission.Dans le second cas, vous pouvez ignorer ce paramètre.
Vérification OTP
L'interface est définie comme suit :
export interface VerifyOTPFormProps {
email: string
verifyToken?: string
editEmailHandler?: (event: MouseEvent<HTMLButtonElement>) => void
serverAction: (
email: string,
verifyToken: string,
currentState: VerifyOTPActionState,
formData: FormData
) => Promise<VerifyOTPActionState>
codeResendAction: (email: string, verifyToken: string) => Promise<VerifyOTPActionState>
serverStateSuccessHandler?: () => void | Promise<void>
}
Paramètre | Valeur par défaut | Explication |
---|---|---|
E-mail initial affiché dans l'interface, permettant à l'utilisateur de le modifier | ||
verifyToken | Token généré par le serveur pour suivre le processus du formulaire | |
editEmailHandler | Fonction appelée lors du clic sur le bouton de modification d'e-mail | |
codeResendAction | Fonction pour renvoyer le code (le délai en secondes peut être défini via la constante code_resend_max_seconds dans verify-otp-form.tsx ) | |
serverAction | Soumission des données du formulaire au serveur via Server Actions | |
serverStateSuccessHandler | Généralement, une redirection côté serveur est effectuée après l'authentification. Si une logique de redirection côté client est nécessaire, utilisez ce rappel |
verifyToken Dans le processus de vérification du one-time password, le serveur génère généralement un
token
pour suivre et confirmer de manière sécurisée l'expéditeur du formulaire et son état.Le serveur transmet généralement le
token
de deux manières : soit dans les paramètres de requête de l'URL, soit dans uncookie
, que le navigateur inclut automatiquement lors de la soumission du formulaire.Dans le premier cas, vous pouvez utiliser
searchParams
ouuseSearchParams()
pour récupérer leverifyToken
dans les paramètres de requête et le transmettre au formulaire. Le formulaire enverra automatiquement ceverifyToken
au Server Action du serveur lors de la soumission.Dans le second cas, vous pouvez ignorer ce paramètre.
Côté serveur
À l'exception de la connexion sociale, toutes les options de connexion sont soumises aux Server Actions après
validation côté client pour le traitement logique côté serveur. Les soumissions de formulaire utilisent
useFormState
et useFormStatus
de React.
Le fichier types/action-state.ts
dans le code des modèles définit simplement le format des données soumises
aux Server Actions. Vous pouvez l'étendre selon vos besoins.
Voici un exemple de code pour les opérations dans une server action :
sign-in-action.ts
'use server'
import type { FormType, SignInActionState } from '@/types/server'
import { redirect } from 'next/navigation'
import { revalidatePath } from 'next/cache'
export async function signInAction(
formType: FormType,
currentState: SignInActionState,
formData: FormData
): Promise<SignInActionState> {
switch (formType) {
case 'email':
return await emailAction(formData)
case 'password':
return await passwordAction(formData)
}
}
async function emailAction(formData: FormData): Promise<SignInActionState> {
const data = Object.fromEntries(formData)
const parsed = signInSchemas.email.safeParse(data)
// La validation du formulaire est également requise côté serveur
if (!parsed.success) {
const issues: Record<string, string> = {}
parsed.error.issues.map((issue) => (issues[issue.path[0]] = issue.message))
return {
success: false,
formIssues: issues
}
}
// Effectuez des opérations côté serveur, comme l'envoi d'e-mails, l'accès aux bases de données, etc.
// La redirection peut être effectuée côté serveur
revalidatePath('/auth/sign-in')
redirect(`/auth/verify-otp`)
// Ou retournez directement au client
// return { success: true }
}
async function passwordAction(formData: FormData): Promise<SignInActionState> {
const data = Object.fromEntries(formData)
// Simulation de délai
await new Promise((resolve) => setTimeout(resolve, 2000))
console.log('Sign in password server action form data : ' + JSON.stringify(data, null, 2))
return { success: true }
}