From 102759cf8a2a9a49b14e847be2d21f19a70fc76c Mon Sep 17 00:00:00 2001 From: Lingfan Gao Date: Wed, 27 Sep 2023 09:06:54 +0000 Subject: [PATCH 01/13] feat: Initial implementation Adds an initial implementation of MessageBar that includes design for different intents and multiline handling. --- .../etc/react-message-bar-preview.api.md | 61 ++++++++ .../react-message-bar-preview/package.json | 2 + .../src/MessageBar.ts | 1 + .../src/MessageBarTitle.ts | 1 + .../components/MessageBar/MessageBar.test.tsx | 18 +++ .../src/components/MessageBar/MessageBar.tsx | 18 +++ .../components/MessageBar/MessageBar.types.ts | 23 +++ .../components/MessageBar/getIntentIcon.tsx | 19 +++ .../src/components/MessageBar/index.ts | 5 + .../MessageBar/renderMessageBar.tsx | 34 ++++ .../components/MessageBar/useMessageBar.ts | 45 ++++++ .../MessageBar/useMessageBarStyles.styles.ts | 146 ++++++++++++++++++ .../MessageBarTitle/MessageBarTitle.test.tsx | 18 +++ .../MessageBarTitle/MessageBarTitle.tsx | 18 +++ .../MessageBarTitle/MessageBarTitle.types.ts | 17 ++ .../src/components/MessageBarTitle/index.ts | 5 + .../MessageBarTitle/renderMessageBarTitle.tsx | 19 +++ .../MessageBarTitle/useMessageBarTitle.ts | 30 ++++ .../useMessageBarTitleStyles.styles.ts | 28 ++++ .../react-message-bar-preview/src/index.ts | 18 ++- .../stories/MessageBar/Default.stories.tsx | 30 ++++ .../MessageBar/MessageBarBestPractices.md | 5 + .../MessageBar/MessageBarDescription.md | 0 .../stories/MessageBar/Multiline.stories.tsx | 31 ++++ .../stories/MessageBar/index.stories.tsx | 19 +++ 25 files changed, 610 insertions(+), 1 deletion(-) create mode 100644 packages/react-components/react-message-bar-preview/src/MessageBar.ts create mode 100644 packages/react-components/react-message-bar-preview/src/MessageBarTitle.ts create mode 100644 packages/react-components/react-message-bar-preview/src/components/MessageBar/MessageBar.test.tsx create mode 100644 packages/react-components/react-message-bar-preview/src/components/MessageBar/MessageBar.tsx create mode 100644 packages/react-components/react-message-bar-preview/src/components/MessageBar/MessageBar.types.ts create mode 100644 packages/react-components/react-message-bar-preview/src/components/MessageBar/getIntentIcon.tsx create mode 100644 packages/react-components/react-message-bar-preview/src/components/MessageBar/index.ts create mode 100644 packages/react-components/react-message-bar-preview/src/components/MessageBar/renderMessageBar.tsx create mode 100644 packages/react-components/react-message-bar-preview/src/components/MessageBar/useMessageBar.ts create mode 100644 packages/react-components/react-message-bar-preview/src/components/MessageBar/useMessageBarStyles.styles.ts create mode 100644 packages/react-components/react-message-bar-preview/src/components/MessageBarTitle/MessageBarTitle.test.tsx create mode 100644 packages/react-components/react-message-bar-preview/src/components/MessageBarTitle/MessageBarTitle.tsx create mode 100644 packages/react-components/react-message-bar-preview/src/components/MessageBarTitle/MessageBarTitle.types.ts create mode 100644 packages/react-components/react-message-bar-preview/src/components/MessageBarTitle/index.ts create mode 100644 packages/react-components/react-message-bar-preview/src/components/MessageBarTitle/renderMessageBarTitle.tsx create mode 100644 packages/react-components/react-message-bar-preview/src/components/MessageBarTitle/useMessageBarTitle.ts create mode 100644 packages/react-components/react-message-bar-preview/src/components/MessageBarTitle/useMessageBarTitleStyles.styles.ts create mode 100644 packages/react-components/react-message-bar-preview/stories/MessageBar/Default.stories.tsx create mode 100644 packages/react-components/react-message-bar-preview/stories/MessageBar/MessageBarBestPractices.md create mode 100644 packages/react-components/react-message-bar-preview/stories/MessageBar/MessageBarDescription.md create mode 100644 packages/react-components/react-message-bar-preview/stories/MessageBar/Multiline.stories.tsx create mode 100644 packages/react-components/react-message-bar-preview/stories/MessageBar/index.stories.tsx diff --git a/packages/react-components/react-message-bar-preview/etc/react-message-bar-preview.api.md b/packages/react-components/react-message-bar-preview/etc/react-message-bar-preview.api.md index e4cc48f2a1684a..3ce4d5291f10bd 100644 --- a/packages/react-components/react-message-bar-preview/etc/react-message-bar-preview.api.md +++ b/packages/react-components/react-message-bar-preview/etc/react-message-bar-preview.api.md @@ -4,6 +4,67 @@ ```ts +/// + +import type { ComponentProps } from '@fluentui/react-utilities'; +import type { ComponentState } from '@fluentui/react-utilities'; +import type { ForwardRefComponent } from '@fluentui/react-utilities'; +import * as React_2 from 'react'; +import type { Slot } from '@fluentui/react-utilities'; + +// @public +export const MessageBar: ForwardRefComponent; + +// @public +export type MessageBarProps = ComponentProps & { + multiline?: boolean; + intent?: 'info' | 'success' | 'warning' | 'error'; +}; + +// @public (undocumented) +export type MessageBarSlots = { + root: Slot<'div'>; + icon?: Slot<'div'>; + action?: Slot<'div'>; + actions?: Slot<'div'>; + body?: Slot<'div'>; +}; + +// @public +export type MessageBarState = ComponentState & Required>; + +// @public +export const MessageBarTitle: ForwardRefComponent; + +// @public +export type MessageBarTitleProps = ComponentProps & {}; + +// @public (undocumented) +export type MessageBarTitleSlots = { + root: Slot<'span'>; +}; + +// @public +export type MessageBarTitleState = ComponentState; + +// @public +export const renderMessageBar_unstable: (state: MessageBarState) => JSX.Element; + +// @public +export const renderMessageBarTitle_unstable: (state: MessageBarTitleState) => JSX.Element; + +// @public +export const useMessageBar_unstable: (props: MessageBarProps, ref: React_2.Ref) => MessageBarState; + +// @public +export const useMessageBarStyles_unstable: (state: MessageBarState) => MessageBarState; + +// @public +export const useMessageBarTitle_unstable: (props: MessageBarTitleProps, ref: React_2.Ref) => MessageBarTitleState; + +// @public +export const useMessageBarTitleStyles_unstable: (state: MessageBarTitleState) => MessageBarTitleState; + // (No @packageDocumentation comment for this package) ``` diff --git a/packages/react-components/react-message-bar-preview/package.json b/packages/react-components/react-message-bar-preview/package.json index b851ab73ce4442..f5b63f244d7164 100644 --- a/packages/react-components/react-message-bar-preview/package.json +++ b/packages/react-components/react-message-bar-preview/package.json @@ -31,6 +31,8 @@ "@fluentui/scripts-tasks": "*" }, "dependencies": { + "@fluentui/react-button": "^9.3.41", + "@fluentui/react-icons": "^2.0.217", "@fluentui/react-jsx-runtime": "^9.0.10", "@fluentui/react-theme": "^9.1.12", "@fluentui/react-utilities": "^9.13.3", diff --git a/packages/react-components/react-message-bar-preview/src/MessageBar.ts b/packages/react-components/react-message-bar-preview/src/MessageBar.ts new file mode 100644 index 00000000000000..380da827afeaa7 --- /dev/null +++ b/packages/react-components/react-message-bar-preview/src/MessageBar.ts @@ -0,0 +1 @@ +export * from './components/MessageBar/index'; diff --git a/packages/react-components/react-message-bar-preview/src/MessageBarTitle.ts b/packages/react-components/react-message-bar-preview/src/MessageBarTitle.ts new file mode 100644 index 00000000000000..e570c6fb916dfc --- /dev/null +++ b/packages/react-components/react-message-bar-preview/src/MessageBarTitle.ts @@ -0,0 +1 @@ +export * from './components/MessageBarTitle/index'; diff --git a/packages/react-components/react-message-bar-preview/src/components/MessageBar/MessageBar.test.tsx b/packages/react-components/react-message-bar-preview/src/components/MessageBar/MessageBar.test.tsx new file mode 100644 index 00000000000000..f38c1f1c33ea8d --- /dev/null +++ b/packages/react-components/react-message-bar-preview/src/components/MessageBar/MessageBar.test.tsx @@ -0,0 +1,18 @@ +import * as React from 'react'; +import { render } from '@testing-library/react'; +import { isConformant } from '../../testing/isConformant'; +import { MessageBar } from './MessageBar'; + +describe('MessageBar', () => { + isConformant({ + Component: MessageBar, + displayName: 'MessageBar', + }); + + // TODO add more tests here, and create visual regression tests in /apps/vr-tests + + it('renders a default state', () => { + const result = render(Default MessageBar); + expect(result.container).toMatchSnapshot(); + }); +}); diff --git a/packages/react-components/react-message-bar-preview/src/components/MessageBar/MessageBar.tsx b/packages/react-components/react-message-bar-preview/src/components/MessageBar/MessageBar.tsx new file mode 100644 index 00000000000000..c6e3220bc668a1 --- /dev/null +++ b/packages/react-components/react-message-bar-preview/src/components/MessageBar/MessageBar.tsx @@ -0,0 +1,18 @@ +import * as React from 'react'; +import type { ForwardRefComponent } from '@fluentui/react-utilities'; +import { useMessageBar_unstable } from './useMessageBar'; +import { renderMessageBar_unstable } from './renderMessageBar'; +import { useMessageBarStyles_unstable } from './useMessageBarStyles.styles'; +import type { MessageBarProps } from './MessageBar.types'; + +/** + * MessageBar component - TODO: add more docs + */ +export const MessageBar: ForwardRefComponent = React.forwardRef((props, ref) => { + const state = useMessageBar_unstable(props, ref); + + useMessageBarStyles_unstable(state); + return renderMessageBar_unstable(state); +}); + +MessageBar.displayName = 'MessageBar'; diff --git a/packages/react-components/react-message-bar-preview/src/components/MessageBar/MessageBar.types.ts b/packages/react-components/react-message-bar-preview/src/components/MessageBar/MessageBar.types.ts new file mode 100644 index 00000000000000..91c379989667d1 --- /dev/null +++ b/packages/react-components/react-message-bar-preview/src/components/MessageBar/MessageBar.types.ts @@ -0,0 +1,23 @@ +import type { ComponentProps, ComponentState, Slot } from '@fluentui/react-utilities'; + +export type MessageBarSlots = { + root: Slot<'div'>; + icon?: Slot<'div'>; + action?: Slot<'div'>; + actions?: Slot<'div'>; + body?: Slot<'div'>; +}; + +/** + * MessageBar Props + */ +export type MessageBarProps = ComponentProps & { + multiline?: boolean; + intent?: 'info' | 'success' | 'warning' | 'error'; +}; + +/** + * State used in rendering MessageBar + */ +export type MessageBarState = ComponentState & + Required>; diff --git a/packages/react-components/react-message-bar-preview/src/components/MessageBar/getIntentIcon.tsx b/packages/react-components/react-message-bar-preview/src/components/MessageBar/getIntentIcon.tsx new file mode 100644 index 00000000000000..8b8f345ce332f7 --- /dev/null +++ b/packages/react-components/react-message-bar-preview/src/components/MessageBar/getIntentIcon.tsx @@ -0,0 +1,19 @@ +import * as React from 'react'; +import { MessageBarProps } from './MessageBar.types'; +import { CheckmarkCircleFilled, InfoFilled, WarningFilled, ErrorCircleFilled } from '@fluentui/react-icons'; + +export function getIntentIcon(intent: MessageBarProps['intent']) { + switch (intent) { + case 'info': + return ; + case 'warning': + return ; + case 'error': + return ; + case 'success': + return ; + + default: + return null; + } +} diff --git a/packages/react-components/react-message-bar-preview/src/components/MessageBar/index.ts b/packages/react-components/react-message-bar-preview/src/components/MessageBar/index.ts new file mode 100644 index 00000000000000..1b87b685202c52 --- /dev/null +++ b/packages/react-components/react-message-bar-preview/src/components/MessageBar/index.ts @@ -0,0 +1,5 @@ +export * from './MessageBar'; +export * from './MessageBar.types'; +export * from './renderMessageBar'; +export * from './useMessageBar'; +export * from './useMessageBarStyles.styles'; diff --git a/packages/react-components/react-message-bar-preview/src/components/MessageBar/renderMessageBar.tsx b/packages/react-components/react-message-bar-preview/src/components/MessageBar/renderMessageBar.tsx new file mode 100644 index 00000000000000..f2a797861eae66 --- /dev/null +++ b/packages/react-components/react-message-bar-preview/src/components/MessageBar/renderMessageBar.tsx @@ -0,0 +1,34 @@ +/** @jsxRuntime automatic */ +/** @jsxImportSource @fluentui/react-jsx-runtime */ + +import { assertSlots } from '@fluentui/react-utilities'; +import type { MessageBarState, MessageBarSlots } from './MessageBar.types'; +import { ButtonContextProvider } from '@fluentui/react-button'; + +/** + * Render the final JSX of MessageBar + */ +export const renderMessageBar_unstable = (state: MessageBarState) => { + assertSlots(state); + + return ( + + {state.icon && } + + + {state.multiline ? ( + <> + {state.action && } + {state.actions && } + + ) : ( + <> + {state.actions && } + {state.actions && } + {state.action && } + + )} + + + ); +}; diff --git a/packages/react-components/react-message-bar-preview/src/components/MessageBar/useMessageBar.ts b/packages/react-components/react-message-bar-preview/src/components/MessageBar/useMessageBar.ts new file mode 100644 index 00000000000000..7554edad43e2bd --- /dev/null +++ b/packages/react-components/react-message-bar-preview/src/components/MessageBar/useMessageBar.ts @@ -0,0 +1,45 @@ +import * as React from 'react'; +import { getNativeElementProps, slot } from '@fluentui/react-utilities'; +import type { MessageBarProps, MessageBarState } from './MessageBar.types'; +import { getIntentIcon } from './getIntentIcon'; + +/** + * Create the state required to render MessageBar. + * + * The returned state can be modified with hooks such as useMessageBarStyles_unstable, + * before being passed to renderMessageBar_unstable. + * + * @param props - props from this instance of MessageBar + * @param ref - reference to root HTMLElement of MessageBar + */ +export const useMessageBar_unstable = (props: MessageBarProps, ref: React.Ref): MessageBarState => { + const { multiline = false, intent = 'info' } = props; + + return { + components: { + root: 'div', + icon: 'div', + action: 'div', + actions: 'div', + body: 'div', + }, + root: slot.always( + getNativeElementProps('div', { + ref, + ...props, + }), + { elementType: 'div' }, + ), + + body: slot.always(props.body ?? {}, { elementType: 'div', defaultProps: { children: props.children } }), + icon: slot.optional(props.icon, { + renderByDefault: true, + elementType: 'div', + defaultProps: { children: getIntentIcon(intent) }, + }), + action: slot.optional(props.action, { renderByDefault: false, elementType: 'div' }), + actions: slot.optional(props.actions, { renderByDefault: false, elementType: 'div' }), + multiline, + intent, + }; +}; diff --git a/packages/react-components/react-message-bar-preview/src/components/MessageBar/useMessageBarStyles.styles.ts b/packages/react-components/react-message-bar-preview/src/components/MessageBar/useMessageBarStyles.styles.ts new file mode 100644 index 00000000000000..caa767c1847f42 --- /dev/null +++ b/packages/react-components/react-message-bar-preview/src/components/MessageBar/useMessageBarStyles.styles.ts @@ -0,0 +1,146 @@ +import { makeResetStyles, makeStyles, mergeClasses, shorthands } from '@griffel/react'; +import { tokens, typographyStyles } from '@fluentui/react-theme'; +import type { SlotClassNames } from '@fluentui/react-utilities'; +import type { MessageBarSlots, MessageBarState } from './MessageBar.types'; + +export const messageBarClassNames: SlotClassNames = { + root: 'fui-MessageBar', + icon: 'fui-MessageBar__icon', + action: 'fui-MessageBar__action', + actions: 'fui-MessageBar__actions', + body: 'fui-MessageBar__body', +}; + +const useRootBaseStyles = makeResetStyles({ + display: 'grid', + gridTemplateColumns: 'auto 1fr auto auto', + gridTemplateAreas: '"icon body actions action"', + ...shorthands.padding('0', tokens.spacingHorizontalM), + ...shorthands.border(tokens.strokeWidthThin, 'solid', tokens.colorNeutralStroke1), + ...shorthands.borderRadius(tokens.borderRadiusMedium), + alignItems: 'center', + minHeight: '36px', + boxSizing: 'border-box', + backgroundColor: tokens.colorNeutralBackground3, +}); + +const useIconBaseStyles = makeResetStyles({ + ...shorthands.gridArea('icon'), + fontSize: tokens.fontSizeBase500, + marginRight: tokens.spacingHorizontalS, + color: tokens.colorNeutralForeground3, +}); + +const useActionBaseStyles = makeResetStyles({ + ...shorthands.gridArea('action'), +}); + +const useActionsBaseStyles = makeResetStyles({ + ...shorthands.gridArea('actions'), + display: 'flex', + alignItems: 'center', + columnGap: tokens.spacingHorizontalM, + marginRight: tokens.spacingHorizontalM, +}); + +const useBodyBaseStyles = makeResetStyles({ + ...typographyStyles.body1, + ...shorthands.gridArea('body'), +}); + +const useMultilineStyles = makeStyles({ + rootMultiline: { + paddingTop: tokens.spacingVerticalMNudge, + gridTemplateColumns: 'auto 1fr auto', + gridTemplateAreas: ` + "icon body action" + "actions actions actions" + `, + }, + + actionsMultiline: { + justifyContent: 'end', + marginTop: tokens.spacingVerticalMNudge, + marginBottom: tokens.spacingVerticalS, + }, +}); + +const useIconIntentStyles = makeStyles({ + info: { + /** already in base reset styles */ + }, + error: { + color: tokens.colorStatusDangerForeground1, + }, + warning: { + color: tokens.colorStatusWarningForeground3, + }, + success: { + color: tokens.colorStatusSuccessForeground1, + }, +}); + +const useRootIntentStyles = makeStyles({ + info: { + /** already in base reset styles */ + }, + error: { + backgroundColor: tokens.colorStatusDangerBackground1, + ...shorthands.borderColor(tokens.colorStatusDangerBorder1), + }, + warning: { + backgroundColor: tokens.colorStatusWarningBackground1, + ...shorthands.borderColor(tokens.colorStatusWarningBorder1), + }, + success: { + backgroundColor: tokens.colorStatusSuccessBackground1, + ...shorthands.borderColor(tokens.colorStatusSuccessBorder1), + }, +}); + +/** + * Apply styling to the MessageBar slots based on the state + */ +export const useMessageBarStyles_unstable = (state: MessageBarState): MessageBarState => { + const rootBaseStyles = useRootBaseStyles(); + const iconBaseStyles = useIconBaseStyles(); + const actionBaseStyles = useActionBaseStyles(); + const actionsBaseStyles = useActionsBaseStyles(); + const bodyBaseStyles = useBodyBaseStyles(); + const multilineStyles = useMultilineStyles(); + const iconIntentStyles = useIconIntentStyles(); + const rootIntntStyles = useRootIntentStyles(); + state.root.className = mergeClasses( + messageBarClassNames.root, + rootBaseStyles, + state.multiline && multilineStyles.rootMultiline, + rootIntntStyles[state.intent], + state.root.className, + ); + + state.body.className = mergeClasses(messageBarClassNames.body, bodyBaseStyles, state.body.className); + + if (state.icon) { + state.icon.className = mergeClasses( + messageBarClassNames.icon, + iconBaseStyles, + iconIntentStyles[state.intent], + state.icon.className, + ); + } + + if (state.action) { + state.action.className = mergeClasses(messageBarClassNames.actions, actionBaseStyles, state.action.className); + } + + if (state.actions) { + state.actions.className = mergeClasses( + messageBarClassNames.action, + actionsBaseStyles, + state.multiline && multilineStyles.actionsMultiline, + state.actions.className, + ); + } + + return state; +}; diff --git a/packages/react-components/react-message-bar-preview/src/components/MessageBarTitle/MessageBarTitle.test.tsx b/packages/react-components/react-message-bar-preview/src/components/MessageBarTitle/MessageBarTitle.test.tsx new file mode 100644 index 00000000000000..c34b6a2446dbc4 --- /dev/null +++ b/packages/react-components/react-message-bar-preview/src/components/MessageBarTitle/MessageBarTitle.test.tsx @@ -0,0 +1,18 @@ +import * as React from 'react'; +import { render } from '@testing-library/react'; +import { isConformant } from '../../testing/isConformant'; +import { MessageBarTitle } from './MessageBarTitle'; + +describe('MessageBarTitle', () => { + isConformant({ + Component: MessageBarTitle, + displayName: 'MessageBarTitle', + }); + + // TODO add more tests here, and create visual regression tests in /apps/vr-tests + + it('renders a default state', () => { + const result = render(Default MessageBarTitle); + expect(result.container).toMatchSnapshot(); + }); +}); diff --git a/packages/react-components/react-message-bar-preview/src/components/MessageBarTitle/MessageBarTitle.tsx b/packages/react-components/react-message-bar-preview/src/components/MessageBarTitle/MessageBarTitle.tsx new file mode 100644 index 00000000000000..a6a12e84462ae1 --- /dev/null +++ b/packages/react-components/react-message-bar-preview/src/components/MessageBarTitle/MessageBarTitle.tsx @@ -0,0 +1,18 @@ +import * as React from 'react'; +import type { ForwardRefComponent } from '@fluentui/react-utilities'; +import { useMessageBarTitle_unstable } from './useMessageBarTitle'; +import { renderMessageBarTitle_unstable } from './renderMessageBarTitle'; +import { useMessageBarTitleStyles_unstable } from './useMessageBarTitleStyles.styles'; +import type { MessageBarTitleProps } from './MessageBarTitle.types'; + +/** + * MessageBarTitle component - TODO: add more docs + */ +export const MessageBarTitle: ForwardRefComponent = React.forwardRef((props, ref) => { + const state = useMessageBarTitle_unstable(props, ref); + + useMessageBarTitleStyles_unstable(state); + return renderMessageBarTitle_unstable(state); +}); + +MessageBarTitle.displayName = 'MessageBarTitle'; diff --git a/packages/react-components/react-message-bar-preview/src/components/MessageBarTitle/MessageBarTitle.types.ts b/packages/react-components/react-message-bar-preview/src/components/MessageBarTitle/MessageBarTitle.types.ts new file mode 100644 index 00000000000000..89818edb55afcd --- /dev/null +++ b/packages/react-components/react-message-bar-preview/src/components/MessageBarTitle/MessageBarTitle.types.ts @@ -0,0 +1,17 @@ +import type { ComponentProps, ComponentState, Slot } from '@fluentui/react-utilities'; + +export type MessageBarTitleSlots = { + root: Slot<'span'>; +}; + +/** + * MessageBarTitle Props + */ +export type MessageBarTitleProps = ComponentProps & {}; + +/** + * State used in rendering MessageBarTitle + */ +export type MessageBarTitleState = ComponentState; +// TODO: Remove semicolon from previous line, uncomment next line, and provide union of props to pick from MessageBarTitleProps. +// & Required> diff --git a/packages/react-components/react-message-bar-preview/src/components/MessageBarTitle/index.ts b/packages/react-components/react-message-bar-preview/src/components/MessageBarTitle/index.ts new file mode 100644 index 00000000000000..4bcb0e7df960b4 --- /dev/null +++ b/packages/react-components/react-message-bar-preview/src/components/MessageBarTitle/index.ts @@ -0,0 +1,5 @@ +export * from './MessageBarTitle'; +export * from './MessageBarTitle.types'; +export * from './renderMessageBarTitle'; +export * from './useMessageBarTitle'; +export * from './useMessageBarTitleStyles.styles'; diff --git a/packages/react-components/react-message-bar-preview/src/components/MessageBarTitle/renderMessageBarTitle.tsx b/packages/react-components/react-message-bar-preview/src/components/MessageBarTitle/renderMessageBarTitle.tsx new file mode 100644 index 00000000000000..6b008739d5dcb6 --- /dev/null +++ b/packages/react-components/react-message-bar-preview/src/components/MessageBarTitle/renderMessageBarTitle.tsx @@ -0,0 +1,19 @@ +/** @jsxRuntime automatic */ +/** @jsxImportSource @fluentui/react-jsx-runtime */ + +import { assertSlots } from '@fluentui/react-utilities'; +import type { MessageBarTitleState, MessageBarTitleSlots } from './MessageBarTitle.types'; + +/** + * Render the final JSX of MessageBarTitle + */ +export const renderMessageBarTitle_unstable = (state: MessageBarTitleState) => { + assertSlots(state); + + // TODO Add additional slots in the appropriate place + return ( + <> + + + ); +}; diff --git a/packages/react-components/react-message-bar-preview/src/components/MessageBarTitle/useMessageBarTitle.ts b/packages/react-components/react-message-bar-preview/src/components/MessageBarTitle/useMessageBarTitle.ts new file mode 100644 index 00000000000000..ffa1883ffdb0c2 --- /dev/null +++ b/packages/react-components/react-message-bar-preview/src/components/MessageBarTitle/useMessageBarTitle.ts @@ -0,0 +1,30 @@ +import * as React from 'react'; +import { getNativeElementProps, slot } from '@fluentui/react-utilities'; +import type { MessageBarTitleProps, MessageBarTitleState } from './MessageBarTitle.types'; + +/** + * Create the state required to render MessageBarTitle. + * + * The returned state can be modified with hooks such as useMessageBarTitleStyles_unstable, + * before being passed to renderMessageBarTitle_unstable. + * + * @param props - props from this instance of MessageBarTitle + * @param ref - reference to root HTMLElement of MessageBarTitle + */ +export const useMessageBarTitle_unstable = ( + props: MessageBarTitleProps, + ref: React.Ref, +): MessageBarTitleState => { + return { + components: { + root: 'span', + }, + root: slot.always( + getNativeElementProps('span', { + ref, + ...props, + }), + { elementType: 'div' }, + ), + }; +}; diff --git a/packages/react-components/react-message-bar-preview/src/components/MessageBarTitle/useMessageBarTitleStyles.styles.ts b/packages/react-components/react-message-bar-preview/src/components/MessageBarTitle/useMessageBarTitleStyles.styles.ts new file mode 100644 index 00000000000000..7bc54ff127ac82 --- /dev/null +++ b/packages/react-components/react-message-bar-preview/src/components/MessageBarTitle/useMessageBarTitleStyles.styles.ts @@ -0,0 +1,28 @@ +import { makeResetStyles, mergeClasses } from '@griffel/react'; +import { typographyStyles } from '@fluentui/react-theme'; +import type { SlotClassNames } from '@fluentui/react-utilities'; +import type { MessageBarTitleSlots, MessageBarTitleState } from './MessageBarTitle.types'; + +export const messageBarTitleClassNames: SlotClassNames = { + root: 'fui-MessageBarTitle', +}; + +/** + * Styles for the root slot + */ +const useRootBaseStyles = makeResetStyles({ + ...typographyStyles.body1Strong, + '::after': { + content: '" "', + }, +}); + +/** + * Apply styling to the MessageBarTitle slots based on the state + */ +export const useMessageBarTitleStyles_unstable = (state: MessageBarTitleState): MessageBarTitleState => { + const rootBaseStyles = useRootBaseStyles(); + state.root.className = mergeClasses(messageBarTitleClassNames.root, rootBaseStyles, state.root.className); + + return state; +}; diff --git a/packages/react-components/react-message-bar-preview/src/index.ts b/packages/react-components/react-message-bar-preview/src/index.ts index cb0ff5c3b541f6..7ad8a189cf2adb 100644 --- a/packages/react-components/react-message-bar-preview/src/index.ts +++ b/packages/react-components/react-message-bar-preview/src/index.ts @@ -1 +1,17 @@ -export {}; +export { + MessageBar, + useMessageBarStyles_unstable, + useMessageBar_unstable, + renderMessageBar_unstable, +} from './MessageBar'; + +export type { MessageBarProps, MessageBarSlots, MessageBarState } from './MessageBar'; + +export { + MessageBarTitle, + useMessageBarTitleStyles_unstable, + useMessageBarTitle_unstable, + renderMessageBarTitle_unstable, +} from './MessageBarTitle'; + +export type { MessageBarTitleProps, MessageBarTitleSlots, MessageBarTitleState } from './MessageBarTitle'; diff --git a/packages/react-components/react-message-bar-preview/stories/MessageBar/Default.stories.tsx b/packages/react-components/react-message-bar-preview/stories/MessageBar/Default.stories.tsx new file mode 100644 index 00000000000000..3d242f41433910 --- /dev/null +++ b/packages/react-components/react-message-bar-preview/stories/MessageBar/Default.stories.tsx @@ -0,0 +1,30 @@ +import * as React from 'react'; +import { Button, Link } from '@fluentui/react-components'; +import { DismissRegular } from '@fluentui/react-icons'; +import { MessageBar, MessageBarTitle } from '@fluentui/react-message-bar-preview'; + +const intents = ['info', 'warning', 'error', 'success'] as const; + +export const Default = () => ( + <> + {intents.map(intent => ( + <> + } appearance="transparent" />} + actions={ + <> + + + + } + > + Descriptive title + Message providing information to the user with actionable insights. Link + +
+ + ))} + +); diff --git a/packages/react-components/react-message-bar-preview/stories/MessageBar/MessageBarBestPractices.md b/packages/react-components/react-message-bar-preview/stories/MessageBar/MessageBarBestPractices.md new file mode 100644 index 00000000000000..08ff8ddeeb5f86 --- /dev/null +++ b/packages/react-components/react-message-bar-preview/stories/MessageBar/MessageBarBestPractices.md @@ -0,0 +1,5 @@ +## Best practices + +### Do + +### Don't diff --git a/packages/react-components/react-message-bar-preview/stories/MessageBar/MessageBarDescription.md b/packages/react-components/react-message-bar-preview/stories/MessageBar/MessageBarDescription.md new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/packages/react-components/react-message-bar-preview/stories/MessageBar/Multiline.stories.tsx b/packages/react-components/react-message-bar-preview/stories/MessageBar/Multiline.stories.tsx new file mode 100644 index 00000000000000..a5c6a4b711c5c1 --- /dev/null +++ b/packages/react-components/react-message-bar-preview/stories/MessageBar/Multiline.stories.tsx @@ -0,0 +1,31 @@ +import * as React from 'react'; +import { Button, Link } from '@fluentui/react-components'; +import { DismissRegular } from '@fluentui/react-icons'; +import { MessageBar, MessageBarTitle } from '@fluentui/react-message-bar-preview'; + +const intents = ['info', 'warning', 'error', 'success'] as const; + +export const Multiline = () => ( + <> + {intents.map(intent => ( + <> + } appearance="transparent" />} + actions={ + <> + + + + } + > + Descriptive title + Message providing information to the user with actionable insights. Link + +
+ + ))} + +); diff --git a/packages/react-components/react-message-bar-preview/stories/MessageBar/index.stories.tsx b/packages/react-components/react-message-bar-preview/stories/MessageBar/index.stories.tsx new file mode 100644 index 00000000000000..e5af5995d3206a --- /dev/null +++ b/packages/react-components/react-message-bar-preview/stories/MessageBar/index.stories.tsx @@ -0,0 +1,19 @@ +import { MessageBar } from '@fluentui/react-message-bar-preview'; + +import descriptionMd from './MessageBarDescription.md'; +import bestPracticesMd from './MessageBarBestPractices.md'; + +export { Default } from './Default.stories'; +export { Multiline } from './Multiline.stories'; + +export default { + title: 'Preview Components/MessageBar', + component: MessageBar, + parameters: { + docs: { + description: { + component: [descriptionMd, bestPracticesMd].join('\n'), + }, + }, + }, +}; From a75a53607e1445e797be7ad82b0b45fab348c062 Mon Sep 17 00:00:00 2001 From: Lingfan Gao Date: Wed, 27 Sep 2023 09:10:33 +0000 Subject: [PATCH 02/13] remove TODOs --- .../src/components/MessageBar/MessageBar.tsx | 2 +- .../src/components/MessageBarTitle/MessageBarTitle.tsx | 2 +- .../src/components/MessageBarTitle/MessageBarTitle.types.ts | 2 -- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/react-components/react-message-bar-preview/src/components/MessageBar/MessageBar.tsx b/packages/react-components/react-message-bar-preview/src/components/MessageBar/MessageBar.tsx index c6e3220bc668a1..b5904b078f1eda 100644 --- a/packages/react-components/react-message-bar-preview/src/components/MessageBar/MessageBar.tsx +++ b/packages/react-components/react-message-bar-preview/src/components/MessageBar/MessageBar.tsx @@ -6,7 +6,7 @@ import { useMessageBarStyles_unstable } from './useMessageBarStyles.styles'; import type { MessageBarProps } from './MessageBar.types'; /** - * MessageBar component - TODO: add more docs + * MessageBar component */ export const MessageBar: ForwardRefComponent = React.forwardRef((props, ref) => { const state = useMessageBar_unstable(props, ref); diff --git a/packages/react-components/react-message-bar-preview/src/components/MessageBarTitle/MessageBarTitle.tsx b/packages/react-components/react-message-bar-preview/src/components/MessageBarTitle/MessageBarTitle.tsx index a6a12e84462ae1..6ce8533ca2ec6d 100644 --- a/packages/react-components/react-message-bar-preview/src/components/MessageBarTitle/MessageBarTitle.tsx +++ b/packages/react-components/react-message-bar-preview/src/components/MessageBarTitle/MessageBarTitle.tsx @@ -6,7 +6,7 @@ import { useMessageBarTitleStyles_unstable } from './useMessageBarTitleStyles.st import type { MessageBarTitleProps } from './MessageBarTitle.types'; /** - * MessageBarTitle component - TODO: add more docs + * MessageBarTitle component */ export const MessageBarTitle: ForwardRefComponent = React.forwardRef((props, ref) => { const state = useMessageBarTitle_unstable(props, ref); diff --git a/packages/react-components/react-message-bar-preview/src/components/MessageBarTitle/MessageBarTitle.types.ts b/packages/react-components/react-message-bar-preview/src/components/MessageBarTitle/MessageBarTitle.types.ts index 89818edb55afcd..d966942d2b9fd0 100644 --- a/packages/react-components/react-message-bar-preview/src/components/MessageBarTitle/MessageBarTitle.types.ts +++ b/packages/react-components/react-message-bar-preview/src/components/MessageBarTitle/MessageBarTitle.types.ts @@ -13,5 +13,3 @@ export type MessageBarTitleProps = ComponentProps & {}; * State used in rendering MessageBarTitle */ export type MessageBarTitleState = ComponentState; -// TODO: Remove semicolon from previous line, uncomment next line, and provide union of props to pick from MessageBarTitleProps. -// & Required> From aeacd98f784cf81b88edac769a1ad8f8f4603a7d Mon Sep 17 00:00:00 2001 From: Lingfan Gao Date: Wed, 27 Sep 2023 10:19:21 +0000 Subject: [PATCH 03/13] fix multiline alignment --- .../src/components/MessageBar/useMessageBarStyles.styles.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/react-components/react-message-bar-preview/src/components/MessageBar/useMessageBarStyles.styles.ts b/packages/react-components/react-message-bar-preview/src/components/MessageBar/useMessageBarStyles.styles.ts index caa767c1847f42..2ee6d443d6f274 100644 --- a/packages/react-components/react-message-bar-preview/src/components/MessageBar/useMessageBarStyles.styles.ts +++ b/packages/react-components/react-message-bar-preview/src/components/MessageBar/useMessageBarStyles.styles.ts @@ -62,6 +62,7 @@ const useMultilineStyles = makeStyles({ justifyContent: 'end', marginTop: tokens.spacingVerticalMNudge, marginBottom: tokens.spacingVerticalS, + marginRight: '0px', }, }); From cf9c216f439c053088169ac4c8b23add1246493d Mon Sep 17 00:00:00 2001 From: Lingfan Gao Date: Wed, 27 Sep 2023 10:20:44 +0000 Subject: [PATCH 04/13] fix slot type misalign --- .../__snapshots__/MessageBar.test.tsx.snap | 33 +++++++++++++++++++ .../MessageBarTitle.test.tsx.snap | 11 +++++++ .../MessageBarTitle/useMessageBarTitle.ts | 2 +- 3 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 packages/react-components/react-message-bar-preview/src/components/MessageBar/__snapshots__/MessageBar.test.tsx.snap create mode 100644 packages/react-components/react-message-bar-preview/src/components/MessageBarTitle/__snapshots__/MessageBarTitle.test.tsx.snap diff --git a/packages/react-components/react-message-bar-preview/src/components/MessageBar/__snapshots__/MessageBar.test.tsx.snap b/packages/react-components/react-message-bar-preview/src/components/MessageBar/__snapshots__/MessageBar.test.tsx.snap new file mode 100644 index 00000000000000..8faf50e88bf662 --- /dev/null +++ b/packages/react-components/react-message-bar-preview/src/components/MessageBar/__snapshots__/MessageBar.test.tsx.snap @@ -0,0 +1,33 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`MessageBar renders a default state 1`] = ` +
+
+
+ +
+
+ Default MessageBar +
+
+
+`; diff --git a/packages/react-components/react-message-bar-preview/src/components/MessageBarTitle/__snapshots__/MessageBarTitle.test.tsx.snap b/packages/react-components/react-message-bar-preview/src/components/MessageBarTitle/__snapshots__/MessageBarTitle.test.tsx.snap new file mode 100644 index 00000000000000..8d96636aac25ed --- /dev/null +++ b/packages/react-components/react-message-bar-preview/src/components/MessageBarTitle/__snapshots__/MessageBarTitle.test.tsx.snap @@ -0,0 +1,11 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`MessageBarTitle renders a default state 1`] = ` +
+ + Default MessageBarTitle + +
+`; diff --git a/packages/react-components/react-message-bar-preview/src/components/MessageBarTitle/useMessageBarTitle.ts b/packages/react-components/react-message-bar-preview/src/components/MessageBarTitle/useMessageBarTitle.ts index ffa1883ffdb0c2..87329b8eba4884 100644 --- a/packages/react-components/react-message-bar-preview/src/components/MessageBarTitle/useMessageBarTitle.ts +++ b/packages/react-components/react-message-bar-preview/src/components/MessageBarTitle/useMessageBarTitle.ts @@ -24,7 +24,7 @@ export const useMessageBarTitle_unstable = ( ref, ...props, }), - { elementType: 'div' }, + { elementType: 'span' }, ), }; }; From b48228337759b8f49acbdb17293e0f38d3bb4ab9 Mon Sep 17 00:00:00 2001 From: Lingfan Gao Date: Wed, 27 Sep 2023 10:22:50 +0000 Subject: [PATCH 05/13] fix tests --- .../src/components/MessageBar/MessageBar.test.tsx | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/packages/react-components/react-message-bar-preview/src/components/MessageBar/MessageBar.test.tsx b/packages/react-components/react-message-bar-preview/src/components/MessageBar/MessageBar.test.tsx index f38c1f1c33ea8d..3e25240e5f343e 100644 --- a/packages/react-components/react-message-bar-preview/src/components/MessageBar/MessageBar.test.tsx +++ b/packages/react-components/react-message-bar-preview/src/components/MessageBar/MessageBar.test.tsx @@ -7,6 +7,17 @@ describe('MessageBar', () => { isConformant({ Component: MessageBar, displayName: 'MessageBar', + testOptions: { + 'has-static-classnames': [ + { + props: { + icon: 'Icon', + actions: 'Actions', + action: 'Action', + }, + }, + ], + }, }); // TODO add more tests here, and create visual regression tests in /apps/vr-tests From 91ffc5e975dc101f18415f8b5625b9a637963493 Mon Sep 17 00:00:00 2001 From: Lingfan Gao Date: Wed, 27 Sep 2023 10:29:47 +0000 Subject: [PATCH 06/13] rename to secondaryActions --- .../etc/react-message-bar-preview.api.md | 9 ++++- .../components/MessageBar/MessageBar.test.tsx | 2 +- .../components/MessageBar/MessageBar.types.ts | 2 +- .../MessageBar/renderMessageBar.tsx | 6 ++-- .../components/MessageBar/useMessageBar.ts | 4 +-- .../MessageBar/useMessageBarStyles.styles.ts | 36 ++++++++++--------- .../react-message-bar-preview/src/index.ts | 2 ++ .../stories/MessageBar/Default.stories.tsx | 4 +-- .../stories/MessageBar/Multiline.stories.tsx | 4 +-- 9 files changed, 41 insertions(+), 28 deletions(-) diff --git a/packages/react-components/react-message-bar-preview/etc/react-message-bar-preview.api.md b/packages/react-components/react-message-bar-preview/etc/react-message-bar-preview.api.md index 3ce4d5291f10bd..c173c5e695e47d 100644 --- a/packages/react-components/react-message-bar-preview/etc/react-message-bar-preview.api.md +++ b/packages/react-components/react-message-bar-preview/etc/react-message-bar-preview.api.md @@ -11,10 +11,14 @@ import type { ComponentState } from '@fluentui/react-utilities'; import type { ForwardRefComponent } from '@fluentui/react-utilities'; import * as React_2 from 'react'; import type { Slot } from '@fluentui/react-utilities'; +import type { SlotClassNames } from '@fluentui/react-utilities'; // @public export const MessageBar: ForwardRefComponent; +// @public (undocumented) +export const messageBarClassNames: SlotClassNames; + // @public export type MessageBarProps = ComponentProps & { multiline?: boolean; @@ -25,8 +29,8 @@ export type MessageBarProps = ComponentProps & { export type MessageBarSlots = { root: Slot<'div'>; icon?: Slot<'div'>; - action?: Slot<'div'>; actions?: Slot<'div'>; + secondaryActions?: Slot<'div'>; body?: Slot<'div'>; }; @@ -36,6 +40,9 @@ export type MessageBarState = ComponentState & Required; +// @public (undocumented) +export const messageBarTitleClassNames: SlotClassNames; + // @public export type MessageBarTitleProps = ComponentProps & {}; diff --git a/packages/react-components/react-message-bar-preview/src/components/MessageBar/MessageBar.test.tsx b/packages/react-components/react-message-bar-preview/src/components/MessageBar/MessageBar.test.tsx index 3e25240e5f343e..8cbf1e49df3801 100644 --- a/packages/react-components/react-message-bar-preview/src/components/MessageBar/MessageBar.test.tsx +++ b/packages/react-components/react-message-bar-preview/src/components/MessageBar/MessageBar.test.tsx @@ -13,7 +13,7 @@ describe('MessageBar', () => { props: { icon: 'Icon', actions: 'Actions', - action: 'Action', + secondaryActions: 'Actions', }, }, ], diff --git a/packages/react-components/react-message-bar-preview/src/components/MessageBar/MessageBar.types.ts b/packages/react-components/react-message-bar-preview/src/components/MessageBar/MessageBar.types.ts index 91c379989667d1..403e7d401b775a 100644 --- a/packages/react-components/react-message-bar-preview/src/components/MessageBar/MessageBar.types.ts +++ b/packages/react-components/react-message-bar-preview/src/components/MessageBar/MessageBar.types.ts @@ -3,8 +3,8 @@ import type { ComponentProps, ComponentState, Slot } from '@fluentui/react-utili export type MessageBarSlots = { root: Slot<'div'>; icon?: Slot<'div'>; - action?: Slot<'div'>; actions?: Slot<'div'>; + secondaryActions?: Slot<'div'>; body?: Slot<'div'>; }; diff --git a/packages/react-components/react-message-bar-preview/src/components/MessageBar/renderMessageBar.tsx b/packages/react-components/react-message-bar-preview/src/components/MessageBar/renderMessageBar.tsx index f2a797861eae66..54aef7d271c07d 100644 --- a/packages/react-components/react-message-bar-preview/src/components/MessageBar/renderMessageBar.tsx +++ b/packages/react-components/react-message-bar-preview/src/components/MessageBar/renderMessageBar.tsx @@ -18,14 +18,14 @@ export const renderMessageBar_unstable = (state: MessageBarState) => { {state.multiline ? ( <> - {state.action && } {state.actions && } + {state.secondaryActions && } ) : ( <> + {state.secondaryActions && } + {state.secondaryActions && } {state.actions && } - {state.actions && } - {state.action && } )} diff --git a/packages/react-components/react-message-bar-preview/src/components/MessageBar/useMessageBar.ts b/packages/react-components/react-message-bar-preview/src/components/MessageBar/useMessageBar.ts index 7554edad43e2bd..371b2668757487 100644 --- a/packages/react-components/react-message-bar-preview/src/components/MessageBar/useMessageBar.ts +++ b/packages/react-components/react-message-bar-preview/src/components/MessageBar/useMessageBar.ts @@ -19,8 +19,8 @@ export const useMessageBar_unstable = (props: MessageBarProps, ref: React.Ref = { root: 'fui-MessageBar', icon: 'fui-MessageBar__icon', - action: 'fui-MessageBar__action', actions: 'fui-MessageBar__actions', + secondaryActions: 'fui-MessageBar__secondaryActions', body: 'fui-MessageBar__body', }; const useRootBaseStyles = makeResetStyles({ display: 'grid', gridTemplateColumns: 'auto 1fr auto auto', - gridTemplateAreas: '"icon body actions action"', + gridTemplateAreas: '"icon body secondaryActions actions"', ...shorthands.padding('0', tokens.spacingHorizontalM), ...shorthands.border(tokens.strokeWidthThin, 'solid', tokens.colorNeutralStroke1), ...shorthands.borderRadius(tokens.borderRadiusMedium), @@ -32,11 +32,11 @@ const useIconBaseStyles = makeResetStyles({ }); const useActionBaseStyles = makeResetStyles({ - ...shorthands.gridArea('action'), + ...shorthands.gridArea('actions'), }); -const useActionsBaseStyles = makeResetStyles({ - ...shorthands.gridArea('actions'), +const useSecondaryActionsBaseStyles = makeResetStyles({ + ...shorthands.gridArea('secondaryActions'), display: 'flex', alignItems: 'center', columnGap: tokens.spacingHorizontalM, @@ -53,12 +53,12 @@ const useMultilineStyles = makeStyles({ paddingTop: tokens.spacingVerticalMNudge, gridTemplateColumns: 'auto 1fr auto', gridTemplateAreas: ` - "icon body action" - "actions actions actions" + "icon body actions" + "secondaryActions secondaryActions secondaryActions" `, }, - actionsMultiline: { + secondaryActionsMultiline: { justifyContent: 'end', marginTop: tokens.spacingVerticalMNudge, marginBottom: tokens.spacingVerticalS, @@ -105,8 +105,8 @@ const useRootIntentStyles = makeStyles({ export const useMessageBarStyles_unstable = (state: MessageBarState): MessageBarState => { const rootBaseStyles = useRootBaseStyles(); const iconBaseStyles = useIconBaseStyles(); - const actionBaseStyles = useActionBaseStyles(); - const actionsBaseStyles = useActionsBaseStyles(); + const actionsBaseStyles = useActionBaseStyles(); + const secondaryActionsBaseStyles = useSecondaryActionsBaseStyles(); const bodyBaseStyles = useBodyBaseStyles(); const multilineStyles = useMultilineStyles(); const iconIntentStyles = useIconIntentStyles(); @@ -130,18 +130,22 @@ export const useMessageBarStyles_unstable = (state: MessageBarState): MessageBar ); } - if (state.action) { - state.action.className = mergeClasses(messageBarClassNames.actions, actionBaseStyles, state.action.className); - } - if (state.actions) { state.actions.className = mergeClasses( - messageBarClassNames.action, + messageBarClassNames.secondaryActions, actionsBaseStyles, - state.multiline && multilineStyles.actionsMultiline, state.actions.className, ); } + if (state.secondaryActions) { + state.secondaryActions.className = mergeClasses( + messageBarClassNames.actions, + secondaryActionsBaseStyles, + state.multiline && multilineStyles.secondaryActionsMultiline, + state.secondaryActions.className, + ); + } + return state; }; diff --git a/packages/react-components/react-message-bar-preview/src/index.ts b/packages/react-components/react-message-bar-preview/src/index.ts index 7ad8a189cf2adb..63270882f450bd 100644 --- a/packages/react-components/react-message-bar-preview/src/index.ts +++ b/packages/react-components/react-message-bar-preview/src/index.ts @@ -3,6 +3,7 @@ export { useMessageBarStyles_unstable, useMessageBar_unstable, renderMessageBar_unstable, + messageBarClassNames, } from './MessageBar'; export type { MessageBarProps, MessageBarSlots, MessageBarState } from './MessageBar'; @@ -12,6 +13,7 @@ export { useMessageBarTitleStyles_unstable, useMessageBarTitle_unstable, renderMessageBarTitle_unstable, + messageBarTitleClassNames, } from './MessageBarTitle'; export type { MessageBarTitleProps, MessageBarTitleSlots, MessageBarTitleState } from './MessageBarTitle'; diff --git a/packages/react-components/react-message-bar-preview/stories/MessageBar/Default.stories.tsx b/packages/react-components/react-message-bar-preview/stories/MessageBar/Default.stories.tsx index 3d242f41433910..d9836f03727186 100644 --- a/packages/react-components/react-message-bar-preview/stories/MessageBar/Default.stories.tsx +++ b/packages/react-components/react-message-bar-preview/stories/MessageBar/Default.stories.tsx @@ -12,8 +12,8 @@ export const Default = () => ( } appearance="transparent" />} - actions={ + actions={ diff --git a/packages/react-components/react-message-bar-preview/stories/MessageBar/Multiline.stories.tsx b/packages/react-components/react-message-bar-preview/stories/MessageBar/Multiline.stories.tsx index a5c6a4b711c5c1..02947f4c8b40b3 100644 --- a/packages/react-components/react-message-bar-preview/stories/MessageBar/Multiline.stories.tsx +++ b/packages/react-components/react-message-bar-preview/stories/MessageBar/Multiline.stories.tsx @@ -13,8 +13,8 @@ export const Multiline = () => ( key={intent} multiline intent={intent} - action={ From 824404fc8bd8e6a66544664e4fb45131eda95fe3 Mon Sep 17 00:00:00 2001 From: Lingfan Gao Date: Wed, 27 Sep 2023 10:57:53 +0000 Subject: [PATCH 07/13] fix warnings --- .../stories/MessageBar/Default.stories.tsx | 35 ++++++++---------- .../stories/MessageBar/Multiline.stories.tsx | 37 +++++++++---------- 2 files changed, 33 insertions(+), 39 deletions(-) diff --git a/packages/react-components/react-message-bar-preview/stories/MessageBar/Default.stories.tsx b/packages/react-components/react-message-bar-preview/stories/MessageBar/Default.stories.tsx index d9836f03727186..496bddf697502f 100644 --- a/packages/react-components/react-message-bar-preview/stories/MessageBar/Default.stories.tsx +++ b/packages/react-components/react-message-bar-preview/stories/MessageBar/Default.stories.tsx @@ -6,25 +6,22 @@ import { MessageBar, MessageBarTitle } from '@fluentui/react-message-bar-preview const intents = ['info', 'warning', 'error', 'success'] as const; export const Default = () => ( - <> +
{intents.map(intent => ( - <> - } appearance="transparent" />} - secondaryActions={ - <> - - - - } - > - Descriptive title - Message providing information to the user with actionable insights. Link - -
- + } appearance="transparent" />} + secondaryActions={ + <> + + + + } + > + Descriptive title + Message providing information to the user with actionable insights. Link + ))} - +
); diff --git a/packages/react-components/react-message-bar-preview/stories/MessageBar/Multiline.stories.tsx b/packages/react-components/react-message-bar-preview/stories/MessageBar/Multiline.stories.tsx index 02947f4c8b40b3..4e448316ff2a41 100644 --- a/packages/react-components/react-message-bar-preview/stories/MessageBar/Multiline.stories.tsx +++ b/packages/react-components/react-message-bar-preview/stories/MessageBar/Multiline.stories.tsx @@ -6,26 +6,23 @@ import { MessageBar, MessageBarTitle } from '@fluentui/react-message-bar-preview const intents = ['info', 'warning', 'error', 'success'] as const; export const Multiline = () => ( - <> +
{intents.map(intent => ( - <> - } appearance="transparent" />} - secondaryActions={ - <> - - - - } - > - Descriptive title - Message providing information to the user with actionable insights. Link - -
- + } appearance="transparent" />} + secondaryActions={ + <> + + + + } + > + Descriptive title + Message providing information to the user with actionable insights. Link + ))} - +
); From dbc31451b8c28b195d33e53066ec373fa8bd1543 Mon Sep 17 00:00:00 2001 From: Lingfan Gao Date: Wed, 27 Sep 2023 15:47:09 +0000 Subject: [PATCH 08/13] break out into components --- .../etc/react-message-bar-preview.api.md | 73 +++++++++++++++++-- .../src/MessageBarActions.ts | 1 + .../src/MessageBarBody.ts | 1 + .../components/MessageBar/MessageBar.test.tsx | 2 - .../src/components/MessageBar/MessageBar.tsx | 3 +- .../components/MessageBar/MessageBar.types.ts | 20 ++--- .../__snapshots__/MessageBar.test.tsx.snap | 6 +- .../MessageBar/renderMessageBar.tsx | 30 +++----- .../components/MessageBar/useMessageBar.ts | 10 +-- .../MessageBar/useMessageBarContextValues.ts | 17 +++++ .../MessageBar/useMessageBarStyles.styles.ts | 46 +----------- .../MessageBarActions.test.tsx | 23 ++++++ .../MessageBarActions/MessageBarActions.tsx | 18 +++++ .../MessageBarActions.types.ts | 18 +++++ .../MessageBarActions.test.tsx.snap | 11 +++ .../src/components/MessageBarActions/index.ts | 5 ++ .../renderMessageBarActions.tsx | 28 +++++++ .../MessageBarActions/useMessageBarActions.ts | 35 +++++++++ .../useMessageBarActionsStyles.styles.ts | 58 +++++++++++++++ .../MessageBarBody/MessageBarBody.test.tsx | 16 ++++ .../MessageBarBody/MessageBarBody.tsx | 18 +++++ .../MessageBarBody/MessageBarBody.types.ts | 15 ++++ .../MessageBarBody.test.tsx.snap | 11 +++ .../src/components/MessageBarBody/index.ts | 5 ++ .../MessageBarBody/renderMessageBarBody.tsx | 14 ++++ .../MessageBarBody/useMessageBarBody.ts | 30 ++++++++ .../useMessageBarBodyStyles.styles.ts | 23 ++++++ .../src/contexts/messageBarContext.ts | 13 ++++ .../react-message-bar-preview/src/index.ts | 23 ++++++ .../stories/MessageBar/Default.stories.tsx | 24 +++--- .../stories/MessageBar/Multiline.stories.tsx | 25 +++---- .../MessageBarActionsBestPractices.md | 5 ++ .../MessageBarActionsDefault.stories.tsx | 4 + .../MessageBarActionsDescription.md | 0 .../MessageBarActions/index.stories.tsx | 18 +++++ .../MessageBarBodyBestPractices.md | 5 ++ .../MessageBarBodyDefault.stories.tsx | 4 + .../MessageBarBodyDescription.md | 0 .../stories/MessageBarBody/index.stories.tsx | 18 +++++ .../tsconfig.lib.json | 2 +- 40 files changed, 552 insertions(+), 126 deletions(-) create mode 100644 packages/react-components/react-message-bar-preview/src/MessageBarActions.ts create mode 100644 packages/react-components/react-message-bar-preview/src/MessageBarBody.ts create mode 100644 packages/react-components/react-message-bar-preview/src/components/MessageBar/useMessageBarContextValues.ts create mode 100644 packages/react-components/react-message-bar-preview/src/components/MessageBarActions/MessageBarActions.test.tsx create mode 100644 packages/react-components/react-message-bar-preview/src/components/MessageBarActions/MessageBarActions.tsx create mode 100644 packages/react-components/react-message-bar-preview/src/components/MessageBarActions/MessageBarActions.types.ts create mode 100644 packages/react-components/react-message-bar-preview/src/components/MessageBarActions/__snapshots__/MessageBarActions.test.tsx.snap create mode 100644 packages/react-components/react-message-bar-preview/src/components/MessageBarActions/index.ts create mode 100644 packages/react-components/react-message-bar-preview/src/components/MessageBarActions/renderMessageBarActions.tsx create mode 100644 packages/react-components/react-message-bar-preview/src/components/MessageBarActions/useMessageBarActions.ts create mode 100644 packages/react-components/react-message-bar-preview/src/components/MessageBarActions/useMessageBarActionsStyles.styles.ts create mode 100644 packages/react-components/react-message-bar-preview/src/components/MessageBarBody/MessageBarBody.test.tsx create mode 100644 packages/react-components/react-message-bar-preview/src/components/MessageBarBody/MessageBarBody.tsx create mode 100644 packages/react-components/react-message-bar-preview/src/components/MessageBarBody/MessageBarBody.types.ts create mode 100644 packages/react-components/react-message-bar-preview/src/components/MessageBarBody/__snapshots__/MessageBarBody.test.tsx.snap create mode 100644 packages/react-components/react-message-bar-preview/src/components/MessageBarBody/index.ts create mode 100644 packages/react-components/react-message-bar-preview/src/components/MessageBarBody/renderMessageBarBody.tsx create mode 100644 packages/react-components/react-message-bar-preview/src/components/MessageBarBody/useMessageBarBody.ts create mode 100644 packages/react-components/react-message-bar-preview/src/components/MessageBarBody/useMessageBarBodyStyles.styles.ts create mode 100644 packages/react-components/react-message-bar-preview/src/contexts/messageBarContext.ts create mode 100644 packages/react-components/react-message-bar-preview/stories/MessageBarActions/MessageBarActionsBestPractices.md create mode 100644 packages/react-components/react-message-bar-preview/stories/MessageBarActions/MessageBarActionsDefault.stories.tsx create mode 100644 packages/react-components/react-message-bar-preview/stories/MessageBarActions/MessageBarActionsDescription.md create mode 100644 packages/react-components/react-message-bar-preview/stories/MessageBarActions/index.stories.tsx create mode 100644 packages/react-components/react-message-bar-preview/stories/MessageBarBody/MessageBarBodyBestPractices.md create mode 100644 packages/react-components/react-message-bar-preview/stories/MessageBarBody/MessageBarBodyDefault.stories.tsx create mode 100644 packages/react-components/react-message-bar-preview/stories/MessageBarBody/MessageBarBodyDescription.md create mode 100644 packages/react-components/react-message-bar-preview/stories/MessageBarBody/index.stories.tsx diff --git a/packages/react-components/react-message-bar-preview/etc/react-message-bar-preview.api.md b/packages/react-components/react-message-bar-preview/etc/react-message-bar-preview.api.md index c173c5e695e47d..6c00a5ed41093a 100644 --- a/packages/react-components/react-message-bar-preview/etc/react-message-bar-preview.api.md +++ b/packages/react-components/react-message-bar-preview/etc/react-message-bar-preview.api.md @@ -16,11 +16,54 @@ import type { SlotClassNames } from '@fluentui/react-utilities'; // @public export const MessageBar: ForwardRefComponent; +// @public +export const MessageBarActions: ForwardRefComponent; + +// @public (undocumented) +export const messageBarActionsClassNames: SlotClassNames; + +// @public +export type MessageBarActionsProps = ComponentProps & {}; + +// @public (undocumented) +export type MessageBarActionsSlots = { + root: Slot<'div'>; + containerAction?: Slot<'div'>; +}; + +// @public +export type MessageBarActionsState = ComponentState & Pick, 'layout'>; + +// @public +export const MessageBarBody: ForwardRefComponent; + +// @public (undocumented) +export const messageBarBodyClassNames: SlotClassNames; + +// @public +export type MessageBarBodyProps = ComponentProps & {}; + +// @public (undocumented) +export type MessageBarBodySlots = { + root: Slot<'div'>; +}; + +// @public +export type MessageBarBodyState = ComponentState; + // @public (undocumented) export const messageBarClassNames: SlotClassNames; +// @public (undocumented) +export const MessageBarContextProvider: React_2.Provider; + +// @public (undocumented) +export type MessageBarContextValue = { + layout?: 'multiline' | 'singleline'; +}; + // @public -export type MessageBarProps = ComponentProps & { +export type MessageBarProps = ComponentProps & Pick & { multiline?: boolean; intent?: 'info' | 'success' | 'warning' | 'error'; }; @@ -29,13 +72,10 @@ export type MessageBarProps = ComponentProps & { export type MessageBarSlots = { root: Slot<'div'>; icon?: Slot<'div'>; - actions?: Slot<'div'>; - secondaryActions?: Slot<'div'>; - body?: Slot<'div'>; }; // @public -export type MessageBarState = ComponentState & Required>; +export type MessageBarState = ComponentState & Required>; // @public export const MessageBarTitle: ForwardRefComponent; @@ -55,7 +95,13 @@ export type MessageBarTitleSlots = { export type MessageBarTitleState = ComponentState; // @public -export const renderMessageBar_unstable: (state: MessageBarState) => JSX.Element; +export const renderMessageBar_unstable: (state: MessageBarState, contexts: MessageBarContextValues) => JSX.Element; + +// @public +export const renderMessageBarActions_unstable: (state: MessageBarActionsState) => JSX.Element; + +// @public +export const renderMessageBarBody_unstable: (state: MessageBarBodyState) => JSX.Element; // @public export const renderMessageBarTitle_unstable: (state: MessageBarTitleState) => JSX.Element; @@ -63,6 +109,21 @@ export const renderMessageBarTitle_unstable: (state: MessageBarTitleState) => JS // @public export const useMessageBar_unstable: (props: MessageBarProps, ref: React_2.Ref) => MessageBarState; +// @public +export const useMessageBarActions_unstable: (props: MessageBarActionsProps, ref: React_2.Ref) => MessageBarActionsState; + +// @public +export const useMessageBarActionsStyles_unstable: (state: MessageBarActionsState) => MessageBarActionsState; + +// @public +export const useMessageBarBody_unstable: (props: MessageBarBodyProps, ref: React_2.Ref) => MessageBarBodyState; + +// @public +export const useMessageBarBodyStyles_unstable: (state: MessageBarBodyState) => MessageBarBodyState; + +// @public (undocumented) +export const useMessageBarContext: () => MessageBarContextValue; + // @public export const useMessageBarStyles_unstable: (state: MessageBarState) => MessageBarState; diff --git a/packages/react-components/react-message-bar-preview/src/MessageBarActions.ts b/packages/react-components/react-message-bar-preview/src/MessageBarActions.ts new file mode 100644 index 00000000000000..7ab9044a3ee734 --- /dev/null +++ b/packages/react-components/react-message-bar-preview/src/MessageBarActions.ts @@ -0,0 +1 @@ +export * from './components/MessageBarActions/index'; diff --git a/packages/react-components/react-message-bar-preview/src/MessageBarBody.ts b/packages/react-components/react-message-bar-preview/src/MessageBarBody.ts new file mode 100644 index 00000000000000..dc59e16a3e414b --- /dev/null +++ b/packages/react-components/react-message-bar-preview/src/MessageBarBody.ts @@ -0,0 +1 @@ +export * from './components/MessageBarBody/index'; diff --git a/packages/react-components/react-message-bar-preview/src/components/MessageBar/MessageBar.test.tsx b/packages/react-components/react-message-bar-preview/src/components/MessageBar/MessageBar.test.tsx index 8cbf1e49df3801..ca8524d34d7bb5 100644 --- a/packages/react-components/react-message-bar-preview/src/components/MessageBar/MessageBar.test.tsx +++ b/packages/react-components/react-message-bar-preview/src/components/MessageBar/MessageBar.test.tsx @@ -12,8 +12,6 @@ describe('MessageBar', () => { { props: { icon: 'Icon', - actions: 'Actions', - secondaryActions: 'Actions', }, }, ], diff --git a/packages/react-components/react-message-bar-preview/src/components/MessageBar/MessageBar.tsx b/packages/react-components/react-message-bar-preview/src/components/MessageBar/MessageBar.tsx index b5904b078f1eda..27f443e9d07bf9 100644 --- a/packages/react-components/react-message-bar-preview/src/components/MessageBar/MessageBar.tsx +++ b/packages/react-components/react-message-bar-preview/src/components/MessageBar/MessageBar.tsx @@ -4,6 +4,7 @@ import { useMessageBar_unstable } from './useMessageBar'; import { renderMessageBar_unstable } from './renderMessageBar'; import { useMessageBarStyles_unstable } from './useMessageBarStyles.styles'; import type { MessageBarProps } from './MessageBar.types'; +import { useMessageBarContextValue_unstable } from './useMessageBarContextValues'; /** * MessageBar component @@ -12,7 +13,7 @@ export const MessageBar: ForwardRefComponent = React.forwardRef const state = useMessageBar_unstable(props, ref); useMessageBarStyles_unstable(state); - return renderMessageBar_unstable(state); + return renderMessageBar_unstable(state, useMessageBarContextValue_unstable(state)); }); MessageBar.displayName = 'MessageBar'; diff --git a/packages/react-components/react-message-bar-preview/src/components/MessageBar/MessageBar.types.ts b/packages/react-components/react-message-bar-preview/src/components/MessageBar/MessageBar.types.ts index 403e7d401b775a..9d0bce2e0aa9ec 100644 --- a/packages/react-components/react-message-bar-preview/src/components/MessageBar/MessageBar.types.ts +++ b/packages/react-components/react-message-bar-preview/src/components/MessageBar/MessageBar.types.ts @@ -1,23 +1,25 @@ import type { ComponentProps, ComponentState, Slot } from '@fluentui/react-utilities'; +import { MessageBarContextValue } from '../../contexts/messageBarContext'; export type MessageBarSlots = { root: Slot<'div'>; icon?: Slot<'div'>; - actions?: Slot<'div'>; - secondaryActions?: Slot<'div'>; - body?: Slot<'div'>; +}; + +export type MessageBarContextValues = { + messageBar: MessageBarContextValue; }; /** * MessageBar Props */ -export type MessageBarProps = ComponentProps & { - multiline?: boolean; - intent?: 'info' | 'success' | 'warning' | 'error'; -}; +export type MessageBarProps = ComponentProps & + Pick & { + multiline?: boolean; + intent?: 'info' | 'success' | 'warning' | 'error'; + }; /** * State used in rendering MessageBar */ -export type MessageBarState = ComponentState & - Required>; +export type MessageBarState = ComponentState & Required>; diff --git a/packages/react-components/react-message-bar-preview/src/components/MessageBar/__snapshots__/MessageBar.test.tsx.snap b/packages/react-components/react-message-bar-preview/src/components/MessageBar/__snapshots__/MessageBar.test.tsx.snap index 8faf50e88bf662..17d8f7e24e3eaa 100644 --- a/packages/react-components/react-message-bar-preview/src/components/MessageBar/__snapshots__/MessageBar.test.tsx.snap +++ b/packages/react-components/react-message-bar-preview/src/components/MessageBar/__snapshots__/MessageBar.test.tsx.snap @@ -23,11 +23,7 @@ exports[`MessageBar renders a default state 1`] = ` /> -
- Default MessageBar -
+ Default MessageBar `; diff --git a/packages/react-components/react-message-bar-preview/src/components/MessageBar/renderMessageBar.tsx b/packages/react-components/react-message-bar-preview/src/components/MessageBar/renderMessageBar.tsx index 54aef7d271c07d..83aa749e3d1eff 100644 --- a/packages/react-components/react-message-bar-preview/src/components/MessageBar/renderMessageBar.tsx +++ b/packages/react-components/react-message-bar-preview/src/components/MessageBar/renderMessageBar.tsx @@ -2,33 +2,21 @@ /** @jsxImportSource @fluentui/react-jsx-runtime */ import { assertSlots } from '@fluentui/react-utilities'; -import type { MessageBarState, MessageBarSlots } from './MessageBar.types'; -import { ButtonContextProvider } from '@fluentui/react-button'; +import type { MessageBarState, MessageBarSlots, MessageBarContextValues } from './MessageBar.types'; +import { MessageBarContextProvider } from '../../contexts/messageBarContext'; /** * Render the final JSX of MessageBar */ -export const renderMessageBar_unstable = (state: MessageBarState) => { +export const renderMessageBar_unstable = (state: MessageBarState, contexts: MessageBarContextValues) => { assertSlots(state); return ( - - {state.icon && } - - - {state.multiline ? ( - <> - {state.actions && } - {state.secondaryActions && } - - ) : ( - <> - {state.secondaryActions && } - {state.secondaryActions && } - {state.actions && } - - )} - - + + + {state.icon && } + {state.root.children} + + ); }; diff --git a/packages/react-components/react-message-bar-preview/src/components/MessageBar/useMessageBar.ts b/packages/react-components/react-message-bar-preview/src/components/MessageBar/useMessageBar.ts index 371b2668757487..b9759360a050d5 100644 --- a/packages/react-components/react-message-bar-preview/src/components/MessageBar/useMessageBar.ts +++ b/packages/react-components/react-message-bar-preview/src/components/MessageBar/useMessageBar.ts @@ -13,15 +13,12 @@ import { getIntentIcon } from './getIntentIcon'; * @param ref - reference to root HTMLElement of MessageBar */ export const useMessageBar_unstable = (props: MessageBarProps, ref: React.Ref): MessageBarState => { - const { multiline = false, intent = 'info' } = props; + const { layout = 'singleline', intent = 'info' } = props; return { components: { root: 'div', icon: 'div', - actions: 'div', - secondaryActions: 'div', - body: 'div', }, root: slot.always( getNativeElementProps('div', { @@ -31,15 +28,12 @@ export const useMessageBar_unstable = (props: MessageBarProps, ref: React.Ref ({ + layout, + }), + [layout], + ); + + return { + messageBar: messageBarContext, + }; +} diff --git a/packages/react-components/react-message-bar-preview/src/components/MessageBar/useMessageBarStyles.styles.ts b/packages/react-components/react-message-bar-preview/src/components/MessageBar/useMessageBarStyles.styles.ts index 520265b62825d4..974c68afba45f8 100644 --- a/packages/react-components/react-message-bar-preview/src/components/MessageBar/useMessageBarStyles.styles.ts +++ b/packages/react-components/react-message-bar-preview/src/components/MessageBar/useMessageBarStyles.styles.ts @@ -1,14 +1,11 @@ import { makeResetStyles, makeStyles, mergeClasses, shorthands } from '@griffel/react'; -import { tokens, typographyStyles } from '@fluentui/react-theme'; +import { tokens } from '@fluentui/react-theme'; import type { SlotClassNames } from '@fluentui/react-utilities'; import type { MessageBarSlots, MessageBarState } from './MessageBar.types'; export const messageBarClassNames: SlotClassNames = { root: 'fui-MessageBar', icon: 'fui-MessageBar__icon', - actions: 'fui-MessageBar__actions', - secondaryActions: 'fui-MessageBar__secondaryActions', - body: 'fui-MessageBar__body', }; const useRootBaseStyles = makeResetStyles({ @@ -31,23 +28,6 @@ const useIconBaseStyles = makeResetStyles({ color: tokens.colorNeutralForeground3, }); -const useActionBaseStyles = makeResetStyles({ - ...shorthands.gridArea('actions'), -}); - -const useSecondaryActionsBaseStyles = makeResetStyles({ - ...shorthands.gridArea('secondaryActions'), - display: 'flex', - alignItems: 'center', - columnGap: tokens.spacingHorizontalM, - marginRight: tokens.spacingHorizontalM, -}); - -const useBodyBaseStyles = makeResetStyles({ - ...typographyStyles.body1, - ...shorthands.gridArea('body'), -}); - const useMultilineStyles = makeStyles({ rootMultiline: { paddingTop: tokens.spacingVerticalMNudge, @@ -105,22 +85,17 @@ const useRootIntentStyles = makeStyles({ export const useMessageBarStyles_unstable = (state: MessageBarState): MessageBarState => { const rootBaseStyles = useRootBaseStyles(); const iconBaseStyles = useIconBaseStyles(); - const actionsBaseStyles = useActionBaseStyles(); - const secondaryActionsBaseStyles = useSecondaryActionsBaseStyles(); - const bodyBaseStyles = useBodyBaseStyles(); const multilineStyles = useMultilineStyles(); const iconIntentStyles = useIconIntentStyles(); const rootIntntStyles = useRootIntentStyles(); state.root.className = mergeClasses( messageBarClassNames.root, rootBaseStyles, - state.multiline && multilineStyles.rootMultiline, + state.layout === 'multiline' && multilineStyles.rootMultiline, rootIntntStyles[state.intent], state.root.className, ); - state.body.className = mergeClasses(messageBarClassNames.body, bodyBaseStyles, state.body.className); - if (state.icon) { state.icon.className = mergeClasses( messageBarClassNames.icon, @@ -130,22 +105,5 @@ export const useMessageBarStyles_unstable = (state: MessageBarState): MessageBar ); } - if (state.actions) { - state.actions.className = mergeClasses( - messageBarClassNames.secondaryActions, - actionsBaseStyles, - state.actions.className, - ); - } - - if (state.secondaryActions) { - state.secondaryActions.className = mergeClasses( - messageBarClassNames.actions, - secondaryActionsBaseStyles, - state.multiline && multilineStyles.secondaryActionsMultiline, - state.secondaryActions.className, - ); - } - return state; }; diff --git a/packages/react-components/react-message-bar-preview/src/components/MessageBarActions/MessageBarActions.test.tsx b/packages/react-components/react-message-bar-preview/src/components/MessageBarActions/MessageBarActions.test.tsx new file mode 100644 index 00000000000000..d62960938f7bae --- /dev/null +++ b/packages/react-components/react-message-bar-preview/src/components/MessageBarActions/MessageBarActions.test.tsx @@ -0,0 +1,23 @@ +import * as React from 'react'; +import { render } from '@testing-library/react'; +import { isConformant } from '../../testing/isConformant'; +import { MessageBarActions } from './MessageBarActions'; +import { MessageBarActionsProps } from './MessageBarActions.types'; + +describe('MessageBarActions', () => { + isConformant({ + Component: MessageBarActions, + displayName: 'MessageBarActions', + disabledTests: [ + // TODO: having problems due to the fact root of DialogTitle is Fragment + 'component-has-static-classnames-object', + ], + }); + + // TODO add more tests here, and create visual regression tests in /apps/vr-tests + + it('renders a default state', () => { + const result = render(Default MessageBarActions); + expect(result.container).toMatchSnapshot(); + }); +}); diff --git a/packages/react-components/react-message-bar-preview/src/components/MessageBarActions/MessageBarActions.tsx b/packages/react-components/react-message-bar-preview/src/components/MessageBarActions/MessageBarActions.tsx new file mode 100644 index 00000000000000..ca28530fe59397 --- /dev/null +++ b/packages/react-components/react-message-bar-preview/src/components/MessageBarActions/MessageBarActions.tsx @@ -0,0 +1,18 @@ +import * as React from 'react'; +import type { ForwardRefComponent } from '@fluentui/react-utilities'; +import { useMessageBarActions_unstable } from './useMessageBarActions'; +import { renderMessageBarActions_unstable } from './renderMessageBarActions'; +import { useMessageBarActionsStyles_unstable } from './useMessageBarActionsStyles.styles'; +import type { MessageBarActionsProps } from './MessageBarActions.types'; + +/** + * MessageBarActions component - TODO: add more docs + */ +export const MessageBarActions: ForwardRefComponent = React.forwardRef((props, ref) => { + const state = useMessageBarActions_unstable(props, ref); + + useMessageBarActionsStyles_unstable(state); + return renderMessageBarActions_unstable(state); +}); + +MessageBarActions.displayName = 'MessageBarActions'; diff --git a/packages/react-components/react-message-bar-preview/src/components/MessageBarActions/MessageBarActions.types.ts b/packages/react-components/react-message-bar-preview/src/components/MessageBarActions/MessageBarActions.types.ts new file mode 100644 index 00000000000000..796972f7bbf8e9 --- /dev/null +++ b/packages/react-components/react-message-bar-preview/src/components/MessageBarActions/MessageBarActions.types.ts @@ -0,0 +1,18 @@ +import type { ComponentProps, ComponentState, Slot } from '@fluentui/react-utilities'; +import { MessageBarContextValue } from '../../contexts/messageBarContext'; + +export type MessageBarActionsSlots = { + root: Slot<'div'>; + containerAction?: Slot<'div'>; +}; + +/** + * MessageBarActions Props + */ +export type MessageBarActionsProps = ComponentProps & {}; + +/** + * State used in rendering MessageBarActions + */ +export type MessageBarActionsState = ComponentState & + Pick, 'layout'>; diff --git a/packages/react-components/react-message-bar-preview/src/components/MessageBarActions/__snapshots__/MessageBarActions.test.tsx.snap b/packages/react-components/react-message-bar-preview/src/components/MessageBarActions/__snapshots__/MessageBarActions.test.tsx.snap new file mode 100644 index 00000000000000..aa2eebdf434aa3 --- /dev/null +++ b/packages/react-components/react-message-bar-preview/src/components/MessageBarActions/__snapshots__/MessageBarActions.test.tsx.snap @@ -0,0 +1,11 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`MessageBarActions renders a default state 1`] = ` +
+
+ Default MessageBarActions +
+
+`; diff --git a/packages/react-components/react-message-bar-preview/src/components/MessageBarActions/index.ts b/packages/react-components/react-message-bar-preview/src/components/MessageBarActions/index.ts new file mode 100644 index 00000000000000..d8ba24f39657b5 --- /dev/null +++ b/packages/react-components/react-message-bar-preview/src/components/MessageBarActions/index.ts @@ -0,0 +1,5 @@ +export * from './MessageBarActions'; +export * from './MessageBarActions.types'; +export * from './renderMessageBarActions'; +export * from './useMessageBarActions'; +export * from './useMessageBarActionsStyles.styles'; diff --git a/packages/react-components/react-message-bar-preview/src/components/MessageBarActions/renderMessageBarActions.tsx b/packages/react-components/react-message-bar-preview/src/components/MessageBarActions/renderMessageBarActions.tsx new file mode 100644 index 00000000000000..15ddc4bf084e33 --- /dev/null +++ b/packages/react-components/react-message-bar-preview/src/components/MessageBarActions/renderMessageBarActions.tsx @@ -0,0 +1,28 @@ +/** @jsxRuntime automatic */ +/** @jsxImportSource @fluentui/react-jsx-runtime */ + +import { assertSlots } from '@fluentui/react-utilities'; +import type { MessageBarActionsState, MessageBarActionsSlots } from './MessageBarActions.types'; +import { ButtonContextProvider } from '@fluentui/react-button'; + +/** + * Render the final JSX of MessageBarActions + */ +export const renderMessageBarActions_unstable = (state: MessageBarActionsState) => { + assertSlots(state); + if (state.layout === 'multiline') { + return ( + + {state.containerAction && } + + + ); + } + + return ( + + + {state.containerAction && } + + ); +}; diff --git a/packages/react-components/react-message-bar-preview/src/components/MessageBarActions/useMessageBarActions.ts b/packages/react-components/react-message-bar-preview/src/components/MessageBarActions/useMessageBarActions.ts new file mode 100644 index 00000000000000..5ccf97a36a7188 --- /dev/null +++ b/packages/react-components/react-message-bar-preview/src/components/MessageBarActions/useMessageBarActions.ts @@ -0,0 +1,35 @@ +import * as React from 'react'; +import { getNativeElementProps, slot } from '@fluentui/react-utilities'; +import type { MessageBarActionsProps, MessageBarActionsState } from './MessageBarActions.types'; +import { useMessageBarContext } from '../../contexts/messageBarContext'; + +/** + * Create the state required to render MessageBarActions. + * + * The returned state can be modified with hooks such as useMessageBarActionsStyles_unstable, + * before being passed to renderMessageBarActions_unstable. + * + * @param props - props from this instance of MessageBarActions + * @param ref - reference to root HTMLElement of MessageBarActions + */ +export const useMessageBarActions_unstable = ( + props: MessageBarActionsProps, + ref: React.Ref, +): MessageBarActionsState => { + const { layout = 'singleline' } = useMessageBarContext(); + return { + components: { + root: 'div', + containerAction: 'div', + }, + containerAction: slot.optional(props.containerAction, { renderByDefault: false, elementType: 'div' }), + root: slot.always( + getNativeElementProps('div', { + ref, + ...props, + }), + { elementType: 'div' }, + ), + layout, + }; +}; diff --git a/packages/react-components/react-message-bar-preview/src/components/MessageBarActions/useMessageBarActionsStyles.styles.ts b/packages/react-components/react-message-bar-preview/src/components/MessageBarActions/useMessageBarActionsStyles.styles.ts new file mode 100644 index 00000000000000..dead8bcab465b9 --- /dev/null +++ b/packages/react-components/react-message-bar-preview/src/components/MessageBarActions/useMessageBarActionsStyles.styles.ts @@ -0,0 +1,58 @@ +import { makeResetStyles, makeStyles, mergeClasses, shorthands } from '@griffel/react'; +import type { SlotClassNames } from '@fluentui/react-utilities'; +import { tokens } from '@fluentui/react-theme'; +import type { MessageBarActionsSlots, MessageBarActionsState } from './MessageBarActions.types'; + +export const messageBarActionsClassNames: SlotClassNames = { + root: 'fui-MessageBarActions', + containerAction: 'fui-MessageBarActions__containerAction', +}; + +/** + * Styles for the root slot + */ +const useRootBaseStyles = makeResetStyles({ + ...shorthands.gridArea('secondaryActions'), + display: 'flex', + alignItems: 'center', + columnGap: tokens.spacingHorizontalM, + marginRight: tokens.spacingHorizontalM, +}); + +const useContainerActionBaseStyles = makeResetStyles({ + ...shorthands.gridArea('actions'), +}); + +const useMultilineStyles = makeStyles({ + root: { + justifyContent: 'end', + marginTop: tokens.spacingVerticalMNudge, + marginBottom: tokens.spacingVerticalS, + marginRight: '0px', + }, +}); + +/** + * Apply styling to the MessageBarActions slots based on the state + */ +export const useMessageBarActionsStyles_unstable = (state: MessageBarActionsState): MessageBarActionsState => { + const rootBaseStyles = useRootBaseStyles(); + const containerActionBaseStyles = useContainerActionBaseStyles(); + const multilineStyles = useMultilineStyles(); + state.root.className = mergeClasses( + messageBarActionsClassNames.root, + rootBaseStyles, + state.layout === 'multiline' && multilineStyles.root, + state.root.className, + ); + + if (state.containerAction) { + state.containerAction.className = mergeClasses( + messageBarActionsClassNames.containerAction, + containerActionBaseStyles, + state.containerAction.className, + ); + } + + return state; +}; diff --git a/packages/react-components/react-message-bar-preview/src/components/MessageBarBody/MessageBarBody.test.tsx b/packages/react-components/react-message-bar-preview/src/components/MessageBarBody/MessageBarBody.test.tsx new file mode 100644 index 00000000000000..b0bc0a9968aa17 --- /dev/null +++ b/packages/react-components/react-message-bar-preview/src/components/MessageBarBody/MessageBarBody.test.tsx @@ -0,0 +1,16 @@ +import * as React from 'react'; +import { render } from '@testing-library/react'; +import { isConformant } from '../../testing/isConformant'; +import { MessageBarBody } from './MessageBarBody'; + +describe('MessageBarBody', () => { + isConformant({ + Component: MessageBarBody, + displayName: 'MessageBarBody', + }); + + it('renders a default state', () => { + const result = render(Default MessageBarBody); + expect(result.container).toMatchSnapshot(); + }); +}); diff --git a/packages/react-components/react-message-bar-preview/src/components/MessageBarBody/MessageBarBody.tsx b/packages/react-components/react-message-bar-preview/src/components/MessageBarBody/MessageBarBody.tsx new file mode 100644 index 00000000000000..21e15ad108048c --- /dev/null +++ b/packages/react-components/react-message-bar-preview/src/components/MessageBarBody/MessageBarBody.tsx @@ -0,0 +1,18 @@ +import * as React from 'react'; +import type { ForwardRefComponent } from '@fluentui/react-utilities'; +import { useMessageBarBody_unstable } from './useMessageBarBody'; +import { renderMessageBarBody_unstable } from './renderMessageBarBody'; +import { useMessageBarBodyStyles_unstable } from './useMessageBarBodyStyles.styles'; +import type { MessageBarBodyProps } from './MessageBarBody.types'; + +/** + * MessageBarBody component + */ +export const MessageBarBody: ForwardRefComponent = React.forwardRef((props, ref) => { + const state = useMessageBarBody_unstable(props, ref); + + useMessageBarBodyStyles_unstable(state); + return renderMessageBarBody_unstable(state); +}); + +MessageBarBody.displayName = 'MessageBarBody'; diff --git a/packages/react-components/react-message-bar-preview/src/components/MessageBarBody/MessageBarBody.types.ts b/packages/react-components/react-message-bar-preview/src/components/MessageBarBody/MessageBarBody.types.ts new file mode 100644 index 00000000000000..f471468f316afb --- /dev/null +++ b/packages/react-components/react-message-bar-preview/src/components/MessageBarBody/MessageBarBody.types.ts @@ -0,0 +1,15 @@ +import type { ComponentProps, ComponentState, Slot } from '@fluentui/react-utilities'; + +export type MessageBarBodySlots = { + root: Slot<'div'>; +}; + +/** + * MessageBarBody Props + */ +export type MessageBarBodyProps = ComponentProps & {}; + +/** + * State used in rendering MessageBarBody + */ +export type MessageBarBodyState = ComponentState; diff --git a/packages/react-components/react-message-bar-preview/src/components/MessageBarBody/__snapshots__/MessageBarBody.test.tsx.snap b/packages/react-components/react-message-bar-preview/src/components/MessageBarBody/__snapshots__/MessageBarBody.test.tsx.snap new file mode 100644 index 00000000000000..4c73379056bad6 --- /dev/null +++ b/packages/react-components/react-message-bar-preview/src/components/MessageBarBody/__snapshots__/MessageBarBody.test.tsx.snap @@ -0,0 +1,11 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`MessageBarBody renders a default state 1`] = ` +
+
+ Default MessageBarBody +
+
+`; diff --git a/packages/react-components/react-message-bar-preview/src/components/MessageBarBody/index.ts b/packages/react-components/react-message-bar-preview/src/components/MessageBarBody/index.ts new file mode 100644 index 00000000000000..360550329c1df0 --- /dev/null +++ b/packages/react-components/react-message-bar-preview/src/components/MessageBarBody/index.ts @@ -0,0 +1,5 @@ +export * from './MessageBarBody'; +export * from './MessageBarBody.types'; +export * from './renderMessageBarBody'; +export * from './useMessageBarBody'; +export * from './useMessageBarBodyStyles.styles'; diff --git a/packages/react-components/react-message-bar-preview/src/components/MessageBarBody/renderMessageBarBody.tsx b/packages/react-components/react-message-bar-preview/src/components/MessageBarBody/renderMessageBarBody.tsx new file mode 100644 index 00000000000000..fa5e80f1b3da25 --- /dev/null +++ b/packages/react-components/react-message-bar-preview/src/components/MessageBarBody/renderMessageBarBody.tsx @@ -0,0 +1,14 @@ +/** @jsxRuntime automatic */ +/** @jsxImportSource @fluentui/react-jsx-runtime */ + +import { assertSlots } from '@fluentui/react-utilities'; +import type { MessageBarBodyState, MessageBarBodySlots } from './MessageBarBody.types'; + +/** + * Render the final JSX of MessageBarBody + */ +export const renderMessageBarBody_unstable = (state: MessageBarBodyState) => { + assertSlots(state); + + return ; +}; diff --git a/packages/react-components/react-message-bar-preview/src/components/MessageBarBody/useMessageBarBody.ts b/packages/react-components/react-message-bar-preview/src/components/MessageBarBody/useMessageBarBody.ts new file mode 100644 index 00000000000000..ed99cf2f18a9bb --- /dev/null +++ b/packages/react-components/react-message-bar-preview/src/components/MessageBarBody/useMessageBarBody.ts @@ -0,0 +1,30 @@ +import * as React from 'react'; +import { getNativeElementProps, slot } from '@fluentui/react-utilities'; +import type { MessageBarBodyProps, MessageBarBodyState } from './MessageBarBody.types'; + +/** + * Create the state required to render MessageBarBody. + * + * The returned state can be modified with hooks such as useMessageBarBodyStyles_unstable, + * before being passed to renderMessageBarBody_unstable. + * + * @param props - props from this instance of MessageBarBody + * @param ref - reference to root HTMLElement of MessageBarBody + */ +export const useMessageBarBody_unstable = ( + props: MessageBarBodyProps, + ref: React.Ref, +): MessageBarBodyState => { + return { + components: { + root: 'div', + }, + root: slot.always( + getNativeElementProps('div', { + ref, + ...props, + }), + { elementType: 'div' }, + ), + }; +}; diff --git a/packages/react-components/react-message-bar-preview/src/components/MessageBarBody/useMessageBarBodyStyles.styles.ts b/packages/react-components/react-message-bar-preview/src/components/MessageBarBody/useMessageBarBodyStyles.styles.ts new file mode 100644 index 00000000000000..1e470a13b0ba1d --- /dev/null +++ b/packages/react-components/react-message-bar-preview/src/components/MessageBarBody/useMessageBarBodyStyles.styles.ts @@ -0,0 +1,23 @@ +import { makeResetStyles, mergeClasses, shorthands } from '@griffel/react'; +import type { SlotClassNames } from '@fluentui/react-utilities'; +import type { MessageBarBodySlots, MessageBarBodyState } from './MessageBarBody.types'; +import { typographyStyles } from '@fluentui/react-theme'; + +export const messageBarBodyClassNames: SlotClassNames = { + root: 'fui-MessageBarBody', +}; + +const useRootBaseStyles = makeResetStyles({ + ...typographyStyles.body1, + ...shorthands.gridArea('body'), +}); + +/** + * Apply styling to the MessageBarBody slots based on the state + */ +export const useMessageBarBodyStyles_unstable = (state: MessageBarBodyState): MessageBarBodyState => { + const rootBaseStyles = useRootBaseStyles(); + state.root.className = mergeClasses(messageBarBodyClassNames.root, rootBaseStyles, state.root.className); + + return state; +}; diff --git a/packages/react-components/react-message-bar-preview/src/contexts/messageBarContext.ts b/packages/react-components/react-message-bar-preview/src/contexts/messageBarContext.ts new file mode 100644 index 00000000000000..add68734a62921 --- /dev/null +++ b/packages/react-components/react-message-bar-preview/src/contexts/messageBarContext.ts @@ -0,0 +1,13 @@ +import * as React from 'react'; + +export type MessageBarContextValue = { + layout?: 'multiline' | 'singleline'; +}; +const messageBarContext = React.createContext(undefined); + +export const messageBarContextDefaultValue: MessageBarContextValue = { + layout: 'singleline', +}; + +export const MessageBarContextProvider = messageBarContext.Provider; +export const useMessageBarContext = () => React.useContext(messageBarContext) ?? messageBarContextDefaultValue; diff --git a/packages/react-components/react-message-bar-preview/src/index.ts b/packages/react-components/react-message-bar-preview/src/index.ts index 63270882f450bd..e4d035efe8584d 100644 --- a/packages/react-components/react-message-bar-preview/src/index.ts +++ b/packages/react-components/react-message-bar-preview/src/index.ts @@ -17,3 +17,26 @@ export { } from './MessageBarTitle'; export type { MessageBarTitleProps, MessageBarTitleSlots, MessageBarTitleState } from './MessageBarTitle'; + +export { + MessageBarActions, + useMessageBarActionsStyles_unstable, + useMessageBarActions_unstable, + renderMessageBarActions_unstable, + messageBarActionsClassNames, +} from './MessageBarActions'; + +export type { MessageBarActionsProps, MessageBarActionsSlots, MessageBarActionsState } from './MessageBarActions'; + +export { + MessageBarBody, + useMessageBarBodyStyles_unstable, + useMessageBarBody_unstable, + renderMessageBarBody_unstable, + messageBarBodyClassNames, +} from './MessageBarBody'; + +export type { MessageBarBodyProps, MessageBarBodySlots, MessageBarBodyState } from './MessageBarBody'; + +export { MessageBarContextProvider, useMessageBarContext } from './contexts/messageBarContext'; +export type { MessageBarContextValue } from './contexts/messageBarContext'; diff --git a/packages/react-components/react-message-bar-preview/stories/MessageBar/Default.stories.tsx b/packages/react-components/react-message-bar-preview/stories/MessageBar/Default.stories.tsx index 496bddf697502f..c6c7034034318f 100644 --- a/packages/react-components/react-message-bar-preview/stories/MessageBar/Default.stories.tsx +++ b/packages/react-components/react-message-bar-preview/stories/MessageBar/Default.stories.tsx @@ -1,26 +1,22 @@ import * as React from 'react'; import { Button, Link } from '@fluentui/react-components'; import { DismissRegular } from '@fluentui/react-icons'; -import { MessageBar, MessageBarTitle } from '@fluentui/react-message-bar-preview'; +import { MessageBar, MessageBarActions, MessageBarTitle, MessageBarBody } from '@fluentui/react-message-bar-preview'; const intents = ['info', 'warning', 'error', 'success'] as const; export const Default = () => (
{intents.map(intent => ( - } appearance="transparent" />} - secondaryActions={ - <> - - - - } - > - Descriptive title - Message providing information to the user with actionable insights. Link + + + Descriptive title + Message providing information to the user with actionable insights. Link + + } />}> + + + ))}
diff --git a/packages/react-components/react-message-bar-preview/stories/MessageBar/Multiline.stories.tsx b/packages/react-components/react-message-bar-preview/stories/MessageBar/Multiline.stories.tsx index 4e448316ff2a41..87901e5318582a 100644 --- a/packages/react-components/react-message-bar-preview/stories/MessageBar/Multiline.stories.tsx +++ b/packages/react-components/react-message-bar-preview/stories/MessageBar/Multiline.stories.tsx @@ -1,27 +1,22 @@ import * as React from 'react'; import { Button, Link } from '@fluentui/react-components'; import { DismissRegular } from '@fluentui/react-icons'; -import { MessageBar, MessageBarTitle } from '@fluentui/react-message-bar-preview'; +import { MessageBar, MessageBarActions, MessageBarBody, MessageBarTitle } from '@fluentui/react-message-bar-preview'; const intents = ['info', 'warning', 'error', 'success'] as const; export const Multiline = () => (
{intents.map(intent => ( - } appearance="transparent" />} - secondaryActions={ - <> - - - - } - > - Descriptive title - Message providing information to the user with actionable insights. Link + + + Descriptive title + Message providing information to the user with actionable insights. Link + + } />}> + + + ))}
diff --git a/packages/react-components/react-message-bar-preview/stories/MessageBarActions/MessageBarActionsBestPractices.md b/packages/react-components/react-message-bar-preview/stories/MessageBarActions/MessageBarActionsBestPractices.md new file mode 100644 index 00000000000000..08ff8ddeeb5f86 --- /dev/null +++ b/packages/react-components/react-message-bar-preview/stories/MessageBarActions/MessageBarActionsBestPractices.md @@ -0,0 +1,5 @@ +## Best practices + +### Do + +### Don't diff --git a/packages/react-components/react-message-bar-preview/stories/MessageBarActions/MessageBarActionsDefault.stories.tsx b/packages/react-components/react-message-bar-preview/stories/MessageBarActions/MessageBarActionsDefault.stories.tsx new file mode 100644 index 00000000000000..6146b89d622795 --- /dev/null +++ b/packages/react-components/react-message-bar-preview/stories/MessageBarActions/MessageBarActionsDefault.stories.tsx @@ -0,0 +1,4 @@ +import * as React from 'react'; +import { MessageBarActions, MessageBarActionsProps } from '@fluentui/react-message-bar-preview'; + +export const Default = (props: Partial) => ; diff --git a/packages/react-components/react-message-bar-preview/stories/MessageBarActions/MessageBarActionsDescription.md b/packages/react-components/react-message-bar-preview/stories/MessageBarActions/MessageBarActionsDescription.md new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/packages/react-components/react-message-bar-preview/stories/MessageBarActions/index.stories.tsx b/packages/react-components/react-message-bar-preview/stories/MessageBarActions/index.stories.tsx new file mode 100644 index 00000000000000..148376427ded46 --- /dev/null +++ b/packages/react-components/react-message-bar-preview/stories/MessageBarActions/index.stories.tsx @@ -0,0 +1,18 @@ +import { MessageBarActions } from '@fluentui/react-message-bar-preview'; + +import descriptionMd from './MessageBarActionsDescription.md'; +import bestPracticesMd from './MessageBarActionsBestPractices.md'; + +export { Default } from './MessageBarActionsDefault.stories'; + +export default { + title: 'Preview Components/MessageBarActions', + component: MessageBarActions, + parameters: { + docs: { + description: { + component: [descriptionMd, bestPracticesMd].join('\n'), + }, + }, + }, +}; diff --git a/packages/react-components/react-message-bar-preview/stories/MessageBarBody/MessageBarBodyBestPractices.md b/packages/react-components/react-message-bar-preview/stories/MessageBarBody/MessageBarBodyBestPractices.md new file mode 100644 index 00000000000000..08ff8ddeeb5f86 --- /dev/null +++ b/packages/react-components/react-message-bar-preview/stories/MessageBarBody/MessageBarBodyBestPractices.md @@ -0,0 +1,5 @@ +## Best practices + +### Do + +### Don't diff --git a/packages/react-components/react-message-bar-preview/stories/MessageBarBody/MessageBarBodyDefault.stories.tsx b/packages/react-components/react-message-bar-preview/stories/MessageBarBody/MessageBarBodyDefault.stories.tsx new file mode 100644 index 00000000000000..60e2f1aab57a01 --- /dev/null +++ b/packages/react-components/react-message-bar-preview/stories/MessageBarBody/MessageBarBodyDefault.stories.tsx @@ -0,0 +1,4 @@ +import * as React from 'react'; +import { MessageBarBody, MessageBarBodyProps } from '@fluentui/react-message-bar-preview'; + +export const Default = (props: Partial) => ; diff --git a/packages/react-components/react-message-bar-preview/stories/MessageBarBody/MessageBarBodyDescription.md b/packages/react-components/react-message-bar-preview/stories/MessageBarBody/MessageBarBodyDescription.md new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/packages/react-components/react-message-bar-preview/stories/MessageBarBody/index.stories.tsx b/packages/react-components/react-message-bar-preview/stories/MessageBarBody/index.stories.tsx new file mode 100644 index 00000000000000..f21a9ae4e96ca2 --- /dev/null +++ b/packages/react-components/react-message-bar-preview/stories/MessageBarBody/index.stories.tsx @@ -0,0 +1,18 @@ +import { MessageBarBody } from '@fluentui/react-message-bar-preview'; + +import descriptionMd from './MessageBarBodyDescription.md'; +import bestPracticesMd from './MessageBarBodyBestPractices.md'; + +export { Default } from './MessageBarBodyDefault.stories'; + +export default { + title: 'Preview Components/MessageBarBody', + component: MessageBarBody, + parameters: { + docs: { + description: { + component: [descriptionMd, bestPracticesMd].join('\n'), + }, + }, + }, +}; diff --git a/packages/react-components/react-message-bar-preview/tsconfig.lib.json b/packages/react-components/react-message-bar-preview/tsconfig.lib.json index 6f90cf95c005bd..8debc43c62f970 100644 --- a/packages/react-components/react-message-bar-preview/tsconfig.lib.json +++ b/packages/react-components/react-message-bar-preview/tsconfig.lib.json @@ -18,5 +18,5 @@ "**/*.stories.ts", "**/*.stories.tsx" ], - "include": ["./src/**/*.ts", "./src/**/*.tsx"] + "include": ["./src/**/*.ts", "./src/**/*.tsx", "src/contexts"] } From 0c03bfaada3eb6232a6c5fb6958f4e894d665bd9 Mon Sep 17 00:00:00 2001 From: Lingfan Gao Date: Wed, 27 Sep 2023 15:48:03 +0000 Subject: [PATCH 09/13] remove stories --- .../MessageBarActionsBestPractices.md | 5 ----- .../MessageBarActionsDefault.stories.tsx | 4 ---- .../MessageBarActionsDescription.md | 0 .../MessageBarActions/index.stories.tsx | 18 ------------------ .../MessageBarBodyBestPractices.md | 5 ----- .../MessageBarBodyDefault.stories.tsx | 4 ---- .../MessageBarBodyDescription.md | 0 .../stories/MessageBarBody/index.stories.tsx | 18 ------------------ 8 files changed, 54 deletions(-) delete mode 100644 packages/react-components/react-message-bar-preview/stories/MessageBarActions/MessageBarActionsBestPractices.md delete mode 100644 packages/react-components/react-message-bar-preview/stories/MessageBarActions/MessageBarActionsDefault.stories.tsx delete mode 100644 packages/react-components/react-message-bar-preview/stories/MessageBarActions/MessageBarActionsDescription.md delete mode 100644 packages/react-components/react-message-bar-preview/stories/MessageBarActions/index.stories.tsx delete mode 100644 packages/react-components/react-message-bar-preview/stories/MessageBarBody/MessageBarBodyBestPractices.md delete mode 100644 packages/react-components/react-message-bar-preview/stories/MessageBarBody/MessageBarBodyDefault.stories.tsx delete mode 100644 packages/react-components/react-message-bar-preview/stories/MessageBarBody/MessageBarBodyDescription.md delete mode 100644 packages/react-components/react-message-bar-preview/stories/MessageBarBody/index.stories.tsx diff --git a/packages/react-components/react-message-bar-preview/stories/MessageBarActions/MessageBarActionsBestPractices.md b/packages/react-components/react-message-bar-preview/stories/MessageBarActions/MessageBarActionsBestPractices.md deleted file mode 100644 index 08ff8ddeeb5f86..00000000000000 --- a/packages/react-components/react-message-bar-preview/stories/MessageBarActions/MessageBarActionsBestPractices.md +++ /dev/null @@ -1,5 +0,0 @@ -## Best practices - -### Do - -### Don't diff --git a/packages/react-components/react-message-bar-preview/stories/MessageBarActions/MessageBarActionsDefault.stories.tsx b/packages/react-components/react-message-bar-preview/stories/MessageBarActions/MessageBarActionsDefault.stories.tsx deleted file mode 100644 index 6146b89d622795..00000000000000 --- a/packages/react-components/react-message-bar-preview/stories/MessageBarActions/MessageBarActionsDefault.stories.tsx +++ /dev/null @@ -1,4 +0,0 @@ -import * as React from 'react'; -import { MessageBarActions, MessageBarActionsProps } from '@fluentui/react-message-bar-preview'; - -export const Default = (props: Partial) => ; diff --git a/packages/react-components/react-message-bar-preview/stories/MessageBarActions/MessageBarActionsDescription.md b/packages/react-components/react-message-bar-preview/stories/MessageBarActions/MessageBarActionsDescription.md deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/packages/react-components/react-message-bar-preview/stories/MessageBarActions/index.stories.tsx b/packages/react-components/react-message-bar-preview/stories/MessageBarActions/index.stories.tsx deleted file mode 100644 index 148376427ded46..00000000000000 --- a/packages/react-components/react-message-bar-preview/stories/MessageBarActions/index.stories.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { MessageBarActions } from '@fluentui/react-message-bar-preview'; - -import descriptionMd from './MessageBarActionsDescription.md'; -import bestPracticesMd from './MessageBarActionsBestPractices.md'; - -export { Default } from './MessageBarActionsDefault.stories'; - -export default { - title: 'Preview Components/MessageBarActions', - component: MessageBarActions, - parameters: { - docs: { - description: { - component: [descriptionMd, bestPracticesMd].join('\n'), - }, - }, - }, -}; diff --git a/packages/react-components/react-message-bar-preview/stories/MessageBarBody/MessageBarBodyBestPractices.md b/packages/react-components/react-message-bar-preview/stories/MessageBarBody/MessageBarBodyBestPractices.md deleted file mode 100644 index 08ff8ddeeb5f86..00000000000000 --- a/packages/react-components/react-message-bar-preview/stories/MessageBarBody/MessageBarBodyBestPractices.md +++ /dev/null @@ -1,5 +0,0 @@ -## Best practices - -### Do - -### Don't diff --git a/packages/react-components/react-message-bar-preview/stories/MessageBarBody/MessageBarBodyDefault.stories.tsx b/packages/react-components/react-message-bar-preview/stories/MessageBarBody/MessageBarBodyDefault.stories.tsx deleted file mode 100644 index 60e2f1aab57a01..00000000000000 --- a/packages/react-components/react-message-bar-preview/stories/MessageBarBody/MessageBarBodyDefault.stories.tsx +++ /dev/null @@ -1,4 +0,0 @@ -import * as React from 'react'; -import { MessageBarBody, MessageBarBodyProps } from '@fluentui/react-message-bar-preview'; - -export const Default = (props: Partial) => ; diff --git a/packages/react-components/react-message-bar-preview/stories/MessageBarBody/MessageBarBodyDescription.md b/packages/react-components/react-message-bar-preview/stories/MessageBarBody/MessageBarBodyDescription.md deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/packages/react-components/react-message-bar-preview/stories/MessageBarBody/index.stories.tsx b/packages/react-components/react-message-bar-preview/stories/MessageBarBody/index.stories.tsx deleted file mode 100644 index f21a9ae4e96ca2..00000000000000 --- a/packages/react-components/react-message-bar-preview/stories/MessageBarBody/index.stories.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { MessageBarBody } from '@fluentui/react-message-bar-preview'; - -import descriptionMd from './MessageBarBodyDescription.md'; -import bestPracticesMd from './MessageBarBodyBestPractices.md'; - -export { Default } from './MessageBarBodyDefault.stories'; - -export default { - title: 'Preview Components/MessageBarBody', - component: MessageBarBody, - parameters: { - docs: { - description: { - component: [descriptionMd, bestPracticesMd].join('\n'), - }, - }, - }, -}; From 038781d326851faf841bc6a0e12e74042067635c Mon Sep 17 00:00:00 2001 From: Lingfan Gao Date: Wed, 27 Sep 2023 15:49:55 +0000 Subject: [PATCH 10/13] revert tsconfig changes --- .../react-message-bar-preview/tsconfig.lib.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-components/react-message-bar-preview/tsconfig.lib.json b/packages/react-components/react-message-bar-preview/tsconfig.lib.json index 8debc43c62f970..6f90cf95c005bd 100644 --- a/packages/react-components/react-message-bar-preview/tsconfig.lib.json +++ b/packages/react-components/react-message-bar-preview/tsconfig.lib.json @@ -18,5 +18,5 @@ "**/*.stories.ts", "**/*.stories.tsx" ], - "include": ["./src/**/*.ts", "./src/**/*.tsx", "src/contexts"] + "include": ["./src/**/*.ts", "./src/**/*.tsx"] } From c58ee70c888b800e6ab997c59881a43b6d3bd663 Mon Sep 17 00:00:00 2001 From: Lingfan Gao Date: Thu, 28 Sep 2023 14:02:39 +0000 Subject: [PATCH 11/13] remove outdated keyborg cypress test --- .../react-tabster/src/useKeyborg.cy.tsx | 25 ------------------- 1 file changed, 25 deletions(-) delete mode 100644 packages/react-components/react-tabster/src/useKeyborg.cy.tsx diff --git a/packages/react-components/react-tabster/src/useKeyborg.cy.tsx b/packages/react-components/react-tabster/src/useKeyborg.cy.tsx deleted file mode 100644 index a027be8a0b4cba..00000000000000 --- a/packages/react-components/react-tabster/src/useKeyborg.cy.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import * as React from 'react'; -import { KEYBOARD_NAV_ATTRIBUTE } from './focus/constants'; -import { useKeyboardNavAttribute } from '@fluentui/react-tabster'; -import { mount as mountBase } from '@cypress/react'; -import { FluentProvider } from '@fluentui/react-provider'; -import { teamsLightTheme } from '@fluentui/react-theme'; - -const mount = (element: JSX.Element) => { - mountBase({element}); -}; - -describe('Keyborg', () => { - const Example = () => ( -
- - -
- ); - - it('should open when clicked', () => { - mount(); - cy.contains('Start').focus().realPress('Tab'); - cy.contains('Finish').should('be.focused').parent().should('have.attr', KEYBOARD_NAV_ATTRIBUTE); - }); -}); From 823248dae3a861d23b4aee8b28104169a80b506c Mon Sep 17 00:00:00 2001 From: Lingfan Gao Date: Thu, 28 Sep 2023 14:07:27 +0000 Subject: [PATCH 12/13] add keyborg test again --- .../react-tabster/src/useKeyborg.cy.tsx | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 packages/react-components/react-tabster/src/useKeyborg.cy.tsx diff --git a/packages/react-components/react-tabster/src/useKeyborg.cy.tsx b/packages/react-components/react-tabster/src/useKeyborg.cy.tsx new file mode 100644 index 00000000000000..a027be8a0b4cba --- /dev/null +++ b/packages/react-components/react-tabster/src/useKeyborg.cy.tsx @@ -0,0 +1,25 @@ +import * as React from 'react'; +import { KEYBOARD_NAV_ATTRIBUTE } from './focus/constants'; +import { useKeyboardNavAttribute } from '@fluentui/react-tabster'; +import { mount as mountBase } from '@cypress/react'; +import { FluentProvider } from '@fluentui/react-provider'; +import { teamsLightTheme } from '@fluentui/react-theme'; + +const mount = (element: JSX.Element) => { + mountBase({element}); +}; + +describe('Keyborg', () => { + const Example = () => ( +
+ + +
+ ); + + it('should open when clicked', () => { + mount(); + cy.contains('Start').focus().realPress('Tab'); + cy.contains('Finish').should('be.focused').parent().should('have.attr', KEYBOARD_NAV_ATTRIBUTE); + }); +}); From e328ff0d6b1073a60517aafa1f6f2c0289ecc896 Mon Sep 17 00:00:00 2001 From: Lingfan Gao Date: Thu, 28 Sep 2023 14:11:08 +0000 Subject: [PATCH 13/13] add tsconfig paths to cypress --- scripts/cypress/src/base.config.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/scripts/cypress/src/base.config.ts b/scripts/cypress/src/base.config.ts index b38813a4c3de84..d3a646e0d07a5e 100644 --- a/scripts/cypress/src/base.config.ts +++ b/scripts/cypress/src/base.config.ts @@ -1,6 +1,7 @@ import * as path from 'path'; import { defineConfig } from 'cypress'; +import { TsconfigPathsPlugin } from 'tsconfig-paths-webpack-plugin'; import type { Configuration } from 'webpack'; /** @@ -32,6 +33,14 @@ const cypressWebpackConfig = (): Configuration => { }); } + baseWebpackConfig.resolve ??= {}; + baseWebpackConfig.resolve.plugins ??= []; + baseWebpackConfig.resolve.plugins.push( + new TsconfigPathsPlugin({ + configFile: path.resolve(__dirname, '../../../tsconfig.base.json'), + }), + ); + return baseWebpackConfig; };