+
+ ${when(
+ this._editMode,
+ () =>
+ html`Done `,
+ () =>
+ html`
+
+
+ `,
+ )}
+
+
+ ${repeat(
+ this._apps,
+ (element) => element.unique,
+ (element) =>
+ html`
+ ${when(
+ this._editMode,
+ () =>
+ html` this.#remove(element.unique)}
+ >`,
+ )}
+ ${this.#renderComponent(element)}
+
`,
+ )}
+
+
+ `;
+ }
+
+ #renderComponent(element: DashboardAppInstance) {
+ // TODO: Hacky rendering of component and entity context
+ const component = element.component;
+ if (!component) throw new Error('Dashboard app component is not defined');
+ const entityContext = new UmbEntityContext(component);
+ entityContext.setEntityType('dashboardApp');
+ entityContext.setUnique(element.unique);
+ return html`${element.component}`;
+ }
+
+ static override styles = [
+ UmbTextStyles,
+ css`
+ :host {
+ container-type: inline-size;
+ --uui-menu-item-flat-structure: 1;
+ }
+
+ #content {
+ padding: var(--uui-size-layout-1);
+ padding-top: var(--uui-size-space-3);
+ container-type: inline-size;
+ }
+
+ .main-actions {
+ display: flex;
+ justify-content: flex-end;
+ }
+
+ uui-box div[slot='header-actions'] uui-button {
+ font-size: 12px;
+ --uui-button-height: auto;
+ }
+
+ uui-box {
+ height: 100%;
+ position: relative;
+ }
+
+ .grid-container {
+ margin-top: var(--uui-size-space-3);
+ display: grid;
+ grid-template-columns: repeat(4, 1fr);
+ grid-auto-rows: 225px;
+ gap: 20px;
+ }
+
+ @container (inline-size < 900px) {
+ .grid-container {
+ grid-template-columns: repeat(3, 1fr);
+ }
+ }
+
+ @container (inline-size < 601px) {
+ .grid-container {
+ grid-template-columns: repeat(1, 1fr);
+ }
+ .grid-container > * {
+ grid-column: span 1 !important;
+ }
+ }
+
+ .dashboard-app {
+ position: relative;
+ display: block;
+ height: 100%;
+
+ &::after {
+ content: '';
+ position: absolute;
+ z-index: 1;
+ pointer-events: none;
+ inset: 0;
+ border: 1px solid transparent;
+ border-radius: var(--uui-border-radius);
+ transition: border-color 240ms ease-in;
+ }
+
+ & > uui-button {
+ position: absolute;
+ top: 0;
+ right: 0;
+ z-index: 1;
+ }
+
+ &[drag-placeholder] {
+ position: relative;
+ display: block;
+ --umb-block-grid-entry-actions-opacity: 0;
+
+ &::after {
+ display: block;
+ border-width: 2px;
+ border-color: var(--uui-color-interactive-emphasis);
+ animation: ${UUIBlinkAnimationValue};
+ }
+
+ &::before {
+ content: '';
+ position: absolute;
+ pointer-events: none;
+ inset: 0;
+ border-radius: var(--uui-border-radius);
+ background-color: var(--uui-color-interactive-emphasis);
+ opacity: 0.12;
+ }
+
+ & > * {
+ transition: opacity 50ms 16ms;
+ opacity: 0;
+ }
+ }
+ }
+ `,
+ ];
+}
+
+export { UmbDashboardElement as element };
+
+declare global {
+ interface HTMLElementTagNameMap {
+ ['umb-dashboard']: UmbDashboardElement;
+ }
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/dashboard/default/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/dashboard/default/index.ts
new file mode 100644
index 000000000000..75b83ef72d33
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/dashboard/default/index.ts
@@ -0,0 +1 @@
+export * from './dashboard.context.token.js';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/dashboard/default/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/dashboard/default/manifests.ts
new file mode 100644
index 000000000000..0d274813ba21
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/dashboard/default/manifests.ts
@@ -0,0 +1,15 @@
+import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry';
+
+export const manifests: Array