fixed modal
This commit is contained in:
@@ -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>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user