调整创作主页顶部与左侧栏
更新 /creation 顶部栏和左侧功能栏的参考图规格 接入创作主页 image2 陶土风背景、图标和按钮素材 保留创作主页现有文案、搜索、登录、钱包、导航与项目创建逻辑 补充创作主页改版文档和移动端直达验证
This commit is contained in:
@@ -9169,6 +9169,23 @@ test('creation home desktop rail can return to platform tabs', async () => {
|
||||
expect(window.location.pathname).toBe('/');
|
||||
});
|
||||
|
||||
test('direct mobile creation home keeps landing content without mobile nav entry', async () => {
|
||||
window.history.replaceState(null, '', '/creation');
|
||||
const { container } = render(<TestWrapper withAuth />);
|
||||
|
||||
expect(
|
||||
await screen.findByRole('main', { name: '陶泥儿创作主页' }),
|
||||
).toBeTruthy();
|
||||
const bottomNav = container.querySelector('.platform-bottom-nav');
|
||||
expect(bottomNav).toBeTruthy();
|
||||
expect(
|
||||
within(bottomNav as HTMLElement).queryByRole('button', { name: '创作' }),
|
||||
).toBeNull();
|
||||
expect(
|
||||
within(bottomNav as HTMLElement).queryByRole('button', { name: '项目' }),
|
||||
).toBeNull();
|
||||
});
|
||||
|
||||
test('embedded puzzle form timeout exits busy state and shows a readable error', async () => {
|
||||
const user = userEvent.setup();
|
||||
|
||||
|
||||
@@ -288,6 +288,7 @@ export interface RpgEntryHomeViewProps {
|
||||
createTabContent?: ReactNode;
|
||||
draftTabContent?: ReactNode;
|
||||
hasUnreadDraftUpdate?: boolean;
|
||||
allowHiddenActiveTab?: boolean;
|
||||
}
|
||||
|
||||
const PANEL_SURFACE_CLASS = 'platform-surface platform-surface--soft';
|
||||
@@ -319,6 +320,19 @@ const PLATFORM_DESKTOP_NAV_TABS: PlatformNavTab[] = [
|
||||
'projects',
|
||||
'profile',
|
||||
];
|
||||
const CREATION_HOME_NAV_ICON_SRC: Record<PlatformNavTab, string> = {
|
||||
home: '/creation-home/nav-recommend.png',
|
||||
category: '/creation-home/nav-discover.png',
|
||||
create: '/creation-home/nav-create.png',
|
||||
projects: '/creation-home/nav-projects.png',
|
||||
saves: '/creation-home/nav-projects.png',
|
||||
profile: '/creation-home/nav-profile.png',
|
||||
};
|
||||
const CREATION_HOME_TOPBAR_ASSETS = {
|
||||
brandMascot: '/creation-home/brand-mascot.png',
|
||||
search: '/creation-home/topbar-search.png',
|
||||
wallet: '/creation-home/topbar-wallet.png',
|
||||
} as const;
|
||||
const AVATAR_MAX_FILE_SIZE = 5 * 1024 * 1024;
|
||||
const AVATAR_OUTPUT_SIZE = 256;
|
||||
const AVATAR_ALLOWED_TYPES = new Set(['image/jpeg', 'image/png', 'image/webp']);
|
||||
@@ -1011,6 +1025,13 @@ function PublicCodeSearchBar({
|
||||
<div
|
||||
className={`platform-desktop-search flex min-w-0 items-center gap-3 px-4 py-3 text-[var(--platform-text-soft)] ${className ?? ''}`}
|
||||
>
|
||||
<img
|
||||
src={CREATION_HOME_TOPBAR_ASSETS.search}
|
||||
alt=""
|
||||
aria-hidden="true"
|
||||
draggable={false}
|
||||
className="creation-home-topbar-art creation-home-topbar-art--search"
|
||||
/>
|
||||
<Search className="h-4 w-4 shrink-0" />
|
||||
<input
|
||||
value={value}
|
||||
@@ -1065,6 +1086,13 @@ function TopbarWalletShortcutButton({
|
||||
.filter(Boolean)
|
||||
.join(' ')}
|
||||
>
|
||||
<img
|
||||
src={CREATION_HOME_TOPBAR_ASSETS.wallet}
|
||||
alt=""
|
||||
aria-hidden="true"
|
||||
draggable={false}
|
||||
className="creation-home-topbar-art creation-home-topbar-art--wallet"
|
||||
/>
|
||||
<PlatformIconBadge
|
||||
icon={<Coins className="h-3.5 w-3.5" />}
|
||||
size="xs"
|
||||
@@ -1868,6 +1896,7 @@ function DesktopTabButton({
|
||||
emphasized = false,
|
||||
showDot = false,
|
||||
disabled = false,
|
||||
creationHomeIconSrc,
|
||||
}: {
|
||||
active: boolean;
|
||||
label: string;
|
||||
@@ -1876,6 +1905,7 @@ function DesktopTabButton({
|
||||
emphasized?: boolean;
|
||||
showDot?: boolean;
|
||||
disabled?: boolean;
|
||||
creationHomeIconSrc?: string;
|
||||
}) {
|
||||
const ariaLabel = showDot ? `${label},有新草稿` : label;
|
||||
|
||||
@@ -1888,6 +1918,15 @@ function DesktopTabButton({
|
||||
className={`platform-desktop-rail__button ${emphasized ? 'platform-desktop-rail__button--primary' : ''} ${active ? 'platform-desktop-rail__button--active' : ''} disabled:cursor-not-allowed disabled:opacity-55`}
|
||||
>
|
||||
<span className="platform-desktop-rail__icon-shell">
|
||||
{creationHomeIconSrc ? (
|
||||
<img
|
||||
src={creationHomeIconSrc}
|
||||
alt=""
|
||||
aria-hidden="true"
|
||||
draggable={false}
|
||||
className="creation-home-nav-art"
|
||||
/>
|
||||
) : null}
|
||||
<Icon className="platform-desktop-rail__icon h-[1.1rem] w-[1.1rem]" />
|
||||
{showDot ? (
|
||||
<span aria-hidden="true" className="platform-nav-unread-dot" />
|
||||
@@ -2597,6 +2636,7 @@ export function RpgEntryHomeView({
|
||||
createTabContent,
|
||||
draftTabContent,
|
||||
hasUnreadDraftUpdate = false,
|
||||
allowHiddenActiveTab = false,
|
||||
}: RpgEntryHomeViewProps) {
|
||||
const authUi = useAuthUi();
|
||||
const showRechargeEntry = shouldShowRechargeEntry();
|
||||
@@ -2935,11 +2975,15 @@ export function RpgEntryHomeView({
|
||||
} as const satisfies Record<PlatformNavTab, string>;
|
||||
|
||||
useEffect(() => {
|
||||
if (allowHiddenActiveTab) {
|
||||
return;
|
||||
}
|
||||
if (!visibleMobileTabs.includes(activeTab) && !isDesktopLayout) {
|
||||
onTabChange(isAuthenticated ? 'home' : 'category');
|
||||
}
|
||||
}, [
|
||||
activeTab,
|
||||
allowHiddenActiveTab,
|
||||
isAuthenticated,
|
||||
isDesktopLayout,
|
||||
onTabChange,
|
||||
@@ -5096,8 +5140,17 @@ export function RpgEntryHomeView({
|
||||
<div className="flex h-full min-h-0 flex-col">
|
||||
<div className="platform-desktop-shell flex h-full min-h-0 flex-col p-5 xl:p-6">
|
||||
<div className="platform-desktop-topbar flex items-center gap-4 px-5 py-4">
|
||||
<div className="flex min-w-0 flex-1 items-center gap-5">
|
||||
<RpgEntryBrandLogo className="shrink-0" decorative />
|
||||
<div className="platform-desktop-topbar__brand-search flex min-w-0 flex-1 items-center gap-5">
|
||||
<span className="creation-home-brand-lockup shrink-0">
|
||||
<img
|
||||
src={CREATION_HOME_TOPBAR_ASSETS.brandMascot}
|
||||
alt=""
|
||||
aria-hidden="true"
|
||||
draggable={false}
|
||||
className="creation-home-brand-lockup__art"
|
||||
/>
|
||||
<RpgEntryBrandLogo className="shrink-0" decorative />
|
||||
</span>
|
||||
<PublicCodeSearchBar
|
||||
value={desktopSearchKeyword}
|
||||
onChange={updateDesktopSearchKeyword}
|
||||
@@ -5109,7 +5162,7 @@ export function RpgEntryHomeView({
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="platform-desktop-topbar__actions flex items-center gap-3">
|
||||
{isAuthenticated &&
|
||||
(activeTab === 'create' || activeTab === 'saves') ? (
|
||||
<TopbarWalletShortcutButton
|
||||
@@ -5162,6 +5215,7 @@ export function RpgEntryHomeView({
|
||||
active={isPlatformHomeTab(tab) && activeTab === tab}
|
||||
label={tabLabels[tab]}
|
||||
icon={tabIcons[tab]}
|
||||
creationHomeIconSrc={CREATION_HOME_NAV_ICON_SRC[tab]}
|
||||
emphasized={tab === 'create'}
|
||||
showDot={false}
|
||||
disabled={isRechargePaymentConfirmationPending}
|
||||
|
||||
Reference in New Issue
Block a user