diff --git a/frontend/src/lib/components/apps/components/layout/AppTabs.svelte b/frontend/src/lib/components/apps/components/layout/AppTabs.svelte
index 521c89ee6d..87396cac20 100644
--- a/frontend/src/lib/components/apps/components/layout/AppTabs.svelte
+++ b/frontend/src/lib/components/apps/components/layout/AppTabs.svelte
@@ -28,6 +28,7 @@
customCss?: ComponentCustomCSS<'tabscomponent'> | undefined
render: boolean
disabledTabs: RichConfiguration[]
+ hiddenTabs: RichConfiguration[]
onTabChange?: string[] | undefined
}
@@ -39,6 +40,7 @@
customCss = undefined,
render,
disabledTabs,
+ hiddenTabs,
onTabChange = undefined
}: Props = $props()
@@ -101,18 +103,28 @@
}
},
left: () => {
- const index = tabs.indexOf(selected)
- if (index > 0) {
- selected = tabs[index - 1]
- return true
+ const currentIndex = tabs.indexOf(selected)
+ if (currentIndex > 0) {
+ // Find the next visible tab to the left
+ for (let i = currentIndex - 1; i >= 0; i--) {
+ if (!resolvedHiddenTabs[i]) {
+ selected = tabs[i]
+ return true
+ }
+ }
}
return false
},
right: () => {
- const index = tabs.indexOf(selected)
- if (index < tabs.length - 1) {
- selected = tabs[index + 1]
- return true
+ const currentIndex = tabs.indexOf(selected)
+ if (currentIndex < tabs.length - 1) {
+ // Find the next visible tab to the right
+ for (let i = currentIndex + 1; i < tabs.length; i++) {
+ if (!resolvedHiddenTabs[i]) {
+ selected = tabs[i]
+ return true
+ }
+ }
}
return false
},
@@ -144,6 +156,31 @@
})
let resolvedDisabledTabs: boolean[] = $state([])
+ let resolvedHiddenTabs: boolean[] = $state([])
+
+ // Filter visible tabs based on hiddenTabs configuration
+ let visibleTabsIndices = $derived(
+ (tabs ?? []).map((_, index) => index).filter((index) => !resolvedHiddenTabs[index])
+ )
+
+ // Auto-select first visible tab if current selection is hidden or invalid
+ $effect(() => {
+ if (visibleTabsIndices.length === 0) {
+ // Handle case where all tabs are hidden
+ selected = ''
+ selectedIndex = -1
+ return
+ }
+
+ const currentIndex = tabs?.indexOf(selected) ?? -1
+ if (currentIndex === -1 || resolvedHiddenTabs[currentIndex]) {
+ const firstVisibleTab = tabs[visibleTabsIndices[0]]
+ if (selected !== firstVisibleTab) {
+ // Current selection is hidden or invalid, select first visible tab
+ selected = firstVisibleTab
+ }
+ }
+ })
@@ -169,6 +206,15 @@
/>
{/each}
+{#each hiddenTabs ?? [] as hideTab, index}
+
+{/each}
+
{#if everRender}
{#if !resolvedConfig.tabsKind || resolvedConfig.tabsKind == 'tabs' || (resolvedConfig.tabsKind == 'invisibleOnView' && $mode == 'dnd')}
@@ -179,16 +225,18 @@
style={css?.tabRow?.style}
>
{#each tabs ?? [] as res, index}
-
- {res}
-
+ {#if !resolvedHiddenTabs[index]}
+
+ {res}
+
+ {/if}
{/each}
@@ -202,78 +250,82 @@
style={css?.tabRow?.style}
>
{#each tabs ?? [] as res, index}
-
{#each tabs ?? [] as res, index}
-
-
-
-
{
- if (!$connectingInput.opened) {
- $selectedComponent = [id]
- handleTabSelection()
- }
- }}
- />
+ {#if !resolvedHiddenTabs[index]}
+
+
+
+ {
+ if (!$connectingInput.opened) {
+ $selectedComponent = [id]
+ handleTabSelection()
+ }
+ }}
+ />
+
-
+ {/if}
{/each}
{:else}
diff --git a/frontend/src/lib/components/apps/editor/component/ComponentInner.svelte b/frontend/src/lib/components/apps/editor/component/ComponentInner.svelte
index 9135de349e..52ed61403c 100644
--- a/frontend/src/lib/components/apps/editor/component/ComponentInner.svelte
+++ b/frontend/src/lib/components/apps/editor/component/ComponentInner.svelte
@@ -853,6 +853,7 @@
id={component.id}
tabs={component.tabs}
disabledTabs={component.disabledTabs}
+ hiddenTabs={component.hiddenTabs}
onTabChange={component.onTabChange}
customCss={component.customCss}
{componentContainerHeight}
diff --git a/frontend/src/lib/components/apps/editor/component/components.ts b/frontend/src/lib/components/apps/editor/component/components.ts
index eb7b1ff9bc..d1235956fd 100644
--- a/frontend/src/lib/components/apps/editor/component/components.ts
+++ b/frontend/src/lib/components/apps/editor/component/components.ts
@@ -239,6 +239,7 @@ export type FileInputComponent = BaseComponent<'fileinputcomponent'> & {
export type TabsComponent = BaseComponent<'tabscomponent'> & {
tabs: string[]
disabledTabs: RichConfiguration[]
+ hiddenTabs: RichConfiguration[]
onTabChange?: string[]
}
@@ -3012,7 +3013,15 @@ See date-fns format for more information. By default, it is 'dd.MM.yyyy HH:mm'
},
componentInput: undefined,
numberOfSubgrids: 2,
- tabs: ['First tab', 'Second tab'] as string[]
+ tabs: ['First tab', 'Second tab'] as string[],
+ disabledTabs: [
+ { type: 'static', value: false, fieldType: 'boolean' },
+ { type: 'static', value: false, fieldType: 'boolean' }
+ ] as RichConfiguration[],
+ hiddenTabs: [
+ { type: 'static', value: false, fieldType: 'boolean' },
+ { type: 'static', value: false, fieldType: 'boolean' }
+ ] as RichConfiguration[]
}
},
steppercomponent: {
diff --git a/frontend/src/lib/components/apps/editor/settingsPanel/ComponentPanel.svelte b/frontend/src/lib/components/apps/editor/settingsPanel/ComponentPanel.svelte
index 8992b2fa0a..39b9bc23f7 100644
--- a/frontend/src/lib/components/apps/editor/settingsPanel/ComponentPanel.svelte
+++ b/frontend/src/lib/components/apps/editor/settingsPanel/ComponentPanel.svelte
@@ -391,8 +391,10 @@
{:else if item.data.type === 'aggridcomponentee'}
diff --git a/frontend/src/lib/components/apps/editor/settingsPanel/GridTab.svelte b/frontend/src/lib/components/apps/editor/settingsPanel/GridTab.svelte
index 2cbdc7d39e..955f1f8c6f 100644
--- a/frontend/src/lib/components/apps/editor/settingsPanel/GridTab.svelte
+++ b/frontend/src/lib/components/apps/editor/settingsPanel/GridTab.svelte
@@ -13,11 +13,14 @@
import { generateRandomString } from '$lib/utils'
import { GripVertical, Plus } from 'lucide-svelte'
import GridTabDisabled from './GridTabDisabled.svelte'
+ import GridTabHidden from './GridTabHidden.svelte'
interface Props {
tabs?: string[]
disabledTabs?: RichConfiguration[]
+ hiddenTabs?: RichConfiguration[]
canDisableTabs?: boolean
+ canHideTabs?: boolean
word?: string
component: AppComponent
}
@@ -25,7 +28,9 @@
let {
tabs = $bindable(undefined),
disabledTabs = $bindable(undefined),
+ hiddenTabs = $bindable(undefined),
canDisableTabs = false,
+ canHideTabs = false,
word = 'Tab',
component = $bindable()
}: Props = $props()
@@ -40,6 +45,12 @@
{ type: 'static', value: false, fieldType: 'boolean' }
]
}
+ if (hiddenTabs == undefined) {
+ hiddenTabs = [
+ { type: 'static', value: false, fieldType: 'boolean' },
+ { type: 'static', value: false, fieldType: 'boolean' }
+ ]
+ }
})
let items = $state.raw(
@@ -77,6 +88,7 @@
component.numberOfSubgrids = items.length
disabledTabs = [...(disabledTabs ?? []), { type: 'static', value: false, fieldType: 'boolean' }]
+ hiddenTabs = [...(hiddenTabs ?? []), { type: 'static', value: false, fieldType: 'boolean' }]
}
function deleteSubgrid(index: number) {
@@ -99,6 +111,9 @@
// Delete the item in the disabledTabs array
disabledTabs = (disabledTabs ?? []).filter((_, i) => i !== index)
+ // Delete the item in the hiddenTabs array
+ hiddenTabs = (hiddenTabs ?? []).filter((_, i) => i !== index)
+
component.numberOfSubgrids = items.length
// Update the originalIndex of the remaining items
items.forEach((item, i) => {
@@ -136,10 +151,13 @@
}
const newDisabledTabs: RichConfiguration[] = []
+ const newHiddenTabs: RichConfiguration[] = []
for (let i = 0; i < items.length; i++) {
disabledTabs && newDisabledTabs.push(disabledTabs[items[i].originalIndex])
+ hiddenTabs && newHiddenTabs.push(hiddenTabs[items[i].originalIndex])
}
disabledTabs = newDisabledTabs
+ hiddenTabs = newHiddenTabs
// update originalIndex
items.forEach((item, i) => {
@@ -203,6 +221,11 @@
{#if canDisableTabs && disabledTabs}
{/if}
+ {#if canHideTabs && hiddenTabs}
+
+
+
+ {/if}
{/each}
diff --git a/frontend/src/lib/components/apps/editor/settingsPanel/GridTabHidden.svelte b/frontend/src/lib/components/apps/editor/settingsPanel/GridTabHidden.svelte
new file mode 100644
index 0000000000..de194d36e5
--- /dev/null
+++ b/frontend/src/lib/components/apps/editor/settingsPanel/GridTabHidden.svelte
@@ -0,0 +1,62 @@
+
+
+