From 5ed0d79d512b55b136458f90070e8e55a4704162 Mon Sep 17 00:00:00 2001 From: Matt Driscoll Date: Thu, 16 Nov 2023 16:06:01 -0800 Subject: [PATCH] feat(list-item): Add content-bottom slot for placing content below the label and description of the component (#8183) **Related Issue:** #8173 ## Summary - Adds a new slot `content-bottom`. - `content-bottom` is indented the same as the item. - screenshot tests --- .../src/components/list-item/list-item.scss | 10 +++- .../src/components/list-item/list-item.tsx | 52 ++++++++++++++----- .../src/components/list-item/resources.ts | 2 + .../src/components/list/list.stories.ts | 28 ++++++++++ 4 files changed, 79 insertions(+), 13 deletions(-) diff --git a/packages/calcite-components/src/components/list-item/list-item.scss b/packages/calcite-components/src/components/list-item/list-item.scss index 928464a0f61..7cfecc3a516 100755 --- a/packages/calcite-components/src/components/list-item/list-item.scss +++ b/packages/calcite-components/src/components/list-item/list-item.scss @@ -74,7 +74,8 @@ td:focus { } .label, -.description { +.description, +.content-bottom { @apply text-n2 word-break font-sans font-normal; &:only-child { @apply m-0 py-1; @@ -102,6 +103,13 @@ td:focus { @apply flex-auto; } +.content-bottom { + @apply bg-foreground-1 flex flex-col; + padding-inline-start: calc( + var(--calcite-list-item-spacing-indent) * var(--calcite-list-item-spacing-indent-multiplier) + ); +} + .content-container--has-center-content .content-start, .content-container--has-center-content .content-end { @apply flex-initial; diff --git a/packages/calcite-components/src/components/list-item/list-item.tsx b/packages/calcite-components/src/components/list-item/list-item.tsx index 5c1b4f27e58..91e9ca18edc 100644 --- a/packages/calcite-components/src/components/list-item/list-item.tsx +++ b/packages/calcite-components/src/components/list-item/list-item.tsx @@ -51,6 +51,7 @@ import { * @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. + * @slot content-bottom - A slot for adding content below the component's `label` and `description`. */ @Component({ tag: "calcite-list-item", @@ -276,6 +277,8 @@ export class ListItem @State() hasContentEnd = false; + @State() hasContentBottom = false; + containerEl: HTMLTableRowElement; contentEl: HTMLTableCellElement; @@ -474,6 +477,35 @@ export class ListItem ); } + renderContentBottom(): VNode { + const { hasContentBottom, visualLevel } = this; + return ( + + ); + } + + renderDefaultContainer(): VNode { + return ( +
+ (this.defaultSlotEl = el)} + /> +
+ ); + } + renderContentProperties(): VNode { const { label, description, hasCustomContent } = this; @@ -535,6 +567,7 @@ export class ListItem selectionAppearance, selectionMode, closed, + visualLevel, } = this; const showBorder = selectionMode !== "none" && selectionAppearance === "border"; @@ -559,7 +592,7 @@ export class ListItem onFocus={this.focusCellNull} onKeyDown={this.handleItemKeyDown} role="row" - style={{ "--calcite-list-item-spacing-indent-multiplier": `${this.visualLevel}` }} + style={{ "--calcite-list-item-spacing-indent-multiplier": `${visualLevel}` }} tabIndex={active ? 0 : -1} // eslint-disable-next-line react/jsx-sort-props -- ref should be last so node attrs/props are in sync (see https://github.com/Esri/calcite-design-system/pull/6530) ref={(el) => (this.containerEl = el)} @@ -571,17 +604,8 @@ export class ListItem {this.renderContentContainer()} {this.renderActionsEnd()} -
- (this.defaultSlotEl = el)} - /> -
+ {this.renderContentBottom()} + {this.renderDefaultContainer()} ); } @@ -621,6 +645,10 @@ export class ListItem this.hasContentEnd = slotChangeHasAssignedElement(event); }; + handleContentBottomSlotChange = (event: Event): void => { + this.hasContentBottom = slotChangeHasAssignedElement(event); + }; + setSelectionDefaults(): void { const { parentListEl, selectionMode, selectionAppearance } = this; diff --git a/packages/calcite-components/src/components/list-item/resources.ts b/packages/calcite-components/src/components/list-item/resources.ts index 3e40f74903d..27cb8de1d3a 100644 --- a/packages/calcite-components/src/components/list-item/resources.ts +++ b/packages/calcite-components/src/components/list-item/resources.ts @@ -14,6 +14,7 @@ export const CSS = { label: "label", description: "description", contentEnd: "content-end", + contentBottom: "content-bottom", actionsEnd: "actions-end", selectionContainer: "selection-container", openContainer: "open-container", @@ -24,6 +25,7 @@ export const SLOTS = { actionsStart: "actions-start", contentStart: "content-start", content: "content", + contentBottom: "content-bottom", contentEnd: "content-end", actionsEnd: "actions-end", }; diff --git a/packages/calcite-components/src/components/list/list.stories.ts b/packages/calcite-components/src/components/list/list.stories.ts index aaeaac3b0d2..b229a824e51 100644 --- a/packages/calcite-components/src/components/list/list.stories.ts +++ b/packages/calcite-components/src/components/list/list.stories.ts @@ -217,6 +217,34 @@ export const startAndEndContentSlots = (): string => html` `; +export const contentBottomSlots = (): string => html` + + Some value or something and a thing. + + + Some value or something and a thing. + + + Some value or something and a thing. + + `; + +export const contentBottomSlotsNested = (): string => html` + + Some value or something and a thing. + + Some value or something and a thing. + Some value or something and a thing. + + + + `; + export const richContent = (): string => html`