Skip to content

calcite-card does not properly handle dynamically added footer slot content #10152

@mjuniper

Description

@mjuniper

Check existing issues

Actual Behavior

Dynamically added footer slots do not render.

Expected Behavior

Dynamically added footer slots like <div slot="footer-end"> will render.

Reproduction Sample

I think this can only be reproduced by creating a stencil component that uses calcite-card. I could probably do this in React Codesandbox but I don't know react well enough.

Reproduction Steps

Create a component like this:

import { Component, Host, State, VNode, h } from '@stencil/core';

@Component({
  tag: 'parent-component',
  // styleUrl: 'parent-component.css',
  shadow: true,
})
export class ParentComponent {

  // The button works as expected, toggling the slot on and off
  // But _only_ if the initial value of showSlot is true
  @State() showSlot = false;

  maybeRenderSlot(slotName): VNode {
    if (this.showSlot) {
      return <div slot={slotName}>foobar</div>;
    }
  }

  render() {
    return (
      <Host data-element="parent-component">
        This is the parent component
        <calcite-button onClick={_ => this.showSlot = !this.showSlot}>Toggle Slot</calcite-button>
        {/* slotted component is just a very simple stencil component with a named slot
            to try to determine if the problem is specific to calcite-card
            slotted component works as expected
        <slotted-component>
          {this.maybeRenderSlot("main")}
        </slotted-component> */}
        <calcite-card>
          WAT
          {/* <div slot="footer-start">foo</div> */}
          {this.maybeRenderSlot("footer-end")}
        </calcite-card>
      </Host>
    );
  }
}

Then run the samples and observe that the calcite-button in the component works when the initial value of showSlot is true but not when the initial value of showSlot is false.

Reproduction Version

2.11

Relevant Info

I think this can be fixed by doing something like this in calcite-card:

@State() hasFooterStart = false;

@State() hasFooterEnd = false;

get hasFooter(): boolean {
  return this.hasFooterStart || this.hasFooterEnd;
}

private handleFooterStartSlotChange = (event: Event): void => {
  this.hasFooterStart = slotChangeHasAssignedElement(event);
};

private handleFooterEndSlotChange = (event: Event): void => {
  this.hasFooterEnd = slotChangeHasAssignedElement(event);
};

private renderFooter(): VNode {
  const { hasFooter } = this;
  return (
    <footer class={CSS.footer} hidden={!hasFooter}>
      <slot name={SLOTS.footerStart} onSlotchange={this.handleFooterStartSlotChange} />
      <slot name={SLOTS.footerEnd} onSlotchange={this.handleFooterEndSlotChange} />
    </footer>
  );
}

Regression?

No response

Priority impact

impact - p2 - want for an upcoming milestone

Impact

I causes one of the components we commonly use on customer sites to not work properly.

Calcite package

  • @esri/calcite-components
  • @esri/calcite-components-angular
  • @esri/calcite-components-react
  • @esri/calcite-design-tokens
  • @esri/eslint-plugin-calcite-components

Esri team

ArcGIS Hub

Metadata

Metadata

Labels

4 - verifiedIssues that have been tested, confirmed as mitigated, and are ready to close.ArcGIS HubIssues logged by ArcGIS Hub team members.bugBug reports for broken functionality. Issues should include a reproduction of the bug.calcite-componentsIssues specific to the @esri/calcite-components package.estimate - 3A day or two of work, likely requires updates to tests.impact - p2 - want for an upcoming milestoneUser set priority impact status of p2 - want for an upcoming milestonep - highIssue should be addressed in the current milestone, impacts component or core functionality

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions