Skip to content

Add apply button and dirty state#6751

Draft
duncanuszkay-d2l wants to merge 12 commits intomainfrom
dunk.apply-button
Draft

Add apply button and dirty state#6751
duncanuszkay-d2l wants to merge 12 commits intomainfrom
dunk.apply-button

Conversation

@duncanuszkay-d2l
Copy link
Copy Markdown
Contributor

@duncanuszkay-d2l duncanuszkay-d2l commented Apr 2, 2026

Note for reviewers- looking for some early input on direction before finishing this up 👀

https://desire2learn.atlassian.net/browse/NTNGL-5471?atlOrigin=eyJpIjoiMDk2MmRlZjZmMjkxNGNhZjlmMTIxMTdiMjJiODZjODYiLCJwIjoiaiJ9

Functional Testing

Moving between the new backdrop states:

Recording.2026-04-07.163437.mp4

Using the new system in the downstream consumer (WIP integration PR)

Recording.2026-04-07.163602.mp4

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 2, 2026

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-6751/

Note

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

Comment on lines -111 to -115
if (changedProperties.has('shown') && (
(reduceMotion && this._state === 'shown') || (!reduceMotion && this._state === 'showing')
)) {
this.#centerLoadingSpinner();
}
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 centering behavior is re-addressed in a later commit

}
:host([_state="showing"]),
:host([_state="shown"]),
:host([_state="loading"]),
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.

The shown state now represents the dirty dialog being open:

Image

The loading state represents the loading spinner being visible:

Image

if (this._state === 'hidden') return nothing;
return html`
<div class="backdrop" @transitionend="${this.#handleTransitionEnd}" @transitioncancel="${this.#hide}"></div>
<div class="backdrop" @transitionend="${this.#handleTransitionEnd}" @transitioncancel="${this.#handleTransitionEnd}"></div>
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 resolved a bug I began to run into once I adjusted the demo to allow the more rapid state changes- we can't assume that a cancellation of a transition must indicate that we need to hide, we need to check to make sure that we're in the hiding state.

Comment on lines -131 to -133
setTimeout(() => {
if (this._state === 'showing') this._state = 'shown';
}, BACKDROP_DELAY_MS);
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.

We've decided to remove this delay and instead show the backdrop as soon as the data becomes dirty

@duncanuszkay-d2l duncanuszkay-d2l requested a review from GZolla April 8, 2026 14:58
Comment on lines +129 to +136
if (changedProperties.has('dataState') &&
changedProperties.get('dataState') === 'clean' &&
(
(reduceMotion && this._state === 'shown') ||
(!reduceMotion && this._state === 'showing') ||
(!reduceMotion && this._state === 'loading')
)
) {
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.

We only want to center if we're moving from a hidden/clean state into a non-hidden state, we don't want to center again when moving from the dialog to the loading spinner

const lowerVisibleBound = Math.min(window.innerHeight, boundingRect.bottom);
const visibleHeight = lowerVisibleBound - upperVisibleBound;
const centeringOffset = visibleHeight / 2;
const centeringOffset = (visibleHeight / 4);
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.

From design feedback on the demo, we're moving to a 25% offset instead of centering (50%).

Comment on lines +185 to +186
await this.shadowRoot.querySelector('d2l-empty-state-simple').getUpdateComplete();
await this.shadowRoot.querySelector('d2l-empty-state-action-button').getUpdateComplete();
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 ensures that we're accurately measuring the height offset for the dialog box, this should remain consistent regardless of the text content

Comment on lines +189 to +190
this._spinnerTop = centeringOffset + topOffset - spinnerSizeOffset;
this._dirtyDialogTop = centeringOffset + topOffset - dirtyDialogSizeOffset;
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.

I'm removing the minimum buffer, when the table get's small it's fine to overlay the headers as per design's demo feedback

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