# Message bar

A message bar communicates important information about the state of the entire product or the surface where it appears, such as a page, drawer, dialog, or card.

## Best practices

### Do

- Match intent to the situation: informational, success, warning, or error.
- Include an action or link in warning and error messages.
- Stack messages from most critical to least critical.

### Don't

- Use a message bar to prevent a destructive action; use a dialog.
- Use it for time-sensitive status originating elsewhere; use a toast.
- Overload the body with long explanations.

## Behavior and states

- Message bar content never truncates.
- After the second line, reflow pushes actions below the body.
- Message bars are dismissible with a Close button.
- A dismissed warning or error reappears in the next session until the problem is resolved.
- If the message is intended to prevent a destructive action, try a dialog instead.
- If the message is time-sensitive, but relates to an activity or status from a different location, try a toast notification instead.

## Default

Source: CoreAI.

Shows an informational message with actions and a dismiss control.

[Download source](/coreai-design-system/source/examples/components-messagebar--default.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import { MessageBar } from "@coreai-ds/react-components";
import { MessageBarBody } from "@coreai-ds/react-components";
import { MessageBarTitle } from "@coreai-ds/react-components";
import { Link } from "@coreai-ds/react-components";
import { MessageBarActions } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { DismissRegular } from "@fluentui/react-icons";

export const Default = () => {
    return (<MessageBar>
        <MessageBarBody>
          <MessageBarTitle>Descriptive title</MessageBarTitle>
          Message providing information to the user with actionable insights. <Link>Link</Link>
        </MessageBarBody>
        <MessageBarActions containerAction={<Button aria-label="dismiss" appearance="transparent" icon={<DismissRegular />}/>}>
          <Button>Action</Button>
          <Button>Action</Button>
        </MessageBarActions>
      </MessageBar>);
};

export default Default;
```

## API

Generated CoreAI prop summaries, not replacement type declarations. Most native DOM/event and ARIA props are omitted. `?` means optional; JSDoc shows defaults, deprecations, and conditional requirements. Defaults assume the standard CoreAI provider.

### MessageBar API

```ts
interface MessageBarProps {
  as?: "div";

  /**
   * Rendered when the component is in multiline layout to guarantee correct spacing even
   * if no actions are rendered. When actions are rendered, the default actions grid area will render
   * over this element
   *
   * NOTE: If you are using this slot, this probably means that you are using the MessageBar without
   * actions, this is not recommended from an accesibility point of view
   */
  bottomReflowSpacer?: WithSlotShorthandValue<{ as?: "div"; } & Omit<Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & { ref?: ((instance: HTMLDivElement | null) => void) | RefObject<HTMLDivElement> | null; }, "children"> & { children?: any; }> | null | undefined;

  children?: any;

  className?: string;

  icon?: WithSlotShorthandValue<{ as?: "div"; } & Omit<Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & { ref?: ((instance: HTMLDivElement | null) => void) | RefObject<HTMLDivElement> | null; }, "children"> & { children?: any; }> | null | undefined;

  /**
   * The intent of the message. In addition to Fluent's options, CoreAI adds
   * `"brand"` for a branded informational callout.
   *
   * - `"info"`: Neutral informational surface.
   * - `"warning"`: Warning status ramp.
   * - `"error"`: Danger status ramp.
   * - `"success"`: Success status ramp.
   * - `"brand"`: Brand primary ramp.
   * @default 'info'
   */
  intent?: "brand" | "success" | "warning" | "error" | "info";

  layout?: "auto" | "multiline" | "singleline";

  politeness?: "assertive" | "polite";

  ref?: Ref<HTMLDivElement>;

  /**
   * Use squal for page level messages and rounded for component level messages
   * @default rounded
   */
  shape?: "rounded" | "square";

  style?: CSSProperties;
}
```

### MessageBarActions API

MessageBarActions component

```ts
interface MessageBarActionsProps {
  as?: "div";

  children?: any;

  className?: string;

  /**
   * Generally the 'Dismiss' button for the MessageBar
   */
  containerAction?: WithSlotShorthandValue<{ as?: "div"; } & Omit<Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & { ref?: ((instance: HTMLDivElement | null) => void) | RefObject<HTMLDivElement> | null; }, "children"> & { children?: any; }> | null | undefined;

  ref?: Ref<HTMLDivElement>;

  style?: CSSProperties;
}
```

### MessageBarBody API

MessageBarBody component

```ts
interface MessageBarBodyProps {
  as?: "div";

  children?: any;

  className?: string;

  ref?: Ref<HTMLDivElement>;

  style?: CSSProperties;
}
```

### MessageBarGroup API

MessageBarGroup component

```ts
interface MessageBarGroupProps {
  animate?: "both" | "exit-only";

  as?: "div";

  children?: any;

  className?: string;

  ref?: Ref<HTMLDivElement>;

  style?: CSSProperties;
}
```

### MessageBarTitle API

MessageBarTitle component

```ts
interface MessageBarTitleProps {
  as?: "span";

  children?: any;

  className?: string;

  ref?: Ref<HTMLSpanElement>;

  style?: CSSProperties;
}
```

## Implementation

CoreAI 0.12.0; Fluent 9.74.9.

[Setup and dependencies](/coreai-design-system/guides/Package.md).

Import components from `@coreai-ds/react-components`. CoreAI guidance above takes precedence over API demonstration examples.

## Actions

Source: Fluent, adapted for CoreAI.

The `MessageBar` can have different actions.

[Download source](/coreai-design-system/source/examples/components-messagebar--actions.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { MessageBar } from "@coreai-ds/react-components";
import { MessageBarBody } from "@coreai-ds/react-components";
import { MessageBarTitle } from "@coreai-ds/react-components";
import { Link } from "@coreai-ds/react-components";
import { MessageBarActions } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { DismissRegular } from "@fluentui/react-icons";
import * as React from 'react';

export const Actions = (): JSXElement => (<MessageBar>
    <MessageBarBody>
      <MessageBarTitle>Descriptive title</MessageBarTitle>
      Message providing information to the user with actionable insights. <Link>Link</Link>
    </MessageBarBody>
    <MessageBarActions containerAction={<Button appearance="transparent" aria-label="Dismiss" icon={<DismissRegular />}/>}>
      <Button>Action</Button>
      <Button>Action</Button>
    </MessageBarActions>
  </MessageBar>);

export default Actions;
```

## Animation

Source: Fluent, adapted for CoreAI.

Enter animations are also handled within the `MessageBarGroup`. However avoid entry animations for MessageBar
components on page load. However, MessageBar components that are mounted during the lifecycle of an
app can use enter animations.

> ⚠️ Animation will only function if the only children of `MessageBarGroup` are `MessageBar` components.
Do not wrap `MessageBar` with other components. This is a known limitation we are actively working on.

[Download source](/coreai-design-system/source/examples/components-messagebar--animation.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { tokens } from "@coreai-ds/react-components";
import * as React from 'react';
import type { MessageBarGroupProps } from "@coreai-ds/react-components";
import type { MessageBarIntent } from "@coreai-ds/react-components";
import { Field } from "@coreai-ds/react-components";
import { RadioGroup } from "@coreai-ds/react-components";
import { Radio } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { MessageBarGroup } from "@coreai-ds/react-components";
import { MessageBar } from "@coreai-ds/react-components";
import { MessageBarBody } from "@coreai-ds/react-components";
import { MessageBarTitle } from "@coreai-ds/react-components";
import { Link } from "@coreai-ds/react-components";
import { MessageBarActions } from "@coreai-ds/react-components";
import { DismissRegular } from "@fluentui/react-icons";

const useStyles = makeStyles({
    controlsContainer: {
        display: 'flex',
        flexDirection: 'row',
    },
    messageBarGroup: {
        padding: tokens.spacingHorizontalMNudge,
        display: 'flex',
        flexDirection: 'column',
        marginTop: '10px',
        gap: '10px',
        height: '300px',
        overflow: 'auto',
        border: `2px solid ${tokens.colorBrandForeground1}`,
    },
    field: {
        flexGrow: 1,
        alignItems: 'center',
        gridTemplateColumns: 'max-content auto',
    },
    buttonGroup: {
        display: 'flex',
        gap: '5px',
    },
});

interface ExampleMessage {
    intent: MessageBarIntent;
    id: number;
}

const intents: MessageBarIntent[] = ['info', 'warning', 'error', 'success'];

export const Animation = (): JSXElement => {
    const styles = useStyles();
    const counterRef = React.useRef(0);
    const [animate, setAnimate] = React.useState<MessageBarGroupProps['animate']>('both');
    const [messages, setMessages] = React.useState<ExampleMessage[]>([]);
    const addMessage = () => {
        const intent = intents[Math.floor(Math.random() * intents.length)];
        const newMessage = { intent, id: counterRef.current++ };
        setMessages(s => [newMessage, ...s]);
    };
    const clearMessages = () => setMessages([]);
    const dismissMessage = (messageId: number) => setMessages(s => s.filter(entry => entry.id !== messageId));
    return (<div>
      <div className={styles.controlsContainer}>
        <Field className={styles.field} label="Select animation type:" orientation="horizontal">
          <RadioGroup layout="horizontal" onChange={(_, { value }) => setAnimate(value as MessageBarGroupProps['animate'])} value={animate}>
            <Radio label="both" value="both"/>
            <Radio label="exit-only" value="exit-only"/>
          </RadioGroup>
        </Field>

        <div className={styles.buttonGroup}>
          <Button appearance="primary" onClick={addMessage}>
            Add message
          </Button>
          <Button onClick={clearMessages}>Clear</Button>
        </div>
      </div>

      <MessageBarGroup animate={animate} className={styles.messageBarGroup}>
        {messages.map(({ intent, id }) => (<MessageBar key={`${intent}-${id}`} intent={intent}>
            <MessageBarBody>
              <MessageBarTitle>Descriptive title</MessageBarTitle>
              Message providing information to the user with actionable insights. <Link>Link</Link>
            </MessageBarBody>
            <MessageBarActions containerAction={<Button onClick={() => dismissMessage(id)} aria-label="dismiss" appearance="transparent" icon={<DismissRegular />}/>}/>
          </MessageBar>))}
      </MessageBarGroup>
    </div>);
};

export default Animation;
```

## Dismiss

Source: Fluent, adapted for CoreAI.

MessageBar components should be used in a `MessageBarGroup` when possible to enable exit animations.
Once inside a `MessageBarGroup` component, the default exit animation will trigger automatically when the
component is unmounted from DOM.

[Download source](/coreai-design-system/source/examples/components-messagebar--dismiss.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { tokens } from "@coreai-ds/react-components";
import * as React from 'react';
import type { MessageBarIntent } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { MessageBarGroup } from "@coreai-ds/react-components";
import { MessageBar } from "@coreai-ds/react-components";
import { MessageBarBody } from "@coreai-ds/react-components";
import { MessageBarTitle } from "@coreai-ds/react-components";
import { Link } from "@coreai-ds/react-components";
import { MessageBarActions } from "@coreai-ds/react-components";
import { DismissRegular } from "@fluentui/react-icons";

const useStyles = makeStyles({
    messageBarGroup: {
        padding: tokens.spacingHorizontalMNudge,
        display: 'flex',
        flexDirection: 'column',
        marginTop: '10px',
        gap: '10px',
        height: '300px',
        overflow: 'auto',
        border: `2px solid ${tokens.colorBrandForeground1}`,
    },
    buttonGroup: {
        display: 'flex',
        justifyContent: 'end',
        gap: '5px',
    },
});

interface ExampleMessage {
    intent: MessageBarIntent;
    id: number;
}

const intents: MessageBarIntent[] = ['info', 'warning', 'error', 'success'];

export const Dismiss = (): JSXElement => {
    const styles = useStyles();
    const counterRef = React.useRef(0);
    const [messages, setMessages] = React.useState<ExampleMessage[]>([]);
    const addMessage = () => {
        const intent = intents[Math.floor(Math.random() * intents.length)];
        const newMessage = { intent, id: counterRef.current++ };
        setMessages(s => [newMessage, ...s]);
    };
    const clearMessages = () => setMessages([]);
    const dismissMessage = (messageId: number) => setMessages(s => s.filter(entry => entry.id !== messageId));
    return (<>
      <div className={styles.buttonGroup}>
        <Button appearance="primary" onClick={addMessage}>
          Add message
        </Button>
        <Button onClick={clearMessages}>Clear</Button>
      </div>

      <MessageBarGroup className={styles.messageBarGroup}>
        {messages.map(({ intent, id }) => (<MessageBar key={`${intent}-${id}`} intent={intent}>
            <MessageBarBody>
              <MessageBarTitle>Descriptive title</MessageBarTitle>
              Message providing information to the user with actionable insights. <Link>Link</Link>
            </MessageBarBody>
            <MessageBarActions containerAction={<Button onClick={() => dismissMessage(id)} aria-label="dismiss" appearance="transparent" icon={<DismissRegular />}/>}/>
          </MessageBar>))}
      </MessageBarGroup>
    </>);
};

export default Dismiss;
```

## Intent

Source: CoreAI.

In addition to Fluent's four preset intents (`info`, `warning`, `error`,
`success`), CoreAI adds a `brand` intent styled with the brand token ramp
(`colorBrandBackground2` surface, `colorBrandStroke2` border,
`colorBrandForeground1` icon). It maps internally to Fluent's `info`
intent, so it keeps the same icon and polite `aria-live` announcement.

[Download source](/coreai-design-system/source/examples/components-messagebar--intent.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { MessageBarIntent } from "@coreai-ds/react-components";
import { MessageBar } from "@coreai-ds/react-components";
import { MessageBarBody } from "@coreai-ds/react-components";
import { MessageBarTitle } from "@coreai-ds/react-components";
import { Link } from "@coreai-ds/react-components";

export const Intent = () => {
    // CoreAI adds `"brand"` on top of Fluent's four preset intents.
    const intents: MessageBarIntent[] = ['info', 'warning', 'error', 'success', 'brand'];
    const styles = /* css */ `
      .message-bar-intent-example {
        display: flex;
        flex-direction: column;
        gap: 10px;
      }
    `;
    return (<>
        <style>{styles}</style>
        <div className="message-bar-intent-example">
          {intents.map((intent) => (<MessageBar key={intent} intent={intent}>
              <MessageBarBody>
                <MessageBarTitle>Intent {intent}</MessageBarTitle>
                Message providing information to the user with actionable insights.{' '}
                <Link>Link</Link>
              </MessageBarBody>
            </MessageBar>))}
        </div>
      </>);
};

export default Intent;
```

## Manual Layout

Source: Fluent, adapted for CoreAI.

It's possible to opt out of automatic reflow with the `layout` prop. This can be useful if an application
has an existing responsive design mechanism.

[Download source](/coreai-design-system/source/examples/components-messagebar--manual-layout.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import * as React from 'react';
import { Switch } from "@coreai-ds/react-components";
import { MessageBar } from "@coreai-ds/react-components";
import { MessageBarBody } from "@coreai-ds/react-components";
import { MessageBarTitle } from "@coreai-ds/react-components";
import { Link } from "@coreai-ds/react-components";
import { MessageBarActions } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { DismissRegular } from "@fluentui/react-icons";

const intents = ['info', 'warning', 'error', 'success'] as const;

export const ManualLayout = (): JSXElement => {
    const [single, setSingle] = React.useState(true);
    return (<>
      <Switch label={single ? 'Single line layout' : 'Multi line layout'} checked={single} onChange={(_, { checked }) => setSingle(checked)}/>
      <div style={{ display: 'flex', flexDirection: 'column', gap: '10px' }}>
        {intents.map(intent => (<MessageBar key={intent} layout={single ? 'singleline' : 'multiline'} intent={intent}>
            <MessageBarBody>
              <MessageBarTitle>Descriptive title</MessageBarTitle>
              Message providing information to the user with actionable insights. <Link>Link</Link>
            </MessageBarBody>
            <MessageBarActions containerAction={<Button aria-label="dismiss" appearance="transparent" icon={<DismissRegular />}/>}>
              <Button>Action</Button>
              <Button>Action</Button>
            </MessageBarActions>
          </MessageBar>))}
      </div>
    </>);
};

export default ManualLayout;
```

## Reflow

Source: Fluent, adapted for CoreAI.

The `MessageBar` will reflow by default once the body content wraps to a second line. This changes the layout
of the actions in the MessageBar.

[Download source](/coreai-design-system/source/examples/components-messagebar--reflow.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { tokens } from "@coreai-ds/react-components";
import * as React from 'react';
import { Switch } from "@coreai-ds/react-components";
import { mergeClasses } from "@coreai-ds/react-components";
import { MessageBar } from "@coreai-ds/react-components";
import { MessageBarBody } from "@coreai-ds/react-components";
import { MessageBarTitle } from "@coreai-ds/react-components";
import { Link } from "@coreai-ds/react-components";
import { MessageBarActions } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { DismissRegular } from "@fluentui/react-icons";

const useStyles = makeStyles({
    compact: {
        width: '600px',
    },
    resizableArea: {
        display: 'flex',
        flexDirection: 'column',
        padding: '30px 10px',
        gap: '10px',
        border: `2px solid ${tokens.colorBrandBackground}`,
        position: 'relative',
        overflow: 'hidden',
        '::after': {
            content: `'Resizable Area'`,
            position: 'absolute',
            padding: '1px 4px 1px',
            top: '-2px',
            left: '-2px',
            fontFamily: 'monospace',
            fontSize: '15px',
            fontWeight: 900,
            lineHeight: 1,
            letterSpacing: '1px',
            color: tokens.colorNeutralForegroundOnBrand,
            backgroundColor: tokens.colorBrandBackground,
        },
    },
});

export const Reflow = (): JSXElement => {
    const styles = useStyles();
    const [compact, setCompact] = React.useState(true);
    return (<>
      <Switch label={compact ? 'Compact width' : 'Full width'} checked={compact} onChange={(_, { checked }) => setCompact(checked)}/>
      <div className={mergeClasses(styles.resizableArea, compact && styles.compact)}>
        <MessageBar intent="success">
          <MessageBarBody>
            <MessageBarTitle>Descriptive title</MessageBarTitle>
            Message providing information to the user with actionable insights. <Link>Link</Link>
          </MessageBarBody>
          <MessageBarActions containerAction={<Button aria-label="dismiss" appearance="transparent" icon={<DismissRegular />}/>}>
            <Button>Action</Button>
            <Button>Action</Button>
          </MessageBarActions>
        </MessageBar>
      </div>
    </>);
};

export default Reflow;
```

## Shape

Source: Fluent, adapted for CoreAI.

MessageBar can have either rounded or square corners, please follow the usage guidance for these shapes:
- **_rounded_** used for component level message bars
- **_square_** used for page/app level message bars

[Download source](/coreai-design-system/source/examples/components-messagebar--shape.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { MessageBar } from "@coreai-ds/react-components";
import { MessageBarBody } from "@coreai-ds/react-components";
import { MessageBarTitle } from "@coreai-ds/react-components";
import * as React from 'react';

const useClasses = makeStyles({
    container: {
        display: 'flex',
        flexDirection: 'column',
        gap: '10px',
    },
});

export const Shape = (): JSXElement => {
    const classes = useClasses();
    return (<div className={classes.container}>
      <MessageBar shape="rounded">
        <MessageBarBody>
          <MessageBarTitle>Rounded shape</MessageBarTitle>
          This message has rounded shape.
        </MessageBarBody>
      </MessageBar>
      <MessageBar shape="square">
        <MessageBarBody>
          <MessageBarTitle>Square shape</MessageBarTitle>
          This message has square shape.
        </MessageBarBody>
      </MessageBar>
    </div>);
};

export default Shape;
```

## Resources

- [Figma component](https://www.figma.com/design/eXfSQrRg3poHRgmr0ivN5V/CoreAI-Figma-Library?node-id=314567-157305)
- [Fluent guidance](https://fluent2.microsoft.design/components/web/react/core/messagebar/usage)