From dde753d579caf88fe515bf13a6b6a186e2555ee6 Mon Sep 17 00:00:00 2001 From: ling1726 Date: Fri, 30 Jun 2023 14:49:53 +0200 Subject: [PATCH] feat: Inverted appearance (#28354) * feat: Inverted appearance Adds the `appearance` prop to `Toast` and adds inverted styles to all Toast components. Renames the ToastContext to ToastContainerContext to avoid the clash with the context that is actually being used by the Toast (i.e. ToastContext) that holds the appearance value for the component. * add extra VR tests * update example * improve types * use shared context * update types * Update packages/react-components/react-toast/src/components/Toast/renderToast.tsx Co-authored-by: Oleksandr Fediashov --------- Co-authored-by: Oleksandr Fediashov --- .../src/stories/Toast/Toast.stories.tsx | 83 +++++++++++++++++++ .../react-toast/etc/react-toast.api.md | 19 +++-- .../src/components/Toast/Toast.tsx | 3 +- .../src/components/Toast/Toast.types.ts | 13 ++- .../src/components/Toast/renderToast.tsx | 11 ++- .../src/components/Toast/useToast.ts | 1 + .../components/Toast/useToastContextValues.ts | 9 ++ .../components/Toast/useToastStyles.styles.ts | 17 +++- .../components/ToastBody/ToastBody.types.ts | 5 +- .../src/components/ToastBody/useToastBody.ts | 7 +- .../ToastBody/useToastBodyStyles.styles.ts | 21 ++++- .../ToastContainer/ToastContainer.types.ts | 6 +- .../ToastContainer/renderToastContainer.tsx | 6 +- .../useToastContainerContextValues.ts | 4 +- .../components/ToastTitle/ToastTitle.types.ts | 8 +- .../components/ToastTitle/useToastTitle.tsx | 9 +- .../ToastTitle/useToastTitleStyles.styles.ts | 53 +++++++++++- .../ToastTrigger/useToastTrigger.ts | 4 +- .../src/contexts/toastContainerContext.tsx | 22 +++++ .../react-toast/src/contexts/toastContext.tsx | 21 ----- .../Toast/InvertedAppearance.stories.tsx | 27 ++++++ .../stories/Toast/index.stories.tsx | 1 + 22 files changed, 292 insertions(+), 58 deletions(-) create mode 100644 packages/react-components/react-toast/src/components/Toast/useToastContextValues.ts create mode 100644 packages/react-components/react-toast/src/contexts/toastContainerContext.tsx delete mode 100644 packages/react-components/react-toast/src/contexts/toastContext.tsx create mode 100644 packages/react-components/react-toast/stories/Toast/InvertedAppearance.stories.tsx diff --git a/apps/vr-tests-react-components/src/stories/Toast/Toast.stories.tsx b/apps/vr-tests-react-components/src/stories/Toast/Toast.stories.tsx index 2ee30146db1a8..de12647fa0d5b 100644 --- a/apps/vr-tests-react-components/src/stories/Toast/Toast.stories.tsx +++ b/apps/vr-tests-react-components/src/stories/Toast/Toast.stories.tsx @@ -136,3 +136,86 @@ export const TitleOnly = () => { ); }; + +export const FullToastInverted = () => { + const { dispatchToast } = useToastController(); + const { toastRef, onStatusChange } = useToastScreenshotData(); + const dispatchToasts = () => { + for (const intent of toastIntents) { + dispatchToast( + + Action}>This is a toast + This is a toast + + Action + Action + + , + { + intent, + timeout: -1, + onStatusChange, + }, + ); + } + }; + return ( + <> + + + + ); +}; + +export const WithoutSubtitleInverted = () => { + const { dispatchToast } = useToastController(); + const { toastRef, onStatusChange } = useToastScreenshotData(); + const dispatchToasts = () => { + for (const intent of toastIntents) { + dispatchToast( + + Action}>This is a toast + This is a toast + + Action + Action + + , + { intent, timeout: -1, onStatusChange }, + ); + } + }; + return ( + <> + + + + ); +}; + +export const TitleOnlyInverted = () => { + const { dispatchToast } = useToastController(); + const { toastRef, onStatusChange } = useToastScreenshotData(); + const dispatchToasts = () => { + for (const intent of toastIntents) { + dispatchToast( + + Action}>This is a toast + , + { intent, onStatusChange, timeout: -1 }, + ); + } + }; + return ( + <> + + + + ); +}; diff --git a/packages/react-components/react-toast/etc/react-toast.api.md b/packages/react-components/react-toast/etc/react-toast.api.md index 968f4fc6dff91..4cf20c5b5b595 100644 --- a/packages/react-components/react-toast/etc/react-toast.api.md +++ b/packages/react-components/react-toast/etc/react-toast.api.md @@ -8,6 +8,7 @@ import { ARIAButtonResultProps } from '@fluentui/react-aria'; import { ARIAButtonType } from '@fluentui/react-aria'; +import { BackgroundAppearanceContextValue } from '@fluentui/react-shared-contexts'; import type { ComponentProps } from '@fluentui/react-utilities'; import type { ComponentState } from '@fluentui/react-utilities'; import type { ForwardRefComponent } from '@fluentui/react-utilities'; @@ -17,7 +18,7 @@ import type { SlotClassNames } from '@fluentui/react-utilities'; import type { TriggerProps } from '@fluentui/react-utilities'; // @public -export const renderToast_unstable: (state: ToastState) => JSX.Element; +export const renderToast_unstable: (state: ToastState, contextValues: ToastContextValues) => JSX.Element; // @public export const renderToastBody_unstable: (state: ToastBodyState) => JSX.Element; @@ -50,7 +51,9 @@ export type ToastBodySlots = { }; // @public -export type ToastBodyState = ComponentState; +export type ToastBodyState = ComponentState & { + backgroundAppearance: BackgroundAppearanceContextValue; +}; // @public (undocumented) export const toastClassNames: SlotClassNames; @@ -111,7 +114,9 @@ export type ToastPoliteness = 'assertive' | 'polite'; export type ToastPosition = 'top-end' | 'top-start' | 'bottom-end' | 'bottom-start'; // @public -export type ToastProps = ComponentProps & {}; +export type ToastProps = ComponentProps & { + appearance?: BackgroundAppearanceContextValue; +}; // @public (undocumented) export type ToastSlots = { @@ -119,7 +124,9 @@ export type ToastSlots = { }; // @public -export type ToastState = ComponentState; +export type ToastState = ComponentState & { + backgroundAppearance: BackgroundAppearanceContextValue; +}; // @public (undocumented) export type ToastStatus = 'queued' | 'visible' | 'dismissed' | 'unmounted'; @@ -141,7 +148,9 @@ export type ToastTitleSlots = { }; // @public -export type ToastTitleState = ComponentState & Pick; +export type ToastTitleState = ComponentState & Pick & { + backgroundAppearance: BackgroundAppearanceContextValue; +}; // @public export const ToastTrigger: React_2.FC; diff --git a/packages/react-components/react-toast/src/components/Toast/Toast.tsx b/packages/react-components/react-toast/src/components/Toast/Toast.tsx index 78998c00a7b49..098c6fc326bc1 100644 --- a/packages/react-components/react-toast/src/components/Toast/Toast.tsx +++ b/packages/react-components/react-toast/src/components/Toast/Toast.tsx @@ -4,6 +4,7 @@ import { renderToast_unstable } from './renderToast'; import { useToastStyles_unstable } from './useToastStyles.styles'; import type { ToastProps } from './Toast.types'; import type { ForwardRefComponent } from '@fluentui/react-utilities'; +import { useToastContextValues_unstable } from './useToastContextValues'; /** * Toast component @@ -12,7 +13,7 @@ export const Toast: ForwardRefComponent = React.forwardRef((props, r const state = useToast_unstable(props, ref); useToastStyles_unstable(state); - return renderToast_unstable(state); + return renderToast_unstable(state, useToastContextValues_unstable(state)); }); Toast.displayName = 'Toast'; diff --git a/packages/react-components/react-toast/src/components/Toast/Toast.types.ts b/packages/react-components/react-toast/src/components/Toast/Toast.types.ts index a894239f2ade9..b19b50447c8ec 100644 --- a/packages/react-components/react-toast/src/components/Toast/Toast.types.ts +++ b/packages/react-components/react-toast/src/components/Toast/Toast.types.ts @@ -1,15 +1,24 @@ import type { ComponentProps, ComponentState, Slot } from '@fluentui/react-utilities'; +import { BackgroundAppearanceContextValue } from '@fluentui/react-shared-contexts'; export type ToastSlots = { root: Slot<'div'>; }; +export type ToastContextValues = { + backgroundAppearance: BackgroundAppearanceContextValue; +}; + /** * Toast Props */ -export type ToastProps = ComponentProps & {}; +export type ToastProps = ComponentProps & { + appearance?: BackgroundAppearanceContextValue; +}; /** * State used in rendering Toast */ -export type ToastState = ComponentState; +export type ToastState = ComponentState & { + backgroundAppearance: BackgroundAppearanceContextValue; +}; diff --git a/packages/react-components/react-toast/src/components/Toast/renderToast.tsx b/packages/react-components/react-toast/src/components/Toast/renderToast.tsx index b7eef53f8eccf..1e2df09864a5d 100644 --- a/packages/react-components/react-toast/src/components/Toast/renderToast.tsx +++ b/packages/react-components/react-toast/src/components/Toast/renderToast.tsx @@ -3,13 +3,18 @@ import { createElement } from '@fluentui/react-jsx-runtime'; import { getSlotsNext } from '@fluentui/react-utilities'; -import type { ToastState, ToastSlots } from './Toast.types'; +import { BackgroundAppearanceProvider } from '@fluentui/react-shared-contexts'; +import type { ToastState, ToastSlots, ToastContextValues } from './Toast.types'; /** * Render the final JSX of Toast */ -export const renderToast_unstable = (state: ToastState) => { +export const renderToast_unstable = (state: ToastState, contextValues: ToastContextValues) => { const { slots, slotProps } = getSlotsNext(state); - return ; + return ( + + + + ); }; diff --git a/packages/react-components/react-toast/src/components/Toast/useToast.ts b/packages/react-components/react-toast/src/components/Toast/useToast.ts index 8409bf802a1d3..1031625606d6d 100644 --- a/packages/react-components/react-toast/src/components/Toast/useToast.ts +++ b/packages/react-components/react-toast/src/components/Toast/useToast.ts @@ -20,5 +20,6 @@ export const useToast_unstable = (props: ToastProps, ref: React.Ref ref, ...props, }), + backgroundAppearance: props.appearance, }; }; diff --git a/packages/react-components/react-toast/src/components/Toast/useToastContextValues.ts b/packages/react-components/react-toast/src/components/Toast/useToastContextValues.ts new file mode 100644 index 0000000000000..ebf0f9dec5aa2 --- /dev/null +++ b/packages/react-components/react-toast/src/components/Toast/useToastContextValues.ts @@ -0,0 +1,9 @@ +import { ToastContextValues, ToastState } from './Toast.types'; + +export function useToastContextValues_unstable(state: ToastState): ToastContextValues { + const { backgroundAppearance } = state; + + return { + backgroundAppearance, + }; +} diff --git a/packages/react-components/react-toast/src/components/Toast/useToastStyles.styles.ts b/packages/react-components/react-toast/src/components/Toast/useToastStyles.styles.ts index cf422a8b31e7f..0f4d117aee033 100644 --- a/packages/react-components/react-toast/src/components/Toast/useToastStyles.styles.ts +++ b/packages/react-components/react-toast/src/components/Toast/useToastStyles.styles.ts @@ -1,4 +1,4 @@ -import { makeResetStyles, mergeClasses, shorthands } from '@griffel/react'; +import { makeResetStyles, makeStyles, mergeClasses, shorthands } from '@griffel/react'; import { tokens } from '@fluentui/react-theme'; import type { ToastSlots, ToastState } from './Toast.types'; import type { SlotClassNames } from '@fluentui/react-utilities'; @@ -21,12 +21,25 @@ const useRootBaseClassName = makeResetStyles({ backgroundColor: tokens.colorNeutralBackground1, }); +const useStyles = makeStyles({ + inverted: { + color: tokens.colorNeutralForegroundInverted2, + backgroundColor: tokens.colorNeutralBackgroundInverted, + }, +}); + /** * Apply styling to the Toast slots based on the state */ export const useToastStyles_unstable = (state: ToastState): ToastState => { const rootBaseClassName = useRootBaseClassName(); - state.root.className = mergeClasses(toastClassNames.root, rootBaseClassName, state.root.className); + const styles = useStyles(); + state.root.className = mergeClasses( + toastClassNames.root, + rootBaseClassName, + state.backgroundAppearance === 'inverted' && styles.inverted, + state.root.className, + ); return state; }; diff --git a/packages/react-components/react-toast/src/components/ToastBody/ToastBody.types.ts b/packages/react-components/react-toast/src/components/ToastBody/ToastBody.types.ts index 22dcda4c205c3..570330970d2e7 100644 --- a/packages/react-components/react-toast/src/components/ToastBody/ToastBody.types.ts +++ b/packages/react-components/react-toast/src/components/ToastBody/ToastBody.types.ts @@ -1,4 +1,5 @@ import type { ComponentProps, ComponentState, Slot } from '@fluentui/react-utilities'; +import { BackgroundAppearanceContextValue } from '@fluentui/react-shared-contexts'; export type ToastBodySlots = { root: Slot<'div'>; @@ -13,4 +14,6 @@ export type ToastBodyProps = ComponentProps & {}; /** * State used in rendering ToastBody */ -export type ToastBodyState = ComponentState; +export type ToastBodyState = ComponentState & { + backgroundAppearance: BackgroundAppearanceContextValue; +}; diff --git a/packages/react-components/react-toast/src/components/ToastBody/useToastBody.ts b/packages/react-components/react-toast/src/components/ToastBody/useToastBody.ts index 72fa92a443c7d..21ef28f4167cf 100644 --- a/packages/react-components/react-toast/src/components/ToastBody/useToastBody.ts +++ b/packages/react-components/react-toast/src/components/ToastBody/useToastBody.ts @@ -1,7 +1,8 @@ import * as React from 'react'; import { getNativeElementProps, resolveShorthand } from '@fluentui/react-utilities'; import type { ToastBodyProps, ToastBodyState } from './ToastBody.types'; -import { useToastContext } from '../../contexts/toastContext'; +import { useToastContainerContext } from '../../contexts/toastContainerContext'; +import { useBackgroundAppearance } from '@fluentui/react-shared-contexts'; /** * Create the state required to render ToastBody. @@ -13,7 +14,8 @@ import { useToastContext } from '../../contexts/toastContext'; * @param ref - reference to root HTMLElement of ToastBody */ export const useToastBody_unstable = (props: ToastBodyProps, ref: React.Ref): ToastBodyState => { - const { bodyId } = useToastContext(); + const backgroundAppearance = useBackgroundAppearance(); + const { bodyId } = useToastContainerContext(); return { components: { root: 'div', @@ -25,5 +27,6 @@ export const useToastBody_unstable = (props: ToastBodyProps, ref: React.Ref { const rootBaseClassName = useRootBaseClassName(); const subtitleBaseClassName = useSubtitleBaseClassName(); - state.root.className = mergeClasses(toastBodyClassNames.root, rootBaseClassName, state.root.className); + const invertedStyles = useInvertedStyles(); + state.root.className = mergeClasses( + toastBodyClassNames.root, + rootBaseClassName, + state.backgroundAppearance === 'inverted' && invertedStyles.root, + state.root.className, + ); if (state.subtitle) { state.subtitle.className = mergeClasses( toastBodyClassNames.subtitle, subtitleBaseClassName, + state.backgroundAppearance === 'inverted' && invertedStyles.subtitle, state.subtitle.className, ); } diff --git a/packages/react-components/react-toast/src/components/ToastContainer/ToastContainer.types.ts b/packages/react-components/react-toast/src/components/ToastContainer/ToastContainer.types.ts index 5b35fc63f4212..0486013951137 100644 --- a/packages/react-components/react-toast/src/components/ToastContainer/ToastContainer.types.ts +++ b/packages/react-components/react-toast/src/components/ToastContainer/ToastContainer.types.ts @@ -2,11 +2,11 @@ import * as React from 'react'; import type { ComponentProps, ComponentState, Slot } from '@fluentui/react-utilities'; import { Announce } from '../AriaLive/AriaLive.types'; import { Toast, ToastIntent } from '../../state'; -import { ToastContextValue } from '../../contexts/toastContext'; +import { ToastContainerContextValue } from '../../contexts/toastContainerContext'; import { TimerProps } from '../Timer/Timer'; export type ToastContainerContextValues = { - toast: ToastContextValue; + toast: ToastContainerContextValue; }; export type ToastContainerSlots = { @@ -30,7 +30,7 @@ export type ToastContainerProps = ComponentProps> & */ export type ToastContainerState = ComponentState & Pick & - Pick & { + Pick & { transitionTimeout: number; timerTimeout: number; running: boolean; diff --git a/packages/react-components/react-toast/src/components/ToastContainer/renderToastContainer.tsx b/packages/react-components/react-toast/src/components/ToastContainer/renderToastContainer.tsx index ab13cae7610e1..8f4e9a9917cb0 100644 --- a/packages/react-components/react-toast/src/components/ToastContainer/renderToastContainer.tsx +++ b/packages/react-components/react-toast/src/components/ToastContainer/renderToastContainer.tsx @@ -5,7 +5,7 @@ import { createElement } from '@fluentui/react-jsx-runtime'; import { getSlotsNext } from '@fluentui/react-utilities'; import { Transition } from 'react-transition-group'; import type { ToastContainerState, ToastContainerSlots, ToastContainerContextValues } from './ToastContainer.types'; -import { ToastContextProvider } from '../../contexts/toastContext'; +import { ToastContainerContextProvider } from '../../contexts/toastContainerContext'; /** * Render the final JSX of ToastContainer @@ -27,10 +27,10 @@ export const renderToastContainer_unstable = ( onEntering={onTransitionEntering} nodeRef={nodeRef} > - + - + ); }; diff --git a/packages/react-components/react-toast/src/components/ToastContainer/useToastContainerContextValues.ts b/packages/react-components/react-toast/src/components/ToastContainer/useToastContainerContextValues.ts index 8ddb91898ab1b..77cf4a513c3ae 100644 --- a/packages/react-components/react-toast/src/components/ToastContainer/useToastContainerContextValues.ts +++ b/packages/react-components/react-toast/src/components/ToastContainer/useToastContainerContextValues.ts @@ -4,7 +4,7 @@ import { ToastContainerContextValues, ToastContainerState } from './ToastContain export function useToastContainerContextValues_unstable(state: ToastContainerState): ToastContainerContextValues { const { close, intent, titleId, bodyId } = state; - const toastContext = React.useMemo( + const toastContainerContext = React.useMemo( () => ({ close, intent, @@ -15,6 +15,6 @@ export function useToastContainerContextValues_unstable(state: ToastContainerSta ); return { - toast: toastContext, + toast: toastContainerContext, }; } diff --git a/packages/react-components/react-toast/src/components/ToastTitle/ToastTitle.types.ts b/packages/react-components/react-toast/src/components/ToastTitle/ToastTitle.types.ts index 602a0d4c1efa5..6b4676098291e 100644 --- a/packages/react-components/react-toast/src/components/ToastTitle/ToastTitle.types.ts +++ b/packages/react-components/react-toast/src/components/ToastTitle/ToastTitle.types.ts @@ -1,5 +1,6 @@ import type { ComponentProps, ComponentState, Slot } from '@fluentui/react-utilities'; -import { ToastContextValue } from '../../contexts/toastContext'; +import { BackgroundAppearanceContextValue } from '@fluentui/react-shared-contexts'; +import { ToastContainerContextValue } from '../../contexts/toastContainerContext'; export type ToastTitleSlots = { root: NonNullable>; @@ -15,4 +16,7 @@ export type ToastTitleProps = ComponentProps & {}; /** * State used in rendering ToastTitle */ -export type ToastTitleState = ComponentState & Pick; +export type ToastTitleState = ComponentState & + Pick & { + backgroundAppearance: BackgroundAppearanceContextValue; + }; diff --git a/packages/react-components/react-toast/src/components/ToastTitle/useToastTitle.tsx b/packages/react-components/react-toast/src/components/ToastTitle/useToastTitle.tsx index 28d80d7f50a8f..df5564e4b07b3 100644 --- a/packages/react-components/react-toast/src/components/ToastTitle/useToastTitle.tsx +++ b/packages/react-components/react-toast/src/components/ToastTitle/useToastTitle.tsx @@ -2,9 +2,10 @@ import * as React from 'react'; import { CheckmarkCircleFilled, DismissCircleFilled, InfoFilled, WarningFilled } from '@fluentui/react-icons'; import { getNativeElementProps, resolveShorthand } from '@fluentui/react-utilities'; +import { useBackgroundAppearance } from '@fluentui/react-shared-contexts'; import type { ToastTitleProps, ToastTitleState } from './ToastTitle.types'; -import { useToastContext } from '../../contexts/toastContext'; +import { useToastContainerContext } from '../../contexts/toastContainerContext'; /** * Create the state required to render ToastTitle. @@ -16,7 +17,8 @@ import { useToastContext } from '../../contexts/toastContext'; * @param ref - reference to root HTMLElement of ToastTitle */ export const useToastTitle_unstable = (props: ToastTitleProps, ref: React.Ref): ToastTitleState => { - const { intent, titleId } = useToastContext(); + const { intent, titleId } = useToastContainerContext(); + const backgroundAppearance = useBackgroundAppearance(); /** Determine the role and media to render based on the intent */ let defaultIcon; @@ -43,12 +45,13 @@ export const useToastTitle_unstable = (props: ToastTitleProps, ref: React.Ref = { root: 'fui-ToastTitle', @@ -13,6 +13,7 @@ const useRootBaseClassName = makeResetStyles({ display: 'flex', alignItems: 'center', gridColumnEnd: 3, + color: tokens.colorNeutralForeground1, }); const useMediaBaseClassName = makeResetStyles({ @@ -21,6 +22,7 @@ const useMediaBaseClassName = makeResetStyles({ gridColumnEnd: 2, paddingRight: '8px', fontSize: '16px', + color: tokens.colorNeutralForeground1, }); const useActionBaseClassName = makeResetStyles({ @@ -31,6 +33,20 @@ const useActionBaseClassName = makeResetStyles({ color: tokens.colorBrandForeground1, }); +const useInvertedStyles = makeStyles({ + root: { + color: tokens.colorNeutralForegroundInverted, + }, + + action: { + color: tokens.colorBrandForegroundInverted, + }, + + media: { + color: tokens.colorNeutralForegroundInverted, + }, +}); + const useIntentIconStyles = makeStyles({ success: { // FIXME https://github.com/microsoft/fluentui/issues/28219 @@ -47,7 +63,22 @@ const useIntentIconStyles = makeStyles({ info: { color: tokens.colorNeutralForeground2, }, - progress: { +}); + +const useIntentIconStylesInverted = makeStyles({ + success: { + // FIXME https://github.com/microsoft/fluentui/issues/28219 + color: tokens.colorPaletteGreenForegroundInverted, + }, + error: { + // FIXME https://github.com/microsoft/fluentui/issues/28219 + color: tokens.colorPaletteRedForegroundInverted, + }, + warning: { + // FIXME https://github.com/microsoft/fluentui/issues/28219 + color: tokens.colorPaletteYellowForegroundInverted, + }, + info: { color: tokens.colorNeutralForegroundInverted2, }, }); @@ -60,20 +91,34 @@ export const useToastTitleStyles_unstable = (state: ToastTitleState): ToastTitle const actionBaseClassName = useActionBaseClassName(); const mediaBaseClassName = useMediaBaseClassName(); const intentIconStyles = useIntentIconStyles(); + const intentIconStylesInverted = useIntentIconStylesInverted(); const { intent } = state; - state.root.className = mergeClasses(toastTitleClassNames.root, rootBaseClassName, state.root.className); + const invertedStyles = useInvertedStyles(); + state.root.className = mergeClasses( + toastTitleClassNames.root, + rootBaseClassName, + state.backgroundAppearance === 'inverted' && invertedStyles.root, + state.root.className, + ); if (state.media) { state.media.className = mergeClasses( toastTitleClassNames.media, mediaBaseClassName, + state.backgroundAppearance === 'inverted' && invertedStyles.media, state.media.className, intent && intentIconStyles[intent], + intent && state.backgroundAppearance === 'inverted' && intentIconStylesInverted[intent], ); } if (state.action) { - state.action.className = mergeClasses(toastTitleClassNames.action, actionBaseClassName, state.action.className); + state.action.className = mergeClasses( + toastTitleClassNames.action, + actionBaseClassName, + state.backgroundAppearance === 'inverted' && invertedStyles.action, + state.action.className, + ); } return state; diff --git a/packages/react-components/react-toast/src/components/ToastTrigger/useToastTrigger.ts b/packages/react-components/react-toast/src/components/ToastTrigger/useToastTrigger.ts index 54736eb886479..cec4fd57dc76f 100644 --- a/packages/react-components/react-toast/src/components/ToastTrigger/useToastTrigger.ts +++ b/packages/react-components/react-toast/src/components/ToastTrigger/useToastTrigger.ts @@ -2,7 +2,7 @@ import * as React from 'react'; import { applyTriggerPropsToChildren, getTriggerChild, useEventCallback } from '@fluentui/react-utilities'; import { useARIAButtonProps } from '@fluentui/react-aria'; import type { ToastTriggerProps, ToastTriggerState } from './ToastTrigger.types'; -import { useToastContext } from '../../contexts/toastContext'; +import { useToastContainerContext } from '../../contexts/toastContainerContext'; /** * A non-visual component that wraps its child @@ -15,7 +15,7 @@ import { useToastContext } from '../../contexts/toastContext'; */ export const useToastTrigger_unstable = (props: ToastTriggerProps): ToastTriggerState => { const { children, disableButtonEnhancement = false } = props; - const { close } = useToastContext(); + const { close } = useToastContainerContext(); const child = getTriggerChild(children); diff --git a/packages/react-components/react-toast/src/contexts/toastContainerContext.tsx b/packages/react-components/react-toast/src/contexts/toastContainerContext.tsx new file mode 100644 index 0000000000000..9ce151cf59b5a --- /dev/null +++ b/packages/react-components/react-toast/src/contexts/toastContainerContext.tsx @@ -0,0 +1,22 @@ +import * as React from 'react'; +import { ToastIntent } from '../state/types'; + +export type ToastContainerContextValue = { + close: () => void; + intent: ToastIntent | undefined; + bodyId: string; + titleId: string; +}; + +const toastContainerContextDefaultValue: ToastContainerContextValue = { + close: () => null, + intent: undefined, + bodyId: '', + titleId: '', +}; + +const ToastContainerContext = React.createContext(undefined); + +export const ToastContainerContextProvider = ToastContainerContext.Provider; +export const useToastContainerContext = () => + React.useContext(ToastContainerContext) ?? toastContainerContextDefaultValue; diff --git a/packages/react-components/react-toast/src/contexts/toastContext.tsx b/packages/react-components/react-toast/src/contexts/toastContext.tsx deleted file mode 100644 index 8355bc4d074f9..0000000000000 --- a/packages/react-components/react-toast/src/contexts/toastContext.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import * as React from 'react'; -import { ToastIntent } from '../state/types'; - -export type ToastContextValue = { - close: () => void; - intent: ToastIntent | undefined; - titleId: string; - bodyId: string; -}; - -const toastContextDefaultValue: ToastContextValue = { - close: () => null, - intent: undefined, - titleId: '', - bodyId: '', -}; - -const toastContext = React.createContext(undefined); - -export const ToastContextProvider = toastContext.Provider; -export const useToastContext = () => React.useContext(toastContext) ?? toastContextDefaultValue; diff --git a/packages/react-components/react-toast/stories/Toast/InvertedAppearance.stories.tsx b/packages/react-components/react-toast/stories/Toast/InvertedAppearance.stories.tsx new file mode 100644 index 0000000000000..50cbd859e7faa --- /dev/null +++ b/packages/react-components/react-toast/stories/Toast/InvertedAppearance.stories.tsx @@ -0,0 +1,27 @@ +import * as React from 'react'; +import { Toaster, useToastController, Toast, ToastTitle, ToastBody, ToastFooter } from '@fluentui/react-toast'; +import { useId, Link, Button } from '@fluentui/react-components'; + +export const InvertedAppearance = () => { + const toasterId = useId('toaster'); + const { dispatchToast } = useToastController(toasterId); + const notify = () => + dispatchToast( + + Undo}>Email sent + This is a toast body + + Action + Action + + , + { intent: 'success' }, + ); + + return ( + <> + + + + ); +}; diff --git a/packages/react-components/react-toast/stories/Toast/index.stories.tsx b/packages/react-components/react-toast/stories/Toast/index.stories.tsx index c8eb27062882c..d60fb71abfbda 100644 --- a/packages/react-components/react-toast/stories/Toast/index.stories.tsx +++ b/packages/react-components/react-toast/stories/Toast/index.stories.tsx @@ -1,6 +1,7 @@ import { Toast, ToastTitle, ToastBody, ToastFooter, Toaster } from '@fluentui/react-toast'; export { Default } from './Default.stories'; export { Intent } from './Intent.stories'; +export { InvertedAppearance } from './InvertedAppearance.stories'; export { DefaultToastOptions } from './DefaultToastOptions.stories'; export { CustomTimeout } from './CustomTimeout.stories'; export { DismissToastWithAction } from './DismissToastWithAction.stories';