Skip to content
Draft
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
Copy link

@github-actions github-actions bot Jan 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🕵🏾‍♀️ visual changes to review in the Visual Change Report

vr-tests-react-components/CalendarCompat 4 screenshots
Image Name Diff(in Pixels) Image Type
vr-tests-react-components/CalendarCompat.multiDayView - Dark Mode.default.chromium.png 555 Changed
vr-tests-react-components/CalendarCompat.multiDayView.default.chromium_1.png 481 Changed
vr-tests-react-components/CalendarCompat.multiDayView.default.chromium.png 391 Changed
vr-tests-react-components/CalendarCompat.multiDayView - High Contrast.default.chromium.png 680 Changed
vr-tests-react-components/Charts-DonutChart 2 screenshots
Image Name Diff(in Pixels) Image Type
vr-tests-react-components/Charts-DonutChart.Dynamic - RTL.default.chromium.png 5570 Changed
vr-tests-react-components/Charts-DonutChart.Dynamic - Dark Mode.default.chromium.png 7530 Changed
vr-tests-react-components/Positioning 2 screenshots
Image Name Diff(in Pixels) Image Type
vr-tests-react-components/Positioning.Positioning end.chromium.png 610 Changed
vr-tests-react-components/Positioning.Positioning end.updated 2 times.chromium.png 607 Changed
vr-tests-react-components/Skeleton converged 1 screenshots
Image Name Diff(in Pixels) Image Type
vr-tests-react-components/Skeleton converged.Opaque Skeleton with circle - High Contrast.default.chromium.png 1 Changed

There were 1 duplicate changes discarded. Check the build logs for more information.

"type": "minor",
"comment": "feat: add base state hooks for MessageBar components",
"packageName": "@fluentui/react-message-bar",
"email": "copilot@github.com",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
export type {
MessageBarBaseProps,
MessageBarBaseState,
MessageBarContextValues,
MessageBarIntent,
MessageBarProps,
Expand All @@ -9,6 +11,7 @@ export {
MessageBar,
messageBarClassNames,
renderMessageBar_unstable,
useMessageBarBase_unstable,
useMessageBarContextValue_unstable,
useMessageBarStyles_unstable,
useMessageBar_unstable,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
export type {
MessageBarActionsBaseProps,
MessageBarActionsBaseState,
MessageBarActionsContextValues,
MessageBarActionsProps,
MessageBarActionsSlots,
Expand All @@ -8,6 +10,7 @@ export {
MessageBarActions,
messageBarActionsClassNames,
renderMessageBarActions_unstable,
useMessageBarActionsBase_unstable,
useMessageBarActionsContextValue_unstable,
useMessageBarActionsStyles_unstable,
useMessageBarActions_unstable,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
export type {
MessageBarBodyBaseProps,
MessageBarBodyBaseState,
MessageBarBodyContextValues,
MessageBarBodyProps,
MessageBarBodySlots,
Expand All @@ -8,6 +10,7 @@ export {
MessageBarBody,
messageBarBodyClassNames,
renderMessageBarBody_unstable,
useMessageBarBodyBase_unstable,
useMessageBarBodyStyles_unstable,
useMessageBarBody_unstable,
} from './components/MessageBarBody/index';
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
export type {
MessageBarGroupBaseProps,
MessageBarGroupBaseState,
MessageBarGroupProps,
MessageBarGroupSlots,
MessageBarGroupState,
Expand All @@ -7,6 +9,8 @@ export {
MessageBarGroup,
messageBarGroupClassNames,
renderMessageBarGroup_unstable,
renderMessageBarGroupBase_unstable,
useMessageBarGroupBase_unstable,
useMessageBarGroupStyles_unstable,
useMessageBarGroup_unstable,
} from './components/MessageBarGroup/index';
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
export type {
MessageBarTitleBaseProps,
MessageBarTitleBaseState,
MessageBarTitleProps,
MessageBarTitleSlots,
MessageBarTitleState,
Expand All @@ -7,6 +9,7 @@ export {
MessageBarTitle,
messageBarTitleClassNames,
renderMessageBarTitle_unstable,
useMessageBarTitleBase_unstable,
useMessageBarTitleStyles_unstable,
useMessageBarTitle_unstable,
} from './components/MessageBarTitle/index';
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export type MessageBarSlots = {
* over this element
*
* NOTE: If you are using this slot, this probably means that you are using the MessageBar without
* actions, this is not recommended from an accesibility point of view
* actions, this is not recommended from an accessibility point of view
*/
bottomReflowSpacer?: Slot<'div'>;
};
Expand All @@ -36,12 +36,17 @@ export type MessageBarProps = ComponentProps<MessageBarSlots> &
*/
politeness?: 'assertive' | 'polite';
/**
* Use squal for page level messages and rounded for component level messages
* Use square for page level messages and rounded for component level messages
* @default rounded
*/
shape?: 'square' | 'rounded';
};

/**
* MessageBar base props, excluding design-related props like intent and shape
*/
export type MessageBarBaseProps = Omit<MessageBarProps, 'transitionClassName' | 'shape'>;

/**
* State used in rendering MessageBar
*/
Expand All @@ -53,3 +58,8 @@ export type MessageBarState = ComponentState<MessageBarSlots> &
*/
transitionClassName: string;
};

/**
* MessageBar base state, excluding design-related state like intent and shape
*/
export type MessageBarBaseState = Omit<MessageBarState, 'transitionClassName' | 'shape'>;
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
export { MessageBar } from './MessageBar';
export type {
MessageBarBaseProps,
MessageBarBaseState,
MessageBarContextValues,
MessageBarIntent,
MessageBarProps,
MessageBarSlots,
MessageBarState,
} from './MessageBar.types';
export { renderMessageBar_unstable } from './renderMessageBar';
export { useMessageBar_unstable } from './useMessageBar';
export { useMessageBar_unstable, useMessageBarBase_unstable } from './useMessageBar';
export { messageBarClassNames, useMessageBarStyles_unstable } from './useMessageBarStyles.styles';
export { useMessageBarContextValue_unstable } from './useMessageBarContextValues';
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
'use client';

import * as React from 'react';
import { getIntrinsicElementProps, slot, useId, useMergedRefs } from '@fluentui/react-utilities';
import { slot, useId, useMergedRefs } from '@fluentui/react-utilities';
import { useAnnounce } from '@fluentui/react-shared-contexts';
import type { MessageBarProps, MessageBarState } from './MessageBar.types';
import type { MessageBarProps, MessageBarState, MessageBarBaseProps, MessageBarBaseState } from './MessageBar.types';
import { getIntentIcon } from './getIntentIcon';
import { useMessageBarReflow } from './useMessageBarReflow';
import { useMessageBarTransitionContext } from '../../contexts/messageBarTransitionContext';
Expand All @@ -19,16 +19,47 @@ import { useMotionForwardedRef } from '../MotionRefForwarder';
* @param ref - reference to root HTMLElement of MessageBar
*/
export const useMessageBar_unstable = (props: MessageBarProps, ref: React.Ref<HTMLDivElement>): MessageBarState => {
const { layout = 'auto', intent = 'info', politeness, shape = 'rounded' } = props;
const computedPoliteness = politeness ?? intent === 'info' ? 'polite' : 'assertive';
const autoReflow = layout === 'auto';
const { ref: reflowRef, reflowing } = useMessageBarReflow(autoReflow);
const computedLayout = autoReflow ? (reflowing ? 'multiline' : 'singleline') : layout;
'use no memo';

const { shape = 'rounded', ...restProps } = props;

const baseState = useMessageBarBase_unstable(restProps, ref);

// eslint-disable-next-line @typescript-eslint/no-deprecated
const { className: transitionClassName, nodeRef } = useMessageBarTransitionContext();
const motionRef = useMotionForwardedRef();

baseState.root.ref = useMergedRefs(baseState.root.ref, nodeRef, motionRef);

return {
...baseState,
icon: slot.optional(props.icon, {
renderByDefault: true,
elementType: 'div',
defaultProps: { children: getIntentIcon(baseState.intent) },
}),
shape,
transitionClassName,
};
};

/**
* Base hook for MessageBar component, manages state and structure common to all variants of MessageBar
*
* @param props - base props from this instance of MessageBar
* @param ref - reference to root HTMLElement of MessageBar
*/
export const useMessageBarBase_unstable = (
props: MessageBarBaseProps,
ref: React.Ref<HTMLDivElement>,
): MessageBarBaseState => {
const { layout = 'auto', politeness, bottomReflowSpacer, icon, intent = 'info', ...rest } = props;
const autoReflow = layout === 'auto';
const { ref: reflowRef, reflowing } = useMessageBarReflow(autoReflow);

const computedPoliteness = politeness ?? (intent === 'info' ? 'polite' : 'assertive');
const computedLayout = autoReflow ? (reflowing ? 'multiline' : 'singleline') : layout;

const actionsRef = React.useRef<HTMLDivElement | null>(null);
const bodyRef = React.useRef<HTMLDivElement | null>(null);
const { announce } = useAnnounce();
Expand All @@ -49,30 +80,25 @@ export const useMessageBar_unstable = (props: MessageBarProps, ref: React.Ref<HT
bottomReflowSpacer: 'div',
},
root: slot.always(
getIntrinsicElementProps('div', {
ref: useMergedRefs(ref, reflowRef, nodeRef, motionRef),
{
ref: useMergedRefs(ref, reflowRef),
role: 'group',
'aria-labelledby': titleId,
...props,
}),
...rest,
},
{ elementType: 'div' },
),

icon: slot.optional(props.icon, {
renderByDefault: true,
icon: slot.optional(icon, {
elementType: 'div',
defaultProps: { children: getIntentIcon(intent) },
}),
bottomReflowSpacer: slot.optional(props.bottomReflowSpacer, {
bottomReflowSpacer: slot.optional(bottomReflowSpacer, {
renderByDefault: computedLayout === 'multiline',
elementType: 'div',
}),
layout: computedLayout,
intent,
transitionClassName,
actionsRef,
bodyRef,
titleId,
shape,
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ export type MessageBarActionsContextValues = {
*/
export type MessageBarActionsProps = ComponentProps<MessageBarActionsSlots>;

/**
* MessageBarActions base props
*/
export type MessageBarActionsBaseProps = MessageBarActionsProps;

/**
* State used in rendering MessageBarActions
*/
Expand All @@ -29,3 +34,8 @@ export type MessageBarActionsState = ComponentState<MessageBarActionsSlots> &
*/
hasActions: boolean;
};

/**
* MessageBarActions base state
*/
export type MessageBarActionsBaseState = MessageBarActionsState;
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
export { MessageBarActions } from './MessageBarActions';
export type {
MessageBarActionsBaseProps,
MessageBarActionsBaseState,
MessageBarActionsContextValues,
MessageBarActionsProps,
MessageBarActionsSlots,
MessageBarActionsState,
} from './MessageBarActions.types';
export { renderMessageBarActions_unstable } from './renderMessageBarActions';
export { useMessageBarActions_unstable } from './useMessageBarActions';
export { useMessageBarActions_unstable, useMessageBarActionsBase_unstable } from './useMessageBarActions';
export { messageBarActionsClassNames, useMessageBarActionsStyles_unstable } from './useMessageBarActionsStyles.styles';
export { useMessageBarActionsContextValue_unstable } from './useMessageBarActionsContextValues';
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@

import * as React from 'react';
import { getIntrinsicElementProps, slot, useMergedRefs } from '@fluentui/react-utilities';
import type { MessageBarActionsProps, MessageBarActionsState } from './MessageBarActions.types';
import type {
MessageBarActionsProps,
MessageBarActionsState,
MessageBarActionsBaseProps,
MessageBarActionsBaseState,
} from './MessageBarActions.types';
import { useMessageBarContext } from '../../contexts/messageBarContext';

/**
Expand All @@ -18,6 +23,19 @@ export const useMessageBarActions_unstable = (
props: MessageBarActionsProps,
ref: React.Ref<HTMLDivElement>,
): MessageBarActionsState => {
return useMessageBarActionsBase_unstable(props, ref);
};

/**
* Base hook for MessageBarActions component, manages state and structure common to all variants of MessageBarActions
*
* @param props - base props from this instance of MessageBarActions
* @param ref - reference to root HTMLElement of MessageBarActions
*/
export const useMessageBarActionsBase_unstable = (
props: MessageBarActionsBaseProps,
ref?: React.Ref<HTMLDivElement>,
): MessageBarActionsBaseState => {
const { layout = 'singleline', actionsRef } = useMessageBarContext();
return {
components: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,17 @@ export type MessageBarBodySlots = {
*/
export type MessageBarBodyProps = ComponentProps<MessageBarBodySlots>;

/**
* MessageBarBody base props
*/
export type MessageBarBodyBaseProps = ComponentProps<MessageBarBodySlots>;

/**
* State used in rendering MessageBarBody
*/
export type MessageBarBodyState = ComponentState<MessageBarBodySlots>;

/**
* MessageBarBody base state
*/
export type MessageBarBodyBaseState = ComponentState<MessageBarBodySlots>;
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
export { MessageBarBody } from './MessageBarBody';
export type {
MessageBarBodyBaseProps,
MessageBarBodyBaseState,
MessageBarBodyContextValues,
MessageBarBodyProps,
MessageBarBodySlots,
MessageBarBodyState,
} from './MessageBarBody.types';
export { renderMessageBarBody_unstable } from './renderMessageBarBody';
export { useMessageBarBody_unstable } from './useMessageBarBody';
export { useMessageBarBody_unstable, useMessageBarBodyBase_unstable } from './useMessageBarBody';
export { messageBarBodyClassNames, useMessageBarBodyStyles_unstable } from './useMessageBarBodyStyles.styles';
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
'use client';

import * as React from 'react';
import { getIntrinsicElementProps, slot, useMergedRefs } from '@fluentui/react-utilities';
import type { MessageBarBodyProps, MessageBarBodyState } from './MessageBarBody.types';
import { slot, useMergedRefs } from '@fluentui/react-utilities';
import type {
MessageBarBodyProps,
MessageBarBodyState,
MessageBarBodyBaseProps,
MessageBarBodyBaseState,
} from './MessageBarBody.types';
import { useMessageBarContext } from '../../contexts/messageBarContext';

/**
Expand All @@ -18,16 +23,29 @@ export const useMessageBarBody_unstable = (
props: MessageBarBodyProps,
ref: React.Ref<HTMLDivElement>,
): MessageBarBodyState => {
return useMessageBarBodyBase_unstable(props, ref);
};

/**
* Base hook for MessageBarBody component, manages state and structure common to all variants of MessageBarBody
*
* @param props - base props from this instance of MessageBarBody
* @param ref - reference to root HTMLElement of MessageBarBody
*/
export const useMessageBarBodyBase_unstable = (
props: MessageBarBodyBaseProps,
ref?: React.Ref<HTMLDivElement>,
): MessageBarBodyBaseState => {
const { bodyRef } = useMessageBarContext();
return {
components: {
root: 'div',
},
root: slot.always(
getIntrinsicElementProps('div', {
{
ref: useMergedRefs(ref, bodyRef),
...props,
}),
},
{ elementType: 'div' },
),
};
Expand Down
Loading