diff --git a/packages/calcite-components/.stylelintrc.cjs b/packages/calcite-components/.stylelintrc.cjs index 2e02214db54..0998dad6911 100644 --- a/packages/calcite-components/.stylelintrc.cjs +++ b/packages/calcite-components/.stylelintrc.cjs @@ -1,13 +1,7 @@ // @ts-check // ⚠️ AUTO-GENERATED CODE - DO NOT EDIT -const customFunctions = [ - "get-trailing-text-input-padding", - "medium-modular-scale", - "modular-scale", - "scale-duration", - "small-modular-scale" -]; +const customFunctions = []; // ⚠️ END OF AUTO-GENERATED CODE const scssPatternRules = [ diff --git a/packages/calcite-components/src/assets/styles/includes.scss b/packages/calcite-components/src/assets/styles/includes.scss index 5470d9ebfba..5235536f57b 100644 --- a/packages/calcite-components/src/assets/styles/includes.scss +++ b/packages/calcite-components/src/assets/styles/includes.scss @@ -153,7 +153,11 @@ } } -@mixin close-button($size: "var(--calcite-internal-close-size, 1.5rem /* 24px */)", $padding: "0") { +@mixin close-button( + $size: "var(--calcite-internal-close-size, 1.5rem /* 24px */)", + $padding: "0", + $color: "var(--calcite-close-icon-color, var(--calcite-color-text-1))" +) { .close { @apply border-none cursor-pointer @@ -168,7 +172,7 @@ display: flex; align-content: center; justify-content: center; - color: var(--calcite-close-icon-color, var(--calcite-color-text-1)); + color: #{$color}; block-size: #{$size}; inline-size: #{$size}; padding: #{$padding}; diff --git a/packages/calcite-components/src/components/accordion-item/accordion-item.scss b/packages/calcite-components/src/components/accordion-item/accordion-item.scss index 1575cd8bac9..1a22c750ce9 100644 --- a/packages/calcite-components/src/components/accordion-item/accordion-item.scss +++ b/packages/calcite-components/src/components/accordion-item/accordion-item.scss @@ -3,7 +3,7 @@ * * These properties can be overridden using the component's tag as selector. * - * @prop --calcite-accordion-border-color: [Deprecate] Use `--calcite-accordion-item-border-color`. Specifies the component's border color. + * @prop --calcite-accordion-border-color: [Deprecated] Use `--calcite-accordion-item-border-color`. Specifies the component's border color. * @prop --calcite-accordion-item-background-color: Specifies the component's background color. * @prop --calcite-accordion-item-border-color: Specifies the component's border color. * @prop --calcite-accordion-item-content-space: Specifies the component's padding. diff --git a/packages/calcite-components/src/components/chip/chip.scss b/packages/calcite-components/src/components/chip/chip.scss index e1ca4d68f02..302b9277ec2 100644 --- a/packages/calcite-components/src/components/chip/chip.scss +++ b/packages/calcite-components/src/components/chip/chip.scss @@ -28,6 +28,7 @@ :host([appearance="outline"]), :host([appearance="outline-fill"]) { .container { + --calcite-internal-chip-close-icon-color: var(--calcite-color-text-3); color: var(--calcite-chip-text-color, var(--calcite-color-text-1)); } @@ -42,10 +43,6 @@ &:host([kind="neutral"]) .container { border-color: var(--calcite-chip-border-color, var(--calcite-color-border-1)); } - - .close { - color: var(--calcite-chip-close-icon-color, var(--calcite-close-icon-color, var(--calcite-color-text-3))); - } } :host([appearance="outline"]) .container { @apply bg-transparent; @@ -86,11 +83,9 @@ } } :host([kind="neutral"]) .container { - color: var(--calcite-chip-text-color, var(--calcite-color-text-1)); + --calcite-internal-chip-close-icon-color: var(--calcite-color-text-3); - .close { - color: var(--calcite-chip-close-icon-color, var(--calcite-close-icon-color, var(--calcite-color-text-3))); - } + color: var(--calcite-chip-text-color, var(--calcite-color-text-1)); } :host([selected]) .select-icon { @@ -391,14 +386,17 @@ inline-size: var(--calcite-internal-chip-icon-size, 1.5rem /* 24px */); } -.close { - color: var(--calcite-chip-close-icon-color, var(--calcite-close-icon-color, currentColor)); -} - slot[name="image"]::slotted(*) { @apply rounded-half flex h-full w-full overflow-hidden; } -@include close-button(); +@include close-button( + var(--calcite-internal-close-size, 1.5rem), + 0, + var( + --calcite-chip-close-icon-color, + var(--calcite-close-icon-color, var(--calcite-internal-chip-close-icon-color, var(--calcite-color-text-1))) + ) +); @include disabled(); @include base-component(); diff --git a/packages/calcite-components/src/components/combobox/combobox.e2e.ts b/packages/calcite-components/src/components/combobox/combobox.e2e.ts index df30e2bd620..9a3caaec1fc 100644 --- a/packages/calcite-components/src/components/combobox/combobox.e2e.ts +++ b/packages/calcite-components/src/components/combobox/combobox.e2e.ts @@ -533,6 +533,49 @@ describe("calcite-combobox", () => { expect(visibleItems.length).toBe(1); expect(await visibleItems[0].getProperty("value")).toBe("1"); }); + + it("should restore filter text when no items are filtered", async () => { + const page = await newE2EPage(); + await page.setContent(html` + + + + + + `); + + const combobox = await page.find("calcite-combobox"); + const input = await page.find("calcite-combobox >>> input"); + await combobox.click(); + await page.waitForChanges(); + await combobox.type("an"); + await page.waitForChanges(); + await new Promise((res) => setTimeout(() => res(true), DEBOUNCE.filter)); + const one = await page.find("#one"); + const two = await page.find("#two"); + const three = await page.find("#three"); + + expect(await one.isVisible()).toBeFalsy(); + expect(await two.isVisible()).toBeFalsy(); + expect(await three.isVisible()).toBeTruthy(); + + await combobox.type("m"); + await new Promise((res) => setTimeout(() => res(true), DEBOUNCE.filter)); + await page.waitForChanges(); + expect(await one.isVisible()).toBeFalsy(); + expect(await two.isVisible()).toBeFalsy(); + expect(await three.isVisible()).toBeFalsy(); + + expect(await combobox.getProperty("value")).toBe("Natural Resources"); + expect((await combobox.getProperty("filteredItems")).length).toBe(0); + expect(await input.getProperty("value")).toBe("anm"); + expect(input).not.toHaveClass(`${CSS.inputHidden}`); + }); }); it("should control max items displayed", async () => { diff --git a/packages/calcite-components/src/components/combobox/combobox.tsx b/packages/calcite-components/src/components/combobox/combobox.tsx index 5d585c20731..41b3e4c4918 100644 --- a/packages/calcite-components/src/components/combobox/combobox.tsx +++ b/packages/calcite-components/src/components/combobox/combobox.tsx @@ -1600,7 +1600,7 @@ export class Combobox const { guid, disabled, placeholder, selectionMode, selectedItems, open } = this; const single = isSingleLike(selectionMode); const selectedItem = selectedItems[0]; - const showLabel = !open && single && !!selectedItem; + const showLabel = !open && single && !!selectedItem && !this.filterText; return ( { expect(await alert.getProperty("embedded")).toBe(true); }); + it("should not set transform when not dragEnabled or resizable", async () => { + const page = await newE2EPage(); + await page.setContent(html` test `); + await skipAnimations(page); + await page.setViewport({ width: 1200, height: 1200 }); + await page.waitForChanges(); + + const container = await page.find(`calcite-dialog >>> .${CSS.dialog}`); + expect((await container.getComputedStyle()).transform).toBe("none"); + }); + describe("keyboard movement", () => { it("should move properly via arrow keys", async () => { const page = await newE2EPage(); @@ -931,19 +942,19 @@ describe("calcite-dialog", () => { await page.setViewport({ width: 1200, height: 1200 }); await page.waitForChanges(); const container = await page.find(`calcite-dialog >>> .${CSS.dialog}`); - expect((await container.getComputedStyle()).transform).toBe("matrix(1, 0, 0, 1, 0, 0)"); + expect((await container.getComputedStyle()).transform).toBe("none"); await dispatchDialogKeydown({ page, key: "ArrowDown", shiftKey: false }); expect((await container.getComputedStyle()).transform).toBe(`matrix(1, 0, 0, 1, 0, ${dialogDragStep})`); await dispatchDialogKeydown({ page, key: "ArrowUp", shiftKey: false }); - expect((await container.getComputedStyle()).transform).toBe("matrix(1, 0, 0, 1, 0, 0)"); + expect((await container.getComputedStyle()).transform).toBe("none"); await dispatchDialogKeydown({ page, key: "ArrowLeft", shiftKey: false }); expect((await container.getComputedStyle()).transform).toBe(`matrix(1, 0, 0, 1, -${dialogDragStep}, 0)`); await dispatchDialogKeydown({ page, key: "ArrowRight", shiftKey: false }); - expect((await container.getComputedStyle()).transform).toBe("matrix(1, 0, 0, 1, 0, 0)"); + expect((await container.getComputedStyle()).transform).toBe("none"); }); }); diff --git a/packages/calcite-components/src/components/dialog/dialog.stories.ts b/packages/calcite-components/src/components/dialog/dialog.stories.ts index 9a0ba8d918d..77cb5bef9a2 100644 --- a/packages/calcite-components/src/components/dialog/dialog.stories.ts +++ b/packages/calcite-components/src/components/dialog/dialog.stories.ts @@ -376,8 +376,16 @@ const themedStyle = html`--calcite-dialog-scrim-background-color: purple; --calc --calcite-dialog-content-space: 50px; --calcite-dialog-offset-x: 50px; --calcite-dialog-offset-y: -30px;`; export const withShellInside = (): string => - html` - + html` + diff --git a/packages/calcite-components/src/components/dialog/dialog.tsx b/packages/calcite-components/src/components/dialog/dialog.tsx index 71f7e4c388c..1b028b15814 100644 --- a/packages/calcite-components/src/components/dialog/dialog.tsx +++ b/packages/calcite-components/src/components/dialog/dialog.tsx @@ -605,18 +605,26 @@ export class Dialog dragPosition: { x, y }, resizePosition, transitionEl, + dragEnabled, + resizable, } = this; if (!transitionEl) { return; } + if (!dragEnabled && !resizable) { + transitionEl.style.transform = null; + return; + } + const { top, right, bottom, left } = this.getAdjustedResizePosition(resizePosition); const translateX = Math.round(x + left + right); const translateY = Math.round(y + top + bottom); - transitionEl.style.transform = `translate(${translateX}px, ${translateY}px)`; + transitionEl.style.transform = + translateX || translateY ? `translate(${translateX}px, ${translateY}px)` : null; } private updateSize({ diff --git a/packages/calcite-components/src/components/notice/notice.e2e.ts b/packages/calcite-components/src/components/notice/notice.e2e.ts index 5e63c1ef2e8..4965aafa08c 100644 --- a/packages/calcite-components/src/components/notice/notice.e2e.ts +++ b/packages/calcite-components/src/components/notice/notice.e2e.ts @@ -36,7 +36,9 @@ describe("calcite-notice", () => { }); describe("openClose", () => { - openClose("calcite-notice"); + openClose("calcite-notice", { + collapsedOnClose: "vertical", + }); }); describe("slots", () => { diff --git a/packages/calcite-components/src/components/notice/notice.scss b/packages/calcite-components/src/components/notice/notice.scss index 8d55050d3f5..6343992b784 100644 --- a/packages/calcite-components/src/components/notice/notice.scss +++ b/packages/calcite-components/src/components/notice/notice.scss @@ -78,6 +78,7 @@ flex w-full opacity-0; + overflow: hidden; max-block-size: 0; transition-property: opacity, max-block-size; transition-duration: var(--calcite-animation-timing); @@ -104,6 +105,7 @@ max-h-full items-center opacity-100; + overflow: visible; } @include slotted("title", "*", ".container") { diff --git a/packages/calcite-components/src/components/panel/panel.scss b/packages/calcite-components/src/components/panel/panel.scss index 4d40f90da8c..29b7cf7c45f 100644 --- a/packages/calcite-components/src/components/panel/panel.scss +++ b/packages/calcite-components/src/components/panel/panel.scss @@ -164,8 +164,7 @@ items-stretch overflow-auto h-full - focus-base - relative; + focus-base; padding: var(--calcite-panel-content-space, 0); background: var(--calcite-panel-background-color, var(--calcite-color-background)); } diff --git a/packages/calcite-components/src/components/shell-center-row/shell-center-row.tsx b/packages/calcite-components/src/components/shell-center-row/shell-center-row.tsx index 6c526f8ea27..dc124273512 100644 --- a/packages/calcite-components/src/components/shell-center-row/shell-center-row.tsx +++ b/packages/calcite-components/src/components/shell-center-row/shell-center-row.tsx @@ -6,9 +6,17 @@ import { } from "../../utils/conditionalSlot"; import { getSlotted } from "../../utils/dom"; import { Position, Scale } from "../interfaces"; +import { logger } from "../../utils/logger"; import { CSS, SLOTS } from "./resources"; +logger.deprecated("component", { + name: "shell-center-row", + removalVersion: 4, + suggested: "shell-panel", +}); + /** + * @deprecated Use the `calcite-shell-panel` component instead. * @slot - A slot for adding content to the `calcite-shell-panel`. * @slot action-bar - A slot for adding a `calcite-action-bar` to the `calcite-shell-panel`. */ diff --git a/packages/calcite-components/src/tests/commonTests/openClose.ts b/packages/calcite-components/src/tests/commonTests/openClose.ts index 566e7cfda23..edba09338c1 100644 --- a/packages/calcite-components/src/tests/commonTests/openClose.ts +++ b/packages/calcite-components/src/tests/commonTests/openClose.ts @@ -1,12 +1,19 @@ import { E2EPage } from "@stencil/core/testing"; import { toHaveNoViolations } from "jest-axe"; -import { GlobalTestProps, newProgrammaticE2EPage } from "../utils"; +import { GlobalTestProps, newProgrammaticE2EPage, toElementHandle } from "../utils"; import { getBeforeContent, getTagAndPage, noopBeforeContent } from "./utils"; import { ComponentTag, ComponentTestSetup, WithBeforeContent } from "./interfaces"; expect.extend(toHaveNoViolations); +type CollapseAxis = "horizontal" | "vertical"; + interface OpenCloseOptions { + /** + * When specified, testing will assert that the component is collapsed (does not affect layout) along the specified axis when closed. + */ + collapsedOnClose?: CollapseAxis; + /** * Toggle property to test. Currently, either "open" or "expanded". */ @@ -54,10 +61,11 @@ export function openClose(componentTestSetup: ComponentTestSetup, options?: Open await setUpEventListeners(tag, page); await testOpenCloseEvents({ - tag, - page, - openPropName: effectiveOptions.openPropName, animationsEnabled: !effectiveOptions.willUseFallback, + collapsedOnClose: effectiveOptions.collapsedOnClose, + openPropName: effectiveOptions.openPropName, + page, + tag, }); }); @@ -69,6 +77,7 @@ export function openClose(componentTestSetup: ComponentTestSetup, options?: Open await setUpEventListeners(tag, page); await testOpenCloseEvents({ animationsEnabled: false, + collapsedOnClose: effectiveOptions.collapsedOnClose, openPropName: effectiveOptions.openPropName, page, tag, @@ -149,6 +158,11 @@ interface TestOpenCloseEventsParams { */ startOpen?: boolean; + /** + * Whether the component should be collapsed (does not affect layout) along the specified axis when closed. + */ + collapsedOnClose?: CollapseAxis; + /** * Whether animations are enabled. */ @@ -159,6 +173,7 @@ async function testOpenCloseEvents({ animationsEnabled, openPropName, page, + collapsedOnClose, startOpen = false, tag, }: TestOpenCloseEventsParams): Promise { @@ -222,6 +237,17 @@ async function testOpenCloseEvents({ assertEventSequence([1, 1, 1, 1]); + if (collapsedOnClose !== undefined) { + const elementHandle = await toElementHandle(element); + const boundingBox = await elementHandle.boundingBox(); + const horizontalCollapse = collapsedOnClose === "horizontal"; + const dimension = horizontalCollapse ? "width" : "height"; + const scrollDimension = horizontalCollapse ? "scrollWidth" : "scrollHeight"; + + expect(boundingBox[dimension]).toBe(0); + expect(await elementHandle.evaluate((el, scrollDimension) => el[scrollDimension], scrollDimension)).toBe(0); + } + expect(await page.evaluate(() => (window as EventOrderWindow).events)).toEqual(eventSequence); const delayDeltaThreshold = 100; // smallest internal animation timing used diff --git a/packages/calcite-components/src/tests/commonTests/themed.ts b/packages/calcite-components/src/tests/commonTests/themed.ts index 5667ec25a84..d99ebcdbd9b 100644 --- a/packages/calcite-components/src/tests/commonTests/themed.ts +++ b/packages/calcite-components/src/tests/commonTests/themed.ts @@ -1,8 +1,8 @@ import { E2EElement, E2EPage } from "@stencil/core/testing"; import { toHaveNoViolations } from "jest-axe"; -import { ElementHandle } from "puppeteer"; import type { RequireExactlyOne } from "type-fest"; import { getTokenValue } from "../utils/cssTokenValues"; +import { toElementHandle } from "../utils"; import type { ComponentTestSetup } from "./interfaces"; import { getTagAndPage } from "./utils"; @@ -266,11 +266,9 @@ async function getComputedStylePropertyValue( property: string, pseudoElement?: string, ): Promise { - type E2EElementInternal = E2EElement & { - _elmHandle: ElementHandle; - }; + const elementHandle = await toElementHandle(element); - return await (element as E2EElementInternal)._elmHandle.evaluate( + return await elementHandle.evaluate( (el, targetProp, pseudoElement): string => window.getComputedStyle(el, pseudoElement).getPropertyValue(targetProp), property, pseudoElement, diff --git a/packages/calcite-components/src/tests/utils.ts b/packages/calcite-components/src/tests/utils.ts index e0de51cb882..c64fff61c50 100644 --- a/packages/calcite-components/src/tests/utils.ts +++ b/packages/calcite-components/src/tests/utils.ts @@ -1,5 +1,5 @@ import { E2EElement, E2EPage, newE2EPage } from "@stencil/core/testing"; -import { BoundingBox } from "puppeteer"; +import { BoundingBox, ElementHandle } from "puppeteer"; import type { JSX } from "../components"; import { ComponentTag } from "./commonTests/interfaces"; @@ -527,3 +527,17 @@ export async function assertCaretPosition({ ), ).toBeTruthy(); } + +/** + * This utils helps to get the element handle from an E2EElement. + * + * @param element - the E2E element + * @returns {Promise} - the element handle + */ +export async function toElementHandle(element: E2EElement): Promise { + type E2EElementInternal = E2EElement & { + _elmHandle: ElementHandle; + }; + + return (element as E2EElementInternal)._elmHandle; +}