diff --git a/packages/calcite-components/src/components/combobox-item-group/combobox-item-group.scss b/packages/calcite-components/src/components/combobox-item-group/combobox-item-group.scss
index d7f6cc3043c..c17512ec9d2 100644
--- a/packages/calcite-components/src/components/combobox-item-group/combobox-item-group.scss
+++ b/packages/calcite-components/src/components/combobox-item-group/combobox-item-group.scss
@@ -1,3 +1,12 @@
+/**
+ * CSS Custom Properties
+ *
+ * These properties can be overridden using the component's tag as selector.
+ *
+ * @prop --calcite-combobox-item-group-text-color: Specifies the text color of the component.
+ * @prop --calcite-combobox-item-group-border-color: Specifies the border color of the component.
+ */
+
.scale--s {
@apply text-n2h;
--calcite-combobox-item-spacing-unit: theme("spacing.2");
@@ -24,7 +33,7 @@
}
.label {
- @apply text-color-3 box-border flex w-full min-w-0 max-w-full;
+ @apply box-border flex w-full min-w-0 max-w-full;
}
.title {
@@ -32,15 +41,15 @@
var(--calcite-combobox-item-spacing-unit) * var(--calcite-combobox-item-spacing-indent-multiplier)
);
border: 0 solid;
- @apply border-b-color-3
- text-color-2
- word-break
+ @apply word-break
block
flex-1
border-b
font-bold;
padding: var(--calcite-combobox-item-spacing-unit);
margin-inline-start: var(--calcite-combobox-item-indent-value);
+ color: var(--calcite-combobox-item-group-text-color, var(--calcite-color-text-2));
+ border-block-end-color: var(--calcite-combobox-item-group-border-color, var(--calcite-color-border-3));
}
::slotted(calcite-combobox-item-group:not([after-empty-group])) {
diff --git a/packages/calcite-components/src/components/combobox/combobox.e2e.ts b/packages/calcite-components/src/components/combobox/combobox.e2e.ts
index 217aaca1686..075bd7b60e4 100644
--- a/packages/calcite-components/src/components/combobox/combobox.e2e.ts
+++ b/packages/calcite-components/src/components/combobox/combobox.e2e.ts
@@ -22,10 +22,12 @@ import {
createEventTimePropValuesAsserter,
findAll,
getElementXY,
+ isElementFocused,
newProgrammaticE2EPage,
skipAnimations,
} from "../../tests/utils";
import { DEBOUNCE } from "../../utils/resources";
+import { ComponentTestTokens, themed } from "../../tests/commonTests/themed";
import { CSS } from "./resources";
import { Combobox } from "./combobox";
@@ -1869,14 +1871,10 @@ describe("calcite-combobox", () => {
await page.waitForChanges();
await element.press("ArrowLeft");
- expect(chips[0]).not.toHaveClass("chip--active");
- expect(chips[1]).not.toHaveClass("chip--active");
- expect(chips[2]).toHaveClass("chip--active");
+ expect(await isElementFocused(page, `calcite-chip[data-test-id="chip-2"]`, { shadowed: true })).toBe(true);
await element.press("ArrowLeft");
- expect(chips[0]).not.toHaveClass("chip--active");
- expect(chips[1]).toHaveClass("chip--active");
- expect(chips[2]).not.toHaveClass("chip--active");
+ expect(await isElementFocused(page, `calcite-chip[data-test-id="chip-1"]`, { shadowed: true })).toBe(true);
await element.press("Delete");
chips = await findAll(page, "#myCombobox >>> calcite-chip");
@@ -2976,4 +2974,106 @@ describe("calcite-combobox", () => {
const combobox = await page.find("calcite-combobox");
expect((await combobox.getProperty("selectedItems")).length).toBe(1);
});
+
+ describe("theme", () => {
+ describe("default", () => {
+ const comboboxHTML = html`
+
+
+
+
+
+
+
+ `;
+
+ const comboboxTokens: ComponentTestTokens = {
+ "--calcite-combobox-input-height": {
+ shadowSelector: `.${CSS.input}`,
+ selector: "calcite-combobox",
+ targetProp: "height",
+ },
+ "--calcite-combobox-input-background-color": {
+ shadowSelector: `.${CSS.wrapper}`,
+ selector: "calcite-combobox",
+ targetProp: "backgroundColor",
+ },
+ "--calcite-combobox-input-border-color": {
+ shadowSelector: `.${CSS.wrapper}`,
+ selector: "calcite-combobox",
+ targetProp: "borderColor",
+ },
+ "--calcite-combobox-input-text-color": {
+ shadowSelector: `.${CSS.wrapper}`,
+ selector: "calcite-combobox",
+ targetProp: "color",
+ },
+ "--calcite-combobox-icon-color": {
+ shadowSelector: `.${CSS.icon}`,
+ selector: "calcite-combobox",
+ targetProp: "color",
+ },
+ "--calcite-combobox-icon-color-hover": {
+ shadowSelector: `.${CSS.icon}`,
+ selector: "calcite-combobox",
+ targetProp: "color",
+ state: "hover",
+ },
+ "--calcite-combobox-background-color": {
+ shadowSelector: `.${CSS.listContainer}`,
+ selector: "calcite-combobox",
+ targetProp: "backgroundColor",
+ },
+ "--calcite-combobox-item-group-text-color": {
+ selector: "calcite-combobox-item-group",
+ shadowSelector: ".title",
+ targetProp: "color",
+ },
+ "--calcite-combobox-item-group-border-color": {
+ selector: "calcite-combobox-item-group",
+ shadowSelector: ".title",
+ targetProp: "borderBottomColor",
+ },
+ };
+ themed(comboboxHTML, comboboxTokens);
+ });
+
+ describe("placeholder icon", () => {
+ const comboboxWithPlaceHolderIconHTML = html`
+
+
+
+ `;
+
+ const comboboxTokens: ComponentTestTokens = {
+ "--calcite-combobox-icon-color": {
+ shadowSelector: `.${CSS.placeholderIcon}`,
+ selector: "calcite-combobox",
+ targetProp: "color",
+ },
+ };
+ themed(comboboxWithPlaceHolderIconHTML, comboboxTokens);
+ });
+
+ describe("single select", () => {
+ const singleSelectComboboxHTML = html`
+
+
+
+ `;
+
+ const comboboxTokens: ComponentTestTokens = {
+ "--calcite-combobox-input-text-color": {
+ shadowSelector: `.${CSS.wrapper}`,
+ selector: "calcite-combobox",
+ targetProp: "color",
+ },
+ };
+ themed(singleSelectComboboxHTML, comboboxTokens);
+ });
+ });
});
diff --git a/packages/calcite-components/src/components/combobox/combobox.scss b/packages/calcite-components/src/components/combobox/combobox.scss
index c2d6d7697e7..9552747c601 100644
--- a/packages/calcite-components/src/components/combobox/combobox.scss
+++ b/packages/calcite-components/src/components/combobox/combobox.scss
@@ -3,7 +3,13 @@
*
* These properties can be overridden using the component's tag as selector.
*
+ * @prop --calcite-combobox-icon-color: Specifies the component's icon color.
+ * @prop --calcite-combobox-icon-color-hover: Specifies the component's icon color when hovered.
+ * @prop --calcite-combobox-background-color: Specifies the background color of the component's listbox.
+ * @prop --calcite-combobox-input-border-color: Specifies the border color of the component's input.
+ * @prop --calcite-combobox-input-background-color: Specifies the background color of the component's input.
* @prop --calcite-combobox-input-height: Specifies the height of the component's input.
+ * @prop --calcite-combobox-input-text-color: Specifies the text color of the component's input.
*/
:host {
@@ -50,19 +56,17 @@
}
.wrapper {
- @apply bg-foreground-1
- text-color-1
- focus-base
- flex
- border-color-input
- border
- border-solid;
+ @apply focus-base flex border border-solid;
padding-block: calc(var(--calcite-combobox-item-spacing-unit-s) / 4);
padding-inline: var(--calcite-combobox-item-spacing-unit-l);
+ background-color: var(--calcite-combobox-input-background-color, var(--calcite-color-foreground-1));
+ color: var(--calcite-combobox-input-text-color, var(--calcite-color-text-1));
+ border-color: var(--calcite-combobox-input-border-color, var(--calcite-color-border-input));
+
&:hover {
.icon {
- color: var(--calcite-color-text-1);
+ color: var(--calcite-combobox-icon-color-hover, var(--calcite-color-text-1));
}
}
}
@@ -97,13 +101,7 @@
}
.grid-input {
- @apply flex
- flex-grow
- flex-wrap
- items-center
- relative
- truncate
- p-0;
+ @apply flex flex-grow flex-wrap items-center relative truncate p-0;
gap: var(--calcite-combobox-item-spacing-unit-s);
margin-inline-end: var(--calcite-combobox-item-spacing-unit-s);
@@ -115,21 +113,14 @@
}
.input {
- @apply appearance-none
- bg-transparent
- border-none
- flex-grow
- font-inherit
- text-color-1
- text-ellipsis
- overflow-hidden
- p-0;
+ @apply appearance-none bg-transparent border-none flex-grow font-inherit text-color-1 text-ellipsis overflow-hidden p-0;
font-size: inherit;
block-size: var(--calcite-combobox-input-height);
line-height: var(--calcite-combobox-input-height);
inline-size: 100%;
margin-block-end: var(--calcite-combobox-item-spacing-unit-s);
min-inline-size: 4.8125rem;
+
&:focus {
@apply outline-none;
}
@@ -149,10 +140,7 @@
}
.input--hidden {
- @apply pointer-events-none
- w-0
- min-w-0
- opacity-0;
+ @apply pointer-events-none w-0 min-w-0 opacity-0;
}
.input--icon {
@@ -161,7 +149,7 @@
}
.placeholder-icon {
- color: var(--calcite-color-text-3);
+ color: var(--calcite-combobox-icon-color, var(--calcite-color-text-3));
}
.input-wrap {
@@ -173,12 +161,7 @@
}
.label {
- @apply pointer-events-none
- max-w-full
- flex-auto
- truncate
- p-0
- font-normal;
+ @apply pointer-events-none max-w-full flex-auto truncate p-0 font-normal;
block-size: var(--calcite-combobox-input-height);
line-height: var(--calcite-combobox-input-height);
}
@@ -196,7 +179,7 @@
@apply flex-none;
.icon {
- color: var(--calcite-color-text-3);
+ color: var(--calcite-combobox-icon-color, var(--calcite-color-text-3));
}
}
@@ -219,10 +202,9 @@
}
.list-container {
- @apply bg-foreground-1
- max-h-menu
- overflow-y-auto;
+ @apply max-h-menu overflow-y-auto;
inline-size: var(--calcite-dropdown-width, 100%);
+ background-color: var(--calcite-combobox-background-color, var(--calcite-color-foreground-1));
}
.list {
@@ -242,10 +224,6 @@ calcite-chip {
max-inline-size: 100%;
}
-.chip--active {
- @apply bg-foreground-3;
-}
-
.chip--invisible {
@apply absolute invisible;
}
diff --git a/packages/calcite-components/src/components/combobox/combobox.tsx b/packages/calcite-components/src/components/combobox/combobox.tsx
index 018aafa68fd..c51d8481561 100644
--- a/packages/calcite-components/src/components/combobox/combobox.tsx
+++ b/packages/calcite-components/src/components/combobox/combobox.tsx
@@ -1418,8 +1418,7 @@ export class Combobox
const { activeChipIndex, readOnly, scale, selectionMode, messages } = this;
return this.selectedItems.map((item, i) => {
const chipClasses = {
- chip: true,
- "chip--active": activeChipIndex === i,
+ [CSS.chip]: true,
};
const ancestors = [...getItemAncestors(item)].reverse();
const itemLabel = getLabel(item);
@@ -1739,9 +1738,9 @@ export class Combobox
, useTestValues = false) =>
${actionMenu}
${icon}
- ${inlineEditable} ${input} ${inputNumber} ${inputText} ${select}
+ ${inlineEditable} ${input} ${inputNumber} ${inputText} ${select} ${singleSelectCombobox}
+ ${comboboxWithPlaceHolderIcon} ${defaultCombobox}
${card}
@@ -176,6 +183,7 @@ const componentTokens = {
...cardTokens,
...checkboxTokens,
...chipTokens,
+ ...comboboxTokens,
...datePickerTokens,
...DropdownTokens,
...DropdownItemTokens,
diff --git a/packages/calcite-components/src/custom-theme/combobox.ts b/packages/calcite-components/src/custom-theme/combobox.ts
new file mode 100644
index 00000000000..4a1241dc696
--- /dev/null
+++ b/packages/calcite-components/src/custom-theme/combobox.ts
@@ -0,0 +1,40 @@
+import { html } from "../../support/formatting";
+
+export const comboboxTokens = {
+ calciteComboboxInputHeight: "",
+ calciteComboboxInputBackgroundColor: "",
+ calciteComboboxInputTextColor: "",
+ calciteComboboxInputBorderColor: "",
+ calciteComboboxIconColor: "",
+ calciteComboboxIconColorHover: "",
+ calciteComboboxBackgroundColor: "",
+ calciteChipBackgroundColor: "",
+ calciteChipTextColor: "",
+ calciteChipIconColor: "",
+ calciteChipCloseIconColor: "",
+ calciteChipCornerRadius: "",
+ calciteComboboxItemGroupTextColor: "",
+ calciteComboboxItemGroupBorderColor: "",
+};
+
+export const defaultCombobox = html`
+
+
+
+
+
+
+
+`;
+
+export const singleSelectCombobox = html`
+
+
+
+`;
+
+export const comboboxWithPlaceHolderIcon = html`
+
+
+
+`;
diff --git a/packages/calcite-components/src/demos/combobox.html b/packages/calcite-components/src/demos/combobox.html
index fe4d2285987..029106669ec 100644
--- a/packages/calcite-components/src/demos/combobox.html
+++ b/packages/calcite-components/src/demos/combobox.html
@@ -1164,6 +1164,47 @@
Validation message
+
+
+
Theme
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+