storebound/examples/demo-app/web/index.html

85 lines
7.4 KiB
HTML

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
<title>Tidy Lists (storebound demo)</title>
<!--
A tiny fictional list app, made only to show storebound's app screenshot style. Sample data only, no network.
Switches for store captures: ?screen=lists|list|share|account&lang=en|tr (window.app.ready turns true when drawn).
-->
<style>
:root { --bg: #f6f7fb; --card: #ffffff; --ink: #111827; --muted: #6b7280; --line: #e5e7eb; --accent: #4f46e5; --ok: #059669; }
* { box-sizing: border-box; margin: 0; padding: 0; }
html, body { height: 100%; background: var(--bg); color: var(--ink); font: 16px/1.4 -apple-system, 'Segoe UI', Roboto, Inter, sans-serif; }
header { padding: 18px 20px 10px; background: var(--bg); }
header small { color: var(--muted); font-size: 13px; font-weight: 600; letter-spacing: .02em; }
h1 { font-size: 30px; font-weight: 750; letter-spacing: -.02em; margin-top: 2px; }
main { padding: 6px 16px 90px; display: grid; gap: 12px; }
.card { background: var(--card); border-radius: 18px; padding: 14px 16px; box-shadow: 0 1px 2px rgba(17,24,39,.06); }
.row { display: flex; align-items: center; gap: 12px; }
.dot { width: 38px; height: 38px; border-radius: 12px; display: grid; place-items: center; color: #fff; font-weight: 700; flex: none; }
.grow { flex: 1; min-width: 0; }
.t { font-weight: 650; }
.m { color: var(--muted); font-size: 13px; }
.bar { height: 6px; border-radius: 6px; background: var(--line); margin-top: 8px; overflow: hidden; }
.bar i { display: block; height: 100%; background: var(--accent); border-radius: 6px; }
.check { width: 24px; height: 24px; border-radius: 50%; border: 2px solid #c7cbd4; flex: none; display: grid; place-items: center; }
.check.on { background: var(--ok); border-color: var(--ok); }
.check.on::after { content: ""; width: 10px; height: 6px; border: 2.5px solid #fff; border-top: 0; border-right: 0; transform: rotate(-45deg) translate(1px, -1px); }
.done .t { color: var(--muted); text-decoration: line-through; }
.item { padding: 13px 0; border-bottom: 1px solid var(--line); }
.item:last-child { border-bottom: 0; }
.av { width: 36px; height: 36px; border-radius: 50%; display: grid; place-items: center; font-weight: 700; color: #fff; flex: none; }
.pill { font-size: 12px; font-weight: 650; padding: 4px 10px; border-radius: 999px; background: #eef2ff; color: var(--accent); }
.btn { display: block; text-align: center; padding: 14px; border-radius: 14px; font-weight: 650; background: var(--accent); color: #fff; }
.danger { color: #dc2626; font-weight: 650; }
nav { position: fixed; left: 0; right: 0; bottom: 0; display: flex; justify-content: space-around; padding: 10px 0 26px; background: rgba(255,255,255,.94); border-top: 1px solid var(--line); }
nav span { font-size: 11px; color: var(--muted); font-weight: 600; display: grid; justify-items: center; gap: 4px; }
nav span b { width: 22px; height: 22px; border-radius: 7px; background: #d1d5db; }
nav span.on { color: var(--accent); } nav span.on b { background: var(--accent); }
.fab { position: fixed; right: 20px; bottom: 96px; width: 58px; height: 58px; border-radius: 18px; background: var(--accent); color: #fff; font-size: 32px; display: grid; place-items: center; box-shadow: 0 8px 20px rgba(79,70,229,.35); }
</style>
</head>
<body>
<div id="app"></div>
<script>
const q = new URLSearchParams(location.search);
const lang = q.get('lang') === 'tr' ? 'tr' : 'en';
const screen = q.get('screen') || 'lists';
document.documentElement.lang = lang;
const T = {
en: { today: 'Thursday, 9 October', lists: 'My lists', groceries: 'Groceries', trip: 'Weekend trip', home: 'Home projects', reading: 'Reading',
items: n => `${n} items`, shared: 'Shared', milk: 'Oat milk', bread: 'Sourdough bread', apples: 'Apples', coffee: 'Coffee beans', pasta: 'Pasta', basil: 'Fresh basil',
left: '3 of 6 left', share: 'Share list', people: 'People on this list', owner: 'Owner', canEdit: 'Can edit', invite: 'Invite by link',
account: 'Account', signedIn: 'Signed in as', sync: 'Sync across devices', on: 'On', export: 'Export my data', privacy: 'Privacy policy', terms: 'Terms of use', del: 'Delete account',
tabs: ['Lists', 'Today', 'Shared', 'Settings'] },
tr: { today: '9 Ekim Perşembe', lists: 'Listelerim', groceries: 'Market', trip: 'Hafta sonu gezisi', home: 'Ev işleri', reading: 'Okuma',
items: n => `${n} öğe`, shared: 'Paylaşılan', milk: 'Yulaf sütü', bread: 'Ekşi maya ekmek', apples: 'Elma', coffee: 'Kahve çekirdeği', pasta: 'Makarna', basil: 'Taze fesleğen',
left: '6 öğeden 3 kaldı', share: 'Listeyi paylaş', people: 'Bu listedeki kişiler', owner: 'Sahip', canEdit: 'Düzenleyebilir', invite: 'Bağlantıyla davet et',
account: 'Hesap', signedIn: 'Giriş yapan', sync: 'Cihazlar arası eşitleme', on: 'Açık', export: 'Verilerimi dışa aktar', privacy: 'Gizlilik politikası', terms: 'Kullanım koşulları', del: 'Hesabı sil',
tabs: ['Listeler', 'Bugün', 'Paylaşılan', 'Ayarlar'] },
}[lang];
const nav = on => `<nav>${T.tabs.map((t, i) => `<span class="${i === on ? 'on' : ''}"><b></b>${t}</span>`).join('')}</nav>`;
const list = (c, name, n, pct, extra = '') => `<div class="card"><div class="row"><div class="dot" style="background:${c}">${name[0]}</div><div class="grow"><div class="t">${name}</div><div class="m">${T.items(n)}${extra}</div><div class="bar"><i style="width:${pct}%"></i></div></div></div></div>`;
const item = (on, t, m = '') => `<div class="item row ${on ? 'done' : ''}"><div class="check ${on ? 'on' : ''}"></div><div class="grow"><div class="t">${t}</div>${m ? `<div class="m">${m}</div>` : ''}</div></div>`;
const S = {
lists: () => `<header><small>${T.today}</small><h1>${T.lists}</h1></header><main>
${list('#4f46e5', T.groceries, 6, 50, ` · <span class="pill">${T.shared}</span>`)}${list('#0ea5e9', T.trip, 9, 20)}${list('#059669', T.home, 5, 80)}${list('#f59e0b', T.reading, 12, 35)}
</main><div class="fab">+</div>${nav(0)}`,
list: () => `<header><small>${T.left}</small><h1>${T.groceries}</h1></header><main><div class="card">
${item(true, T.milk)}${item(true, T.bread)}${item(false, T.apples, '1 kg')}${item(true, T.coffee)}${item(false, T.pasta)}${item(false, T.basil)}
</div></main>${nav(0)}`,
share: () => `<header><small>${T.groceries}</small><h1>${T.share}</h1></header><main><div class="card"><div class="m" style="margin-bottom:6px">${T.people}</div>
${[['#4f46e5', 'Alex Kim', T.owner], ['#db2777', 'Sam Rivera', T.canEdit], ['#0d9488', 'Deniz Ay', T.canEdit]].map(([c, n, r]) => `<div class="item row"><div class="av" style="background:${c}">${n[0]}</div><div class="grow"><div class="t">${n}</div><div class="m">${r}</div></div></div>`).join('')}
</div><div class="btn">${T.invite}</div></main>${nav(2)}`,
account: () => `<header><small>${T.signedIn} demo@example.com</small><h1>${T.account}</h1></header><main><div class="card">
<div class="item row"><div class="grow t">${T.sync}</div><span class="pill">${T.on}</span></div><div class="item row"><div class="grow t">${T.export}</div></div>
<div class="item row"><div class="grow t">${T.privacy}</div></div><div class="item row"><div class="grow t">${T.terms}</div></div></div>
<div class="card"><div class="danger">${T.del}</div></div></main>${nav(3)}`,
};
document.getElementById('app').innerHTML = (S[screen] || S.lists)();
window.app = { ready: true };
</script>
</body>
</html>