diff --git a/web/src/components/RightSidebar.jsx b/web/src/components/RightSidebar.jsx index 459de2c..2cc9834 100644 --- a/web/src/components/RightSidebar.jsx +++ b/web/src/components/RightSidebar.jsx @@ -124,9 +124,6 @@ export default function RightSidebar() { Browse by URL - - Public Highlights - )} diff --git a/web/src/css/login.css b/web/src/css/login.css index 75bfaa8..2a01d5e 100644 --- a/web/src/css/login.css +++ b/web/src/css/login.css @@ -3,57 +3,54 @@ flex-direction: column; align-items: center; justify-content: center; - min-height: 70vh; - padding: 60px 20px; + min-height: 80vh; + padding: 40px 20px; width: 100%; - max-width: 500px; - margin: 0 auto; } -@media (max-width: 600px) { - .login-page { - padding: 40px 16px; - } - - .login-at-logo { - font-size: 4rem; - } - - .login-brand-name { - font-size: 1.25rem; - } +.login-header-group { + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + gap: 24px; + margin-bottom: 48px; + width: auto; +} - .login-brand-icon { - width: 40px; - height: 40px; - font-size: 1.5rem; - } +.login-logo-img { + width: 60px; + height: 60px; + object-fit: contain; + display: block; } -.login-at-logo { - font-size: 5rem; - font-weight: 800; - color: var(--accent); - margin-bottom: 24px; +.login-x { + font-size: 2rem; + color: var(--text-tertiary); + font-weight: 300; line-height: 1; + padding-bottom: 4px; } -.login-logo-img { - width: 80px; - height: 80px; - margin-bottom: 24px; - object-fit: contain; +.login-atproto-icon { + color: #3b83f6 !important; + display: flex; + align-items: center; + justify-content: center; } .login-heading { font-size: 1.5rem; - font-weight: 600; + font-weight: 700; margin-bottom: 32px; display: flex; align-items: center; - gap: 10px; + justify-content: center; + gap: 8px; text-align: center; - line-height: 1.4; + line-height: 1.3; + color: var(--text-primary); } .login-help-btn { @@ -73,28 +70,30 @@ } .login-help-text { - background: var(--bg-elevated); + background: var(--bg-tertiary); border: 1px solid var(--border); border-radius: var(--radius-md); - padding: 16px 20px; + padding: 16px; margin-bottom: 24px; - font-size: 0.95rem; + font-size: 0.9rem; color: var(--text-secondary); - line-height: 1.6; + line-height: 1.5; text-align: center; + width: 100%; } .login-help-text code { - background: var(--bg-tertiary); - padding: 2px 8px; + background: rgba(255, 255, 255, 0.05); + padding: 2px 6px; border-radius: var(--radius-sm); - font-size: 0.9rem; + font-size: 0.85rem; + font-family: var(--font-mono); } .login-form { display: flex; flex-direction: column; - gap: 16px; + gap: 20px; width: 100%; } @@ -105,20 +104,20 @@ .login-input { width: 100%; padding: 14px 16px; - background: var(--bg-elevated); + background: var(--bg-secondary); border: 1px solid var(--border); border-radius: var(--radius-md); color: var(--text-primary); font-size: 1rem; - transition: - border-color 0.15s, - box-shadow 0.15s; + transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1); + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); } .login-input:focus { outline: none; border-color: var(--accent); - box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.15); + box-shadow: 0 0 0 4px var(--accent-subtle); + background: var(--bg-primary); } .login-input::placeholder { @@ -127,15 +126,17 @@ .login-suggestions { position: absolute; - top: calc(100% + 4px); + top: calc(100% + 8px); left: 0; right: 0; - background: var(--bg-card); + background: var(--bg-elevated); border: 1px solid var(--border); border-radius: var(--radius-md); box-shadow: var(--shadow-lg); overflow: hidden; z-index: 100; + max-height: 300px; + overflow-y: auto; } .login-suggestion { @@ -149,16 +150,21 @@ cursor: pointer; text-align: left; transition: background 0.1s; + border-bottom: 1px solid var(--border); +} + +.login-suggestion:last-child { + border-bottom: none; } .login-suggestion:hover, .login-suggestion.selected { - background: var(--bg-elevated); + background: var(--bg-tertiary); } .login-suggestion-avatar { - width: 40px; - height: 40px; + width: 36px; + height: 36px; border-radius: var(--radius-full); background: linear-gradient(135deg, var(--accent), #a855f7); display: flex; @@ -166,7 +172,7 @@ justify-content: center; flex-shrink: 0; overflow: hidden; - font-size: 0.875rem; + font-size: 0.8rem; font-weight: 600; color: white; } @@ -181,10 +187,12 @@ display: flex; flex-direction: column; min-width: 0; + gap: 2px; } .login-suggestion-name { font-weight: 600; + font-size: 0.95rem; color: var(--text-primary); white-space: nowrap; overflow: hidden; @@ -192,7 +200,7 @@ } .login-suggestion-handle { - font-size: 0.875rem; + font-size: 0.85rem; color: var(--text-secondary); white-space: nowrap; overflow: hidden; @@ -202,69 +210,24 @@ .login-error { padding: 12px 16px; background: rgba(239, 68, 68, 0.1); - border: 1px solid rgba(239, 68, 68, 0.3); + border: 1px solid rgba(239, 68, 68, 0.2); border-radius: var(--radius-md); - color: #ef4444; + color: var(--error); font-size: 0.875rem; + text-align: center; } -.login-legal { - font-size: 0.75rem; - color: var(--text-tertiary); - line-height: 1.5; - margin-top: 16px; -} - -.login-brand { - display: flex; - align-items: center; - justify-content: center; - gap: 12px; - margin-bottom: 24px; -} - -.login-brand-icon { - width: 48px; - height: 48px; - background: linear-gradient(135deg, var(--accent), #a855f7); - border-radius: var(--radius-lg); - display: flex; - align-items: center; - justify-content: center; - font-size: 1.75rem; - font-weight: 800; - color: white; -} - -.login-brand-name { - font-size: 1.75rem; - font-weight: 700; -} - -.login-avatar { - width: 72px; - height: 72px; - border-radius: var(--radius-full); - background: linear-gradient(135deg, var(--accent), #a855f7); - display: flex; - align-items: center; - justify-content: center; - margin: 0 auto 16px; - font-weight: 700; - font-size: 1.5rem; - color: white; - overflow: hidden; -} - -.login-avatar img { +.login-submit { + padding: 14px 24px; + font-size: 1rem; + font-weight: 600; width: 100%; - height: 100%; - object-fit: cover; + justify-content: center; } .login-avatar-large { - width: 100px; - height: 100px; + width: 80px; + height: 80px; border-radius: var(--radius-full); background: linear-gradient(135deg, var(--accent), #a855f7); display: flex; @@ -275,6 +238,7 @@ font-size: 2rem; color: white; overflow: hidden; + box-shadow: var(--shadow-md); } .login-avatar-large img { @@ -284,16 +248,11 @@ } .login-welcome { - font-size: 1.5rem; + font-size: 1.25rem; font-weight: 600; margin-bottom: 32px; text-align: center; -} - -.login-welcome-name { - font-size: 1.25rem; - font-weight: 600; - margin-bottom: 24px; + color: var(--text-primary); } .login-actions { @@ -303,15 +262,47 @@ width: 100%; } -.login-btn { - width: 100%; - padding: 14px 24px; - font-size: 1rem; - font-weight: 600; +.morph-container { + display: inline-block; + color: var(--text-primary); + font-weight: 700; + transition: + opacity 0.4s cubic-bezier(0.4, 0, 0.2, 1), + transform 0.4s cubic-bezier(0.4, 0, 0.2, 1), + filter 0.4s cubic-bezier(0.4, 0, 0.2, 1); + white-space: nowrap; + vertical-align: bottom; } -.login-submit { - padding: 18px 32px; - font-size: 1.1rem; - font-weight: 600; +.morph-out { + opacity: 0; + transform: translateY(8px) scale(0.95); + filter: blur(4px); +} + +.morph-in { + opacity: 1; + transform: translateY(0) scale(1); + filter: blur(0); +} + +.login-legal { + margin-top: 24px; + font-size: 0.85rem; + color: var(--text-tertiary); + text-align: center; + line-height: 1.5; +} + +.login-legal a { + color: var(--accent); + text-decoration: underline; + text-decoration-color: var(--accent); + text-underline-offset: 4px; + font-weight: 500; +} + +.login-legal a:hover { + text-decoration-thickness: 2px; + opacity: 0.8; } diff --git a/web/src/pages/Login.jsx b/web/src/pages/Login.jsx index 6f9646e..e8d41e8 100644 --- a/web/src/pages/Login.jsx +++ b/web/src/pages/Login.jsx @@ -2,7 +2,7 @@ import { useState, useEffect, useRef } from "react"; import { Link } from "react-router-dom"; import { useAuth } from "../context/AuthContext"; import { searchActors, startLogin } from "../api/client"; -import { HelpCircle } from "lucide-react"; +import { AtSign } from "lucide-react"; import logo from "../assets/logo.svg"; export default function Login() { @@ -12,7 +12,6 @@ export default function Login() { const [showInviteInput, setShowInviteInput] = useState(false); const [suggestions, setSuggestions] = useState([]); const [showSuggestions, setShowSuggestions] = useState(false); - const [showHelp, setShowHelp] = useState(false); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const [selectedIndex, setSelectedIndex] = useState(-1); @@ -20,6 +19,34 @@ export default function Login() { const inviteRef = useRef(null); const suggestionsRef = useRef(null); + const [providerIndex, setProviderIndex] = useState(0); + const [morphClass, setMorphClass] = useState("morph-in"); + const providers = [ + "AT Protocol", + "Bluesky", + "Blacksky", + "Tangled", + "selfhosted.social", + "Northsky", + "witchcraft.systems", + "topphie.social", + "altq.net", + ]; + + useEffect(() => { + const cycleText = () => { + setMorphClass("morph-out"); + + setTimeout(() => { + setProviderIndex((prev) => (prev + 1) % providers.length); + setMorphClass("morph-in"); + }, 400); + }; + + const interval = setInterval(cycleText, 3000); + return () => clearInterval(interval); + }, [providers.length]); + const isSelectionRef = useRef(false); useEffect(() => { @@ -58,6 +85,35 @@ export default function Login() { return () => document.removeEventListener("mousedown", handleClickOutside); }, []); + if (isAuthenticated) { + return ( +
- The AT Protocol is an open, decentralized network for social apps.
- Your handle looks like name.bsky.social or your own
- domain.
-