From 04107da7369fca772062d5d0b50695ea09459436 Mon Sep 17 00:00:00 2001 From: Tomi Virkki Date: Thu, 23 May 2024 17:28:06 +0300 Subject: [PATCH] feat: add slot for empty state content (#7429) --- .../grid/src/vaadin-grid-active-item-mixin.js | 2 +- .../vaadin-grid-keyboard-navigation-mixin.js | 6 +- packages/grid/src/vaadin-grid-mixin.js | 23 ++++ packages/grid/src/vaadin-grid-styles.js | 26 ++++ packages/grid/src/vaadin-grid.d.ts | 1 + packages/grid/src/vaadin-grid.js | 9 ++ packages/grid/src/vaadin-lit-grid.js | 8 ++ packages/grid/test/accessibility.common.js | 10 +- packages/grid/test/basic.common.js | 125 +++++++++++++++++- .../test/dom/__snapshots__/grid.test.snap.js | 75 +++++++++++ packages/grid/test/frozen-columns.common.js | 2 +- packages/grid/test/helpers.js | 2 +- .../grid/test/keyboard-navigation.common.js | 97 +++++++++++++- packages/grid/test/visual/grid.common.js | 29 ++++ packages/grid/test/visual/lumo/grid.test.js | 13 ++ .../grid/baseline/empty-state-compact.png | Bin 0 -> 5830 bytes .../screenshots/grid/baseline/empty-state.png | Bin 0 -> 15337 bytes .../screenshots/grid/baseline/empty-state.png | Bin 0 -> 15561 bytes .../grid/theme/lumo/vaadin-grid-styles.js | 10 ++ .../grid/theme/material/vaadin-grid-styles.js | 6 + 20 files changed, 433 insertions(+), 11 deletions(-) create mode 100644 packages/grid/test/visual/lumo/screenshots/grid/baseline/empty-state-compact.png create mode 100644 packages/grid/test/visual/lumo/screenshots/grid/baseline/empty-state.png create mode 100644 packages/grid/test/visual/material/screenshots/grid/baseline/empty-state.png diff --git a/packages/grid/src/vaadin-grid-active-item-mixin.js b/packages/grid/src/vaadin-grid-active-item-mixin.js index 607f35b166..2145b4ab7c 100644 --- a/packages/grid/src/vaadin-grid-active-item-mixin.js +++ b/packages/grid/src/vaadin-grid-active-item-mixin.js @@ -83,7 +83,7 @@ export const ActiveItemMixin = (superClass) => const path = e.composedPath(); const cell = path[path.indexOf(this.$.table) - 3]; - if (!cell || cell.getAttribute('part').indexOf('details-cell') > -1) { + if (!cell || cell.getAttribute('part').indexOf('details-cell') > -1 || cell === this.$.emptystatecell) { return; } const cellContent = cell._content; diff --git a/packages/grid/src/vaadin-grid-keyboard-navigation-mixin.js b/packages/grid/src/vaadin-grid-keyboard-navigation-mixin.js index 101f84d051..3a3402df47 100644 --- a/packages/grid/src/vaadin-grid-keyboard-navigation-mixin.js +++ b/packages/grid/src/vaadin-grid-keyboard-navigation-mixin.js @@ -675,7 +675,7 @@ export const KeyboardNavigationMixin = (superClass) => const tabOrder = [ this.$.table, this._headerFocusable, - this._itemsFocusable, + this.__emptyState ? this.$.emptystatecell : this._itemsFocusable, this._footerFocusable, this.$.focusexit, ]; @@ -860,7 +860,7 @@ export const KeyboardNavigationMixin = (superClass) => if (cell) { const context = this.getEventContext(e); this.__pendingBodyCellFocus = this.loading && context.section === 'body'; - if (!this.__pendingBodyCellFocus) { + if (!this.__pendingBodyCellFocus && cell !== this.$.emptystatecell) { // Fire a cell-focus event for the cell cell.dispatchEvent(new CustomEvent('cell-focus', { bubbles: true, composed: true, detail: { context } })); } @@ -907,7 +907,7 @@ export const KeyboardNavigationMixin = (superClass) => * @private */ _detectInteracting(e) { - const isInteracting = e.composedPath().some((el) => el.localName === 'vaadin-grid-cell-content'); + const isInteracting = e.composedPath().some((el) => el.localName === 'slot' && this.shadowRoot.contains(el)); this._setInteracting(isInteracting); this.__updateHorizontalScrollPosition(); } diff --git a/packages/grid/src/vaadin-grid-mixin.js b/packages/grid/src/vaadin-grid-mixin.js index 85d4df21fb..1535a1fe39 100644 --- a/packages/grid/src/vaadin-grid-mixin.js +++ b/packages/grid/src/vaadin-grid-mixin.js @@ -9,6 +9,7 @@ import { animationFrame, microTask } from '@vaadin/component-base/src/async.js'; import { isAndroid, isChrome, isFirefox, isIOS, isSafari, isTouch } from '@vaadin/component-base/src/browser-utils.js'; import { Debouncer } from '@vaadin/component-base/src/debounce.js'; import { getClosestElement } from '@vaadin/component-base/src/dom-utils.js'; +import { SlotObserver } from '@vaadin/component-base/src/slot-observer.js'; import { processTemplates } from '@vaadin/component-base/src/templates.js'; import { TooltipController } from '@vaadin/component-base/src/tooltip-controller.js'; import { Virtualizer } from '@vaadin/component-base/src/virtualizer.js'; @@ -156,6 +157,18 @@ export const GridMixin = (superClass) => type: Boolean, value: true, }, + + /** @private */ + __hasEmptyStateContent: { + type: Boolean, + value: false, + }, + + /** @private */ + __emptyState: { + type: Boolean, + computed: '__computeEmptyState(_flatSize, __hasEmptyStateContent)', + }, }; } @@ -261,6 +274,11 @@ export const GridMixin = (superClass) => this._tooltipController = new TooltipController(this); this.addController(this._tooltipController); this._tooltipController.setManual(true); + + this.__emptyStateContentObserver = new SlotObserver(this.$.emptystateslot, ({ currentNodes }) => { + this.$.emptystatecell._content = currentNodes[0]; + this.__hasEmptyStateContent = !!this.$.emptystatecell._content; + }); } /** @private */ @@ -864,6 +882,11 @@ export const GridMixin = (superClass) => }); } + /** @private */ + __computeEmptyState(flatSize, hasEmptyStateContent) { + return flatSize === 0 && hasEmptyStateContent; + } + /** * @param {!Array} columnTree * @protected diff --git a/packages/grid/src/vaadin-grid-styles.js b/packages/grid/src/vaadin-grid-styles.js index 419491ceab..a23ad3a9eb 100644 --- a/packages/grid/src/vaadin-grid-styles.js +++ b/packages/grid/src/vaadin-grid-styles.js @@ -189,6 +189,32 @@ export const gridStyles = css` overflow: hidden; } + /* Empty state */ + + #scroller:not([empty-state]) #emptystatebody, + #scroller[empty-state] #items { + display: none; + } + + #emptystatebody { + display: flex; + position: sticky; + inset: 0; + flex: 1; + overflow: hidden; + } + + #emptystaterow { + display: flex; + flex: 1; + } + + #emptystatecell { + display: block; + flex: 1; + overflow: auto; + } + /* Reordering styles */ :host([reordering]) [part~='cell'] ::slotted(vaadin-grid-cell-content), :host([reordering]) [part~='resize-handle'], diff --git a/packages/grid/src/vaadin-grid.d.ts b/packages/grid/src/vaadin-grid.d.ts index 084efbddd4..058306e0e3 100644 --- a/packages/grid/src/vaadin-grid.d.ts +++ b/packages/grid/src/vaadin-grid.d.ts @@ -205,6 +205,7 @@ export type GridDefaultItem = any; * `reorder-allowed-cell` | Cell in a column where another column can be reordered * `reorder-dragging-cell` | Cell in a column currently being reordered * `resize-handle` | Handle for resizing the columns + * `empty-state` | The container for the content to be displayed when there are no body rows to show * `reorder-ghost` | Ghost element of the header cell being dragged * * The following state attributes are available for styling: diff --git a/packages/grid/src/vaadin-grid.js b/packages/grid/src/vaadin-grid.js index 6b23311e1b..00442bb8f0 100644 --- a/packages/grid/src/vaadin-grid.js +++ b/packages/grid/src/vaadin-grid.js @@ -205,6 +205,7 @@ registerStyles('vaadin-grid', gridStyles, { moduleId: 'vaadin-grid-styles' }); * `reorder-allowed-cell` | Cell in a column where another column can be reordered * `reorder-dragging-cell` | Cell in a column currently being reordered * `resize-handle` | Handle for resizing the columns + * `empty-state` | The container for the content to be displayed when there are no body rows to show * `reorder-ghost` | Ghost element of the header cell being dragged * * The following state attributes are available for styling: @@ -268,11 +269,19 @@ class Grid extends GridMixin(ElementMixin(ThemableMixin(ControllerMixin(PolymerE ios$="[[_ios]]" loading$="[[loading]]" column-reordering-allowed$="[[columnReorderingAllowed]]" + empty-state$="[[__emptyState]]" > + + + + +
+ +
diff --git a/packages/grid/src/vaadin-lit-grid.js b/packages/grid/src/vaadin-lit-grid.js index a19746ff8b..8ea129a989 100644 --- a/packages/grid/src/vaadin-lit-grid.js +++ b/packages/grid/src/vaadin-lit-grid.js @@ -40,11 +40,19 @@ class Grid extends GridMixin(ElementMixin(ThemableMixin(PolylitMixin(LitElement) ios="${isIOS}" ?loading="${this.loading}" column-reordering-allowed="${this.columnReorderingAllowed}" + ?empty-state="${this.__emptyState}" > + + + + +
+ +
diff --git a/packages/grid/test/accessibility.common.js b/packages/grid/test/accessibility.common.js index b16dd7a79b..4e00b3e6b2 100644 --- a/packages/grid/test/accessibility.common.js +++ b/packages/grid/test/accessibility.common.js @@ -269,7 +269,9 @@ describe('accessibility', () => { col.path = 'value'; flushGrid(grid); - const rowCount = Array.from(grid.$.table.querySelectorAll('tr')).filter((tr) => !tr.hidden).length; + const rowCount = Array.from(grid.$.table.querySelectorAll('tr:not(#emptystaterow)')).filter( + (tr) => !tr.hidden, + ).length; expect(grid.$.table.getAttribute('aria-rowcount')).to.equal(String(rowCount)); expect(grid.$.table.getAttribute('aria-rowcount')).to.equal('3'); }); @@ -279,7 +281,9 @@ describe('accessibility', () => { col.header = null; flushGrid(grid); - const rowCount = Array.from(grid.$.table.querySelectorAll('tr')).filter((tr) => !tr.hidden).length; + const rowCount = Array.from(grid.$.table.querySelectorAll('tr:not(#emptystaterow)')).filter( + (tr) => !tr.hidden, + ).length; expect(grid.$.table.getAttribute('aria-rowcount')).to.equal(String(rowCount)); expect(grid.$.table.getAttribute('aria-rowcount')).to.equal('2'); }); @@ -323,7 +327,7 @@ describe('accessibility', () => { } it('should have aria-rowindex on rows', () => { - Array.from(grid.$.table.querySelectorAll('tr')).forEach((row, index) => { + Array.from(grid.$.table.querySelectorAll('tr:not(#emptystaterow)')).forEach((row, index) => { expect(row.getAttribute('aria-rowindex')).to.equal((index + 1).toString()); }); }); diff --git a/packages/grid/test/basic.common.js b/packages/grid/test/basic.common.js index 06dcb29969..bae8ceccb1 100644 --- a/packages/grid/test/basic.common.js +++ b/packages/grid/test/basic.common.js @@ -50,7 +50,7 @@ describe('basic features', () => { it('check visible item count', () => { grid.size = 10; flushGrid(grid); - expect(grid.shadowRoot.querySelectorAll('tbody tr:not([hidden])').length).to.eql(10); + expect(grid.shadowRoot.querySelectorAll('tbody tr:not([hidden]):not(#emptystaterow)').length).to.eql(10); }); it('first visible item', () => { @@ -363,3 +363,126 @@ describe('flex child', () => { }); }); }); + +describe('empty state', () => { + let grid; + + function getEmptyState() { + return grid.querySelector('[slot="empty-state"]'); + } + + function emptyStateVisible() { + return getEmptyState()?.offsetHeight > 0; + } + + function itemsBodyVisible() { + return grid.$.items.offsetHeight > 0; + } + + beforeEach(async () => { + grid = fixtureSync(` + + +
+ No items +
+
+ `); + + grid.querySelector('vaadin-grid-column').footerRenderer = (root) => { + root.textContent = 'Footer'; + }; + await nextFrame(); + }); + + it('should show empty state', () => { + expect(emptyStateVisible()).to.be.true; + expect(itemsBodyVisible()).to.be.false; + }); + + it('should not show empty state when grid has items', async () => { + grid.items = [{ name: 'foo' }]; + await nextFrame(); + expect(emptyStateVisible()).to.be.false; + expect(itemsBodyVisible()).to.be.true; + }); + + it('should not show empty state when empty state content is not defined', async () => { + grid.removeChild(getEmptyState()); + await nextFrame(); + expect(emptyStateVisible()).to.be.false; + expect(itemsBodyVisible()).to.be.true; + }); + + it('should not throw on empty state click', () => { + expect(() => getEmptyState().click()).not.to.throw(); + }); + + it('should not dispatch cell-activate on empty state click', () => { + const spy = sinon.spy(); + grid.addEventListener('cell-activate', spy); + getEmptyState().click(); + expect(spy.called).to.be.false; + }); + + describe('bounds', () => { + let gridRect, emptyStateCellRect, headerRect, footerRect; + + beforeEach(() => { + gridRect = grid.getBoundingClientRect(); + emptyStateCellRect = grid.$.emptystatecell.getBoundingClientRect(); + headerRect = grid.$.header.getBoundingClientRect(); + footerRect = grid.$.footer.getBoundingClientRect(); + }); + + it('should cover the viewport', () => { + expect(emptyStateCellRect.top).to.be.closeTo(headerRect.bottom, 1); + expect(emptyStateCellRect.bottom).to.be.closeTo(footerRect.top, 1); + expect(emptyStateCellRect.left).to.be.closeTo(gridRect.left, 1); + expect(emptyStateCellRect.right).to.be.closeTo(gridRect.right, 1); + }); + + it('should push footer to the bottom of the viewport', () => { + expect(footerRect.bottom).to.be.closeTo(gridRect.bottom, 1); + }); + + it('should not scroll horizontally with the columns', () => { + grid.append( + ...Array.from({ length: 10 }, () => fixtureSync('')), + ); + flushGrid(grid); + + grid.$.table.scrollLeft = grid.$.table.scrollWidth; + emptyStateCellRect = grid.$.emptystatecell.getBoundingClientRect(); + expect(emptyStateCellRect.left).to.be.closeTo(gridRect.left, 1); + expect(emptyStateCellRect.right).to.be.closeTo(gridRect.right, 1); + }); + + it('should not scroll verticaly with the columns', () => { + getEmptyState().innerHTML = Array.from({ length: 10 }, () => '

Lorem ipsum dolor sit amet

').join(''); + flushGrid(grid); + + grid.$.emptystatecell.scrollTop = grid.$.emptystatecell.scrollHeight; + expect(grid.$.emptystatecell.scrollTop).to.be.greaterThan(0); + emptyStateCellRect = grid.$.emptystatecell.getBoundingClientRect(); + expect(emptyStateCellRect.top).to.be.closeTo(headerRect.bottom, 1); + expect(emptyStateCellRect.bottom).to.be.closeTo(footerRect.top, 1); + }); + + it('should not overflow on all-rows-visible', () => { + grid.allRowsVisible = true; + grid.style.width = '200px'; + getEmptyState().innerHTML = Array.from({ length: 10 }, () => '

Lorem ipsum dolor sit amet

').join(''); + flushGrid(grid); + + const emptyStateRect = getEmptyState().getBoundingClientRect(); + gridRect = grid.getBoundingClientRect(); + headerRect = grid.$.header.getBoundingClientRect(); + footerRect = grid.$.footer.getBoundingClientRect(); + expect(emptyStateRect.top).to.be.greaterThan(headerRect.bottom); + expect(emptyStateRect.bottom).to.be.lessThan(footerRect.top); + expect(emptyStateRect.left).to.be.greaterThan(gridRect.left); + expect(emptyStateRect.right).to.be.lessThan(gridRect.right); + }); + }); +}); diff --git a/packages/grid/test/dom/__snapshots__/grid.test.snap.js b/packages/grid/test/dom/__snapshots__/grid.test.snap.js index 745425f8a4..13ea28d52f 100644 --- a/packages/grid/test/dom/__snapshots__/grid.test.snap.js +++ b/packages/grid/test/dom/__snapshots__/grid.test.snap.js @@ -196,6 +196,21 @@ snapshots["vaadin-grid shadow default"] = + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { let translateValue; beforeEach(() => { - containerElement = grid.shadowRoot.querySelector(container === 'header' ? 'thead' : 'tbody'); + containerElement = grid.shadowRoot.querySelector(container === 'header' ? 'thead' : 'tbody#items'); containerRows = getRows(containerElement); scrollbarWidth = grid.$.table.offsetWidth - grid.$.table.clientWidth; borderWidth = parseInt(getComputedStyle(grid).getPropertyValue('--_lumo-grid-border-width')); diff --git a/packages/grid/test/helpers.js b/packages/grid/test/helpers.js index 1e5839d3c3..d4ee0f3845 100644 --- a/packages/grid/test/helpers.js +++ b/packages/grid/test/helpers.js @@ -93,7 +93,7 @@ const isVisible = (item, grid) => { }; export const getPhysicalItems = (grid) => { - return Array.from(grid.shadowRoot.querySelector('tbody').children) + return Array.from(grid.shadowRoot.querySelector('tbody#items').children) .filter((item) => !item.hidden) .sort((a, b) => a.index - b.index); }; diff --git a/packages/grid/test/keyboard-navigation.common.js b/packages/grid/test/keyboard-navigation.common.js index 12573f136c..92db0307d0 100644 --- a/packages/grid/test/keyboard-navigation.common.js +++ b/packages/grid/test/keyboard-navigation.common.js @@ -185,7 +185,16 @@ function getFocusedRowIndex() { } function getTabbableElements(root) { - return root.querySelectorAll('[tabindex]:not([tabindex="-1"])'); + return [...root.querySelectorAll('[tabindex]:not([tabindex="-1"])')].filter((el) => { + let parent = el; + while (parent) { + if (getComputedStyle(parent).display === 'none') { + return false; + } + parent = parent.parentElement; + } + return true; + }); } function getTabbableCells(root) { @@ -2585,3 +2594,89 @@ describe('lazy data provider', () => { expect(cellFocusSpy.called).to.be.false; }); }); + +describe('empty state', () => { + function getEmptyState() { + return grid.querySelector('[slot="empty-state"]'); + } + + function getEmptyStateFocusables() { + return [...getEmptyState().querySelectorAll('button')]; + } + + function getEmptyStateBody() { + return grid.$.emptystatebody; + } + + beforeEach(async () => { + grid = fixtureSync(` + + +
+ No items +
+
+ `); + await nextFrame(); + }); + + it('should tab to empty state body', async () => { + tabToHeader(); + tab(); + + await nextFrame(); + expect(getEmptyStateBody().contains(grid.shadowRoot.activeElement)).to.be.true; + expect(getEmptyStateBody().querySelector('td[part~="focused-cell"]')).to.be.ok; + }); + + it('should shift tab back to header from empty state body', () => { + tabToHeader(); + tab(); + shiftTab(); + + expect(grid.$.header.contains(grid.shadowRoot.activeElement)).to.be.true; + expect(getEmptyStateBody().querySelector('td[part~="focused-cell"]')).to.be.null; + }); + + it('should enter interaction mode on empty state body', () => { + tabToHeader(); + tab(); + enter(); + + expect(grid.hasAttribute('interacting')).to.be.true; + }); + + it('should focus the first focusable element in empty state content', () => { + tabToHeader(); + tab(); + enter(); + expect(document.activeElement).to.equal(getEmptyStateFocusables()[0]); + }); + + it('should tab to the next focusable element in empty state content', async () => { + tabToHeader(); + tab(); + enter(); + await sendKeys({ press: 'Tab' }); + expect(document.activeElement).to.equal(getEmptyStateFocusables()[1]); + }); + + it('should exit interaction mode on escape on empty state content', () => { + tabToHeader(); + tab(); + enter(); + escape(document.activeElement); + expect(grid.hasAttribute('interacting')).to.be.false; + expect(getEmptyStateBody().contains(grid.shadowRoot.activeElement)).to.be.true; + }); + + it('should not dispatch cell-focus event on empty state body', () => { + tabToHeader(); + + const spy = sinon.spy(); + grid.addEventListener('cell-focus', spy); + tab(); + + expect(spy.called).to.be.false; + }); +}); diff --git a/packages/grid/test/visual/grid.common.js b/packages/grid/test/visual/grid.common.js index 59e64067a1..0bd6b053be 100644 --- a/packages/grid/test/visual/grid.common.js +++ b/packages/grid/test/visual/grid.common.js @@ -434,4 +434,33 @@ describe('grid', () => { await visualDiff(element, 'tree-overflow'); }); }); + + describe('empty state', () => { + beforeEach(async () => { + element = fixtureSync(` + + + + + +
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. Distinctio laborum optio quo perferendis unde, fuga reprehenderit molestias cum laboriosam ipsa enim voluptatem iusto fugit. Sed, veniam repudiandae consectetur recusandae laudantium. +
+
+ `); + + [...element.querySelectorAll('vaadin-grid-column')].forEach((col) => { + col.footerRenderer = (root) => { + root.textContent = 'footer'; + }; + }); + + flushGrid(element); + await nextRender(element); + }); + + it('default', async () => { + await visualDiff(element, 'empty-state'); + }); + }); }); diff --git a/packages/grid/test/visual/lumo/grid.test.js b/packages/grid/test/visual/lumo/grid.test.js index a0a31e3629..198d6c4584 100644 --- a/packages/grid/test/visual/lumo/grid.test.js +++ b/packages/grid/test/visual/lumo/grid.test.js @@ -36,6 +36,19 @@ describe('theme', () => { await visualDiff(element, 'theme-compact'); }); + it('empty state compact', async () => { + element.setAttribute('theme', 'compact'); + element.items = []; + element.appendChild( + fixtureSync(` +
+ No items found. +
+ `), + ); + await visualDiff(element, 'empty-state-compact'); + }); + it('no-row-borders', async () => { element.setAttribute('theme', 'no-row-borders'); await visualDiff(element, 'theme-no-row-borders'); diff --git a/packages/grid/test/visual/lumo/screenshots/grid/baseline/empty-state-compact.png b/packages/grid/test/visual/lumo/screenshots/grid/baseline/empty-state-compact.png new file mode 100644 index 0000000000000000000000000000000000000000..c25185a82d4351f117443bf884c58565cfbdb5a9 GIT binary patch literal 5830 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 Xd}RrBC?zqq$yi!yx~i2b))D^+ibLP* literal 0 HcmV?d00001 diff --git a/packages/grid/theme/lumo/vaadin-grid-styles.js b/packages/grid/theme/lumo/vaadin-grid-styles.js index 9a9bdbad37..aa18393d03 100644 --- a/packages/grid/theme/lumo/vaadin-grid-styles.js +++ b/packages/grid/theme/lumo/vaadin-grid-styles.js @@ -90,6 +90,12 @@ registerStyles( z-index: 3; } + /* Empty state */ + [part~='empty-state'] { + padding: var(--lumo-space-m); + color: var(--lumo-secondary-text-color); + } + /* Drag and Drop styles */ :host([dragover])::after { content: ''; @@ -346,6 +352,10 @@ registerStyles( min-height: calc(var(--lumo-size-s) - var(--_lumo-grid-border-width)); } + :host([theme~='compact']) [part~='empty-state'] { + padding: var(--lumo-space-s); + } + /* Wrap cell contents */ :host([theme~='wrap-cell-content']) [part~='cell'] ::slotted(vaadin-grid-cell-content) { diff --git a/packages/grid/theme/material/vaadin-grid-styles.js b/packages/grid/theme/material/vaadin-grid-styles.js index 0ac16e5d60..42dea8babe 100644 --- a/packages/grid/theme/material/vaadin-grid-styles.js +++ b/packages/grid/theme/material/vaadin-grid-styles.js @@ -151,6 +151,12 @@ registerStyles( z-index: 3; } + /* Empty state */ + [part~='empty-state'] { + padding: 16px; + color: var(--material-secondary-text-color); + } + /* Drag and Drop styles */ :host([dragover])::after { content: '';