mirror of
https://github.com/t8y2/dbx.git
synced 2026-10-21 06:00:39 +00:00
feat(docs): float RainYun sponsor card on doc pages
This commit is contained in:
@@ -2,6 +2,7 @@ import type { ReactNode } from "react";
|
||||
import { DocsLayout } from "fumadocs-ui/layouts/docs";
|
||||
import { RootProvider } from "fumadocs-ui/provider/next";
|
||||
import { DocsSidebarFooter, DocsSidebarLanguageButton } from "@/components/DocsSidebarFooter";
|
||||
import { FloatingSponsorCard } from "@/components/FloatingSponsorCard";
|
||||
import { StaticSearchDialog } from "@/components/StaticSearchDialog";
|
||||
import { i18nUI, resolveLang } from "@/lib/i18n";
|
||||
import { source } from "@/lib/source";
|
||||
@@ -37,6 +38,7 @@ export default async function Layout({ params, children }: { params: Promise<{ l
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
<FloatingSponsorCard lang={locale} />
|
||||
</DocsLayout>
|
||||
</RootProvider>
|
||||
);
|
||||
|
||||
@@ -22,6 +22,23 @@
|
||||
opacity 0.22s ease;
|
||||
}
|
||||
|
||||
/* 文档页右下角赞助悬浮卡片入场动画 */
|
||||
|
||||
@keyframes sponsor-card-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(8px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.sponsor-card-in {
|
||||
animation: sponsor-card-in 0.3s ease-out both;
|
||||
}
|
||||
|
||||
@theme {
|
||||
--color-landing-bg: #161616;
|
||||
--color-landing-ink: #ededf0;
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
"use client";
|
||||
|
||||
import { X } from "lucide-react";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
const DISMISS_STORAGE_KEY = "dbx.docs.sponsorCard.dismissedAt";
|
||||
// 关闭 7 天后重新出现
|
||||
const RESURFACE_MS = 7 * 24 * 60 * 60 * 1000;
|
||||
|
||||
const RAINYUN_URL = "https://www.rainyun.com/MTE5Mjc4Ng==_";
|
||||
|
||||
const COPY = {
|
||||
cn: {
|
||||
badge: "赞助商",
|
||||
tagline: "云服务器 · 游戏云 · 物理服务器",
|
||||
closeLabel: "关闭赞助卡片",
|
||||
},
|
||||
en: {
|
||||
badge: "Sponsor",
|
||||
tagline: "Cloud servers, game hosting & bare metal",
|
||||
closeLabel: "Dismiss sponsor card",
|
||||
},
|
||||
} as const;
|
||||
|
||||
export function FloatingSponsorCard({ lang }: { lang: string }) {
|
||||
const [visible, setVisible] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
try {
|
||||
const dismissedAt = Number(window.localStorage.getItem(DISMISS_STORAGE_KEY));
|
||||
if (!Number.isFinite(dismissedAt) || Date.now() - dismissedAt > RESURFACE_MS) {
|
||||
setVisible(true);
|
||||
}
|
||||
} catch {
|
||||
setVisible(true);
|
||||
}
|
||||
}, []);
|
||||
|
||||
if (!visible) return null;
|
||||
|
||||
const dismiss = () => {
|
||||
setVisible(false);
|
||||
try {
|
||||
window.localStorage.setItem(DISMISS_STORAGE_KEY, String(Date.now()));
|
||||
} catch {
|
||||
// localStorage 不可用时按本次会话关闭处理
|
||||
}
|
||||
};
|
||||
|
||||
const t = lang === "cn" ? COPY.cn : COPY.en;
|
||||
|
||||
return (
|
||||
<aside
|
||||
aria-label={t.badge}
|
||||
className="sponsor-card-in fixed bottom-4 right-4 z-30 w-52 rounded-xl border border-fd-border bg-fd-card/95 p-2.5 shadow-lg backdrop-blur"
|
||||
>
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-[10px] font-medium tracking-wide text-fd-muted-foreground">{t.badge}</span>
|
||||
<button
|
||||
type="button"
|
||||
aria-label={t.closeLabel}
|
||||
onClick={dismiss}
|
||||
className="rounded-md p-1 text-fd-muted-foreground transition-colors hover:bg-fd-accent hover:text-fd-foreground"
|
||||
>
|
||||
<X className="size-3.5" />
|
||||
</button>
|
||||
</div>
|
||||
<a href={RAINYUN_URL} target="_blank" rel="nofollow sponsored noopener noreferrer" className="group mt-1.5 block">
|
||||
{/* 品牌图为白底,暗色主题下需显式白底容器承载 */}
|
||||
<span className="block overflow-hidden rounded-lg bg-white ring-1 ring-black/5 transition-shadow group-hover:ring-black/15">
|
||||
<img src="/sponsors/rainyun-card.png" alt="RainYun" width={400} height={160} className="h-auto w-full" />
|
||||
</span>
|
||||
<span className="mt-1 block text-center text-xs text-fd-muted-foreground">{t.tagline}</span>
|
||||
</a>
|
||||
</aside>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user