-
Notifications
You must be signed in to change notification settings - Fork 33
Dunk.list #6802
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Dunk.list #6802
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,4 @@ | ||
| import '../backdrop/backdrop-loading.js'; | ||
| import { css, html, LitElement } from 'lit'; | ||
| import { getNextFocusable, getPreviousFocusable } from '../../helpers/focus.js'; | ||
| import { SelectionInfo, SelectionMixin } from '../selection/selection-mixin.js'; | ||
|
|
@@ -94,13 +95,48 @@ class List extends PageableMixin(SelectionMixin(LitElement)) { | |
| * @default "all" | ||
| */ | ||
| separators: { type: String, reflect: true }, | ||
| /** | ||
| * The state of data in the table. Set to 'clean' when the data represents the user's latest selections, 'dirty' when the data does not represent the user's latest selections, and 'loading' if the data is being actively refreshed | ||
| * @type {'clean'|'dirty'|'loading'} | ||
| */ | ||
| dataState: { | ||
| reflect: true, | ||
| type: String | ||
| }, | ||
| /** | ||
| * The text displayed on the dirty state overlay when the 'dirty' dataState is set. | ||
| * @type {string} | ||
| */ | ||
| dirtyText: { | ||
| reflect: true, | ||
| attribute: 'dirty-text', | ||
| required: { | ||
| dependentProps: ['dataState'], | ||
| validator: (_value, elem, hasValue) => hasValue || elem.dataState !== 'dirty' | ||
| }, | ||
| type: String | ||
| }, | ||
| /** | ||
| * The text displayed on the button dirty state overlay when the 'dirty' dataState is set. | ||
| * @type {string} | ||
| */ | ||
| dirtyButtonText: { | ||
| reflect: true, | ||
| attribute: 'dirty-button-text', | ||
| required: { | ||
| dependentProps: ['dataState'], | ||
| validator: (_value, elem, hasValue) => hasValue || elem.dataState !== 'dirty' | ||
| }, | ||
| type: String | ||
| }, | ||
| /** | ||
| * Show selection only on hover, focus or if at least one item is selected. Exclusive for the tile layout | ||
| * @type {boolean} | ||
| */ | ||
| selectionWhenInteracted: { type: Boolean, attribute: 'selection-when-interacted', reflect: true }, | ||
| _breakpoint: { type: Number, reflect: true }, | ||
| _slimColor: { type: Boolean, reflect: true, attribute: '_slim-color' } | ||
| _slimColor: { type: Boolean, reflect: true, attribute: '_slim-color' }, | ||
| _backdropTriggered: { type: Boolean, reflect: true } | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This state attribute is a defensive measure to avoid breaking or changing existing list users. It records if the backdrop feature has ever been used, which opts into the new styles below. |
||
| }; | ||
| } | ||
|
|
||
|
|
@@ -161,6 +197,19 @@ class List extends PageableMixin(SelectionMixin(LitElement)) { | |
| flex-basis: 100%; | ||
| height: 0; | ||
| } | ||
|
|
||
| :host([_backdropTriggered]) { | ||
| position: relative; | ||
| } | ||
|
Comment on lines
+201
to
+203
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The backdrop must be rendered within a stacking context so that it doesn't leak out and render over a parent element or the entire page. |
||
| :host([_backdropTriggered]) slot { | ||
| z-index: 2; | ||
| } | ||
| :host([_backdropTriggered]) d2l-backdrop-loading { | ||
| z-index: 1; | ||
| } | ||
| :host([_backdropTriggered]) #list-slot { | ||
| z-index: 0; | ||
| } | ||
|
Comment on lines
+204
to
+212
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For most cases, I'd expect that we could ignore this by:
Unfortunately, adding the To avoid addressing that difficult issue, I've instead opted to make the list itself a stacking context, and manually specify an order that ensures that only the list items (in |
||
| `; | ||
| } | ||
|
|
||
|
|
@@ -175,11 +224,15 @@ class List extends PageableMixin(SelectionMixin(LitElement)) { | |
| this._listItemChanges = []; | ||
| this._childHasColor = false; | ||
| this._childHasExpandCollapseToggle = false; | ||
| this.dataState = 'clean'; | ||
|
|
||
| this._breakpoint = 0; | ||
| this._slimColor = false; | ||
| this._width = 0; | ||
|
|
||
| this.dirtyText = null; | ||
| this.dirtyButtonText = null; | ||
|
|
||
| this._listChildrenUpdatedSubscribers = new SubscriberRegistryController(this, 'list-child-status', { | ||
| onSubscribe: this._updateActiveSubscriber.bind(this), | ||
| updateSubscribers: this._updateActiveSubscribers.bind(this) | ||
|
|
@@ -250,12 +303,14 @@ class List extends PageableMixin(SelectionMixin(LitElement)) { | |
| return html` | ||
| <slot name="controls"></slot> | ||
| <slot name="header"></slot> | ||
| <div role="${role}" aria-label="${ifDefined(ariaLabel)}" class="d2l-list-content"> | ||
| <div id="list-slot" role="${role}" class="d2l-list-content" aria-label="${ifDefined(ariaLabel)}"> | ||
| <slot @keydown="${this._handleKeyDown}" @slotchange="${this._handleSlotChange}"></slot> | ||
| </div> | ||
| <d2l-backdrop-loading @d2l-backdrop-dirty-overlay-action=${this._handleDirtyButton} for="list-slot" .dataState='${this.dataState}' dirty-text="${this.dirtyText}" dirty-button-text="${this.dirtyButtonText}"></d2l-backdrop-loading> | ||
| ${this._renderPagerContainer()} | ||
| `; | ||
| } | ||
|
|
||
| willUpdate(changedProperties) { | ||
| super.willUpdate(changedProperties); | ||
| if (changedProperties.has('breakpoints') && changedProperties.get('breakpoints') !== undefined) { | ||
|
|
@@ -276,6 +331,9 @@ class List extends PageableMixin(SelectionMixin(LitElement)) { | |
| if (changedProperties.has('dragHandleShowAlways')) { | ||
| this._updateItemDragHandleShowAlways(); | ||
| } | ||
| if (changedProperties.has('dataState') && this.dataState !== undefined) { | ||
| this._backdropTriggered = true; | ||
| } | ||
| } | ||
|
|
||
| getItems(slot) { | ||
|
|
@@ -381,6 +439,11 @@ class List extends PageableMixin(SelectionMixin(LitElement)) { | |
| return items.length > 0 ? items[0]._getFlattenedListItems().lazyLoadListItems : new Map(); | ||
| } | ||
|
|
||
| _handleDirtyButton() { | ||
| /** Dispatched when the action button on the dirty overlay is clicked */ | ||
| this.dispatchEvent(new CustomEvent('d2l-list-dirty-button-clicked')); | ||
| } | ||
|
|
||
| _handleKeyDown(e) { | ||
| if (!this.grid || this.slot === 'nested' || e.keyCode !== keyCodes.TAB) return; | ||
| e.preventDefault(); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -39,6 +39,11 @@ export class SelectionControls extends PageableSubscriberMixin(SelectionObserver | |
| * @type {boolean} | ||
| */ | ||
| selectAllPagesAllowed: { type: Boolean, attribute: 'select-all-pages-allowed' }, | ||
| /** | ||
| * Whether to disable and visually grey out the select all items checkbox | ||
| * @type {boolean} | ||
| */ | ||
| selectAllPagesDisabled: { type: Boolean, attribute: 'select-all-pages-disabled' }, | ||
|
Comment on lines
41
to
+46
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Having both of these properties is not ideal since the difference between I also considered using Any ideas on how to make this nicer without breaking the existing API are welcome 😄 |
||
| _hasActions: { state: true }, | ||
| _noSelectionText: { state: true }, | ||
| _scrolled: { type: Boolean, reflect: true } | ||
|
|
@@ -118,6 +123,7 @@ export class SelectionControls extends PageableSubscriberMixin(SelectionObserver | |
| constructor() { | ||
| super(); | ||
| this.noSelection = false; | ||
| this.selectAllPagesDisabled = false; | ||
| this.noSticky = false; | ||
| this.selectAllPagesAllowed = false; | ||
| this._scrolled = false; | ||
|
|
@@ -183,7 +189,7 @@ export class SelectionControls extends PageableSubscriberMixin(SelectionObserver | |
|
|
||
| _renderSelection() { | ||
| return html` | ||
| ${this._provider && !this._noSelectAll ? html`<d2l-selection-select-all></d2l-selection-select-all>` : nothing} | ||
| ${this._provider && !this._noSelectAll ? html`<d2l-selection-select-all ?disabled=${this.selectAllPagesDisabled} ></d2l-selection-select-all>` : nothing} | ||
| <d2l-selection-summary no-selection-text="${ifDefined(this._noSelectionText)}"></d2l-selection-summary> | ||
| ${this.selectAllPagesAllowed ? html`<d2l-selection-select-all-pages></d2l-selection-select-all-pages>` : nothing} | ||
| `; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this iteration, disabling controls is a responsibility assumed by the caller, since they're picking and choosing which controls to include in their slot.
The alternative would be to go programmatically disable everything within the control slot- this might not be desirable for all use cases, especially if those controls are part of a flow in which the loading backdrop would go away, E.G.