> Leaf UI 0.6.0 · Package: @ifhover/leaf-ui · Source: b30c3d3a8fa9c5e15d0d0522cebfbd33f60c6b06
> Browser documentation: https://ifhover.github.io/leaf-ui/v/0.6.0/en/components/message.html

> For AI agents: the complete documentation index is available at https://ifhover.github.io/leaf-ui/v/0.6.0/en/llms.txt, the full documentation bundle is available at https://ifhover.github.io/leaf-ui/v/0.6.0/en/llms-full.txt.

# Message

Provide brief feedback about an operation.

## Set up once

Wrap your application in `ConfigProvider`. It manages messages automatically, so pages and business components can call `useMessage` directly.

```tsx
import { ConfigProvider } from '@ifhover/leaf-ui';

export function Root() {
  return <ConfigProvider><App /></ConfigProvider>;
}
```

Applications already using `ConfigProvider` need no additional setup. Call `useMessage` in its descendants; the returned `message` can also be passed to business functions.

## Messages and updates


Save asynchronouslyInformationErrorSuccessWarningClear messages

basic.tsx

Copy code

```tsx lineNumbers file="../../../src/examples/en/message/basic.tsx"
import { Button, Flex, useMessage } from '@ifhover/leaf-ui';

export function MessageBasic() {
  const { message } = useMessage();
  async function save() {
    const key = message.loading('Saving');
    await new Promise((resolve) => setTimeout(resolve, 1200));
    message.open({
      key,
      type: 'success',
      content: 'Saved successfully',
      duration: 3,
      closable: true,
    });
  }
  return (
    <Flex gap="md" align="center" wrap justify="center">
      <Button onClick={save}>Save asynchronously</Button>
      <Button variant="outline" onClick={() => message.info('An information message')}>
        Information
      </Button>
      <Button danger variant="outline" onClick={() => message.error('Failed. Please try again.')}>
        Error
      </Button>
      <Button variant="outline" onClick={() => message.success('Completed successfully')}>
        Success
      </Button>
      <Button variant="outline" onClick={() => message.warning('Please check your input')}>
        Warning
      </Button>
      <Button variant="ghost" onClick={() => message.close()}>
        Clear messages
      </Button>
    </Flex>
  );
}
```

Expand code

## Share between components

These two buttons belong to different components. Use the same `key` to update one message, even when switching pages.


Start publishingUpdate from another component

shared.tsx

Copy code

```tsx lineNumbers file="../../../src/examples/en/message/shared.tsx"
import { Button, Flex, useMessage } from '@ifhover/leaf-ui';

function PublishAction() {
  const { message } = useMessage();
  return (
    <Button
      variant="outline"
      onClick={() =>
        message.open({ key: 'shared-publish', type: 'loading', content: 'Publishing the project' })
      }
    >
      Start publishing
    </Button>
  );
}

function PublishResult() {
  const { message } = useMessage();
  return (
    <Button
      onClick={() =>
        message.open({
          key: 'shared-publish',
          type: 'success',
          content: 'Project published',
          duration: 3,
          closable: true,
        })
      }
    >
      Update from another component
    </Button>
  );
}

export function MessageShared() {
  return (
    <Flex gap="md" align="center" wrap justify="center">
      <PublishAction />
      <PublishResult />
    </Flex>
  );
}
```

Expand code

## Multiple messages

When a message closes, those below it move up smoothly. Content of different heights collapses using its actual space.


Show three messages

stack.tsx

Copy code

```tsx lineNumbers file="../../../src/examples/en/message/stack.tsx"
import { Button, useMessage } from '@ifhover/leaf-ui';

export function MessageStack() {
  const { message } = useMessage();
  return (
    <Button
      variant="outline"
      onClick={() => {
        message.close();
        message.open({
          key: 'stack-first',
          content: 'The first message closes after one second',
          duration: 1,
        });
        message.open({
          key: 'stack-second',
          content: 'Following messages move up smoothly',
          duration: 5,
          closable: true,
        });
        message.open({
          key: 'stack-third',
          content:
            'Longer messages collapse using their actual height, without jumping to a new position.',
          type: 'success',
          duration: 7,
          closable: true,
        });
      }}
    >
      Show three messages
    </Button>
  );
}
```

Expand code

## useMessage API

| Property  | Type                        | Default | Description                                        |
| --------- | --------------------------- | ------- | -------------------------------------------------- |
| `message` | [`MessageApi`](#messageapi) | —       | Call the queue managed by the application provider |

## MessageProvider API

If your application has no `ConfigProvider`, add `MessageProvider` at the entry point. An explicit `MessageProvider` also creates an independent queue for a region.

```tsx
import { MessageProvider } from '@ifhover/leaf-ui';

export function Root() {
  return <MessageProvider><App /></MessageProvider>;
}
```

| Property   | Type        | Default | Description                   |
| ---------- | ----------- | ------- | ----------------------------- |
| `children` | `ReactNode` | —       | Components sharing this queue |

## MessageApi

| Property                           | Type                                                     | Default | Description                                   |
| ---------------------------------- | -------------------------------------------------------- | ------- | --------------------------------------------- |
| `open`                             | [`(options: MessageOptions) => string`](#messageoptions) | —       | Create or update by key; returns the key      |
| `success / info / warning / error` | `(content: ReactNode, duration?: number) => string`      | —       | Show feedback of the specified type           |
| `loading`                          | `(content: ReactNode) => string`                         | —       | Persistent loading message; returns the key   |
| `close`                            | `(key?: string) => void`                                 | —       | Close one message, or all when key is omitted |

## MessageOptions

| Property   | Type                                                       | Default   | Description                                                 |
| ---------- | ---------------------------------------------------------- | --------- | ----------------------------------------------------------- |
| `key`      | `string`                                                   | Generated | Use the same key to update a message                        |
| `content`  | `ReactNode`                                                | Required  | Message content                                             |
| `type`     | `'success' \| 'info' \| 'warning' \| 'error' \| 'loading'` | `'info'`  | Message type                                                |
| `duration` | `number`                                                   | `3`       | Seconds before dismissal; 0 persists, loading defaults to 0 |
| `closable` | `boolean`                                                  | `false`   | Show a close button                                         |
| `onClose`  | `() => void`                                               | —         | Called once when dismissal starts                           |

## Message API

| Property               | Type                                                       | Default  | Description                                            |
| ---------------------- | ---------------------------------------------------------- | -------- | ------------------------------------------------------ |
| `open`                 | `boolean`                                                  | Required | Controlled visibility                                  |
| `content`              | `ReactNode`                                                | Required | Message content                                        |
| `type`                 | `'success' \| 'info' \| 'warning' \| 'error' \| 'loading'` | `'info'` | Message type                                           |
| `duration`             | `number`                                                   | `3`      | Duration in seconds; 0 persists, loading defaults to 0 |
| `closable`             | `boolean`                                                  | `false`  | Close button                                           |
| `onClose / afterClose` | `() => void`                                               | —        | Requests closure / closing animation completed         |

## Types

Import types when defining reusable component props or assembling options.

```ts
import type { MessageProps, MessageOptions, MessageApi, MessageProviderProps } from '@ifhover/leaf-ui';
```

## Usage notes

Prefer `useMessage`. Update a loading message with its `key` to show the result. Timers pause while a message is hovered or focused and resume with the remaining time.

Components under the same entry provider share a queue. `close()` closes all its messages; `close(key)` closes one. Nested `ConfigProvider` regions share that queue, while each message keeps the theme and language of the calling component.

Messages continue after the calling component unmounts, and asynchronous work can update them through the same `message` instance. Unmounting the entry provider clears its messages and timers. Separate React applications and SSR requests have independent queues.

`Message` also supports declarative rendering; set `open=false` after `onClose`.
