@coffic/cosy-ui 0.3.10-beta.1 → 0.3.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -11,15 +11,16 @@
11
11
  * <p>内容将被包裹在一个合适的区块中</p>
12
12
  * </Section>
13
13
  *
14
- * <Section padding="lg" background="gray" centered={true}>
14
+ * <Section padding="lg" background="gray" centered={true} border={true}>
15
15
  * <h2>自定义区块</h2>
16
- * <p>大内边距,灰色背景,内容居中</p>
16
+ * <p>大内边距,灰色背景,内容居中,带边框</p>
17
17
  * </Section>
18
18
  * ```
19
19
  */
20
20
 
21
21
  import type { HTMLAttributes } from 'astro/types';
22
22
  import Container from './Container.astro';
23
+ import "../../app.css"
23
24
 
24
25
  interface Props extends HTMLAttributes<'section'> {
25
26
  /**
@@ -51,6 +52,12 @@ interface Props extends HTMLAttributes<'section'> {
51
52
  * @default false
52
53
  */
53
54
  centered?: boolean;
55
+
56
+ /**
57
+ * 是否显示边框
58
+ * @default false
59
+ */
60
+ border?: boolean;
54
61
 
55
62
  /**
56
63
  * 自定义类名
@@ -79,6 +86,7 @@ const {
79
86
  container = true,
80
87
  containerSize = 'md',
81
88
  centered = false,
89
+ border = false,
82
90
  class: className = '',
83
91
  'class:list': classList,
84
92
  id,
@@ -88,32 +96,33 @@ const {
88
96
 
89
97
  // 内边距映射
90
98
  const paddingClasses = {
91
- 'none': 'py-0',
92
- 'sm': 'py-6',
93
- 'md': 'py-12',
94
- 'lg': 'py-16',
95
- 'xl': 'py-24'
99
+ 'none': 'cosy:py-0',
100
+ 'sm': 'cosy:py-6',
101
+ 'md': 'cosy:py-12',
102
+ 'lg': 'cosy:py-16',
103
+ 'xl': 'cosy:py-24'
96
104
  };
97
105
 
98
106
  // 背景颜色映射
99
107
  const backgroundClasses = {
100
- 'transparent': 'bg-transparent',
101
- 'white': 'bg-white',
102
- 'gray': 'bg-gray-100',
103
- 'primary': 'bg-blue-50',
104
- 'secondary': 'bg-gray-50',
105
- 'dark': 'bg-gray-900 text-white'
108
+ 'transparent': 'cosy:bg-transparent',
109
+ 'white': 'cosy:bg-base-100',
110
+ 'gray': 'cosy:bg-base-200',
111
+ 'primary': 'cosy:bg-primary/10',
112
+ 'secondary': 'cosy:bg-secondary/10',
113
+ 'dark': 'cosy:bg-neutral cosy:text-neutral-content'
106
114
  };
107
115
 
108
116
  // 构建最终类名
109
117
  const sectionClasses = [
110
118
  paddingClasses[padding as keyof typeof paddingClasses],
111
119
  backgroundClasses[background as keyof typeof backgroundClasses],
120
+ border ? 'cosy:border cosy:rounded-lg' : '',
112
121
  className
113
122
  ].join(' ');
114
123
 
115
124
  // 内容类名
116
- const contentClasses = centered ? 'text-center' : '';
125
+ const contentClasses = centered ? 'cosy:text-center' : '';
117
126
  ---
118
127
 
119
128
  <section id={id} class:list={[sectionClasses, classList]} style={style} {...rest}>
@@ -127,19 +136,3 @@ const contentClasses = centered ? 'text-center' : '';
127
136
  </div>
128
137
  )}
129
138
  </section>
130
-
131
- <style>
132
- /* 背景颜色 */
133
- .bg-transparent { background-color: transparent; }
134
- .bg-white { background-color: #ffffff; }
135
- .bg-gray-50 { background-color: #f9fafb; }
136
- .bg-gray-100 { background-color: #f3f4f6; }
137
- .bg-blue-50 { background-color: #eff6ff; }
138
- .bg-gray-900 { background-color: #111827; }
139
-
140
- /* 文字颜色 */
141
- .text-white { color: #ffffff; }
142
-
143
- /* 文本对齐 */
144
- .text-center { text-align: center; }
145
- </style>
@@ -46,6 +46,7 @@
46
46
 
47
47
  // 导入样式
48
48
  import '../../app.css';
49
+ import Button from '../base/Button.astro';
49
50
 
50
51
  interface Props {
51
52
  /**
@@ -75,26 +76,32 @@ const {
75
76
  } = Astro.props;
76
77
  ---
77
78
 
78
- <dialog id={id} class="modal">
79
- <div class:list={["modal-box", className]}>
79
+ <dialog id={id} class="cosy:modal">
80
+ <div class:list={["cosy:modal-box", className]}>
80
81
  {showCloseButton && (
81
82
  <form method="dialog">
82
- <button class="modal-close-button">✕</button>
83
+ <Button
84
+ variant="ghost"
85
+ size="sm"
86
+ shape="circle"
87
+ formmethod="dialog"
88
+ class="cosy:modal-close-button"
89
+ >✕</Button>
83
90
  </form>
84
91
  )}
85
92
 
86
- {title && <h3 class="modal-title">{title}</h3>}
93
+ {title && <h3 class="cosy:modal-title">{title}</h3>}
87
94
 
88
- <div class="modal-content">
95
+ <div class="cosy:modal-content">
89
96
  <slot />
90
97
  </div>
91
98
 
92
- <div class="modal-action">
99
+ <div class="cosy:modal-action">
93
100
  <slot name="actions" />
94
101
  </div>
95
102
  </div>
96
103
 
97
- <form method="dialog" class="modal-backdrop">
104
+ <form method="dialog" class="cosy:modal-backdrop">
98
105
  <button>关闭</button>
99
106
  </form>
100
107
  </dialog>
@@ -1,4 +1,7 @@
1
1
  ---
2
+ /**
3
+ * 菜单图标组件
4
+ */
2
5
  interface Props {
3
6
  /**
4
7
  * 图标的大小
@@ -14,13 +17,9 @@ interface Props {
14
17
  * 自定义类名
15
18
  */
16
19
  class?: string;
17
- /**
18
- * 插槽名称
19
- */
20
- slot?: string;
21
20
  }
22
21
 
23
- const { size = '24px', color = 'currentColor', class: className = '', slot } = Astro.props;
22
+ const { size = '24px', color = 'currentColor', class: className = '' } = Astro.props;
24
23
  ---
25
24
 
26
25
  <svg
@@ -35,7 +34,5 @@ const { size = '24px', color = 'currentColor', class: className = '', slot } = A
35
34
  stroke-linejoin="round"
36
35
  class={className}
37
36
  >
38
- <line x1="3" y1="12" x2="21" y2="12" />
39
- <line x1="3" y1="6" x2="21" y2="6" />
40
- <line x1="3" y1="18" x2="21" y2="18" />
37
+ <path d="M4 6h16M4 12h16M4 18h16" />
41
38
  </svg>
@@ -4,6 +4,38 @@
4
4
  *
5
5
  * 适用于文档页面的布局,包含侧边栏导航和目录
6
6
  *
7
+ * 布局效果:
8
+ *
9
+ * 移动端:
10
+ * ```
11
+ * +------------------+
12
+ * | Header |
13
+ * +------------------+
14
+ * | Sidebar (1 line) |
15
+ * +------------------+
16
+ * | |
17
+ * | Main Content |
18
+ * | |
19
+ * | |
20
+ * +------------------+
21
+ * | Footer |
22
+ * +------------------+
23
+ * ```
24
+ *
25
+ * 桌面端:
26
+ * ```
27
+ * +------------------+
28
+ * | Header |
29
+ * +--------+---------+
30
+ * | | |
31
+ * |Sidebar | Content |
32
+ * | | |
33
+ * | | |
34
+ * +--------+---------+
35
+ * | Footer |
36
+ * +------------------+
37
+ * ```
38
+ *
7
39
  * @example
8
40
  * ```astro
9
41
  * ---
@@ -317,6 +349,12 @@ export interface Props {
317
349
  * 首页链接
318
350
  */
319
351
  footerHomeLink?: string;
352
+
353
+ /**
354
+ * 是否默认展开侧边栏(移动端)
355
+ * @default false
356
+ */
357
+ defaultSidebarOpen?: boolean;
320
358
  }
321
359
 
322
360
  const {
@@ -360,6 +398,7 @@ const {
360
398
  footerFaqLink,
361
399
  footerMediaLink,
362
400
  footerTechStackLink,
401
+ defaultSidebarOpen = false,
363
402
  ...rest
364
403
  } = Astro.props;
365
404
 
@@ -386,37 +425,38 @@ const validLang = getValidLanguage(currentLocale);
386
425
  currentLocale={currentLocale}
387
426
  sticky={true}
388
427
  basePath={basePath}
428
+ showSidebarToggle={true}
429
+ defaultSidebarOpen={defaultSidebarOpen}
389
430
  />
390
431
  )}
391
432
 
392
- {debug && (
393
- <div class="cosy:fixed cosy:top-2 cosy:right-2 cosy:badge cosy:badge-warning">
394
- 调试模式已启用
433
+ <div class="cosy:flex cosy:lg:flex-row cosy:flex-col cosy:flex-1">
434
+ <!-- 侧边栏容器 -->
435
+ <div class="cosy:top-16 cosy:z-10 cosy:sticky cosy:bg-base-100">
436
+ <Sidebar
437
+ sidebarItems={sidebarItems}
438
+ currentPath={currentPath}
439
+ debug={false}
440
+ class="cosy:lg:border-r cosy:border-b cosy:border-base-300 cosy:lg:border-b-0 cosy:lg:w-64 cosy:lg:shrink-0"
441
+ />
395
442
  </div>
396
- )}
397
-
398
- <div class="cosy:flex-1 cosy:flex">
399
- <Sidebar sidebarItems={sidebarItems} currentPath={currentPath} />
400
443
 
401
- <Main
402
- class="cosy:flex-1 cosy:py-8 cosy:min-h-screen"
403
- >
404
- <div class="cosy:container cosy:mx-auto cosy:px-4 cosy:flex cosy:gap-8">
405
- <Article >
406
- <slot />
407
- </Article>
408
-
409
- {showTableOfContents && (
410
- <div class="cosy:w-64 cosy:shrink-0">
411
- <div class="cosy:sticky cosy:top-16">
412
- <slot name="toc">
413
- <TableOfContents lang={currentLocale} />
414
- </slot>
415
- </div>
444
+ <!-- 主内容区域 -->
445
+ <div class="cosy:flex cosy:flex-col cosy:flex-1 cosy:items-center cosy:min-h-screen">
446
+ <Main class="cosy:lg:py-8 cosy:py-4 cosy:w-full">
447
+ <div class="cosy:mx-auto cosy:px-4 lg:cosy:px-8 cosy:container">
448
+ <div class="cosy:flex cosy:lg:flex-row cosy:flex-col cosy:justify-center cosy:gap-8">
449
+ <Article class="cosy:flex-1 xl:cosy:w-[calc(100%-16rem)]">
450
+ <slot />
451
+ </Article>
452
+
453
+ {showTableOfContents && (
454
+ <TableOfContents lang={currentLocale} />
455
+ )}
416
456
  </div>
417
- )}
418
- </div>
419
- </Main>
457
+ </div>
458
+ </Main>
459
+ </div>
420
460
  </div>
421
461
 
422
462
  {showFooter && (
@@ -447,4 +487,20 @@ const validLang = getValidLanguage(currentLocale);
447
487
  techStackLink={footerTechStackLink}
448
488
  />
449
489
  )}
490
+
491
+ <script>
492
+ // Handle sidebar toggle
493
+ const sidebarToggle = document.getElementById('sidebar-toggle');
494
+ const sidebar = document.getElementById('sidebar-mobile');
495
+ const sidebarOverlay = document.getElementById('sidebar-overlay');
496
+
497
+ function toggleSidebar() {
498
+ sidebar?.classList.toggle('cosy:hidden');
499
+ sidebarOverlay?.classList.toggle('cosy:hidden');
500
+ document.body.classList.toggle('cosy:overflow-hidden');
501
+ }
502
+
503
+ sidebarToggle?.addEventListener('click', toggleSidebar);
504
+ sidebarOverlay?.addEventListener('click', toggleSidebar);
505
+ </script>
450
506
  </BaseLayout>
@@ -146,11 +146,11 @@
146
146
  */
147
147
 
148
148
  import { processSocialLink } from '../../utils/social';
149
- import Link from '../base/Link.astro';
150
149
  import SocialIcon from '../icons/SocialIcon.astro';
151
150
  import type { FooterProps } from '../../types/footer';
152
- import { getCurrentLanguage, LanguageSource } from '../../utils/language';
151
+ import { getCurrentLanguage } from '../../utils/language';
153
152
  import { createTextGetter } from '../../utils/i18n';
153
+ import NavSection from './NavSection.astro';
154
154
 
155
155
  // 导入样式
156
156
  import '../../app.css';
@@ -194,7 +194,6 @@ const {
194
194
  techStackLink,
195
195
  debug = false,
196
196
  lang: userLang,
197
- enableLogging = false,
198
197
  }: Props = Astro.props;
199
198
 
200
199
  // 获取当前语言
@@ -202,22 +201,6 @@ const langInfo = getCurrentLanguage(userLang);
202
201
  // 创建文本获取函数
203
202
  const t = createTextGetter(langInfo, 'footer');
204
203
 
205
- // 获取语言来源的描述
206
- function getLanguageSourceDescription(source: LanguageSource): string {
207
- switch (source) {
208
- case LanguageSource.USER:
209
- return '用户指定';
210
- case LanguageSource.URL:
211
- return 'URL参数';
212
- case LanguageSource.BROWSER:
213
- return '浏览器设置';
214
- case LanguageSource.DEFAULT:
215
- return '默认语言';
216
- default:
217
- return '未知来源';
218
- }
219
- }
220
-
221
204
  const currentYear = new Date().getFullYear();
222
205
 
223
206
  // 处理社交链接
@@ -238,28 +221,28 @@ const debugClasses = debug ? {
238
221
  ---
239
222
 
240
223
  <footer class:list={["cosy:footer cosy:sm:footer-horizontal cosy:bg-base-200 cosy:text-base-content cosy:p-10", debugClasses.footer]}>
241
- <div class:list={["cosy:flex cosy:flex-col cosy:gap-8 cosy:container cosy:mx-auto cosy:items-center cosy:w-full cosy:md:flex-row cosy:md:justify-between", debugClasses.section]}>
224
+ <div class:list={["cosy:flex cosy:flex-col cosy:md:h-56 cosy:gap-8 cosy:container cosy:mx-auto cosy:items-center cosy:w-full cosy:md:flex-row cosy:md:justify-between", debugClasses.section]}>
242
225
  {/* 品牌区域 */}
243
- <aside class:list={["cosy:max-w-xs", debugClasses.aside]}>
244
- <a href={homeLink} class="cosy:flex cosy:items-center cosy:gap-2 cosy:mb-4">
226
+ <aside class:list={["cosy:max-w-xs cosy:text-center", debugClasses.aside]}>
227
+ <a href={homeLink} class="cosy:flex cosy:items-center cosy:gap-2 cosy:mb-4 cosy:no-underline">
245
228
  {logo && (
246
229
  <img
247
230
  src={logo.src}
248
231
  alt={logo.alt}
249
- class="cosy:mask cosy:mask-squircle cosy:w-12 cosy:h-12"
232
+ class="cosy:w-12 cosy:h-12 cosy:mask cosy:mask-squircle"
250
233
  width="48"
251
234
  height="48"
252
235
  />
253
236
  )}
254
237
  <div>
255
- <h2 class="cosy:text-xl cosy:font-bold">{siteName}</h2>
238
+ <h2 class="cosy:font-bold cosy:text-xl">{siteName}</h2>
256
239
  <p class="cosy:text-base-content/70">{slogan}</p>
257
240
  </div>
258
241
  </a>
259
242
 
260
243
  {/* 社交媒体链接 */}
261
244
  {processedSocialLinks.length > 0 && (
262
- <div class="cosy:flex cosy:gap-2 cosy:mt-4">
245
+ <div class="cosy:flex cosy:justify-center cosy:gap-2 cosy:mt-4">
263
246
  {processedSocialLinks.map((link) => (
264
247
  <a
265
248
  href={link.url}
@@ -276,49 +259,39 @@ const debugClasses = debug ? {
276
259
  </aside>
277
260
 
278
261
  {/* 导航区域 */}
279
- <div class:list={["cosy:flex cosy:flex-col cosy:gap-8 cosy:mx-auto cosy:max-w-xl cosy:text-center cosy:items-center cosy:w-full cosy:md:flex-row cosy:md:justify-between cosy:md:items-start", debugClasses.section]}>
262
+ <div class:list={["cosy:flex cosy:h-full cosy:flex-col cosy:justify-center cosy:gap-8 cosy:mx-auto cosy:max-w-xl cosy:text-center cosy:items-center cosy:w-full cosy:md:flex-row cosy:md:justify-between cosy:md:items-start", debugClasses.section]}>
280
263
  {/* 产品导航 */}
281
264
  {products.length > 0 && (
282
- <nav class:list={["cosy:flex cosy:flex-col cosy:gap-3 cosy:h-full cosy:self-start", debugClasses.nav]}>
283
- <h6 class="cosy:footer-title">{t('products')}</h6>
284
- {products.map((product) => (
285
- <Link href={product.href} external={product.external} size='sm' block animation='hover-lift'>
286
- {product.name}
287
- </Link>
288
- ))}
289
- </nav>
265
+ <NavSection title={t('products')} links={products} />
290
266
  )}
291
267
 
292
268
  {/* 关于导航 */}
293
269
  {(aboutLink || contactLink || teamLink || careersLink) && (
294
- <nav class:list={["cosy:flex cosy:flex-col cosy:gap-3 cosy:h-full cosy:self-start", debugClasses.nav]}>
295
- <h6 class="cosy:footer-title">{t('about')}</h6>
296
- {aboutLink && <Link href={aboutLink} block animation='hover-lift' size='sm'>{t('aboutUs')}</Link>}
297
- {teamLink && <Link href={teamLink} block animation='hover-lift' size='sm'>{t('team')}</Link>}
298
- {careersLink && <Link href={careersLink} block animation='hover-lift' size='sm'>{t('careers')}</Link>}
299
- {contactLink && <Link href={contactLink} block animation='hover-lift' size='sm'>{t('contactUs')}</Link>}
300
- </nav>
270
+ <NavSection title={t('about')} links={[
271
+ { name: t('aboutUs'), href: aboutLink },
272
+ { name: t('team'), href: teamLink },
273
+ { name: t('careers'), href: careersLink },
274
+ { name: t('contactUs'), href: contactLink }
275
+ ].filter(link => link.href)} />
301
276
  )}
302
277
 
303
278
  {/* 资源导航 */}
304
279
  {(newsLink || historyLink || partnersLink || blogLink || faqLink || mediaLink || techStackLink) && (
305
- <nav class:list={["cosy:flex cosy:flex-col cosy:gap-3 cosy:h-full cosy:self-start", debugClasses.nav]}>
306
- <h6 class="cosy:footer-title">{t('resources')}</h6>
307
- {newsLink && <Link href={newsLink} block animation='hover-lift' size='sm'>{t('news')}</Link>}
308
- {blogLink && <Link href={blogLink} block animation='hover-lift' size='sm'>{t('blog')}</Link>}
309
- {faqLink && <Link href={faqLink} block animation='hover-lift' size='sm'>{t('faq')}</Link>}
310
- {historyLink && <Link href={historyLink} block animation='hover-lift' size='sm'>{t('history')}</Link>}
311
- {techStackLink && <Link href={techStackLink} block animation='hover-lift' size='sm'>{t('techStack')}</Link>}
312
- </nav>
280
+ <NavSection title={t('resources')} links={[
281
+ { name: t('news'), href: newsLink },
282
+ { name: t('blog'), href: blogLink },
283
+ { name: t('faq'), href: faqLink },
284
+ { name: t('history'), href: historyLink },
285
+ { name: t('techStack'), href: techStackLink }
286
+ ].filter(link => link.href)} />
313
287
  )}
314
288
 
315
289
  {/* 法律导航 */}
316
290
  {(termsLink || privacyLink) && (
317
- <nav class:list={["cosy:flex cosy:flex-col cosy:gap-3 cosy:h-full cosy:self-start", debugClasses.nav]}>
318
- <h6 class="cosy:footer-title">{t('legal')}</h6>
319
- {termsLink && <Link href={termsLink} block animation='hover-lift' size='sm'>{t('terms')}</Link>}
320
- {privacyLink && <Link href={privacyLink} block animation='hover-lift' size='sm'>{t('privacy')}</Link>}
321
- </nav>
291
+ <NavSection title={t('legal')} links={[
292
+ { name: t('terms'), href: termsLink },
293
+ { name: t('privacy'), href: privacyLink }
294
+ ].filter(link => link.href)} />
322
295
  )}
323
296
  </div>
324
297
  </div>
@@ -334,32 +307,13 @@ const debugClasses = debug ? {
334
307
  {/* 底部版权信息 */}
335
308
  <div class:list={["cosy:footer cosy:footer-center cosy:p-4 cosy:bg-base-300 cosy:text-base-content", debugClasses.footer]}>
336
309
  <aside class:list={["cosy:items-center cosy:grid-flow-col", debugClasses.aside]}>
337
- <p class="cosy:text-sm cosy:opacity-70">
310
+ <p class="cosy:opacity-70 cosy:text-sm">
338
311
  © {currentYear} {company} - {copyright || t('allRightsReserved')}
339
312
  </p>
340
313
  {icp && (
341
- <p class="cosy:text-sm cosy:opacity-70 cosy:ml-4">
314
+ <p class="cosy:opacity-70 cosy:ml-4 cosy:text-sm">
342
315
  {icp}
343
316
  </p>
344
317
  )}
345
318
  </aside>
346
- </div>
347
-
348
- <script define:vars={{ langInfo, enableLogging }}>
349
- // 输出语言信息到控制台
350
- if (enableLogging) {
351
- console.log(`[Footer] 语言信息:`, {
352
- 语言代码: langInfo.code,
353
- 语言来源: langInfo.source,
354
- 来源描述: (() => {
355
- switch (langInfo.source) {
356
- case 'user': return '用户指定';
357
- case 'url': return 'URL参数';
358
- case 'browser': return '浏览器设置';
359
- case 'default': return '默认语言';
360
- default: return '未知来源';
361
- }
362
- })()
363
- });
364
- }
365
- </script>
319
+ </div>
@@ -1,7 +1,5 @@
1
1
  ---
2
- import SearchIcon from '../icons/SearchIcon.astro';
3
2
  import Link from '../base/Link.astro';
4
- import Button from '../base/Button.astro';
5
3
  import Image from '../base/Image.astro';
6
4
  import '../../app.css';
7
5
 
@@ -42,6 +40,16 @@ interface Props {
42
40
  * @default ""
43
41
  */
44
42
  basePath?: string;
43
+ /**
44
+ * 是否显示侧边栏切换按钮
45
+ * @default false
46
+ */
47
+ showSidebarToggle?: boolean;
48
+ /**
49
+ * 侧边栏是否默认展开
50
+ * @default false
51
+ */
52
+ defaultSidebarOpen?: boolean;
45
53
  }
46
54
 
47
55
  const {
@@ -54,7 +62,7 @@ const {
54
62
  { code: 'en', name: 'English' }
55
63
  ],
56
64
  currentLocale = 'zh-cn',
57
- basePath = ''
65
+ basePath = '',
58
66
  } = Astro.props;
59
67
 
60
68
  type NavItem = { href: string; label: string; match: (path: string) => boolean };
@@ -77,36 +85,18 @@ function getLanguageUrl(langCode: string) {
77
85
  ---
78
86
 
79
87
  <header class:list={[
80
- "cosy:navbar cosy:bg-accent/30 cosy:backdrop-blur cosy:border-base-200 cosy:z-50 cosy:w-full",
88
+ "cosy:navbar cosy:bg-accent/70 cosy:backdrop-blur cosy:border-base-200 cosy:z-50 cosy:w-full",
81
89
  { "cosy:fixed cosy:top-0": sticky }
82
90
  ]}>
83
91
  <div class="cosy:navbar-start">
84
- <!-- 移动端菜单 -->
85
- <div class="cosy:dropdown cosy:lg:hidden">
86
- <div tabindex="0" role="button" class="cosy:btn cosy:btn-ghost cosy:btn-circle">
87
- <svg xmlns="http://www.w3.org/2000/svg" class="cosy:h-5 cosy:w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
88
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h7" />
89
- </svg>
90
- </div>
91
- <ul tabindex="0" class="cosy:menu cosy:menu-sm cosy:dropdown-content cosy:mt-3 cosy:z-[1] cosy:p-2 cosy:shadow cosy:bg-base-100 cosy:rounded-box cosy:w-52">
92
- {navItems.map((item: NavItem) => (
93
- <li>
94
- <Link href={item.href}>
95
- {item.label}
96
- </Link>
97
- </li>
98
- ))}
99
- </ul>
100
- </div>
101
-
102
92
  <Link href={logoHref} class="cosy:btn cosy:btn-ghost">
103
93
  <Image src={logo} alt="logo" class="cosy:w-10 cosy:h-10" />
104
94
  </Link>
105
95
  </div>
106
96
 
107
- <!-- 桌面端导航 -->
108
- <div class="cosy:navbar-center cosy:hidden cosy:lg:flex">
109
- <ul class="cosy:menu cosy:menu-horizontal cosy:px-1">
97
+ <!-- 导航 -->
98
+ <div class="cosy:hidden cosy:lg:flex cosy:navbar-center">
99
+ <ul class="cosy:px-1 cosy:menu cosy:menu-horizontal">
110
100
  {navItems.map((item: NavItem) => (
111
101
  <li>
112
102
  <Link href={item.href}>
@@ -122,11 +112,11 @@ function getLanguageUrl(langCode: string) {
122
112
  <div class="cosy:dropdown cosy:dropdown-end">
123
113
  <div tabindex="0" role="button" class="cosy:btn cosy:btn-ghost cosy:btn-sm">
124
114
  <span class="cosy:mr-1">{currentLocale === 'zh-cn' ? '中文' : 'English'}</span>
125
- <svg xmlns="http://www.w3.org/2000/svg" class="cosy:h-4 cosy:w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
115
+ <svg xmlns="http://www.w3.org/2000/svg" class="cosy:w-4 cosy:h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
126
116
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
127
117
  </svg>
128
118
  </div>
129
- <ul tabindex="0" class="cosy:dropdown-content cosy:z-[1] cosy:menu cosy:p-2 cosy:shadow cosy:bg-base-100 cosy:rounded-box cosy:w-32">
119
+ <ul tabindex="0" class="cosy:z-[1] cosy:bg-base-100 cosy:shadow cosy:p-2 cosy:rounded-box cosy:w-32 cosy:dropdown-content cosy:menu">
130
120
  {languages.map((lang) => (
131
121
  <li class={currentLocale === lang.code ? "cosy:disabled" : ""}>
132
122
  <a href={getLanguageUrl(lang.code)} class={currentLocale === lang.code ? "cosy:active" : ""}>
@@ -0,0 +1,32 @@
1
+ ---
2
+ /**
3
+ * @component NavSection
4
+ *
5
+ * @description
6
+ * NavSection 组件用于在页脚中创建一个导航部分。
7
+ *
8
+ * @props
9
+ * @prop {string} title - 导航部分的标题
10
+ * @prop {Array<Object>} links - 链接数组,每个对象包含name、href和可选的external属性
11
+ *
12
+ */
13
+
14
+ import Link from '../base/Link.astro';
15
+
16
+ interface NavSectionProps {
17
+ title: string;
18
+ links: Array<{ name: string; href: string; external?: boolean }>;
19
+ }
20
+
21
+ const props = Astro.props as NavSectionProps;
22
+ const { title, links } = props;
23
+ ---
24
+
25
+ <nav class="cosy:flex cosy:flex-col cosy:items-center cosy:gap-3 cosy:hover:bg-base-300 cosy:hover:shadow-lg cosy:p-4 cosy:rounded cosy:h-full! cosy:hover:scale-105 cosy:transition-transform cosy:duration-300">
26
+ <h6 class="cosy:footer-title">{title}</h6>
27
+ {links.map((link) => (
28
+ <Link href={link.href} external={link.external} size='sm' block animation='hover-lift' centerText>
29
+ {link.name}
30
+ </Link>
31
+ ))}
32
+ </nav>