Files
OnBudget/design/index.html
T
2026-05-27 09:19:19 +03:00

173 lines
6.4 KiB
HTML

<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>Главный экран — Бюджет · вайрфреймы</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&family=Caveat:wght@500;600&display=swap" rel="stylesheet" />
<style>
:root {
/* Light tokens */
--paper: #f6f4ef;
--paper-2: #efece5;
--card-soft: #edeae3;
--ink: #1c1c1a;
--ink-2: #6b6b66;
--line: #d8d5cc;
--line-2: #b8b5ac;
--accent: #4a8a82;
--accent-soft:#dde9e6;
--pos: #6f8c69;
--neg: #b3675a;
--canvas-bg: #efece5;
}
[data-theme="dark"] {
--paper: #19191a;
--paper-2: #232325;
--card-soft: #232325;
--ink: #ece9e2;
--ink-2: #8d8a83;
--line: #2e2d2a;
--line-2: #4a4845;
--accent: #76b3a9;
--accent-soft:#23332f;
--pos: #92b58a;
--neg: #d18d7e;
--canvas-bg: #111112;
}
html, body { margin: 0; padding: 0; background: var(--canvas-bg); }
body {
font-family: 'DM Sans', system-ui, sans-serif;
color: var(--ink);
-webkit-font-smoothing: antialiased;
}
* { box-sizing: border-box; }
/* Wireframe root sets dark/light tokens for all frames */
.wf-root { color: var(--ink); }
/* Remove webkit scrollbars on hscrolls */
.wf-root *::-webkit-scrollbar { display: none; }
</style>
<!-- React + Babel -->
<script src="https://unpkg.com/react@18.3.1/umd/react.development.js" integrity="sha384-hD6/rw4ppMLGNu3tX5cjIb+uRZ7UkRJ6BPkLpg4hAu/6onKUg4lLsHAs9EBPT82L" crossorigin="anonymous"></script>
<script src="https://unpkg.com/react-dom@18.3.1/umd/react-dom.development.js" integrity="sha384-u6aeetuaXnQ38mYT8rp6sbXaQe3NL9t+IBXmnYxwkUI2Hw4bsp2Wvmx4yRQF1uAm" crossorigin="anonymous"></script>
<script src="https://unpkg.com/@babel/standalone@7.29.0/babel.min.js" integrity="sha384-m08KidiNqLdpJqLq95G/LEi8Qvjl/xUYll3QILypMoQ65QorJ9Lvtp2RXYGBFj1y" crossorigin="anonymous"></script>
<script type="text/babel" src="design-canvas.jsx"></script>
<script type="text/babel" src="android-frame.jsx"></script>
<script type="text/babel" src="tweaks-panel.jsx"></script>
<script type="text/babel" src="common.jsx"></script>
<script type="text/babel" src="variants.jsx"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
"theme": "dark"
}/*EDITMODE-END*/;
// Custom Android frame that uses our CSS-var palette (so dark/light flows through)
function PhoneShell({ children }) {
return (
<div style={{
width: 412, height: 892, borderRadius: 18, overflow: 'hidden',
background: 'var(--paper)',
border: '8px solid var(--line-2)',
boxShadow: '0 24px 60px rgba(0,0,0,0.18)',
display: 'flex', flexDirection: 'column', boxSizing: 'border-box',
}}>
{/* Status bar */}
<div style={{
height: 32, padding: '0 16px', display: 'flex',
alignItems: 'center', justifyContent: 'space-between',
position: 'relative', fontSize: 12, color: 'var(--ink)',
fontFamily: 'DM Sans, sans-serif',
}}>
<span style={{ fontWeight: 500 }}>9:30</span>
<div style={{
position: 'absolute', left: '50%', top: 6, transform: 'translateX(-50%)',
width: 18, height: 18, borderRadius: '50%', background: 'var(--ink)',
opacity: 0.85,
}} />
<div style={{ display: 'flex', gap: 4, alignItems: 'center', opacity: 0.85 }}>
<svg width="14" height="14" viewBox="0 0 16 16"><path d="M8 13.3L.67 5.97a10.37 10.37 0 0114.66 0L8 13.3z" fill="currentColor"/></svg>
<svg width="14" height="14" viewBox="0 0 16 16"><path d="M14.67 14.67V1.33L1.33 14.67h13.34z" fill="currentColor"/></svg>
<svg width="16" height="14" viewBox="0 0 16 16"><rect x="3.75" y="2" width="8.5" height="13" rx="1.5" fill="currentColor"/><rect x="5.5" y="0.9" width="5" height="2" rx="0.5" fill="currentColor"/></svg>
</div>
</div>
{/* Content */}
<div style={{ flex: 1, overflow: 'auto', position: 'relative' }}>
{children}
</div>
{/* Bottom nav */}
<BottomNav active={0} />
{/* Gesture pill */}
<div style={{ height: 18, display: 'flex', alignItems: 'center', justifyContent: 'center', background: 'var(--paper)' }}>
<div style={{ width: 96, height: 4, borderRadius: 2, background: 'var(--ink)', opacity: 0.35 }} />
</div>
</div>
);
}
// Variation meta
const VARIANTS = [
{ n: 1, title: 'Segmented account tabs',
Component: V1,
axes: ['Счёт: горизонтальные таб-пиллы', 'KPI: баланс + доходырасходы', 'Фильтр: bottom-sheet триггер', 'Список: группировка по дням'] },
];
function Stage() {
const [tweaks, setTweak] = useTweaks(TWEAK_DEFAULTS);
React.useEffect(() => {
document.documentElement.setAttribute('data-theme', tweaks.theme);
}, [tweaks.theme]);
return (
<div className="wf-root" data-screen-label="Главный экран">
<DesignCanvas>
<DCSection id="phones" title="Главный экран">
{VARIANTS.map(v => (
<DCArtboard key={v.n}
id={`v${v.n}`}
label={`0${v.n} · ${v.title}`}
width={412} height={892}>
<PhoneShell><v.Component /></PhoneShell>
</DCArtboard>
))}
</DCSection>
</DesignCanvas>
<TweaksPanel>
<TweakSection label="Тема">
<TweakRadio
label="Режим"
value={tweaks.theme}
onChange={v => setTweak('theme', v)}
options={[
{ value: 'light', label: 'Светлая' },
{ value: 'dark', label: 'Тёмная' },
]}
/>
</TweakSection>
</TweaksPanel>
</div>
);
}
ReactDOM.createRoot(document.getElementById('root')).render(<Stage />);
</script>
</body>
</html>