- 新建 components/ui/(Button/Input/Select/Modal/Tabs/Spinner/Skeleton 等),变体用联合类型约束,根治幻影变体 - admin/components.tsx 与 matches/ui.tsx 改为再导出壳,消除 Spinner 三份重复 - 日期工具收口到 lib/date.ts,滚动监听收口到 lib/useScroll.ts - index.css 引入 :root RGB 三元组令牌,tailwind.config 接 <alpha-value>(修复透明度修饰符静默失效) - 刘建毛草 5MB 全字库(jsDelivr 未锁版) → 1KB 自托管子集(仅「先知」二字,unicode-range 限定)
32 lines
1015 B
TypeScript
32 lines
1015 B
TypeScript
/**
|
|
* Switch:一组互斥的文字切换(状态 / 模式)。
|
|
*
|
|
* 原位于 pages/matches/ui.tsx,上移到 UI 层 —— 它用的是全站统一的
|
|
* `.tab` / `.tab-on` 语言(方角、印报红下划线),属通用组件。
|
|
*
|
|
* 注:内部的 <button> 不在 `.btn` 体系内(用 `.tab`),属有意保留的自定义样式。
|
|
*/
|
|
|
|
export function Switch({ value, onChange, items }: {
|
|
value: string
|
|
onChange: (v: string) => void
|
|
items: { v: string; label: string; title?: string }[]
|
|
}) {
|
|
return (
|
|
<span className="inline-flex items-center gap-2.5">
|
|
{items.map((it, i) => (
|
|
<span key={it.v} className="inline-flex items-center gap-2.5">
|
|
{i > 0 && <span className="text-ink-300" aria-hidden="true">/</span>}
|
|
<button
|
|
onClick={() => onChange(it.v)}
|
|
title={it.title}
|
|
className={`relative tab ${value === it.v ? 'tab-on' : ''} text-xs`}
|
|
>
|
|
{it.label}
|
|
</button>
|
|
</span>
|
|
))}
|
|
</span>
|
|
)
|
|
}
|