Skip to content

Commit dd22eca

Browse files
feat(tray): expand API for dismissible behavior
- adds several properties and methods to tray API to support more flexibile dismissible behavior. - queries for keyboard-accessible dismiss buttons in the tray's slot content - adds a state property to track if dismiss buttons are needed
1 parent 7ab0fc6 commit dd22eca

File tree

1 file changed

+45
-3
lines changed

1 file changed

+45
-3
lines changed

packages/tray/src/Tray.ts

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,15 @@
1313
import {
1414
CSSResultArray,
1515
html,
16+
nothing,
1617
PropertyValues,
1718
SpectrumElement,
1819
TemplateResult,
1920
} from '@spectrum-web-components/base';
2021
import {
2122
property,
2223
query,
24+
queryAssignedElements,
2325
} from '@spectrum-web-components/base/src/decorators.js';
2426
import '@spectrum-web-components/underlay/sp-underlay.js';
2527
import { firstFocusableIn } from '@spectrum-web-components/shared/src/first-focusable-in.js';
@@ -98,6 +100,46 @@ export class Tray extends SpectrumElement {
98100
`;
99101
}
100102

103+
/**
104+
* Add a state property to track if dismiss buttons are needed
105+
* Set to false if your tray content already includes keyboard-accessible dismiss buttons.
106+
*/
107+
@property({ type: Boolean, attribute: false })
108+
private needsDismissHelper = true;
109+
110+
// Track slotted content
111+
@queryAssignedElements({ flatten: true })
112+
private slottedContent!: HTMLElement[];
113+
114+
// Check if slotted content has keyboard-accessible dismiss buttons
115+
private checkForDismissButtons(): void {
116+
// Look for common dismiss button patterns
117+
const hasDismissButton = this.slottedContent.some((element) => {
118+
// Check for buttons at the top level
119+
if (
120+
element.tagName === 'SP-BUTTON' ||
121+
element.tagName === 'SP-CLOSE-BUTTON' ||
122+
element.tagName === 'BUTTON'
123+
)
124+
return true;
125+
126+
// Check for buttons within the slotted content
127+
const buttons = element.querySelectorAll(
128+
'sp-button, sp-close-button, button'
129+
);
130+
if (buttons.length > 0) return true;
131+
132+
return false;
133+
});
134+
135+
this.needsDismissHelper = !hasDismissButton;
136+
}
137+
138+
// Update when slot content changes
139+
private handleSlotChange(): void {
140+
this.checkForDismissButtons();
141+
}
142+
101143
private dispatchClosed(): void {
102144
this.dispatchEvent(
103145
new Event('close', {
@@ -148,9 +190,9 @@ export class Tray extends SpectrumElement {
148190
tabindex="-1"
149191
@transitionend=${this.handleTrayTransitionend}
150192
>
151-
${this.dismissHelper}
152-
<slot></slot>
153-
${this.dismissHelper}
193+
${this.needsDismissHelper ? this.dismissHelper : nothing}
194+
<slot @slotchange=${this.handleSlotChange}></slot>
195+
${this.needsDismissHelper ? this.dismissHelper : nothing}
154196
</div>
155197
`;
156198
}

0 commit comments

Comments
 (0)