50 lines
1.5 KiB
TypeScript
50 lines
1.5 KiB
TypeScript
import type { AppItem } from '../../data/types'
|
||
|
||
/**
|
||
* 应用卡片:逐项复刻 Alright 主题「推荐作者」条目的结构。
|
||
*
|
||
* 对应主题的:
|
||
* .flex-avatar > img.avatar-48 + span.avatar-badge.badge_5
|
||
* .item-content > h3.font-title.text-md(名字 + span.item-badge.hot)
|
||
* + div.text-xs.text-muted.h-1x(单行描述)
|
||
*
|
||
* 热门条目才会同时出现头像角标和 HOT 徽标,普通条目两者都没有。
|
||
*/
|
||
type AppCardProps = {
|
||
item: AppItem
|
||
onOpen?: (itemId: string) => void
|
||
}
|
||
|
||
export function AppCard({ item, onOpen }: AppCardProps) {
|
||
return (
|
||
<a
|
||
className="app-card"
|
||
href={item.href}
|
||
title={item.name}
|
||
onClick={(event) => {
|
||
if (onOpen === undefined) return
|
||
if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return
|
||
event.preventDefault()
|
||
onOpen(item.id)
|
||
}}
|
||
>
|
||
<span className="app-card-avatar" aria-hidden="true">
|
||
{item.cover !== undefined ? (
|
||
<img src={item.cover} alt="" loading="lazy" />
|
||
) : (
|
||
<span className="app-card-letter">{item.icon}</span>
|
||
)}
|
||
{item.hot === true && <span className="app-card-verify" />}
|
||
</span>
|
||
|
||
<span className="app-card-info">
|
||
<span className="app-card-title">
|
||
<span className="app-card-name">{item.name}</span>
|
||
{item.hot === true && <span className="app-card-badge" />}
|
||
</span>
|
||
<span className="app-card-desc">{item.desc}</span>
|
||
</span>
|
||
</a>
|
||
)
|
||
}
|