3 Commits

Author SHA1 Message Date
Sebastian 122c4a3b1f chore(deps): update dependency phpunit/phpunit to v12.5.32
Build Test / build (pull_request) Successful in 28s
JS Unit Tests / test (pull_request) Successful in 23s
PHP Integration Tests / Integration Tests (pull_request) Failing after 1m22s
PHP Unit Tests / test (pull_request) Failing after 1m22s
2026-07-27 03:04:00 +00:00
Sebastian 98826143a8 fix: sub menu spacing
Signed-off-by: Sebastian Krupinski <krupinski01@gmail.com>
2026-07-26 20:32:46 -04:00
Sebastian e47d0ed619 feat: improve menu section selector
Signed-off-by: Sebastian Krupinski <krupinski01@gmail.com>
2026-07-26 18:20:40 -04:00
2 changed files with 80 additions and 47 deletions
Generated
+8 -8
View File
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "68916c1b58d9ce06a59f6c58e4a2d226", "content-hash": "d1b5f8dbf4a0d0bfddbd1473bf180da7",
"packages": [ "packages": [
{ {
"name": "laravel/serializable-closure", "name": "laravel/serializable-closure",
@@ -1946,16 +1946,16 @@
}, },
{ {
"name": "phpunit/phpunit", "name": "phpunit/phpunit",
"version": "12.5.31", "version": "12.5.32",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git", "url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "0608d157a284f15cc73b99a3327eff06b66a176d" "reference": "c02591dd7840ed124a98d7770753329ad28e9f8f"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/0608d157a284f15cc73b99a3327eff06b66a176d", "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c02591dd7840ed124a98d7770753329ad28e9f8f",
"reference": "0608d157a284f15cc73b99a3327eff06b66a176d", "reference": "c02591dd7840ed124a98d7770753329ad28e9f8f",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -2024,7 +2024,7 @@
"support": { "support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues", "issues": "https://github.com/sebastianbergmann/phpunit/issues",
"security": "https://github.com/sebastianbergmann/phpunit/security/policy", "security": "https://github.com/sebastianbergmann/phpunit/security/policy",
"source": "https://github.com/sebastianbergmann/phpunit/tree/12.5.31" "source": "https://github.com/sebastianbergmann/phpunit/tree/12.5.32"
}, },
"funding": [ "funding": [
{ {
@@ -2032,7 +2032,7 @@
"type": "other" "type": "other"
} }
], ],
"time": "2026-07-06T14:54:16+00:00" "time": "2026-07-25T06:54:13+00:00"
}, },
{ {
"name": "sebastian/cli-parser", "name": "sebastian/cli-parser",
@@ -3057,5 +3057,5 @@
"ext-iconv": "*" "ext-iconv": "*"
}, },
"platform-dev": {}, "platform-dev": {},
"plugin-api-version": "2.6.0" "plugin-api-version": "2.9.0"
} }
+72 -39
View File
@@ -1,6 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed } from 'vue'; import { computed } from 'vue';
import { useLayoutStore } from '@KTXC/stores/layoutStore'; import { useLayoutStore, type MenuMode } from '@KTXC/stores/layoutStore';
import { useIntegrationStore } from '@KTXC/stores/integrationStore'; import { useIntegrationStore } from '@KTXC/stores/integrationStore';
import { useL10n } from '@KTXC/composables/useL10n'; import { useL10n } from '@KTXC/composables/useL10n';
import Logo from '@KTXC/layouts/logo/LogoDark.vue'; import Logo from '@KTXC/layouts/logo/LogoDark.vue';
@@ -25,33 +25,12 @@ const menuEntries = computed(() => {
} }
}); });
// Menu mode display info // Static list of menu modes shown as icon buttons
const menuModeInfo = computed(() => { const menuModes = computed((): Array<{ value: MenuMode; icon: string; label: string }> => [
switch (layoutStore.menuMode) { { value: 'apps', icon: 'mdi-view-dashboard', label: t('systemMenu.apps', 'Applications') },
case 'user-settings': { value: 'user-settings', icon: 'mdi-account-cog', label: t('systemMenu.personalSettings', 'Settings') },
return { { value: 'admin-settings', icon: 'mdi-shield-crown', label: t('systemMenu.adminSettings', 'System') },
icon: 'mdi-account-cog', ]);
label: t('systemMenu.personalSettings', 'Settings'),
toggleLabel: t('systemMenu.adminSettings', 'System'),
toggleIcon: 'mdi-shield-crown',
};
case 'admin-settings':
return {
icon: 'mdi-shield-crown',
label: t('systemMenu.adminSettings', 'System'),
toggleLabel: t('systemMenu.apps', 'Applications'),
toggleIcon: 'mdi-view-dashboard',
};
case 'apps':
default:
return {
icon: 'mdi-view-dashboard',
label: t('systemMenu.apps', 'Applications'),
toggleLabel: t('systemMenu.userSettings', 'Settings'),
toggleIcon: 'mdi-account-cog',
};
}
});
</script> </script>
<script lang="ts"> <script lang="ts">
@@ -103,20 +82,74 @@ export default {
</v-list> </v-list>
</perfect-scrollbar> </perfect-scrollbar>
<!-- Menu Mode Toggle --> <!-- Menu Mode Switcher -->
<template v-slot:append> <template v-slot:append>
<v-divider /> <v-divider />
<v-list density="compact" class="pa-2"> <div class="menu-mode-switcher d-flex justify-space-around align-center py-2">
<v-list-item <v-tooltip
rounded v-for="mode in menuModes"
color="primary" :key="mode.value"
@click="layoutStore.toggleMenuMode()" location="right"
:prepend-icon="menuModeInfo.toggleIcon"
class="menu-mode-toggle"
> >
<v-list-item-title class="text-body-2">{{ menuModeInfo.toggleLabel }}</v-list-item-title> <template v-slot:activator="{ props }">
</v-list-item> <v-btn
</v-list> v-bind="props"
icon
variant="text"
density="comfortable"
:color="layoutStore.menuMode === mode.value ? 'primary' : undefined"
:class="['menu-mode-btn', { 'menu-mode-btn--active': layoutStore.menuMode === mode.value }]"
@click="layoutStore.setMenuMode(mode.value)"
>
<v-icon>{{ mode.icon }}</v-icon>
</v-btn>
</template>
<span>{{ mode.label }}</span>
</v-tooltip>
</div>
</template> </template>
</v-navigation-drawer> </v-navigation-drawer>
</template> </template>
<style scoped>
.menu-mode-btn {
opacity: 0.6;
transition: opacity 0.2s ease, background-color 0.2s ease;
}
.menu-mode-btn:hover {
opacity: 1;
background-color: rgba(var(--v-theme-on-surface), 0.06);
}
.menu-mode-btn--active {
opacity: 1;
}
/* Collapsed rail: only the active mode icon fits without crowding */
.leftSidebar.v-navigation-drawer--rail:not(.v-navigation-drawer--is-hovering) .menu-mode-switcher {
justify-content: center;
}
.leftSidebar.v-navigation-drawer--rail:not(.v-navigation-drawer--is-hovering) .menu-mode-btn:not(.menu-mode-btn--active) {
display: none;
}
/* Sub-menu items: Vuetify's default group indent (prepend width + indent
size) stacks up to ~72px; bring it back down closer to top-level items */
.scrollnavbar :deep(.v-list-group__items .v-list-item) {
padding-inline-start: 40px;
}
/* Collapsed rail (not hovering): sub-items have no room to show icon or
text, so they render as an empty highlighted bar when active. Hide the
expanded group entirely and highlight the parent icon instead. */
.leftSidebar.v-navigation-drawer--rail:not(.v-navigation-drawer--is-hovering) :deep(.v-list-group__items) {
display: none;
}
.leftSidebar.v-navigation-drawer--rail:not(.v-navigation-drawer--is-hovering)
:deep(.v-list-group:has(.v-list-item--active) > .v-list-item.v-list-group__header) {
color: rgb(var(--v-theme-primary));
}
</style>