387a1c26e3
清理已跟踪原始日志与个人本地配置 修复前后端有效门禁、测试和构建问题 补齐生产 Jenkins、SpacetimeDB 本地命令与文档约束 收紧图片编辑器状态、附件与媒体引用测试 排除已下线旧创作入口测试并清理 warning
183 lines
5.4 KiB
TypeScript
183 lines
5.4 KiB
TypeScript
import {
|
|
type PlatformSegmentedTabItem,
|
|
PlatformSegmentedTabs,
|
|
} from './PlatformSegmentedTabs';
|
|
|
|
type PlatformSegmentedTabPresetProps<TId extends string> = {
|
|
items: readonly PlatformSegmentedTabItem<TId>[];
|
|
activeId: TId;
|
|
onChange: (id: TId) => void;
|
|
ariaLabel?: string;
|
|
className?: string;
|
|
};
|
|
|
|
export type PlatformUnderlineTabRailVariant = 'channel' | 'ranking';
|
|
|
|
const PLATFORM_UNDERLINE_TAB_RAIL_CLASS: Record<
|
|
PlatformUnderlineTabRailVariant,
|
|
string
|
|
> = {
|
|
channel: 'platform-mobile-home-channelbar pb-1',
|
|
ranking: 'platform-ranking-tabs pb-1',
|
|
};
|
|
|
|
const PLATFORM_UNDERLINE_TAB_ITEM_CLASS: Record<
|
|
PlatformUnderlineTabRailVariant,
|
|
{ base: string; active: string }
|
|
> = {
|
|
channel: {
|
|
base: 'platform-mobile-home-channel shrink-0 !min-h-8 !rounded-none !border-0 !bg-transparent !px-0 !shadow-none hover:!bg-transparent',
|
|
active: 'platform-mobile-home-channel--active',
|
|
},
|
|
ranking: {
|
|
base: 'platform-ranking-tab shrink-0 !min-h-[2.35rem] !rounded-none !border-0 !bg-transparent !px-[0.15rem] !shadow-none hover:!bg-transparent',
|
|
active: 'platform-ranking-tab--active',
|
|
},
|
|
};
|
|
|
|
export type PlatformOptionSegmentVariant = 'categoryFilter' | 'profile';
|
|
|
|
const PLATFORM_OPTION_SEGMENT_CLASS: Record<
|
|
PlatformOptionSegmentVariant,
|
|
{
|
|
rail: string;
|
|
active: string;
|
|
idle: string;
|
|
}
|
|
> = {
|
|
categoryFilter: {
|
|
rail: 'platform-category-filter-dialog__options',
|
|
active:
|
|
'platform-category-filter-dialog__option--active !border-[var(--platform-cool-border)] !bg-[var(--platform-cool-bg)] !text-[var(--platform-cool-text)]',
|
|
idle:
|
|
'platform-category-filter-dialog__option !min-h-[2.35rem] !rounded-[0.78rem] !border !border-[var(--platform-subpanel-border)] !bg-[var(--platform-subpanel-fill)] !px-3 !text-[0.88rem] !font-black !text-[var(--platform-text-base)] !shadow-none hover:!bg-[var(--platform-subpanel-fill)]',
|
|
},
|
|
profile: {
|
|
rail: '',
|
|
active:
|
|
'!border-[var(--platform-cool-border)] !bg-[var(--platform-cool-bg)] !text-[var(--platform-cool-text)]',
|
|
idle:
|
|
'w-full !min-h-[2.25rem] !rounded-[0.78rem] !border !border-[var(--platform-subpanel-border)] !bg-[rgba(255,255,255,0.04)] !px-3 !text-sm !font-extrabold !text-[var(--platform-text-base)] !shadow-none hover:!bg-[rgba(255,255,255,0.08)]',
|
|
},
|
|
};
|
|
|
|
/**
|
|
* 统一首页、作品架这类横向文字 rail,只沉淀稳定的滚动与下划线皮肤。
|
|
*/
|
|
export function PlatformUnderlineTabRail<TId extends string>({
|
|
items,
|
|
activeId,
|
|
onChange,
|
|
ariaLabel,
|
|
className,
|
|
variant = 'channel',
|
|
}: PlatformSegmentedTabPresetProps<TId> & {
|
|
variant?: PlatformUnderlineTabRailVariant;
|
|
}) {
|
|
return (
|
|
<PlatformSegmentedTabs
|
|
items={items}
|
|
activeId={activeId}
|
|
onChange={onChange}
|
|
layout="scroll"
|
|
gap="md"
|
|
frame="bare"
|
|
surface="transparent"
|
|
size="sm"
|
|
tone="neutral"
|
|
semantics="tabs"
|
|
ariaLabel={ariaLabel}
|
|
className={[PLATFORM_UNDERLINE_TAB_RAIL_CLASS[variant], className]
|
|
.filter(Boolean)
|
|
.join(' ')}
|
|
itemClassName={(_, active) =>
|
|
[
|
|
PLATFORM_UNDERLINE_TAB_ITEM_CLASS[variant].base,
|
|
active ? PLATFORM_UNDERLINE_TAB_ITEM_CLASS[variant].active : null,
|
|
]
|
|
.filter(Boolean)
|
|
.join(' ')
|
|
}
|
|
/>
|
|
);
|
|
}
|
|
|
|
/**
|
|
* 统一二列按钮式切换,只负责稳定的视觉 preset,不承接业务语义。
|
|
*/
|
|
export function PlatformOptionSegment<TId extends string>({
|
|
items,
|
|
activeId,
|
|
onChange,
|
|
ariaLabel,
|
|
className,
|
|
variant,
|
|
}: PlatformSegmentedTabPresetProps<TId> & {
|
|
variant: PlatformOptionSegmentVariant;
|
|
}) {
|
|
return (
|
|
<PlatformSegmentedTabs
|
|
items={items}
|
|
activeId={activeId}
|
|
onChange={onChange}
|
|
columns="two"
|
|
layout="grid"
|
|
gap={variant === 'profile' ? 'sm' : 'md'}
|
|
frame="bare"
|
|
surface="transparent"
|
|
size="sm"
|
|
semantics={variant === 'profile' ? 'tabs' : 'segment'}
|
|
ariaLabel={ariaLabel}
|
|
className={[PLATFORM_OPTION_SEGMENT_CLASS[variant].rail, className]
|
|
.filter(Boolean)
|
|
.join(' ')}
|
|
itemClassName={(_, active) =>
|
|
[
|
|
PLATFORM_OPTION_SEGMENT_CLASS[variant].idle,
|
|
active ? PLATFORM_OPTION_SEGMENT_CLASS[variant].active : null,
|
|
]
|
|
.filter(Boolean)
|
|
.join(' ')
|
|
}
|
|
/>
|
|
);
|
|
}
|
|
|
|
/**
|
|
* 创作入口使用的轻量 pill rail,保留 snap 与下划线的组合语义。
|
|
*/
|
|
export function PlatformPillTabRail<TId extends string>({
|
|
items,
|
|
activeId,
|
|
onChange,
|
|
ariaLabel,
|
|
className,
|
|
}: PlatformSegmentedTabPresetProps<TId>) {
|
|
return (
|
|
<PlatformSegmentedTabs
|
|
items={items}
|
|
activeId={activeId}
|
|
onChange={onChange}
|
|
layout="scroll"
|
|
gap="md"
|
|
frame="bare"
|
|
surface="transparent"
|
|
size="sm"
|
|
tone="neutral"
|
|
semantics="tabs"
|
|
ariaLabel={ariaLabel}
|
|
className={['-mx-0.5 snap-x px-0.5 pb-1 scroll-px-2 sm:!gap-3', className]
|
|
.filter(Boolean)
|
|
.join(' ')}
|
|
itemClassName={(_, active) =>
|
|
[
|
|
"relative shrink-0 snap-start !min-h-8 !rounded-full !border-0 !bg-transparent !px-2.5 !text-xs !font-black !shadow-none sm:!min-h-9 sm:!px-3.5 sm:!text-sm",
|
|
active
|
|
? "!text-[#6f2f21] after:absolute after:bottom-0 after:left-3 after:right-3 after:h-1 after:rounded-full after:bg-[#d9793f] after:content-['']"
|
|
: '!text-[#7a6558] hover:!bg-transparent hover:!text-[#6f2f21]',
|
|
].join(' ')
|
|
}
|
|
/>
|
|
);
|
|
}
|