Skip to content

Commit 4b848f9

Browse files
committed
feat: add customizable expanded sidebar width option
1 parent 41df0e3 commit 4b848f9

File tree

6 files changed

+35
-23
lines changed

6 files changed

+35
-23
lines changed

adminforth/documentation/docs/tutorial/03-Customization/01-branding.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,8 @@ const admin = new AdminForth({
141141
enabled: true, // Optional: Enable the collapsible icon-only sidebar feature
142142
//diff-add
143143
logo: '@@/logo.svg', // Optional: Custom logo to display in icon-only mode
144+
//diff-add
145+
expandedSidebarWidth: '18.5rem', // Optional: sets the expanded sidebar width, defaults to 16.5rem
144146
//diff-add
145147
},
146148
},

adminforth/spa/src/App.vue

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<template>
2-
<div class="">
2+
<div>
33
<nav
44
v-if="loggedIn && routerIsReady && loginRedirectCheckIsReady && defaultLayout"
55
class="fixed h-14 top-0 z-30 w-full border-b shadow-sm bg-lightNavbar shadow-headerShadow dark:bg-darkNavbar dark:border-darkSidebarDevider"
@@ -82,11 +82,9 @@
8282
/>
8383

8484
<div class="af-content-wrapper transition-all duration-300 ease-in-out max-w-[100vw]"
85-
:class="{
86-
'sm:ml-18': isSidebarIconOnly,
87-
'sm:ml-[16.5rem]': !isSidebarIconOnly,
88-
'sm:max-w-[calc(100%-4.5rem)]': isSidebarIconOnly,
89-
'sm:max-w-[calc(100%-16rem)]': !isSidebarIconOnly
85+
:style="{
86+
marginLeft: isSidebarIconOnly ? '4.5rem' : expandedWidth,
87+
maxWidth: isSidebarIconOnly ? 'calc(100% - 4.5rem)' : `calc(100% - ${expandedWidth})`
9088
}"
9189
v-if="loggedIn && routerIsReady && loginRedirectCheckIsReady && defaultLayout">
9290
<div class="p-0 dark:border-gray-700 mt-14">
@@ -147,12 +145,10 @@
147145
@apply opacity-100;
148146
}
149147
150-
@media (min-width: 640px) {
151-
.sm\:ml-18 {
152-
margin-left: 4.5rem;
153-
}
154-
.sm\:max-w-\[calc\(100\%-4\.5rem\)\] {
155-
max-width: calc(100% - 4.5rem);
148+
@media (max-width: 640px) {
149+
.af-content-wrapper {
150+
margin-left: 0 !important;
151+
max-width: 100% !important;
156152
}
157153
}
158154
@@ -200,6 +196,8 @@ const isSidebarIconOnly = ref(localStorage.getItem('afIconOnlySidebar') === 'tru
200196
201197
const loggedIn = computed(() => !!coreStore?.adminUser);
202198
199+
const expandedWidth = computed(() => coreStore.config?.iconOnlySidebar?.expandedSidebarWidth || '16.5rem');
200+
203201
const theme = ref('light');
204202
205203
function hideSidebar(): void {

adminforth/spa/src/components/MenuLink.vue

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@
2424
}"
2525
:style="isSidebarIconOnly ? {
2626
minWidth: isChild
27-
? 'calc(16.5rem - 0.75rem*2 - 1.5rem*2 - 1.25rem - 0.75rem)'
28-
: 'calc(16.5rem - 0.75rem*2 - 0.875rem*2 - 1.25rem - 0.75rem)',
27+
? `calc(${expandedWidth} - 0.75rem*2 - 1.5rem*2 - 1.25rem - 0.75rem)`
28+
: `calc(${expandedWidth} - 0.75rem*2 - 0.875rem*2 - 1.25rem - 0.75rem)`,
2929
width: isChild
30-
? 'calc(16.5rem - 0.75rem*2 - 1.5rem*2 - 1.25rem - 0.75rem)'
31-
: 'calc(16.5rem - 0.75rem*2 - 0.875rem*2 - 1.25rem - 0.75rem)'
30+
? `calc(${expandedWidth} - 0.75rem*2 - 1.5rem*2 - 1.25rem - 0.75rem)`
31+
: `calc(${expandedWidth} - 0.75rem*2 - 0.875rem*2 - 1.25rem - 0.75rem)`
3232
} : {}"
3333
>
3434
{{ item.label }}
@@ -55,10 +55,15 @@
5555
<script setup lang="ts">
5656
import { getIcon } from '@/utils';
5757
import { Tooltip } from '@/afcl';
58-
import { ref, watch } from 'vue';
58+
import { ref, watch, computed } from 'vue';
59+
import { useCoreStore } from '@/stores/core';
5960
6061
const props = defineProps(['item', 'isChild', 'isSidebarIconOnly', 'isSidebarHovering']);
6162
63+
const coreStore = useCoreStore();
64+
65+
const expandedWidth = computed(() => coreStore.config?.iconOnlySidebar?.expandedSidebarWidth || '16.5rem');
66+
6267
const BADGE_SHOW_DELAY_MS = 200;
6368
const showExpandedBadge = ref(false);
6469
let showBadgeTimer: ReturnType<typeof setTimeout> | null = null;

adminforth/spa/src/components/Sidebar.vue

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
>
2424
{{ coreStore.config?.brandName }}
2525
</span>
26-
<div class="flex items-center gap-2 w-auto" :class="{'w-full justify-end': coreStore.config?.showBrandLogoInSidebar === false}">
26+
<div v-if="!isSidebarIconOnly || (isSidebarIconOnly && isSidebarHovering)" class="flex items-center gap-2 w-auto" :class="{'w-full justify-end': coreStore.config?.showBrandLogoInSidebar === false}">
2727
<component
2828
v-for="c in coreStore?.config?.globalInjections?.sidebarTop || []"
2929
:is="getCustomComponent(c)"
@@ -106,8 +106,8 @@
106106
'opacity-100 ms-3 translate-x-0 flex-1': !isSidebarIconOnly
107107
}"
108108
:style="isSidebarIconOnly ? {
109-
minWidth: 'calc(16.5rem - 0.75rem*2 - 0.875rem*2 - 1.25rem - 0.75rem)',
110-
width: 'calc(16.5rem - 0.75rem*2 - 0.875rem*2 - 1.25rem - 0.75rem)'
109+
minWidth: `calc(${expandedWidth} - 0.75rem*2 - 0.875rem*2 - 1.25rem - 0.75rem)`,
110+
width: `calc(${expandedWidth} - 0.75rem*2 - 0.875rem*2 - 1.25rem - 0.75rem)`
111111
} : {}"
112112
>{{ item.label }}
113113

@@ -188,7 +188,7 @@
188188
<style lang="scss" scoped>
189189
/* Sidebar width animations */
190190
.sidebar-container {
191-
width: 16.5rem; /* Default expanded width (w-64) */
191+
width: v-bind(expandedWidth); /* Default expanded width (w-64) */
192192
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
193193
overflow: hidden; /* Prevent content from showing during animation */
194194
will-change: width, transform;
@@ -199,8 +199,8 @@
199199
}
200200
201201
.sidebar-expanded {
202-
width: 16.5rem; /* Expanded width (w-64) */
203-
box-shadow: 12px 0px 18px -8px rgba(0, 0, 0, 0.15);
202+
width: v-bind(expandedWidth); /* Expanded width (w-64) */
203+
box-shadow: 3px 0px 12px -2px rgba(0, 0, 0, 0.15);
204204
}
205205
206206
:deep(.dark) .sidebar-collapsed {
@@ -313,6 +313,8 @@ const isMobile = ref(!smQuery.matches);
313313
const iconOnlySidebarEnabled = computed(() => props.forceIconOnly === true || coreStore.config?.iconOnlySidebar?.enabled !== false);
314314
const isSidebarIconOnly = ref(false);
315315
316+
const expandedWidth = computed(() => coreStore.config?.iconOnlySidebar?.expandedSidebarWidth || '16.5rem');
317+
316318
function handleBreakpointChange(e: MediaQueryListEvent) {
317319
isMobile.value = !e.matches;
318320
if (isMobile.value) {

adminforth/types/Back.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -700,6 +700,10 @@ interface AdminForthInputConfigCustomization {
700700
iconOnlySidebar?: {
701701
logo?: string,
702702
enabled?: boolean,
703+
/**
704+
* Width of expanded sidebar (default: '16.5rem')
705+
*/
706+
expandedSidebarWidth?: string,
703707
},
704708

705709
/**

adminforth/types/Common.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1110,6 +1110,7 @@ export interface AdminForthConfigForFrontend {
11101110
iconOnlySidebar?: {
11111111
logo?: string,
11121112
enabled?: boolean,
1113+
expandedSidebarWidth?: string,
11131114
},
11141115
singleTheme?: 'light' | 'dark',
11151116
datesFormat: string,

0 commit comments

Comments
 (0)