From f4dc5b843796adbb83f20c10c1b065a2407bda6a Mon Sep 17 00:00:00 2001 From: Dannon Baker Date: Mon, 2 Mar 2026 15:04:36 -0500 Subject: [PATCH 1/6] Fix GTabs vertical layout and spacing Match BSV's rendered structure for vertical tabs: container uses Bootstrap row/no-gutters grid, nav is wrapped in a col-auto div, tab-content gets the col class. When card+vertical, the nav gets card-header h-100 border-bottom-0 rounded-0 and card-header-tabs/pills classes are skipped since they conflict. Also pass the card prop through provide/inject so GTab can add the card-body class to tab panes, matching BSV's padding behavior. Fixes #21966 --- client/src/components/BaseComponents/GTab.vue | 2 +- .../src/components/BaseComponents/GTabs.vue | 61 +++++++++++++++---- 2 files changed, 51 insertions(+), 12 deletions(-) diff --git a/client/src/components/BaseComponents/GTab.vue b/client/src/components/BaseComponents/GTab.vue index 0b75cb6cc08..21d69b8108a 100644 --- a/client/src/components/BaseComponents/GTab.vue +++ b/client/src/components/BaseComponents/GTab.vue @@ -112,7 +112,7 @@ onBeforeUnmount(() => { v-show="isActive" :id="id" class="tab-pane" - :class="{ active: isActive, show: isActive }" + :class="{ active: isActive, show: isActive, 'card-body': context.tabsCard }" role="tabpanel"> diff --git a/client/src/components/BaseComponents/GTabs.vue b/client/src/components/BaseComponents/GTabs.vue index 9ee0d217cce..8d9ac0e0770 100644 --- a/client/src/components/BaseComponents/GTabs.vue +++ b/client/src/components/BaseComponents/GTabs.vue @@ -22,6 +22,7 @@ export interface TabsContext { updateTab: (index: number, tab: TabRegistration) => void; setActive: (index: number) => void; tabsLazy: boolean; + tabsCard: boolean; } const props = withDefaults( @@ -105,6 +106,7 @@ provide("g-tabs-context", { updateTab, setActive, tabsLazy: props.lazy, + tabsCard: props.card, }); const navClasses = computed(() => ({ @@ -112,15 +114,20 @@ const navClasses = computed(() => ({ "nav-pills": props.pills, "nav-justified": props.justified, "nav-fill": props.fill, - "card-header-tabs": props.card && !props.pills, - "card-header-pills": props.card && props.pills, + "card-header-tabs": props.card && !props.pills && !props.vertical, + "card-header-pills": props.card && props.pills && !props.vertical, "flex-column": props.vertical, + "card-header": props.card && props.vertical, + "h-100": props.card && props.vertical, + "border-bottom-0": props.card && props.vertical, + "rounded-0": props.card && props.vertical, })); // "tabs" class matches BTabs' outer div class for Selenium selector compatibility const containerClasses = computed(() => ({ tabs: true, - "d-flex": props.vertical, + row: props.vertical, + "no-gutters": props.vertical && props.card, })); // Vue 2.7 doesn't support plain functions as components via , @@ -146,7 +153,44 @@ const TabTitleContent = defineComponent({