Feedback & status
Notice Toast
Toast that slides in and settles
detent-notice-toast
Port status
- Catalog status
- implemented
- Origin
- upstream
- Phase
- 3
- Wave
- phase-3-overlays
- Group
- Feedback & status
6.6 KB gzip for the class module · inlines the shared spring
Variants
The toast is anchored to the viewport (like upstream), so this preview opens one on demand. Hover or focus it to freeze the countdown bar.
No toast opened yet.
Recorded states
hoverrecorded state; no setteropenrecorded state; no setterpausedrecorded state; no setterdark themerecorded state; no setter
Usage
Import
import '/components/notice-toast/define.js';
// or register it yourself
import { DetentNoticeToast } from '/components/notice-toast/notice-toast.js';
Attributes
descriptiondurationopenpositionshow-progresstitlevariant
Properties
onDismissposition
Slots
icon
Events
detent-dismiss— {}
Example
Runnable example: site/examples/notice-toast.ts. The snippet below is generated from the catalogued attributes.
<detent-notice-toast
description
duration="4000"
open
position="bottom-center"
show-progress
title
variant="default"
></detent-notice-toast>
Property-only values
const element = document.querySelector('detent-notice-toast');
if (element !== null) {
// onDismiss: () => void
element.onDismiss = () => {};
// position: VelocityToastPosition
element.position = 'bottom-center';
}
Source
The pinned upstream source for this row:
src/components/ui/VelocityToast.tsxsha256 4bc21f48fca4…
Native files
The native module and its artifacts:
src/components/notice-toast/notice-toast.tssrc/components/notice-toast/styles.csssrc/components/notice-toast/define.tsdocs/components/notice-toast.mdsite/examples/notice-toast.tstests/browser/notice-toast.spec.tsevidence/components/notice-toast.md
API
Boolean attributes follow HTML presence semantics: present means true, absent means false, and disabled="false" still means disabled.
Attributes
| Attribute | Property | Type | Default | Notes |
|---|---|---|---|---|
description | description | string | undefined | Kebab-case attribute; camelCase property. |
duration | duration | number | 4000 | Kebab-case attribute; camelCase property. |
open | open | boolean | undefined | Presence semantics: present means true, absent means false. |
position | position | VelocityToastPosition | 'bottom-center' | Kebab-case attribute; camelCase property. |
show-progress | showProgress | boolean | true | Presence semantics: present means true, absent means false. |
title | title | string | undefined | Kebab-case attribute; camelCase property. |
variant | variant | 'default' | 'success' | 'warning' | 'error' | 'info' | 'default' | Kebab-case attribute; camelCase property. |
Properties
| Property | Type | Default | Notes |
|---|---|---|---|
onDismiss | () => void | undefined | Property-only: assign from script; not accepted as an attribute. |
position | VelocityToastPosition | 'bottom-center' | Property-only: assign from script; not accepted as an attribute. |
Events
| Event | Upstream prop | Payload type | Notes |
|---|---|---|---|
detent-dismiss | onDismiss | () => void | Composed, bubbles; fires only for a user action. |
Slots
| Slot | Notes |
|---|---|
icon | Consumer content; rendered through a slot, never re-created. |
CSS customisation
- React callback props become typed composed CustomEvents; programmatic state assignment emits none.
- Framer Motion springs/AnimatePresence ported to CSS transitions, WAAPI or the shared rAF spring helper.
- `lucide-react` icon components replaced with local SVG assets (ISC notice retained).
- React state/hooks replaced by element-owned state with pre-upgrade property preservation.
- onDismiss becomes detent-dismiss with detail: {}; className becomes parts and custom properties; icon becomes the icon slot (an empty slot element suppresses the variant icon, the native form of icon={false}).
- The toast is position: fixed inside the host, not in the top layer. A native dialog would make it modal and a popover would light-dismiss it on an outside click. Recorded limitation: an ancestor with transform, filter, contain or perspective becomes the containing block, so the toast would be anchored to that ancestor instead of the viewport (PC-9.8).
- Framer Motion's springSnappy entry/exit becomes the shared spring helper with the same pinned values (380/30/0.5) driving one progress value, so an interrupted exit reverses from where it is. Entry y: ±22 px / scale: 0.94 and exit y: ±12 px / scale: 0.96 match upstream; reduced motion skips both.
- The progress bar is a direct requestAnimationFrame width update through the upstream pow(1.05) easing instead of a useMotionValue + useTransform pair. The eased value is asserted against the linear value in the spec.
- lucide-react icons (Check, X, AlertTriangle, AlertCircle, Info) become local decorative inline SVGs (upstream ISC notice retained in THIRD_PARTY_NOTICES.md).
- Accessibility additions: Escape inside the toast dismisses it, focus inside pauses the countdown, a dismissal moves focus out of the toast, and the close button's focus ring comes from --detent-focus-ring instead of a Tailwind focus-ring utility.
- open has no documented default in the row and upstream required the prop, so the native default is “closed until open is set”; the reflected attribute is the observable state.
- The entry offset animation is not applied while reduced motion is on, and the final state is the same one a settled spring produces (no leftover transform).
What it does
A toast that enters with a higher initial velocity, settles on a snappy spring, and drains a countdown bar with a slight ease-in so the last part of the window feels decisive.
Upstream behaviour
- Entry animation starts further out (y: 22px) for higher perceived velocity, then springs to rest
- Progress indicator uses a slight ease-in (pow 1.05) so the final 10% feels decisive
- Hover pauses progress without visual jump; resume picks up from the remaining time
- 6 position presets, 5 variant tones, optional custom icon
- Light/dark theme aware — works in both palettes
Differences from upstream
- React callback props become typed composed CustomEvents; programmatic state assignment emits none.
- Framer Motion springs/AnimatePresence ported to CSS transitions, WAAPI or the shared rAF spring helper.
- `lucide-react` icon components replaced with local SVG assets (ISC notice retained).
- React state/hooks replaced by element-owned state with pre-upgrade property preservation.
- onDismiss becomes detent-dismiss with detail: {}; className becomes parts and custom properties; icon becomes the icon slot (an empty slot element suppresses the variant icon, the native form of icon={false}).
- The toast is position: fixed inside the host, not in the top layer. A native dialog would make it modal and a popover would light-dismiss it on an outside click. Recorded limitation: an ancestor with transform, filter, contain or perspective becomes the containing block, so the toast would be anchored to that ancestor instead of the viewport (PC-9.8).
- Framer Motion's springSnappy entry/exit becomes the shared spring helper with the same pinned values (380/30/0.5) driving one progress value, so an interrupted exit reverses from where it is. Entry y: ±22 px / scale: 0.94 and exit y: ±12 px / scale: 0.96 match upstream; reduced motion skips both.
- The progress bar is a direct requestAnimationFrame width update through the upstream pow(1.05) easing instead of a useMotionValue + useTransform pair. The eased value is asserted against the linear value in the spec.
- lucide-react icons (Check, X, AlertTriangle, AlertCircle, Info) become local decorative inline SVGs (upstream ISC notice retained in THIRD_PARTY_NOTICES.md).
- Accessibility additions: Escape inside the toast dismisses it, focus inside pauses the countdown, a dismissal moves focus out of the toast, and the close button's focus ring comes from --detent-focus-ring instead of a Tailwind focus-ring utility.
- open has no documented default in the row and upstream required the prop, so the native default is “closed until open is set”; the reflected attribute is the observable state.
- The entry offset animation is not applied while reduced motion is on, and the final state is the same one a settled spring produces (no leftover transform).