Components · Feedback
Toast
A brief, auto-dismissing confirmation of an action — rendered through antd's message API.
Examples
<!-- Paste-and-run: save as .html and open in a browser. No build step, no bundler.
Toast is a COMPOSITE (antd's message API, no framework-free element), so its HTML form is a
CDN-React page — React + antd load from a CDN (esm.sh) and mount on open. It consumes the
SAME shared `toastTheme` the React/Vue wrappers use, so it renders the DS V3 look (white
pill, radius 8, ink text). Keeps antd's built-in enter/leave motion.
No JSX here (JSX needs a compiler) — we use React.createElement via the `h` alias. -->
<div id="root"></div>
<script type="module">
import React from 'https://esm.sh/react@18';
import { createRoot } from 'https://esm.sh/react-dom@18/client';
import { ConfigProvider, message, Button, Space } from 'https://esm.sh/antd@6?deps=react@18,react-dom@18';
import { toastTheme } from 'https://cdn.jsdelivr.net/gh/ahaslides-product/ahaslides-design@master/lib/toast-theme.js';
const h = React.createElement;
function App() {
// v6: the hook + ctx so every toast consumes the theme. Static message.success() is FORBIDDEN.
const [api, ctx] = message.useMessage();
return h(ConfigProvider, { theme: toastTheme },
ctx,
h(Space, { wrap: true },
h(Button, { type: 'primary', onClick: () => api.success('Slide saved') }, 'Save'),
h(Button, { onClick: () => api.info('Link copied to clipboard') }, 'Copy link'),
h(Button, { onClick: () => api.warning('You are near the slide limit') }, 'Warn'),
h(Button, { danger: true, onClick: () => api.error('Upload failed') }, 'Fail'),
h(Button, { onClick: () => api.loading('Saving your changes…') }, 'Save (async)')
)
);
}
// type ∈ { success, info, warning, error, loading }; duration defaults to 3s (0 = sticky).
// Same shared theme the React/Vue wrappers pass to ConfigProvider.
createRoot(document.getElementById('root')).render(h(App));
</script>
import { ConfigProvider, message, Button, Space } from 'antd'; // antd v6
import { toastTheme } from '@ahaslides-product/design/toast-theme';
function Toasts() {
// v6: use the hook so every toast consumes the ConfigProvider theme.
// The static message.success() is FORBIDDEN — it renders outside the provider and drops the theme.
const [api, contextHolder] = message.useMessage();
return (
<ConfigProvider theme={toastTheme}>
{contextHolder}
<Space wrap>
<Button type="primary" onClick={() => api.success('Slide saved')}>Save</Button>
<Button onClick={() => api.info('Link copied to clipboard')}>Copy link</Button>
<Button onClick={() => api.warning('You are near the slide limit')}>Warn</Button>
<Button danger onClick={() => api.error('Upload failed')}>Fail</Button>
<Button onClick={() => api.loading('Saving your changes…')}>Save (async)</Button>
</Space>
</ConfigProvider>
);
}
// type ∈ { success, info, warning, error, loading }; duration defaults to 3s (0 = sticky).
// One shared toastTheme → the DS V3 look; keeps antd's built-in enter/leave motion.
<script setup>
import { ConfigProvider, message, Button, Space } from 'ant-design-vue'; // ant-design-vue v4
import { toastTheme } from '@ahaslides-product/design/toast-theme';
// v4: use the hook so every toast consumes the ConfigProvider theme.
// The static message.success() is FORBIDDEN — it renders outside the provider and drops the theme.
const [messageApi, contextHolder] = message.useMessage();
</script>
<template>
<a-config-provider :theme="toastTheme">
<component :is="contextHolder" />
<a-space wrap>
<a-button type="primary" @click="messageApi.success('Slide saved')">Save</a-button>
<a-button @click="messageApi.info('Link copied to clipboard')">Copy link</a-button>
<a-button @click="messageApi.warning('You are near the slide limit')">Warn</a-button>
<a-button danger @click="messageApi.error('Upload failed')">Fail</a-button>
<a-button @click="messageApi.loading('Saving your changes…')">Save (async)</a-button>
</a-space>
</a-config-provider>
</template>
<!-- type ∈ { success, info, warning, error, loading }; duration defaults to 3s (0 = sticky).
The SAME toastTheme as React → one DS V3 look across both vendor libraries. -->
// @ahaslides-product/design/toast-theme — declared ONCE, consumed by both tiers.
import { toastTheme } from '@ahaslides-product/design/toast-theme';
export const toastTheme = {
token: {
colorPrimary: '#6A1EBB',
borderRadius: 8,
colorText: '#1A1A1A',
colorBgElevated: '#FFFFFF',
fontFamily: 'var(--aha-font-product, "Plus Jakarta Sans", sans-serif)',
},
components: {
Message: {
contentBg: '#FFFFFF', // white elevated surface
contentPadding: '9px 12px',
},
},
};
API
| Prop | Type | Default | Notes |
|---|---|---|---|
type | success | info | warning | error | loading | info | Status glyph + tone |
content | string | — | The message text |
duration | number | 3 | Seconds on screen; 0 keeps it until dismissed |
onClose | () => void | — | Fires after the toast leaves |
Install
# .npmrc — once: point the @ahaslides-product scope at GitHub Packages
@ahaslides-product:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN} # a GitHub token with read:packages
npm i @ahaslides-product/design
import '@ahaslides-product/design/tokens.css'; // once, at the app root
import '@ahaslides-product/design/toast-theme'; // registers <toast>
Agent feed for this component (absolute, fetchable anywhere): toast.agent.json · toast.md · toast.llms.txt
When to use
When to use
- Toast — confirming a quick action succeeded (saved, copied, sent) with nothing to act on
- Notification — a richer message with a title + description, or one the user may need later
- Alert — a persistent, inline message tied to a region of the page
One line, past tense, no title. Never put an action inside a toast that disappears — if the user must respond, use a Notification or a Modal.
Surfaces
editor dashboard settings
Spec
Surface white elevated pill · radius 8 · ink #1A1A1A text · Position top-centre, floating · Duration 3s default (0 = sticky) · Status success / info / warning / error / loading