feat(web): 页头滚动信息、移除返回按钮、面包屑左侧可点、侧栏加首页
- 页头中间信息改为无缝滚动 ticker(3 份拼接,24s 线性,尊重 reduced-motion) - 去掉分区 / 条目 / 文章三处「返回」「返回首页」按钮 - 面包屑移到左侧,中间项可点击并通过 onNavigate 走 SPA 路由 - 侧栏新增「首页」,首页时高亮,点击回首页
This commit is contained in:
@@ -1,34 +1,39 @@
|
||||
import { Card, Paragraph, Space, Text, Title } from '@stash/ui'
|
||||
import { Breadcrumb, Card, Paragraph, Text, Title } from '@stash/ui'
|
||||
import type { ArticleItem } from '../../data/types'
|
||||
import { viewPath } from '../../data/view'
|
||||
import { ArticleBody } from './ArticleBody'
|
||||
|
||||
/**
|
||||
* 文章详情页(对应模板图二):
|
||||
* 大标题 + [编辑] + 元信息行 + 白色正文卡。
|
||||
* 面包屑 + 大标题 + [编辑] + 元信息行 + 白色正文卡。
|
||||
*
|
||||
* 正文是一整段 Markdown,交给 ArticleBody 解析渲染;
|
||||
* 渲染细节(支持哪些语法)都收在那一个组件里。
|
||||
*/
|
||||
type ArticleDetailViewProps = {
|
||||
article: ArticleItem
|
||||
categoryId: string
|
||||
categoryTitle: string
|
||||
onBack: () => void
|
||||
onNavigate: (href: string) => void
|
||||
}
|
||||
|
||||
export function ArticleDetailView({ article, categoryTitle, onBack }: ArticleDetailViewProps) {
|
||||
export function ArticleDetailView({
|
||||
article,
|
||||
categoryId,
|
||||
categoryTitle,
|
||||
onNavigate,
|
||||
}: ArticleDetailViewProps) {
|
||||
const meta = article.meta ?? ['2 年前', categoryTitle]
|
||||
const crumbs = [
|
||||
{ label: '首页', href: '/' },
|
||||
{ label: categoryTitle, href: viewPath({ type: 'detail', categoryId }) },
|
||||
{ label: '文章' },
|
||||
]
|
||||
|
||||
return (
|
||||
<div className="detail-view article-view">
|
||||
<Card padding="none" className="detail-nav">
|
||||
<Space justify="between" wrap>
|
||||
<button type="button" className="detail-back" onClick={onBack}>
|
||||
返回
|
||||
</button>
|
||||
<Text size="xs" tone="muted">
|
||||
{categoryTitle} / 文章
|
||||
</Text>
|
||||
</Space>
|
||||
<Breadcrumb className="detail-breadcrumb" items={crumbs} onNavigate={onNavigate} />
|
||||
</Card>
|
||||
|
||||
<header className="article-head">
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import { Breadcrumb, Card, Empty, Space, Title } from '@stash/ui'
|
||||
import { categoryCount, type Category } from '../../data/types'
|
||||
import { viewPath } from '../../data/view'
|
||||
import { AppGrid } from './AppGrid'
|
||||
import { CesCardGrid } from './CesCardGrid'
|
||||
import { GroupBlock } from './GroupBlock'
|
||||
import { PosterGrid } from './PosterGrid'
|
||||
|
||||
/**
|
||||
* 分类明细视图:返回条 + 面包屑 + hero(图标 / 标题 / 数量)+ 内容区。
|
||||
* 分类明细视图:面包屑 + hero(图标 / 标题 / 数量)+ 内容区。
|
||||
*
|
||||
* 内容区按分类类型切换:
|
||||
* - apps:指定分组时只渲染该组,否则单组扁平渲染、多组带小标题分组渲染;
|
||||
@@ -17,12 +18,13 @@ type DetailViewProps = {
|
||||
category: Category
|
||||
/** 从侧栏子菜单进入时指定的分组 */
|
||||
groupId?: string
|
||||
onBack: () => void
|
||||
/** 点击面包屑中间项(SPA 路由) */
|
||||
onNavigate: (href: string) => void
|
||||
/** 点击卡片 / 海报进入条目详情 */
|
||||
onOpenItem: (itemId: string) => void
|
||||
}
|
||||
|
||||
export function DetailView({ category, groupId, onBack, onOpenItem }: DetailViewProps) {
|
||||
export function DetailView({ category, groupId, onNavigate, onOpenItem }: DetailViewProps) {
|
||||
const groups = category.kind === 'apps' ? category.groups : []
|
||||
const activeGroup =
|
||||
groupId !== undefined ? groups.find((group) => group.id === groupId) : undefined
|
||||
@@ -33,10 +35,13 @@ export function DetailView({ category, groupId, onBack, onOpenItem }: DetailView
|
||||
activeGroup !== undefined
|
||||
? [
|
||||
{ label: '首页', href: '/' },
|
||||
{ label: category.title },
|
||||
{ label: category.title, href: viewPath({ type: 'detail', categoryId: category.id }) },
|
||||
{ label: activeGroup.name },
|
||||
]
|
||||
: [{ label: '首页', href: '/' }, { label: category.title }]
|
||||
: [
|
||||
{ label: '首页', href: '/' },
|
||||
{ label: category.title, href: viewPath({ type: 'detail', categoryId: category.id }) },
|
||||
]
|
||||
|
||||
function renderBody() {
|
||||
if (category.kind === 'posters') {
|
||||
@@ -71,12 +76,11 @@ export function DetailView({ category, groupId, onBack, onOpenItem }: DetailView
|
||||
return (
|
||||
<div className="detail-view">
|
||||
<Card padding="none" className="detail-nav">
|
||||
<Space justify="between" wrap>
|
||||
<button type="button" className="detail-back" onClick={onBack}>
|
||||
返回首页
|
||||
</button>
|
||||
<Breadcrumb items={crumbs} />
|
||||
</Space>
|
||||
<Breadcrumb
|
||||
className="detail-breadcrumb"
|
||||
items={crumbs}
|
||||
onNavigate={onNavigate}
|
||||
/>
|
||||
</Card>
|
||||
|
||||
<div className="detail-hero">
|
||||
|
||||
@@ -1,4 +1,15 @@
|
||||
import { Card, Icon, IconButton, Paragraph, Space, Tag, Text, Title } from '@stash/ui'
|
||||
import {
|
||||
Breadcrumb,
|
||||
Card,
|
||||
Icon,
|
||||
IconButton,
|
||||
Paragraph,
|
||||
Space,
|
||||
Tag,
|
||||
Text,
|
||||
Title,
|
||||
type BreadcrumbItem,
|
||||
} from '@stash/ui'
|
||||
import type { ItemDetailModel } from '../../data/detail'
|
||||
import type { RelatedItem } from '../../data/types'
|
||||
import { RelatedList } from './RelatedList'
|
||||
@@ -6,38 +17,29 @@ import { RelatedList } from './RelatedList'
|
||||
/**
|
||||
* 条目详情页:应用与电影共用。
|
||||
*
|
||||
* 版式:标题 + 主图(方形头像 / 竖版海报)+ 标签行 + 一句话评价 + 正文
|
||||
* 版式:面包屑 + 标题 + 主图(方形头像 / 竖版海报)+ 标签行 + 一句话评价 + 正文
|
||||
* + 操作条(浏览 / 点赞 / 分享 / 跳转)+ 可选横幅 + 「推荐阅读」。
|
||||
* 具体形态由 ItemDetailModel 决定,这里不判断条目类型。
|
||||
*/
|
||||
type ItemDetailViewProps = {
|
||||
breadcrumb: string
|
||||
crumbs: BreadcrumbItem[]
|
||||
model: ItemDetailModel
|
||||
related: RelatedItem[]
|
||||
onBack: () => void
|
||||
onNavigate: (href: string) => void
|
||||
onOpenItem: (itemId: string) => void
|
||||
}
|
||||
|
||||
export function ItemDetailView({
|
||||
breadcrumb,
|
||||
crumbs,
|
||||
model,
|
||||
related,
|
||||
onBack,
|
||||
onNavigate,
|
||||
onOpenItem,
|
||||
}: ItemDetailViewProps) {
|
||||
return (
|
||||
<div className="detail-view item-view">
|
||||
<Card padding="none" className="detail-nav">
|
||||
<Space justify="between" wrap>
|
||||
<button type="button" className="detail-back" onClick={onBack}>
|
||||
返回
|
||||
</button>
|
||||
<span className="detail-breadcrumb">
|
||||
<Text size="xs" tone="muted">
|
||||
{breadcrumb}
|
||||
</Text>
|
||||
</span>
|
||||
</Space>
|
||||
<Breadcrumb className="detail-breadcrumb" items={crumbs} onNavigate={onNavigate} />
|
||||
</Card>
|
||||
|
||||
<Card padding="none" className="item-card">
|
||||
|
||||
Reference in New Issue
Block a user