Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
152 changes: 152 additions & 0 deletions LoginReadme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
# React Login Modal Component

A modern, accessible, animated React login modal featuring:

- Email & Password inputs with strong validation
- "Show Password" toggle
- Gravatar-based user avatars
- Animated SVG logo and heading
- User greeting on successful login
- Toast notifications and redirect after login
- Smooth modal transitions
- Easy integration in any layout

---

## Features


## Features

- **Login Form & Accessibility:**
Collects Email and Password with proper labels, screen-reader text, and ARIA roles for inclusive usage.

- **Password Validation:**
Enforces minimum 8 characters, uppercase, lowercase, digit, and special characters.

- **Show/Hide Password:**
Adjacent button toggles password input visibility for better usability.

- **Gravatar Avatars:**
Displays user's avatar using their email via Gravatar, with fallback to default icon.

- **Animated UI:**
Animated SVG logo, gradient headings, and fade-in effects for greeting and feedback. All controlled via CSS (`Login.css`).

- **Post-login Greeting:**
Friendly "Hi, [username]!" message and avatar for 2 seconds after success.

- **Toast Notification:**
Uses `react-hot-toast` to provide instant feedback.

- **Navigation:**
Redirects the user to the main website’s home page after login.

- **Fully Responsive & Accessible:**
Keyboard navigable and screen-reader friendly.

---

## Files Included

- `src/components/Login.tsx`
React component implementing the login modal UI, logic for password validation, Gravatar integration, and login workflow.

- `src/components/Login.css`
CSS styles for the modal overlay, login card, forms, inputs, buttons, greetings, logo, and animations.

---

## Installation and Setup

1. **Install dependencies:**

npm install react-router-dom react-hot-toast blueimp-md5

2. **TypeScript type definitions (for TS projects):**

npm install --save-dev @types/react @types/react-dom


3. **Usage in your app:**

Import and use the `Login` component where you want the login modal to appear.

import Login from './components/Login';

const [showLogin, setShowLogin] = useState(false);

return (
<>
<button onClick={() => setShowLogin(true)}>Login</button>
{showLogin && <Login onClose={() => setShowLogin(false)} />}
</>
);


4. **Add Toast container in your app root:**

import { Toaster } from 'react-hot-toast';

function App() {
return (
<>
{/* Your app content */}
<Toaster />
</>
);
}


5. **Ensure your app uses routing with `BrowserRouter`** for navigation support.

---

## How It Works

- User fills in email and password.
- "Show Password" button toggles visibility for convenience.
- Client-side validation ensures password strength.
- On submit, simulates backend login, then:
- Stores a fake JWT token to localStorage.
- Generates and displays Gravatar avatar and greeting.
- Shows success toast.
- After 2 seconds, modal closes and user is redirected to the homepage.

---

## Accessibility Considerations

- Labels are properly associated with inputs.
- ARIA roles and `aria-describedby` attributes improve screen reader experience.
- Screen reader only descriptions provide useful hints without cluttering visual UI.
- All buttons have accessible names (`aria-label`).
- Keyboard focus and interactions are fully supported.

---
## Customization

- To use your company/users’ actual avatars, swap the Gravatar logic.
- Replace simulated login with real authentication API as needed.
- Use or adapt `Layout.css` for page-wide visual consistency.

---

## License

Open source under the MIT License.

---

## Acknowledgments

- [react-hot-toast](https://react-hot-toast.com) for toast notifications.
- [blueimp-md5](https://github.com/blueimp/JavaScript-MD5) for hashing emails to support Gravatar.
- [Gravatar](https://en.gravatar.com/) for providing unique user avatars based on email.
- [react-router-dom](https://reactrouter.com/) for routing and navigation.

---

Feel free to open an issue or submit a pull request to improve the login experience or add features!

Happy coding! πŸš€
201 changes: 201 additions & 0 deletions src/components/Login.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
.login-root {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
background: rgba(27, 33, 54, 0.18);
z-index: 9999;
}

.login-card {
position: relative;
width: 350px;
background: #ffffff;
border-radius: 18px;
box-shadow: 0 12px 40px rgba(59, 130, 246, 0.12), 0 1.5px 4px #8bbcff1c;
padding: 2.2rem 2rem 2rem;
display: flex;
flex-direction: column;
align-items: stretch;
animation: fadeInScale 0.5s ease forwards;
}

@keyframes fadeInScale {
0% {
opacity: 0;
transform: scale(0.96);
}
100% {
opacity: 1;
transform: scale(1);
}
}

.login-header {
display: flex;
align-items: center;
gap: 0.95rem;
margin-bottom: 1.5rem;
}

.login-logo-attractive {
filter: drop-shadow(0 4px 14px #60a5fa66);
animation: iconFloat 2.5s ease-in-out infinite alternate;
flex-shrink: 0;
}

@keyframes iconFloat {
0% {
transform: translateY(0) scale(1);
}
100% {
transform: translateY(-8px) scale(1.06);
}
}

.login-attractive-title {
font-weight: 900;
font-size: 2.5rem;
background: linear-gradient(90deg, #2563eb 60%, #60a5fa 100%);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;

text-shadow:
2px 2px 16px #2563eb22,
1px 1px 8px #b8d0f78f;
margin: 0;
letter-spacing: 0.04em;
user-select: none;
animation: loginTitlePulse 2.5s 1.2s infinite alternate;
}

@keyframes loginTitlePulse {
0% {
text-shadow: 2px 2px 10px #2563eb22, 1px 1px 8px #b8d0f78f;
}
100% {
text-shadow: 2px 2px 24px #2563eb66, 2px 2px 16px #c7ddffcc;
}
}

.login-form {
display: flex;
flex-direction: column;
gap: 12px;
}

.login-form label {
margin-bottom: 5px;
font-weight: 500;
color: #283366;
}

.login-form input {
padding: 11px 13px;
border-radius: 7px;
border: 1.5px solid #e5e7eb;
background: #f9fafb;
font-size: 1em;
outline-color: #2563eb;
transition: border 0.18s ease;
font-family: inherit;
}

.login-form input:focus {
border: 1.5px solid #2563eb;
background: #fff;
}

.login-error {
color: #ef4444;
padding: 6px 0 0 0;
text-align: center;
font-size: 0.96em;
font-weight: 600;
}

.login-submit-btn {
margin-top: 1rem;
padding: 11px 0;
background: linear-gradient(90deg, #2563eb 60%, #5176fb 100%);
color: #fff;
font-weight: 700;
border-radius: 8px;
border: none;
cursor: pointer;
font-size: 1.07em;
letter-spacing: 0.03em;
box-shadow: 0 3px 16px rgba(37, 99, 235, 0.13);
transition: background 0.16s ease;
user-select: none;
font-family: inherit;
}

.login-submit-btn:hover,
.login-submit-btn:focus {
background: linear-gradient(90deg, #1d4ed8 60%, #2563eb 100%);
outline: none;
}

.login-close {
position: absolute;
top: 13px;
right: 15px;
font-size: 1.6rem;
background: none;
border: none;
color: #6b7280;
font-weight: 400;
cursor: pointer;
padding: 0 7px;
transition: color 0.15s ease;
user-select: none;
}

.login-close:hover,
.login-close:focus {
color: #ef4444;
outline: none;
}

/* Screen reader only helper */
.sr-only {
position: absolute !important;
width: 1px !important;
height: 1px !important;
padding: 0 !important;
margin: -1px !important;
overflow: hidden !important;
clip: rect(0 0 0 0) !important;
white-space: nowrap !important;
border: 0 !important;
}
.login-icon-spin {
animation: spin 1s linear infinite;
vertical-align: middle; /* Align icon with button text */
}

@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}











Loading