Skip to content

feat(segmented-control, segmented-control-item): add component tokens #11359

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 29, 2025
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,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", () => {
Expand Down Expand Up @@ -40,15 +41,15 @@ describe("calcite-segmented-control-item", () => {
it("renders icon at start if requested", async () => {
const page = await newE2EPage();
await page.setContent(`
<calcite-segmented-control-item icon-start="car">Content</calcite-accordion-item>`);
<calcite-segmented-control-item icon-start="car">Content</calcite-segmented-control-item>`);
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹

const icon = await page.find(`calcite-segmented-control-item >>> .${CSS.icon}`);
expect(icon).not.toBe(null);
});

it("does not render icon if not requested", async () => {
const page = await newE2EPage();
await page.setContent(`
<calcite-segmented-control-item>Content</calcite-accordion-item>`);
<calcite-segmented-control-item>Content</calcite-segmented-control-item>`);
const icon = await page.find(`calcite-segmented-control-item >>> .${CSS.icon}`);
expect(icon).toBe(null);
});
Expand Down Expand Up @@ -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`<calcite-segmented-control-item icon-start="car">Content</calcite-segmented-control-item>`, {
"--calcite-segmented-control-icon-color": {
shadowSelector: `.${CSS.icon}`,
targetProp: "--calcite-icon-color",
},
});
});
});
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -26,10 +42,6 @@
@apply justify-center;
}

// focus styles
:host {
@apply focus-base;
}
:host(:focus) {
@apply focus-inset;
outline-offset: -1px;
Expand All @@ -49,42 +61,47 @@
@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) {
@apply hidden;
}

@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;
}
}
Expand All @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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", () => {
Expand Down Expand Up @@ -495,4 +497,13 @@ describe("calcite-segmented-control", () => {
);
});
});

describe("theme", () => {
themed("calcite-segmented-control", {
"--calcite-segmented-control-border-color": {
shadowSelector: `.${CSS.itemWrapper}`,
targetProp: "outlineColor",
},
});
});
});
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
/**
* 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;
}

.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;
}

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 @@ -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";
Expand Down Expand Up @@ -174,6 +174,7 @@ const componentTokens = {
...paginationTokens,
...popoverTokens,
...progressTokens,
...segmentedControlTokens,
...ratingTokens,
...selectTokens,
...sliderTokens,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
import { html } from "../../support/formatting";

export const segmentedControlTokens = {
calciteSegmentedControlColor: "",
calciteSegmentedControlBackgroundColor: "",
calciteSegmentedControlBorderColor: "",
calciteSegmentedControlShadow: "",
calciteSegmentedControlIconColor: "",
};

export const segmentedControl = html`<calcite-label>
Segmented Control
<calcite-segmented-control>
Expand Down
41 changes: 41 additions & 0 deletions packages/calcite-components/src/demos/segmented-control.html
Original file line number Diff line number Diff line change
Expand Up @@ -1560,6 +1560,47 @@
</calcite-segmented-control>
</div>
</div>

<div
class="parent-flex"
style="
--calcite-segmented-control-color: red;
--calcite-segmented-control-background-color: blue;
--calcite-segmented-control-border-color: pink;
--calcite-segmented-control-shadow: box-shadow: 5px 5px 5px orange;
--calcite-segmented-control-icon-color: yellow;
"
>
<div class="child-flex right-aligned-text">themed</div>

<!-- solid -->
<div class="child-flex">
<calcite-segmented-control scale="s">
<calcite-segmented-control-item icon-end="car" value="react" checked>React</calcite-segmented-control-item>
<calcite-segmented-control-item value="ember">Ember</calcite-segmented-control-item>
<calcite-segmented-control-item value="angular">Angular</calcite-segmented-control-item>
<calcite-segmented-control-item value="vue">Vue</calcite-segmented-control-item>
</calcite-segmented-control>
</div>

<div class="child-flex">
<calcite-segmented-control scale="m">
<calcite-segmented-control-item icon-end="car" value="react" checked>React</calcite-segmented-control-item>
<calcite-segmented-control-item value="ember">Ember</calcite-segmented-control-item>
<calcite-segmented-control-item value="angular">Angular</calcite-segmented-control-item>
<calcite-segmented-control-item value="vue">Vue</calcite-segmented-control-item>
</calcite-segmented-control>
</div>

<div class="child-flex">
<calcite-segmented-control scale="l">
<calcite-segmented-control-item icon-end="car" value="react" checked>React</calcite-segmented-control-item>
<calcite-segmented-control-item value="ember">Ember</calcite-segmented-control-item>
<calcite-segmented-control-item value="angular">Angular</calcite-segmented-control-item>
<calcite-segmented-control-item value="vue">Vue</calcite-segmented-control-item>
</calcite-segmented-control>
</div>
</div>
</demo-dom-swapper>
</body>
</html>
Loading