From e20d41055be59587ca16a97d03500df3f58070b6 Mon Sep 17 00:00:00 2001 From: Matt Driscoll Date: Wed, 22 Jan 2025 11:41:21 -0800 Subject: [PATCH] feat(segmented-control, segmented-control-item): add component tokens #7180 --- .../segmented-control-item.e2e.ts | 34 ++++++++++- .../segmented-control-item.scss | 58 ++++++++++++------- .../segmented-control.e2e.ts | 11 ++++ .../segmented-control/segmented-control.scss | 10 +++- .../src/custom-theme.stories.ts | 3 +- .../src/custom-theme/segmented-control.ts | 8 +++ .../src/demos/segmented-control.html | 41 +++++++++++++ 7 files changed, 140 insertions(+), 25 deletions(-) diff --git a/packages/calcite-components/src/components/segmented-control-item/segmented-control-item.e2e.ts b/packages/calcite-components/src/components/segmented-control-item/segmented-control-item.e2e.ts index 23a000df708..ad7646fe5bf 100644 --- a/packages/calcite-components/src/components/segmented-control-item/segmented-control-item.e2e.ts +++ b/packages/calcite-components/src/components/segmented-control-item/segmented-control-item.e2e.ts @@ -1,6 +1,7 @@ import { newE2EPage } from "@arcgis/lumina-compiler/puppeteerTesting"; import { describe, expect, it } from "vitest"; -import { renders, hidden } from "../../tests/commonTests"; +import { renders, hidden, themed } from "../../tests/commonTests"; +import { html } from "../../../support/formatting"; import { CSS } from "./resources"; describe("calcite-segmented-control-item", () => { @@ -40,7 +41,7 @@ describe("calcite-segmented-control-item", () => { it("renders icon at start if requested", async () => { const page = await newE2EPage(); await page.setContent(` - Content`); + Content`); const icon = await page.find(`calcite-segmented-control-item >>> .${CSS.icon}`); expect(icon).not.toBe(null); }); @@ -48,7 +49,7 @@ describe("calcite-segmented-control-item", () => { it("does not render icon if not requested", async () => { const page = await newE2EPage(); await page.setContent(` - Content`); + Content`); const icon = await page.find(`calcite-segmented-control-item >>> .${CSS.icon}`); expect(icon).toBe(null); }); @@ -108,4 +109,31 @@ describe("calcite-segmented-control-item", () => { expect(element).not.toHaveAttribute("icon-end"); }); }); + + describe("theme", () => { + themed("calcite-segmented-control-item", { + "--calcite-segmented-control-color": { + shadowSelector: `.${CSS.label}`, + targetProp: "color", + }, + "--calcite-segmented-control-background-color": { + shadowSelector: `.${CSS.label}`, + targetProp: "backgroundColor", + }, + "--calcite-segmented-control-border-color": { + shadowSelector: `.${CSS.label}`, + targetProp: "borderColor", + }, + "--calcite-segmented-control-shadow": { + shadowSelector: `.${CSS.label}`, + targetProp: "boxShadow", + }, + }); + themed(html`Content`, { + "--calcite-segmented-control-icon-color": { + shadowSelector: `.${CSS.icon}`, + targetProp: "--calcite-icon-color", + }, + }); + }); }); diff --git a/packages/calcite-components/src/components/segmented-control-item/segmented-control-item.scss b/packages/calcite-components/src/components/segmented-control-item/segmented-control-item.scss index 3f666f4130d..8c5730c8992 100644 --- a/packages/calcite-components/src/components/segmented-control-item/segmented-control-item.scss +++ b/packages/calcite-components/src/components/segmented-control-item/segmented-control-item.scss @@ -1,21 +1,37 @@ +/** + * CSS Custom Properties + * + * These properties can be overridden using the component's tag as selector. + * + * @prop --calcite-segmented-control-color: Specifies the component's color. + * @prop --calcite-segmented-control-background-color: Specifies the component's background color. + * @prop --calcite-segmented-control-border-color: Specifies the component's border color. + * @prop --calcite-segmented-control-shadow: Specifies the component's shadow. + * @prop --calcite-segmented-control-icon-color: Specifies the icons's color. + */ + :host { @apply flex cursor-pointer self-stretch - font-normal; + font-normal + focus-base; transition: background-color var(--calcite-internal-animation-timing-fast) ease-in-out, border-color var(--calcite-animation-timing) ease-in-out; } -:host label { - @apply text-color-3 - pointer-events-none +.label { + @apply pointer-events-none m-0.5 box-border flex flex-1 items-center; + color: var(--calcite-segmented-control-color, var(--calcite-color-text-3)); + background-color: var(--calcite-segmented-control-background-color); + box-shadow: var(--calcite-segmented-control-shadow); + border-color: var(--calcite-segmented-control-border-color); transition: background-color var(--calcite-internal-animation-timing-fast) ease-in-out, border-color var(--calcite-internal-animation-timing-fast) ease-in-out, @@ -26,10 +42,6 @@ @apply justify-center; } -// focus styles -:host { - @apply focus-base; -} :host(:focus) { @apply focus-inset; outline-offset: -1px; @@ -49,27 +61,32 @@ @apply text-0h px-4 py-2.5; } -:host(:hover) label { - @apply bg-foreground-2 text-color-1; +:host(:hover) .label { + background-color: var(--calcite-segmented-control-background-color, var(--calcite-color-foreground-2)); + color: var(--calcite-segmented-control-color, var(--calcite-color-text-1)); } -:host(:active) label { - @apply bg-foreground-3; +:host(:active) .label { + background-color: var(--calcite-segmented-control-background-color, var(--calcite-color-foreground-3)); } -:host([checked]) label { - @apply bg-brand border-color-brand cursor-default text-color-inverse; +:host([checked]) .label { + @apply cursor-default; + background-color: var(--calcite-segmented-control-background-color, var(--calcite-color-brand)); + border-color: var(--calcite-segmented-control-border-color, var(--calcite-color-brand)); + color: var(--calcite-segmented-control-color, var(--calcite-color-text-inverse)); } :host([checked]) .label--outline, :host([checked]) .label--outline-fill { - @apply bg-foreground-1 border-color-brand; - box-shadow: inset 0 0 0 1px theme("backgroundColor.brand"); - color: theme("backgroundColor.brand"); + background-color: var(--calcite-segmented-control-background-color, var(--calcite-color-foreground-1)); + border-color: var(--calcite-segmented-control-border-color, var(--calcite-color-brand)); + box-shadow: var(--calcite-segmented-control-shadow, inset 0 0 0 1px var(--calcite-color-brand)); + color: var(--calcite-segmented-control-color, var(--calcite-color-brand)); } :host([checked]) .label--outline { - @apply bg-transparent; + background-color: var(--calcite-segmented-control-background-color, transparent); } ::slotted(input) { @@ -77,14 +94,14 @@ } @media (forced-colors: active) { - :host([checked]) label { + :host([checked]) .label { background-color: highlight; } :host([checked]) .label--outline, :host([checked]) .label--outline-fill { @apply outline-none; } - :host([checked]) label:not([class~="label--outline"]) .icon { + :host([checked]) .label:not([class~="label--outline"]) .icon { color: highlightText; } } @@ -97,6 +114,7 @@ margin-inline-start: var(--calcite-internal-segmented-control-icon-margin-start); margin-inline-end: var(--calcite-internal-segmented-control-icon-margin-end); + --calcite-icon-color: var(--calcite-segmented-control-icon-color); } :host([icon-start]) .label--scale-s { diff --git a/packages/calcite-components/src/components/segmented-control/segmented-control.e2e.ts b/packages/calcite-components/src/components/segmented-control/segmented-control.e2e.ts index 2b7bd486c9a..9d78dfc6110 100644 --- a/packages/calcite-components/src/components/segmented-control/segmented-control.e2e.ts +++ b/packages/calcite-components/src/components/segmented-control/segmented-control.e2e.ts @@ -11,9 +11,11 @@ import { labelable, reflects, renders, + themed, } from "../../tests/commonTests"; import { GlobalTestProps } from "../../tests/utils"; import type { SegmentedControl } from "./segmented-control"; +import { CSS } from "./resources"; describe("calcite-segmented-control", () => { describe("defaults", () => { @@ -495,4 +497,13 @@ describe("calcite-segmented-control", () => { ); }); }); + + describe("theme", () => { + themed("calcite-segmented-control", { + "--calcite-segmented-control-border-color": { + shadowSelector: `.${CSS.itemWrapper}`, + targetProp: "outlineColor", + }, + }); + }); }); diff --git a/packages/calcite-components/src/components/segmented-control/segmented-control.scss b/packages/calcite-components/src/components/segmented-control/segmented-control.scss index aee1e1863d8..36ddc1502a8 100644 --- a/packages/calcite-components/src/components/segmented-control/segmented-control.scss +++ b/packages/calcite-components/src/components/segmented-control/segmented-control.scss @@ -1,3 +1,11 @@ +/** + * CSS Custom Properties + * + * These properties can be overridden using the component's tag as selector. + * + * @prop --calcite-segmented-control-border-color: Specifies the component's border color. + */ + :host { @apply flex flex-col; } @@ -5,7 +13,7 @@ .item-wrapper { @apply bg-foreground-1 flex; inline-size: fit-content; - outline: 1px solid var(--calcite-color-border-input); + outline: 1px solid var(--calcite-segmented-control-border-color, var(--calcite-color-border-input)); outline-offset: -1px; } diff --git a/packages/calcite-components/src/custom-theme.stories.ts b/packages/calcite-components/src/custom-theme.stories.ts index 6e74361034c..a51479ca2da 100644 --- a/packages/calcite-components/src/custom-theme.stories.ts +++ b/packages/calcite-components/src/custom-theme.stories.ts @@ -37,7 +37,7 @@ import { notice, noticeTokens } from "./custom-theme/notice"; import { pagination, paginationTokens } from "./custom-theme/pagination"; import { popover, popoverTokens } from "./custom-theme/popover"; import { progress, progressTokens } from "./custom-theme/progress"; -import { segmentedControl } from "./custom-theme/segmented-control"; +import { segmentedControl, segmentedControlTokens } from "./custom-theme/segmented-control"; import { select, selectTokens } from "./custom-theme/select"; import { rating, ratingTokens } from "./custom-theme/rating"; import { slider, sliderTokens } from "./custom-theme/slider"; @@ -174,6 +174,7 @@ const componentTokens = { ...paginationTokens, ...popoverTokens, ...progressTokens, + ...segmentedControlTokens, ...ratingTokens, ...selectTokens, ...sliderTokens, diff --git a/packages/calcite-components/src/custom-theme/segmented-control.ts b/packages/calcite-components/src/custom-theme/segmented-control.ts index 72aa38b76e6..54089a9889f 100644 --- a/packages/calcite-components/src/custom-theme/segmented-control.ts +++ b/packages/calcite-components/src/custom-theme/segmented-control.ts @@ -1,5 +1,13 @@ import { html } from "../../support/formatting"; +export const segmentedControlTokens = { + calciteSegmentedControlColor: "", + calciteSegmentedControlBackgroundColor: "", + calciteSegmentedControlBorderColor: "", + calciteSegmentedControlShadow: "", + calciteSegmentedControlIconColor: "", +}; + export const segmentedControl = html` Segmented Control diff --git a/packages/calcite-components/src/demos/segmented-control.html b/packages/calcite-components/src/demos/segmented-control.html index b221da85280..2f3c8fba87c 100644 --- a/packages/calcite-components/src/demos/segmented-control.html +++ b/packages/calcite-components/src/demos/segmented-control.html @@ -1560,6 +1560,47 @@ + +
+
themed
+ + +
+ + React + Ember + Angular + Vue + +
+ +
+ + React + Ember + Angular + Vue + +
+ +
+ + React + Ember + Angular + Vue + +
+