260 lines
14 KiB
HTML
260 lines
14 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>在线演示 — MetonaToast</title>
|
||
<style>
|
||
:root {
|
||
--bg: #0b1121; --surface: #151d33; --border: #1e2d4d;
|
||
--text: #e2e8f0; --muted: #64748b; --accent: #6366f1; --accent2: #818cf8;
|
||
--radius: 14px;
|
||
}
|
||
* { margin:0; padding:0; box-sizing:border-box; }
|
||
body { font-family:-apple-system,BlinkMacSystemFont,'Segoe UI','PingFang SC','Microsoft YaHei',sans-serif; background:var(--bg); color:var(--text); line-height:1.6; min-height:100vh; }
|
||
a { color:var(--accent2); text-decoration:none; }
|
||
code { background:rgba(99,102,241,0.12); color:#a5b4fc; padding:1px 6px; border-radius:4px; font-size:0.85em; }
|
||
.nav { position:sticky; top:0; z-index:100; background:rgba(11,17,33,0.88); backdrop-filter:blur(14px); border-bottom:1px solid var(--border); }
|
||
.nav-inner { max-width:1300px; margin:0 auto; display:flex; align-items:center; justify-content:space-between; padding:0 20px; height:56px; }
|
||
.nav-logo { font-size:18px; font-weight:700; background:linear-gradient(135deg,#818cf8,#c084fc,#f472b6); -webkit-background-clip:text; -webkit-text-fill-color:transparent; background-clip:text; }
|
||
.nav-links { display:flex; gap:20px; }
|
||
.nav-links a { color:var(--muted); font-size:13px; font-weight:500; transition:.2s; }
|
||
.nav-links a:hover { color:var(--accent2); }
|
||
.hero { text-align:center; padding:50px 20px 40px; border-bottom:1px solid var(--border); background:radial-gradient(ellipse at 50% 0%,rgba(99,102,241,0.12) 0%,transparent 50%); }
|
||
.hero h1 { font-size:36px; font-weight:800; }
|
||
.hero h1 span { background:linear-gradient(135deg,#818cf8,#c084fc,#f472b6); -webkit-background-clip:text; -webkit-text-fill-color:transparent; background-clip:text; }
|
||
.hero p { color:var(--muted); font-size:14px; margin-top:6px; }
|
||
|
||
.container { max-width:1300px; margin:0 auto; padding:32px 20px; display:grid; grid-template-columns:repeat(auto-fill,minmax(380px,1fr)); gap:20px; }
|
||
.card { background:var(--surface); border:1px solid var(--border); border-radius:var(--radius); padding:22px; }
|
||
.card h2 { font-size:16px; margin-bottom:4px; }
|
||
.card > p { color:var(--muted); font-size:12px; margin-bottom:14px; }
|
||
.btn-row { display:flex; flex-wrap:wrap; gap:7px; }
|
||
.btn { padding:8px 15px; border:none; border-radius:7px; font-size:12px; font-weight:500; cursor:pointer; transition:.15s; color:#fff; }
|
||
.btn:hover { transform:translateY(-1px); filter:brightness(1.15); }
|
||
.btn-sm { padding:5px 10px; font-size:11px; border-radius:5px; }
|
||
.btn-outline { background:transparent; border:1px solid var(--border); color:var(--text); }
|
||
.btn-outline:hover { border-color:var(--accent); background:rgba(99,102,241,0.06); }
|
||
.c-s { background:#10b981; } .c-e { background:#ef4444; } .c-w { background:#f59e0b; color:#1e293b; }
|
||
.c-i { background:#3b82f6; } .c-p { background:#6366f1; } .c-pp { background:#8b5cf6; }
|
||
.c-pk { background:#ec4899; } .c-t { background:#14b8a6; } .c-o { background:#f97316; }
|
||
.c-sl { background:#475569; } .c-r { background:#f43f5e; }
|
||
.label { font-size:10px; text-transform:uppercase; letter-spacing:0.8px; color:var(--muted); margin-bottom:12px; font-weight:600; }
|
||
.demo-section { border-top:1px solid var(--border); padding-top:10px; margin-top:10px; }
|
||
footer { text-align:center; padding:30px 20px; color:var(--muted); font-size:12px; border-top:1px solid var(--border); }
|
||
@media (max-width:768px) { .container { grid-template-columns:1fr; } }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
|
||
<nav class="nav">
|
||
<div class="nav-inner">
|
||
<div class="nav-logo">MetonaToast</div>
|
||
<div class="nav-links">
|
||
<a href="index.html">首页</a>
|
||
<a href="docs.html">文档</a>
|
||
<a href="demo.html">演示</a>
|
||
<a href="https://github.com/metona/metona-toast" target="_blank">GitHub</a>
|
||
</div>
|
||
</div>
|
||
</nav>
|
||
|
||
<header class="hero">
|
||
<h1><span>在线演示</span></h1>
|
||
<p>所有功能均可点击体验 — 192 个测试用例全部通过验证</p>
|
||
</header>
|
||
|
||
<main class="container">
|
||
|
||
<!-- 基础通知 -->
|
||
<div class="card">
|
||
<div class="label">📢 基础通知</div>
|
||
<div class="btn-row">
|
||
<button class="btn c-s" onclick="M.success('操作成功!')">✓ 成功</button>
|
||
<button class="btn c-e" onclick="M.error('操作失败!')">✕ 错误</button>
|
||
<button class="btn c-w" onclick="M.warning('请注意检查')">⚠ 警告</button>
|
||
<button class="btn c-i" onclick="M.info('系统维护中')">ℹ 信息</button>
|
||
<button class="btn c-sl" onclick="M.show('默认消息')">— 默认</button>
|
||
</div>
|
||
<div class="demo-section">
|
||
<div class="btn-row">
|
||
<button class="btn btn-outline btn-sm" onclick="M.success({title:'保存成功',message:'文件已同步到云端'})">带标题</button>
|
||
<button class="btn btn-outline btn-sm" onclick="M.info('显示10秒',{duration:10000})">长时10s</button>
|
||
<button class="btn btn-outline btn-sm" onclick="M.info('手动关闭',{duration:0})">手动关闭</button>
|
||
<button class="btn btn-outline btn-sm" onclick="M.info('隐藏图标',{icon:false})">无图标</button>
|
||
<button class="btn btn-outline btn-sm" onclick="M.info('隐藏进度条',{showProgress:false})">无进度条</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Loading 链式 -->
|
||
<div class="card">
|
||
<div class="label">🔄 Loading 链式转换</div>
|
||
<div class="btn-row">
|
||
<button class="btn c-p" onclick="demoLoading()">提交成功</button>
|
||
<button class="btn c-e" onclick="demoLoadingFail()">提交失败</button>
|
||
<button class="btn c-pp" onclick="demoPromise()">Promise 风格</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 对话框 -->
|
||
<div class="card">
|
||
<div class="label">💬 对话框</div>
|
||
<div class="btn-row">
|
||
<button class="btn c-pk" onclick="demoConfirm()">确认对话框</button>
|
||
<button class="btn c-t" onclick="demoPrompt()">输入对话框</button>
|
||
<button class="btn c-o" onclick="demoCountdown()">倒计时 5s</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 进度 & 队列 -->
|
||
<div class="card">
|
||
<div class="label">📊 进度 & 队列</div>
|
||
<div class="btn-row">
|
||
<button class="btn c-o" onclick="demoProgress()">进度条</button>
|
||
<button class="btn c-p" onclick="demoQueue()">队列展示</button>
|
||
<button class="btn c-pp" onclick="demoStack()">堆叠展示</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Action Toast -->
|
||
<div class="card">
|
||
<div class="label">⚡ Action Toast <span style="color:#34d399;font-size:10px;">NEW</span></div>
|
||
<div class="btn-row">
|
||
<button class="btn c-e" onclick="demoActionDelete()">删除+撤销</button>
|
||
<button class="btn c-i" onclick="demoActionMulti()">多个操作</button>
|
||
<button class="btn c-s" onclick="demoActionSuccess()">成功+查看</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 分组管理 -->
|
||
<div class="card">
|
||
<div class="label">📁 分组管理 <span style="color:#34d399;font-size:10px;">NEW</span></div>
|
||
<div class="btn-row">
|
||
<button class="btn c-p" onclick="demoGroup()">创建分组</button>
|
||
<button class="btn c-e" onclick="dismissGroup()">关闭分组</button>
|
||
<button class="btn btn-outline btn-sm" onclick="M.info('分组数量: '+group.count())">查看数量</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 动画效果 -->
|
||
<div class="card">
|
||
<div class="label">🎭 动画效果</div>
|
||
<div class="btn-row">
|
||
<button class="btn btn-outline btn-sm" onclick="anim('slide')">slide</button>
|
||
<button class="btn btn-outline btn-sm" onclick="anim('fade')">fade</button>
|
||
<button class="btn btn-outline btn-sm" onclick="anim('scale')">scale</button>
|
||
<button class="btn btn-outline btn-sm" onclick="anim('bounce')">bounce</button>
|
||
<button class="btn btn-outline btn-sm" onclick="anim('flip')">flip</button>
|
||
<button class="btn btn-outline btn-sm" onclick="anim('rotate')">rotate</button>
|
||
<button class="btn btn-outline btn-sm" onclick="anim('zoom')">zoom</button>
|
||
<button class="btn btn-outline btn-sm" onclick="anim('slideUp')">slideUp</button>
|
||
<button class="btn btn-outline btn-sm" onclick="anim('slideDown')">slideDown</button>
|
||
<button class="btn btn-outline btn-sm" onclick="anim('slideLeft')">slideLeft</button>
|
||
<button class="btn btn-outline btn-sm" onclick="anim('slideRight')">slideRight</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 位置 -->
|
||
<div class="card">
|
||
<div class="label">📍 位置</div>
|
||
<div class="btn-row">
|
||
<button class="btn c-sl" onclick="M.success('左上角',{position:'top-left'})">↖ top-left</button>
|
||
<button class="btn c-sl" onclick="M.success('顶部居中',{position:'top-center'})">↑ top-center</button>
|
||
<button class="btn c-sl" onclick="M.success('右上角',{position:'top-right'})">↗ top-right</button>
|
||
<button class="btn c-sl" onclick="M.success('左下角',{position:'bottom-left'})">↙ bottom-left</button>
|
||
<button class="btn c-sl" onclick="M.success('底部居中',{position:'bottom-center'})">↓ bottom-center</button>
|
||
<button class="btn c-sl" onclick="M.success('右下角',{position:'bottom-right'})">↘ bottom-right</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 主题 -->
|
||
<div class="card">
|
||
<div class="label">🎨 主题切换</div>
|
||
<div class="btn-row">
|
||
<button class="btn btn-outline btn-sm" onclick="switchTheme('light')">☀️ Light</button>
|
||
<button class="btn btn-outline btn-sm" onclick="switchTheme('dark')">🌙 Dark</button>
|
||
<button class="btn btn-outline btn-sm" onclick="switchTheme('auto')">🔄 Auto</button>
|
||
<button class="btn btn-outline btn-sm" onclick="switchTheme('warm')">🔥 Warm</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 插件 -->
|
||
<div class="card">
|
||
<div class="label">🔌 插件</div>
|
||
<div class="btn-row">
|
||
<button class="btn c-p" onclick="M.use('keyboard');M.info('已安装 — 试试按 ESC 键','keyboard插件')">keyboard ESC关闭</button>
|
||
<button class="btn c-i" onclick="M.use('persistence');M.info('已安装 — 配置将自动保存','persistence插件')">persistence 持久化</button>
|
||
<button class="btn c-t" onclick="M.use('accessibility');M.info('已安装 — 屏幕阅读器可用','accessibility插件')">accessibility 无障碍</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 管理 -->
|
||
<div class="card">
|
||
<div class="label">🔧 Toast 管理</div>
|
||
<div class="btn-row">
|
||
<button class="btn c-s" onclick="M.success('消息 '+(M.count()+1))">发一条</button>
|
||
<button class="btn c-i" onclick="M.info('消息 '+(M.count()+1))">再发一条</button>
|
||
<button class="btn c-w" onclick="alert('当前共 '+M.count()+' 条消息')">查看数量</button>
|
||
<button class="btn c-e" onclick="M.dismiss()">关闭全部</button>
|
||
<button class="btn c-sl" onclick="M.pauseAll();M.info('已暂停全部计时')">暂停全部</button>
|
||
<button class="btn c-sl" onclick="M.resumeAll();M.info('已恢复全部计时')">恢复全部</button>
|
||
</div>
|
||
</div>
|
||
|
||
</main>
|
||
|
||
<footer>
|
||
MetonaToast v2.0.0 · MIT License · <a href="index.html">首页</a> · <a href="docs.html">文档</a>
|
||
</footer>
|
||
|
||
<script src="../dist/metona-toast.js"></script>
|
||
<script>
|
||
const M = MeToast;
|
||
M.configure({ position:'top-right', duration:4000, theme:'dark', animation:'slide', pauseOnHover:true, showProgress:true });
|
||
|
||
// Loading
|
||
function demoLoading() { const l=M.loading('正在提交...'); setTimeout(()=>l.success('提交成功!'),2000); }
|
||
function demoLoadingFail() { const l=M.loading('正在提交...'); setTimeout(()=>l.error('提交失败,请重试'),2000); }
|
||
async function demoPromise() {
|
||
const p=new Promise((r,e)=>setTimeout(()=>Math.random()>0.3?r('ok'):e('fail'),2000));
|
||
try{await M.promise(p,{loading:'处理中...',success:'成功!',error:'失败'});}catch(_){}
|
||
}
|
||
|
||
// 对话框
|
||
async function demoConfirm() { const ok=await M.confirm('确定删除吗?',{confirmText:'删除',confirmColor:'#ef4444'}); if(ok)M.success('已删除'); else M.info('已取消'); }
|
||
async function demoPrompt() { const v=await M.prompt('请输入姓名',{placeholder:'请输入...'}); if(v) M.info('你好,'+v+'!'); }
|
||
|
||
// 进度 & 队列
|
||
function demoProgress() { const p=M.progress('上传中...'); let v=0; const t=setInterval(()=>{v+=Math.random()*28; if(v>=100){clearInterval(t);p.complete('完成!');}else p.setProgress(v);},400); }
|
||
function demoCountdown() { M.countdown('{seconds} 秒后执行',5,{onComplete:()=>M.success('已执行')}); }
|
||
async function demoQueue() { await M.queue(['步骤一','步骤二','步骤三'],{delay:800,duration:2000,type:'info'}); }
|
||
function demoStack() { M.stack(['消息1','消息2','消息3','消息4'],{stagger:150,type:'info'}); }
|
||
|
||
// Action
|
||
function demoActionDelete() {
|
||
let deleted=true;
|
||
M.action('文件 data.json 已删除',[{text:'撤销',onClick:()=>{deleted=false;M.success('已撤销删除');},color:'#3b82f6'}]);
|
||
}
|
||
function demoActionMulti() {
|
||
M.action('邮件已发送',[
|
||
{text:'查看',onClick:()=>M.info('打开邮件详情'),color:'#3b82f6'},
|
||
{text:'撤回',onClick:()=>M.warning('邮件已撤回'),color:'#f59e0b'},
|
||
]);
|
||
}
|
||
function demoActionSuccess() {
|
||
M.action('上传完成',[{text:'查看文件',onClick:()=>M.info('打开文件管理器'),color:'#10b981'}]);
|
||
}
|
||
|
||
// 分组
|
||
const group = M.group('demo-group');
|
||
function demoGroup() { group.success('分组消息 #'+(group.count()+1)); group.info('分组消息 #'+(group.count()+1)); }
|
||
function dismissGroup() { M.dismissGroup('demo-group'); M.info('已关闭 demo-group 分组'); }
|
||
|
||
// 动画
|
||
function anim(name) { M.success('动画: '+name,{animation:name,duration:3000}); }
|
||
function switchTheme(t) { M.themes.switchTheme(t); M.configure({theme:t}); const n={light:'浅色',dark:'深色',auto:'自动',warm:'暖色'}; M.info('主题: '+n[t],{theme:t}); }
|
||
</script>
|
||
</body>
|
||
</html>
|