feat: allow dismissing sovereign flow to use traditional auth form

- "Go back" replaced with red italic "fuck you, I wanna be lame"
- After dismissing, sovereign trap no longer intercepts clicks
- Form fields become real inputs (email/password) for actual use
- sovereignDismissed state resets when modal reopens or closes

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Dorian
2026-02-13 23:05:24 +00:00
parent d8b8237300
commit 0e2f2b0a73
2 changed files with 29 additions and 12 deletions

View File

@@ -20,7 +20,7 @@ services:
context: . context: .
dockerfile: Dockerfile dockerfile: Dockerfile
args: args:
CACHEBUST: "31" CACHEBUST: "32"
VITE_USE_MOCK_DATA: "false" VITE_USE_MOCK_DATA: "false"
VITE_CONTENT_ORIGIN: ${FRONTEND_URL} VITE_CONTENT_ORIGIN: ${FRONTEND_URL}
VITE_INDEEHUB_API_URL: /api VITE_INDEEHUB_API_URL: /api

View File

@@ -24,23 +24,35 @@
{{ errorMessage }} {{ errorMessage }}
</div> </div>
<!-- Cognito Auth Form clicking anywhere triggers the sovereign flow --> <!-- Auth Form first click triggers sovereign flow; after dismiss, form is functional -->
<div class="space-y-4 sovereign-trap" @click.capture="triggerSovereignFlow"> <form class="space-y-4" :class="{ 'sovereign-trap': !sovereignDismissed }" @click.capture="triggerSovereignFlow" @submit.prevent>
<div class="form-group"> <div class="form-group">
<label class="block text-white/80 text-sm font-medium mb-2">Email</label> <label class="block text-white/80 text-sm font-medium mb-2">Email</label>
<div class="auth-input pointer-events-none select-none text-white/30">you@example.com</div> <input
v-if="sovereignDismissed"
type="email"
class="auth-input"
placeholder="you@example.com"
/>
<div v-else class="auth-input pointer-events-none select-none text-white/30">you@example.com</div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="block text-white/80 text-sm font-medium mb-2">Password</label> <label class="block text-white/80 text-sm font-medium mb-2">Password</label>
<div class="auth-input pointer-events-none select-none text-white/30">{{ mode === 'register' ? 'Create a password' : 'Enter your password' }}</div> <input
v-if="sovereignDismissed"
type="password"
class="auth-input"
:placeholder="mode === 'register' ? 'Create a password' : 'Enter your password'"
/>
<div v-else class="auth-input pointer-events-none select-none text-white/30">{{ mode === 'register' ? 'Create a password' : 'Enter your password' }}</div>
</div> </div>
<div v-if="mode === 'login'" class="text-right"> <div v-if="mode === 'login'" class="text-right">
<span class="text-sm text-white/60">Forgot password?</span> <span class="text-sm text-white/60">Forgot password?</span>
</div> </div>
<button type="button" class="hero-play-button w-full flex items-center justify-center"> <button type="submit" class="hero-play-button w-full flex items-center justify-center">
<span>{{ mode === 'register' ? 'Create Account' : 'Sign In' }}</span> <span>{{ mode === 'register' ? 'Create Account' : 'Sign In' }}</span>
</button> </button>
</div> </form>
<!-- Divider --> <!-- Divider -->
<div class="relative my-6"> <div class="relative my-6">
@@ -143,10 +155,10 @@
{{ isLoading ? 'Generating...' : 'Generate Sovereign Identity' }} {{ isLoading ? 'Generating...' : 'Generate Sovereign Identity' }}
</button> </button>
<button <button
@click="sovereignPhase = 'normal'" @click="sovereignDismissed = true; sovereignPhase = 'normal'"
class="text-sm text-white/30 hover:text-white/50 transition-colors" class="text-sm text-red-500/70 hover:text-red-400 transition-colors italic"
> >
Go back fuck you, I wanna be lame
</button> </button>
</div> </div>
</div> </div>
@@ -222,6 +234,7 @@ const amberPhase = ref<'idle' | 'waiting'>('idle')
type SovereignPhase = 'normal' | 'nah' | 'own-privacy' | 'generated' type SovereignPhase = 'normal' | 'nah' | 'own-privacy' | 'generated'
const sovereignPhase = ref<SovereignPhase>('normal') const sovereignPhase = ref<SovereignPhase>('normal')
const sovereignGenerating = ref(false) const sovereignGenerating = ref(false)
const sovereignDismissed = ref(false)
// Store the generated keypair so it can be downloaded // Store the generated keypair so it can be downloaded
const generatedKeys = ref<{ nsec: string; npub: string; hexSecret: string; hexPub: string } | null>(null) const generatedKeys = ref<{ nsec: string; npub: string; hexSecret: string; hexPub: string } | null>(null)
@@ -230,6 +243,7 @@ const generatedKeys = ref<{ nsec: string; npub: string; hexSecret: string; hexPu
watch(() => props.isOpen, (open) => { watch(() => props.isOpen, (open) => {
if (open) { if (open) {
sovereignPhase.value = 'normal' sovereignPhase.value = 'normal'
sovereignDismissed.value = false
generatedKeys.value = null generatedKeys.value = null
errorMessage.value = null errorMessage.value = null
amberPhase.value = 'idle' amberPhase.value = 'idle'
@@ -241,6 +255,7 @@ function closeModal() {
errorMessage.value = null errorMessage.value = null
amberPhase.value = 'idle' amberPhase.value = 'idle'
sovereignPhase.value = 'normal' sovereignPhase.value = 'normal'
sovereignDismissed.value = false
generatedKeys.value = null generatedKeys.value = null
} }
@@ -251,14 +266,16 @@ function toggleMode() {
/** /**
* Intercept clicks on the legacy auth form. * Intercept clicks on the legacy auth form.
* Triggers the "NAH!" → sovereign identity animation. * Triggers the "STOP!" → sovereign identity animation.
* Skipped if the user already dismissed the sovereign flow.
*/ */
function triggerSovereignFlow(e: Event) { function triggerSovereignFlow(e: Event) {
if (sovereignDismissed.value) return
e.preventDefault() e.preventDefault()
e.stopPropagation() e.stopPropagation()
sovereignPhase.value = 'nah' sovereignPhase.value = 'nah'
// After "NAH!" animation plays, transition to the privacy message // After "STOP!" animation plays, transition to the privacy message
setTimeout(() => { setTimeout(() => {
sovereignPhase.value = 'own-privacy' sovereignPhase.value = 'own-privacy'
}, 1400) }, 1400)