Skip to content

Commit bfee99c

Browse files
authored
Block Workspace: Tabs navigation, Cherry-pick from #21672 (#21693)
* cherry-pick from #21672 * cherry pick tab rendering to handle one more case * move the root route down for it to stay an empty path. * Revert empty root path commit * fullPath for root includes 'root' * revert claude settings commit * refactor accordingly to feedback
1 parent ed963b2 commit bfee99c

1 file changed

Lines changed: 39 additions & 31 deletions

File tree

src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/views/edit/block-workspace-view-edit.element.ts

Lines changed: 39 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { UmbBlockWorkspaceElementManagerNames } from '../../block-workspace.context.js';
22
import { UMB_BLOCK_WORKSPACE_CONTEXT } from '../../block-workspace.context-token.js';
33
import 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';
55
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
66
import type { UmbContentTypeModel, UmbPropertyTypeContainerMergedModel } from '@umbraco-cms/backoffice/content-type';
77
import { 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

Comments
 (0)