fixed modal

This commit is contained in:
Christopher
2026-01-28 13:17:36 -08:00
parent aebc3a81fc
commit 9cd23081ed
+211 -188
View File
@@ -59,209 +59,232 @@ export function IdentityUnlockPrompt({ onUnlock, onCancel }: IdentityUnlockPromp
}; };
return ( return (
<div <>
style={{ <style jsx>{`
position: 'fixed', @keyframes slideUp {
top: 0, from {
left: 0, transform: translateY(100%);
right: 0,
bottom: 0,
background: 'rgba(0, 0, 0, 0.8)',
display: 'flex',
alignItems: 'flex-end',
justifyContent: 'center',
zIndex: 99999,
padding: 0
}}
onClick={handleCancel}
>
<div
className="identity-unlock-sheet"
style={{
width: '100%',
maxWidth: '100%',
background: 'var(--background-secondary)',
borderTopLeftRadius: '20px',
borderTopRightRadius: '20px',
padding: '24px',
paddingBottom: 'calc(24px + env(safe-area-inset-bottom))',
boxShadow: '0 -4px 20px rgba(0, 0, 0, 0.5)',
animation: 'slideUp 0.3s ease-out'
}}
onClick={(e) => e.stopPropagation()}
>
<style jsx>{`
@keyframes slideUp {
from {
transform: translateY(100%);
}
to {
transform: translateY(0);
}
} }
`}</style> to {
transform: translateY(0);
}
}
{/* Drag indicator */} .identity-unlock-container {
<div style={{ position: fixed;
width: '40px', top: 0;
height: '4px', left: 0;
background: 'var(--border)', right: 0;
borderRadius: '2px', bottom: 0;
margin: '0 auto 20px' background: rgba(0, 0, 0, 0.8);
}} /> display: flex;
align-items: center;
justify-content: center;
z-index: 99999;
padding: 20px;
}
{/* Header */} .identity-unlock-sheet {
<div style={{ textAlign: 'center', marginBottom: '20px' }}> width: 100%;
<div style={{ max-width: 400px;
width: '56px', background: var(--background-secondary);
height: '56px', border-radius: 12px;
borderRadius: '50%', padding: 24px;
background: 'rgba(255, 255, 255, 0.1)', box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5);
display: 'flex', }
alignItems: 'center',
justifyContent: 'center',
margin: '0 auto 16px'
}}>
<Lock size={28} style={{ color: 'var(--accent)' }} />
</div>
<h2 style={{ fontSize: '22px', fontWeight: 600, margin: '0 0 8px 0' }}>
Identity Required
</h2>
<p style={{ color: 'var(--foreground-secondary)', margin: 0, lineHeight: 1.5, fontSize: '15px' }}>
Enter your password to unlock your identity
</p>
</div>
{/* Form */} .drag-indicator {
<form onSubmit={handleSubmit}> display: none;
<div style={{ marginBottom: '16px' }}> }
<label
htmlFor="unlock-password"
style={{
display: 'block',
marginBottom: '8px',
fontSize: '14px',
fontWeight: 500,
color: 'var(--foreground)'
}}
>
Password
</label>
<input
id="unlock-password"
type="password"
value={password}
onChange={(e) => {
setPassword(e.target.value);
setError(null);
}}
disabled={isUnlocking}
placeholder="Enter your password"
autoFocus
style={{
width: '100%',
padding: '14px 16px',
borderRadius: '12px',
border: error ? '2px solid var(--error)' : '2px solid var(--border)',
background: 'var(--background)',
color: 'var(--foreground)',
fontSize: '16px',
outline: 'none',
transition: 'border-color 0.2s'
}}
onFocus={(e) => {
if (!error) {
e.target.style.borderColor = 'var(--accent)';
}
}}
onBlur={(e) => {
if (!error) {
e.target.style.borderColor = 'var(--border)';
}
}}
/>
</div>
{/* Error Message */} @media (max-width: 768px) {
{error && ( .identity-unlock-container {
align-items: flex-end;
padding: 0;
}
.identity-unlock-sheet {
max-width: 100%;
border-radius: 0;
border-top-left-radius: 20px;
border-top-right-radius: 20px;
padding: 24px;
padding-bottom: calc(24px + env(safe-area-inset-bottom));
animation: slideUp 0.3s ease-out;
}
.drag-indicator {
display: block;
width: 40px;
height: 4px;
background: var(--border);
border-radius: 2px;
margin: 0 auto 20px;
}
}
`}</style>
<div
className="identity-unlock-container"
onClick={handleCancel}
>
<div
className="identity-unlock-sheet"
onClick={(e) => e.stopPropagation()}
>
{/* Drag indicator - only visible on mobile */}
<div className="drag-indicator" />
{/* Header */}
<div style={{ display: 'flex', alignItems: 'center', gap: '12px', marginBottom: '16px' }}>
<div style={{ <div style={{
width: '48px',
height: '48px',
borderRadius: '50%',
background: 'rgba(255, 255, 255, 0.1)',
display: 'flex', display: 'flex',
alignItems: 'center', alignItems: 'center',
gap: '8px', justifyContent: 'center'
padding: '12px 14px',
borderRadius: '10px',
background: 'rgba(239, 68, 68, 0.1)',
color: 'var(--error)',
fontSize: '14px',
marginBottom: '16px'
}}> }}>
<AlertCircle size={18} /> <Lock size={24} style={{ color: 'var(--accent)' }} />
<span>{error}</span>
</div> </div>
)} <h2 style={{ fontSize: '20px', fontWeight: 600, margin: 0 }}>
Identity Required
</h2>
</div>
{/* Buttons */} {/* Description */}
<div style={{ display: 'flex', flexDirection: 'column', gap: '10px', marginTop: '20px' }}> <p style={{ color: 'var(--foreground-secondary)', marginBottom: '20px', lineHeight: 1.5, fontSize: '15px' }}>
<button Enter your password to unlock your identity
type="submit" </p>
disabled={isUnlocking || !password.trim()}
className="btn btn-primary" {/* Form */}
style={{ <form onSubmit={handleSubmit}>
width: '100%', <div style={{ marginBottom: '16px' }}>
<label
htmlFor="unlock-password"
style={{
display: 'block',
marginBottom: '8px',
fontSize: '14px',
fontWeight: 500,
color: 'var(--foreground)'
}}
>
Password
</label>
<input
id="unlock-password"
type="password"
value={password}
onChange={(e) => {
setPassword(e.target.value);
setError(null);
}}
disabled={isUnlocking}
placeholder="Enter your password"
autoFocus
style={{
width: '100%',
padding: '12px 14px',
borderRadius: '8px',
border: error ? '2px solid var(--error)' : '1px solid var(--border)',
background: 'var(--background)',
color: 'var(--foreground)',
fontSize: '15px',
outline: 'none',
transition: 'border-color 0.2s'
}}
onFocus={(e) => {
if (!error) {
e.target.style.borderColor = 'var(--accent)';
}
}}
onBlur={(e) => {
if (!error) {
e.target.style.borderColor = 'var(--border)';
}
}}
/>
</div>
{/* Error Message */}
{error && (
<div style={{
display: 'flex', display: 'flex',
alignItems: 'center', alignItems: 'center',
justifyContent: 'center',
gap: '8px', gap: '8px',
minHeight: '52px', padding: '12px 14px',
padding: '14px 20px', borderRadius: '8px',
fontSize: '16px', background: 'rgba(239, 68, 68, 0.1)',
fontWeight: 600, color: 'var(--error)',
borderRadius: '12px' fontSize: '14px',
}} marginBottom: '16px'
> }}>
{isUnlocking ? ( <AlertCircle size={18} />
<> <span>{error}</span>
<Loader2 size={20} className="animate-spin" /> </div>
<span>Unlocking...</span> )}
</>
) : (
<>
<Lock size={18} />
<span>Unlock Identity</span>
</>
)}
</button>
<button
type="button"
onClick={handleCancel}
disabled={isUnlocking}
className="btn btn-ghost"
style={{
width: '100%',
minHeight: '52px',
padding: '14px 20px',
fontSize: '16px',
fontWeight: 500,
borderRadius: '12px'
}}
>
Cancel
</button>
</div>
</form>
{/* Info Note */} {/* Buttons */}
<p style={{ <div style={{ display: 'flex', gap: '12px', marginTop: '20px' }}>
fontSize: '13px', <button
color: 'var(--foreground-tertiary)', type="button"
marginTop: '20px', onClick={handleCancel}
marginBottom: 0, disabled={isUnlocking}
lineHeight: 1.5, className="btn btn-ghost"
textAlign: 'center' style={{
}}> flex: 1,
Your password never leaves this device minHeight: '44px',
</p> padding: '10px 16px',
fontSize: '15px'
}}
>
Cancel
</button>
<button
type="submit"
disabled={isUnlocking || !password.trim()}
className="btn btn-primary"
style={{
flex: 1,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
gap: '8px',
minHeight: '44px',
padding: '10px 16px',
fontSize: '15px'
}}
>
{isUnlocking ? (
<>
<Loader2 size={18} className="animate-spin" />
<span>Unlocking...</span>
</>
) : (
<>
<Lock size={16} />
<span>Unlock</span>
</>
)}
</button>
</div>
</form>
{/* Info Note */}
<p style={{
fontSize: '13px',
color: 'var(--foreground-tertiary)',
marginTop: '16px',
marginBottom: 0,
lineHeight: 1.5,
textAlign: 'center'
}}>
Your password never leaves this device
</p>
</div>
</div> </div>
</div> </>
); );
} }