Skip to content

Commit 91a0610

Browse files
authored
fix(panel): Remove double border styling when content isn't provided (#7368)
**Related Issue:** #7423 ## Summary - Fixes display issue when no content is slotted within a panel but a footer or action-bar is displayed then a double border occurs. - Cleans up code to use `slotChangeHasAssignedElement` dom utility for slot changes - Fixes conditional element surrounding default slot. - Adds screenshot tests
1 parent 7324f70 commit 91a0610

File tree

4 files changed

+85
-66
lines changed

4 files changed

+85
-66
lines changed

packages/calcite-components/src/components/panel/panel.scss

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,7 @@
2929
}
3030

3131
.header {
32-
border-block-end: 1px solid;
3332
@apply bg-foreground-1
34-
border-b-color-3
3533
w-full
3634
items-stretch
3735
justify-start
@@ -40,9 +38,12 @@
4038
}
4139

4240
.action-bar-container {
43-
border-block-end: 1px solid;
4441
@apply w-full
45-
z-header border-b-color-3;
42+
z-header;
43+
}
44+
45+
.bottom-separator {
46+
border-block-end: 1px solid var(--calcite-ui-border-3);
4647
}
4748

4849
.action-bar-container ::slotted(calcite-action-bar) {
@@ -92,11 +93,7 @@
9293
}
9394

9495
.content-wrapper {
95-
@apply overflow-auto;
96-
}
97-
98-
.content-height {
99-
@apply h-full;
96+
@apply overflow-auto h-full;
10097
}
10198

10299
.content-container {
@@ -109,15 +106,14 @@
109106
}
110107

111108
.footer {
112-
border-block-start: 1px solid;
113109
@apply bg-foreground-1
114-
border-t-color-3
115110
flex
116111
w-full
117112
justify-evenly;
118113

119114
flex: 0 0 auto;
120115
padding: var(--calcite-panel-footer-padding);
116+
border-block-start: 1px solid var(--calcite-ui-border-3);
121117
}
122118

123119
.fab-container {

packages/calcite-components/src/components/panel/panel.stories.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,3 +218,40 @@ export const actionBarBackgroundColor_TestOnly = (): string => html`<calcite-pan
218218
<p style="height: 400px">Hello world!</p>
219219
<p slot="footer">Slotted content!</p>
220220
</calcite-panel>`;
221+
222+
export const footerWithoutContent_TestOnly = (): string => html`<calcite-panel
223+
height-scale="s"
224+
heading="Header!"
225+
style="width: 300px; height:auto;"
226+
>
227+
<p slot="footer">Footer content!</p>
228+
</calcite-panel>`;
229+
230+
export const actionBarWithoutContent_TestOnly = (): string => html`<calcite-panel
231+
height-scale="s"
232+
heading="Header!"
233+
style="width: 300px; height:auto;"
234+
>
235+
<calcite-action-bar slot="action-bar">
236+
<calcite-action-group>
237+
<calcite-action text="Add" icon="plus"> </calcite-action>
238+
<calcite-action text="Save" icon="save"> </calcite-action>
239+
<calcite-action text="Layers" icon="layers"> </calcite-action>
240+
</calcite-action-group>
241+
</calcite-action-bar>
242+
</calcite-panel>`;
243+
244+
export const footerAndActionBarWithoutContent_TestOnly = (): string => html`<calcite-panel
245+
height-scale="s"
246+
heading="Header!"
247+
style="width: 300px; height:auto;"
248+
>
249+
<calcite-action-bar slot="action-bar">
250+
<calcite-action-group>
251+
<calcite-action text="Add" icon="plus"> </calcite-action>
252+
<calcite-action text="Save" icon="save"> </calcite-action>
253+
<calcite-action text="Layers" icon="layers"> </calcite-action>
254+
</calcite-action-group>
255+
</calcite-action-bar>
256+
<p slot="footer">Footer content!</p>
257+
</calcite-panel>`;

packages/calcite-components/src/components/panel/panel.tsx

Lines changed: 40 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,12 @@ import {
1111
VNode,
1212
Watch,
1313
} from "@stencil/core";
14-
import { focusFirstTabbable, slotChangeGetAssignedElements, toAriaBoolean } from "../../utils/dom";
14+
import {
15+
focusFirstTabbable,
16+
slotChangeGetAssignedElements,
17+
slotChangeHasAssignedElement,
18+
toAriaBoolean,
19+
} from "../../utils/dom";
1520
import {
1621
connectInteractive,
1722
disconnectInteractive,
@@ -168,6 +173,8 @@ export class Panel
168173

169174
resizeObserver = createObserver("resize", () => this.resizeHandler());
170175

176+
@State() hasDefaultContent = false;
177+
171178
@State() hasStartActions = false;
172179

173180
@State() hasEndActions = false;
@@ -257,28 +264,20 @@ export class Panel
257264
this.calcitePanelScroll.emit();
258265
};
259266

260-
handleHeaderActionsStartSlotChange = (event: Event): void => {
261-
const elements = (event.target as HTMLSlotElement).assignedElements({
262-
flatten: true,
263-
});
267+
handleDefaultSlotChange = (event: Event): void => {
268+
this.hasDefaultContent = slotChangeHasAssignedElement(event);
269+
};
264270

265-
this.hasStartActions = !!elements.length;
271+
handleHeaderActionsStartSlotChange = (event: Event): void => {
272+
this.hasStartActions = slotChangeHasAssignedElement(event);
266273
};
267274

268275
handleHeaderActionsEndSlotChange = (event: Event): void => {
269-
const elements = (event.target as HTMLSlotElement).assignedElements({
270-
flatten: true,
271-
});
272-
273-
this.hasEndActions = !!elements.length;
276+
this.hasEndActions = slotChangeHasAssignedElement(event);
274277
};
275278

276279
handleHeaderMenuActionsSlotChange = (event: Event): void => {
277-
const elements = (event.target as HTMLSlotElement).assignedElements({
278-
flatten: true,
279-
});
280-
281-
this.hasMenuItems = !!elements.length;
280+
this.hasMenuItems = slotChangeHasAssignedElement(event);
282281
};
283282

284283
handleActionBarSlotChange = (event: Event): void => {
@@ -292,35 +291,19 @@ export class Panel
292291
};
293292

294293
handleHeaderContentSlotChange = (event: Event): void => {
295-
const elements = (event.target as HTMLSlotElement).assignedElements({
296-
flatten: true,
297-
});
298-
299-
this.hasHeaderContent = !!elements.length;
294+
this.hasHeaderContent = slotChangeHasAssignedElement(event);
300295
};
301296

302297
handleFooterSlotChange = (event: Event): void => {
303-
const elements = (event.target as HTMLSlotElement).assignedElements({
304-
flatten: true,
305-
});
306-
307-
this.hasFooterContent = !!elements.length;
298+
this.hasFooterContent = slotChangeHasAssignedElement(event);
308299
};
309300

310301
handleFooterActionsSlotChange = (event: Event): void => {
311-
const elements = (event.target as HTMLSlotElement).assignedElements({
312-
flatten: true,
313-
});
314-
315-
this.hasFooterActions = !!elements.length;
302+
this.hasFooterActions = slotChangeHasAssignedElement(event);
316303
};
317304

318305
handleFabSlotChange = (event: Event): void => {
319-
const elements = (event.target as HTMLSlotElement).assignedElements({
320-
flatten: true,
321-
});
322-
323-
this.hasFab = !!elements.length;
306+
this.hasFab = slotChangeHasAssignedElement(event);
324307
};
325308

326309
// --------------------------------------------------------------------------
@@ -380,7 +363,10 @@ export class Panel
380363

381364
renderActionBar(): VNode {
382365
return (
383-
<div class={CSS.actionBarContainer} hidden={!this.hasActionBar}>
366+
<div
367+
class={{ [CSS.actionBarContainer]: true, [CSS.bottomSeparator]: this.hasDefaultContent }}
368+
hidden={!this.hasActionBar}
369+
>
384370
<slot name={SLOTS.actionBar} onSlotchange={this.handleActionBarSlotChange} />
385371
</div>
386372
);
@@ -475,7 +461,15 @@ export class Panel
475461
}
476462

477463
renderHeaderNode(): VNode {
478-
const { hasHeaderContent, hasStartActions, hasEndActions, closable, hasMenuItems } = this;
464+
const {
465+
hasHeaderContent,
466+
hasStartActions,
467+
hasEndActions,
468+
closable,
469+
hasMenuItems,
470+
hasDefaultContent,
471+
hasActionBar,
472+
} = this;
479473

480474
const headerContentNode = this.renderHeaderContent();
481475

@@ -488,7 +482,10 @@ export class Panel
488482
hasMenuItems;
489483

490484
return (
491-
<header class={CSS.header} hidden={!showHeader}>
485+
<header
486+
class={{ [CSS.header]: true, [CSS.bottomSeparator]: hasDefaultContent || hasActionBar }}
487+
hidden={!showHeader}
488+
>
492489
{this.renderHeaderStartActions()}
493490
{this.renderHeaderSlottedContent()}
494491
{headerContentNode}
@@ -525,27 +522,16 @@ export class Panel
525522
};
526523

527524
renderContent(): VNode {
528-
const { hasFab } = this;
529-
530-
const defaultSlotNode: VNode = <slot key="default-slot" />;
531-
const containerNode = hasFab ? (
532-
<section class={CSS.contentContainer}>{defaultSlotNode}</section>
533-
) : (
534-
defaultSlotNode
535-
);
536-
537525
return (
538526
<div
539-
class={{
540-
[CSS.contentWrapper]: true,
541-
[CSS.contentContainer]: !hasFab,
542-
[CSS.contentHeight]: hasFab,
543-
}}
527+
class={CSS.contentWrapper}
544528
onScroll={this.panelScrollHandler}
545529
// eslint-disable-next-line react/jsx-sort-props
546530
ref={this.setPanelScrollEl}
547531
>
548-
{containerNode}
532+
<section class={CSS.contentContainer}>
533+
<slot onSlotchange={this.handleDefaultSlotChange} />
534+
</section>
549535
{this.renderFab()}
550536
</div>
551537
);

packages/calcite-components/src/components/panel/resources.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ export const CSS = {
33
backButton: "back-button",
44
container: "container",
55
header: "header",
6+
bottomSeparator: "bottom-separator",
67
heading: "heading",
78
summary: "summary",
89
description: "description",
@@ -12,7 +13,6 @@ export const CSS = {
1213
headerActionsStart: "header-actions--start",
1314
contentWrapper: "content-wrapper",
1415
contentContainer: "content-container",
15-
contentHeight: "content-height",
1616
fabContainer: "fab-container",
1717
footer: "footer",
1818
};

0 commit comments

Comments
 (0)