update menu

This commit is contained in:
2026-05-07 12:03:58 +08:00
parent 697d3773c8
commit 783779f4ae
8 changed files with 1155 additions and 229 deletions
+29 -37
View File
@@ -3,9 +3,16 @@ import type * as Preset from '@docusaurus/preset-classic';
import remarkMath from 'remark-math';
import rehypeKatex from 'rehype-katex';
import { config as loadEnv } from 'dotenv';
import fs from 'fs';
import path from 'path';
loadEnv({ path: '.env.local' });
const techDocsHTML = fs.readFileSync(
path.join(__dirname, 'src/snippets/tech-docs.html'),
'utf-8',
);
const config: Config = {
title: 'CodeDocs 编程文档',
tagline: 'CodeDocs 编程文档 -- 这里是一些技术人的编程文档',
@@ -35,13 +42,22 @@ const config: Config = {
},
themeConfig: {
// Only enable Algolia when API keys are provided
...(process.env.ALGOLIA_API_KEY && process.env.ALGOLIA_APP_ID ? {
algolia: {
apiKey: process.env.ALGOLIA_API_KEY ?? '',
appId: process.env.ALGOLIA_APP_ID ?? '',
apiKey: process.env.ALGOLIA_API_KEY,
appId: process.env.ALGOLIA_APP_ID,
indexName: 'code-docs',
contextualSearch: true,
searchParameters: {},
},
} : {}),
// Enable sidebar collapse/expand button (dyte-style)
docs: {
sidebar: {
hideable: true,
},
},
navbar: {
title: 'CodeDocs 编程文档',
logo: {
@@ -49,57 +65,33 @@ const config: Config = {
src: 'img/logo.svg',
},
items: [
// ── Mega Dropdown: 技术文档 (left-right panel, mirrors dyte SDK dropdown)
{
label: '技术文档',
type: 'dropdown',
label: '📚 技术文档',
className: 'tech-docs-dropdown',
position: 'left',
items: [
{
type: 'doc',
docId: 'backend-doc/intro-docs',
label: '⚙️ 后端技术',
},
{
type: 'doc',
docId: 'frontend-doc/intro-docs',
label: '⚛️ 前端开发',
},
{
type: 'doc',
docId: 'LeetCode/intro-docs',
label: '🧠 算法与面试',
},
],
},
{
type: 'dropdown',
label: '🛠️ 工具与资源',
position: 'left',
items: [
{
label: '📖 最佳实践',
href: '#',
},
{
label: '🔗 常用链接',
href: '#',
},
{
label: '📚 推荐阅读',
href: '#',
type: 'html',
value: techDocsHTML,
className: 'tech-docs-dropdown',
},
],
},
// ── Blog
{
to: '/blog',
label: '📝 Blog',
position: 'left'
label: 'Blog',
position: 'left',
},
// ── GitHub (right)
{
href: 'https://github.com/chuyaoyuan/code-docs',
label: 'GitHub',
position: 'right',
},
// ── Language toggle (right)
{
type: 'localeDropdown',
position: 'right',
-3
View File
@@ -27,10 +27,7 @@
},
"devDependencies": {
"@docusaurus/tsconfig": "^3.10.1",
"autoprefixer": "^10.5.0",
"dotenv": "^16.4.7",
"postcss": "^8.5.14",
"tailwindcss": "^4.2.4",
"typescript": "^5.4.5"
},
"overrides": {
-6
View File
@@ -1,6 +0,0 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};
+423 -49
View File
@@ -1,49 +1,88 @@
/* stylelint-disable docusaurus/copyright-header */
/**
* Any CSS included here will be global. The classic template
* bundles Infima by default. Infima is a CSS framework designed to
* work well for content-centric websites.
*/
/* Import Tailwind CSS */
@import 'tailwindcss/base';
@import 'tailwindcss/components';
@import 'tailwindcss/utilities';
/* You can override the default Infima variables here. */
/* ══════════════════════════════════════════════════
Base CSS variables (mirrors dyte-io/docs token system)
══════════════════════════════════════════════════ */
:root {
/* Infima primary (matches dyte blue) */
--ifm-color-primary: #2160fd;
--ifm-color-primary-dark: #1850d8;
--ifm-color-primary-darker: #1442c4;
--ifm-color-primary-darkest: #102ca0;
--ifm-color-primary-light: #4d7ffe;
--ifm-color-primary-lighter: #7a9eff;
--ifm-color-primary-lightest: #a8c0ff;
--ifm-color-primary-dark: #1959fc;
--ifm-color-primary-darker: #0f51f8;
--ifm-color-primary-darkest: #0042e7;
--ifm-color-primary-light: #3d72f8;
--ifm-color-primary-lighter: #477af8;
--ifm-color-primary-lightest: #6791fc;
--docs-color-primary: rgb(33 96 253);
--docs-color-primary-100: rgb(26 144 255);
--docs-color-primary-200: rgb(33 96 253);
/* Docs color tokens */
--docs-color-primary: #2160fd;
--docs-color-primary-tint: rgba(33, 96, 253, 0.16);
--docs-color-primary-tint-light: rgba(33, 96, 253, 0.24);
--docs-color-secondary-1000: rgb(0 0 0);
--docs-color-secondary-900: rgb(25 25 25);
--docs-color-secondary-800: rgb(38 38 38);
--docs-color-secondary-700: rgb(71 71 71);
/* Background */
--docs-color-background: #ffffff;
--docs-color-background-100: #f8f8f8;
--docs-color-background-200: #efefef;
--docs-color-background-300: #dcdcdc;
--docs-color-text: rgb(31 41 55);
--docs-color-text-100: rgb(107 114 128);
--docs-color-text-400: rgb(153 153 153);
/* Text */
--docs-color-text: #000000;
--docs-color-text-100: #646464;
--docs-color-text-400: #474747;
--docs-color-text-secondary: rgb(107 114 128);
/* Border */
--docs-color-border: #dadde1;
--ifm-code-font-size: 95%;
/* Secondary scale (light mode = lighter greys) */
--docs-color-secondary-700: 232 232 236;
--docs-color-secondary-800: 245 245 247;
--docs-color-secondary-900: 251 251 251;
--docs-color-secondary-1000: 255 255 255;
/* Navbar */
--ifm-navbar-shadow: none;
--ifm-navbar-padding-horizontal: 0.75rem;
/* Misc */
--ifm-code-font-size: 92%;
--ifm-toc-border-color: #dedede;
--docusaurus-highlighted-code-line-bg: rgba(147, 178, 244, 0.38);
}
[data-theme='dark'] {
--docs-color-text: rgb(243 244 246);
--docs-color-text-secondary: rgb(209 213 219);
html[data-theme='dark'] {
--ifm-color-primary: #1a90ff;
--docs-color-primary: #1a90ff;
--docs-color-background: #161616;
--docs-color-background-100: #1c1c1c;
--docs-color-background-200: #2a2a2a;
--docs-color-background-300: #2e2e2e;
--docs-color-text: #ffffff;
--docs-color-text-100: #b4b4b4;
--docs-color-text-400: #999999;
--docs-color-border: #2e2e2e;
--docs-color-secondary-700: 71 71 71;
--docs-color-secondary-800: 38 38 38;
--docs-color-secondary-900: 25 25 25;
--docs-color-secondary-1000: 0 0 0;
--ifm-background-color: #161616;
--ifm-background-surface-color: #161616;
--ifm-footer-background-color: #1c1c1c;
--ifm-toc-border-color: #2e2e2e;
--ifm-color-content: #e7e7e7;
--docusaurus-highlighted-code-line-bg: rgba(105, 105, 105, 0.3);
}
/* ══════════════════════════════════════════════════
Base element styles
══════════════════════════════════════════════════ */
nav.navbar {
border-bottom: 1px solid var(--ifm-toc-border-color);
}
/* Code highlighting */
.docusaurus-highlight-code-line {
background-color: rgb(72, 77, 91);
display: block;
@@ -51,7 +90,7 @@
padding: 0 var(--ifm-pre-padding);
}
/* Enhanced link hover decoration */
/* Disable underline-on-hover in nav/sidebar */
.navbar__link,
.menu__link,
.table-of-contents__link,
@@ -61,27 +100,362 @@
}
.menu__link {
--ifm-link-hover-color: var(--ifm-color-primary);
--ifm-menu-color-background-active: var(--docs-color-primary-tint);
}
/* Smooth transitions */
* {
@apply transition-colors;
/* Dropdown chevron (matches dyte) */
.dropdown > .navbar__link {
display: flex;
align-items: center;
}
/* Hero section enhancements */
.hero {
background: linear-gradient(
135deg,
rgba(33, 96, 253, 0.05) 0%,
rgba(6, 182, 212, 0.05) 100%
);
.dropdown > .navbar__link:after {
content: '';
border: none;
position: static;
top: auto;
transform: none;
width: 12px;
height: 12px;
margin-left: 4px;
background-image: url("data:image/svg+xml,%3Csvg width='24' height='24' fill='none' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M4.293 8.293a1 1 0 0 1 1.414 0L12 14.586l6.293-6.293a1 1 0 1 1 1.414 1.414l-7 7a1 1 0 0 1-1.414 0l-7-7a1 1 0 0 1 0-1.414Z' fill='%23888888'/%3E%3C/svg%3E");
background-size: 12px;
background-repeat: no-repeat;
}
.hero--primary {
background-color: #f9fafb;
html[data-theme='dark'] .dropdown > .navbar__link:after {
background-image: url("data:image/svg+xml,%3Csvg width='24' height='24' fill='none' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M4.293 8.293a1 1 0 0 1 1.414 0L12 14.586l6.293-6.293a1 1 0 1 1 1.414 1.414l-7 7a1 1 0 0 1-1.414 0l-7-7a1 1 0 0 1 0-1.414Z' fill='%23cccccc'/%3E%3C/svg%3E");
}
[data-theme='dark'] .hero--primary {
background-color: #1a1a2e;
.dropdown:hover > .navbar__link:after {
background-image: url("data:image/svg+xml,%3Csvg width='24' height='24' fill='none' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M4.293 8.293a1 1 0 0 1 1.414 0L12 14.586l6.293-6.293a1 1 0 1 1 1.414 1.414l-7 7a1 1 0 0 1-1.414 0l-7-7a1 1 0 0 1 0-1.414Z' fill='%232160fd'/%3E%3C/svg%3E") !important;
}
/* ══════════════════════════════════════════════════
Tech Dropdown: Mega Menu (left panel + right panel)
Mirrors dyte's SDK dropdown pattern exactly
══════════════════════════════════════════════════ */
/* Docusaurus wraps the html item in a ul.dropdown__menu */
.tech-docs-dropdown + ul.dropdown__menu {
padding: 0;
border-radius: 16px;
overflow: hidden;
border: 1px solid var(--docs-color-border);
background: transparent;
min-width: 750px;
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.12);
}
.tech-dropdown {
display: flex;
min-height: 280px;
}
/* Left Category Panel */
.tech-dropdown-left {
display: flex;
flex-direction: column;
gap: 0;
background: rgb(var(--docs-color-secondary-1000));
min-width: 200px;
padding: 0.75rem;
border-right: 1px solid var(--docs-color-border);
}
.tech-menu-item {
display: flex;
align-items: flex-start;
gap: 0.6rem;
padding: 0.65rem 0.75rem;
border-radius: 8px;
cursor: pointer;
text-decoration: none !important;
color: var(--docs-color-text) !important;
border: 2px solid transparent;
transition: background 0.15s, border-color 0.15s;
}
.tech-menu-item:hover {
background: rgb(var(--docs-color-secondary-800) / 0.6);
border-color: transparent;
color: var(--docs-color-text) !important;
}
/* Active category item (matches dyte's left border style) */
body[data-tech-menu='backend'] [data-dropdown-tech-menu='backend'],
body[data-tech-menu='frontend'] [data-dropdown-tech-menu='frontend'],
body[data-tech-menu='algorithms'] [data-dropdown-tech-menu='algorithms'] {
border-left-color: #2160fd;
background: rgb(var(--docs-color-secondary-800) / 0.5);
}
.tech-menu-icon {
font-size: 1.2rem;
flex-shrink: 0;
margin-top: 0.1rem;
}
.tech-menu-item-title {
font-size: 0.875rem;
font-weight: 600;
line-height: 1.3;
color: var(--docs-color-text);
}
.tech-menu-item-desc {
font-size: 0.75rem;
color: var(--docs-color-text-100);
margin: 0;
line-height: 1.4;
}
/* Right Content Panel */
.tech-dropdown-right {
flex: 1;
padding: 1rem 1.25rem;
background: rgb(var(--docs-color-secondary-900));
}
/* Panel visibility: dyte's body data-attribute pattern */
[data-dropdown-tech] {
display: none;
}
.tech-panel-group {
min-width: 150px;
}
.tech-panel-heading {
font-size: 0.78rem !important;
font-weight: 700 !important;
text-transform: uppercase;
letter-spacing: 0.06em;
color: var(--docs-color-text-100) !important;
margin-bottom: 0.5rem !important;
margin-top: 0 !important;
}
.tech-panel-links {
list-style: none;
padding: 0;
margin: 0;
display: flex;
flex-direction: row;
flex-wrap: wrap;
gap: 0.2rem 0.4rem;
}
.tech-link {
display: flex;
align-items: center;
gap: 0.4rem;
padding: 0.35rem 0.5rem;
border-radius: 6px;
font-size: 0.84rem;
text-decoration: none !important;
color: var(--docs-color-text) !important;
transition: background 0.15s, color 0.15s;
}
.tech-link:hover {
background: rgba(33, 96, 253, 0.08);
color: #2160fd !important;
}
[data-theme='dark'] .tech-link:hover {
background: rgba(26, 144, 255, 0.1);
color: #1a90ff !important;
}
/* ══════════════════════════════════════════════════
Right panel: groups stack vertically, links flow horizontally
══════════════════════════════════════════════════ */
body:not([data-tech-menu]) [data-dropdown-tech='backend'],
body[data-tech-menu='backend'] [data-dropdown-tech='backend'],
body[data-tech-menu='frontend'] [data-dropdown-tech='frontend'],
body[data-tech-menu='algorithms'] [data-dropdown-tech='algorithms'] {
display: flex !important;
flex-direction: column;
gap: 1.25rem;
width: 100%;
}
/* ══════════════════════════════════════════════════
Sidebar: dyte-style collapse/expand button
══════════════════════════════════════════════════ */
aside.theme-doc-sidebar-container {
position: relative;
z-index: 2; /* ensure sidebar renders above main content */
clip-path: inset(0px -140px);
}
/* ── Collapse button (visible when sidebar is expanded) ── */
/* Title is translated to Chinese in zh-cn locale, so target both */
.theme-doc-sidebar-container button[title='Collapse sidebar'],
.theme-doc-sidebar-container button[title='收起侧边栏'] {
position: absolute;
top: 95vh;
right: -14px;
width: 28px;
height: 28px;
padding: 0;
border-radius: 4px;
z-index: 10;
background-size: 16px;
background-position: center;
background-repeat: no-repeat;
background-color: var(--docs-color-border);
border: none;
cursor: pointer;
background-image: url("data:image/svg+xml,%3Csvg width='24' height='24' fill='none' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M15.707 4.293a1 1 0 0 1 0 1.414L9.414 12l6.293 6.293a1 1 0 0 1-1.414 1.414l-7-7a1 1 0 0 1 0-1.414l7-7a1 1 0 0 1 1.414 0Z' fill='%23181818'/%3E%3C/svg%3E");
}
html[data-theme='dark'] .theme-doc-sidebar-container button[title='Collapse sidebar'],
html[data-theme='dark'] .theme-doc-sidebar-container button[title='收起侧边栏'] {
background-image: url("data:image/svg+xml,%3Csvg width='24' height='24' fill='none' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M15.707 4.293a1 1 0 0 1 0 1.414L9.414 12l6.293 6.293a1 1 0 0 1-1.414 1.414l-7-7a1 1 0 0 1 0-1.414l7-7a1 1 0 0 1 1.414 0Z' fill='%23ffffff'/%3E%3C/svg%3E");
}
/* ── Collapse button: hide Docusaurus default SVG (we use bg-image) ── */
.theme-doc-sidebar-container button[title='Collapse sidebar'] svg,
.theme-doc-sidebar-container button[title='收起侧边栏'] svg {
display: none;
}
/* ── Expand button (visible when sidebar is collapsed to 30px strip) ── */
/* Strategy: keep the div as full-area click target, use ::after for the visible icon */
.theme-doc-sidebar-container div[title='Expand sidebar'],
.theme-doc-sidebar-container div[title='展开侧边栏'] {
position: absolute !important;
top: 0 !important;
left: 0 !important;
right: 0 !important;
bottom: 0 !important;
width: 100% !important;
height: 100% !important;
background-image: none !important;
background-color: transparent !important;
display: flex !important;
align-items: flex-end !important;
justify-content: center !important;
padding-bottom: 5vh !important;
}
/* Visible icon at bottom of the strip */
.theme-doc-sidebar-container div[title='Expand sidebar']::after,
.theme-doc-sidebar-container div[title='展开侧边栏']::after {
content: '';
display: block;
width: 28px;
height: 28px;
flex-shrink: 0;
border-radius: 4px;
background-color: var(--docs-color-border);
background-size: 16px;
background-position: center;
background-repeat: no-repeat;
background-image: url("data:image/svg+xml,%3Csvg width='24' height='24' fill='none' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M8.293 4.293a1 1 0 0 0 0 1.414L14.586 12l-6.293 6.293a1 1 0 1 0 1.414 1.414l7-7a1 1 0 0 0 0-1.414l-7-7a1 1 0 0 0-1.414 0Z' fill='%23181818'/%3E%3C/svg%3E");
}
html[data-theme='dark'] .theme-doc-sidebar-container div[title='Expand sidebar']::after,
html[data-theme='dark'] .theme-doc-sidebar-container div[title='展开侧边栏']::after {
background-image: url("data:image/svg+xml,%3Csvg width='24' height='24' fill='none' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M8.293 4.293a1 1 0 0 0 0 1.414L14.586 12l-6.293 6.293a1 1 0 1 0 1.414 1.414l7-7a1 1 0 0 0 0-1.414l-7-7a1 1 0 0 0-1.414 0Z' fill='%23ffffff'/%3E%3C/svg%3E");
}
/* Hide the default SVG inside the expand div */
.theme-doc-sidebar-container div[title='Expand sidebar'] svg,
.theme-doc-sidebar-container div[title='展开侧边栏'] svg {
display: none;
}
/* ══════════════════════════════════════════════════
Sidebar enhancements
══════════════════════════════════════════════════ */
.menu__link {
border-radius: 4px 0 0 4px;
font-size: 14px;
}
ul.menu__list > li > a.menu__link--active {
border-right: 1px solid var(--ifm-color-primary);
}
/* ══════════════════════════════════════════════════
Footer tweaks — dyte-style dark palette
══════════════════════════════════════════════════ */
.footer,
.footer--dark {
background-color: #1c1c1c !important;
border-top: 1px solid #2e2e2e !important;
padding: 3rem 0 2rem;
color: #b4b4b4;
}
.footer__title {
font-size: 14px;
font-weight: normal;
color: #b4b4b4;
margin-bottom: 0.5rem;
}
.footer__item {
font-size: 14px;
font-weight: normal;
}
.footer__link-item {
color: #b4b4b4;
transition: color 0.15s;
}
.footer__link-item:hover {
text-decoration: none;
color: #ffffff;
}
.footer__copyright {
margin-top: 32px;
font-size: 14px;
color: #b4b4b4;
}
/* ══════════════════════════════════════════════════
Code block tweaks — dyte-style
══════════════════════════════════════════════════ */
/* Reference variable (used by details/admonitions) — do NOT use as pre background */
:root {
--docs-color-code-background: #f6f8fa;
--code-border-color: var(--docs-color-border);
}
html[data-theme='dark'] {
--docs-color-code-background: #1e1e1e;
}
/* Only add a border — let Prism theme control the background/colors */
pre.prism-code {
border: 1px solid var(--code-border-color);
}
/* Inline code */
code:not(pre code) {
background-color: var(--docs-color-background-200);
border: 1px solid var(--docs-color-border);
border-radius: 4px;
font-size: 0.88em;
padding: 0.1em 0.35em;
}
/* Code block title bar */
.codeBlockTitle_node_modules-\@docusaurus-theme-classic-lib-theme-CodeBlock-Content-styles-module {
background-color: var(--docs-color-background-100) !important;
border-bottom: 1px solid var(--code-border-color) !important;
font-size: 13px;
}
/* Details/Admonition code blocks */
details code {
background-color: var(--docs-color-background);
}
+408 -10
View File
@@ -1,10 +1,414 @@
/* stylelint-disable docusaurus/copyright-header */
/**
* CSS files with the .module.css suffix will be treated as CSS modules
* and scoped locally.
*/
/* ══════════════════════════════════════════════════════════
Homepage Wrapper
══════════════════════════════════════════════════════════ */
.homepageWrapper {
display: flex;
flex-direction: column;
}
/* ══════════════════════════════════════════════════════════
Hero Background — dyte's noise-bg with grid pattern
══════════════════════════════════════════════════════════ */
.heroBg {
padding-bottom: 4rem;
background-color: #fafafa;
background-image:
linear-gradient(rgba(33, 96, 253, 0.03) 1px, transparent 1px),
linear-gradient(90deg, rgba(33, 96, 253, 0.03) 1px, transparent 1px);
background-size: 40px 40px;
border-bottom: 1px solid var(--ifm-toc-border-color);
}
[data-theme='dark'] .heroBg {
background-color: #111;
background-image:
linear-gradient(rgba(33, 96, 253, 0.06) 1px, transparent 1px),
linear-gradient(90deg, rgba(33, 96, 253, 0.06) 1px, transparent 1px);
background-size: 40px 40px;
}
/* ══════════════════════════════════════════════════════════
Hero Top Section (title + subtitle)
══════════════════════════════════════════════════════════ */
.heroTop {
padding: 5rem 1.5rem 3rem;
text-align: center;
display: flex;
flex-direction: column;
align-items: center;
gap: 1rem;
}
.heroBadge {
display: inline-block;
padding: 0.3rem 0.9rem;
border-radius: 9999px;
border: 1px solid rgba(33, 96, 253, 0.35);
background: rgba(33, 96, 253, 0.08);
color: #2160fd;
font-size: 0.8rem;
font-weight: 600;
letter-spacing: 0.04em;
text-transform: uppercase;
}
[data-theme='dark'] .heroBadge {
background: rgba(33, 96, 253, 0.15);
color: #7a9eff;
border-color: rgba(33, 96, 253, 0.4);
}
.heroTitle {
font-size: 3.5rem;
font-weight: 800;
line-height: 1.1;
letter-spacing: -0.03em;
color: #0f172a;
margin: 0;
}
[data-theme='dark'] .heroTitle {
color: #f1f5f9;
}
.heroTitleAccent {
color: #2160fd;
}
[data-theme='dark'] .heroTitleAccent {
color: #7a9eff;
}
.heroSubtitle {
max-width: 560px;
font-size: 1.1rem;
line-height: 1.7;
color: #475569;
margin: 0;
}
[data-theme='dark'] .heroSubtitle {
color: #94a3b8;
}
.heroButtons {
display: flex;
gap: 0.75rem;
flex-wrap: wrap;
justify-content: center;
margin-top: 0.5rem;
}
.btnPrimary {
display: inline-flex;
align-items: center;
padding: 0.65rem 1.5rem;
border-radius: 8px;
background: #2160fd;
color: #fff !important;
font-weight: 600;
font-size: 0.95rem;
text-decoration: none !important;
transition: background 0.2s, transform 0.15s, box-shadow 0.2s;
box-shadow: 0 2px 12px rgba(33, 96, 253, 0.35);
}
.btnPrimary:hover {
background: #1442c4;
transform: translateY(-1px);
box-shadow: 0 4px 20px rgba(33, 96, 253, 0.45);
color: #fff !important;
}
.btnOutline {
display: inline-flex;
align-items: center;
padding: 0.65rem 1.5rem;
border-radius: 8px;
border: 1.5px solid #cbd5e1;
background: transparent;
color: #334155 !important;
font-weight: 600;
font-size: 0.95rem;
text-decoration: none !important;
transition: border-color 0.2s, color 0.2s, background 0.2s;
}
.btnOutline:hover {
border-color: #2160fd;
color: #2160fd !important;
background: rgba(33, 96, 253, 0.04);
}
[data-theme='dark'] .btnOutline {
border-color: #334155;
color: #cbd5e1 !important;
}
[data-theme='dark'] .btnOutline:hover {
border-color: #7a9eff;
color: #7a9eff !important;
}
/* ══════════════════════════════════════════════════════════
Hero Cards (dyte-style: dark bg + blue hover gradient)
══════════════════════════════════════════════════════════ */
.heroCards {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 1.25rem;
max-width: 1200px;
margin: 0 auto;
padding: 0 1.5rem;
}
/* The card itself is the <Link> */
.heroCard {
position: relative;
display: flex;
flex-direction: column;
justify-content: space-between;
width: 360px;
border-radius: 1.5rem; /* rounded-3xl */
border: 1px solid #e2e8f0; /* secondary-700 light */
background: #f8fafc; /* secondary-900 light */
overflow: hidden;
cursor: pointer;
text-decoration: none !important;
color: #0f172a !important;
transition: border-color 0.25s ease,
background 0.25s ease,
box-shadow 0.25s ease,
color 0.25s ease,
transform 0.2s ease;
}
[data-theme='dark'] .heroCard {
border-color: #1e293b; /* secondary-700 dark */
background: #0f172a; /* secondary-900 dark */
color: #f1f5f9 !important;
}
/* ── Hover State ───────────────────────────────────── */
.heroCard:hover {
border-color: #2160fd;
background: linear-gradient(
135deg,
rgba(33, 96, 253, 0.15) 0%,
transparent 60%
);
box-shadow: 0 0 0 1px rgba(33, 96, 253, 0.25),
0 8px 30px rgba(33, 96, 253, 0.12);
color: #2160fd !important;
transform: translateY(-3px);
}
[data-theme='dark'] .heroCard:hover {
background: linear-gradient(
135deg,
rgba(33, 96, 253, 0.25) 0%,
transparent 60%
);
}
.heroCardContent {
padding: 1.5rem;
display: flex;
flex-direction: column;
gap: 0.75rem;
flex: 1;
}
.heroCardHeader {
display: flex;
align-items: center;
gap: 0.75rem;
}
.heroCardEmoji {
font-size: 1.75rem;
line-height: 1;
width: 2.5rem;
height: 2.5rem;
display: flex;
align-items: center;
justify-content: center;
border-radius: 0.75rem;
background: rgba(33, 96, 253, 0.08);
flex-shrink: 0;
transition: background 0.25s, transform 0.2s;
}
.heroCard:hover .heroCardEmoji {
background: rgba(33, 96, 253, 0.18);
transform: scale(1.1);
}
.heroCardTitle {
font-size: 1.2rem;
font-weight: 700;
margin: 0;
color: #0f172a;
transition: color 0.25s;
}
[data-theme='dark'] .heroCardTitle {
color: #f1f5f9;
}
.heroCard:hover .heroCardTitle {
color: #2160fd;
}
[data-theme='dark'] .heroCard:hover .heroCardTitle {
color: #7a9eff;
}
.heroCardText {
font-size: 0.9rem;
line-height: 1.65;
color: #64748b;
margin: 0;
transition: color 0.25s;
}
[data-theme='dark'] .heroCardText {
color: #94a3b8;
}
.heroCard:hover .heroCardText {
color: #1e40af;
}
[data-theme='dark'] .heroCard:hover .heroCardText {
color: #93c5fd;
}
.heroCardTags {
display: flex;
flex-wrap: wrap;
gap: 0.4rem;
margin-top: 0.25rem;
}
.heroCardTag {
display: inline-block;
padding: 0.15rem 0.55rem;
border-radius: 4px;
background: rgba(33, 96, 253, 0.07);
color: #2160fd;
font-size: 0.72rem;
font-weight: 600;
transition: background 0.2s;
}
.heroCard:hover .heroCardTag {
background: rgba(33, 96, 253, 0.15);
}
[data-theme='dark'] .heroCardTag {
background: rgba(33, 96, 253, 0.12);
color: #7a9eff;
}
/* Arrow in top-right */
.heroCardArrow {
position: absolute;
top: 1.1rem;
right: 1.2rem;
font-size: 1.25rem;
opacity: 0;
transform: translate(6px, -6px);
color: #2160fd;
transition: opacity 0.25s, transform 0.25s;
}
.heroCard:hover .heroCardArrow {
opacity: 1;
transform: translate(0, 0);
}
/* ══════════════════════════════════════════════════════════
Feature Strip
══════════════════════════════════════════════════════════ */
.featuresStrip {
background: #fff;
border-bottom: 1px solid var(--ifm-toc-border-color);
padding: 2.5rem 1.5rem;
}
[data-theme='dark'] .featuresStrip {
background: #161616;
}
.featuresInner {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 1.5rem;
max-width: 1100px;
margin: 0 auto;
}
@media (max-width: 900px) {
.featuresInner {
grid-template-columns: repeat(2, 1fr);
}
}
@media (max-width: 480px) {
.featuresInner {
grid-template-columns: 1fr;
}
.heroCards {
flex-direction: column;
align-items: center;
}
.heroCard {
width: 100%;
max-width: 380px;
}
.heroTitle {
font-size: 2.2rem;
}
}
.featureItem {
display: flex;
align-items: flex-start;
gap: 0.8rem;
}
.featureIcon {
font-size: 1.6rem;
flex-shrink: 0;
margin-top: 0.1rem;
}
.featureTitle {
font-size: 0.9rem;
font-weight: 600;
color: #0f172a;
margin-bottom: 0.25rem;
}
[data-theme='dark'] .featureTitle {
color: #f1f5f9;
}
.featureDesc {
font-size: 0.8rem;
line-height: 1.5;
color: #64748b;
}
[data-theme='dark'] .featureDesc {
color: #94a3b8;
}
/* Legacy - kept for compatibility */
.heroBanner {
padding: 4rem 0;
text-align: center;
@@ -12,12 +416,6 @@
overflow: hidden;
}
@media screen and (max-width: 966px) {
.heroBanner {
padding: 2rem;
}
}
.buttons {
display: flex;
align-items: center;
+102 -38
View File
@@ -1,55 +1,119 @@
import React from 'react';
import clsx from 'clsx';
import Layout from '@theme/Layout';
import Link from '@docusaurus/Link';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import styles from './index.module.css';
import HomepageFeatures from '../components/HomepageFeatures';
function HomepageHeader(): JSX.Element {
const { siteConfig } = useDocusaurusContext();
/* ── Hero Cards ────────────────────────────────────────────── */
const HERO_CARDS = [
{
id: 'backend',
emoji: '⚙️',
title: '后端技术',
link: '/docs/backend-doc/intro-docs',
text: '深入讲解 Spring Boot / Spring Cloud 核心概念,微服务架构、分布式缓存与性能调优,含真实项目案例',
tags: ['Spring Boot', 'Spring Cloud', 'MySQL', 'Redis'],
},
{
id: 'frontend',
emoji: '⚛️',
title: '前端开发',
link: '/docs/frontend-doc/intro-docs',
text: '系统化学习 React / Vue 现代框架,工程化实践、状态管理与跨端开发,构建高质量前端应用',
tags: ['React', 'Vue 3', 'Vite', 'TypeScript'],
},
{
id: 'algorithms',
emoji: '🧠',
title: '算法与面试',
link: '/docs/LeetCode/intro-docs',
text: '精选 LeetCode 题解与数据结构深析,系统设计面试指南,快速突破大厂技术面试关卡',
tags: ['LeetCode', '数据结构', '系统设计', '剑指Offer'],
},
];
/* ── Feature List ───────────────────────────────────────────── */
const FEATURES = [
{ icon: '🔍', title: '全文搜索', desc: '集成 Algolia DocSearch,毫秒级检索,快速定位任意知识点' },
{ icon: '🌙', title: '深色模式', desc: '完整支持深色/浅色主题切换,护眼阅读体验' },
{ icon: '📱', title: '响应式设计', desc: '适配桌面、平板、手机,随时随地查阅技术文档' },
{ icon: '⚡', title: '持续更新', desc: '技术团队持续维护,同步最新技术栈与面试题解' },
];
function HeroCard({ emoji, title, link, text, tags }) {
return (
<header className={clsx('hero hero--primary', styles.heroBanner)}>
<div className="container">
<h1 className="hero__title">🚀 {siteConfig.title}</h1>
<p className="hero__subtitle">{siteConfig.tagline}</p>
<p style={{ fontSize: '0.95rem', color: 'rgba(0,0,0,0.6)', marginBottom: '1.5rem' }}>
<strong> + + </strong>
</p>
<div className={styles.buttons}>
<Link
className="button button--primary button--lg"
to="/docs/backend-doc/intro-docs">
</Link>
<Link
className="button button--secondary button--lg"
to="/docs/frontend-doc/intro-docs"
style={{ marginLeft: '1rem' }}>
</Link>
<Link
className="button button--outline button--lg"
to="/docs/LeetCode/intro-docs"
style={{ marginLeft: '1rem' }}>
🧠
</Link>
<Link to={link} className={styles.heroCard}>
<div className={styles.heroCardContent}>
<div className={styles.heroCardHeader}>
<span className={styles.heroCardEmoji}>{emoji}</span>
<h3 className={styles.heroCardTitle}>{title}</h3>
</div>
<p className={styles.heroCardText}>{text}</p>
<div className={styles.heroCardTags}>
{tags.map(tag => (
<span key={tag} className={styles.heroCardTag}>{tag}</span>
))}
</div>
</div>
<div className={styles.heroCardArrow}></div>
</Link>
);
}
function FeatureItem({ icon, title, desc }) {
return (
<div className={styles.featureItem}>
<span className={styles.featureIcon}>{icon}</span>
<div>
<div className={styles.featureTitle}>{title}</div>
<div className={styles.featureDesc}>{desc}</div>
</div>
</div>
</header>
);
}
export default function Home(): JSX.Element {
const { siteConfig } = useDocusaurusContext();
return (
<Layout
title={`Hello from ${siteConfig.title}`}
description="Description will go into a meta tag in <head />">
<HomepageHeader />
<main>
<HomepageFeatures />
</main>
title="CodeDocs — 全栈技术文档"
description="覆盖后端、前端、算法面试的一站式技术文档库,为全栈工程师打造"
wrapperClassName={styles.homepageWrapper}
>
{/* ── Hero ──────────────────────────────────────── */}
<div className={styles.heroBg}>
<section className={styles.heroTop}>
<span className={styles.heroBadge}></span>
<h1 className={styles.heroTitle}>
<span className={styles.heroTitleAccent}></span>
</h1>
<p className={styles.heroSubtitle}>
<strong> · · </strong>
</p>
<div className={styles.heroButtons}>
<Link className={styles.btnPrimary} to="/docs/backend-doc/intro-docs">
</Link>
<Link className={styles.btnOutline} to="/docs/intro-docs">
</Link>
</div>
</section>
{/* ── Hero Cards ────────────────────────────── */}
<section className={styles.heroCards}>
{HERO_CARDS.map(card => (
<HeroCard key={card.id} {...card} />
))}
</section>
</div>
{/* ── Feature Strip ────────────────────────────── */}
<section className={styles.featuresStrip}>
<div className={styles.featuresInner}>
{FEATURES.map(f => (
<FeatureItem key={f.title} {...f} />
))}
</div>
</section>
</Layout>
);
}
+184
View File
@@ -0,0 +1,184 @@
<div class="tech-dropdown">
<!-- Left Panel: Category Nav -->
<div class="tech-dropdown-left">
<a
href="/docs/backend-doc/intro-docs"
class="tech-menu-item"
data-dropdown-tech-menu="backend"
onmouseover="document.body.setAttribute('data-tech-menu','backend')"
onfocus="document.body.setAttribute('data-tech-menu','backend')"
>
<span class="tech-menu-icon">⚙️</span>
<div class="tech-menu-item-text">
<div class="tech-menu-item-title">后端技术</div>
<p class="tech-menu-item-desc">Spring Boot / Cloud · 数据库 · 分布式</p>
</div>
</a>
<a
href="/docs/frontend-doc/intro-docs"
class="tech-menu-item"
data-dropdown-tech-menu="frontend"
onmouseover="document.body.setAttribute('data-tech-menu','frontend')"
onfocus="document.body.setAttribute('data-tech-menu','frontend')"
>
<span class="tech-menu-icon">⚛️</span>
<div class="tech-menu-item-text">
<div class="tech-menu-item-title">前端开发</div>
<p class="tech-menu-item-desc">React · Vue · 工程化 · 跨端</p>
</div>
</a>
<a
href="/docs/LeetCode/intro-docs"
class="tech-menu-item"
data-dropdown-tech-menu="algorithms"
onmouseover="document.body.setAttribute('data-tech-menu','algorithms')"
onfocus="document.body.setAttribute('data-tech-menu','algorithms')"
>
<span class="tech-menu-icon">🧠</span>
<div class="tech-menu-item-text">
<div class="tech-menu-item-title">算法与面试</div>
<p class="tech-menu-item-desc">LeetCode · 数据结构 · 系统设计</p>
</div>
</a>
</div>
<!-- Right Panel: Links -->
<div class="tech-dropdown-right">
<!-- Backend -->
<div class="tech-panel" data-dropdown-tech="backend">
<div class="tech-panel-group">
<h3 class="tech-panel-heading">Spring 全家桶</h3>
<ul class="tech-panel-links">
<li><a href="/docs/backend-doc/SpringBoot/helloboot" class="tech-link">
<span>🌿</span> Spring Boot 入门
</a></li>
<li><a href="/docs/backend-doc/SpringCloud/hellocloud" class="tech-link">
<span>☁️</span> Spring Cloud 微服务
</a></li>
<li><a href="/docs/backend-doc/intro-docs" class="tech-link">
<span>📖</span> 后端文档总览
</a></li>
</ul>
</div>
<div class="tech-panel-group">
<h3 class="tech-panel-heading">数据库 &amp; 缓存</h3>
<ul class="tech-panel-links">
<li><a href="/docs/backend-doc/intro-docs" class="tech-link">
<span>🗄️</span> MySQL 核心
</a></li>
<li><a href="/docs/backend-doc/intro-docs" class="tech-link">
<span></span> Redis 实战
</a></li>
</ul>
</div>
<div class="tech-panel-group">
<h3 class="tech-panel-heading">并发 &amp; JVM</h3>
<ul class="tech-panel-links">
<li><a href="/docs/backend-doc/intro-docs" class="tech-link">
<span>🧵</span> 并发编程
</a></li>
<li><a href="/docs/backend-doc/intro-docs" class="tech-link">
<span></span> JVM 调优
</a></li>
</ul>
</div>
<div class="tech-panel-group">
<h3 class="tech-panel-heading">分布式</h3>
<ul class="tech-panel-links">
<li><a href="/docs/backend-doc/intro-docs" class="tech-link">
<span>🔗</span> 消息队列
</a></li>
<li><a href="/docs/backend-doc/intro-docs" class="tech-link">
<span>🏗️</span> 微服务治理
</a></li>
</ul>
</div>
</div>
<!-- Frontend -->
<div class="tech-panel" data-dropdown-tech="frontend">
<div class="tech-panel-group">
<h3 class="tech-panel-heading">核心框架</h3>
<ul class="tech-panel-links">
<li><a href="/docs/frontend-doc/React/helloreact" class="tech-link">
<span>⚛️</span> React 进阶
</a></li>
<li><a href="/docs/frontend-doc/Vue/hellovue" class="tech-link">
<span>💚</span> Vue 3 全指南
</a></li>
<li><a href="/docs/frontend-doc/intro-docs" class="tech-link">
<span>📖</span> 前端文档总览
</a></li>
</ul>
</div>
<div class="tech-panel-group">
<h3 class="tech-panel-heading">工程化实践</h3>
<ul class="tech-panel-links">
<li><a href="/docs/frontend-doc/intro-docs" class="tech-link">
<span></span> Vite / Webpack
</a></li>
<li><a href="/docs/frontend-doc/intro-docs" class="tech-link">
<span>📦</span> 构建与部署
</a></li>
</ul>
</div>
<div class="tech-panel-group">
<h3 class="tech-panel-heading">状态管理</h3>
<ul class="tech-panel-links">
<li><a href="/docs/frontend-doc/intro-docs" class="tech-link">
<span>🔄</span> Redux / Zustand
</a></li>
<li><a href="/docs/frontend-doc/intro-docs" class="tech-link">
<span>🍍</span> Pinia
</a></li>
</ul>
</div>
<div class="tech-panel-group">
<h3 class="tech-panel-heading">性能 &amp; 跨端</h3>
<ul class="tech-panel-links">
<li><a href="/docs/frontend-doc/intro-docs" class="tech-link">
<span>🚀</span> 性能优化
</a></li>
<li><a href="/docs/frontend-doc/intro-docs" class="tech-link">
<span>📱</span> 小程序 / RN
</a></li>
</ul>
</div>
</div>
<!-- Algorithms -->
<div class="tech-panel" data-dropdown-tech="algorithms">
<div class="tech-panel-group">
<h3 class="tech-panel-heading">LeetCode 题解</h3>
<ul class="tech-panel-links">
<li><a href="/docs/LeetCode/1 - 100/hello" class="tech-link">
<span>📝</span> 1-100 题
</a></li>
<li><a href="/docs/LeetCode/100 - 200/hello 100" class="tech-link">
<span>📝</span> 100-200 题
</a></li>
<li><a href="/docs/LeetCode/CodingInterviews/StackAndQueue/MaxValueOfQueue" class="tech-link">
<span>🎯</span> 剑指 Offer
</a></li>
</ul>
</div>
<div class="tech-panel-group">
<h3 class="tech-panel-heading">专项突破</h3>
<ul class="tech-panel-links">
<li><a href="/docs/LeetCode/intro-docs" class="tech-link">
<span>🏗️</span> 系统设计
</a></li>
<li><a href="/docs/LeetCode/intro-docs" class="tech-link">
<span>🧮</span> 数据结构
</a></li>
</ul>
</div>
</div>
</div>
</div>
-77
View File
@@ -1,77 +0,0 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
corePlugins: {
preflight: false,
},
darkMode: ['class', '[data-theme="dark"]'],
content: ['./src/**/*.{jsx,tsx,html}', './docs/**/*.{jsx,tsx,html}'],
theme: {
extend: {
colors: {
primary: {
50: '#f0f5ff',
100: '#e0ebff',
200: '#c5d9ff',
300: '#a3bdff',
400: '#7a99ff',
500: '#2160fd',
600: '#1e4fd4',
700: '#1939a8',
800: '#15278a',
900: '#121d70',
},
slate: {
50: '#f8fafc',
100: '#f1f5f9',
200: '#e2e8f0',
300: '#cbd5e1',
400: '#94a3b8',
500: '#64748b',
600: '#475569',
700: '#334155',
800: '#1e293b',
900: '#0f172a',
},
},
fontFamily: {
sans: ['Inter', 'system-ui', 'sans-serif'],
},
spacing: {
'1': '0.25rem',
'2': '0.5rem',
'3': '0.75rem',
'4': '1rem',
'6': '1.5rem',
'8': '2rem',
'12': '3rem',
'16': '4rem',
'20': '5rem',
'24': '6rem',
},
borderRadius: {
'sm': '0.375rem',
'md': '0.5rem',
'lg': '0.75rem',
'xl': '1rem',
'2xl': '1.5rem',
'3xl': '2rem',
},
boxShadow: {
'sm': '0 1px 2px 0 rgb(0 0 0 / 0.05)',
'md': '0 4px 6px -1px rgb(0 0 0 / 0.1)',
'lg': '0 10px 15px -3px rgb(0 0 0 / 0.1)',
'xl': '0 20px 25px -5px rgb(0 0 0 / 0.1)',
},
transitionProperty: {
'colors': 'color, background-color, border-color, text-decoration-color, fill, stroke',
'all': 'all',
},
transitionDuration: {
'200': '200ms',
'300': '300ms',
'500': '500ms',
},
},
},
plugins: [],
};