Components · Feedback
Notification
A richer, stacking message with a title + description — rendered through antd's notification API.
Examples
<!-- Paste-and-run: save as .html and open in a browser. No build step, no bundler.
Notification is a COMPOSITE (antd's notification 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 `notificationTheme` the React/Vue wrappers use, so it renders the DS V3 look
(white card, 384 wide, radius 8). Keeps antd's built-in motion.
DS rule: use the useNotification() hook + contextHolder — the static notification.open() is
FORBIDDEN (it renders outside the ConfigProvider theme).
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, notification, Button } from 'https://esm.sh/antd@6?deps=react@18,react-dom@18';
import { notificationTheme } from 'https://cdn.jsdelivr.net/gh/ahaslides-product/ahaslides-design@master/lib/notification-theme.js';
const h = React.createElement;
function App() {
const [api, ctx] = notification.useNotification();
// type: success | info | warning | error · placement: topLeft | topRight | bottomLeft | bottomRight
const notify = (type, placement) =>
api[type]({
message: 'Export ready',
description: 'Your CSV is ready to download.',
placement, // which corner it stacks in (default topRight)
duration: 4.5, // seconds on screen; 0 keeps it until dismissed
btn: h(Button, { type: 'primary', size: 'small', onClick: () => api.destroy() }, 'Undo'), // optional action
});
return h(ConfigProvider, { theme: notificationTheme },
ctx,
h(Button, { type: 'primary', onClick: () => notify('success', 'topRight') }, 'Publish'),
h(Button, { danger: true, onClick: () => notify('error', 'bottomLeft') }, 'Retry sync')
);
}
// Same shared theme the React/Vue wrappers pass to ConfigProvider.
createRoot(document.getElementById('root')).render(h(App));
</script>
import { ConfigProvider, notification, Button } from 'antd'; // antd v6
import { notificationTheme } from '@ahaslides-product/design/notification-theme';
function Notifications() {
// v6 DS rule: use the hook so the card consumes the ConfigProvider theme.
// The static notification.open() is FORBIDDEN — it renders outside the theme.
const [api, contextHolder] = notification.useNotification();
// type: success | info | warning | error · placement: topLeft | topRight | bottomLeft | bottomRight
const notify = (type, placement) =>
api[type]({
message: 'Export ready',
description: 'Your CSV of responses is ready to download.',
placement, // which corner it stacks in (default topRight)
duration: 4.5, // seconds on screen; 0 keeps it until dismissed
btn: <Button type="primary" size="small" onClick={() => api.destroy()}>Undo</Button>, // optional action
});
return (
<ConfigProvider theme={notificationTheme}>
{contextHolder}
<Button type="primary" onClick={() => notify('success', 'topRight')}>Publish</Button>
<Button danger onClick={() => notify('error', 'bottomLeft')}>Retry sync</Button>
</ConfigProvider>
);
}
// One shared notificationTheme → the DS V3 look; keeps antd's built-in motion.
<script setup>
import { h } from 'vue';
import { ConfigProvider, notification, Button } from 'ant-design-vue'; // ant-design-vue v4
import { notificationTheme } from '@ahaslides-product/design/notification-theme';
// v4 DS rule: use the hook so the card consumes the ConfigProvider theme.
// The static notification.open() is FORBIDDEN — it renders outside the theme.
const [notificationApi, contextHolder] = notification.useNotification();
// type: success | info | warning | error · placement: topLeft | topRight | bottomLeft | bottomRight
const notify = (type, placement) =>
notificationApi[type]({
message: 'Export ready',
description: 'Your CSV of responses is ready to download.',
placement, // which corner it stacks in (default topRight)
duration: 4.5, // seconds on screen; 0 keeps it until dismissed
btn: h(Button, { type: 'primary', size: 'small', onClick: () => notificationApi.destroy() }, () => 'Undo'),
});
</script>
<template>
<a-config-provider :theme="notificationTheme">
<component :is="contextHolder" />
<a-button type="primary" @click="notify('success', 'topRight')">Publish</a-button>
<a-button danger @click="notify('error', 'bottomLeft')">Retry sync</a-button>
</a-config-provider>
</template>
<!-- The SAME notificationTheme as React → one DS V3 look across both vendor libraries. -->
// @ahaslides-product/design/notification-theme — declared ONCE, consumed by both tiers.
import { notificationTheme } from '@ahaslides-product/design/notification-theme';
export const notificationTheme = {
token: {
colorPrimary: '#6A1EBB',
borderRadius: 8,
colorText: '#1A1A1A',
colorTextHeading: '#1A1A1A',
colorBgElevated: '#FFFFFF',
fontFamily: 'var(--aha-font-product, "Plus Jakarta Sans", sans-serif)',
},
components: {
Notification: {
width: 384,
borderRadiusLG: 8,
colorBgElevated: '#FFFFFF',
},
},
};
API
| Prop | Type | Default | Notes |
|---|---|---|---|
message | string | — | The bold title line |
description | string | — | The supporting body text |
type | success | info | warning | error | — | Status glyph + tone |
placement | topLeft | topRight | bottomLeft | bottomRight | topRight | Which corner it stacks in |
duration | number | 4.5 | Seconds on screen; 0 keeps it until dismissed |
btn | ReactNode | — | One optional action (e.g. Undo) rendered in the card |
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/notification-theme'; // registers <notification>
Agent feed for this component (absolute, fetchable anywhere): notification.agent.json · notification.md · notification.llms.txt
When to use
When to use
- Notification — a message with a title + detail, or one from a background event the user may act on later
- Toast — a one-line, past-tense confirmation with nothing to act on
- Modal — the user must respond before continuing
Give it a short title and a one-sentence description. Put at most one action in it; anything more belongs in a Modal or the page itself.
Surfaces
editor dashboard settings
Spec
Card white elevated · 384 wide · radius 8 · Title ink #1A1A1A, SemiBold · Type success · info · warning · error (status glyph + tone) · Placement topRight default (4 corners) · Duration 4.5s default (0 = sticky)