Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "2.4.1"
".": "2.4.2"
}
2 changes: 1 addition & 1 deletion client/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "monolith-client",
"version": "2.4.1",
"version": "2.4.2",
"private": true,
"type": "module",
"scripts": {
Expand Down
4 changes: 2 additions & 2 deletions client/src/components/admin-gate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ export function AdminGate({
<div className="overflow-hidden rounded-md border border-border/35 bg-card/95 shadow-[0_28px_90px_oklch(0_0_0_/_38%)] backdrop-blur-xl">
<div className="flex items-center justify-between border-b border-border/20 px-[18px] py-[14px]">
<div className="flex items-center gap-[10px]">
<div className="flex h-[32px] w-[32px] items-center justify-center rounded-md border border-cyan-400/20 bg-cyan-400/10 text-cyan-300">
<div className="flex h-[32px] w-[32px] items-center justify-center rounded-md border border-foreground/16 bg-foreground/[0.06] text-foreground/72">
<ShieldCheck className="h-[16px] w-[16px]" />
</div>
<div>
Expand Down Expand Up @@ -191,7 +191,7 @@ export function AdminGate({
placeholder="输入密码"
autoComplete="current-password"
aria-label="管理员密码"
className="h-[46px] w-full rounded-md border border-border/45 bg-background/55 px-[14px] pr-[48px] text-[15px] text-foreground outline-none transition-all placeholder:text-muted-foreground/35 focus:border-cyan-400/45 focus:ring-1 focus:ring-cyan-400/20"
className="h-[46px] w-full rounded-md border border-border/45 bg-background/55 px-[14px] pr-[48px] text-[15px] text-foreground outline-none transition-all placeholder:text-muted-foreground/35 focus:border-foreground/35 focus:ring-1 focus:ring-foreground/12"
/>

{error && (
Expand Down
28 changes: 14 additions & 14 deletions client/src/components/admin-layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,26 +24,26 @@ interface AdminLayoutProps {

const NAV_GROUPS = [
{
title: "内容管理",
title: "内容运营",
items: [
{ href: "/admin", icon: LayoutDashboard, label: "控制台" },
{ href: "/admin/pages", icon: StickyNote, label: "独立页面" },
{ href: "/admin/comments", icon: MessageCircle, label: "评论审核" },
{ href: "/admin", icon: LayoutDashboard, label: "运营总览" },
{ href: "/admin/pages", icon: StickyNote, label: "页面管理" },
{ href: "/admin/comments", icon: MessageCircle, label: "互动审核" },
],
},
{
title: "资源与数据",
title: "增长工具",
items: [
{ href: "/admin/media", icon: ImageIcon, label: "媒体库" },
{ href: "/admin/analytics", icon: BarChart3, label: "数据分析" },
{ href: "/admin/seo", icon: Sparkles, label: "SEO 优化" },
{ href: "/admin/backup", icon: HardDrive, label: "安全备份" },
{ href: "/admin/media", icon: ImageIcon, label: "媒体资产" },
{ href: "/admin/analytics", icon: BarChart3, label: "运营洞察" },
{ href: "/admin/seo", icon: Sparkles, label: "搜索优化" },
{ href: "/admin/backup", icon: HardDrive, label: "备份恢复" },
],
},
{
title: "系统配置",
title: "系统维护",
items: [
{ href: "/admin/settings", icon: Settings, label: "站点设置" },
{ href: "/admin/settings", icon: Settings, label: "站点配置" },
],
},
];
Expand Down Expand Up @@ -113,7 +113,7 @@ export function AdminLayout({ children }: AdminLayoutProps) {
</div>
<div>
<span className="block font-heading text-[17px] font-semibold tracking-[-0.02em]">Monolith</span>
<span className="block text-[10px] text-muted-foreground/45">Admin Console</span>
<span className="block text-[10px] text-muted-foreground/45">Operations Desk</span>
</div>
</Link>
<label className="mt-[14px] flex min-h-[44px] items-center gap-[8px] rounded-md border border-border/25 bg-background/45 px-[12px] text-[13px] text-foreground shadow-[0_8px_24px_oklch(0_0_0_/_10%)] transition-colors focus-within:border-foreground/25 focus-within:bg-background/65 focus-within:ring-1 focus-within:ring-foreground/10">
Expand Down Expand Up @@ -163,7 +163,7 @@ export function AdminLayout({ children }: AdminLayoutProps) {
: "text-muted-foreground/55 hover:bg-muted/35 hover:text-foreground/85"
}`}
>
{isActive && <span className="absolute left-[4px] top-1/2 h-[18px] w-[2px] -translate-y-1/2 rounded-full bg-cyan-300/80" />}
{isActive && <span className="absolute left-[4px] top-1/2 h-[18px] w-[2px] -translate-y-1/2 rounded-full bg-background/75" />}
<item.icon className="w-[14px] h-[14px]" />
{item.label}
</Link>
Expand Down Expand Up @@ -237,7 +237,7 @@ export function AdminLayout({ children }: AdminLayoutProps) {

<div className="hidden h-[56px] items-center justify-between border-b border-border/20 bg-background/72 px-[24px] backdrop-blur-xl md:flex">
<div className="flex items-center gap-[8px]">
<span className="font-heading text-[13px] font-medium text-foreground/90">Monolith 管理后台</span>
<span className="font-heading text-[13px] font-medium text-foreground/90">Monolith 运营后台</span>
<span className="text-[12px] text-muted-foreground/25">/</span>
<span className="font-heading text-[13px] font-semibold text-foreground/75">{currentTitle}</span>
</div>
Expand Down
11 changes: 6 additions & 5 deletions client/src/components/comments.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ function CommentForm({ slug, onSubmitted }: { slug: string; onSubmitted: () => v
}
};

const inputClass = "w-full rounded-md border border-border/40 bg-card/20 px-[12px] py-[8px] text-[14px] text-foreground placeholder:text-muted-foreground/40 outline-none transition-all duration-200 focus:border-blue-500/40 focus:ring-1 focus:ring-blue-500/20";
const inputClass = "w-full rounded-md border border-border/40 bg-card/20 px-[12px] py-[8px] text-[14px] text-foreground placeholder:text-muted-foreground/40 outline-none transition-all duration-200 focus:border-foreground/35 focus:ring-1 focus:ring-foreground/12";

return (
<form onSubmit={handleSubmit} className="space-y-[12px]">
Expand Down Expand Up @@ -134,7 +134,7 @@ function CommentForm({ slug, onSubmitted }: { slug: string; onSubmitted: () => v
{message && (
<div className={`rounded-md px-[12px] py-[8px] text-[13px] ${
message.type === "success"
? "bg-green-500/10 text-green-400 border border-green-500/20"
? "border border-foreground/12 bg-foreground/[0.06] text-foreground/82"
: "bg-red-500/10 text-red-400 border border-red-500/20"
}`}>
{message.text}
Expand All @@ -144,7 +144,7 @@ function CommentForm({ slug, onSubmitted }: { slug: string; onSubmitted: () => v
<button
type="submit"
disabled={submitting || !authorName.trim() || !content.trim()}
className="inline-flex items-center gap-[6px] rounded-md bg-blue-600/80 px-[16px] py-[8px] text-[13px] font-medium text-white transition-all duration-200 hover:bg-blue-600 disabled:opacity-40 disabled:cursor-not-allowed"
className="inline-flex min-h-[44px] items-center gap-[6px] rounded-md bg-foreground px-[16px] py-[8px] text-[13px] font-medium text-background transition-all duration-200 hover:-translate-y-[2px] hover:opacity-90 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring disabled:translate-y-0 disabled:cursor-not-allowed disabled:opacity-40 sm:min-h-[36px]"
>
<Send className="h-[14px] w-[14px]" />
{submitting ? "提交中..." : "发表评论"}
Expand Down Expand Up @@ -173,11 +173,12 @@ export function CommentsSection({ slug }: { slug: string }) {

return (
<section className="mt-[40px] animate-fade-in delay-5">
<div className="rounded-xl border border-border/40 bg-card/10 overflow-hidden transition-all duration-300">
<div className="overflow-hidden rounded-md border border-border/32 bg-card/10 transition-all duration-300">
<button
onClick={() => setIsOpen(!isOpen)}
className="w-full flex items-center justify-between p-[16px] md:px-[20px] bg-transparent hover:bg-card/30 transition-colors"
className="flex min-h-[56px] w-full items-center justify-between bg-transparent p-[16px] text-left transition-colors hover:bg-card/30 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-[-2px] focus-visible:outline-ring md:px-[20px]"
title={isOpen ? "收起评论区" : "展开评论区"}
aria-expanded={isOpen}
>
<div className="flex items-center gap-[8px]">
<MessageCircle className="h-[18px] w-[18px] text-muted-foreground/60" />
Expand Down
93 changes: 92 additions & 1 deletion client/src/components/hero.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export function Hero() {
export function LegacyHero() {
return (
<section className="relative border-b border-border/20 py-[44px] sm:py-[56px] lg:py-[68px]">
<div className="pointer-events-none absolute inset-0 hero-grid opacity-45" />
Expand Down Expand Up @@ -40,3 +40,94 @@ export function Hero() {
</section>
);
}

export type HeroTopic = {
title: string;
desc: string;
};

export type HeroAction = {
label: string;
href: string;
};

type HeroProps = {
title?: string;
kicker?: string;
subtitle?: string;
description?: string;
actions?: HeroAction[];
topics?: HeroTopic[];
};

const DEFAULT_ACTIONS: HeroAction[] = [
{ label: "最新文章", href: "#latest-posts" },
{ label: "主题索引", href: "#content-index" },
{ label: "工程笔记", href: "/archive" },
];

const DEFAULT_TOPICS: HeroTopic[] = [
{ title: "系统设计", desc: "从边界、接口和运维成本切入" },
{ title: "阅读体验", desc: "让长文、代码与目录保持同一节奏" },
{ title: "边缘部署", desc: "Workers / D1 / R2 的真实工程路径" },
];

export function Hero({
title = "Monolith",
kicker = "EDGE JOURNAL / CODE ARCHIVE",
subtitle = "技术写作、系统设计与边缘实践的索引页",
description = "用更冷静的网格整理长期主题:前端架构、设计系统、边缘计算与工程排障。每一篇文章都尽量给出可复用的上下文,而不是只留下零散记录。",
actions = DEFAULT_ACTIONS,
topics = DEFAULT_TOPICS,
}: HeroProps) {
const visibleActions = actions.filter((item) => item.label.trim() && item.href.trim()).slice(0, 3);
const visibleTopics = topics.filter((item) => item.title.trim() && item.desc.trim()).slice(0, 3);

return (
<section className="relative border-b border-border/18 py-[40px] sm:py-[52px] lg:py-[64px]">
<div className="pointer-events-none absolute inset-0 hero-grid opacity-35" />
<div className="relative grid gap-[24px] lg:grid-cols-[minmax(0,1fr)_320px] lg:items-stretch">
<div className="min-w-0 border-l border-border/35 pl-[16px] sm:pl-[20px]">
<div className="mb-[20px] flex items-center gap-[12px]">
<div className="min-w-0">
<p className="font-mono text-[11px] text-muted-foreground/45">{kicker}</p>
<p className="mt-[4px] text-[12px] text-muted-foreground/42">{subtitle}</p>
</div>
</div>

<h1 className="max-w-[820px] font-heading text-[42px] font-semibold leading-[0.96] tracking-[-0.045em] text-foreground sm:text-[60px] lg:text-[76px]">
{title}
</h1>
<p className="mt-[20px] max-w-[660px] text-[16px] leading-[1.85] text-muted-foreground sm:text-[17px]">
{description}
</p>

<div className="mt-[24px] flex flex-wrap gap-[8px]">
{visibleActions.map((item) => (
<a
key={`${item.label}-${item.href}`}
href={item.href}
className="inline-flex min-h-[44px] items-center rounded-md border border-border/18 bg-background/32 px-[12px] text-[13px] text-muted-foreground/72 transition-all duration-200 hover:-translate-y-[2px] hover:border-border/36 hover:bg-card/22 hover:text-foreground focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring sm:min-h-[36px]"
>
{item.label}
</a>
))}
</div>
</div>

<div className="grid gap-[10px] rounded-md border border-border/20 bg-background/35 p-[14px] backdrop-blur-sm">
<p className="font-mono text-[11px] text-muted-foreground/42">CURRENT THREADS</p>
{visibleTopics.map((item) => (
<div key={item.title} className="rounded-md border border-border/14 bg-card/[0.10] px-[12px] py-[10px]">
<div className="flex items-center justify-between gap-[12px]">
<span className="text-[13px] font-medium text-foreground/86">{item.title}</span>
<span className="h-[6px] w-[6px] rounded-full bg-foreground/42" />
</div>
<p className="mt-[6px] text-[12px] leading-[1.6] text-muted-foreground/55">{item.desc}</p>
</div>
))}
</div>
</div>
</section>
);
}
Loading