Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
39ab314
feat(split-button): Add component tokens
macandcheese Aug 18, 2025
c2342ce
Merge branch 'dev' into macandcheese/7180-split-button-tokens
macandcheese Aug 21, 2025
b4a64ad
Merge branch 'dev' into macandcheese/7180-split-button-tokens
macandcheese Aug 22, 2025
c7a7587
feat(split-button): Add component tokens
macandcheese Aug 22, 2025
44f663a
Merge branch 'dev' into macandcheese/7180-split-button-tokens
macandcheese Aug 25, 2025
8c1f80e
Clean up
macandcheese Aug 25, 2025
d714670
Merge branch 'dev' into macandcheese/7180-split-button-tokens
macandcheese Aug 25, 2025
ea220ff
Merge branch 'dev' into macandcheese/7180-split-button-tokens
macandcheese Aug 26, 2025
9efed73
Merge branch 'dev' into macandcheese/7180-split-button-tokens
macandcheese Aug 28, 2025
f8aa018
Merge branch 'dev' into macandcheese/7180-split-button-tokens
macandcheese Sep 2, 2025
ef194a8
Merge branch 'dev' into macandcheese/7180-split-button-tokens
macandcheese Sep 3, 2025
a0ff2be
Merge branch 'dev' into macandcheese/7180-split-button-tokens
macandcheese Sep 5, 2025
2eed52f
Merge branch 'dev' into macandcheese/7180-split-button-tokens
macandcheese Sep 8, 2025
0f09f69
Clean up
macandcheese Sep 8, 2025
9a303b3
Clean up
macandcheese Sep 8, 2025
882eb8d
Clean up
macandcheese Sep 8, 2025
d55ae84
Merge branch 'dev' into macandcheese/7180-split-button-tokens
macandcheese Sep 8, 2025
0d64d7b
Merge branch 'dev' into macandcheese/7180-split-button-tokens
macandcheese Sep 9, 2025
5e2a140
Merge branch 'dev' into macandcheese/7180-split-button-tokens
macandcheese Sep 10, 2025
99d8880
Merge branch 'dev' into macandcheese/7180-split-button-tokens
macandcheese Sep 10, 2025
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
Expand Up @@ -2,9 +2,10 @@
import { newE2EPage } from "@arcgis/lumina-compiler/puppeteerTesting";
import { describe, expect, it } from "vitest";
import { html } from "../../../support/formatting";
import { accessible, defaults, disabled, focusable, hidden, reflects, renders } from "../../tests/commonTests";
import { accessible, defaults, disabled, focusable, hidden, reflects, renders, themed } from "../../tests/commonTests";
import { CSS as DropdownCSS } from "../dropdown/resources";
import { findAll } from "../../tests/utils/puppeteer";
import { CSS } from "./resources";

describe("calcite-split-button", () => {
describe("defaults", () => {
Expand Down Expand Up @@ -327,4 +328,70 @@ describe("calcite-split-button", () => {
expect(await elementAsButton.getProperty("download")).toBe(false);
expect(elementAsButton).not.toHaveAttribute("download");
});

describe("theming", () => {
themed(
html`<calcite-split-button primary-text="Button" loading primary-icon-start="layer">
<calcite-dropdown-group selection-mode="none">
<calcite-dropdown-item>Option 2</calcite-dropdown-item>
<calcite-dropdown-item>Option 3</calcite-dropdown-item>
<calcite-dropdown-item>Option 4</calcite-dropdown-item>
</calcite-dropdown-group>
</calcite-split-button>`,
{
"--calcite-split-button-text-color": [
{
shadowSelector: "calcite-button[split-child='primary']",
targetProp: "--calcite-button-text-color",
},
{
shadowSelector: "calcite-button[split-child='secondary']",
targetProp: "--calcite-button-text-color",
},
],
"--calcite-split-button-icon-color": [
{
shadowSelector: "calcite-button[split-child='primary']",
targetProp: "--calcite-button-icon-color",
},
],
"--calcite-split-button-border-color": [
{
shadowSelector: "calcite-button[split-child='secondary']",
targetProp: "--calcite-button-border-color",
},
{
shadowSelector: "calcite-button[split-child='primary']",
targetProp: "--calcite-button-border-color",
},
],
"--calcite-split-button-shadow": [
{
shadowSelector: "calcite-button[split-child='primary']",
targetProp: "--calcite-button-shadow",
},
{
shadowSelector: "calcite-button[split-child='secondary']",
targetProp: "--calcite-button-shadow",
},
],
"--calcite-split-button-divider-color": {
shadowSelector: `.${CSS.dividerContainer}`,
targetProp: "backgroundColor",
},
"--calcite-split-button-divider-border-color": {
shadowSelector: `.${CSS.divider}`,
targetProp: "backgroundColor",
},
"--calcite-split-button-dropdown-background-color": {
shadowSelector: `calcite-dropdown`,
targetProp: "--calcite-dropdown-background-color",
},
"--calcite-split-button-dropdown-width": {
shadowSelector: `calcite-dropdown`,
targetProp: "--calcite-dropdown-width",
},
},
);
});
});
Original file line number Diff line number Diff line change
@@ -1,3 +1,28 @@
/**
* CSS Custom Properties
*
* These properties can be overridden using the component's tag as selector.
*
* @prop --calcite-split-button-background-color: Specifies the component's background color.
* @prop --calcite-split-button-border-color: Specifies the component's border color.
* @prop --calcite-split-button-corner-radius: Specifies the component's corner radius.
* @prop --calcite-split-button-icon-color: Specifies the component's `iconStart` and/or `iconEnd` color.
* @prop --calcite-split-button-loader-color: Specifies the component's loader color.
* @prop --calcite-split-button-text-color: Specifies the component's text color.
* @prop --calcite-split-button-shadow: Specifies the component's shadow.
* @prop --calcite-split-button-divider-border-color: Specifies the component's divider border color.
* @prop --calcite-split-button-divider-color: Specifies the component's divider color.
* @prop --calcite-split-button-dropdown-width: Specifies the width of the component's dropdown.
* @prop --calcite-split-button-dropdown-background-color: Specifies the component's dropdown background color.
**/

// AUTO-GENERATED — do not modify. Changes will be overwritten.
//
// Internal CSS custom properties for component use only. Overwriting is not recommended.
//
// --calcite-internal-split-button-divider-border-color
// --calcite-internal-split-button-divider-color

:host {
@apply inline-block;
}
Expand All @@ -15,38 +40,38 @@
}

:host([kind="brand"]) {
--calcite-internal-split-button-background: theme("colors.brand");
--calcite-internal-split-button-divider: theme("colors.background.foreground.1");
--calcite-internal-split-button-divider-border-color: var(--calcite-color-brand);
--calcite-internal-split-button-divider-color: var(--calcite-color-foreground-1);
}

:host([kind="danger"]) {
--calcite-internal-split-button-background: theme("colors.danger");
--calcite-internal-split-button-divider: theme("colors.background.foreground.1");
--calcite-internal-split-button-divider-border-color: var(--calcite-color-status-danger);
--calcite-internal-split-button-divider-color: var(--calcite-color-foreground-1);
}

:host([kind="neutral"]) {
--calcite-internal-split-button-background: theme("colors.background.foreground.3");
--calcite-internal-split-button-divider: theme("colors.color.1");
--calcite-internal-split-button-divider-border-color: var(--calcite-color-foreground-3);
--calcite-internal-split-button-divider-color: var(--calcite-color-text-1);
}

:host([kind="inverse"]) {
--calcite-internal-split-button-background: var(--calcite-color-inverse);
--calcite-internal-split-button-divider: theme("colors.background.foreground.1");
--calcite-internal-split-button-divider-border-color: var(--calcite-color-inverse);
--calcite-internal-split-button-divider-color: var(--calcite-color-foreground-1);
}

:host([appearance="transparent"]) {
--calcite-internal-split-button-background: transparent;
--calcite-internal-split-button-divider-border-color: transparent;
&:host([kind="brand"]) {
--calcite-internal-split-button-divider: theme("colors.brand");
--calcite-internal-split-button-divider-color: var(--calcite-color-brand);
}
&:host([kind="danger"]) {
--calcite-internal-split-button-divider: theme("colors.danger");
--calcite-internal-split-button-divider-color: var(--calcite-color-status-danger);
}
&:host([kind="neutral"]) {
--calcite-internal-split-button-divider: theme("colors.color.1");
--calcite-internal-split-button-divider-color: var(--calcite-color-text-1);
}
&:host([kind="inverse"]) {
--calcite-internal-split-button-divider: theme("colors.background.foreground.1");
--calcite-internal-split-button-divider-color: var(--calcite-color-foreground-1);
}
}

Expand All @@ -55,7 +80,7 @@
&:host([kind="danger"]),
&:host([kind="neutral"]),
&:host([kind="inverse"]) {
--calcite-internal-split-button-background: transparent;
--calcite-internal-split-button-divider-border-color: transparent;
}
}

Expand All @@ -64,23 +89,23 @@
&:host([kind="danger"]),
&:host([kind="neutral"]),
&:host([kind="inverse"]) {
--calcite-internal-split-button-background: var(--calcite-color-background);
--calcite-internal-split-button-divider-border-color: var(--calcite-color-background);
}
}

:host([appearance="outline"]),
:host([appearance="outline-fill"]) {
&:host([kind="brand"]) {
--calcite-internal-split-button-divider: theme("colors.brand");
--calcite-internal-split-button-divider-color: var(--calcite-color-brand);
}
&:host([kind="danger"]) {
--calcite-internal-split-button-divider: theme("colors.danger");
--calcite-internal-split-button-divider-color: var(--calcite-color-status-danger);
}
&:host([kind="neutral"]) {
--calcite-internal-split-button-divider: theme("borderColor.color.1");
--calcite-internal-split-button-divider-color: var(--calcite-color-border-1);
}
&:host([kind="inverse"]) {
--calcite-internal-split-button-divider: var(--calcite-color-inverse);
--calcite-internal-split-button-divider-color: var(--calcite-color-inverse);
}
}

Expand All @@ -93,44 +118,76 @@

.divider-container {
@apply transition-default flex w-px items-stretch;
background-color: var(--calcite-internal-split-button-background);
background-color: var(
--calcite-split-button-divider-color,
var(--calcite-internal-split-button-divider-border-color)
);
}

.divider {
@apply my-1 inline-block w-px;
background-color: var(--calcite-internal-split-button-divider);
background-color: var(
--calcite-split-button-divider-border-color,
var(--calcite-internal-split-button-divider-color)
);
}

:host([appearance="outline-fill"]),
:host([appearance="outline"]) {
.divider-container {
border-block: 1px solid var(--calcite-internal-split-button-divider);
border-block: 1px solid var(--calcite-internal-split-button-divider-color);
}
&:hover .divider-container {
background-color: var(--calcite-internal-split-button-divider);
background-color: var(--calcite-internal-split-button-divider-color);
}
}

:host([appearance="outline-fill"]:hover),
:host([appearance="outline"]:hover) {
.divider-container {
background-color: var(--calcite-internal-split-button-divider);
background-color: var(--calcite-internal-split-button-divider-color);
}
}

:host([appearance="outline-fill"]:focus-within),
:host([appearance="outline"]:focus-within) {
&:host([kind="brand"]) {
--calcite-internal-split-button-divider: theme("colors.brand-press");
--calcite-internal-split-button-divider-color: var(--calcite-color-brand-press);
}
&:host([kind="danger"]) {
--calcite-internal-split-button-divider: theme("colors.danger-press");
--calcite-internal-split-button-divider-color: var(--calcite-color-danger-press);
}
.divider-container {
background-color: var(--calcite-internal-split-button-divider);
background-color: var(--calcite-internal-split-button-divider-color);
}
}

calcite-button[split-child="primary"],
calcite-button[split-child="secondary"] {
--calcite-button-background-color: var(--calcite-split-button-background-color);
--calcite-button-border-color: var(--calcite-split-button-border-color);
--calcite-button-text-color: var(--calcite-split-button-text-color);
--calcite-button-icon-color: var(--calcite-split-button-icon-color);
--calcite-button-loading-color: var(--calcite-split-button-loading-color);
--calcite-button-shadow: var(--calcite-split-button-shadow);
}

calcite-button[split-child="primary"] {
--calcite-button-corner-radius: var(--calcite-split-button-corner-radius) var(--calcite-corner-radius-none)
var(--calcite-corner-radius-none) var(--calcite-split-button-corner-radius);
}

calcite-button[split-child="secondary"] {
--calcite-button-corner-radius: var(--calcite-corner-radius-none) var(--calcite-split-button-corner-radius)
var(--calcite-split-button-corner-radius) var(--calcite-corner-radius-none);
}

calcite-dropdown {
--calcite-dropdown-shadow: var(--calcite-split-button-dropdown-shadow);
--calcite-dropdown-background-color: var(--calcite-split-button-dropdown-background-color);
--calcite-dropdown-width: var(--calcite-split-button-dropdown-width);
}

@include disabled() {
calcite-dropdown > calcite-button {
@apply pointer-events-none;
Expand Down
5 changes: 5 additions & 0 deletions packages/calcite-components/src/custom-theme.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ import { carousel, carouselTokens } from "./custom-theme/carousel";
import { dialog, dialogTokens } from "./custom-theme/dialog";
import { swatchGroup, swatchGroupTokens } from "./custom-theme/swatch-group";
import { swatch, swatchTokens } from "./custom-theme/swatch";
import { splitButton, splitButtonTokens } from "./custom-theme/split-button";

const globalTokens = {
calciteColorBrand: "#007ac2",
Expand Down Expand Up @@ -253,6 +254,9 @@ const kitchenSink = (args: Record<string, string>, useTestValues = false) =>
<div class="demo-row">
<div class="demo-column">${swatch}</div>
</div>
<div class="demo-row">
<div class="demo-column">${splitButton}</div>
</div>
</div>`;

const componentTokens = {
Expand Down Expand Up @@ -324,6 +328,7 @@ const componentTokens = {
...dialogTokens,
...swatchGroupTokens,
...swatchTokens,
...splitButtonTokens,
};

export default {
Expand Down
23 changes: 23 additions & 0 deletions packages/calcite-components/src/custom-theme/split-button.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { html } from "../../support/formatting";

export const splitButtonTokens = {
calciteSplitButtonBackgroundColor: "",
calciteSplitButtonBorderColor: "",
calciteSplitButtonCornerRadius: "",
calciteSplitButtonIconColor: "",
calciteSplitButtonLoaderColor: "",
calciteSplitButtonTextColor: "",
calciteSplitButtonShadow: "",
calciteSplitButtonDividerColor: "",
calciteSplitButtonDividerBorderColor: "",
calciteSplitButtonDropdownWidth: "",
calciteSplitButtonDropdownBackgroundColor: "",
};

export const splitButton = html` <calcite-split-button primary-text="Button">
<calcite-dropdown-group selection-mode="none">
<calcite-dropdown-item>Option 2</calcite-dropdown-item>
<calcite-dropdown-item>Option 3</calcite-dropdown-item>
<calcite-dropdown-item>Option 4</calcite-dropdown-item>
</calcite-dropdown-group>
</calcite-split-button>`;
Loading
Loading