From 62c27767aedd54af443079f8b4b53e2c8b81720c Mon Sep 17 00:00:00 2001 From: Matt Driscoll Date: Tue, 8 Aug 2023 15:21:59 -0700 Subject: [PATCH] fix(panel): Fix heading border when only text content is slotted. #7489 --- .../src/components/panel/panel.stories.ts | 4 ++ .../src/components/panel/panel.tsx | 3 +- packages/calcite-components/src/utils/dom.ts | 62 +++++++++++++++++++ 3 files changed, 68 insertions(+), 1 deletion(-) diff --git a/packages/calcite-components/src/components/panel/panel.stories.ts b/packages/calcite-components/src/components/panel/panel.stories.ts index c73e2b78bed..b2960a9bd6c 100644 --- a/packages/calcite-components/src/components/panel/panel.stories.ts +++ b/packages/calcite-components/src/components/panel/panel.stories.ts @@ -313,3 +313,7 @@ export const noOverflowContentWithFab_TestOnly = (): string => html`
My Content
`; + +export const withTextContentOnly = (): string => html` +
Slotted content!
+
`; diff --git a/packages/calcite-components/src/components/panel/panel.tsx b/packages/calcite-components/src/components/panel/panel.tsx index 7236d9626bb..6996822b7d8 100644 --- a/packages/calcite-components/src/components/panel/panel.tsx +++ b/packages/calcite-components/src/components/panel/panel.tsx @@ -15,6 +15,7 @@ import { focusFirstTabbable, slotChangeGetAssignedElements, slotChangeHasAssignedElement, + slotChangeHasTextContent, toAriaBoolean, } from "../../utils/dom"; import { @@ -267,7 +268,7 @@ export class Panel }; handleDefaultSlotChange = (event: Event): void => { - this.hasDefaultContent = slotChangeHasAssignedElement(event); + this.hasDefaultContent = slotChangeHasAssignedElement(event) || slotChangeHasTextContent(event); }; handleHeaderActionsStartSlotChange = (event: Event): void => { diff --git a/packages/calcite-components/src/utils/dom.ts b/packages/calcite-components/src/utils/dom.ts index 3da1128518f..f82d8f808de 100644 --- a/packages/calcite-components/src/utils/dom.ts +++ b/packages/calcite-components/src/utils/dom.ts @@ -426,6 +426,68 @@ export function toAriaBoolean(value: boolean): string { return Boolean(value).toString(); } +/** + * This helper returns a string of textContent if the target `slot` element from the `onSlotchange` event has any text content. + * + * ``` + * this.mySlotText = slotChangeGetTextContent(event)} />} + * ``` + * + * @param {Event} event The event. + * @returns {string} The slots text. + */ +export function slotChangeGetTextContent(event: Event): string { + return slotChangeGetAssignedNodes(event) + .filter((node) => node.nodeType === Node.TEXT_NODE) + .map((node) => node.textContent) + .join("") + .trim(); +} + +/** + * This helper returns `true` if the target `slot` element from the `onSlotchange` event has any text content. + * + * ``` + * this.mySlotHasTextContent = slotChangeHasTextContent(event)} />} + * ``` + * + * @param {Event} event The event. + * @returns {boolean} Whether the slot has any text content. + */ +export function slotChangeHasTextContent(event: Event): boolean { + return !!slotChangeGetTextContent(event); +} + +/** + * This helper returns `true` if the target `slot` element from the `onSlotchange` event has an assigned node. + * + * ``` + * this.mySlotHasNode = slotChangeHasAssignedNode(event)} />} + * ``` + * + * @param {Event} event The event. + * @returns {boolean} Whether the slot has any assigned nodes. + */ +export function slotChangeHasAssignedNode(event: Event): boolean { + return !!slotChangeGetAssignedNodes(event).length; +} + +/** + * This helper returns the assigned nodes on a `slot` element from the `onSlotchange` event. + * + * ``` + * this.mySlotNodes = slotChangeGetAssignedNodes(event)} />} + * ``` + * + * @param {Event} event The event. + * @returns {boolean} Whether the slot has any assigned nodes. + */ +export function slotChangeGetAssignedNodes(event: Event): Node[] { + return (event.target as HTMLSlotElement).assignedNodes({ + flatten: true, + }); +} + /** * This helper returns `true` if the target `slot` element from the `onSlotchange` event has an assigned element. *