Skip to content
Open
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 @@
{
"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