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

+
+ + + + + + + + + + + +
+
+ + + + + + + +
+