Skip to content
Merged
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
12 changes: 10 additions & 2 deletions ui/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,16 @@ const DEMO = (() => {
if (typeof window === 'undefined') return ENV.VITE_DEMO === '1'
try {
const q = new URLSearchParams(window.location.search)
if (q.get('demo') === '1') { localStorage.setItem('konclave.demo', '1'); return true }
if (q.get('demo') === '0') { localStorage.removeItem('konclave.demo'); return false }
const flag = q.get('demo')
if (flag === '1' || flag === '0') {
if (flag === '1') localStorage.setItem('konclave.demo', '1')
else localStorage.removeItem('konclave.demo')
// Strip `?demo` from the address bar so the path stays clean; the mode persists via localStorage.
q.delete('demo')
const qs = q.toString()
window.history.replaceState(null, '', window.location.pathname + (qs ? `?${qs}` : '') + window.location.hash)
return flag === '1'
}
if (localStorage.getItem('konclave.demo') === '1') return true
} catch { /* storage unavailable — fall through to the build flag */ }
return ENV.VITE_DEMO === '1'
Expand Down
9 changes: 4 additions & 5 deletions ui/src/components.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,19 @@ import { Link } from 'react-router-dom'
import { useReveal } from './reveal'
import { useI18n, useT } from './i18n'
import { IS_DEMO } from './api'
import { helperConfigured } from './helper'

/** A thin, always-visible strip in demo mode (runtime `?demo=1` or the VITE_DEMO fallback) so a
* visitor never mistakes the sample data for a real vault. Offers "Exit demo" (`?demo=0`) ONLY when
* a real mode exists to exit to (a helper is configured) — a pure demo deploy has nowhere to go, so
* the exit would land on an empty backend. Renders nothing outside demo mode. */
* visitor never mistakes the sample data for a real vault. Always offers a way back to the landing
* (which leaves demo mode via `?demo=0`), from where a visitor re-enters the demo or the real vault.
* Renders nothing outside demo mode. */
export function DemoBanner() {
const t = useT()
if (!IS_DEMO) return null
return (
<div className="demo-banner" role="note">
<span className="demo-banner-tag">DEMO</span>
{t('demo.bannerNote')}
{helperConfigured() && <a className="demo-banner-exit" href="?demo=0">{t('demo.bannerExit')}</a>}
<a className="demo-banner-exit" href="?demo=0">{t('demo.bannerExit')}</a>
</div>
)
}
Expand Down
2 changes: 1 addition & 1 deletion ui/src/i18n/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ export const en: Record<string, string> = {
'demo.live': 'Live demo',
'demo.note': 'This is the cryptography itself, running live, not the everyday vault screens.',
'demo.bannerNote': 'Demonstration with sample data. No real funds, no real transactions.',
'demo.bannerExit': 'Exit demo',
'demo.bannerExit': '← Back to landing',
'settings.eyebrow': 'SETTINGS',
'settings.title': 'Settings',
'settings.vault': 'Vault',
Expand Down
2 changes: 1 addition & 1 deletion ui/src/i18n/pt-BR.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ export const ptBR: Record<string, string> = {
'demo.live': 'Demonstração ao vivo',
'demo.note': 'Isto é a própria criptografia, rodando ao vivo, não as telas do dia a dia do cofre.',
'demo.bannerNote': 'Demonstração com dados de exemplo. Nenhum fundo real, nenhuma transação de verdade.',
'demo.bannerExit': 'Sair da demo',
'demo.bannerExit': '← Voltar à landing',
'settings.eyebrow': 'AJUSTES',
'settings.title': 'Ajustes',
'settings.vault': 'Cofre',
Expand Down
Loading