From a510773ba87994010e84184f7709c84ce40f2d2c Mon Sep 17 00:00:00 2001 From: Matt Driscoll Date: Mon, 5 Dec 2022 14:26:14 -0800 Subject: [PATCH] feat(list-item): Add content slot for specialized content (#5876) **Related Issue:** #3032 ## Summary feat(list-item): Add slot for specialized content #3032 - Adds a new `content` slot to the `list-item` for customized content. - `content` slot takes precedence over `label` and `description` properties. --- src/components/list-item/list-item.e2e.ts | 16 +++++++++++ src/components/list-item/list-item.scss | 3 ++- src/components/list-item/list-item.tsx | 33 ++++++++++++++++++----- src/components/list-item/resources.ts | 2 ++ src/components/list/list.stories.ts | 21 +++++++++++++++ 5 files changed, 68 insertions(+), 7 deletions(-) diff --git a/src/components/list-item/list-item.e2e.ts b/src/components/list-item/list-item.e2e.ts index 5c1a456779c..37076c3b050 100755 --- a/src/components/list-item/list-item.e2e.ts +++ b/src/components/list-item/list-item.e2e.ts @@ -69,6 +69,22 @@ describe("calcite-list-item", () => { expect(contentNode).toBeNull(); }); + it("renders custom content in place of label and description", async () => { + const page = await newE2EPage({ + html: `
My custom content
` + }); + + await page.waitForChanges(); + + const contentNode = await page.find(`calcite-list-item >>> .${CSS.content}`); + + expect(contentNode).toBeNull(); + + const customContentNode = await page.find(`calcite-list-item >>> .${CSS.customContent}`); + + expect(customContentNode).not.toBeNull(); + }); + it("emits calciteListItemSelect on click", async () => { const page = await newE2EPage({ html: `` diff --git a/src/components/list-item/list-item.scss b/src/components/list-item/list-item.scss index 89b6440f4fa..1ea94d2c807 100755 --- a/src/components/list-item/list-item.scss +++ b/src/components/list-item/list-item.scss @@ -62,7 +62,8 @@ td:focus { @apply focus-normal z-sticky; } -.content { +.content, +.custom-content { @apply text-n2-wrap flex flex-auto diff --git a/src/components/list-item/list-item.tsx b/src/components/list-item/list-item.tsx index 833bb523d81..6209c78dd54 100644 --- a/src/components/list-item/list-item.tsx +++ b/src/components/list-item/list-item.tsx @@ -33,6 +33,7 @@ import { * @slot - A slot for adding `calcite-list-item` and `calcite-list-item-group` elements. * @slot actions-start - A slot for adding actionable `calcite-action` elements before the content of the component. * @slot content-start - A slot for adding non-actionable elements before the label and description of the component. + * @slot content - A slot for adding non-actionable, centered content in place of the `label` and `description` of the component. * @slot content-end - A slot for adding non-actionable elements after the label and description of the component. * @slot actions-end - A slot for adding actionable `calcite-action` elements after the content of the component. */ @@ -175,6 +176,8 @@ export class ListItem implements InteractiveComponent, LoadableComponent { @State() hasActionsEnd = false; + @State() hasCustomContent = false; + @State() hasContentStart = false; @State() hasContentEnd = false; @@ -321,6 +324,15 @@ export class ListItem implements InteractiveComponent, LoadableComponent { ); } + renderCustomContent(): VNode { + const { hasCustomContent } = this; + return ( + + ); + } + renderContentEnd(): VNode { const { hasContentEnd } = this; return ( @@ -330,10 +342,10 @@ export class ListItem implements InteractiveComponent, LoadableComponent { ); } - renderContent(): VNode { - const { label, description } = this; + renderContentProperties(): VNode { + const { label, description, hasCustomContent } = this; - return !!label || !!description ? ( + return !hasCustomContent && (!!label || !!description) ? (
{label ? (
@@ -350,9 +362,14 @@ export class ListItem implements InteractiveComponent, LoadableComponent { } renderContentContainer(): VNode { - const { description, label, selectionMode } = this; - const hasCenterContent = !!label || !!description; - const content = [this.renderContentStart(), this.renderContent(), this.renderContentEnd()]; + const { description, label, selectionMode, hasCustomContent } = this; + const hasCenterContent = hasCustomContent || !!label || !!description; + const content = [ + this.renderContentStart(), + this.renderCustomContent(), + this.renderContentProperties(), + this.renderContentEnd() + ]; return ( { + this.hasCustomContent = slotChangeHasAssignedElement(event); + }; + handleActionsStartSlotChange = (event: Event): void => { this.hasActionsStart = slotChangeHasAssignedElement(event); }; diff --git a/src/components/list-item/resources.ts b/src/components/list-item/resources.ts index c7a00dc5646..7de9e874788 100644 --- a/src/components/list-item/resources.ts +++ b/src/components/list-item/resources.ts @@ -8,6 +8,7 @@ export const CSS = { nestedContainer: "nested-container", nestedContainerHidden: "nested-container--hidden", content: "content", + customContent: "custom-content", actionsStart: "actions-start", contentStart: "content-start", label: "label", @@ -21,6 +22,7 @@ export const CSS = { export const SLOTS = { actionsStart: "actions-start", contentStart: "content-start", + content: "content", contentEnd: "content-end", actionsEnd: "actions-end" }; diff --git a/src/components/list/list.stories.ts b/src/components/list/list.stories.ts index 84f6fa754ee..82d11b58c17 100644 --- a/src/components/list/list.stories.ts +++ b/src/components/list/list.stories.ts @@ -305,3 +305,24 @@ export const disabled_TestOnly = (): string => html` " > `; + +export const customContent_TestOnly = (): string => html` + +
+ Cras iaculis ultricies nulla. +
Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
+
+ +
+ Cras iaculis ultricies nulla. +
Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
+
+
+ Cras iaculis ultricies nulla. +
Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
+
+
`;