diff --git a/packages/fluentui/CHANGELOG.md b/packages/fluentui/CHANGELOG.md
index 2bda8c3131e1e5..c55c0b5ea1396a 100644
--- a/packages/fluentui/CHANGELOG.md
+++ b/packages/fluentui/CHANGELOG.md
@@ -18,6 +18,9 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
## [Unreleased]
+### BREAKING CHANGES
+- Styles from `ChatMessage` content slot were moved to exact component `ChatMessageContent` @yuanboxue-amber ([#24691](https://github.com/microsoft/fluentui/pull/24691))
+
### Features
- Add a new comfy layout variation for `ChatMessage` @davezuko ([#23974](https://github.com/microsoft/fluentui/pull/23974))
diff --git a/packages/fluentui/docs/src/examples/components/Chat/Content/ChatExampleReactionGroupMeReacting.shorthand.steps.ts b/packages/fluentui/docs/src/examples/components/Chat/Content/ChatExampleReactionGroupMeReacting.shorthand.steps.ts
index 975ba3744a680a..47c4430516daaa 100644
--- a/packages/fluentui/docs/src/examples/components/Chat/Content/ChatExampleReactionGroupMeReacting.shorthand.steps.ts
+++ b/packages/fluentui/docs/src/examples/components/Chat/Content/ChatExampleReactionGroupMeReacting.shorthand.steps.ts
@@ -1,8 +1,8 @@
import { ALL_THEMES, ScreenerTestsConfig } from '@fluentui/scripts/screener';
-import { reactionClassName, chatMessageSlotClassNames } from '@fluentui/react-northstar';
+import { reactionClassName, chatMessageContentClassName } from '@fluentui/react-northstar';
const selectors = {
- chatMessageContent: `.${chatMessageSlotClassNames.content}`,
+ chatMessageContent: chatMessageContentClassName,
reaction: `.${reactionClassName}`,
};
diff --git a/packages/fluentui/docs/src/examples/components/Chat/Playground.tsx b/packages/fluentui/docs/src/examples/components/Chat/Playground.tsx
index 4fe381e260c702..1ac90de5d886a8 100644
--- a/packages/fluentui/docs/src/examples/components/Chat/Playground.tsx
+++ b/packages/fluentui/docs/src/examples/components/Chat/Playground.tsx
@@ -15,6 +15,7 @@ import {
import {
Avatar,
Chat,
+ ChatItem,
ChatItemProps,
ChatMessageProps,
MenuProps,
@@ -126,17 +127,13 @@ const ChatPlayground: React.FunctionComponent = () => {
};
return (
- } size={size} />,
- key: '1',
- message: ,
- ...chatItemProps,
- },
- ]}
- />
+
+ } size={size} />}
+ message={}
+ {...chatItemProps}
+ />
+
);
};
diff --git a/packages/fluentui/docs/src/examples/components/Chat/Types/ChatMessageExampleStyled.shorthand.tsx b/packages/fluentui/docs/src/examples/components/Chat/Types/ChatMessageExampleStyled.shorthand.tsx
index fde12dc562e7bf..d1932062888e57 100644
--- a/packages/fluentui/docs/src/examples/components/Chat/Types/ChatMessageExampleStyled.shorthand.tsx
+++ b/packages/fluentui/docs/src/examples/components/Chat/Types/ChatMessageExampleStyled.shorthand.tsx
@@ -72,7 +72,6 @@ const ChatMessageExampleStyled = () => (
backgroundColor: '#E0FFFF',
}),
}),
- content: { ...slotLabelStyles('content'), backgroundColor: '#F08080' },
timestamp: {
...slotLabelStyles('timestamp', {}, { display: 'inline-block' }),
backgroundColor: '#FFFFE0',
@@ -90,10 +89,13 @@ const ChatMessageExampleStyled = () => (
backgroundColor: '#FFFFE0',
},
},
+ ChatMessageContent: {
+ root: { ...slotLabelStyles('content'), backgroundColor: '#F08080' },
+ },
},
componentVariables: {
- ChatMessage: siteVars => ({
- content: {
+ ChatMessageContent: siteVars => ({
+ root: {
focusOutlineColor: siteVars.colors.red[400],
},
}),
diff --git a/packages/fluentui/react-northstar-prototypes/src/prototypes/chatMessages/ThreadedMessages/classNames.ts b/packages/fluentui/react-northstar-prototypes/src/prototypes/chatMessages/ThreadedMessages/classNames.ts
index 1f566667c5d821..05df9ed8db2b6e 100644
--- a/packages/fluentui/react-northstar-prototypes/src/prototypes/chatMessages/ThreadedMessages/classNames.ts
+++ b/packages/fluentui/react-northstar-prototypes/src/prototypes/chatMessages/ThreadedMessages/classNames.ts
@@ -4,13 +4,14 @@ import {
chatItemSlotClassNames,
chatItemClassName,
chatMessageClassName,
+ chatMessageContentClassName,
} from '@fluentui/react-northstar';
const classNames = {
threadedMessage: {
thread: `${chatMessageClassName}__thread`,
threadBody: `${chatMessageClassName}__thread-body`,
- innerContent: `${chatMessageSlotClassNames.content}-inner`,
+ innerContent: `${chatMessageContentClassName}-inner`,
author: `${chatMessageSlotClassNames.author}-inner`,
timestamp: `${chatMessageSlotClassNames.timestamp}-inner`,
},
diff --git a/packages/fluentui/react-northstar/src/components/Chat/ChatMessage.tsx b/packages/fluentui/react-northstar/src/components/Chat/ChatMessage.tsx
index 01b32a32f448ac..32ad0a8768500f 100644
--- a/packages/fluentui/react-northstar/src/components/Chat/ChatMessage.tsx
+++ b/packages/fluentui/react-northstar/src/components/Chat/ChatMessage.tsx
@@ -17,6 +17,7 @@ import {
useUnhandledProps,
useMergedRefs,
ForwardRefWithAs,
+ mergeVariablesOverrides,
} from '@fluentui/react-bindings';
import { Ref } from '@fluentui/react-component-ref';
import * as customPropTypes from '@fluentui/react-proptypes';
@@ -67,6 +68,7 @@ import { ChatItemContext } from './chatItemContext';
import { ChatMessageDetails, ChatMessageDetailsProps } from './ChatMessageDetails';
import { ChatMessageHeader, ChatMessageHeaderProps } from './ChatMessageHeader';
import { ChatMessageReadStatus, ChatMessageReadStatusProps } from './ChatMessageReadStatus';
+import { ChatMessageContent } from './ChatMessageContent';
export interface ChatMessageSlotClassNames {
actionMenu: string;
@@ -77,7 +79,6 @@ export interface ChatMessageSlotClassNames {
bubbleInset: string;
body: string;
compactBody: string;
- content: string;
reactionGroup: string;
timestamp: string;
}
@@ -226,7 +227,6 @@ export const chatMessageSlotClassNames: ChatMessageSlotClassNames = {
bubble: `${chatMessageClassName}__bubble`,
bubbleInset: `${chatMessageClassName}__bubble-inset`,
compactBody: `${chatMessageClassName}__compact-body`,
- content: `${chatMessageClassName}__content`,
reactionGroup: `${chatMessageClassName}__reactions`,
timestamp: `${chatMessageClassName}__timestamp`,
};
@@ -542,10 +542,10 @@ export const ChatMessage = (React.forwardRef((
}),
});
- const messageContent = Box.create(content, {
- defaultProps: () => ({
- className: chatMessageSlotClassNames.content,
- styles: resolvedStyles.content,
+ const messageContent = createShorthand(ChatMessageContent, content, {
+ defaultProps: () => ({ badgePosition, density, failed, hasBadge: !!badge, mine, unstable_layout: layout }),
+ overrideProps: predefinedProps => ({
+ variables: mergeVariablesOverrides(variables, predefinedProps.variables),
}),
});
diff --git a/packages/fluentui/react-northstar/src/components/Chat/ChatMessageContent.tsx b/packages/fluentui/react-northstar/src/components/Chat/ChatMessageContent.tsx
new file mode 100644
index 00000000000000..8ca7fc7fdc1e35
--- /dev/null
+++ b/packages/fluentui/react-northstar/src/components/Chat/ChatMessageContent.tsx
@@ -0,0 +1,56 @@
+import { compose } from '@fluentui/react-bindings';
+import * as PropTypes from 'prop-types';
+
+import { commonPropTypes } from '../../utils';
+import { Box, BoxProps, BoxStylesProps } from '../Box/Box';
+import { ChatDensity } from './chatDensity';
+import { ChatMessageLayout, ChatMessageProps } from './ChatMessage';
+
+export interface ChatMessageContentOwnProps
+ extends Pick {
+ /** Indicates whether parent ChatMessage has badge. */
+ hasBadge?: boolean;
+}
+export interface ChatMessageContentProps extends ChatMessageContentOwnProps, BoxProps {}
+
+export type ChatMessageContentStylesProps = Required<
+ Pick
+> & {
+ layout: ChatMessageLayout;
+};
+export const chatMessageContentClassName = 'ui-chat__messagecontent';
+
+/**
+ * A ChatMessageContent provides a slot for content in the ChatMessage.
+ */
+export const ChatMessageContent = compose<
+ 'div',
+ ChatMessageContentOwnProps,
+ ChatMessageContentStylesProps,
+ BoxProps,
+ BoxStylesProps
+>(Box, {
+ className: chatMessageContentClassName,
+ displayName: 'ChatMessageContent',
+ handledProps: ['badgePosition', 'density', 'failed', 'hasBadge', 'mine', 'unstable_layout'],
+ mapPropsToStylesProps: ({ badgePosition, density, failed, hasBadge, mine, unstable_layout }) => ({
+ badgePosition,
+ density,
+ failed,
+ hasBadge,
+ layout: unstable_layout,
+ mine,
+ }),
+ overrideStyles: true,
+ shorthandConfig: { mappedProp: 'content' },
+});
+
+ChatMessageContent.propTypes = {
+ ...commonPropTypes.createCommon(),
+ badgePosition: PropTypes.oneOf(['start', 'end']),
+ density: PropTypes.oneOf(['comfy', 'compact']),
+ failed: PropTypes.bool,
+ hasBadge: PropTypes.bool,
+ mine: PropTypes.bool,
+ unstable_layout: PropTypes.oneOf(['default', 'refresh']),
+};
diff --git a/packages/fluentui/react-northstar/src/index.ts b/packages/fluentui/react-northstar/src/index.ts
index d635199fdb0b96..2e278a33074dbf 100644
--- a/packages/fluentui/react-northstar/src/index.ts
+++ b/packages/fluentui/react-northstar/src/index.ts
@@ -61,6 +61,7 @@ export * from './components/Breadcrumb/BreadcrumbLink';
export * from './components/Chat/Chat';
export * from './components/Chat/ChatItem';
export * from './components/Chat/ChatMessage';
+export * from './components/Chat/ChatMessageContent';
export * from './components/Chat/ChatMessageDetails';
export * from './components/Chat/ChatMessageHeader';
export * from './components/Chat/ChatMessageReadStatus';
diff --git a/packages/fluentui/react-northstar/src/themes/teams/componentStyles.ts b/packages/fluentui/react-northstar/src/themes/teams/componentStyles.ts
index 58d3ec740ef79a..e5508657092a9a 100644
--- a/packages/fluentui/react-northstar/src/themes/teams/componentStyles.ts
+++ b/packages/fluentui/react-northstar/src/themes/teams/componentStyles.ts
@@ -32,6 +32,7 @@ export { breadcrumbStyles as Breadcrumb } from './components/Breadcrumb/breadcru
export { chatStyles as Chat } from './components/Chat/chatStyles';
export { chatItemStyles as ChatItem } from './components/Chat/chatItemStyles';
export { chatMessageStyles as ChatMessage } from './components/Chat/chatMessageStyles';
+export { chatMessageContentStyles as ChatMessageContent } from './components/Chat/chatMessageContentStyles';
export { chatMessageDetailsStyles as ChatMessageDetails } from './components/Chat/chatMessageDetailsStyles';
export { chatMessageReadStatusStyles as ChatMessageReadStatus } from './components/Chat/chatMessageReadStatusStyles';
diff --git a/packages/fluentui/react-northstar/src/themes/teams/componentVariables.ts b/packages/fluentui/react-northstar/src/themes/teams/componentVariables.ts
index e86c403cf2abb7..455b5f6e49e598 100644
--- a/packages/fluentui/react-northstar/src/themes/teams/componentVariables.ts
+++ b/packages/fluentui/react-northstar/src/themes/teams/componentVariables.ts
@@ -31,6 +31,7 @@ export { breadcrumbDividerVariables as BreadcrumbDivider } from './components/Br
export { chatVariables as Chat } from './components/Chat/chatVariables';
export { chatItemVariables as ChatItem } from './components/Chat/chatItemVariables';
export { chatMessageVariables as ChatMessage } from './components/Chat/chatMessageVariables';
+export { chatMessageContentVariables as ChatMessageContent } from './components/Chat/chatMessageContentVariables';
export { chatMessageDetailsVariables as ChatMessageDetails } from './components/Chat/chatMessageDetailsVariables';
export { chatMessageReadStatusVariables as ChatMessageReadStatus } from './components/Chat/chatMessageReadStatusVariables';
diff --git a/packages/fluentui/react-northstar/src/themes/teams/components/Chat/chatMessageContentStyles.ts b/packages/fluentui/react-northstar/src/themes/teams/components/Chat/chatMessageContentStyles.ts
new file mode 100644
index 00000000000000..a3268ad71db47c
--- /dev/null
+++ b/packages/fluentui/react-northstar/src/themes/teams/components/Chat/chatMessageContentStyles.ts
@@ -0,0 +1,45 @@
+import { ComponentSlotStylesPrepared, ICSSInJSStyle } from '@fluentui/styles';
+
+import { ChatMessageContentStylesProps } from '../../../../components/Chat/ChatMessageContent';
+import { ChatMessageVariables } from './chatMessageVariables';
+import { pxToRem } from '../../../../utils';
+
+export const chatMessageContentStyles: ComponentSlotStylesPrepared<
+ ChatMessageContentStylesProps,
+ ChatMessageVariables
+> = {
+ root: (componentStyleFunctionParam): ICSSInJSStyle => {
+ const { props: p, variables: v, theme } = componentStyleFunctionParam;
+ return {
+ color: v.contentColor,
+ display: 'block',
+ '& a': {
+ outline: 'none',
+ color: p.mine ? v.linkColorMine : v.linkColor,
+ ':focus': {
+ textDecoration: 'underline',
+ },
+ },
+
+ ...(p.layout === 'refresh' &&
+ p.density === 'comfy' && {
+ wordBreak: 'break-word',
+ wordWrap: 'break-word',
+ '& a': {
+ color: 'inherit',
+ textDecoration: 'underline',
+ wordBreak: 'break-all',
+ '&:hover': { textDecorationStyle: 'double' },
+ '&:focus': { textDecorationStyle: 'double' },
+ },
+ ...(p.failed && {
+ color: theme.siteVariables.colorScheme.default.foreground,
+ }),
+ }),
+
+ ...(p.density === 'comfy' && {
+ ...(p.hasBadge && p.badgePosition === 'end' && { marginRight: pxToRem(4) }),
+ }),
+ };
+ },
+};
diff --git a/packages/fluentui/react-northstar/src/themes/teams/components/Chat/chatMessageContentVariables.ts b/packages/fluentui/react-northstar/src/themes/teams/components/Chat/chatMessageContentVariables.ts
new file mode 100644
index 00000000000000..72a5ef81fee76a
--- /dev/null
+++ b/packages/fluentui/react-northstar/src/themes/teams/components/Chat/chatMessageContentVariables.ts
@@ -0,0 +1 @@
+export { chatMessageVariables as chatMessageContentVariables } from './chatMessageVariables';
diff --git a/packages/fluentui/react-northstar/src/themes/teams/components/Chat/chatMessageStyles.ts b/packages/fluentui/react-northstar/src/themes/teams/components/Chat/chatMessageStyles.ts
index dda9be3a5b6fbe..3d5f9921d98dd1 100644
--- a/packages/fluentui/react-northstar/src/themes/teams/components/Chat/chatMessageStyles.ts
+++ b/packages/fluentui/react-northstar/src/themes/teams/components/Chat/chatMessageStyles.ts
@@ -114,22 +114,6 @@ export const chatMessageStyles: ComponentSlotStylesPrepared {
- const { props: p, variables: v } = componentStyleFunctionParam;
- return {
- color: v.contentColor,
- display: 'block',
- '& a': {
- outline: 'none',
- color: p.mine ? v.linkColorMine : v.linkColor,
- ':focus': {
- textDecoration: 'underline',
- },
- },
- ...getChatMessageVariantStyles(p).content?.(componentStyleFunctionParam),
- };
- },
-
badge: (componentStyleFunctionParam): ICSSInJSStyle => {
const { props: p, variables: v } = componentStyleFunctionParam;
return {
diff --git a/packages/fluentui/react-northstar/src/themes/teams/components/Chat/chatMessageStylesComfy.ts b/packages/fluentui/react-northstar/src/themes/teams/components/Chat/chatMessageStylesComfy.ts
index 05ec82c172efee..89694a21337614 100644
--- a/packages/fluentui/react-northstar/src/themes/teams/components/Chat/chatMessageStylesComfy.ts
+++ b/packages/fluentui/react-northstar/src/themes/teams/components/Chat/chatMessageStylesComfy.ts
@@ -66,10 +66,6 @@ export const chatMessageStylesComfy: ComponentSlotStylesPrepared ({
- ...(p.hasBadge && p.badgePosition === 'end' && { marginRight: pxToRem(4) }),
- }),
-
reactionGroup: ({ props: p, variables: v }) => ({
marginLeft: v.reactionGroupMarginLeft,
...(p.hasBadge && p.badgePosition === 'end' && { marginRight: pxToRem(2) }),
diff --git a/packages/fluentui/react-northstar/src/themes/teams/components/Chat/chatMessageStylesComfyRefresh.ts b/packages/fluentui/react-northstar/src/themes/teams/components/Chat/chatMessageStylesComfyRefresh.ts
index 58ce704aebf28d..75825264f73bde 100644
--- a/packages/fluentui/react-northstar/src/themes/teams/components/Chat/chatMessageStylesComfyRefresh.ts
+++ b/packages/fluentui/react-northstar/src/themes/teams/components/Chat/chatMessageStylesComfyRefresh.ts
@@ -160,22 +160,6 @@ export const chatMessageStylesComfyRefresh: ComponentSlotStylesPrepared<
},
}),
- content: ({ props: p, variables: v, theme }): ICSSInJSStyle => ({
- color: v.contentColor,
- wordBreak: 'break-word',
- wordWrap: 'break-word',
- '& a': {
- color: 'inherit',
- textDecoration: 'underline',
- wordBreak: 'break-all',
- '&:hover': { textDecorationStyle: 'double' },
- '&:focus': { textDecorationStyle: 'double' },
- },
- ...(p.failed && {
- color: theme.siteVariables.colorScheme.default.foreground,
- }),
- }),
-
badge: ({ props: p, variables: v }): ICSSInJSStyle => ({
position: 'relative',
top: pxToRem(-5),
diff --git a/packages/fluentui/react-northstar/src/themes/teams/types.ts b/packages/fluentui/react-northstar/src/themes/teams/types.ts
index 36a9b52bbbb4af..dff2efc58077ce 100644
--- a/packages/fluentui/react-northstar/src/themes/teams/types.ts
+++ b/packages/fluentui/react-northstar/src/themes/teams/types.ts
@@ -29,6 +29,7 @@ import { ButtonStylesProps } from '../../components/Button/Button';
import { ButtonContentStylesProps } from '../../components/Button/ButtonContent';
import { ChatItemStylesProps } from '../../components/Chat/ChatItem';
import { ChatMessageStylesProps } from '../../components/Chat/ChatMessage';
+import { ChatMessageContentStylesProps } from '../../components/Chat/ChatMessageContent';
import { ChatMessageDetailsStylesProps } from '../../components/Chat/ChatMessageDetails';
import { ChatMessageHeaderStylesProps } from '../../components/Chat/ChatMessageHeader';
import { ChatMessageReadStatusStylesProps } from '../../components/Chat/ChatMessageReadStatus';
@@ -144,6 +145,7 @@ export type TeamsThemeStylesProps = {
Chat: ChatStylesProps;
ChatItem: ChatItemStylesProps;
ChatMessage: ChatMessageStylesProps;
+ ChatMessageContent: ChatMessageContentStylesProps;
ChatMessageDetails: ChatMessageDetailsStylesProps;
ChatMessageHeader: ChatMessageHeaderStylesProps;
ChatMessageReadStatus: ChatMessageReadStatusStylesProps;
diff --git a/packages/fluentui/react-northstar/test/specs/components/Chat/ChatMessage-test.tsx b/packages/fluentui/react-northstar/test/specs/components/Chat/ChatMessage-test.tsx
index 012f57f9a746cf..ffd1a2ee925037 100644
--- a/packages/fluentui/react-northstar/test/specs/components/Chat/ChatMessage-test.tsx
+++ b/packages/fluentui/react-northstar/test/specs/components/Chat/ChatMessage-test.tsx
@@ -2,8 +2,8 @@ import { handlesAccessibility, implementsShorthandProp, isConformant } from 'tes
import { ChatMessage } from 'src/components/Chat/ChatMessage';
import { Text } from 'src/components/Text/Text';
-import { Box } from 'src/components/Box/Box';
import { ChatMessageDetails } from 'src/components/Chat/ChatMessageDetails';
+import { ChatMessageContent } from 'src/components/Chat/ChatMessageContent';
const chatMessageImplementsShorthandProp = implementsShorthandProp(ChatMessage);
@@ -19,7 +19,7 @@ describe('ChatMessage', () => {
chatMessageImplementsShorthandProp('author', Text);
chatMessageImplementsShorthandProp('timestamp', Text);
chatMessageImplementsShorthandProp('details', ChatMessageDetails);
- chatMessageImplementsShorthandProp('content', Box, { mapsValueToProp: 'children' });
+ chatMessageImplementsShorthandProp('content', ChatMessageContent);
describe('accessibility', () => {
handlesAccessibility(ChatMessage);
diff --git a/packages/fluentui/react-northstar/test/specs/components/Chat/ChatMessageContent-test.tsx b/packages/fluentui/react-northstar/test/specs/components/Chat/ChatMessageContent-test.tsx
new file mode 100644
index 00000000000000..ee518926040569
--- /dev/null
+++ b/packages/fluentui/react-northstar/test/specs/components/Chat/ChatMessageContent-test.tsx
@@ -0,0 +1,9 @@
+import { ChatMessageContent } from 'src/components/Chat/ChatMessageContent';
+import { isConformant } from 'test/specs/commonTests';
+
+describe('ChatMessageContent', () => {
+ isConformant(ChatMessageContent, {
+ testPath: __filename,
+ constructorName: 'ChatMessageContent',
+ });
+});