feat(ui): 今日页日期切换 + 卡片可点 + 路由切换进度条
需求 3.7 / 4.5 / 4.6 / 4.7 今日页 - 左右箭头切换日期,中间点开日历选任意一天,范围限定在已有数据内 - 没有记录的日期直接跳过,不会停在一个空白页上 - 一次读一年:往回翻一天不该产生一次请求,卡片的迷你曲线本来也需要前后几天 - 曲线窗口跟着所看的那天结束,卡片上的走势总是通向它上面那个数字 - 卡片改为从 lib/metrics.ts 渲染,点击进入指标详情 路由切换进度条 - 切换本身是瞬时的,用户等的是新页面的第一次请求,没有指示就像点了没反应 - 跑到 90% 停住等页面就位,不谎报完成 - 有最短显示时长,快速跳转时不会闪一下 Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { App as F7App, View, Views, Toolbar, Link } from 'framework7-react';
|
||||
import { App as F7App, View, Views, Toolbar, Link, f7ready } from 'framework7-react';
|
||||
import Framework7 from 'framework7/lite-bundle';
|
||||
import Framework7React from 'framework7-react';
|
||||
|
||||
@@ -55,8 +55,49 @@ function useTheme() {
|
||||
return [theme, setTheme] as const;
|
||||
}
|
||||
|
||||
/**
|
||||
* A progress line across the top while a screen is being pushed.
|
||||
*
|
||||
* The transition itself is instant; what the user waits on is the new page's
|
||||
* first fetch, which without this reads as a dead tap. Shown on route change
|
||||
* and cleared once the incoming page has settled, with a floor on how briefly
|
||||
* it can appear so a fast navigation does not produce a flash.
|
||||
*/
|
||||
function useNavProgress() {
|
||||
const [busy, setBusy] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
let shownAt = 0;
|
||||
let timer: number | undefined;
|
||||
|
||||
const show = () => {
|
||||
shownAt = Date.now();
|
||||
window.clearTimeout(timer);
|
||||
setBusy(true);
|
||||
};
|
||||
|
||||
const hide = () => {
|
||||
const elapsed = Date.now() - shownAt;
|
||||
const wait = Math.max(0, 260 - elapsed);
|
||||
window.clearTimeout(timer);
|
||||
timer = window.setTimeout(() => setBusy(false), wait);
|
||||
};
|
||||
|
||||
f7ready((app) => {
|
||||
app.on('routeChange', show);
|
||||
app.on('pageAfterIn', hide);
|
||||
app.on('pageBeforeRemove', hide);
|
||||
});
|
||||
|
||||
return () => window.clearTimeout(timer);
|
||||
}, []);
|
||||
|
||||
return busy;
|
||||
}
|
||||
|
||||
function App() {
|
||||
useTheme();
|
||||
const navigating = useNavProgress();
|
||||
|
||||
return (
|
||||
<F7App
|
||||
@@ -68,6 +109,15 @@ function App() {
|
||||
routes={routes}
|
||||
touch={{ tapHold: true }}
|
||||
>
|
||||
<div
|
||||
className={`nav-progress ${navigating ? 'on' : ''}`}
|
||||
role="status"
|
||||
aria-live="polite"
|
||||
aria-label={navigating ? '正在打开' : ''}
|
||||
>
|
||||
<span className="nav-progress-bar" />
|
||||
</div>
|
||||
|
||||
<Views tabs className="safe-areas">
|
||||
<Toolbar tabbar icons bottom>
|
||||
{TABS.map((tab) => (
|
||||
|
||||
Reference in New Issue
Block a user