Skip to content

Commit

Permalink
feat(list-item): Add content-bottom slot for placing content below th…
Browse files Browse the repository at this point in the history
…e 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
  • Loading branch information
driskull authored and benelan committed Nov 24, 2023
1 parent 2f60131 commit 5ed0d79
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
52 changes: 40 additions & 12 deletions packages/calcite-components/src/components/list-item/list-item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -276,6 +277,8 @@ export class ListItem

@State() hasContentEnd = false;

@State() hasContentBottom = false;

containerEl: HTMLTableRowElement;

contentEl: HTMLTableCellElement;
Expand Down Expand Up @@ -474,6 +477,35 @@ export class ListItem
);
}

renderContentBottom(): VNode {
const { hasContentBottom, visualLevel } = this;
return (
<div
class={CSS.contentBottom}
hidden={!hasContentBottom}
style={{ "--calcite-list-item-spacing-indent-multiplier": `${visualLevel}` }}
>
<slot name={SLOTS.contentBottom} onSlotchange={this.handleContentBottomSlotChange} />
</div>
);
}

renderDefaultContainer(): VNode {
return (
<div
class={{
[CSS.nestedContainer]: true,
[CSS.nestedContainerHidden]: this.openable && !this.open,
}}
>
<slot
onSlotchange={this.handleDefaultSlotChange}
ref={(el: HTMLSlotElement) => (this.defaultSlotEl = el)}
/>
</div>
);
}

renderContentProperties(): VNode {
const { label, description, hasCustomContent } = this;

Expand Down Expand Up @@ -535,6 +567,7 @@ export class ListItem
selectionAppearance,
selectionMode,
closed,
visualLevel,
} = this;

const showBorder = selectionMode !== "none" && selectionAppearance === "border";
Expand All @@ -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)}
Expand All @@ -571,17 +604,8 @@ export class ListItem
{this.renderContentContainer()}
{this.renderActionsEnd()}
</tr>
<div
class={{
[CSS.nestedContainer]: true,
[CSS.nestedContainerHidden]: openable && !open,
}}
>
<slot
onSlotchange={this.handleDefaultSlotChange}
ref={(el: HTMLSlotElement) => (this.defaultSlotEl = el)}
/>
</div>
{this.renderContentBottom()}
{this.renderDefaultContainer()}
</Host>
);
}
Expand Down Expand Up @@ -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;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -24,6 +25,7 @@ export const SLOTS = {
actionsStart: "actions-start",
contentStart: "content-start",
content: "content",
contentBottom: "content-bottom",
contentEnd: "content-end",
actionsEnd: "actions-end",
};
Expand Down
28 changes: 28 additions & 0 deletions packages/calcite-components/src/components/list/list.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,34 @@ export const startAndEndContentSlots = (): string => html`<calcite-list ${knobsH
</calcite-list-item>
</calcite-list> `;

export const contentBottomSlots = (): string => html`<calcite-list ${knobsHTML()}>
<calcite-list-item label="Princess Bubblegum" description="Ruler of The Candy Kingdom">
<span slot="content-bottom">Some value or something and a <b>thing</b>.</span>
</calcite-list-item>
<calcite-list-item label="Princess Bubblegum" description="Ruler of The Candy Kingdom">
<span slot="content-bottom">Some value or something and a <b>thing</b>.</span>
</calcite-list-item>
<calcite-list-item label="Princess Bubblegum" description="Ruler of The Candy Kingdom">
<span slot="content-bottom">Some value or something and a <b>thing</b>.</span>
</calcite-list-item>
</calcite-list> `;

export const contentBottomSlotsNested = (): string => html`<calcite-list ${knobsHTML()}>
<calcite-list-item label="Princess Bubblegum" description="Ruler of The Candy Kingdom" open>
<span slot="content-bottom">Some value or something and a <b>thing</b>.</span>
<calcite-list
><calcite-list-item label="Princess Bubblegum" description="Ruler of The Candy Kingdom" open>
<span slot="content-bottom">Some value or something and a <b>thing</b>.</span
><calcite-list
><calcite-list-item label="Princess Bubblegum" description="Ruler of The Candy Kingdom">
<span slot="content-bottom">Some value or something and a <b>thing</b>.</span>
</calcite-list-item></calcite-list
>
</calcite-list-item></calcite-list
>
</calcite-list-item>
</calcite-list> `;

export const richContent = (): string => html`
<calcite-list ${knobsHTML()}>
<calcite-list-item label="Princess Bubblegum" description="Ruler of The Candy Kingdom">
Expand Down

0 comments on commit 5ed0d79

Please sign in to comment.