Skip to content

Commit c4ba38f

Browse files
committed
fix(card): properly handle slotted elements. #10152 #6059
1 parent 3ed86ce commit c4ba38f

File tree

2 files changed

+180
-29
lines changed

2 files changed

+180
-29
lines changed

packages/calcite-components/src/components.d.ts

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,91 +9,191 @@ import { Alignment, Appearance, CollapseDirection, FlipContext, IconType, Kind,
99
import { RequestedItem } from "./components/accordion/interfaces";
1010
import { IconNameOrString } from "./components/icon/interfaces";
1111
import { RequestedItem as RequestedItem1 } from "./components/accordion-item/interfaces";
12+
import { ActionMessages } from "./components/action/assets/action/t9n";
1213
import { FlipPlacement, LogicalPlacement, MenuPlacement, OverlayPositioning, ReferenceElement } from "./utils/floating-ui";
14+
import { ActionBarMessages } from "./components/action-bar/assets/action-bar/t9n";
1315
import { Columns } from "./components/action-group/interfaces";
16+
import { ActionGroupMessages } from "./components/action-group/assets/action-group/t9n";
17+
import { ActionPadMessages } from "./components/action-pad/assets/action-pad/t9n";
1418
import { AlertDuration, AlertQueue } from "./components/alert/interfaces";
1519
import { NumberingSystem } from "./utils/locale";
20+
import { AlertMessages } from "./components/alert/assets/alert/t9n";
1621
import { HeadingLevel } from "./components/functional/Heading";
22+
import { BlockMessages } from "./components/block/assets/block/t9n";
1723
import { BlockSectionToggleDisplay } from "./components/block-section/interfaces";
24+
import { BlockSectionMessages } from "./components/block-section/assets/block-section/t9n";
1825
import { ButtonAlignment, DropdownIconType } from "./components/button/interfaces";
26+
import { ButtonMessages } from "./components/button/assets/button/t9n";
27+
import { CardMessages } from "./components/card/assets/card/t9n";
1928
import { ArrowType, AutoplayType } from "./components/carousel/interfaces";
29+
import { CarouselMessages } from "./components/carousel/assets/carousel/t9n";
2030
import { MutableValidityState } from "./utils/form";
31+
import { ChipMessages } from "./components/chip/assets/chip/t9n";
2132
import { ColorValue, InternalColor } from "./components/color-picker/interfaces";
2233
import { Format } from "./components/color-picker/utils";
34+
import { ColorPickerMessages } from "./components/color-picker/assets/color-picker/t9n";
2335
import { ComboboxChildElement, SelectionDisplay } from "./components/combobox/interfaces";
36+
import { ComboboxMessages } from "./components/combobox/assets/combobox/t9n";
37+
import { DatePickerMessages } from "./components/date-picker/assets/date-picker/t9n";
2438
import { DateLocaleData } from "./components/date-picker/utils";
2539
import { HoverRange } from "./utils/date";
40+
import { DialogMessages } from "./components/dialog/assets/dialog/t9n";
2641
import { DialogPlacement } from "./components/dialog/interfaces";
2742
import { RequestedItem as RequestedItem2 } from "./components/dropdown-group/interfaces";
2843
import { ItemKeyboardEvent } from "./components/dropdown/interfaces";
44+
import { FilterMessages } from "./components/filter/assets/filter/t9n";
2945
import { FlowItemLikeElement } from "./components/flow/interfaces";
46+
import { FlowItemMessages } from "./components/flow-item/assets/flow-item/t9n";
3047
import { ColorStop, DataSeries } from "./components/graph/interfaces";
48+
import { HandleMessages } from "./components/handle/assets/handle/t9n";
3149
import { HandleChange, HandleNudge } from "./components/handle/interfaces";
50+
import { InlineEditableMessages } from "./components/inline-editable/assets/inline-editable/t9n";
3251
import { InputPlacement } from "./components/input/interfaces";
52+
import { InputMessages } from "./components/input/assets/input/t9n";
53+
import { InputDatePickerMessages } from "./components/input-date-picker/assets/input-date-picker/t9n";
54+
import { InputNumberMessages } from "./components/input-number/assets/input-number/t9n";
55+
import { InputTextMessages } from "./components/input-text/assets/input-text/t9n";
56+
import { InputTimePickerMessages } from "./components/input-time-picker/assets/input-time-picker/t9n";
57+
import { TimePickerMessages } from "./components/time-picker/assets/time-picker/t9n";
58+
import { InputTimeZoneMessages } from "./components/input-time-zone/assets/input-time-zone/t9n";
3359
import { OffsetStyle, TimeZoneMode } from "./components/input-time-zone/interfaces";
3460
import { ListDragDetail } from "./components/list/interfaces";
3561
import { ItemData } from "./components/list-item/interfaces";
62+
import { ListMessages } from "./components/list/assets/list/t9n";
3663
import { SelectionAppearance } from "./components/list/resources";
64+
import { ListItemMessages } from "./components/list-item/assets/list-item/t9n";
65+
import { MenuMessages } from "./components/menu/assets/menu/t9n";
66+
import { MenuItemMessages } from "./components/menu-item/assets/menu-item/t9n";
3767
import { MenuItemCustomEvent } from "./components/menu-item/interfaces";
3868
import { MeterFillType, MeterLabelType } from "./components/meter/interfaces";
69+
import { ModalMessages } from "./components/modal/assets/modal/t9n";
70+
import { NoticeMessages } from "./components/notice/assets/notice/t9n";
71+
import { PaginationMessages } from "./components/pagination/assets/pagination/t9n";
72+
import { PanelMessages } from "./components/panel/assets/panel/t9n";
3973
import { ItemData as ItemData1, ListFocusId } from "./components/pick-list/shared-list-logic";
4074
import { ICON_TYPES } from "./components/pick-list/resources";
75+
import { PickListItemMessages } from "./components/pick-list-item/assets/pick-list-item/t9n";
76+
import { PopoverMessages } from "./components/popover/assets/popover/t9n";
77+
import { RatingMessages } from "./components/rating/assets/rating/t9n";
78+
import { ScrimMessages } from "./components/scrim/assets/scrim/t9n";
4179
import { DisplayMode } from "./components/sheet/interfaces";
4280
import { DisplayMode as DisplayMode1 } from "./components/shell-panel/interfaces";
81+
import { ShellPanelMessages } from "./components/shell-panel/assets/shell-panel/t9n";
4382
import { DragDetail } from "./utils/sortableComponent";
4483
import { StepperItemChangeEventDetail, StepperItemEventDetail, StepperItemKeyEventDetail, StepperLayout } from "./components/stepper/interfaces";
84+
import { StepperMessages } from "./components/stepper/assets/stepper/t9n";
85+
import { StepperItemMessages } from "./components/stepper-item/assets/stepper-item/t9n";
4586
import { TabID, TabLayout, TabPosition } from "./components/tabs/interfaces";
87+
import { TabNavMessages } from "./components/tab-nav/assets/tab-nav/t9n";
4688
import { Element } from "@stencil/core";
4789
import { TabChangeEventDetail, TabCloseEventDetail } from "./components/tab/interfaces";
90+
import { TabTitleMessages } from "./components/tab-title/assets/tab-title/t9n";
4891
import { RowType, TableInteractionMode, TableLayout, TableRowFocusEvent, TableSelectionDisplay } from "./components/table/interfaces";
92+
import { TableMessages } from "./components/table/assets/table/t9n";
93+
import { TableCellMessages } from "./components/table-cell/assets/table-cell/t9n";
94+
import { TableHeaderMessages } from "./components/table-header/assets/table-header/t9n";
95+
import { TextAreaMessages } from "./components/text-area/assets/text-area/t9n";
4996
import { TileSelectType } from "./components/tile-select/interfaces";
5097
import { TileSelectGroupLayout } from "./components/tile-select-group/interfaces";
98+
import { TipMessages } from "./components/tip/assets/tip/t9n";
99+
import { TipManagerMessages } from "./components/tip-manager/assets/tip-manager/t9n";
51100
import { TreeItemSelectDetail } from "./components/tree-item/interfaces";
101+
import { ValueListMessages } from "./components/value-list/assets/value-list/t9n";
52102
import { ListItemAndHandle } from "./components/value-list-item/interfaces";
53103
export { Alignment, Appearance, CollapseDirection, FlipContext, IconType, Kind, Layout, LogicalFlowPosition, Position, Scale, SelectionAppearance as SelectionAppearance1, SelectionMode, Status, Width } from "./components/interfaces";
54104
export { RequestedItem } from "./components/accordion/interfaces";
55105
export { IconNameOrString } from "./components/icon/interfaces";
56106
export { RequestedItem as RequestedItem1 } from "./components/accordion-item/interfaces";
107+
export { ActionMessages } from "./components/action/assets/action/t9n";
57108
export { FlipPlacement, LogicalPlacement, MenuPlacement, OverlayPositioning, ReferenceElement } from "./utils/floating-ui";
109+
export { ActionBarMessages } from "./components/action-bar/assets/action-bar/t9n";
58110
export { Columns } from "./components/action-group/interfaces";
111+
export { ActionGroupMessages } from "./components/action-group/assets/action-group/t9n";
112+
export { ActionPadMessages } from "./components/action-pad/assets/action-pad/t9n";
59113
export { AlertDuration, AlertQueue } from "./components/alert/interfaces";
60114
export { NumberingSystem } from "./utils/locale";
115+
export { AlertMessages } from "./components/alert/assets/alert/t9n";
61116
export { HeadingLevel } from "./components/functional/Heading";
117+
export { BlockMessages } from "./components/block/assets/block/t9n";
62118
export { BlockSectionToggleDisplay } from "./components/block-section/interfaces";
119+
export { BlockSectionMessages } from "./components/block-section/assets/block-section/t9n";
63120
export { ButtonAlignment, DropdownIconType } from "./components/button/interfaces";
121+
export { ButtonMessages } from "./components/button/assets/button/t9n";
122+
export { CardMessages } from "./components/card/assets/card/t9n";
64123
export { ArrowType, AutoplayType } from "./components/carousel/interfaces";
124+
export { CarouselMessages } from "./components/carousel/assets/carousel/t9n";
65125
export { MutableValidityState } from "./utils/form";
126+
export { ChipMessages } from "./components/chip/assets/chip/t9n";
66127
export { ColorValue, InternalColor } from "./components/color-picker/interfaces";
67128
export { Format } from "./components/color-picker/utils";
129+
export { ColorPickerMessages } from "./components/color-picker/assets/color-picker/t9n";
68130
export { ComboboxChildElement, SelectionDisplay } from "./components/combobox/interfaces";
131+
export { ComboboxMessages } from "./components/combobox/assets/combobox/t9n";
132+
export { DatePickerMessages } from "./components/date-picker/assets/date-picker/t9n";
69133
export { DateLocaleData } from "./components/date-picker/utils";
70134
export { HoverRange } from "./utils/date";
135+
export { DialogMessages } from "./components/dialog/assets/dialog/t9n";
71136
export { DialogPlacement } from "./components/dialog/interfaces";
72137
export { RequestedItem as RequestedItem2 } from "./components/dropdown-group/interfaces";
73138
export { ItemKeyboardEvent } from "./components/dropdown/interfaces";
139+
export { FilterMessages } from "./components/filter/assets/filter/t9n";
74140
export { FlowItemLikeElement } from "./components/flow/interfaces";
141+
export { FlowItemMessages } from "./components/flow-item/assets/flow-item/t9n";
75142
export { ColorStop, DataSeries } from "./components/graph/interfaces";
143+
export { HandleMessages } from "./components/handle/assets/handle/t9n";
76144
export { HandleChange, HandleNudge } from "./components/handle/interfaces";
145+
export { InlineEditableMessages } from "./components/inline-editable/assets/inline-editable/t9n";
77146
export { InputPlacement } from "./components/input/interfaces";
147+
export { InputMessages } from "./components/input/assets/input/t9n";
148+
export { InputDatePickerMessages } from "./components/input-date-picker/assets/input-date-picker/t9n";
149+
export { InputNumberMessages } from "./components/input-number/assets/input-number/t9n";
150+
export { InputTextMessages } from "./components/input-text/assets/input-text/t9n";
151+
export { InputTimePickerMessages } from "./components/input-time-picker/assets/input-time-picker/t9n";
152+
export { TimePickerMessages } from "./components/time-picker/assets/time-picker/t9n";
153+
export { InputTimeZoneMessages } from "./components/input-time-zone/assets/input-time-zone/t9n";
78154
export { OffsetStyle, TimeZoneMode } from "./components/input-time-zone/interfaces";
79155
export { ListDragDetail } from "./components/list/interfaces";
80156
export { ItemData } from "./components/list-item/interfaces";
157+
export { ListMessages } from "./components/list/assets/list/t9n";
81158
export { SelectionAppearance } from "./components/list/resources";
159+
export { ListItemMessages } from "./components/list-item/assets/list-item/t9n";
160+
export { MenuMessages } from "./components/menu/assets/menu/t9n";
161+
export { MenuItemMessages } from "./components/menu-item/assets/menu-item/t9n";
82162
export { MenuItemCustomEvent } from "./components/menu-item/interfaces";
83163
export { MeterFillType, MeterLabelType } from "./components/meter/interfaces";
164+
export { ModalMessages } from "./components/modal/assets/modal/t9n";
165+
export { NoticeMessages } from "./components/notice/assets/notice/t9n";
166+
export { PaginationMessages } from "./components/pagination/assets/pagination/t9n";
167+
export { PanelMessages } from "./components/panel/assets/panel/t9n";
84168
export { ItemData as ItemData1, ListFocusId } from "./components/pick-list/shared-list-logic";
85169
export { ICON_TYPES } from "./components/pick-list/resources";
170+
export { PickListItemMessages } from "./components/pick-list-item/assets/pick-list-item/t9n";
171+
export { PopoverMessages } from "./components/popover/assets/popover/t9n";
172+
export { RatingMessages } from "./components/rating/assets/rating/t9n";
173+
export { ScrimMessages } from "./components/scrim/assets/scrim/t9n";
86174
export { DisplayMode } from "./components/sheet/interfaces";
87175
export { DisplayMode as DisplayMode1 } from "./components/shell-panel/interfaces";
176+
export { ShellPanelMessages } from "./components/shell-panel/assets/shell-panel/t9n";
88177
export { DragDetail } from "./utils/sortableComponent";
89178
export { StepperItemChangeEventDetail, StepperItemEventDetail, StepperItemKeyEventDetail, StepperLayout } from "./components/stepper/interfaces";
179+
export { StepperMessages } from "./components/stepper/assets/stepper/t9n";
180+
export { StepperItemMessages } from "./components/stepper-item/assets/stepper-item/t9n";
90181
export { TabID, TabLayout, TabPosition } from "./components/tabs/interfaces";
182+
export { TabNavMessages } from "./components/tab-nav/assets/tab-nav/t9n";
91183
export { Element } from "@stencil/core";
92184
export { TabChangeEventDetail, TabCloseEventDetail } from "./components/tab/interfaces";
185+
export { TabTitleMessages } from "./components/tab-title/assets/tab-title/t9n";
93186
export { RowType, TableInteractionMode, TableLayout, TableRowFocusEvent, TableSelectionDisplay } from "./components/table/interfaces";
187+
export { TableMessages } from "./components/table/assets/table/t9n";
188+
export { TableCellMessages } from "./components/table-cell/assets/table-cell/t9n";
189+
export { TableHeaderMessages } from "./components/table-header/assets/table-header/t9n";
190+
export { TextAreaMessages } from "./components/text-area/assets/text-area/t9n";
94191
export { TileSelectType } from "./components/tile-select/interfaces";
95192
export { TileSelectGroupLayout } from "./components/tile-select-group/interfaces";
193+
export { TipMessages } from "./components/tip/assets/tip/t9n";
194+
export { TipManagerMessages } from "./components/tip-manager/assets/tip-manager/t9n";
96195
export { TreeItemSelectDetail } from "./components/tree-item/interfaces";
196+
export { ValueListMessages } from "./components/value-list/assets/value-list/t9n";
97197
export { ListItemAndHandle } from "./components/value-list-item/interfaces";
98198
export namespace Components {
99199
interface CalciteAccordion {

packages/calcite-components/src/components/card/card.tsx

Lines changed: 80 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
VNode,
1212
Watch,
1313
} from "@stencil/core";
14-
import { getSlotted, slotChangeHasAssignedElement, toAriaBoolean } from "../../utils/dom";
14+
import { slotChangeHasAssignedElement, toAriaBoolean } from "../../utils/dom";
1515
import { connectLocalized, disconnectLocalized, LocalizedComponent } from "../../utils/locale";
1616
import {
1717
connectMessages,
@@ -181,6 +181,20 @@ export class Card
181181

182182
@State() effectiveLocale: string;
183183

184+
@State() hasThumbnail = false;
185+
186+
@State() hasHeading = false;
187+
188+
@State() hasDescription = false;
189+
190+
@State() hasSubtitle = false;
191+
192+
@State() hasTitle = false;
193+
194+
@State() hasFooterStart = false;
195+
196+
@State() hasFooterEnd = false;
197+
184198
@Watch("effectiveLocale")
185199
effectiveLocaleChange(): void {
186200
updateMessages(this, this.effectiveLocale);
@@ -198,6 +212,34 @@ export class Card
198212
//
199213
//--------------------------------------------------------------------------
200214

215+
private handleThumbnailSlotChange = (event: Event): void => {
216+
this.hasThumbnail = slotChangeHasAssignedElement(event);
217+
};
218+
219+
private handleHeadingSlotChange = (event: Event): void => {
220+
this.hasHeading = slotChangeHasAssignedElement(event);
221+
};
222+
223+
private handleDescriptionSlotChange = (event: Event): void => {
224+
this.hasDescription = slotChangeHasAssignedElement(event);
225+
};
226+
227+
private handleTitleSlotChange = (event: Event): void => {
228+
this.hasTitle = slotChangeHasAssignedElement(event);
229+
};
230+
231+
private handleSubtitleSlotChange = (event: Event): void => {
232+
this.hasSubtitle = slotChangeHasAssignedElement(event);
233+
};
234+
235+
private handleFooterStartSlotChange = (event: Event): void => {
236+
this.hasFooterStart = slotChangeHasAssignedElement(event);
237+
};
238+
239+
private handleFooterEndSlotChange = (event: Event): void => {
240+
this.hasFooterEnd = slotChangeHasAssignedElement(event);
241+
};
242+
201243
private handleDefaultSlotChange = (event: Event): void => {
202244
this.hasContent = slotChangeHasAssignedElement(event);
203245
};
@@ -265,11 +307,11 @@ export class Card
265307
};
266308

267309
private renderThumbnail(): VNode {
268-
return getSlotted(this.el, SLOTS.thumbnail) ? (
269-
<section class={CSS.thumbnailWrapper}>
270-
<slot name={SLOTS.thumbnail} />
310+
return (
311+
<section class={CSS.thumbnailWrapper} hidden={!this.hasThumbnail}>
312+
<slot name={SLOTS.thumbnail} onSlotchange={this.handleThumbnailSlotChange} />
271313
</section>
272-
) : null;
314+
);
273315
}
274316

275317
private renderSelectionIcon(): VNode {
@@ -290,39 +332,48 @@ export class Card
290332
}
291333

292334
private renderHeader(): VNode {
293-
const { el } = this;
294-
const heading = getSlotted(el, SLOTS.heading);
295-
const description = getSlotted(el, SLOTS.description);
296-
const hasHeader = heading || description;
297-
const subtitle = getSlotted(el, SLOTS.subtitle);
298-
const title = getSlotted(el, SLOTS.title);
299-
const hasDeprecatedHeader = subtitle || title;
300-
return hasHeader || hasDeprecatedHeader ? (
301-
<header class={CSS.header}>
335+
const hasHeader = this.hasHeading || this.hasDescription;
336+
const hasDeprecatedHeader = this.hasSubtitle || this.hasTitle;
337+
const showHeader = hasHeader || hasDeprecatedHeader;
338+
339+
return (
340+
<header class={CSS.header} hidden={!showHeader}>
302341
{this.selectable ? this.renderCheckboxDeprecated() : null}
303342
<div class={CSS.headerTextContainer}>
304-
<slot key="heading-slot" name={SLOTS.heading} />
305-
<slot key="description-slot" name={SLOTS.description} />
306-
<slot key="deprecated-title-slot" name={SLOTS.title} />
307-
<slot key="deprecated-subtitle-slot" name={SLOTS.subtitle} />
343+
<slot
344+
key="heading-slot"
345+
name={SLOTS.heading}
346+
onSlotchange={this.handleHeadingSlotChange}
347+
/>
348+
<slot
349+
key="description-slot"
350+
name={SLOTS.description}
351+
onSlotchange={this.handleDescriptionSlotChange}
352+
/>
353+
<slot
354+
key="deprecated-title-slot"
355+
name={SLOTS.title}
356+
onSlotchange={this.handleTitleSlotChange}
357+
/>
358+
<slot
359+
key="deprecated-subtitle-slot"
360+
name={SLOTS.subtitle}
361+
onSlotchange={this.handleSubtitleSlotChange}
362+
/>
308363
</div>
309364
{this.selectionMode !== "none" && this.renderSelectionIcon()}
310365
</header>
311-
) : null;
366+
);
312367
}
313368

314369
private renderFooter(): VNode {
315-
const { el } = this;
316-
const startFooter = getSlotted(el, SLOTS.footerStart);
317-
const endFooter = getSlotted(el, SLOTS.footerEnd);
318-
319-
const hasFooter = startFooter || endFooter;
320-
return hasFooter ? (
321-
<footer class={CSS.footer}>
322-
<slot name={SLOTS.footerStart} />
323-
<slot name={SLOTS.footerEnd} />
370+
const hasFooter = this.hasFooterStart || this.hasFooterEnd;
371+
return (
372+
<footer class={CSS.footer} hidden={!hasFooter}>
373+
<slot name={SLOTS.footerStart} onSlotchange={this.handleFooterStartSlotChange} />
374+
<slot name={SLOTS.footerEnd} onSlotchange={this.handleFooterEndSlotChange} />
324375
</footer>
325-
) : null;
376+
);
326377
}
327378

328379
render(): VNode {

0 commit comments

Comments
 (0)