11import type { UmbBlockWorkspaceElementManagerNames } from '../../block-workspace.context.js' ;
22import { UMB_BLOCK_WORKSPACE_CONTEXT } from '../../block-workspace.context-token.js' ;
33import type { UmbBlockWorkspaceViewEditTabElement } from './block-workspace-view-edit-tab.element.js' ;
4- import { css , html , customElement , state , repeat , property } from '@umbraco-cms/backoffice/external/lit' ;
4+ import { css , html , customElement , state , repeat , property , nothing } from '@umbraco-cms/backoffice/external/lit' ;
55import { UmbTextStyles } from '@umbraco-cms/backoffice/style' ;
66import type { UmbContentTypeModel , UmbPropertyTypeContainerMergedModel } from '@umbraco-cms/backoffice/content-type' ;
77import { UmbContentTypeContainerStructureHelper } from '@umbraco-cms/backoffice/content-type' ;
@@ -101,6 +101,17 @@ export class UmbBlockWorkspaceViewEditElement extends UmbLitElement implements U
101101 if ( ! this . _tabs || ! this . #blockWorkspace) return ;
102102 const routes : UmbRoute [ ] = [ ] ;
103103
104+ if ( this . _hasRootGroups || this . _hasRootProperties ) {
105+ routes . push ( {
106+ path : 'root' ,
107+ component : ( ) => import ( './block-workspace-view-edit-tab.element.js' ) ,
108+ setup : ( component ) => {
109+ ( component as UmbBlockWorkspaceViewEditTabElement ) . managerName = this . #managerName;
110+ ( component as UmbBlockWorkspaceViewEditTabElement ) . containerId = null ;
111+ } ,
112+ } ) ;
113+ }
114+
104115 if ( this . _tabs . length > 0 ) {
105116 this . _tabs ?. forEach ( ( tab ) => {
106117 const tabName = tab . name ?? '' ;
@@ -115,25 +126,13 @@ export class UmbBlockWorkspaceViewEditElement extends UmbLitElement implements U
115126 } ) ;
116127 }
117128
118- if ( this . _hasRootGroups || this . _hasRootProperties ) {
129+ if ( routes . length !== 0 ) {
119130 routes . push ( {
131+ ...routes [ 0 ] ,
132+ unique : 'emptyPathFor_' + routes [ 0 ] . path ,
120133 path : '' ,
121- component : ( ) => import ( './block-workspace-view-edit-tab.element.js' ) ,
122- setup : ( component ) => {
123- ( component as UmbBlockWorkspaceViewEditTabElement ) . managerName = this . #managerName;
124- ( component as UmbBlockWorkspaceViewEditTabElement ) . containerId = null ;
125- } ,
126134 } ) ;
127- }
128135
129- if ( routes . length !== 0 ) {
130- if ( ! this . _hasRootGroups ) {
131- routes . push ( {
132- path : '' ,
133- pathMatch : 'full' ,
134- redirectTo : routes [ 0 ] ?. path ,
135- } ) ;
136- }
137136 routes . push ( {
138137 path : `**` ,
139138 component : async ( ) => ( await import ( '@umbraco-cms/backoffice/router' ) ) . UmbRouteNotFoundElement ,
@@ -151,24 +150,14 @@ export class UmbBlockWorkspaceViewEditElement extends UmbLitElement implements U
151150 ( this . _tabs . length > 1 || ( this . _tabs . length === 1 && ( this . _hasRootGroups || this . _hasRootProperties ) ) )
152151 ? html ` <uui- tab- group slot= "header" >
153152 ${ ( this . _hasRootGroups || this . _hasRootProperties ) && this . _tabs . length > 0
154- ? html `
155- <uui- tab
156- label= ${ this . localize . term ( 'general_generic' ) }
157- .active = ${ this . _routerPath + '/' === this . _activePath }
158- href= ${ this . _routerPath + '/' } > </ uui- tab>
159- `
160- : '' }
153+ ? this . #renderTab( null , '#general_generic' )
154+ : nothing }
161155 ${ repeat (
162156 this . _tabs ,
163157 ( tab ) => tab . name ,
164- ( tab ) => {
165- const path = this . _routerPath + '/tab/' + encodeFolderName ( tab . name || '' ) ;
166- return html `<uui- tab
167- label= ${ this . localize . string ( tab . name ?? '#general_unknown' ) }
168- .active = ${ path === this . _activePath }
169- href= ${ path } >
170- ${ this . localize . string ( tab . name ) }
171- </ uui- tab> ` ;
158+ ( tab , index ) => {
159+ const path = 'tab/' + encodeFolderName ( tab . name || '' ) ;
160+ return this . #renderTab( path , tab . name , index ) ;
172161 } ,
173162 ) }
174163 </ uui- tab- group> `
@@ -187,6 +176,25 @@ export class UmbBlockWorkspaceViewEditElement extends UmbLitElement implements U
187176 ` ;
188177 }
189178
179+ #renderTab( path : string | null , name : string , index = 0 ) {
180+ const isRootTab = path === null ;
181+ const hasRootItems = this . _hasRootGroups || this . _hasRootProperties ;
182+ const basePath = this . _routerPath + '/' ;
183+ const fullPath = basePath + ( path ? path : 'root' ) ;
184+
185+ const active =
186+ fullPath === this . _activePath ||
187+ // When there are no root items, the first tab should be active on the alias path.
188+ ( ! hasRootItems && index === 0 && basePath === this . _activePath ) ||
189+ // When there are root items, the root tab should be active on both the canonical `/root` and alias `/` paths.
190+ ( hasRootItems && isRootTab && basePath === this . _activePath ) ;
191+ return html `<uui- tab
192+ label= ${ this . localize . string ( name ?? '#general_unnamed' ) }
193+ .active = ${ active }
194+ href= ${ isRootTab ? basePath : fullPath }
195+ data- mark= "content- tab: ${ path ?? 'root' } "> </ uui- tab> ` ;
196+ }
197+
190198 static override readonly styles = [
191199 UmbTextStyles ,
192200 css `
0 commit comments