From c220a727c5a75653d3c811bb7a6258e243613edf Mon Sep 17 00:00:00 2001 From: Eugene Date: Fri, 26 Dec 2025 17:37:18 +0000 Subject: [PATCH 01/10] CSS Modules: migrate bundle package --- .../adaptiveCard/withTapAction.html | 2 +- __tests__/html2/adaptiveCard/rerender.html | 2 +- __tests__/html2/adaptiveCard/tapAction.html | 2 +- package-lock.json | 1 + packages/bundle/package.json | 2 + packages/bundle/src/AddFullBundle.tsx | 6 +- .../AdaptiveCardRenderer.module.css | 83 +++++++++++++++++++ .../Attachment/AdaptiveCardRenderer.tsx | 10 ++- .../AnimationCardContent.module.css | 10 +++ .../Attachment/AnimationCardContent.tsx | 8 +- .../Attachment/AudioCardContent.module.css | 10 +++ .../Attachment/AudioCardContent.tsx | 8 +- .../Attachment/SignInCardContent.module.css | 10 +++ .../Attachment/SignInCardContent.tsx | 8 +- .../Attachment/VideoCardContent.module.css | 10 +++ .../Attachment/VideoCardContent.tsx | 8 +- packages/bundle/src/env.d.ts | 2 + .../src/stylesheet/BundleStylesheet.tsx | 33 ++++++++ .../stylesheet/createBundleStyleElements.ts | 8 ++ packages/bundle/tsup.config.ts | 8 +- 20 files changed, 210 insertions(+), 21 deletions(-) create mode 100644 packages/bundle/src/adaptiveCards/Attachment/AdaptiveCardRenderer.module.css create mode 100644 packages/bundle/src/adaptiveCards/Attachment/AnimationCardContent.module.css create mode 100644 packages/bundle/src/adaptiveCards/Attachment/AudioCardContent.module.css create mode 100644 packages/bundle/src/adaptiveCards/Attachment/SignInCardContent.module.css create mode 100644 packages/bundle/src/adaptiveCards/Attachment/VideoCardContent.module.css create mode 100644 packages/bundle/src/stylesheet/BundleStylesheet.tsx create mode 100644 packages/bundle/src/stylesheet/createBundleStyleElements.ts diff --git a/__tests__/html2/accessibility/adaptiveCard/withTapAction.html b/__tests__/html2/accessibility/adaptiveCard/withTapAction.html index 40a434edb1..c87ebcf45e 100644 --- a/__tests__/html2/accessibility/adaptiveCard/withTapAction.html +++ b/__tests__/html2/accessibility/adaptiveCard/withTapAction.html @@ -30,7 +30,7 @@ await host.sendShiftTab(); const focusingOnRoot = - document.activeElement === document.querySelector('.webchat__adaptive-card-renderer').firstChild; + document.activeElement === document.querySelector('.adaptive-card-renderer').firstChild; expect(focusingOnRoot).toBe(true); diff --git a/__tests__/html2/adaptiveCard/rerender.html b/__tests__/html2/adaptiveCard/rerender.html index fb4725bd0a..aad3c3dfd7 100644 --- a/__tests__/html2/adaptiveCard/rerender.html +++ b/__tests__/html2/adaptiveCard/rerender.html @@ -66,7 +66,7 @@ ] }); - const adaptiveCardEl = document.querySelector('.webchat__adaptive-card-renderer'); + const adaptiveCardEl = document.querySelector('.adaptive-card-renderer'); const [currentRenderedChild] = adaptiveCardEl.children; await new Promise(resolve => setTimeout(resolve, 200)); diff --git a/__tests__/html2/adaptiveCard/tapAction.html b/__tests__/html2/adaptiveCard/tapAction.html index bcc5faaaaf..9464cb680b 100644 --- a/__tests__/html2/adaptiveCard/tapAction.html +++ b/__tests__/html2/adaptiveCard/tapAction.html @@ -51,7 +51,7 @@ // When using runHookActivityMiddleware, an additional hidden activities will be rendered to run the hook function. Thus, minNumActivitiesShown must be +1. await pageConditions.numActivitiesShown(1); - const renderer = document.querySelector('.webchat__adaptive-card-renderer'); + const renderer = document.querySelector('.adaptive-card-renderer'); const card = renderer.querySelector('.ac-adaptiveCard[tabindex="0"]'); expect(card).toBeTruthy(); diff --git a/package-lock.json b/package-lock.json index 3828630abe..79bc497832 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20437,6 +20437,7 @@ "@msinternal/botframework-directlinejs": "0.0.0-0", "@msinternal/botframework-webchat-base": "0.0.0-0", "@msinternal/botframework-webchat-react-valibot": "0.0.0-0", + "@msinternal/botframework-webchat-styles": "0.0.0-0", "@msinternal/botframework-webchat-tsconfig": "0.0.0-0", "@msinternal/isomorphic-react": "0.0.0-0", "@msinternal/isomorphic-react-dom": "0.0.0-0", diff --git a/packages/bundle/package.json b/packages/bundle/package.json index fbf59a407b..6078d224d9 100644 --- a/packages/bundle/package.json +++ b/packages/bundle/package.json @@ -161,6 +161,7 @@ "@msinternal/botframework-directlinejs": "development", "@msinternal/botframework-webchat-base": "development", "@msinternal/botframework-webchat-react-valibot": "development", + "@msinternal/botframework-webchat-styles": "development", "@msinternal/botframework-webchat-tsconfig": "development", "@msinternal/isomorphic-react": "development", "@msinternal/isomorphic-react-dom": "development", @@ -188,6 +189,7 @@ "@msinternal/botframework-directlinejs": "0.0.0-0", "@msinternal/botframework-webchat-base": "0.0.0-0", "@msinternal/botframework-webchat-react-valibot": "0.0.0-0", + "@msinternal/botframework-webchat-styles": "0.0.0-0", "@msinternal/botframework-webchat-tsconfig": "0.0.0-0", "@msinternal/isomorphic-react": "0.0.0-0", "@msinternal/isomorphic-react-dom": "0.0.0-0", diff --git a/packages/bundle/src/AddFullBundle.tsx b/packages/bundle/src/AddFullBundle.tsx index c729191519..94042db8b4 100644 --- a/packages/bundle/src/AddFullBundle.tsx +++ b/packages/bundle/src/AddFullBundle.tsx @@ -14,6 +14,7 @@ import ShikiComposer from './codeHighlighter/ShikiComposer'; import { type AdaptiveCardsPackage } from './types/AdaptiveCardsPackage'; import { type StrictFullBundleStyleOptions } from './types/FullBundleStyleOptions'; import useComposerProps from './useComposerProps'; +import BundleStylesheet from './stylesheet/BundleStylesheet'; type AddFullBundleChildren = ({ extraStyleSet }: { extraStyleSet: any }) => ReactNode; @@ -31,6 +32,7 @@ type AddFullBundleProps = Readonly<{ ) => string; styleOptions?: StyleOptions & AdaptiveCardsStyleOptions; styleSet?: any & { options: StrictFullBundleStyleOptions }; + nonce: string | undefined; /** @deprecated Rename to "adaptiveCardsHostConfig" */ adaptiveCardHostConfig?: any; @@ -50,7 +52,8 @@ function AddFullBundle({ htmlContentTransformMiddleware, renderMarkdown, styleOptions, - styleSet + styleSet, + nonce }: AddFullBundleProps) { adaptiveCardHostConfig && adaptiveCardHostConfigDeprecation(); @@ -69,6 +72,7 @@ function AddFullBundle({ adaptiveCardsHostConfig={adaptiveCardHostConfig || adaptiveCardsHostConfig} adaptiveCardsPackage={adaptiveCardsPackage} > + {children(patchedProps)} diff --git a/packages/bundle/src/adaptiveCards/Attachment/AdaptiveCardRenderer.module.css b/packages/bundle/src/adaptiveCards/Attachment/AdaptiveCardRenderer.module.css new file mode 100644 index 0000000000..d430fc6ab5 --- /dev/null +++ b/packages/bundle/src/adaptiveCards/Attachment/AdaptiveCardRenderer.module.css @@ -0,0 +1,83 @@ +:global(.webchat) .adaptive-card-renderer { + /* Related to #4075. */ + /* Adaptive Cards assume its host is in "forced border-box" mode. */ + /* In CSS, the default is "content-box" mode. */ + /* https://developer.mozilla.org/en-US/docs/Web/CSS/box-sizing#values */ + * { + box-sizing: border-box; + } + + :global(.ac-input), + :global(.ac-inlineActionButton), + :global(.ac-quickActionButton) { + font-family: var(--webchat__font--primary); + } + + :global(.ac-multichoiceInput) { + padding: var(--webchat__padding--regular); + } + + :global(.ac-pushButton) { + appearance: none; + background-color: white; + border-style: solid; + border-width: 1px; + color: var(--webchat__color--accent); + font-weight: 600; + padding: var(--webchat__padding--regular); + } + + :global(.ac-pushButton.style-destructive) { + background-color: #e50000; + color: white; + } + + :global(.ac-pushButton.style-destructive:hover), + :global(.ac-pushButton.style-destructive:active) { + background-color: #bf0000; + } + + :global(.ac-pushButton.style-positive) { + background-color: #0078d7; + color: white; + } + + :global(.ac-pushButton.style-positive:hover), + :global(.ac-pushButton.style-positive:active) { + background-color: #006abc; + } + + /* The following styles are copied from :disabled via Chromium. */ + :global(.ac-pushButton[aria-disabled='true']), + input[aria-disabled='true'], + select[aria-disabled='true'], + textarea[aria-disabled='true'] { + background-color: rgba(239, 239, 239, 0.3); + border-color: rgba(118, 118, 118, 0.3); + border-style: solid; + border-width: 1px; + color: #545454; + } + + :global(.ac-pushButton[aria-disabled='true']) { + background-color: #eee; + color: #4f4f4f; + } + + :global(.ac-pushButton[aria-pressed='true']) { + background-color: var(--webchat__background--card-push-button, #0063b1); + border-color: var(--webchat__background--card-push-button, #0063b1); + color: var(--webchat__color--card-push-button-text, white); + + @media (forced-colors: active) { + background-color: Highlight; + border-color: Highlight; + color: HighlightText; + forced-color-adjust: none; + } + } + + input[aria-disabled='true'] { + padding: 2px 1px; + } +} diff --git a/packages/bundle/src/adaptiveCards/Attachment/AdaptiveCardRenderer.tsx b/packages/bundle/src/adaptiveCards/Attachment/AdaptiveCardRenderer.tsx index e8dbf5543f..091b1a3480 100644 --- a/packages/bundle/src/adaptiveCards/Attachment/AdaptiveCardRenderer.tsx +++ b/packages/bundle/src/adaptiveCards/Attachment/AdaptiveCardRenderer.tsx @@ -1,11 +1,12 @@ /* eslint no-magic-numbers: ["error", { "ignore": [-1, 0, 2] }] */ import { validateProps } from '@msinternal/botframework-webchat-react-valibot'; +import { useStyles } from '@msinternal/botframework-webchat-styles/react'; import { type Action as AdaptiveCardAction, type OpenUrlAction, type SubmitAction } from 'adaptivecards'; import { ErrorBoxPolymiddlewareProxy } from 'botframework-webchat-api/middleware'; import { getTabIndex, hooks } from 'botframework-webchat-component'; import { type DirectLineCardAction } from 'botframework-webchat-core'; -import classNames from 'classnames'; +import cx from 'classnames'; import React, { memo, useCallback, @@ -19,7 +20,6 @@ import React, { import { useRefFrom } from 'use-ref-from'; import { any, boolean, object, optional, pipe, readonly, string, type InferInput } from 'valibot'; -import useStyleSet from '../../hooks/useStyleSet'; import useAdaptiveCardsHostConfig from '../hooks/useAdaptiveCardsHostConfig'; import useAdaptiveCardsPackage from '../hooks/useAdaptiveCardsPackage'; import { BotFrameworkCardAction } from './AdaptiveCardBuilder'; @@ -32,6 +32,8 @@ import useRoleModEffect from './AdaptiveCardHacks/useRoleModEffect'; import { directLineCardActionSchema } from './private/directLineSchema'; import renderAdaptiveCard from './private/renderAdaptiveCard'; +import styles from './AdaptiveCardRenderer.module.css'; + const { useLocalizer, usePerformCardAction, useRenderMarkdownAsHTML, useScrollToEnd, useUIState } = hooks; const adaptiveCardRendererPropsSchema = pipe( @@ -54,7 +56,6 @@ function AdaptiveCardRenderer(props: AdaptiveCardRendererProps) { tapAction } = validateProps(adaptiveCardRendererPropsSchema, props); - const [{ adaptiveCardRenderer: adaptiveCardRendererStyleSet }] = useStyleSet(); const [{ GlobalSettings, HostConfig }] = useAdaptiveCardsPackage(); const [adaptiveCardsHostConfig] = useAdaptiveCardsHostConfig(); const [uiState] = useUIState(); @@ -63,6 +64,7 @@ function AdaptiveCardRenderer(props: AdaptiveCardRendererProps) { const performCardAction = usePerformCardAction(); const renderMarkdownAsHTML = useRenderMarkdownAsHTML('adaptive cards'); const scrollToEnd = useScrollToEnd(); + const classNames = useStyles(styles); const disabled = uiState === 'disabled' || disabledFromProps; const tapActionRef = useValueRef(tapAction); @@ -249,7 +251,7 @@ function AdaptiveCardRenderer(props: AdaptiveCardRendererProps) { ) : (
} onKeyPress={handleClickAndKeyPressForTapAction as KeyboardEventHandler} ref={contentRef} diff --git a/packages/bundle/src/adaptiveCards/Attachment/AnimationCardContent.module.css b/packages/bundle/src/adaptiveCards/Attachment/AnimationCardContent.module.css new file mode 100644 index 0000000000..6aab802db6 --- /dev/null +++ b/packages/bundle/src/adaptiveCards/Attachment/AnimationCardContent.module.css @@ -0,0 +1,10 @@ +:global(.webchat) .animation-card-attachment { + display: flex; + flex-direction: column; + + > :global(ul.media-list) { + list-style-type: none; + margin: 0; + padding: 0; + } +} diff --git a/packages/bundle/src/adaptiveCards/Attachment/AnimationCardContent.tsx b/packages/bundle/src/adaptiveCards/Attachment/AnimationCardContent.tsx index 2e93e1db2a..6a738306da 100644 --- a/packages/bundle/src/adaptiveCards/Attachment/AnimationCardContent.tsx +++ b/packages/bundle/src/adaptiveCards/Attachment/AnimationCardContent.tsx @@ -1,14 +1,16 @@ /* eslint react/no-array-index-key: "off" */ import { validateProps } from '@msinternal/botframework-webchat-react-valibot'; +import { useStyles } from '@msinternal/botframework-webchat-styles/react'; import { Components } from 'botframework-webchat-component'; import React, { memo } from 'react'; import { boolean, object, optional, pipe, readonly, string, type InferInput } from 'valibot'; -import useStyleSet from '../../hooks/useStyleSet'; import CommonCard from './CommonCard'; import { directLineMediaCardSchema } from './private/directLineSchema'; +import styles from './AnimationCardContent.module.css'; + const { ImageContent, VideoContent } = Components; const animationCardContentPropsSchema = pipe( @@ -26,10 +28,10 @@ function AnimationCardContent(props: AnimationCardContentProps) { const { actionPerformedClassName, content, disabled } = validateProps(animationCardContentPropsSchema, props); const { media = [] } = content; - const [{ animationCardAttachment: animationCardAttachmentStyleSet }] = useStyleSet(); + const classNames = useStyles(styles); return ( -
+