Browse Source

chore(admin-ui): Improve styling of data table elements

Michael Bromley 2 years ago
parent
commit
7a26f832a4
31 changed files with 243 additions and 94 deletions
  1. 18 18
      packages/admin-ui/i18n-coverage.json
  2. 46 29
      packages/admin-ui/src/lib/catalog/src/components/collection-data-table/collection-data-table.component.html
  3. 1 5
      packages/admin-ui/src/lib/catalog/src/components/collection-data-table/collection-data-table.component.scss
  4. 18 2
      packages/admin-ui/src/lib/catalog/src/components/collection-data-table/collection-data-table.component.ts
  5. 1 1
      packages/admin-ui/src/lib/core/src/common/generated-types.ts
  6. 4 0
      packages/admin-ui/src/lib/core/src/data/definitions/collection-definitions.ts
  7. 1 1
      packages/admin-ui/src/lib/core/src/shared/components/data-table-2/data-table-custom-field-column.component.html
  8. 1 1
      packages/admin-ui/src/lib/core/src/shared/components/data-table-2/data-table2.component.html
  9. 11 1
      packages/admin-ui/src/lib/core/src/shared/components/data-table-2/data-table2.component.scss
  10. 16 10
      packages/admin-ui/src/lib/core/src/shared/components/data-table-column-picker/data-table-column-picker.component.html
  11. 4 0
      packages/admin-ui/src/lib/core/src/shared/components/data-table-column-picker/data-table-column-picker.component.scss
  12. 20 8
      packages/admin-ui/src/lib/core/src/shared/components/items-per-page-controls/items-per-page-controls.component.html
  13. 4 0
      packages/admin-ui/src/lib/core/src/shared/components/page-block/page-block.component.scss
  14. 26 10
      packages/admin-ui/src/lib/core/src/shared/components/pagination-controls/pagination-controls.component.html
  15. 25 5
      packages/admin-ui/src/lib/core/src/shared/components/pagination-controls/pagination-controls.component.scss
  16. 1 1
      packages/admin-ui/src/lib/core/src/shared/components/split-view/split-view.component.html
  17. 2 1
      packages/admin-ui/src/lib/core/src/shared/components/split-view/split-view.component.scss
  18. 6 1
      packages/admin-ui/src/lib/core/src/shared/components/split-view/split-view.component.ts
  19. 3 0
      packages/admin-ui/src/lib/static/i18n-messages/cs.json
  20. 3 0
      packages/admin-ui/src/lib/static/i18n-messages/de.json
  21. 2 0
      packages/admin-ui/src/lib/static/i18n-messages/en.json
  22. 3 0
      packages/admin-ui/src/lib/static/i18n-messages/es.json
  23. 3 0
      packages/admin-ui/src/lib/static/i18n-messages/fr.json
  24. 3 0
      packages/admin-ui/src/lib/static/i18n-messages/it.json
  25. 3 0
      packages/admin-ui/src/lib/static/i18n-messages/pl.json
  26. 3 0
      packages/admin-ui/src/lib/static/i18n-messages/pt_BR.json
  27. 3 0
      packages/admin-ui/src/lib/static/i18n-messages/pt_PT.json
  28. 3 0
      packages/admin-ui/src/lib/static/i18n-messages/ru.json
  29. 3 0
      packages/admin-ui/src/lib/static/i18n-messages/uk.json
  30. 3 0
      packages/admin-ui/src/lib/static/i18n-messages/zh_Hans.json
  31. 3 0
      packages/admin-ui/src/lib/static/i18n-messages/zh_Hant.json

+ 18 - 18
packages/admin-ui/i18n-coverage.json

@@ -1,69 +1,69 @@
 {
-  "generatedOn": "2023-05-12T08:21:18.191Z",
-  "lastCommit": "cac8b3a037147744054096663dbb29bd0830344f",
+  "generatedOn": "2023-05-16T11:06:46.976Z",
+  "lastCommit": "b458c0c43132e11b5605b3d62cfcbb9763f618ce",
   "translationStatus": {
     "cs": {
-      "tokenCount": 703,
+      "tokenCount": 706,
       "translatedCount": 566,
-      "percentage": 81
+      "percentage": 80
     },
     "de": {
-      "tokenCount": 703,
+      "tokenCount": 706,
       "translatedCount": 549,
       "percentage": 78
     },
     "en": {
-      "tokenCount": 703,
-      "translatedCount": 702,
+      "tokenCount": 706,
+      "translatedCount": 703,
       "percentage": 100
     },
     "es": {
-      "tokenCount": 703,
+      "tokenCount": 706,
       "translatedCount": 594,
       "percentage": 84
     },
     "fr": {
-      "tokenCount": 703,
+      "tokenCount": 706,
       "translatedCount": 586,
       "percentage": 83
     },
     "it": {
-      "tokenCount": 703,
+      "tokenCount": 706,
       "translatedCount": 592,
       "percentage": 84
     },
     "pl": {
-      "tokenCount": 703,
+      "tokenCount": 706,
       "translatedCount": 393,
       "percentage": 56
     },
     "pt_BR": {
-      "tokenCount": 703,
+      "tokenCount": 706,
       "translatedCount": 564,
       "percentage": 80
     },
     "pt_PT": {
-      "tokenCount": 703,
+      "tokenCount": 706,
       "translatedCount": 602,
-      "percentage": 86
+      "percentage": 85
     },
     "ru": {
-      "tokenCount": 703,
+      "tokenCount": 706,
       "translatedCount": 591,
       "percentage": 84
     },
     "uk": {
-      "tokenCount": 703,
+      "tokenCount": 706,
       "translatedCount": 591,
       "percentage": 84
     },
     "zh_Hans": {
-      "tokenCount": 703,
+      "tokenCount": 706,
       "translatedCount": 534,
       "percentage": 76
     },
     "zh_Hant": {
-      "tokenCount": 703,
+      "tokenCount": 706,
       "translatedCount": 373,
       "percentage": 53
     }

+ 46 - 29
packages/admin-ui/src/lib/catalog/src/components/collection-data-table/collection-data-table.component.html

@@ -9,16 +9,21 @@
     >
         <thead [class.items-selected]="selectionManager?.selection.length">
             <tr class="heading-row">
-                <th *ngIf="selectionManager" class="flex">
-                    <div class="drag-handle-spacer"></div>
-                    <input
-                        type="checkbox"
-                        clrCheckbox
-                        [checked]="selectionManager?.areAllCurrentItemsSelected()"
-                        (change)="onToggleAllClick()"
-                    />
+                <th *ngIf="selectionManager" class="selection-col">
+                    <div class="flex">
+                        <div class="drag-handle-spacer"></div>
+                        <input
+                            type="checkbox"
+                            clrCheckbox
+                            [checked]="selectionManager?.areAllCurrentItemsSelected()"
+                            (change)="onToggleAllClick()"
+                        />
+                    </div>
                 </th>
-                <th *ngFor="let column of visibleSortedColumns; last as isLast" [class.expand]="column.expand">
+                <th
+                    *ngFor="let column of visibleSortedColumns; last as isLast"
+                    [class.expand]="column.expand"
+                >
                     <div class="cell-content" [ngClass]="column.align">
                         <span>{{ column.heading }}</span>
                         <div *ngIf="column.sort as sort" class="sort-toggle">
@@ -30,19 +35,21 @@
                             <div class="sort-label" *ngIf="sort.sortOrder">{{ sort.sortOrder }}</div>
                         </div>
                     </div>
-
-                    <div *ngIf="isLast" class="column-picker">
+                </th>
+                <th>
+                    <div class="column-picker">
                         <vdr-data-table-colum-picker
                             [uiLanguage]="uiLanguage$ | async"
                             [columns]="sortedColumns"
                             (reorder)="onColumnReorder($event)"
+                            (resetColumns)="onColumnsReset()"
                         ></vdr-data-table-colum-picker>
                     </div>
                 </th>
             </tr>
             <tr *ngIf="searchComponent || customSearchTemplate || filters?.length">
                 <th
-                    [attr.colspan]="visibleSortedColumns.length + (selectionManager ? 1 : 0)"
+                    [attr.colspan]="visibleSortedColumns.length + (selectionManager ? 2 : 1)"
                     class="filter-row"
                     [class.active]="showSearchFilterRow"
                 >
@@ -103,7 +110,7 @@
             </ng-container>
             <ng-container>
                 <tr *ngIf="!items?.length">
-                    <td [attr.colspan]="visibleSortedColumns.length + (selectionManager ? 1 : 0)">
+                    <td [attr.colspan]="visibleSortedColumns.length + (selectionManager ? 2 : 1)">
                         <vdr-empty-placeholder [emptyStateLabel]="emptyStateLabel"></vdr-empty-placeholder>
                     </td>
                 </tr>
@@ -111,13 +118,13 @@
         </tbody>
     </table>
 </div>
-<div class="table-footer ml-4">
+<div class="table-footer">
     <vdr-items-per-page-controls
         *ngIf="totalItems"
         [itemsPerPage]="itemsPerPage"
         (itemsPerPageChange)="itemsPerPageChange.emit($event)"
     ></vdr-items-per-page-controls>
-    <div *ngIf="totalItems" class="p5">
+    <div *ngIf="totalItems" class="p5 total-items-count">
         {{ 'common.total-items' | translate : { currentStart, currentEnd, totalItems } }}
     </div>
 
@@ -131,30 +138,40 @@
     ></vdr-pagination-controls>
 </div>
 
-<ng-template #collectionRowTmp let-item="item" let-i="i" let-depth="depth">
+<ng-template #collectionRowTmp let-item="item" let-depth="depth">
     <tr #collectionRow cdkDrag [cdkDragData]="{ depth: depth, collection: item }" cdkDragBoundary="tbody">
-        <td *ngIf="selectionManager" class="flex" [class.active]="activeIndex === i">
-            <div class="drag-handle" cdkDragHandle [title]="'catalog.reorder-collection' | translate">
-                <clr-icon shape="drag-handle"></clr-icon>
+        <td
+            *ngIf="selectionManager"
+            [class.active]="activeIndex === absoluteIndex[item.id]"
+            class="selection-col"
+        >
+            <div class="flex">
+                <div class="drag-handle" cdkDragHandle [title]="'catalog.reorder-collection' | translate">
+                    <clr-icon shape="drag-handle"></clr-icon>
+                </div>
+                <input
+                    type="checkbox"
+                    clrCheckbox
+                    [checked]="selectionManager?.isSelected(item)"
+                    (click)="onRowClick(item, $event)"
+                />
             </div>
-            <input
-                type="checkbox"
-                clrCheckbox
-                [checked]="selectionManager?.isSelected(item)"
-                (click)="onRowClick(item, $event)"
-            />
         </td>
-        <td *ngFor="let column of visibleSortedColumns" [class.active]="activeIndex === i">
+        <td
+            *ngFor="let column of visibleSortedColumns"
+            [class.active]="activeIndex === absoluteIndex[item.id]"
+        >
             <div class="cell-content" [ngClass]="column.align">
                 <ng-container
-                    *ngTemplateOutlet="column.template; context: { item: item, index: i, depth: depth }"
+                    *ngTemplateOutlet="column.template; context: { item: item, depth: depth }"
                 ></ng-container>
             </div>
         </td>
+        <td [class.active]="activeIndex === absoluteIndex[item.id]"><!-- column select --></td>
     </tr>
-    <ng-container *ngFor="let subCollection of getSubcollections(item); index as j">
+    <ng-container *ngFor="let subCollection of getSubcollections(item)">
         <ng-container
-            *ngTemplateOutlet="collectionRowTmp; context: { item: subCollection, i: i + j, depth: depth + 1 }"
+            *ngTemplateOutlet="collectionRowTmp; context: { item: subCollection, depth: depth + 1 }"
         ></ng-container>
     </ng-container>
 </ng-template>

+ 1 - 5
packages/admin-ui/src/lib/catalog/src/components/collection-data-table/collection-data-table.component.scss

@@ -1,15 +1,11 @@
 .bulk-actions {
     margin-left: calc(var(--space-unit) * 10);
 }
-
-.selection-col {
-    display: flex;
-}
 .drag-handle {
     cursor: grab;
 }
 .drag-handle-spacer {
-    width: 14px;
+    width: 16px;
 }
 
 /* Animate items as they're being sorted. */

+ 18 - 2
packages/admin-ui/src/lib/catalog/src/components/collection-data-table/collection-data-table.component.ts

@@ -6,9 +6,11 @@ import {
     Component,
     EventEmitter,
     Input,
+    OnChanges,
     OnInit,
     Output,
     QueryList,
+    SimpleChanges,
     ViewChild,
     ViewChildren,
 } from '@angular/core';
@@ -37,7 +39,7 @@ export type CollectionOrderEvent = {
 })
 export class CollectionDataTableComponent
     extends DataTable2Component<CollectionTableItem>
-    implements OnInit, AfterViewInit
+    implements OnInit, OnChanges, AfterViewInit
 {
     @Input() subCollections: CollectionTableItem[];
     @Output() changeOrder = new EventEmitter<CollectionOrderEvent>();
@@ -47,6 +49,7 @@ export class CollectionDataTableComponent
     }>;
     @ViewChildren('collectionRow', { read: CdkDrag }) collectionRowList: QueryList<CdkDrag>;
     dragRefs: DragRef[] = [];
+    absoluteIndex: { [id: string]: number } = {};
     constructor(
         protected changeDetectorRef: ChangeDetectorRef,
         protected localStorageService: LocalStorageService,
@@ -60,6 +63,19 @@ export class CollectionDataTableComponent
         super.ngOnInit();
     }
 
+    ngOnChanges(changes: SimpleChanges) {
+        super.ngOnChanges(changes);
+        if (changes.subCollections || changes.items) {
+            const allCollections: CollectionTableItem[] = [];
+            for (const collection of this.items ?? []) {
+                allCollections.push(collection);
+                const subCollectionMatches = this.getSubcollections(collection);
+                allCollections.push(...subCollectionMatches.flat());
+            }
+            allCollections.forEach((collection, index) => (this.absoluteIndex[collection.id] = index));
+        }
+    }
+
     ngAfterViewInit() {
         this.collectionRowList.changes.subscribe((val: QueryList<CdkDrag>) => {
             this.dropList.getSortedItems().forEach(item => this.dropList.removeItem(item));
@@ -72,7 +88,7 @@ export class CollectionDataTableComponent
     }
 
     getSubcollections(item: CollectionTableItem) {
-        return this.subCollections?.filter(c => c.parentId === item.id);
+        return this.subCollections?.filter(c => c.parentId === item.id) ?? [];
     }
 
     /**

+ 1 - 1
packages/admin-ui/src/lib/core/src/common/generated-types.ts

@@ -6696,7 +6696,7 @@ export type PreviewCollectionContentsQueryVariables = Exact<{
 }>;
 
 
-export type PreviewCollectionContentsQuery = { previewCollectionVariants: { __typename?: 'ProductVariantList', totalItems: number, items: Array<{ __typename?: 'ProductVariant', id: string, productId: string, name: string, sku: string }> } };
+export type PreviewCollectionContentsQuery = { previewCollectionVariants: { __typename?: 'ProductVariantList', totalItems: number, items: Array<{ __typename?: 'ProductVariant', id: string, createdAt: any, updatedAt: any, productId: string, name: string, sku: string }> } };
 
 export type AssignCollectionsToChannelMutationVariables = Exact<{
   input: AssignCollectionsToChannelInput;

+ 4 - 0
packages/admin-ui/src/lib/core/src/data/definitions/collection-definitions.ts

@@ -156,6 +156,8 @@ export const GET_COLLECTION_CONTENTS = gql`
             productVariants(options: $options) {
                 items {
                     id
+                    createdAt
+                    updatedAt
                     productId
                     name
                     sku
@@ -174,6 +176,8 @@ export const PREVIEW_COLLECTION_CONTENTS = gql`
         previewCollectionVariants(input: $input, options: $options) {
             items {
                 id
+                createdAt
+                updatedAt
                 productId
                 name
                 sku

+ 1 - 1
packages/admin-ui/src/lib/core/src/shared/components/data-table-2/data-table-custom-field-column.component.html

@@ -25,7 +25,7 @@
                     <button
                         class="btn btn-link btn-icon"
                         vdrDropdownTrigger
-                        [title]="'common.info' | translate"
+                        [title]="'common.details' | translate"
                     >
                         <clr-icon shape="details"></clr-icon>
                     </button>

+ 1 - 1
packages/admin-ui/src/lib/core/src/shared/components/data-table-2/data-table2.component.html

@@ -128,7 +128,7 @@
         [itemsPerPage]="itemsPerPage"
         (itemsPerPageChange)="itemsPerPageChange.emit($event)"
     ></vdr-items-per-page-controls>
-    <div *ngIf="totalItems" class="p5">
+    <div *ngIf="totalItems" class="total-items-count">
         {{ 'common.total-items' | translate : { currentStart, currentEnd, totalItems } }}
     </div>
 

+ 11 - 1
packages/admin-ui/src/lib/core/src/shared/components/data-table-2/data-table2.component.scss

@@ -5,6 +5,7 @@
     max-width: 100%;
     position: relative;
     margin-bottom: calc(var(--space-unit) * 4);
+    container-type: inline-size;
 }
 
 .bulk-actions {
@@ -198,6 +199,15 @@ vdr-empty-placeholder {
     display: flex;
     align-items: baseline;
     justify-content: space-between;
-    margin-top: 6px;
+    margin-top: var(--space-unit);
     margin-left: var(--surface-margin-left);
+    margin-right: 3px;
+}
+.total-items-count {
+    font-size: var(--font-size-xs);
+}
+@container (max-width: 500px) {
+    .total-items-count {
+        display: none;
+    }
 }

+ 16 - 10
packages/admin-ui/src/lib/core/src/shared/components/data-table-column-picker/data-table-column-picker.component.html

@@ -14,19 +14,25 @@
                 <div cdkDragHandle class="drag-handle">
                     <clr-icon shape="drag-handle"></clr-icon>
                 </div>
-                <label>
-                    <input
-                        type="checkbox"
-                        [disabled]="column.optional === false"
-                        [checked]="column.visible"
-                        (change)="toggleColumn(column)"
-                        class="mr-1"
-                    />
-                    <span>{{ column.heading | translate }}</span>
+                <label class="flex">
+                    <clr-checkbox-container>
+                        <clr-checkbox-wrapper>
+                            <input
+                                type="checkbox"
+                                clrCheckbox
+                                [disabled]="column.optional === false"
+                                [indeterminate]="column.optional === false"
+                                [checked]="column.visible"
+                                (change)="toggleColumn(column)"
+                                class="mr-1"
+                            />
+                            <label>{{ column.heading | translate }}</label>
+                        </clr-checkbox-wrapper>
+                    </clr-checkbox-container>
                 </label>
             </div>
         </div>
-        <div class="mt-1 mx-1 flex center">
+        <div class="mt-1 pt-1 mx-1 flex center reset-button">
             <button class="button-small" (click)="reset()">
                 <span>{{ 'common.reset-columns' | translate }}</span>
                 <clr-icon shape="history"></clr-icon>

+ 4 - 0
packages/admin-ui/src/lib/core/src/shared/components/data-table-column-picker/data-table-column-picker.component.scss

@@ -15,3 +15,7 @@
 .cdk-drag-preview {
     opacity: 0;
 }
+
+.reset-button {
+    border-top: 1px solid var(--color-weight-125);
+}

+ 20 - 8
packages/admin-ui/src/lib/core/src/shared/components/items-per-page-controls/items-per-page-controls.component.html

@@ -1,8 +1,20 @@
-<div class="select">
-    <select [ngModel]="itemsPerPage" (change)="itemsPerPageChange.emit($event.target.value)">
-        <option [value]="10">{{ 'common.items-per-page-option' | translate: { count: 10 } }}</option>
-        <option [value]="25">{{ 'common.items-per-page-option' | translate: { count: 25 } }}</option>
-        <option [value]="50">{{ 'common.items-per-page-option' | translate: { count: 50 } }}</option>
-        <option [value]="100">{{ 'common.items-per-page-option' | translate: { count: 100 } }}</option>
-    </select>
-</div>
+<vdr-dropdown>
+    <button class="button" vdrDropdownTrigger>
+        <span>{{ 'common.items-per-page-option' | translate : { count: itemsPerPage } }}</span>
+        <clr-icon shape="ellipsis-vertical"></clr-icon>
+    </button>
+    <vdr-dropdown-menu vdrPosition="bottom-left">
+        <button vdrDropdownItem (click)="itemsPerPageChange.emit(10)">
+            {{ 'common.items-per-page-option' | translate : { count: 10 } }}
+        </button>
+        <button vdrDropdownItem (click)="itemsPerPageChange.emit(25)">
+            {{ 'common.items-per-page-option' | translate : { count: 25 } }}
+        </button>
+        <button vdrDropdownItem (click)="itemsPerPageChange.emit(50)">
+            {{ 'common.items-per-page-option' | translate : { count: 50 } }}
+        </button>
+        <button vdrDropdownItem (click)="itemsPerPageChange.emit(100)">
+            {{ 'common.items-per-page-option' | translate : { count: 100 } }}
+        </button>
+    </vdr-dropdown-menu>
+</vdr-dropdown>

+ 4 - 0
packages/admin-ui/src/lib/core/src/shared/components/page-block/page-block.component.scss

@@ -1,5 +1,9 @@
 @import "variables";
 
+:host {
+    margin-top: var(--space-unit);
+    display: block;
+}
 .page-block {
     margin-left: var(--surface-margin-left);
 }

+ 26 - 10
packages/admin-ui/src/lib/core/src/shared/components/pagination-controls/pagination-controls.component.html

@@ -1,26 +1,42 @@
 <pagination-template #p="paginationApi" (pageChange)="pageChange.emit($event)" [id]="id">
     <ul>
         <li class="pagination-previous">
-            <a *ngIf="!p.isFirstPage()" (click)="p.previous()" (keyup.enter)="p.previous()" tabindex="0">«</a>
-            <div *ngIf="p.isFirstPage()">«</div>
+            <button
+                class="button"
+                [disabled]="p.isFirstPage()"
+                (click)="p.previous()"
+                (keyup.enter)="p.previous()"
+                tabindex="0"
+            >
+                «
+            </button>
         </li>
 
-        <li *ngFor="let page of p.pages">
-            <a
+        <li
+            *ngFor="let page of p.pages"
+            class="page-number-button"
+            [class.current]="p.getCurrent() === page.value && !(p.isFirstPage() && p.isLastPage())"
+        >
+            <button
+                class="button"
                 (click)="p.setCurrent(page.value)"
                 (keyup.enter)="p.setCurrent(page.value)"
-                *ngIf="p.getCurrent() !== page.value"
                 tabindex="0"
             >
                 {{ page.label }}
-            </a>
-
-            <div class="current" *ngIf="p.getCurrent() === page.value">{{ page.label }}</div>
+            </button>
         </li>
 
         <li class="pagination-next">
-            <a *ngIf="!p.isLastPage()" (click)="p.next()" (keyup.enter)="p.next()" tabindex="0">»</a>
-            <div *ngIf="p.isLastPage()">»</div>
+            <button
+                class="button"
+                [disabled]="p.isLastPage()"
+                (click)="p.next()"
+                (keyup.enter)="p.next()"
+                tabindex="0"
+            >
+                »
+            </button>
         </li>
     </ul>
 </pagination-template>

+ 25 - 5
packages/admin-ui/src/lib/core/src/shared/components/pagination-controls/pagination-controls.component.scss

@@ -1,28 +1,48 @@
-
 pagination-template {
     display: block;
     ul {
         list-style-type: none;
         display: flex;
         justify-content: center;
+        gap: 2px;
     }
     li {
         transition: border-bottom-color 0.2s;
     }
     li > a {
         cursor: pointer;
-        &:hover, &:focus {
+        &:hover,
+        &:focus {
             border-bottom-color: var(--color-grey-300);
             text-decoration: none;
         }
     }
-    li > a, li > div {
+    li > a,
+    li > div {
         padding: 3px 12px;
         display: block;
-        border-bottom: 3px solid transparent;
         user-select: none;
     }
-    li > div.current {
+    button {
+    }
+    .page-number-button button {
+        box-shadow: none;
+        border-bottom: 2px solid transparent;
+        font-size: var(--font-size-xs);
+    }
+    .page-number-button.current button {
         border-bottom-color: var(--color-primary-500);
     }
+    .pagination-previous,
+    .pagination-next {
+        z-index: 1;
+    }
+}
+@container (max-width: 500px) {
+    .page-number-button:not(.current) {
+        display: none;
+    }
+    .page-number-button.current button {
+        border-bottom-color: transparent !important;
+    }
 }

+ 1 - 1
packages/admin-ui/src/lib/core/src/shared/components/split-view/split-view.component.html

@@ -1,5 +1,5 @@
 <div class="split-view-wrapper" [class.expanded]="rightPanelOpen" [class.resizing]="resizing$ | async">
-    <div class="left-panel">
+    <div class="left-panel" [style.width]="leftPanelWidth$ | async">
         <ng-container *ngTemplateOutlet="leftTemplate"></ng-container>
     </div>
     <div class="separator" [class.hidden]="!rightPanelOpen">

+ 2 - 1
packages/admin-ui/src/lib/core/src/shared/components/split-view/split-view.component.scss

@@ -1,5 +1,6 @@
 :host {
     --separator-border: var(--color-split-view-separator-border);
+    max-width: var(--surface-width);
 }
 
 .split-view-wrapper {
@@ -69,7 +70,7 @@
     display: flex;
     justify-content: space-between;
     padding: calc(var(--space-unit) * 1);
-    padding-left: calc(var(--space-unit) * 4);
+    padding-left: var(--surface-margin-left);
     padding-right: 4px;
 }
 .right-panel {

+ 6 - 1
packages/admin-ui/src/lib/core/src/shared/components/split-view/split-view.component.ts

@@ -12,6 +12,7 @@ import {
     ViewChild,
     ViewContainerRef,
 } from '@angular/core';
+import { DomSanitizer, SafeStyle } from '@angular/platform-browser';
 import { fromEvent, merge, Observable, switchMap } from 'rxjs';
 import { map, mapTo, startWith, takeUntil } from 'rxjs/operators';
 import { SplitViewLeftDirective, SplitViewRightDirective } from './split-view.directive';
@@ -32,9 +33,10 @@ export class SplitViewComponent implements AfterContentInit, AfterViewInit {
     rightTemplate: SplitViewRightDirective;
     @ViewChild('resizeHandle', { static: true, read: ElementRef }) resizeHandle: ElementRef<HTMLDivElement>;
     protected rightPanelWidth$: Observable<number>;
+    protected leftPanelWidth$: Observable<SafeStyle>;
     protected resizing$: Observable<boolean>;
 
-    constructor(private viewContainerRef: ViewContainerRef) {}
+    constructor(private viewContainerRef: ViewContainerRef, private domSanitizer: DomSanitizer) {}
 
     ngAfterContentInit(): void {
         if (!this.leftTemplate) {
@@ -62,6 +64,9 @@ export class SplitViewComponent implements AfterContentInit, AfterViewInit {
             }),
             startWith(hostElementWidth / 2),
         );
+        this.leftPanelWidth$ = this.rightPanelWidth$.pipe(
+            map(width => `calc(var(--surface-width) - ${width}px)`),
+        );
 
         this.resizing$ = merge(mouseDown$.pipe(mapTo(true)), mouseUp$.pipe(mapTo(false)));
     }

+ 3 - 0
packages/admin-ui/src/lib/static/i18n-messages/cs.json

@@ -100,6 +100,7 @@
     "edit-options": "",
     "facet-value-not-available": "",
     "facet-values": "Hodnoty atributů",
+    "facets": "",
     "filter-by-name": "Filtrovat dle jména",
     "filter-by-name-or-sku": "Filtrovat dle jména nebo SKU",
     "filter-inheritance": "",
@@ -235,6 +236,7 @@
     "guest": "Host",
     "id": "",
     "image": "",
+    "info": "",
     "items-per-page-option": "{ count } na stránku",
     "items-selected-count": "",
     "keep-editing": "",
@@ -286,6 +288,7 @@
     "remember-me": "Zapamatovat",
     "remove": "Smazat",
     "remove-item-from-list": "Odebrat položku ze seznamu",
+    "reset-columns": "",
     "results-count": "{ count } {count, plural, one {výsledek} other {výsledků/y}}",
     "sample-formatting": "",
     "search-and-filter-list": "",

+ 3 - 0
packages/admin-ui/src/lib/static/i18n-messages/de.json

@@ -100,6 +100,7 @@
     "edit-options": "",
     "facet-value-not-available": "",
     "facet-values": "Facettenwerte",
+    "facets": "",
     "filter-by-name": "Nach Name filtern",
     "filter-by-name-or-sku": "Nach Name oder Artikelnummer filtern",
     "filter-inheritance": "",
@@ -235,6 +236,7 @@
     "guest": "Gast",
     "id": "",
     "image": "",
+    "info": "",
     "items-per-page-option": "{ count } pro Seite",
     "items-selected-count": "",
     "keep-editing": "",
@@ -286,6 +288,7 @@
     "remember-me": "Logindaten merken",
     "remove": "Entfernen",
     "remove-item-from-list": "Artikel von Liste entfernen",
+    "reset-columns": "",
     "results-count": "{ count } {count, plural, one {Ergebnis} other {Ergebnisse}}",
     "sample-formatting": "",
     "search-and-filter-list": "",

+ 2 - 0
packages/admin-ui/src/lib/static/i18n-messages/en.json

@@ -100,6 +100,7 @@
     "edit-options": "Edit options",
     "facet-value-not-available": "Facet value \"{ id }\" not available",
     "facet-values": "Facet values",
+    "facets": "Facets",
     "filter-by-name": "Filter by name",
     "filter-by-name-or-sku": "Filter by name or SKU",
     "filter-inheritance": "Filter inheritance",
@@ -286,6 +287,7 @@
     "remember-me": "Remember me",
     "remove": "Remove",
     "remove-item-from-list": "Remove item from list",
+    "reset-columns": "Reset columns",
     "results-count": "{ count } {count, plural, one {result} other {results}}",
     "sample-formatting": "Sample formatting",
     "search-and-filter-list": "Search and filter this list",

+ 3 - 0
packages/admin-ui/src/lib/static/i18n-messages/es.json

@@ -100,6 +100,7 @@
     "edit-options": "Editar opciones",
     "facet-value-not-available": "",
     "facet-values": "Valores de faceta",
+    "facets": "",
     "filter-by-name": "Filtrar por nombre",
     "filter-by-name-or-sku": "Filtrar por código de referencia",
     "filter-inheritance": "",
@@ -235,6 +236,7 @@
     "guest": "Invitado",
     "id": "",
     "image": "",
+    "info": "",
     "items-per-page-option": "{ count } por página",
     "items-selected-count": "",
     "keep-editing": "",
@@ -286,6 +288,7 @@
     "remember-me": "Recordarme",
     "remove": "Borrar",
     "remove-item-from-list": "Eliminar elemento de la lista",
+    "reset-columns": "",
     "results-count": "{ count } {count, plural, one {resultado} other {resultados}}",
     "sample-formatting": "",
     "search-and-filter-list": "",

+ 3 - 0
packages/admin-ui/src/lib/static/i18n-messages/fr.json

@@ -100,6 +100,7 @@
     "edit-options": "",
     "facet-value-not-available": "",
     "facet-values": "Valeurs de composant",
+    "facets": "",
     "filter-by-name": "Filtrer par nom",
     "filter-by-name-or-sku": "Filtrer par nom ou UGS",
     "filter-inheritance": "",
@@ -235,6 +236,7 @@
     "guest": "Invité",
     "id": "",
     "image": "",
+    "info": "",
     "items-per-page-option": "{ count } par page",
     "items-selected-count": "",
     "keep-editing": "",
@@ -286,6 +288,7 @@
     "remember-me": "Se souvenir de moi",
     "remove": "Retirer",
     "remove-item-from-list": "Retirer l'article de la liste",
+    "reset-columns": "",
     "results-count": "{ count } {count, plural, one {resultat} other {resultats}}",
     "sample-formatting": "",
     "search-and-filter-list": "",

+ 3 - 0
packages/admin-ui/src/lib/static/i18n-messages/it.json

@@ -100,6 +100,7 @@
     "edit-options": "",
     "facet-value-not-available": "",
     "facet-values": "Valori attributo",
+    "facets": "",
     "filter-by-name": "Filtra per nome",
     "filter-by-name-or-sku": "Filtra per nome o SKU",
     "filter-inheritance": "",
@@ -235,6 +236,7 @@
     "guest": "Ospite",
     "id": "",
     "image": "",
+    "info": "",
     "items-per-page-option": "{ count } per pagina",
     "items-selected-count": "",
     "keep-editing": "",
@@ -286,6 +288,7 @@
     "remember-me": "Ricordami",
     "remove": "Rimuovi",
     "remove-item-from-list": "Rimuovi elemento dalla lista",
+    "reset-columns": "",
     "results-count": "{ count } {count, plural, one {risultato} other {risultati}}",
     "sample-formatting": "",
     "search-and-filter-list": "",

+ 3 - 0
packages/admin-ui/src/lib/static/i18n-messages/pl.json

@@ -100,6 +100,7 @@
     "edit-options": "",
     "facet-value-not-available": "",
     "facet-values": "Wartości faseta",
+    "facets": "",
     "filter-by-name": "Filtruj po nazwie",
     "filter-by-name-or-sku": "",
     "filter-inheritance": "",
@@ -235,6 +236,7 @@
     "guest": "Gość",
     "id": "",
     "image": "",
+    "info": "",
     "items-per-page-option": "{ count } na stronę",
     "items-selected-count": "",
     "keep-editing": "",
@@ -286,6 +288,7 @@
     "remember-me": "Zapamiętaj mnie",
     "remove": "Usuń",
     "remove-item-from-list": "",
+    "reset-columns": "",
     "results-count": "{ count } {count, plural, one {wynik} other {wyników}}",
     "sample-formatting": "",
     "search-and-filter-list": "",

+ 3 - 0
packages/admin-ui/src/lib/static/i18n-messages/pt_BR.json

@@ -100,6 +100,7 @@
     "edit-options": "",
     "facet-value-not-available": "",
     "facet-values": "Valor da Etiqueta",
+    "facets": "",
     "filter-by-name": "Filtrar por nome",
     "filter-by-name-or-sku": "Filtrar por nome ou SKU",
     "filter-inheritance": "",
@@ -235,6 +236,7 @@
     "guest": "Convidado",
     "id": "",
     "image": "",
+    "info": "",
     "items-per-page-option": "{ count } por página",
     "items-selected-count": "",
     "keep-editing": "",
@@ -286,6 +288,7 @@
     "remember-me": "Lembre de mim",
     "remove": "Exclui",
     "remove-item-from-list": "",
+    "reset-columns": "",
     "results-count": "{ count } {count, plural, one {result} other {results}}",
     "sample-formatting": "",
     "search-and-filter-list": "",

+ 3 - 0
packages/admin-ui/src/lib/static/i18n-messages/pt_PT.json

@@ -100,6 +100,7 @@
     "edit-options": "Editar opções",
     "facet-value-not-available": "",
     "facet-values": "Valor da Etiqueta",
+    "facets": "",
     "filter-by-name": "Filtrar por nome",
     "filter-by-name-or-sku": "Filtrar por nome ou SKU",
     "filter-inheritance": "",
@@ -235,6 +236,7 @@
     "guest": "Convidado",
     "id": "",
     "image": "",
+    "info": "",
     "items-per-page-option": "{ count } por página",
     "items-selected-count": "",
     "keep-editing": "",
@@ -286,6 +288,7 @@
     "remember-me": "Lembre-se de mim",
     "remove": "Eliminar",
     "remove-item-from-list": "Remover item da lista",
+    "reset-columns": "",
     "results-count": "{ count } {count, plural, one {resultado} other {resultados}}",
     "sample-formatting": "Formatação de amostra",
     "search-and-filter-list": "",

+ 3 - 0
packages/admin-ui/src/lib/static/i18n-messages/ru.json

@@ -100,6 +100,7 @@
     "edit-options": "",
     "facet-value-not-available": "",
     "facet-values": "Значения тега",
+    "facets": "",
     "filter-by-name": "Фильтр по имени",
     "filter-by-name-or-sku": "Фильтр по имени или артикулу (SKU)",
     "filter-inheritance": "",
@@ -235,6 +236,7 @@
     "guest": "Гость",
     "id": "",
     "image": "",
+    "info": "",
     "items-per-page-option": "{ count } на странице",
     "items-selected-count": "",
     "keep-editing": "",
@@ -286,6 +288,7 @@
     "remember-me": "Запомнить меня",
     "remove": "Удалить",
     "remove-item-from-list": "Удалить позицию из списка",
+    "reset-columns": "",
     "results-count": "{ count } {count, plural, one {результат} other {результатов}}",
     "sample-formatting": "",
     "search-and-filter-list": "",

+ 3 - 0
packages/admin-ui/src/lib/static/i18n-messages/uk.json

@@ -100,6 +100,7 @@
     "edit-options": "",
     "facet-value-not-available": "",
     "facet-values": "Значення тегу",
+    "facets": "",
     "filter-by-name": "Фільтр по імені",
     "filter-by-name-or-sku": "Фільтр по імені або артикулу (SKU)",
     "filter-inheritance": "",
@@ -235,6 +236,7 @@
     "guest": "Гість",
     "id": "",
     "image": "",
+    "info": "",
     "items-per-page-option": "{ count } на сторінці",
     "items-selected-count": "",
     "keep-editing": "",
@@ -286,6 +288,7 @@
     "remember-me": "Запам'ятати мене",
     "remove": "Видалити",
     "remove-item-from-list": "Видалити позицію зі списку",
+    "reset-columns": "",
     "results-count": "{ count } {count, plural, one {результат} other {результатів}}",
     "sample-formatting": "",
     "search-and-filter-list": "",

+ 3 - 0
packages/admin-ui/src/lib/static/i18n-messages/zh_Hans.json

@@ -100,6 +100,7 @@
     "edit-options": "",
     "facet-value-not-available": "",
     "facet-values": "特征值列表",
+    "facets": "",
     "filter-by-name": "按名字过滤",
     "filter-by-name-or-sku": "按名字或商品编码过滤",
     "filter-inheritance": "",
@@ -235,6 +236,7 @@
     "guest": "游客",
     "id": "",
     "image": "",
+    "info": "",
     "items-per-page-option": "每页显示 { count } 条",
     "items-selected-count": "",
     "keep-editing": "",
@@ -286,6 +288,7 @@
     "remember-me": "记住我",
     "remove": "删除",
     "remove-item-from-list": "从列表中移除",
+    "reset-columns": "",
     "results-count": "{count, plural, =0{无} other {{count}个过滤结果}}",
     "sample-formatting": "",
     "search-and-filter-list": "",

+ 3 - 0
packages/admin-ui/src/lib/static/i18n-messages/zh_Hant.json

@@ -100,6 +100,7 @@
     "edit-options": "",
     "facet-value-not-available": "",
     "facet-values": "特徵值列表",
+    "facets": "",
     "filter-by-name": "按名字篩選",
     "filter-by-name-or-sku": "",
     "filter-inheritance": "",
@@ -235,6 +236,7 @@
     "guest": "游客",
     "id": "",
     "image": "",
+    "info": "",
     "items-per-page-option": "每页顯示 { count } 條",
     "items-selected-count": "",
     "keep-editing": "",
@@ -286,6 +288,7 @@
     "remember-me": "記住登入帳號",
     "remove": "移除",
     "remove-item-from-list": "",
+    "reset-columns": "",
     "results-count": "{count, plural, =0{無} other {{count}個篩選結果}}",
     "sample-formatting": "",
     "search-and-filter-list": "",