Skip to content

Loading/dirty state refactoring#7232

Open
dbatiste wants to merge 20 commits into
mainfrom
dbatiste/dirty-state-refactoring
Open

Loading/dirty state refactoring#7232
dbatiste wants to merge 20 commits into
mainfrom
dbatiste/dirty-state-refactoring

Conversation

@dbatiste

@dbatiste dbatiste commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

GAUD-10306

This PR factors out the data state properties (dataState, dirtyText, and dirtyButtonText) into a mixin since they are used in two places currently, and soon d2l-list as well. It also introduces the dataStates enum (clean, loading, dirty) to eliminate these hard-coded values. This PR also tidies things up with some naming and formatting.

I will add comments to make review easier.

@github-actions

Copy link
Copy Markdown
Contributor

Thanks for the PR! 🎉

We've deployed an automatic preview for this PR - you can see your changes here:

URL https://live.d2l.dev/prs/BrightspaceUI/core/pr-7232/

Note

The build needs to finish before your changes are deployed.
Changes to the PR will automatically update the instance.

Comment thread components/backdrop/backdrop-loading.js
class BackdropLoading extends DataStateMixin(LocalizeCoreElement(LitElement)) {

static properties = {
/**

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These properties were factored out into DataStateMixin, where the attributes are reflected as we normally would. (i.e. data-state instead of dataState).

_state: { type: String, reflect: true },
_spinnerTop: { state: true },
_ariaContent: { state: true }
_ariaContent: { state: true },

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These private reactive properties were re-order and renamed. The _dirtyDialogTop (renamed to _dirtyOverlayTop) should have been a reactive private property - it was renamed and included here as we'd expect.


static styles = [css`
#visible {
.backdrop-container {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is simply renamed for clarity.

this._spinnerTop = 0;
this._dirtyDialogTop = 0;
this._ariaContent = '';
this._dirtyOverlayTop = 0;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just reordered.

render() {
const backdropVisible = this._state !== 'hidden';

const backdropContainer = backdropVisible ? html`<div class="backdrop-container">

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This HTML was just moved out to tidy things up and reduce indentation.

super.willUpdate(changedProperties);

if (changedProperties.has('dataState') && changedProperties.get('dataState') !== undefined) {
this.#clearLiveArea();

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These "LiveArea" methods were just renamed for clarity.

}
}

async #centerLoadingSpinnerAndDialog() {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other than renaming, this logic remained exactly the same.

clearTimeout(this.announcementTimeout);
}

this.announcementTimeout = null;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed to be private, and to be specific about it being an "Id".

#fade() {
let hideImmediately = reduceMotion || this._state === 'showing';
if (this._state === 'shown') {
const currentOpacity = getComputedStyle(this.shadowRoot.querySelector('#d2l-live-region')).opacity;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, renaming for clarity.

#getBackdropTarget() {
const parent = getComposedParent(this);

const targetedChildren = getComposedChildren(

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just tidied up the formatting.

@dbatiste
dbatiste marked this pull request as ready for review July 17, 2026 18:02
@dbatiste
dbatiste requested a review from a team as a code owner July 17, 2026 18:02
opacity: 1;
transition: opacity ${FADE_DURATION_MS}ms ease-in ${SPINNER_DELAY_MS}ms;
}
:host([_state="shown"][dataState="dirty"]) d2l-loading-spinner,

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then improper property reflection tripped me up during the refactoring because I'd corrected it and didn't realize the CSS was relying on this subtle difference.

* @type {'clean'|'dirty'|'loading'}
* @default "clean"
*/
dataState: { type: String, attribute: 'data-state', reflect: true },

@dbatiste dbatiste Jul 17, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that d2l-table-wrapper previously did not specify the attribute and was therefore defaulting to dataState. This change would normally be breaking, but the only usage is pointing to the JavaScript property here in Insights, so we can safely update to define with the data-state attribute we would normally expect.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant