Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ Breaking changes in this release:
- New debug API, by [@compulim](https://github.com/compulim) in PR [#5663](https://github.com/microsoft/BotFramework-WebChat/pull/5663) and PR [#5664](https://github.com/microsoft/BotFramework-WebChat/pull/5664), see [`DEBUGGING.md`](docs/DEBUGGING.md) for more
- Debug into element: open <kbd>F12</kbd>, select the subject in Element pane, type `$0.webChat.debugger`
- Breakpoint: open <kbd>F12</kbd>, select the subject in Element pane, type `$0.webChat.breakpoint.incomingActivity`
- The `botframework-webchat` package now uses CSS modules for styling purposes, in PR [#5666](https://github.com/microsoft/BotFramework-WebChat/pull/5666), by [@OEvgeny](https://github.com/OEvgeny)

### Changed

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
2 changes: 1 addition & 1 deletion __tests__/html2/adaptiveCard/rerender.html
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down
2 changes: 1 addition & 1 deletion __tests__/html2/adaptiveCard/tapAction.html
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
Binary file modified __tests__/html2/fluentTheme/carousel.html.snap-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified __tests__/html2/fluentTheme/carousel.html.snap-2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified __tests__/html2/fluentTheme/simple.coarsePointer.html.snap-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified __tests__/html2/fluentTheme/withCustomDecorator.html.snap-2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 6 additions & 4 deletions __tests__/html2/themeProvider/override.html
Original file line number Diff line number Diff line change
Expand Up @@ -132,14 +132,15 @@

const styleElements = document.head.querySelectorAll('[data-webchat-injected]');

// THEN: Should have 5 <style> elements.
expect(styleElements).toHaveLength(5);
// THEN: Should have 6 <style> elements.
expect(styleElements).toHaveLength(6);

// THEN: <style> should be strictly ordered as below.
expect(Array.from(styleElements).map(element => element.dataset['webchatInjected'])).toEqual([
'',
'fluent-theme',
'component/decorator',
'bundle',
'component',
expect.stringMatching(/^component\/CustomPropertiesContainer-/)
]);
Expand All @@ -154,19 +155,20 @@
// WHEN: Move `stylesRoot` to document.body.
render(document.body);

// THEN: Should remove all 5 style elements from document.head.
// THEN: Should remove all 6 style elements from document.head.
expect(document.head.querySelectorAll('[data-webchat-injected]')).toHaveLength(0);

// THEN: Should move all 5 style elements to document.body.
const styleElementsInBody = document.body.querySelectorAll('[data-webchat-injected]');

expect(styleElementsInBody).toHaveLength(5);
expect(styleElementsInBody).toHaveLength(6);

// THEN: <style> should be strictly ordered as below.
expect(Array.from(styleElementsInBody).map(element => element.dataset['webchatInjected'])).toEqual([
'',
'fluent-theme',
'component/decorator',
'bundle',
'component',
expect.stringMatching(/^component\/CustomPropertiesContainer-/)
]);
Expand Down
1 change: 1 addition & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

38 changes: 35 additions & 3 deletions packages/bundle/esbuild.static.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,17 @@
/* eslint-disable no-magic-numbers */
/* eslint-disable no-restricted-globals */

import { injectCSSPlugin } from '@msinternal/botframework-webchat-styles/build';
import { mkdir, writeFile } from 'fs/promises';
import { build, context } from 'esbuild';
import { resolve } from 'path';
import { dirname, resolve } from 'path';
import { readPackage } from 'read-pkg';
import { fileURLToPath } from 'url';
import { cssPlugin } from '../../esbuildPlugins.mjs';

// TODO: [P0] We cannot import TypeScript file here.
const bundleStyleContentPlaceholder = '@--BUNDLE-STYLES-CONTENT--@';

// eslint-disable-next-line no-unused-vars
const isomorphicReactPlugin = {
name: 'isomorphic-react',
Expand Down Expand Up @@ -74,10 +79,37 @@ const BASE_CONFIG = {
minify: true,
outdir: resolve(fileURLToPath(import.meta.url), `../static/`),
platform: 'browser',
plugins: [cssPlugin],
metafile: true,
plugins: [
cssPlugin,
injectCSSPlugin({
getCSSText: (_source, cssFiles) => cssFiles.find(({ path }) => path.endsWith('botframework-webchat.css'))?.text,
stylesPlaceholder: bundleStyleContentPlaceholder
}),
{
// `write` is set to `false`, we need to emit files ourselves.
name: 'emit-output',
setup(build) {
build.onEnd(async args => {
await Promise.all(
args.outputFiles.map(async entry => {
// eslint-disable-next-line security/detect-non-literal-fs-filename
await mkdir(dirname(entry.path), { recursive: true });

// eslint-disable-next-line security/detect-non-literal-fs-filename
await writeFile(entry.path, entry.contents);
})
);
});
}
}
],
sourcemap: true,
splitting: true,
target: ['chrome100', 'firefox100', 'safari15']
target: ['chrome100', 'firefox100', 'safari15'],
// Set write to false for the `injectCSSPlugin` to work.
// We will emit the output in another plugin.
write: false
};

function* getKeysRecursive(exports) {
Expand Down
2 changes: 2 additions & 0 deletions packages/bundle/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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",
Expand Down
4 changes: 4 additions & 0 deletions packages/bundle/src/AddFullBundle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import React, { memo, type ReactNode } from 'react';
import AdaptiveCardsComposer from './adaptiveCards/AdaptiveCardsComposer';
import { type AdaptiveCardsStyleOptions } from './adaptiveCards/AdaptiveCardsStyleOptions';
import ShikiComposer from './codeHighlighter/ShikiComposer';
import BundleStylesheet from './stylesheet/BundleStylesheet';
import { type AdaptiveCardsPackage } from './types/AdaptiveCardsPackage';
import { type StrictFullBundleStyleOptions } from './types/FullBundleStyleOptions';
import useComposerProps from './useComposerProps';
Expand All @@ -24,6 +25,7 @@ type AddFullBundleProps = Readonly<{
attachmentMiddleware?: OneOrMany<AttachmentMiddleware>;
children: AddFullBundleChildren;
htmlContentTransformMiddleware?: HTMLContentTransformMiddleware[];
nonce?: string | undefined;
renderMarkdown?: (
markdown: string,
newLineOptions: { markdownRespectCRLF: boolean },
Expand All @@ -48,6 +50,7 @@ function AddFullBundle({
attachmentMiddleware,
children,
htmlContentTransformMiddleware,
nonce,
renderMarkdown,
styleOptions,
styleSet
Expand All @@ -69,6 +72,7 @@ function AddFullBundle({
adaptiveCardsHostConfig={adaptiveCardHostConfig || adaptiveCardsHostConfig}
adaptiveCardsPackage={adaptiveCardsPackage}
>
<BundleStylesheet at={styleOptions?.stylesRoot} nonce={nonce} />
{children(patchedProps)}
</AdaptiveCardsComposer>
</ShikiComposer>
Expand Down
Original file line number Diff line number Diff line change
@@ -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, white);

@media (forced-colors: active) {
background-color: Highlight;
border-color: Highlight;
color: HighlightText;
forced-color-adjust: none;
}
}

input[aria-disabled='true'] {
padding: 2px 1px;
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
/* 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 React, {
memo,
useCallback,
Expand All @@ -19,7 +19,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';
Expand All @@ -32,6 +31,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(
Expand All @@ -54,7 +55,6 @@ function AdaptiveCardRenderer(props: AdaptiveCardRendererProps) {
tapAction
} = validateProps(adaptiveCardRendererPropsSchema, props);

const [{ adaptiveCardRenderer: adaptiveCardRendererStyleSet }] = useStyleSet();
const [{ GlobalSettings, HostConfig }] = useAdaptiveCardsPackage();
const [adaptiveCardsHostConfig] = useAdaptiveCardsHostConfig();
const [uiState] = useUIState();
Expand All @@ -63,6 +63,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);
Expand Down Expand Up @@ -249,7 +250,7 @@ function AdaptiveCardRenderer(props: AdaptiveCardRendererProps) {
<ErrorBoxPolymiddlewareProxy error={errors[0]} where={localize('ADAPTIVE_CARD_ERROR_BOX_TITLE_RENDER')} />
) : (
<div
className={classNames(adaptiveCardRendererStyleSet + '', 'webchat__adaptive-card-renderer')}
className={classNames['adaptive-card-renderer']}
onClick={handleClickAndKeyPressForTapAction as MouseEventHandler<HTMLDivElement>}
onKeyPress={handleClickAndKeyPressForTapAction as KeyboardEventHandler<HTMLDivElement>}
ref={contentRef}
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
@@ -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(
Expand All @@ -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 (
<div className={animationCardAttachmentStyleSet}>
<div className={classNames['animation-card-attachment']}>
<ul className="media-list">
{media.map(({ profile = '', url }, index) => (
<li key={index}>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
:global(.webchat) .audio-card-attachment {
display: flex;
flex-direction: column;

> :global(ul.media-list) {
list-style-type: none;
margin: var(--webchat__padding--regular);
padding: 0;
}
}
Loading
Loading