Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { newE2EPage } from "@stencil/core/testing";
import { html } from "../../../support/formatting";
import { accessible, renders, hidden, disabled } from "../../tests/commonTests";
import { accessible, renders, hidden, disabled, themed } from "../../tests/commonTests";
import { CSS } from "../card/resources";
import { createSelectedItemsAsserter } from "../../tests/utils";

Expand Down Expand Up @@ -441,4 +441,23 @@ describe("calcite-card-group", () => {
expect(await element.getProperty("selectedItems")).toHaveLength(2);
await selectedItemAsserter([card4.id, card5.id]);
});

describe("theme", () => {
describe("default", () => {
themed("calcite-card-group", {
"--calcite-card-group-space": {
shadowSelector: `.${CSS.container}`,
targetProp: "gap",
},
});
});
describe("deprecated", () => {
themed("calcite-card-group", {
"--calcite-card-group-gap": {
shadowSelector: `.${CSS.container}`,
targetProp: "gap",
},
});
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,19 @@
*
* These properties can be overridden using the component's tag as selector.
*
* @prop --calcite-card-group-gap: Specifies the gap between slotted components.
* @prop --calcite-card-group-gap: [Deprecated] Use --calcite-card-group-space. Specifies the gap between slotted components.
* @prop --calcite-card-group-space: Specifies the space between slotted components.
*/

:host {
--calcite-card-group-gap: var(--calcite-size-md);
display: block;
@apply block;
}

.container {
display: flex;
flex-wrap: wrap;
gap: var(--calcite-card-group-gap);
gap: var(--calcite-card-group-space, var(--calcite-card-group-gap, var(--calcite-size-md)));
}

@include disabled();
@include base-component();
@include disabled();
68 changes: 67 additions & 1 deletion packages/calcite-components/src/components/card/card.e2e.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { newE2EPage } from "@stencil/core/testing";
import { accessible, renders, slots, hidden, t9n } from "../../tests/commonTests";
import { accessible, renders, slots, hidden, t9n, themed } from "../../tests/commonTests";
import { placeholderImage } from "../../../.storybook/placeholder-image";
import { html } from "../../../support/formatting";
import { CSS, SLOTS } from "./resources";
Expand Down Expand Up @@ -116,4 +116,70 @@ describe("calcite-card", () => {
const loaderContainer = await page.find("calcite-card >>> .calcite-card-loader-container");
expect(loaderContainer.getAttribute("aria-live")).toBe("polite");
});

describe("theme", () => {
describe("default", () => {
themed("calcite-card", {
"--calcite-card-background-color": {
shadowSelector: `.${CSS.contentWrapper}`,
targetProp: "backgroundColor",
},
"--calcite-card-border-color": {
shadowSelector: `.${CSS.contentWrapper}`,
targetProp: "borderColor",
},
"--calcite-card-corner-radius": { shadowSelector: `.${CSS.contentWrapper}`, targetProp: "borderRadius" },
"--calcite-card-shadow": { shadowSelector: `.${CSS.contentWrapper}`, targetProp: "boxShadow" },
});
});
describe("selectable", () => {
describe("default", () => {
themed(
html`<calcite-card label="example-label" selectable>
<h3 slot="title">ArcGIS Online: Gallery and Organization pages</h3>
<span slot="subtitle">
A great example of a study description that might wrap to a line or two, but isn't overly verbose.
</span>
</calcite-card>`,
{
"--calcite-card-selection-background-color-hover": {
shadowSelector: `.${CSS.checkboxWrapperDeprecated}`,
targetProp: "backgroundColor",
state: "hover",
},
"--calcite-card-selection-background-color-press": {
shadowSelector: `.${CSS.checkboxWrapperDeprecated}`,
targetProp: "backgroundColor",
state: { press: { attribute: "class", value: CSS.checkboxWrapperDeprecated } },
},
"--calcite-card-selection-color": {
shadowSelector: `.${CSS.checkboxWrapperDeprecated}`,
targetProp: "color",
},
"--calcite-card-selection-color-hover": {
shadowSelector: `.${CSS.checkboxWrapperDeprecated}`,
targetProp: "color",
state: "hover",
},
},
);
});
describe("selected", () => {
themed(
html`<calcite-card label="example-label" selectable selected>
<h3 slot="title">ArcGIS Online: Gallery and Organization pages</h3>
<span slot="subtitle">
A great example of a study description that might wrap to a line or two, but isn't overly verbose.
</span>
</calcite-card>`,
{
"--calcite-card-accent-color-selected": {
shadowSelector: `.${CSS.checkboxWrapperDeprecated}`,
targetProp: "color",
},
},
);
});
});
});
});
107 changes: 63 additions & 44 deletions packages/calcite-components/src/components/card/card.scss
Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,26 @@
*
* These properties can be overridden using the component's tag as selector.
*
* @prop --calcite-card-accent-color-selected: Specifies the accent color of the component when `selected`.
* @prop --calcite-card-background-color: Specifies the background color of the component.
* @prop --calcite-card-border-color: Specifies the border color of the component.
* @prop --calcite-card-shadow: Specifies the shadow of the component.
* @prop --calcite-card-corner-radius: Specifies the corner radius of the component.
* @prop --calcite-card-accent-color-selected: Specifies the accent color of the component when `selected`.
* @prop --calcite-card-selection-background-color: Specifies the background color of the component's selection element.
* @prop --calcite-card-selection-background-color-active: [Deprecated] Use --calcite-card-selection-background-color-press. Specifies the background color of the component's selection element when active.
* @prop --calcite-card-selection-background-color-hover: Specifies the background color of the component's selection element when hovered.
* @prop --calcite-card-selection-background-color-active: Specifies the background color of the component's selection element when active.
* @prop --calcite-card-selection-background-color-selected: Specifies the icon color of the component's selection element when `selected`.
* @prop --calcite-card-selection-icon-color: Specifies the icon color of the component's selection element.
* @prop --calcite-card-selection-icon-color-hover: Specifies the icon color of the component's selection element when hovered.
* @prop --calcite-card-selection-icon-color-selected: Specifies the icon color of the component's selection element when `selected`.
* @prop --calcite-card-selection-background-color-press: Specifies the background color of the component's selection element when active.
* @prop --calcite-card-selection-background-color-selected: [Deprecated] Use --calcite-card-background-color. Specifies the icon color of the component's selection element when `selected`.
Copy link
Copy Markdown
Contributor

@macandcheese macandcheese Aug 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these still intended to be deprecated?

I would not expect to use “—calcite-card-background-color” to control the background color of the internal “checkbox element” like this deprecation message suggests.

The newly introduced names are confusing to me, there is no general hover or press state or interaction case for a Card component itself, those states should be applied separately via css prop imo. If a user wants to set calcite-card:hover { whatever } they can do so, but this internally rendered element is different.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes.

  1. the checkbox component should probably control it's own hover styles anyway
  2. this is added style complexity which breaks our existing design patterns unless there is a current user request use case I don't know about.
  3. While the entire card background doesn't change there is a design pattern of foreground-1 for default, foreground-2 for hover, and foreground-3 for active, which is basically what we are doing. The goal is not to recreate CSS styling or JS props with CSS variables but to create a baseline set of styles which allow flexibility while maintaining our styling cadence. Naming every sub-element in a component with it's own set of variables when changing only the styles of that one element would break the design pattern without cause is an anti-pattern IMO

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not actually a checkbox component - it's just a styled div with an icon as it is in most other selection-enabled components.

The design I posted above with the multiple selection cards is a real-world use case I'd like to achieve (and is currently possible) - so removing these would prevent that design. We shouldn't be arbiters of theming choices - if we are truly making our components fully them able via tokens, everything should be theme able, not just what some deem appropriate.

I think this proposed nomenclature is more confusing - there is no hover state for the card - and we want folks to use stateful overrides (:hover, etc.) for actual parent-level adjustments based on those interactions right?

IMO setting --calcite-card-background-color-hover to control the bg of a portion of the card doesn't make sense.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we are truly making our components fully them able via tokens, everything should be theme able, not just what some deem appropriate.

This is not what we have discussed as a team. What we are providing is white labeling. We still have design patterns we have set and want to adhere to. That said, I can understand your argument against --calcite-card-background-color-hover, I've updated the tokens. Is this an acceptable compromise?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good

* @prop --calcite-card-selection-background-color: [Deprecated] Use --calcite-card-background-color. Specifies the background color of the component's selection element.
* @prop --calcite-card-selection-color-hover: Specifies the color of the component's selection element when hovered or focused.
* @prop --calcite-card-selection-color: Specifies the color of the component's selection element.
* @prop --calcite-card-selection-icon-color-hover: [Deprecated] Use --calcite-card-selection-color-hover. Specifies the icon color of the component's selection element when hovered.
* @prop --calcite-card-selection-icon-color-selected: [Deprecated] Use --calcite-card-accent-color-selected. Specifies the icon color of the component's selection element when `selected`.
* @prop --calcite-card-selection-icon-color: [Deprecated] Use --calcite-card-selection-color. Specifies the icon color of the component's selection element.
* @prop --calcite-card-shadow: Specifies the shadow of the component.
*
*/

:host {
@apply block max-w-full;
--calcite-card-corner-radius: var(--calcite-corner-radius-sharp);
--calcite-card-background-color: var(--calcite-color-foreground-1);
--calcite-card-border-color: var(--calcite-color-border-3);
--calcite-card-shadow: var(--calcite-shadow-none);
--calcite-card-accent-color-selected: var(--calcite-color-brand);
--calcite-card-selection-background-color: transparent;
--calcite-card-selection-background-color-hover: var(--calcite-color-transparent-hover);
--calcite-card-selection-background-color-active: var(--calcite-color-transparent-press);
--calcite-card-selection-background-color-selected: transparent;
--calcite-card-selection-icon-color: var(--calcite-color-text-3);
--calcite-card-selection-icon-color-hover: var(--calcite-color-text-2);
--calcite-card-selection-icon-color-selected: var(--calcite-color-brand);
}

.content-wrapper {
Expand All @@ -41,10 +32,10 @@
flex-col
justify-between
overflow-hidden;
border: var(--calcite-border-width-sm) solid var(--calcite-card-border-color);
border-radius: var(--calcite-card-corner-radius);
background-color: var(--calcite-card-background-color);
box-shadow: var(--calcite-card-shadow);
border: var(--calcite-border-width-sm) solid var(--calcite-card-border-color, var(--calcite-color-border-3));
border-radius: var(--calcite-card-corner-radius, var(--calcite-corner-radius-sharp));
background-color: var(--calcite-card-background-color, var(--calcite-color-foreground-1));
box-shadow: var(--calcite-card-shadow, var(--calcite-shadow-none));
pointer-events: none;
}

Expand Down Expand Up @@ -111,7 +102,7 @@
}

:host([selected]) .content-wrapper {
box-shadow: inset 0 -4px 0 0 var(--calcite-card-accent-color-selected);
box-shadow: inset 0 -4px 0 0 var(--calcite-card-accent-color-selected, var(--calcite-color-brand));
}

:host([selectable]) .header {
Expand Down Expand Up @@ -159,53 +150,81 @@
@apply text-n2-wrap self-center;
}

// deprecated
.checkbox-wrapper-deprecated {
@apply absolute pointer-events-auto;
inset-block-start: var(--calcite-spacing-sm);
inset-inline-end: var(--calcite-spacing-sm);
margin: 0;
padding: 0;
color: var(--calcite-card-selection-color, var(--calcite-color-text-3));

&:hover {
background-color: var(--calcite-card-selection-background-color-hover, var(--calcite-color-foreground-2));
color: var(
--calcite-card-selection-color-hover,
var(--calcite-card-selection-icon-color-hover, var(--calcite-color-text-2))
);
}
&:active {
background-color: var(--calcite-card-selection-background-color-press, var(--calcite-color-transparent-press));
}
}

.checkbox-wrapper {
@apply m-2 p-2 focus-base cursor-pointer pointer-events-auto;
background-color: var(--calcite-card-selection-background-color);
display: flex;
align-items: center;
justify-items: center;
--calcite-icon-color: var(--calcite-card-selection-icon-color);
color: var(--calcite-card-selection-color, var(--calcite-color-text-3));

&:hover {
background-color: var(--calcite-card-selection-background-color-hover);
--calcite-icon-color: var(--calcite-card-selection-icon-color-hover);
background-color: var(--calcite-card-selection-background-color-hover, var(--calcite-color-foreground-2));
color: var(
--calcite-card-selection-color-hover,
var(--calcite-card-selection-icon-color-hover, var(--calcite-color-text-2))
);
}
&:active {
background-color: var(--calcite-card-selection-background-color-active);
background-color: var(--calcite-card-selection-background-color-press, var(--calcite-color-transparent-press));
}
& calcite-icon {
pointer-events: none;
}
}

:host([selected]) .checkbox-wrapper {
--calcite-icon-color: var(--calcite-card-selection-icon-color-selected);
background-color: var(--calcite-card-selection-background-color-selected);
&:hover {
background-color: var(--calcite-card-selection-background-color-hover);
}
&:active {
background-color: var(--calcite-card-selection-background-color-active);
:host([selected]) {
.checkbox-wrapper-deprecated,
.checkbox-wrapper {
color: var(
--calcite-card-accent-color-selected,
var(--calcite-card-selection-icon-color-selected, var(--calcite-color-brand))
);
}
}

:host(:not([selectable])) .content-wrapper:not(.non-interactive):focus .checkbox-wrapper {
background-color: var(--calcite-card-selection-background-color-hover);
--calcite-icon-color: var(--calcite-card-selection-icon-color-hover);
:host(:not([selectable])) .content-wrapper:not(.non-interactive):focus {
.checkbox-wrapper-deprecated,
.checkbox-wrapper {
background-color: var(--calcite-card-selection-background-color-hover, var(--calcite-color-foreground-2));
color: var(
--calcite-card-selection-color-hover,
var(--calcite-card-selection-icon-color-hover, var(--calcite-color-text-2))
);
}
}

:host([selected]:not([selectable])) .content-wrapper:not(.non-interactive):focus .checkbox-wrapper {
background-color: var(--calcite-card-selection-background-color-active);
--calcite-icon-color: var(--calcite-card-selection-icon-color-selected);
:host([selected]:not([selectable])) .content-wrapper:not(.non-interactive):focus {
.checkbox-wrapper-deprecated,
.checkbox-wrapper {
background-color: var(--calcite-card-selection-background-color-press, var(--calcite-color-transparent-press));
color: var(
--calcite-card-accent-color-selected,
var(--calcite-card-selection-icon-color-selected, var(--calcite-color-brand))
);
}
}
/* end deprecated */

.thumbnail-wrapper {
@apply flex;
Expand Down
32 changes: 0 additions & 32 deletions packages/calcite-components/src/components/card/card.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,38 +144,6 @@ export const thumbnail = (): string => html`
</div>
`;

export const thumbnailRounded = (): string => html`
<div id="card-container" style="width:260px;">
<style>
calcite-card {
--calcite-border-radius-base: 12px;
}
</style>
<calcite-card>
${thumbnailHtml}
<h3 slot="heading">Portland Businesses</h3>
<span slot="description"
>by
<calcite-link>example_user</calcite-link>
</span>
<div>
Created: Apr 22, 2019
<br />
Updated: Dec 9, 2019
<br />
View Count: 0
</div>
<calcite-button
slot="footer-start"
kind="neutral"
scale="s"
id="card-icon-test-1"
icon-start="circle"
></calcite-button>
</calcite-card>
</div>
`;

export const headerDoesNotOverlapWithCheckboxDeprecated_TestOnly = (): string => html`
<calcite-card selectable style="width:260px">
<h3 slot="heading">Pokem ipsum dolor sit amet Skitty Hoothoot</h3>
Expand Down
3 changes: 2 additions & 1 deletion packages/calcite-components/src/custom-theme.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
} from "./custom-theme/action";
import { accordion } from "./custom-theme/accordion";
import { buttons } from "./custom-theme/button";
import { card, cardTokens } from "./custom-theme/card";
import { card, cardThumbnail, cardTokens } from "./custom-theme/card";
import { checkbox } from "./custom-theme/checkbox";
import { chips } from "./custom-theme/chips";
import { datePicker } from "./custom-theme/date-picker";
Expand Down Expand Up @@ -99,6 +99,7 @@ const kitchenSink = (args: Record<string, string>, useTestValues = false) =>
</div>
<div class="demo-column">
<div>${card}</div>
${cardThumbnail}
<div>${dropdown} ${buttons}</div>
<div>${checkbox}</div>
${chips} ${pagination} ${slider}
Expand Down
Loading