From 85561f72d36bdc0ab99da086fd9af5366825a285 Mon Sep 17 00:00:00 2001 From: Jordan Kohl Date: Mon, 14 Jul 2025 13:53:44 -0400 Subject: [PATCH 1/5] fix: makes productIcon optional in ProductSwitcherItem --- .changeset/great-frogs-grin.md | 5 ++ .../__tests__/ProductSwitcher.spec.tsx | 20 ++++- .../src/ProductSwitcherItem.tsx | 6 +- .../ProductSwitcher.customization.stories.tsx | 78 +++++++++++++++++++ 4 files changed, 105 insertions(+), 4 deletions(-) create mode 100644 .changeset/great-frogs-grin.md diff --git a/.changeset/great-frogs-grin.md b/.changeset/great-frogs-grin.md new file mode 100644 index 0000000000..cf249aa1d9 --- /dev/null +++ b/.changeset/great-frogs-grin.md @@ -0,0 +1,5 @@ +--- +"@twilio-paste/product-switcher": patch +--- + +[ProductSwitcherItem] made productIcon optional diff --git a/packages/paste-core/components/product-switcher/__tests__/ProductSwitcher.spec.tsx b/packages/paste-core/components/product-switcher/__tests__/ProductSwitcher.spec.tsx index fd9d2ed8b0..d162ac4208 100644 --- a/packages/paste-core/components/product-switcher/__tests__/ProductSwitcher.spec.tsx +++ b/packages/paste-core/components/product-switcher/__tests__/ProductSwitcher.spec.tsx @@ -1,7 +1,7 @@ import { act, render, screen } from "@testing-library/react"; import * as React from "react"; -import { CustomElementName, DefaultElementName } from "../stories/ProductSwitcher.customization.stories"; +import { CustomElementName, DefaultElementName, WithoutProductIcons } from "../stories/ProductSwitcher.customization.stories"; import { ProductSwitcherMenu } from "../stories/ProductSwitcher.stories"; describe("ProductSwitcher", () => { @@ -64,3 +64,21 @@ describe("ProductSwitcher", () => { }); }); }); +describe("customization of productIcon", () => { + it("should render product icon if set", async () => { + await act(async () => { + render(); + }); + const menuItem = screen.getByRole("menuitemradio", { name: "Twilio SMS, Voice & Video" }); + const imgChildren = Array.from(menuItem.querySelectorAll('[role="img"]')); + expect(imgChildren).toHaveLength(2); + }); + it("should not render product icon if none is set", async () => { + await act(async () => { + render(); + }); + const menuItem = screen.getByRole("menuitemradio", { name: "Twilio SMS, Voice & Video" }); + const imgChildren = Array.from(menuItem.querySelectorAll('[role="img"]')); + expect(imgChildren).toHaveLength(1); + }); +}); diff --git a/packages/paste-core/components/product-switcher/src/ProductSwitcherItem.tsx b/packages/paste-core/components/product-switcher/src/ProductSwitcherItem.tsx index 15db93150f..f31bfacf2e 100644 --- a/packages/paste-core/components/product-switcher/src/ProductSwitcherItem.tsx +++ b/packages/paste-core/components/product-switcher/src/ProductSwitcherItem.tsx @@ -24,10 +24,10 @@ export interface ProductSwitcherItemProps extends Omit} + * @type {React.ReactNode} * @memberof ProductSwitcherItemProps */ - productIcon: NonNullable; + productIcon?: React.ReactNode; /** * Overrides the default element name to apply unique styles with the Customization Provider. * @@ -43,7 +43,7 @@ const ProductSwitcherItem = React.forwardRef - {productIcon} + {productIcon && {productIcon}} {productName} diff --git a/packages/paste-core/components/product-switcher/stories/ProductSwitcher.customization.stories.tsx b/packages/paste-core/components/product-switcher/stories/ProductSwitcher.customization.stories.tsx index e9999d8327..8472ae5876 100644 --- a/packages/paste-core/components/product-switcher/stories/ProductSwitcher.customization.stories.tsx +++ b/packages/paste-core/components/product-switcher/stories/ProductSwitcher.customization.stories.tsx @@ -173,3 +173,81 @@ export const CustomElementName: StoryFn = () => { ); }; + +export const WithoutProductIcons: StoryFn = () => { + const productSwitcher = useProductSwitcherState({ visible: true }); + const [product, setProduct] = React.useState("twilio"); + return ( + + + + { + setProduct("twilio"); + }} + productName="Twilio" + productStrapline="SMS, Voice & Video" + /> + { + setProduct("segment"); + }} + productName="Segment" + productStrapline="Customer data platform" + /> + { + setProduct("flex"); + }} + productName="Flex" + productStrapline="Cloud-based contact center" + /> + { + setProduct("sendgrid"); + }} + productName="SendGrid" + productStrapline="Email delivery and API" + /> + { + setProduct("admin"); + }} + productName="Console Admin" + productStrapline="Admin center" + /> + + + ); +}; From 0322c576ba9d445ad78d9c8fba6539c0846d5a38 Mon Sep 17 00:00:00 2001 From: Jordan Kohl Date: Wed, 16 Jul 2025 13:14:39 -0400 Subject: [PATCH 2/5] fix: removes customizationprovider from story --- .../stories/ProductSwitcher.customization.stories.tsx | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/packages/paste-core/components/product-switcher/stories/ProductSwitcher.customization.stories.tsx b/packages/paste-core/components/product-switcher/stories/ProductSwitcher.customization.stories.tsx index 8472ae5876..cca401aae7 100644 --- a/packages/paste-core/components/product-switcher/stories/ProductSwitcher.customization.stories.tsx +++ b/packages/paste-core/components/product-switcher/stories/ProductSwitcher.customization.stories.tsx @@ -178,13 +178,7 @@ export const WithoutProductIcons: StoryFn = () => { const productSwitcher = useProductSwitcherState({ visible: true }); const [product, setProduct] = React.useState("twilio"); return ( - + <> { productStrapline="Admin center" /> - + ); }; From 8feac50b202d8823a19d61e56a9788ac5f76bbf5 Mon Sep 17 00:00:00 2001 From: Jordan Kohl Date: Wed, 16 Jul 2025 13:15:54 -0400 Subject: [PATCH 3/5] Update .changeset/great-frogs-grin.md Co-authored-by: krisantrobus <55083528+krisantrobus@users.noreply.github.com> --- .changeset/great-frogs-grin.md | 1 + 1 file changed, 1 insertion(+) diff --git a/.changeset/great-frogs-grin.md b/.changeset/great-frogs-grin.md index cf249aa1d9..6ce0ff146a 100644 --- a/.changeset/great-frogs-grin.md +++ b/.changeset/great-frogs-grin.md @@ -1,5 +1,6 @@ --- "@twilio-paste/product-switcher": patch +"@twilio-paste/core": patch --- [ProductSwitcherItem] made productIcon optional From 6f12174474f786dc54ab8598db64ce01af758cd7 Mon Sep 17 00:00:00 2001 From: Kristian Antrobus Date: Thu, 17 Jul 2025 10:04:16 -0500 Subject: [PATCH 4/5] fix(ci): fix failing ci checks --- .../__tests__/ProductSwitcher.spec.tsx | 6 +++++- .../components/product-switcher/type-docs.json | 14 +++++++------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/packages/paste-core/components/product-switcher/__tests__/ProductSwitcher.spec.tsx b/packages/paste-core/components/product-switcher/__tests__/ProductSwitcher.spec.tsx index d162ac4208..f042eb0a29 100644 --- a/packages/paste-core/components/product-switcher/__tests__/ProductSwitcher.spec.tsx +++ b/packages/paste-core/components/product-switcher/__tests__/ProductSwitcher.spec.tsx @@ -1,7 +1,11 @@ import { act, render, screen } from "@testing-library/react"; import * as React from "react"; -import { CustomElementName, DefaultElementName, WithoutProductIcons } from "../stories/ProductSwitcher.customization.stories"; +import { + CustomElementName, + DefaultElementName, + WithoutProductIcons +} from "../stories/ProductSwitcher.customization.stories"; import { ProductSwitcherMenu } from "../stories/ProductSwitcher.stories"; describe("ProductSwitcher", () => { diff --git a/packages/paste-core/components/product-switcher/type-docs.json b/packages/paste-core/components/product-switcher/type-docs.json index 9f92d44f9a..73dc961837 100644 --- a/packages/paste-core/components/product-switcher/type-docs.json +++ b/packages/paste-core/components/product-switcher/type-docs.json @@ -2026,13 +2026,6 @@ "externalProp": true, "description": "Moves focus to the previous item." }, - "productIcon": { - "type": "NonNullable", - "defaultValue": "'PRODUCT_SWITCHER_ITEM'", - "required": true, - "externalProp": false, - "description": "Icon to use for the ProductSwitcherItem. Use a Paste Icon." - }, "productName": { "type": "string", "defaultValue": null, @@ -3883,6 +3876,13 @@ "required": false, "externalProp": true }, + "productIcon": { + "type": "string | number | bigint | boolean | ReactElement> | Iterable | ReactPortal | Promise<...>", + "defaultValue": "'PRODUCT_SWITCHER_ITEM'", + "required": false, + "externalProp": false, + "description": "Icon to use for the ProductSwitcherItem. Use a Paste Icon." + }, "property": { "type": "string", "defaultValue": null, From 8def6056442baca04c7afd2491686ed1b79c949e Mon Sep 17 00:00:00 2001 From: Kristian Antrobus Date: Thu, 17 Jul 2025 10:15:17 -0500 Subject: [PATCH 5/5] fix(ci): fix failing ci checks --- .../product-switcher/__tests__/ProductSwitcher.spec.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/paste-core/components/product-switcher/__tests__/ProductSwitcher.spec.tsx b/packages/paste-core/components/product-switcher/__tests__/ProductSwitcher.spec.tsx index f042eb0a29..66c4e3818e 100644 --- a/packages/paste-core/components/product-switcher/__tests__/ProductSwitcher.spec.tsx +++ b/packages/paste-core/components/product-switcher/__tests__/ProductSwitcher.spec.tsx @@ -4,7 +4,7 @@ import * as React from "react"; import { CustomElementName, DefaultElementName, - WithoutProductIcons + WithoutProductIcons, } from "../stories/ProductSwitcher.customization.stories"; import { ProductSwitcherMenu } from "../stories/ProductSwitcher.stories";