@coffic/cosy-ui 0.3.12 → 0.3.33

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.
@@ -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
  // 处理社交链接
@@ -237,29 +220,29 @@ const debugClasses = debug ? {
237
220
  };
238
221
  ---
239
222
 
240
- <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]}>
223
+ <footer class:list={["cosy:footer cosy:z-50 cosy:sm:footer-horizontal cosy:bg-base-200 cosy:text-base-content cosy:p-10", debugClasses.footer]}>
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>
@@ -1,14 +1,14 @@
1
1
  ---
2
2
  /**
3
3
  * Sidebar组件
4
- *
4
+ *
5
5
  * 用于文档页面的侧边栏导航
6
- *
6
+ *
7
7
  * @example
8
8
  * ```astro
9
9
  * ---
10
10
  * import Sidebar from './Sidebar.astro';
11
- *
11
+ *
12
12
  * const sidebarItems = [
13
13
  * { title: "入门", items: [
14
14
  * { href: "/docs/getting-started", text: "快速开始" },
@@ -16,104 +16,81 @@
16
16
  * ]}
17
17
  * ];
18
18
  * ---
19
- *
19
+ *
20
20
  * <Sidebar sidebarItems={sidebarItems} currentPath="/docs/getting-started" />
21
21
  * ```
22
22
  */
23
23
 
24
24
  import { isPathMatch } from '../../utils/path';
25
- import "../../app.css"
25
+ import Modal from '../display/Modal.astro';
26
+ import SidebarNav from './SidebarNav.astro';
27
+ import MenuIcon from '../icons/MenuIcon.astro';
28
+ import '../../app.css';
26
29
 
27
- export interface SidebarItem {
28
- href: string;
29
- text: string;
30
- items?: SidebarItem[];
31
- }
32
-
33
- export interface SidebarSection {
34
- title: string;
35
- items: SidebarItem[];
36
- }
30
+ import type { SidebarSection } from '../../types/layout';
37
31
 
38
32
  export interface Props {
39
- /**
40
- * 侧边栏项目
41
- */
42
- sidebarItems: SidebarSection[];
43
-
44
- /**
45
- * 当前路径
46
- */
47
- currentPath: string;
33
+ /**
34
+ * 侧边栏项目
35
+ */
36
+ sidebarItems: SidebarSection[];
37
+
38
+ /**
39
+ * 当前路径
40
+ */
41
+ currentPath: string;
42
+
43
+ /**
44
+ * 桌面端类名
45
+ */
46
+ class?: string;
47
+
48
+ /**
49
+ * 是否开启调试模式,显示边框
50
+ * @default false
51
+ */
52
+ debug?: boolean;
48
53
  }
49
54
 
50
- const { sidebarItems, currentPath } = Astro.props;
55
+ const { sidebarItems, currentPath, class: className, debug = false } = Astro.props;
56
+
57
+ const debugClass = debug ? 'cosy:border cosy:border-red-500' : '';
58
+
59
+ // 获取当前活动的一级导航项
60
+ const currentSection = sidebarItems.find((section) =>
61
+ section.items.some((item) => isPathMatch(currentPath, item.href))
62
+ );
51
63
  ---
52
64
 
53
- <aside class="cosy:w-64 cosy:border-r cosy:border-base-300 cosy:shrink-0">
54
- <nav class="cosy:p-4 cosy:sticky cosy:top-16">
55
- {sidebarItems.map((section: SidebarSection) => (
56
- <div class="cosy:mb-6">
57
- <h3 class="cosy:font-bold cosy:mb-2 cosy:text-base-content/70">{section.title}</h3>
58
- <ul class="cosy:menu cosy:bg-base-200 cosy:rounded-box cosy:w-56">
59
- {section.items.map((item: SidebarItem) => {
60
- const isActive = isPathMatch(currentPath, item.href);
61
- return (
62
- <li>
63
- <a
64
- href={item.href}
65
- class:list={[
66
- "cosy:hover:bg-base-300",
67
- { "cosy:menu-active": isActive }
68
- ]}
69
- >
70
- {item.text}
71
- </a>
72
- {item.items && (
73
- <ul>
74
- {item.items.map((subitem: SidebarItem) => {
75
- const isSubActive = isPathMatch(currentPath, subitem.href);
76
- return (
77
- <li>
78
- <a
79
- href={subitem.href}
80
- class:list={[
81
- "cosy:hover:bg-base-300",
82
- { "cosy:active": isSubActive }
83
- ]}
84
- >
85
- {subitem.text}
86
- </a>
87
- {subitem.items && (
88
- <ul>
89
- {subitem.items.map((subsubitem: SidebarItem) => {
90
- const isSubSubActive = isPathMatch(currentPath, subsubitem.href);
91
- return (
92
- <li>
93
- <a
94
- href={subsubitem.href}
95
- class:list={[
96
- "cosy:hover:bg-base-300",
97
- { "cosy:active": isSubSubActive }
98
- ]}
99
- >
100
- {subsubitem.text}
101
- </a>
102
- </li>
103
- );
104
- })}
105
- </ul>
106
- )}
107
- </li>
108
- );
109
- })}
110
- </ul>
111
- )}
112
- </li>
113
- );
114
- })}
115
- </ul>
116
- </div>
117
- ))}
118
- </nav>
119
- </aside>
65
+ {/* 移动端导航栏 */}
66
+ <div
67
+ class:list={[
68
+ 'cosy:flex cosy:lg:hidden cosy:items-center cosy:justify-between cosy:px-4 cosy:py-2 cosy:border-b cosy:border-base-300 cosy:bg-base-100 cosy:relative cosy:z-10',
69
+ debugClass,
70
+ ]}>
71
+ <div class="cosy:flex cosy:items-center cosy:gap-2">
72
+ <button
73
+ type="button"
74
+ class="cosy:p-2 cosy:btn cosy:btn-ghost cosy:btn-sm"
75
+ data-modal-target="mobile-sidebar">
76
+ <MenuIcon class="cosy:w-5 cosy:h-5" />
77
+ </button>
78
+ <span class="cosy:font-medium cosy:text-sm">
79
+ {currentSection?.title || '导航'}
80
+ </span>
81
+ </div>
82
+ </div>
83
+
84
+ {/* 移动端侧边栏弹出层 */}
85
+ <Modal id="mobile-sidebar" class="cosy:mx-4 cosy:lg:w-80 cosy:w-[calc(100vw-2rem)] cosy:max-w-full">
86
+ <div class="cosy:h-[calc(100vh-8rem)] cosy:overflow-y-auto">
87
+ <SidebarNav sidebarItems={sidebarItems} currentPath={currentPath} debug={debug} />
88
+ </div>
89
+ </Modal>
90
+
91
+ {/* 桌面端侧边栏 */}
92
+ <aside class:list={[className, debugClass, 'cosy:hidden cosy:lg:block']}>
93
+ <div class="cosy:top-16 cosy:sticky cosy:h-[calc(100vh-4rem)]">
94
+ <SidebarNav sidebarItems={sidebarItems} currentPath={currentPath} debug={debug} />
95
+ </div>
96
+ </aside>
@@ -0,0 +1,122 @@
1
+ ---
2
+ /**
3
+ * SidebarNav组件
4
+ *
5
+ * 用于渲染侧边栏的导航内容
6
+ */
7
+
8
+ import { isPathMatch } from '../../utils/path';
9
+ import "../../app.css"
10
+
11
+ export interface SidebarItem {
12
+ href: string;
13
+ text: string;
14
+ items?: SidebarItem[];
15
+ }
16
+
17
+ export interface SidebarSection {
18
+ title: string;
19
+ items: SidebarItem[];
20
+ }
21
+
22
+ interface Props {
23
+ /**
24
+ * 侧边栏项目
25
+ */
26
+ sidebarItems: SidebarSection[];
27
+
28
+ /**
29
+ * 当前路径
30
+ */
31
+ currentPath: string;
32
+
33
+ /**
34
+ * 是否开启调试模式,显示边框
35
+ * @default false
36
+ */
37
+ debug?: boolean;
38
+
39
+ /**
40
+ * 自定义类名
41
+ */
42
+ class?: string;
43
+ }
44
+
45
+ const {
46
+ sidebarItems,
47
+ currentPath,
48
+ debug = false,
49
+ class: className
50
+ } = Astro.props;
51
+
52
+ const debugClass = debug ? "cosy:border cosy:border-red-500" : "";
53
+ ---
54
+
55
+ <nav class:list={["cosy:p-4", debugClass, className]}>
56
+ {sidebarItems.map((section: SidebarSection) => (
57
+ <div class:list={["cosy:mb-6", debugClass]}>
58
+ <h3 class:list={["cosy:font-bold cosy:mb-2 cosy:text-base-content/70", debugClass]}>{section.title}</h3>
59
+ <ul class:list={["cosy:menu cosy:bg-base-200 cosy:rounded-box cosy:w-56", debugClass]}>
60
+ {section.items.map((item: SidebarItem) => {
61
+ const isActive = isPathMatch(currentPath, item.href);
62
+ return (
63
+ <li class:list={[debugClass]}>
64
+ <a
65
+ href={item.href}
66
+ class:list={[
67
+ "cosy:hover:bg-base-300",
68
+ { "cosy:menu-active": isActive },
69
+ debugClass
70
+ ]}
71
+ >
72
+ {item.text}
73
+ </a>
74
+ {item.items && (
75
+ <ul class:list={[debugClass]}>
76
+ {item.items.map((subitem: SidebarItem) => {
77
+ const isSubActive = isPathMatch(currentPath, subitem.href);
78
+ return (
79
+ <li class:list={[debugClass]}>
80
+ <a
81
+ href={subitem.href}
82
+ class:list={[
83
+ "cosy:hover:bg-base-300",
84
+ { "cosy:active": isSubActive },
85
+ debugClass
86
+ ]}
87
+ >
88
+ {subitem.text}
89
+ </a>
90
+ {subitem.items && (
91
+ <ul class:list={[debugClass]}>
92
+ {subitem.items.map((subsubitem: SidebarItem) => {
93
+ const isSubSubActive = isPathMatch(currentPath, subsubitem.href);
94
+ return (
95
+ <li class:list={[debugClass]}>
96
+ <a
97
+ href={subsubitem.href}
98
+ class:list={[
99
+ "cosy:hover:bg-base-300",
100
+ { "cosy:active": isSubSubActive },
101
+ debugClass
102
+ ]}
103
+ >
104
+ {subsubitem.text}
105
+ </a>
106
+ </li>
107
+ );
108
+ })}
109
+ </ul>
110
+ )}
111
+ </li>
112
+ );
113
+ })}
114
+ </ul>
115
+ )}
116
+ </li>
117
+ );
118
+ })}
119
+ </ul>
120
+ </div>
121
+ ))}
122
+ </nav>