@functionalcms/svelte-components 5.22.0 → 5.23.1
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.
|
@@ -24,13 +24,15 @@
|
|
|
24
24
|
img: string;
|
|
25
25
|
};
|
|
26
26
|
sidebarPosition?: 'fixed' | 'absolute' | 'static';
|
|
27
|
+
collapseButtonPosition?: 'top' | 'bottom';
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
let {
|
|
30
31
|
children,
|
|
31
32
|
menuItems = [],
|
|
32
33
|
logo = undefined,
|
|
33
|
-
sidebarPosition = 'fixed'
|
|
34
|
+
sidebarPosition = 'fixed',
|
|
35
|
+
collapseButtonPosition = 'top'
|
|
34
36
|
}: Partial<TwoColumnLayoutProps> = $props();
|
|
35
37
|
|
|
36
38
|
let container: HTMLElement | undefined = undefined;
|
|
@@ -55,56 +57,71 @@
|
|
|
55
57
|
position={sidebarPosition}
|
|
56
58
|
class="z-50 h-full transition-all duration-300 {isCollapsed ? 'w-16' : 'w-64'}"
|
|
57
59
|
>
|
|
58
|
-
<
|
|
59
|
-
<
|
|
60
|
-
<
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
60
|
+
<div class="flex h-full flex-col justify-between">
|
|
61
|
+
<SidebarGroup>
|
|
62
|
+
<div class="mb-4 flex items-center justify-between px-2">
|
|
63
|
+
{#if collapseButtonPosition === 'top'}
|
|
64
|
+
<button
|
|
65
|
+
onclick={() => (isCollapsed = !isCollapsed)}
|
|
66
|
+
class="rounded-lg p-2 hover:bg-gray-100 dark:hover:bg-gray-700"
|
|
67
|
+
title={isCollapsed ? 'Expand menu' : 'Collapse menu'}
|
|
68
|
+
>
|
|
69
|
+
<Icon {icon} />
|
|
70
|
+
</button>
|
|
71
|
+
{/if}
|
|
72
|
+
{#if logo && !isCollapsed}
|
|
73
|
+
<SidebarBrand site={logo} classes={{ img: 'h-6 w-6' }} />
|
|
74
|
+
{/if}
|
|
75
|
+
</div>
|
|
76
|
+
{#each menuItems as item}
|
|
77
|
+
{#if !isCollapsed}
|
|
78
|
+
{#if 'items' in item}
|
|
79
|
+
<SidebarDropdownWrapper label={item.label} isOpen={item.isOpen}>
|
|
80
|
+
{#each item.items as subItem}
|
|
81
|
+
<SidebarItem label={subItem.label} href={subItem.href}>
|
|
82
|
+
{#snippet icon()}
|
|
83
|
+
<Icon icon={subItem.icon} />
|
|
84
|
+
{/snippet}
|
|
85
|
+
</SidebarItem>
|
|
86
|
+
{/each}
|
|
87
|
+
</SidebarDropdownWrapper>
|
|
88
|
+
{:else}
|
|
89
|
+
<SidebarItem label={item.label} href={item.href}>
|
|
90
|
+
{#snippet icon()}
|
|
91
|
+
<Icon icon={item.icon} />
|
|
92
|
+
{/snippet}
|
|
93
|
+
</SidebarItem>
|
|
94
|
+
{/if}
|
|
95
|
+
{:else}
|
|
96
|
+
<SidebarItem label="" href={item.href} class="justify-center" title={item.label}>
|
|
97
|
+
{#snippet icon()}
|
|
98
|
+
<Icon icon={item.icon} />
|
|
99
|
+
{/snippet}
|
|
100
|
+
</SidebarItem>
|
|
101
|
+
{#if item.items && item.isOpen}
|
|
75
102
|
{#each item.items as subItem}
|
|
76
|
-
<SidebarItem label=
|
|
103
|
+
<SidebarItem label="" href={subItem.href}>
|
|
77
104
|
{#snippet icon()}
|
|
78
105
|
<Icon icon={subItem.icon} />
|
|
79
106
|
{/snippet}
|
|
80
107
|
</SidebarItem>
|
|
81
108
|
{/each}
|
|
82
|
-
|
|
83
|
-
{:else}
|
|
84
|
-
<SidebarItem label={item.label} href={item.href}>
|
|
85
|
-
{#snippet icon()}
|
|
86
|
-
<Icon icon={item.icon} />
|
|
87
|
-
{/snippet}
|
|
88
|
-
</SidebarItem>
|
|
89
|
-
{/if}
|
|
90
|
-
{:else}
|
|
91
|
-
<SidebarItem label="" href={item.href} class="justify-center" title={item.label}>
|
|
92
|
-
{#snippet icon()}
|
|
93
|
-
<Icon icon={item.icon} />
|
|
94
|
-
{/snippet}
|
|
95
|
-
</SidebarItem>
|
|
96
|
-
{#if item.items && item.isOpen}
|
|
97
|
-
{#each item.items as subItem}
|
|
98
|
-
<SidebarItem label="" href={subItem.href}>
|
|
99
|
-
{#snippet icon()}
|
|
100
|
-
<Icon icon={subItem.icon} />
|
|
101
|
-
{/snippet}
|
|
102
|
-
</SidebarItem>
|
|
103
|
-
{/each}
|
|
109
|
+
{/if}
|
|
104
110
|
{/if}
|
|
105
|
-
{/
|
|
106
|
-
|
|
107
|
-
|
|
111
|
+
{/each}
|
|
112
|
+
</SidebarGroup>
|
|
113
|
+
{#if collapseButtonPosition === 'bottom'}
|
|
114
|
+
<div class="mb-2 flex items-center px-2 {isCollapsed ? 'justify-center' : ''}">
|
|
115
|
+
<button
|
|
116
|
+
onclick={() => (isCollapsed = !isCollapsed)}
|
|
117
|
+
class="rounded-lg p-2 hover:bg-gray-100 dark:hover:bg-gray-700"
|
|
118
|
+
title={isCollapsed ? 'Expand menu' : 'Collapse menu'}
|
|
119
|
+
>
|
|
120
|
+
<Icon {icon} />
|
|
121
|
+
</button>
|
|
122
|
+
</div>
|
|
123
|
+
{/if}
|
|
124
|
+
</div>
|
|
108
125
|
</Sidebar>
|
|
109
126
|
<div
|
|
110
127
|
class="content h-full overflow-auto px-4 transition-all duration-300 {sidebarPosition ===
|
|
@@ -28,22 +28,23 @@
|
|
|
28
28
|
<aside
|
|
29
29
|
class="resizable-aside"
|
|
30
30
|
class:collapsed={isCollapsed}
|
|
31
|
-
style="width: {isCollapsed ? '
|
|
31
|
+
style="width: {isCollapsed ? 'var(--collapsed-width)' : asideWidth + 'px'}"
|
|
32
32
|
>
|
|
33
|
-
<
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
<button
|
|
34
|
+
class="collapse-toggle"
|
|
35
|
+
onclick={toggleCollapse}
|
|
36
|
+
aria-label={isCollapsed ? "Expand sidebar" : "Collapse sidebar"}
|
|
37
|
+
>
|
|
38
|
+
<Icon icon={icon} />
|
|
39
|
+
</button>
|
|
40
|
+
|
|
41
|
+
{#if !isCollapsed}
|
|
42
|
+
<div class="aside-content">
|
|
43
|
+
{@render aside()}
|
|
44
|
+
</div>
|
|
45
|
+
{/if}
|
|
36
46
|
</aside>
|
|
37
47
|
|
|
38
|
-
<button
|
|
39
|
-
class="collapse-toggle"
|
|
40
|
-
class:collapsed={isCollapsed}
|
|
41
|
-
onclick={toggleCollapse}
|
|
42
|
-
aria-label={isCollapsed ? "Expand sidebar" : "Collapse sidebar"}
|
|
43
|
-
>
|
|
44
|
-
<Icon icon={icon} />
|
|
45
|
-
</button>
|
|
46
|
-
|
|
47
48
|
<main class="resizable-main">
|
|
48
49
|
{@render main()}
|
|
49
50
|
</main>
|
|
@@ -58,6 +59,7 @@
|
|
|
58
59
|
}
|
|
59
60
|
|
|
60
61
|
.resizable-aside {
|
|
62
|
+
--collapsed-width: 2.5rem;
|
|
61
63
|
position: relative;
|
|
62
64
|
height: 100%;
|
|
63
65
|
background-color: #f5f5f5;
|
|
@@ -67,38 +69,26 @@
|
|
|
67
69
|
flex-shrink: 0;
|
|
68
70
|
}
|
|
69
71
|
|
|
70
|
-
.resizable-aside.collapsed {
|
|
71
|
-
width: 0 !important;
|
|
72
|
-
border-right: none;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
72
|
.aside-content {
|
|
76
73
|
height: 100%;
|
|
77
74
|
overflow-y: auto;
|
|
78
75
|
overflow-x: hidden;
|
|
79
|
-
padding: 1rem;
|
|
76
|
+
padding: 2.5rem 1rem 1rem;
|
|
80
77
|
}
|
|
81
78
|
|
|
82
79
|
.collapse-toggle {
|
|
83
80
|
position: absolute;
|
|
84
|
-
|
|
81
|
+
right: 0;
|
|
85
82
|
top: 0;
|
|
86
83
|
z-index: 10;
|
|
87
84
|
background-color: #fff;
|
|
88
85
|
border: 1px solid #ddd;
|
|
89
|
-
border-
|
|
86
|
+
border-top: none;
|
|
87
|
+
border-right: none;
|
|
88
|
+
border-radius: 0 0 0 4px;
|
|
90
89
|
padding: 0.5rem 0.25rem;
|
|
91
90
|
cursor: pointer;
|
|
92
|
-
transition:
|
|
93
|
-
box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.1);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
.collapse-toggle.collapsed {
|
|
97
|
-
left: 0;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
.collapse-toggle:not(.collapsed) {
|
|
101
|
-
left: var(--aside-width, 300px);
|
|
91
|
+
transition: background-color 0.2s ease;
|
|
102
92
|
}
|
|
103
93
|
|
|
104
94
|
.collapse-toggle:hover {
|