@coffic/cosy-ui 0.3.69 → 0.4.5
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.
- package/dist/app.css +1 -1
- package/dist/components/base/Alert.astro +3 -3
- package/dist/components/containers/Container.astro +80 -4
- package/dist/components/containers/Main.astro +41 -54
- package/dist/components/data-display/Blog.astro +1 -0
- package/dist/components/data-display/ProductCard.astro +0 -2
- package/dist/components/data-display/Products.astro +0 -2
- package/dist/components/data-display/TeamMember.astro +0 -2
- package/dist/components/data-display/TeamMembers.astro +0 -2
- package/dist/components/display/Banner.astro +0 -1
- package/dist/components/display/Card.astro +0 -1
- package/dist/components/display/CodeBlock.astro +0 -1
- package/dist/components/display/CodeExample.astro +0 -1
- package/dist/components/display/Modal.astro +65 -67
- package/dist/components/layouts/AppLayout.astro +258 -0
- package/dist/components/layouts/BaseLayout.astro +46 -92
- package/dist/components/layouts/DashboardLayout.astro +615 -604
- package/dist/components/layouts/Footer.astro +141 -113
- package/dist/components/layouts/Header.astro +11 -292
- package/dist/components/layouts/Sidebar.astro +54 -31
- package/dist/components/layouts/SidebarNav.astro +1 -11
- package/dist/components/typography/Article.astro +8 -30
- package/dist/index.ts +7 -4
- package/dist/types/article.ts +22 -0
- package/dist/types/footer.ts +119 -22
- package/dist/types/header.ts +70 -0
- package/dist/types/layout.ts +71 -10
- package/dist/types/main.ts +69 -0
- package/dist/types/meta.ts +50 -0
- package/dist/types/sidebar.ts +38 -0
- package/package.json +2 -2
- package/dist/components/layouts/DefaultLayout.astro +0 -170
- package/dist/components/layouts/DocumentationLayout.astro +0 -624
- package/dist/components/layouts/LandingLayout.astro +0 -388
@@ -47,58 +47,12 @@
|
|
47
47
|
* </Main>
|
48
48
|
* ```
|
49
49
|
*/
|
50
|
-
|
51
|
-
import Container from './Container.astro';
|
52
|
-
|
53
|
-
// 导入样式
|
54
50
|
import '../../app.css';
|
51
|
+
import type { MainContentProps } from '../../index';
|
52
|
+
import Article from '../typography/Article.astro';
|
53
|
+
import TableOfContents from '../navigation/TableOfContents.astro';
|
55
54
|
|
56
|
-
export interface Props {
|
57
|
-
/**
|
58
|
-
* 容器大小
|
59
|
-
* @default "md"
|
60
|
-
*/
|
61
|
-
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'full';
|
62
|
-
|
63
|
-
/**
|
64
|
-
* 水平内边距(通过 Container 组件的 padding 属性设置)
|
65
|
-
* @default "md"
|
66
|
-
*/
|
67
|
-
padding?: 'none' | 'sm' | 'md' | 'lg' | 'xl';
|
68
|
-
|
69
|
-
/**
|
70
|
-
* 垂直内边距
|
71
|
-
* @default "md"
|
72
|
-
*/
|
73
|
-
verticalPadding?: 'none' | 'sm' | 'md' | 'lg' | 'xl' | string;
|
74
|
-
|
75
|
-
/**
|
76
|
-
* 是否居中显示内容
|
77
|
-
* @default true
|
78
|
-
*/
|
79
|
-
centered?: boolean;
|
80
|
-
|
81
|
-
/**
|
82
|
-
* 背景颜色
|
83
|
-
* @default undefined
|
84
|
-
*/
|
85
|
-
backgroundColor?: 'primary' | 'secondary' | 'tertiary' | 'light' | 'dark' | string;
|
86
|
-
|
87
|
-
/**
|
88
|
-
* HTML id 属性
|
89
|
-
*/
|
90
|
-
id?: string;
|
91
|
-
|
92
|
-
/**
|
93
|
-
* 类名
|
94
|
-
*/
|
95
|
-
class?: string;
|
96
|
-
|
97
|
-
/**
|
98
|
-
* 类名列表
|
99
|
-
*/
|
100
|
-
'class:list'?: any;
|
101
|
-
}
|
55
|
+
export interface Props extends MainContentProps {}
|
102
56
|
|
103
57
|
const {
|
104
58
|
size = 'md',
|
@@ -106,19 +60,37 @@ const {
|
|
106
60
|
verticalPadding = 'md',
|
107
61
|
centered = true,
|
108
62
|
backgroundColor,
|
63
|
+
layout = 'row',
|
64
|
+
isArticle = false,
|
109
65
|
id,
|
66
|
+
showTableOfContents = false,
|
110
67
|
class: className,
|
111
68
|
'class:list': classList,
|
69
|
+
currentLocale,
|
112
70
|
...rest
|
113
71
|
} = Astro.props;
|
114
72
|
|
73
|
+
// 新增获取布局类的函数
|
74
|
+
function getLayoutClasses(layout: string) {
|
75
|
+
if (layout === 'row') return 'cosy:flex cosy:flex-row';
|
76
|
+
if (layout === 'column') return 'cosy:flex cosy:flex-col';
|
77
|
+
return 'cosy:flex cosy:flex-col'; // 默认列布局
|
78
|
+
}
|
79
|
+
|
80
|
+
const layoutClass = getLayoutClasses(layout as string);
|
81
|
+
|
115
82
|
// 获取垂直内边距的Tailwind类
|
116
83
|
function getVerticalPaddingClasses(padding: string) {
|
117
84
|
if (padding === 'none') return 'cosy:py-0';
|
85
|
+
if (padding === 'xs') return 'cosy:py-1';
|
118
86
|
if (padding === 'sm') return 'cosy:py-2';
|
119
87
|
if (padding === 'md') return 'cosy:py-4';
|
120
88
|
if (padding === 'lg') return 'cosy:py-6';
|
121
89
|
if (padding === 'xl') return 'cosy:py-8';
|
90
|
+
if (padding === '2xl') return 'cosy:py-10';
|
91
|
+
if (padding === '3xl') return 'cosy:py-12';
|
92
|
+
if (padding === '4xl') return 'cosy:py-16';
|
93
|
+
if (padding === '5xl') return 'cosy:py-20';
|
122
94
|
return ''; // 对于自定义padding,使用内联样式
|
123
95
|
}
|
124
96
|
|
@@ -153,10 +125,25 @@ const inlineStyle = customStyle.length > 0 ? customStyle.join(' ') : undefined;
|
|
153
125
|
|
154
126
|
<main
|
155
127
|
id={id}
|
156
|
-
class:list={[
|
128
|
+
class:list={[
|
129
|
+
'cosy:w-full',
|
130
|
+
layoutClass,
|
131
|
+
verticalPaddingClass,
|
132
|
+
bgColorClass,
|
133
|
+
className,
|
134
|
+
classList,
|
135
|
+
]}
|
157
136
|
style={inlineStyle}
|
158
137
|
{...rest}>
|
159
|
-
|
160
|
-
|
161
|
-
|
138
|
+
{
|
139
|
+
isArticle ? (
|
140
|
+
<Article>
|
141
|
+
<slot />
|
142
|
+
</Article>
|
143
|
+
) : (
|
144
|
+
<slot />
|
145
|
+
)
|
146
|
+
}
|
147
|
+
|
148
|
+
{showTableOfContents && <TableOfContents lang={currentLocale} />}
|
162
149
|
</main>
|
@@ -1,18 +1,18 @@
|
|
1
1
|
---
|
2
2
|
/**
|
3
3
|
* @component Modal
|
4
|
-
*
|
4
|
+
*
|
5
5
|
* @description
|
6
6
|
* Modal 组件是一个模态对话框,用于在不离开当前页面的情况下显示内容、通知或请求用户输入。
|
7
7
|
* 它会覆盖在页面内容上方,并提供一个聚焦的交互环境。
|
8
|
-
*
|
8
|
+
*
|
9
9
|
* @design
|
10
10
|
* 设计理念:
|
11
11
|
* 1. 聚焦交互 - 通过遮罩层和动画效果引导用户注意力
|
12
12
|
* 2. 灵活布局 - 支持标题、内容和操作按钮的灵活组合
|
13
13
|
* 3. 可访问性 - 支持键盘导航和屏幕阅读器
|
14
14
|
* 4. 响应式设计 - 在不同屏幕尺寸下保持良好的用户体验
|
15
|
-
*
|
15
|
+
*
|
16
16
|
* @usage
|
17
17
|
* 基本用法:
|
18
18
|
* ```astro
|
@@ -20,11 +20,11 @@
|
|
20
20
|
* <p>这是一个模态对话框的内容。</p>
|
21
21
|
* <button slot="actions" data-modal-target="my-modal">关闭</button>
|
22
22
|
* </Modal>
|
23
|
-
*
|
23
|
+
*
|
24
24
|
* <!-- 触发按钮 -->
|
25
25
|
* <button data-modal-target="my-modal">打开模态框</button>
|
26
26
|
* ```
|
27
|
-
*
|
27
|
+
*
|
28
28
|
* 自定义操作按钮:
|
29
29
|
* ```astro
|
30
30
|
* <Modal id="confirm-modal" title="确认操作">
|
@@ -35,7 +35,7 @@
|
|
35
35
|
* </div>
|
36
36
|
* </Modal>
|
37
37
|
* ```
|
38
|
-
*
|
38
|
+
*
|
39
39
|
* 不带标题的模态框:
|
40
40
|
* ```astro
|
41
41
|
* <Modal id="image-modal">
|
@@ -44,79 +44,77 @@
|
|
44
44
|
* ```
|
45
45
|
*/
|
46
46
|
|
47
|
-
// 导入样式
|
48
47
|
import '../../app.css';
|
49
48
|
import Button from '../base/Button.astro';
|
50
49
|
|
51
50
|
interface Props {
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
51
|
+
/**
|
52
|
+
* Modal 的唯一标识符
|
53
|
+
*/
|
54
|
+
id: string;
|
55
|
+
/**
|
56
|
+
* 模态框的标题
|
57
|
+
*/
|
58
|
+
title?: string;
|
59
|
+
/**
|
60
|
+
* 是否显示关闭按钮
|
61
|
+
* @default true
|
62
|
+
*/
|
63
|
+
showCloseButton?: boolean;
|
64
|
+
/**
|
65
|
+
* 自定义类名
|
66
|
+
*/
|
67
|
+
class?: string;
|
69
68
|
}
|
70
69
|
|
71
|
-
const {
|
72
|
-
id,
|
73
|
-
title,
|
74
|
-
showCloseButton = true,
|
75
|
-
class: className = '',
|
76
|
-
} = Astro.props;
|
70
|
+
const { id, title, showCloseButton = true, class: className = '' } = Astro.props;
|
77
71
|
---
|
78
72
|
|
79
73
|
<dialog id={id} class="cosy:modal">
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
<div class="cosy:modal-content">
|
96
|
-
<slot />
|
97
|
-
</div>
|
74
|
+
<div class:list={['cosy:modal-box', className]}>
|
75
|
+
{
|
76
|
+
showCloseButton && (
|
77
|
+
<form method="dialog">
|
78
|
+
<Button
|
79
|
+
variant="ghost"
|
80
|
+
size="sm"
|
81
|
+
shape="circle"
|
82
|
+
formmethod="dialog"
|
83
|
+
class="cosy:modal-close-button">
|
84
|
+
✕
|
85
|
+
</Button>
|
86
|
+
</form>
|
87
|
+
)
|
88
|
+
}
|
98
89
|
|
99
|
-
|
100
|
-
<slot name="actions" />
|
101
|
-
</div>
|
102
|
-
</div>
|
90
|
+
{title && <h3 class="cosy:modal-title">{title}</h3>}
|
103
91
|
|
104
|
-
|
105
|
-
|
106
|
-
|
92
|
+
<div class="cosy:modal-content">
|
93
|
+
<slot />
|
94
|
+
</div>
|
95
|
+
|
96
|
+
<div class="cosy:modal-action">
|
97
|
+
<slot name="actions" />
|
98
|
+
</div>
|
99
|
+
</div>
|
100
|
+
|
101
|
+
<form method="dialog" class="cosy:modal-backdrop">
|
102
|
+
<button>关闭</button>
|
103
|
+
</form>
|
107
104
|
</dialog>
|
108
105
|
|
109
106
|
<script define:vars={{ id }}>
|
110
|
-
// 为了方便使用,我们提供一些辅助方法
|
111
|
-
document.addEventListener('DOMContentLoaded', () => {
|
112
|
-
|
113
|
-
|
107
|
+
// 为了方便使用,我们提供一些辅助方法
|
108
|
+
document.addEventListener('DOMContentLoaded', () => {
|
109
|
+
const modal = document.getElementById(id);
|
110
|
+
if (!modal) return;
|
111
|
+
|
112
|
+
// 为所有触发这个模态框的按钮添加点击事件
|
113
|
+
document.querySelectorAll(`[data-modal-target="${id}"]`).forEach((trigger) => {
|
114
|
+
trigger.addEventListener('click', () => {
|
115
|
+
modal.showModal();
|
116
|
+
});
|
117
|
+
});
|
118
|
+
});
|
119
|
+
</script>
|
114
120
|
|
115
|
-
// 为所有触发这个模态框的按钮添加点击事件
|
116
|
-
document.querySelectorAll(`[data-modal-target="${id}"]`).forEach(trigger => {
|
117
|
-
trigger.addEventListener('click', () => {
|
118
|
-
modal.showModal();
|
119
|
-
});
|
120
|
-
});
|
121
|
-
});
|
122
|
-
</script>
|
@@ -0,0 +1,258 @@
|
|
1
|
+
---
|
2
|
+
/**
|
3
|
+
* AppLayout组件
|
4
|
+
*
|
5
|
+
* 适用于页面布局,包含侧边栏导航和目录
|
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
|
+
*
|
39
|
+
* @param {Object} sidebarConfig - 侧边栏配置
|
40
|
+
* @param {boolean} [showHeader=true] - 是否显示头部
|
41
|
+
* @param {boolean} [showFooter=true] - 是否显示页脚
|
42
|
+
* @param {boolean} [showSidebar=true] - 是否显示侧边栏
|
43
|
+
* @param {string} [className] - 自定义类名
|
44
|
+
* @param {Array} [classList] - 自定义类名列表
|
45
|
+
* @param {boolean} [debug=true] - 是否启用调试模式
|
46
|
+
* @param {Object} mainContentConfig - 主内容区域配置
|
47
|
+
* @param {Object} footerConfig - 页脚配置
|
48
|
+
* @param {Object} headerConfig - 头部配置
|
49
|
+
* @param {Object} metaConfig - 元数据配置
|
50
|
+
* @param {Object} rest - 其他属性
|
51
|
+
*
|
52
|
+
* @example
|
53
|
+
* ```astro
|
54
|
+
* ---
|
55
|
+
* import AppLayout from '../layouts/AppLayout.astro';
|
56
|
+
*
|
57
|
+
* const sidebarItems = [
|
58
|
+
* { title: "入门", items: [
|
59
|
+
* { href: "/docs/getting-started", text: "快速开始" },
|
60
|
+
* { href: "/docs/installation", text: "安装" }
|
61
|
+
* ]},
|
62
|
+
* { title: "组件", items: [
|
63
|
+
* { href: "/docs/components/button", text: "Button 按钮" },
|
64
|
+
* { href: "/docs/components/card", text: "Card 卡片" }
|
65
|
+
* ]}
|
66
|
+
* ];
|
67
|
+
* ---
|
68
|
+
*
|
69
|
+
* <AppLayout
|
70
|
+
* metaConfig={{
|
71
|
+
* title: "文档标题",
|
72
|
+
* description: "文档描述"
|
73
|
+
* }}
|
74
|
+
* sidebarConfig={{
|
75
|
+
* sidebarItems: sidebarItems
|
76
|
+
* }}
|
77
|
+
* >
|
78
|
+
* <h1>文档内容</h1>
|
79
|
+
* <p>这是文档的主要内容</p>
|
80
|
+
* </AppLayout>
|
81
|
+
* ```
|
82
|
+
*
|
83
|
+
* 自定义页脚示例:
|
84
|
+
* ```astro
|
85
|
+
* <AppLayout
|
86
|
+
* metaConfig={{
|
87
|
+
* title: "文档标题",
|
88
|
+
* description: "文档描述"
|
89
|
+
* }}
|
90
|
+
* sidebarConfig={{
|
91
|
+
* sidebarItems: sidebarItems
|
92
|
+
* }}
|
93
|
+
* footerConfig={{
|
94
|
+
* slogan: "简单而强大的组件库",
|
95
|
+
* inspirationalSlogan: "让开发更加愉悦",
|
96
|
+
* socialLinks: [
|
97
|
+
* "https://github.com/myorg/myrepo",
|
98
|
+
* "https://twitter.com/myorg"
|
99
|
+
* ],
|
100
|
+
* products: [
|
101
|
+
* { name: "组件库", href: "/components" },
|
102
|
+
* { name: "模板", href: "/templates" }
|
103
|
+
* ]
|
104
|
+
* }}
|
105
|
+
* >
|
106
|
+
* <h1>文档内容</h1>
|
107
|
+
* <p>这是文档的主要内容</p>
|
108
|
+
* </AppLayout>
|
109
|
+
* ```
|
110
|
+
*
|
111
|
+
* 组件支持多种页脚相关的配置参数,可以通过以 `footer` 为前缀的属性来自定义页脚的内容和链接。
|
112
|
+
* 所有这些参数都是可选的,组件会为常用参数提供默认值。
|
113
|
+
*
|
114
|
+
* 全宽内容区域示例:
|
115
|
+
* ```astro
|
116
|
+
* <AppLayout
|
117
|
+
* metaConfig={{
|
118
|
+
* title: "文档标题",
|
119
|
+
* description: "文档描述"
|
120
|
+
* }}
|
121
|
+
* sidebarConfig={{
|
122
|
+
* sidebarItems: sidebarItems
|
123
|
+
* }}
|
124
|
+
* mainContentConfig={{
|
125
|
+
* fullWidth: true
|
126
|
+
* }}
|
127
|
+
* >
|
128
|
+
* <!-- 全宽Hero部分,无需容器限制 -->
|
129
|
+
* <div class="cosy:bg-primary cosy:p-10 cosy:text-white cosy:text-center">
|
130
|
+
* <h1 class="cosy:text-3xl">全宽Hero部分</h1>
|
131
|
+
* <p class="cosy:mt-4">没有容器限制,宽度可以100%占满</p>
|
132
|
+
* </div>
|
133
|
+
*
|
134
|
+
* <!-- 自定义容器部分 -->
|
135
|
+
* <div class="cosy:mx-auto cosy:p-6 cosy:container">
|
136
|
+
* <p>在全宽模式下,您可以自行控制内容的容器和间距</p>
|
137
|
+
* <p>这使得创建全宽背景的同时,保持内容在合适的宽度内</p>
|
138
|
+
* </div>
|
139
|
+
*
|
140
|
+
* <!-- 另一个全宽部分 -->
|
141
|
+
* <div class="cosy:bg-accent cosy:mt-8 cosy:p-10">
|
142
|
+
* <div class="cosy:mx-auto cosy:container">
|
143
|
+
* <h2 class="cosy:text-2xl">灵活的布局</h2>
|
144
|
+
* <p>您可以自由组合全宽区域和容器限制区域</p>
|
145
|
+
* </div>
|
146
|
+
* </div>
|
147
|
+
* </AppLayout>
|
148
|
+
* ```
|
149
|
+
*
|
150
|
+
* 调试模式示例:
|
151
|
+
* ```astro
|
152
|
+
* <AppLayout
|
153
|
+
* metaConfig={{
|
154
|
+
* title: "文档标题",
|
155
|
+
* description: "文档描述"
|
156
|
+
* }}
|
157
|
+
* sidebarConfig={{
|
158
|
+
* sidebarItems: sidebarItems
|
159
|
+
* }}
|
160
|
+
* debug={true}
|
161
|
+
* >
|
162
|
+
* <h1>文档内容</h1>
|
163
|
+
* <p>这是文档的主要内容</p>
|
164
|
+
* </AppLayout>
|
165
|
+
* ```
|
166
|
+
*/
|
167
|
+
|
168
|
+
import '../../app.css';
|
169
|
+
import BaseLayout from './BaseLayout.astro';
|
170
|
+
import Footer from './Footer.astro';
|
171
|
+
import Main from '../containers/Main.astro';
|
172
|
+
import Header from './Header.astro';
|
173
|
+
import Sidebar from './Sidebar.astro';
|
174
|
+
import { ClientRouter } from 'astro:transitions';
|
175
|
+
import type { AppLayoutProps } from '../../index';
|
176
|
+
import Container from '../containers/Container.astro';
|
177
|
+
|
178
|
+
interface Props extends AppLayoutProps {}
|
179
|
+
|
180
|
+
const {
|
181
|
+
sidebarConfig,
|
182
|
+
showHeader = true,
|
183
|
+
showFooter = true,
|
184
|
+
showSidebar = true,
|
185
|
+
class: className,
|
186
|
+
'class:list': classList,
|
187
|
+
debug = true,
|
188
|
+
mainContentConfig,
|
189
|
+
footerConfig,
|
190
|
+
headerConfig,
|
191
|
+
metaConfig,
|
192
|
+
...rest
|
193
|
+
}: Props = Astro.props;
|
194
|
+
---
|
195
|
+
|
196
|
+
<BaseLayout
|
197
|
+
title={metaConfig.title}
|
198
|
+
description={metaConfig.description}
|
199
|
+
keywords={metaConfig.keywords}
|
200
|
+
author={metaConfig.author}
|
201
|
+
robots={metaConfig.robots}
|
202
|
+
head={metaConfig.head}
|
203
|
+
debug={debug}
|
204
|
+
{...rest}>
|
205
|
+
{
|
206
|
+
showHeader && (
|
207
|
+
<Header
|
208
|
+
logo={headerConfig.logo}
|
209
|
+
logoHref={headerConfig.logoHref}
|
210
|
+
navItems={headerConfig.navItems}
|
211
|
+
languages={headerConfig.languages}
|
212
|
+
currentLocale={headerConfig.currentLocale}
|
213
|
+
sticky={headerConfig.sticky}
|
214
|
+
basePath={headerConfig.basePath}
|
215
|
+
showSidebarToggle={headerConfig.showSidebarToggle}
|
216
|
+
defaultSidebarOpen={headerConfig.defaultSidebarOpen}
|
217
|
+
height={headerConfig.height}
|
218
|
+
transition:persist
|
219
|
+
/>
|
220
|
+
)
|
221
|
+
}
|
222
|
+
|
223
|
+
<Container flex="row" gap="md" size="full" padding="none">
|
224
|
+
<!-- 侧边栏容器 -->
|
225
|
+
{showSidebar && <Sidebar {...sidebarConfig} />}
|
226
|
+
|
227
|
+
<!-- 主内容区域 -->
|
228
|
+
<Main {...mainContentConfig}>
|
229
|
+
<slot />
|
230
|
+
<ClientRouter />
|
231
|
+
</Main>
|
232
|
+
</Container>
|
233
|
+
|
234
|
+
<!-- Footer -->
|
235
|
+
{
|
236
|
+
showFooter && (
|
237
|
+
<Container size="full" padding="none">
|
238
|
+
<Footer {...footerConfig} />
|
239
|
+
</Container>
|
240
|
+
)
|
241
|
+
}
|
242
|
+
|
243
|
+
<script>
|
244
|
+
// Handle sidebar toggle
|
245
|
+
const sidebarToggle = document.getElementById('sidebar-toggle');
|
246
|
+
const sidebar = document.getElementById('sidebar-mobile');
|
247
|
+
const sidebarOverlay = document.getElementById('sidebar-overlay');
|
248
|
+
|
249
|
+
function toggleSidebar() {
|
250
|
+
sidebar?.classList.toggle('cosy:hidden');
|
251
|
+
sidebarOverlay?.classList.toggle('cosy:hidden');
|
252
|
+
document.body.classList.toggle('cosy:overflow-hidden');
|
253
|
+
}
|
254
|
+
|
255
|
+
sidebarToggle?.addEventListener('click', toggleSidebar);
|
256
|
+
sidebarOverlay?.addEventListener('click', toggleSidebar);
|
257
|
+
</script>
|
258
|
+
</BaseLayout>
|