diff --git a/change/@fluentui-contrib-react-chat-8b525164-bd14-41d1-b21f-e1bcc2a2a54b.json b/change/@fluentui-contrib-react-chat-8b525164-bd14-41d1-b21f-e1bcc2a2a54b.json new file mode 100644 index 00000000..bcaec6e1 --- /dev/null +++ b/change/@fluentui-contrib-react-chat-8b525164-bd14-41d1-b21f-e1bcc2a2a54b.json @@ -0,0 +1,7 @@ +{ + "type": "patch", + "comment": "chore: use new slot api for ChatMessage/ChatMyMessage", + "packageName": "@fluentui-contrib/react-chat", + "email": "yuanboxue@microsoft.com", + "dependentChangeType": "patch" +} diff --git a/packages/react-chat/src/components/ChatMessage/renderChatMessage.tsx b/packages/react-chat/src/components/ChatMessage/renderChatMessage.tsx index 21c73356..1694510b 100644 --- a/packages/react-chat/src/components/ChatMessage/renderChatMessage.tsx +++ b/packages/react-chat/src/components/ChatMessage/renderChatMessage.tsx @@ -1,36 +1,37 @@ -import * as React from 'react'; -import { getSlots } from '@fluentui/react-components'; +/** @jsxRuntime classic */ +/** @jsx createElement */ + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +import { createElement } from '@fluentui/react-jsx-runtime'; + +import { assertSlots } from '@fluentui/react-components'; import type { ChatMessageState, ChatMessageSlots } from './ChatMessage.types'; /** * Render the final JSX of ChatMessage */ export const renderChatMessage_unstable = (state: ChatMessageState) => { - const { slots, slotProps } = getSlots(state); + assertSlots(state); return ( - - {slots.avatar && } + + {state.avatar && } - +
- {slots.author && } - {slots.timestamp && } - {slots.details && } + {state.author && } + {state.timestamp && } + {state.details && }
- {slots.decorationLabel && ( - - )} + {state.decorationLabel && } - {slotProps.body.children} + {state.body.children} - {slots.decorationIcon && ( - - )} + {state.decorationIcon && } - {slots.reactions && } -
-
+ {state.reactions && } + + ); }; diff --git a/packages/react-chat/src/components/ChatMessage/useChatMessage.ts b/packages/react-chat/src/components/ChatMessage/useChatMessage.ts index 5d643e12..7cb41c05 100644 --- a/packages/react-chat/src/components/ChatMessage/useChatMessage.ts +++ b/packages/react-chat/src/components/ChatMessage/useChatMessage.ts @@ -1,8 +1,5 @@ import * as React from 'react'; -import { - getPartitionedNativeProps, - resolveShorthand, -} from '@fluentui/react-components'; +import { getPartitionedNativeProps, slot } from '@fluentui/react-components'; import type { ChatMessageProps, ChatMessageState } from './ChatMessage.types'; import { getDecorationIcon } from '../utils/getDecorationIcon'; import { useChatMessageFocusableGroup } from '../utils/useChatMessageFocusableGroup'; @@ -60,29 +57,33 @@ export const useChatMessage_unstable = ( persistentTimestamp, showAnimation, - body: resolveShorthand(body, { - required: true, + body: slot.always(body, { defaultProps: { ref, ...nativeProps.primary, tabIndex: 0, }, + elementType: 'div', }), - root: resolveShorthand(root, { - required: true, + root: slot.always(root, { defaultProps: nativeProps.root, + elementType: 'div', }), - author: resolveShorthand(author), + author: slot.optional(author, { elementType: 'div' }), avatar: - attached && attached !== 'top' ? undefined : resolveShorthand(avatar), - decorationIcon: resolveShorthand(decorationIcon, { - required: !!decoration, + attached && attached !== 'top' + ? undefined + : slot.optional(avatar, { elementType: 'div' }), + decorationIcon: slot.optional(decorationIcon, { + elementType: 'div', + defaultProps: { children: getDecorationIcon(decoration) }, + renderByDefault: !!decoration, }), - decorationLabel: resolveShorthand(decorationLabel), - details: resolveShorthand(details), - reactions: resolveShorthand(reactions), - timestamp: resolveShorthand(timestamp), + decorationLabel: slot.optional(decorationLabel, { elementType: 'div' }), + details: slot.optional(details, { elementType: 'div' }), + reactions: slot.optional(reactions, { elementType: 'div' }), + timestamp: slot.optional(timestamp, { elementType: 'span' }), components: { author: 'div', @@ -97,10 +98,6 @@ export const useChatMessage_unstable = ( }, }; - if (state.decorationIcon && !state.decorationIcon.children) { - state.decorationIcon.children = getDecorationIcon(decoration); - } - useChatMessagePopoverTrigger(state); useChatMessageFocusableGroup(state); diff --git a/packages/react-chat/src/components/ChatMyMessage/renderChatMyMessage.tsx b/packages/react-chat/src/components/ChatMyMessage/renderChatMyMessage.tsx index c759589c..63c1ca35 100644 --- a/packages/react-chat/src/components/ChatMyMessage/renderChatMyMessage.tsx +++ b/packages/react-chat/src/components/ChatMyMessage/renderChatMyMessage.tsx @@ -1,5 +1,10 @@ -import { getSlots } from '@fluentui/react-components'; -import * as React from 'react'; +/** @jsxRuntime classic */ +/** @jsx createElement */ + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +import { createElement } from '@fluentui/react-jsx-runtime'; + +import { assertSlots } from '@fluentui/react-components'; import type { ChatMyMessageSlots, @@ -7,37 +12,29 @@ import type { } from './ChatMyMessage.types'; export const renderChatMyMessage_unstable = (state: ChatMyMessageState) => { - const { slots, slotProps } = getSlots(state); + assertSlots(state); return ( - - + +
- {slots.author && } - {slots.timestamp && } - {slots.details && !slots.statusMessage && ( - - )} - {slots.statusMessage && ( - - )} + {state.author && } + {state.timestamp && } + {state.details && !state.statusMessage && } + {state.statusMessage && }
- {slots.decorationLabel && ( - - )} + {state.decorationLabel && } - {slotProps.body.children} + {state.body.children} - {slots.decorationIcon && ( - - )} + {state.decorationIcon && } - {slots.reactions && } -
+ {state.reactions && } + - {slots.statusIcon && } + {state.statusIcon && } - {slots.actions && } -
+ {state.actions && } + ); }; diff --git a/packages/react-chat/src/components/ChatMyMessage/useChatMyMessage.tsx b/packages/react-chat/src/components/ChatMyMessage/useChatMyMessage.tsx index 1bd51243..d539db51 100644 --- a/packages/react-chat/src/components/ChatMyMessage/useChatMyMessage.tsx +++ b/packages/react-chat/src/components/ChatMyMessage/useChatMyMessage.tsx @@ -5,10 +5,7 @@ import type { ChatMyMessageState, } from './ChatMyMessage.types'; -import { - getPartitionedNativeProps, - resolveShorthand, -} from '@fluentui/react-components'; +import { getPartitionedNativeProps, slot } from '@fluentui/react-components'; import { CheckmarkCircle16Regular, Circle16Regular, @@ -67,30 +64,40 @@ export const useChatMyMessage_unstable = ( showAnimation, status, - body: resolveShorthand(body, { - required: true, + body: slot.always(body, { defaultProps: { ref, ...nativeProps.primary, tabIndex: 0, }, + elementType: 'div', }), - root: resolveShorthand(root, { - required: true, + root: slot.always(root, { defaultProps: nativeProps.root, + elementType: 'div', }), - actions: resolveShorthand(actions), - author: resolveShorthand(author), - decorationIcon: resolveShorthand(decorationIcon, { - required: !!decoration, + actions: slot.optional(actions, { elementType: 'div' }), + author: slot.optional(author, { elementType: 'div' }), + decorationIcon: slot.optional(decorationIcon, { + elementType: 'div', + defaultProps: { + children: getDecorationIcon(decoration), + }, + renderByDefault: !!decoration, }), - decorationLabel: resolveShorthand(decorationLabel), - details: resolveShorthand(details), - reactions: resolveShorthand(reactions), - statusIcon: resolveShorthand(statusIcon, { required: !!status }), - statusMessage: resolveShorthand(statusMessage), - timestamp: resolveShorthand(timestamp), + decorationLabel: slot.optional(decorationLabel, { elementType: 'div' }), + details: slot.optional(details, { elementType: 'div' }), + reactions: slot.optional(reactions, { elementType: 'div' }), + statusIcon: slot.optional(statusIcon, { + elementType: 'div', + defaultProps: { + children: getStatusIcon(status), + }, + renderByDefault: !!status, + }), + statusMessage: slot.optional(statusMessage, { elementType: 'div' }), + timestamp: slot.optional(timestamp, { elementType: 'span' }), components: { actions: 'div', @@ -107,39 +114,25 @@ export const useChatMyMessage_unstable = ( }, }; - updateStatusWithIcon(state); - - if (state.decorationIcon && !state.decorationIcon.children) { - state.decorationIcon.children = getDecorationIcon(decoration); - } - useChatMessagePopoverTrigger(state); useChatMessageFocusableGroup(state); return state; }; -const updateStatusWithIcon = (state: ChatMyMessageState) => { - if (state.statusIcon && !state.statusIcon.children) { - switch (state.status) { - case 'sending': - state.statusIcon.children = ; - break; - case 'received': - state.statusIcon.children = ; - break; - case 'read': - state.statusIcon.children = ; - break; - case 'failed': - state.statusIcon.children = ; - break; - case 'blocked': - state.statusIcon.children = ; - break; - case 'scheduled': - state.statusIcon.children = ; - break; - } +const getStatusIcon = (status: ChatMyMessageProps['status']) => { + switch (status) { + case 'sending': + return ; + case 'received': + return ; + case 'read': + return ; + case 'failed': + return ; + case 'blocked': + return ; + case 'scheduled': + return ; } };