diff --git a/toast-notification/README.md b/toast-notification/README.md
new file mode 100644
index 0000000..f1a5835
--- /dev/null
+++ b/toast-notification/README.md
@@ -0,0 +1,117 @@
+# ToastNotification
+
+A toast notification system that displays temporary messages in a configurable screen corner with smooth animations and auto-dismiss functionality.
+
+## Getting Started
+
+Install dependencies:
+```bash
+npm install
+```
+
+Share the component to your Webflow workspace:
+```bash
+npx webflow library share
+```
+
+For local development:
+```bash
+npm run dev
+```
+
+## Designer Properties
+
+| Property | Type | Default | Description |
+|----------|------|---------|-------------|
+| ID | Id | — | HTML ID attribute for the toast container |
+| Position | Variant | top-right | Screen corner position where toasts appear (top-right, top-left, bottom-right, bottom-left) |
+| Variant | Variant | info | Visual style and color scheme of the toast (success, error, warning, info) |
+| Message | TextNode | Notification message | Primary message text displayed prominently |
+| Description | Text | Additional details about this notification | Optional secondary description text below the message |
+| Show Description | Visibility | — | Show or hide the description text |
+| Duration | Number | 5000 | Auto-dismiss duration in milliseconds |
+| Show Progress Bar | Boolean | true | Display animated progress bar showing time until auto-dismiss |
+| Show Close Button | Boolean | true | Display close button for manual dismissal |
+| Max Toasts | Number | 5 | Maximum number of toasts visible simultaneously |
+| Enable Animations | Boolean | true | Enable smooth slide and fade animations |
+| Toast 1 Message | Text | Changes saved successfully | Message text for first demo toast |
+| Toast 1 Description | Text | Your profile has been updated | Description text for first demo toast |
+| Toast 1 Variant | Variant | success | Variant style for first demo toast |
+| Toast 1 Visible | Visibility | — | Show or hide the first demo toast |
+| Toast 2 Message | Text | Connection error | Message text for second demo toast |
+| Toast 2 Description | Text | Unable to reach the server | Description text for second demo toast |
+| Toast 2 Variant | Variant | error | Variant style for second demo toast |
+| Toast 2 Visible | Visibility | — | Show or hide the second demo toast |
+| Toast 3 Message | Text | Storage almost full | Message text for third demo toast |
+| Toast 3 Description | Text | You have used 90% of your storage | Description text for third demo toast |
+| Toast 3 Variant | Variant | warning | Variant style for third demo toast |
+| Toast 3 Visible | Visibility | — | Show or hide the third demo toast |
+
+## Styling
+
+This component automatically adapts to your Webflow site's design system through site variables and inherited properties.
+
+### Site Variables
+
+To match your site's design system, define these CSS variables in your Webflow project settings. The component will use the fallback values shown below until you configure them.
+
+| Site Variable | What It Controls | Fallback |
+|---------------|------------------|----------|
+| --background-primary | Toast card background color | #ffffff |
+| --background-secondary | Close button hover state background | #f5f5f5 |
+| --text-primary | Message text color | #1a1a1a |
+| --text-secondary | Description text and close button color | #737373 |
+| --border-color | Toast card border and progress bar background | #e5e5e5 |
+| --border-radius | Toast card and button corner rounding | 8px |
+| --success-color | Success variant border, icon, and progress bar color | #22c55e |
+| --success-bg | Success variant background tint | #f0fdf4 |
+| --error-color | Error variant border, icon, and progress bar color | #ef4444 |
+| --error-bg | Error variant background tint | #fef2f2 |
+| --warning-color | Warning variant border, icon, and progress bar color | #f59e0b |
+| --warning-bg | Warning variant background tint | #fffbeb |
+| --info-color | Info variant border, icon, and progress bar color | #3b82f6 |
+| --info-bg | Info variant background tint | #eff6ff |
+
+### Inherited Properties
+
+The component inherits these CSS properties from its parent element:
+- `font-family` — Typography style
+- `color` — Text color
+- `line-height` — Text spacing
+
+## Extending in Code
+
+### Triggering Toasts Programmatically
+
+To show toasts dynamically based on user actions or application events:
+
+```javascript
+// Access the toast container element
+const toastContainer = document.querySelector('[data-component="toast-notification"]');
+
+// Create and dispatch a custom event to trigger a new toast
+const showToast = (message, description, variant = 'info') => {
+ const event = new CustomEvent('showToast', {
+ detail: { message, description, variant }
+ });
+ toastContainer.dispatchEvent(event);
+};
+
+// Usage examples
+showToast('Form submitted', 'Your data has been saved', 'success');
+showToast('Network error', 'Please check your connection', 'error');
+```
+
+### Customizing Animation Duration
+
+Adjust the slide-in animation speed for different timing preferences:
+
+```css
+.wf-toastnotification-animated .wf-toastnotification-card {
+ animation-duration: 0.5s; /* Slower entrance */
+}
+```
+
+## Dependencies
+
+No external dependencies.
\ No newline at end of file
diff --git a/toast-notification/index.html b/toast-notification/index.html
new file mode 100644
index 0000000..90bfefd
--- /dev/null
+++ b/toast-notification/index.html
@@ -0,0 +1,17 @@
+
+
+
+
+
+ ToastNotification
+
+
+
+
+
+
+
diff --git a/toast-notification/metadata.json b/toast-notification/metadata.json
new file mode 100644
index 0000000..b57d731
--- /dev/null
+++ b/toast-notification/metadata.json
@@ -0,0 +1,5 @@
+{
+ "name": "Toast Notifications",
+ "description": "Temporary notification messages with success, error, warning, and info variants. Auto-dismiss with progress bar.",
+ "category": "Feedback"
+}
diff --git a/toast-notification/package.json b/toast-notification/package.json
new file mode 100644
index 0000000..66e6d89
--- /dev/null
+++ b/toast-notification/package.json
@@ -0,0 +1,25 @@
+{
+ "name": "toast-notification",
+ "private": true,
+ "version": "0.0.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "tsc -b && vite build",
+ "preview": "vite preview"
+ },
+ "dependencies": {
+ "react": "^19.1.1",
+ "react-dom": "^19.1.1"
+ },
+ "devDependencies": {
+ "@types/react": "^19.1.13",
+ "@types/react-dom": "^19.1.9",
+ "@vitejs/plugin-react": "^5.0.3",
+ "@webflow/data-types": "^1.0.1",
+ "@webflow/react": "^1.0.1",
+ "@webflow/webflow-cli": "^1.8.44",
+ "typescript": "~5.8.3",
+ "vite": "^7.1.7"
+ }
+}
\ No newline at end of file
diff --git a/toast-notification/screenshot-brand.png b/toast-notification/screenshot-brand.png
new file mode 100644
index 0000000..3c0baad
Binary files /dev/null and b/toast-notification/screenshot-brand.png differ
diff --git a/toast-notification/screenshot-dark.png b/toast-notification/screenshot-dark.png
new file mode 100644
index 0000000..fe92b5e
Binary files /dev/null and b/toast-notification/screenshot-dark.png differ
diff --git a/toast-notification/screenshot-light.png b/toast-notification/screenshot-light.png
new file mode 100644
index 0000000..4394e44
Binary files /dev/null and b/toast-notification/screenshot-light.png differ
diff --git a/toast-notification/src/components/ToastNotification/ToastNotification.css b/toast-notification/src/components/ToastNotification/ToastNotification.css
new file mode 100644
index 0000000..31a4dc8
--- /dev/null
+++ b/toast-notification/src/components/ToastNotification/ToastNotification.css
@@ -0,0 +1,294 @@
+/*
+ * Webflow Site Variables Used:
+ * - --background-primary: Toast card background
+ * - --background-secondary: Close button hover state
+ * - --text-primary: Message text color
+ * - --text-secondary: Description text color
+ * - --border-color: Toast card border
+ * - --border-radius: Toast card and button rounding
+ * - --success-color: Success variant border and icon color
+ * - --success-bg: Success variant background tint
+ * - --error-color: Error variant border and icon color
+ * - --error-bg: Error variant background tint
+ * - --warning-color: Warning variant border and icon color
+ * - --warning-bg: Warning variant background tint
+ * - --info-color: Info variant border and icon color
+ * - --info-bg: Info variant background tint
+ */
+
+/* Box sizing reset */
+.wf-toastnotification *,
+.wf-toastnotification *::before,
+.wf-toastnotification *::after {
+ box-sizing: border-box;
+}
+
+/* Root container - fixed positioning for toast notifications */
+.wf-toastnotification {
+ font-family: inherit;
+ color: inherit;
+ line-height: inherit;
+ position: fixed;
+ z-index: 9999;
+ display: flex;
+ flex-direction: column;
+ gap: 12px;
+ pointer-events: none;
+ max-width: 420px;
+ width: calc(100% - 48px);
+}
+
+/* Position variants */
+.wf-toastnotification-position-top-right {
+ top: 24px;
+ right: 24px;
+}
+
+.wf-toastnotification-position-top-left {
+ top: 24px;
+ left: 24px;
+}
+
+.wf-toastnotification-position-bottom-right {
+ bottom: 24px;
+ right: 24px;
+}
+
+.wf-toastnotification-position-bottom-left {
+ bottom: 24px;
+ left: 24px;
+}
+
+/* Toast card */
+.wf-toastnotification-card {
+ background: var(--background-primary, #ffffff);
+ border: 1px solid var(--border-color, #e5e5e5);
+ border-radius: var(--border-radius, 8px);
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
+ overflow: hidden;
+ pointer-events: auto;
+ position: relative;
+ border-left-width: 4px;
+}
+
+/* Animation states */
+.wf-toastnotification-animated .wf-toastnotification-card {
+ animation: wf-toast-slide-in 0.3s ease-out;
+}
+
+.wf-toastnotification-position-top-right.wf-toastnotification-animated .wf-toastnotification-card,
+.wf-toastnotification-position-bottom-right.wf-toastnotification-animated .wf-toastnotification-card {
+ animation: wf-toast-slide-in-right 0.3s ease-out;
+}
+
+.wf-toastnotification-position-top-left.wf-toastnotification-animated .wf-toastnotification-card,
+.wf-toastnotification-position-bottom-left.wf-toastnotification-animated .wf-toastnotification-card {
+ animation: wf-toast-slide-in-left 0.3s ease-out;
+}
+
+@keyframes wf-toast-slide-in-right {
+ from {
+ transform: translateX(100%);
+ opacity: 0;
+ }
+ to {
+ transform: translateX(0);
+ opacity: 1;
+ }
+}
+
+@keyframes wf-toast-slide-in-left {
+ from {
+ transform: translateX(-100%);
+ opacity: 0;
+ }
+ to {
+ transform: translateX(0);
+ opacity: 1;
+ }
+}
+
+/* Variant colors - success */
+.wf-toastnotification-variant-success {
+ border-left-color: var(--success-color, #22c55e);
+ background: var(--success-bg, #f0fdf4);
+}
+
+.wf-toastnotification-variant-success .wf-toastnotification-icon {
+ color: var(--success-color, #22c55e);
+}
+
+.wf-toastnotification-variant-success .wf-toastnotification-progress-bar {
+ background: var(--success-color, #22c55e);
+}
+
+/* Variant colors - error */
+.wf-toastnotification-variant-error {
+ border-left-color: var(--error-color, #ef4444);
+ background: var(--error-bg, #fef2f2);
+}
+
+.wf-toastnotification-variant-error .wf-toastnotification-icon {
+ color: var(--error-color, #ef4444);
+}
+
+.wf-toastnotification-variant-error .wf-toastnotification-progress-bar {
+ background: var(--error-color, #ef4444);
+}
+
+/* Variant colors - warning */
+.wf-toastnotification-variant-warning {
+ border-left-color: var(--warning-color, #f59e0b);
+ background: var(--warning-bg, #fffbeb);
+}
+
+.wf-toastnotification-variant-warning .wf-toastnotification-icon {
+ color: var(--warning-color, #f59e0b);
+}
+
+.wf-toastnotification-variant-warning .wf-toastnotification-progress-bar {
+ background: var(--warning-color, #f59e0b);
+}
+
+/* Variant colors - info */
+.wf-toastnotification-variant-info {
+ border-left-color: var(--info-color, #3b82f6);
+ background: var(--info-bg, #eff6ff);
+}
+
+.wf-toastnotification-variant-info .wf-toastnotification-icon {
+ color: var(--info-color, #3b82f6);
+}
+
+.wf-toastnotification-variant-info .wf-toastnotification-progress-bar {
+ background: var(--info-color, #3b82f6);
+}
+
+/* Content container */
+.wf-toastnotification-content {
+ display: flex;
+ align-items: flex-start;
+ gap: 12px;
+ padding: 16px;
+}
+
+/* Icon wrapper */
+.wf-toastnotification-icon-wrapper {
+ flex-shrink: 0;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 20px;
+ height: 20px;
+}
+
+.wf-toastnotification-icon {
+ width: 20px;
+ height: 20px;
+ display: block;
+}
+
+/* Text content */
+.wf-toastnotification-text {
+ flex: 1;
+ min-width: 0;
+}
+
+.wf-toastnotification-message {
+ font-weight: 600;
+ font-size: 14px;
+ line-height: 1.4;
+ color: var(--text-primary, #1a1a1a);
+ margin: 0;
+}
+
+.wf-toastnotification-description {
+ font-size: 13px;
+ line-height: 1.4;
+ color: var(--text-secondary, #737373);
+ margin-top: 4px;
+}
+
+/* Close button */
+.wf-toastnotification-close {
+ flex-shrink: 0;
+ background: transparent;
+ border: none;
+ padding: 4px;
+ cursor: pointer;
+ border-radius: var(--border-radius, 8px);
+ color: var(--text-secondary, #737373);
+ transition: background-color 0.2s, color 0.2s;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 24px;
+ height: 24px;
+ margin-top: -2px;
+}
+
+.wf-toastnotification-close:hover {
+ background: var(--background-secondary, #f5f5f5);
+ color: var(--text-primary, #1a1a1a);
+}
+
+.wf-toastnotification-close:focus-visible {
+ outline: 2px solid var(--info-color, #3b82f6);
+ outline-offset: 2px;
+}
+
+.wf-toastnotification-close:active {
+ transform: scale(0.95);
+}
+
+.wf-toastnotification-close svg {
+ width: 14px;
+ height: 14px;
+ display: block;
+}
+
+/* Progress bar container */
+.wf-toastnotification-progress-container {
+ height: 4px;
+ background: var(--border-color, #e5e5e5);
+ overflow: hidden;
+}
+
+.wf-toastnotification-progress-bar {
+ height: 100%;
+ transition: width 0.1s linear;
+}
+
+/* Responsive adjustments */
+@media (max-width: 640px) {
+ .wf-toastnotification {
+ width: calc(100% - 32px);
+ max-width: none;
+ }
+
+ .wf-toastnotification-position-top-right,
+ .wf-toastnotification-position-top-left {
+ top: 16px;
+ left: 16px;
+ right: 16px;
+ }
+
+ .wf-toastnotification-position-bottom-right,
+ .wf-toastnotification-position-bottom-left {
+ bottom: 16px;
+ left: 16px;
+ right: 16px;
+ }
+
+ .wf-toastnotification-content {
+ padding: 12px;
+ }
+
+ .wf-toastnotification-message {
+ font-size: 13px;
+ }
+
+ .wf-toastnotification-description {
+ font-size: 12px;
+ }
+}
\ No newline at end of file
diff --git a/toast-notification/src/components/ToastNotification/ToastNotification.tsx b/toast-notification/src/components/ToastNotification/ToastNotification.tsx
new file mode 100644
index 0000000..6026e05
--- /dev/null
+++ b/toast-notification/src/components/ToastNotification/ToastNotification.tsx
@@ -0,0 +1,207 @@
+import { useState, useEffect, useRef } from "react";
+
+export interface ToastNotificationProps {
+ id?: string;
+ position?: "top-right" | "top-left" | "bottom-right" | "bottom-left";
+ variant?: "success" | "error" | "warning" | "info";
+ message?: React.ReactNode;
+ description?: string;
+ showDescription?: boolean;
+ duration?: number;
+ showProgressBar?: boolean;
+ showCloseButton?: boolean;
+ maxToasts?: number;
+ enableAnimations?: boolean;
+ toast1Message?: string;
+ toast1Description?: string;
+ toast1Variant?: "success" | "error" | "warning" | "info";
+ toast1Visible?: boolean;
+ toast2Message?: string;
+ toast2Description?: string;
+ toast2Variant?: "success" | "error" | "warning" | "info";
+ toast2Visible?: boolean;
+ toast3Message?: string;
+ toast3Description?: string;
+ toast3Variant?: "success" | "error" | "warning" | "info";
+ toast3Visible?: boolean;
+}
+
+interface Toast {
+ id: string;
+ message: React.ReactNode;
+ description?: string;
+ variant: "success" | "error" | "warning" | "info";
+ progress: number;
+}
+
+const variantIcons = {
+ success: (
+
+
+
+ ),
+ error: (
+
+
+
+ ),
+ warning: (
+
+
+
+ ),
+ info: (
+
+
+
+ ),
+};
+
+export default function ToastNotification({
+ id,
+ position = "top-right",
+ variant = "info",
+ message = "Notification message",
+ description = "Additional details about this notification",
+ showDescription = true,
+ duration = 5000,
+ showProgressBar = true,
+ showCloseButton = true,
+ maxToasts = 5,
+ enableAnimations = true,
+ toast1Message = "Changes saved successfully",
+ toast1Description = "Your profile has been updated",
+ toast1Variant = "success",
+ toast1Visible = false,
+ toast2Message = "Connection error",
+ toast2Description = "Unable to reach the server",
+ toast2Variant = "error",
+ toast2Visible = false,
+ toast3Message = "Storage almost full",
+ toast3Description = "You have used 90% of your storage",
+ toast3Variant = "warning",
+ toast3Visible = false,
+}: ToastNotificationProps) {
+ const [toasts, setToasts] = useState([]);
+ const progressIntervals = useRef>(new Map());
+ const dismissTimeouts = useRef>(new Map());
+
+ const addToast = (toastMessage: React.ReactNode, toastDescription: string | undefined, toastVariant: "success" | "error" | "warning" | "info") => {
+ const newToast: Toast = {
+ id: `toast-${Date.now()}-${Math.random()}`,
+ message: toastMessage,
+ description: toastDescription,
+ variant: toastVariant,
+ progress: 100,
+ };
+
+ setToasts((prev) => {
+ const updated = [...prev, newToast];
+ if (updated.length > maxToasts) {
+ const removed = updated.shift();
+ if (removed) {
+ clearInterval(progressIntervals.current.get(removed.id));
+ clearTimeout(dismissTimeouts.current.get(removed.id));
+ progressIntervals.current.delete(removed.id);
+ dismissTimeouts.current.delete(removed.id);
+ }
+ }
+ return updated;
+ });
+
+ const progressInterval = setInterval(() => {
+ setToasts((prev) =>
+ prev.map((t) =>
+ t.id === newToast.id
+ ? { ...t, progress: Math.max(0, t.progress - (100 / (duration / 100))) }
+ : t
+ )
+ );
+ }, 100);
+
+ const dismissTimeout = setTimeout(() => {
+ removeToast(newToast.id);
+ }, duration);
+
+ progressIntervals.current.set(newToast.id, progressInterval);
+ dismissTimeouts.current.set(newToast.id, dismissTimeout);
+ };
+
+ const removeToast = (toastId: string) => {
+ clearInterval(progressIntervals.current.get(toastId));
+ clearTimeout(dismissTimeouts.current.get(toastId));
+ progressIntervals.current.delete(toastId);
+ dismissTimeouts.current.delete(toastId);
+ setToasts((prev) => prev.filter((t) => t.id !== toastId));
+ };
+
+ useEffect(() => {
+ return () => {
+ progressIntervals.current.forEach((interval) => clearInterval(interval));
+ dismissTimeouts.current.forEach((timeout) => clearTimeout(timeout));
+ };
+ }, []);
+
+ useEffect(() => {
+ if (toast1Visible) {
+ addToast(toast1Message, toast1Description, toast1Variant);
+ }
+ }, [toast1Visible, toast1Message, toast1Description, toast1Variant]);
+
+ useEffect(() => {
+ if (toast2Visible) {
+ addToast(toast2Message, toast2Description, toast2Variant);
+ }
+ }, [toast2Visible, toast2Message, toast2Description, toast2Variant]);
+
+ useEffect(() => {
+ if (toast3Visible) {
+ addToast(toast3Message, toast3Description, toast3Variant);
+ }
+ }, [toast3Visible, toast3Message, toast3Description, toast3Variant]);
+
+ const positionClass = `wf-toastnotification-position-${position}`;
+ const animationClass = enableAnimations ? "wf-toastnotification-animated" : "";
+
+ return (
+
+ {toasts.map((toast) => (
+
+
+
+ {variantIcons[toast.variant]}
+
+
+
{toast.message}
+ {toast.description && (
+
{toast.description}
+ )}
+
+ {showCloseButton && (
+
removeToast(toast.id)}
+ aria-label="Close notification"
+ >
+
+
+
+
+ )}
+
+ {showProgressBar && (
+
+ )}
+
+ ))}
+
+ );
+}
\ No newline at end of file
diff --git a/toast-notification/src/components/ToastNotification/ToastNotification.webflow.tsx b/toast-notification/src/components/ToastNotification/ToastNotification.webflow.tsx
new file mode 100644
index 0000000..d7a4995
--- /dev/null
+++ b/toast-notification/src/components/ToastNotification/ToastNotification.webflow.tsx
@@ -0,0 +1,154 @@
+import ToastNotification from "./ToastNotification";
+import { props } from "@webflow/data-types";
+import { declareComponent } from "@webflow/react";
+import "./ToastNotification.css";
+
+export default declareComponent(ToastNotification, {
+ name: "ToastNotification",
+ description: "A toast notification system that displays temporary messages in a configurable screen corner (top-right, top-left, bottom-right, bottom-left). Each toast card features a colored left border and icon matching the variant (success with green checkmark, error with red X, warning with yellow exclamation, info with blue info icon), followed by a bold message title and optional lighter description text below. A close button (X) appears on the right. A progress bar animates along the bottom edge, depleting over the auto-dismiss duration. Toasts stack vertically with 12px gaps, slide in smoothly from their corner direction, and fade out when dismissed. Maximum 5 toasts visible simultaneously; oldest auto-dismiss when the limit is exceeded. Fully responsive with appropriate padding and max-width constraints.",
+ group: "Interactive",
+ options: {
+ ssr: false,
+ applyTagSelectors: true
+ },
+ props: {
+ id: props.Id({
+ name: "Element ID",
+ group: "Settings",
+ tooltip: "HTML ID attribute for the toast container"
+ }),
+ position: props.Variant({
+ name: "Position",
+ options: ["top-right", "top-left", "bottom-right", "bottom-left"],
+ defaultValue: "top-right",
+ group: "Style",
+ tooltip: "Screen corner position where toasts appear"
+ }),
+ variant: props.Variant({
+ name: "Variant",
+ options: ["success", "error", "warning", "info"],
+ defaultValue: "info",
+ group: "Style",
+ tooltip: "Visual style and color scheme of the toast"
+ }),
+ message: props.TextNode({
+ name: "Message",
+ defaultValue: "Notification message",
+ group: "Content",
+ tooltip: "Primary message text displayed prominently"
+ }),
+ description: props.Text({
+ name: "Description",
+ defaultValue: "Additional details about this notification",
+ group: "Content",
+ tooltip: "Optional secondary description text below the message"
+ }),
+ showDescription: props.Visibility({
+ name: "Show Description",
+ group: "Display",
+ tooltip: "Show or hide the description text"
+ }),
+ duration: props.Number({
+ name: "Duration",
+ defaultValue: 5000,
+ group: "Behavior",
+ tooltip: "Auto-dismiss duration in milliseconds"
+ }),
+ showProgressBar: props.Boolean({
+ name: "Show Progress Bar",
+ defaultValue: true,
+ group: "Display",
+ tooltip: "Display animated progress bar showing time until auto-dismiss"
+ }),
+ showCloseButton: props.Boolean({
+ name: "Show Close Button",
+ defaultValue: true,
+ group: "Display",
+ tooltip: "Display close button for manual dismissal"
+ }),
+ maxToasts: props.Number({
+ name: "Max Toasts",
+ defaultValue: 5,
+ group: "Behavior",
+ tooltip: "Maximum number of toasts visible simultaneously"
+ }),
+ enableAnimations: props.Boolean({
+ name: "Enable Animations",
+ defaultValue: true,
+ group: "Behavior",
+ tooltip: "Enable smooth slide and fade animations"
+ }),
+ toast1Message: props.Text({
+ name: "Toast 1 Message",
+ defaultValue: "Changes saved successfully",
+ group: "Demo Toast 1",
+ tooltip: "Message text for first demo toast"
+ }),
+ toast1Description: props.Text({
+ name: "Toast 1 Description",
+ defaultValue: "Your profile has been updated",
+ group: "Demo Toast 1",
+ tooltip: "Description text for first demo toast"
+ }),
+ toast1Variant: props.Variant({
+ name: "Toast 1 Variant",
+ options: ["success", "error", "warning", "info"],
+ defaultValue: "success",
+ group: "Demo Toast 1",
+ tooltip: "Variant style for first demo toast"
+ }),
+ toast1Visible: props.Visibility({
+ name: "Toast 1 Visible",
+ group: "Demo Toast 1",
+ tooltip: "Show or hide the first demo toast"
+ }),
+ toast2Message: props.Text({
+ name: "Toast 2 Message",
+ defaultValue: "Connection error",
+ group: "Demo Toast 2",
+ tooltip: "Message text for second demo toast"
+ }),
+ toast2Description: props.Text({
+ name: "Toast 2 Description",
+ defaultValue: "Unable to reach the server",
+ group: "Demo Toast 2",
+ tooltip: "Description text for second demo toast"
+ }),
+ toast2Variant: props.Variant({
+ name: "Toast 2 Variant",
+ options: ["success", "error", "warning", "info"],
+ defaultValue: "error",
+ group: "Demo Toast 2",
+ tooltip: "Variant style for second demo toast"
+ }),
+ toast2Visible: props.Visibility({
+ name: "Toast 2 Visible",
+ group: "Demo Toast 2",
+ tooltip: "Show or hide the second demo toast"
+ }),
+ toast3Message: props.Text({
+ name: "Toast 3 Message",
+ defaultValue: "Storage almost full",
+ group: "Demo Toast 3",
+ tooltip: "Message text for third demo toast"
+ }),
+ toast3Description: props.Text({
+ name: "Toast 3 Description",
+ defaultValue: "You have used 90% of your storage",
+ group: "Demo Toast 3",
+ tooltip: "Description text for third demo toast"
+ }),
+ toast3Variant: props.Variant({
+ name: "Toast 3 Variant",
+ options: ["success", "error", "warning", "info"],
+ defaultValue: "warning",
+ group: "Demo Toast 3",
+ tooltip: "Variant style for third demo toast"
+ }),
+ toast3Visible: props.Visibility({
+ name: "Toast 3 Visible",
+ group: "Demo Toast 3",
+ tooltip: "Show or hide the third demo toast"
+ })
+ }
+});
\ No newline at end of file
diff --git a/toast-notification/src/components/ToastNotification/ToastNotificationSimple.webflow.tsx b/toast-notification/src/components/ToastNotification/ToastNotificationSimple.webflow.tsx
new file mode 100644
index 0000000..8fecdfd
--- /dev/null
+++ b/toast-notification/src/components/ToastNotification/ToastNotificationSimple.webflow.tsx
@@ -0,0 +1,75 @@
+import ToastNotification from "./ToastNotification";
+import { props } from "@webflow/data-types";
+import { declareComponent } from "@webflow/react";
+import "./ToastNotification.css";
+
+export default declareComponent(ToastNotification, {
+ name: "ToastNotification (Simple)",
+ description: "A toast notification system that displays temporary messages in a configurable screen corner (top-right, top-left, bottom-right, bottom-left). Each toast card features a colored left border and icon matching the variant (success with green checkmark, error with red X, warning with yellow exclamation, info with blue info icon), followed by a bold message title and optional lighter description text below. A close button (X) appears on the right. A progress bar animates along the bottom edge, depleting over the auto-dismiss duration. Toasts stack vertically with 12px gaps, slide in smoothly from their corner direction, and fade out when dismissed. Maximum 5 toasts visible simultaneously; oldest auto-dismiss when the limit is exceeded. Fully responsive with appropriate padding and max-width constraints.",
+ group: "Interactive",
+ options: {
+ ssr: false,
+ applyTagSelectors: true
+ },
+ props: {
+ id: props.Id({
+ name: "Element ID",
+ group: "Settings",
+ tooltip: "HTML ID attribute for the toast container"
+ }),
+ toast1Message: props.Text({
+ name: "Toast 1 Message",
+ defaultValue: "Changes saved successfully",
+ group: "Demo Toast 1",
+ tooltip: "Message text for first demo toast"
+ }),
+ toast1Variant: props.Variant({
+ name: "Toast 1 Variant",
+ options: ["success", "error", "warning", "info"],
+ defaultValue: "success",
+ group: "Demo Toast 1",
+ tooltip: "Variant style for first demo toast"
+ }),
+ toast1Visible: props.Visibility({
+ name: "Toast 1 Visible",
+ group: "Demo Toast 1",
+ tooltip: "Show or hide the first demo toast"
+ }),
+ toast2Message: props.Text({
+ name: "Toast 2 Message",
+ defaultValue: "Connection error",
+ group: "Demo Toast 2",
+ tooltip: "Message text for second demo toast"
+ }),
+ toast2Variant: props.Variant({
+ name: "Toast 2 Variant",
+ options: ["success", "error", "warning", "info"],
+ defaultValue: "error",
+ group: "Demo Toast 2",
+ tooltip: "Variant style for second demo toast"
+ }),
+ toast2Visible: props.Visibility({
+ name: "Toast 2 Visible",
+ group: "Demo Toast 2",
+ tooltip: "Show or hide the second demo toast"
+ }),
+ toast3Message: props.Text({
+ name: "Toast 3 Message",
+ defaultValue: "Storage almost full",
+ group: "Demo Toast 3",
+ tooltip: "Message text for third demo toast"
+ }),
+ toast3Variant: props.Variant({
+ name: "Toast 3 Variant",
+ options: ["success", "error", "warning", "info"],
+ defaultValue: "warning",
+ group: "Demo Toast 3",
+ tooltip: "Variant style for third demo toast"
+ }),
+ toast3Visible: props.Visibility({
+ name: "Toast 3 Visible",
+ group: "Demo Toast 3",
+ tooltip: "Show or hide the third demo toast"
+ })
+ }
+});
\ No newline at end of file
diff --git a/toast-notification/src/main.tsx b/toast-notification/src/main.tsx
new file mode 100644
index 0000000..aa90ebf
--- /dev/null
+++ b/toast-notification/src/main.tsx
@@ -0,0 +1,334 @@
+import { StrictMode, useState } from "react"
+import { createRoot } from "react-dom/client"
+import ToastNotification from "./components/ToastNotification/ToastNotification"
+import "./components/ToastNotification/ToastNotification.css"
+
+type ThemeVars = {
+ "--background-primary": string
+ "--background-secondary": string
+ "--text-primary": string
+ "--text-secondary": string
+ "--border-color": string
+ "--accent-color": string
+ "--accent-text-color": string
+ "--border-radius": string
+}
+
+const themes: Record = {
+ light: {
+ "--background-primary": "#ffffff",
+ "--background-secondary": "#f5f5f5",
+ "--text-primary": "#1a1a1a",
+ "--text-secondary": "#737373",
+ "--border-color": "#e5e5e5",
+ "--accent-color": "#2563eb",
+ "--accent-text-color": "#ffffff",
+ "--border-radius": "8px",
+ },
+ dark: {
+ "--background-primary": "#0a0a0a",
+ "--background-secondary": "#1a1a1a",
+ "--text-primary": "#fafafa",
+ "--text-secondary": "#a3a3a3",
+ "--border-color": "#2a2a2a",
+ "--accent-color": "#3b82f6",
+ "--accent-text-color": "#ffffff",
+ "--border-radius": "8px",
+ },
+ brand: {
+ "--background-primary": "#fef7f0",
+ "--background-secondary": "#fde8d0",
+ "--text-primary": "#1c1917",
+ "--text-secondary": "#78716c",
+ "--border-color": "#e7e5e4",
+ "--accent-color": "#ea580c",
+ "--accent-text-color": "#ffffff",
+ "--border-radius": "12px",
+ },
+}
+
+function App() {
+ const [activeTheme, setActiveTheme] = useState<"light" | "dark" | "brand" | "custom">("light")
+ const [customVars, setCustomVars] = useState(themes.light)
+
+ const currentVars = activeTheme === "custom" ? customVars : themes[activeTheme]
+
+ const handleThemeChange = (theme: "light" | "dark" | "brand" | "custom") => {
+ setActiveTheme(theme)
+ if (theme !== "custom") {
+ setCustomVars(themes[theme])
+ }
+ }
+
+ const handleCustomVarChange = (key: keyof ThemeVars, value: string) => {
+ setCustomVars((prev) => ({ ...prev, [key]: value }))
+ }
+
+ const pageBackground = activeTheme === "dark" ? "#000000" : activeTheme === "brand" ? "#fef3e8" : "#f9fafb"
+
+ return (
+
+
+
+
+ Toast Notification Preview
+
+
+
+
+ {(["light", "dark", "brand", "custom"] as const).map((theme) => (
+ handleThemeChange(theme)}
+ style={{
+ padding: "8px 16px",
+ border: `2px solid ${activeTheme === theme ? currentVars["--accent-color"] : currentVars["--border-color"]}`,
+ borderRadius: "6px",
+ background: activeTheme === theme ? currentVars["--accent-color"] : currentVars["--background-secondary"],
+ color: activeTheme === theme ? currentVars["--accent-text-color"] : currentVars["--text-primary"],
+ cursor: "pointer",
+ fontSize: "14px",
+ fontWeight: "500",
+ textTransform: "capitalize",
+ transition: "all 0.2s ease"
+ }}
+ >
+ {theme}
+
+ ))}
+
+
+
+ {activeTheme === "custom" && (
+
+
+ Custom Theme Editor
+
+
+ {Object.entries(customVars).map(([key, value]) => (
+
+
+ {key}
+
+ handleCustomVarChange(key as keyof ThemeVars, e.target.value)}
+ style={{
+ width: "100%",
+ padding: "8px 12px",
+ border: `1px solid ${currentVars["--border-color"]}`,
+ borderRadius: "4px",
+ background: currentVars["--background-primary"],
+ color: currentVars["--text-primary"],
+ fontSize: "13px",
+ fontFamily: "monospace"
+ }}
+ />
+
+ ))}
+
+
+ )}
+
+
+
+
+
+ Default Configuration
+
+
+
+
+
+
+ Bottom Left Position - Minimal Style
+
+
+
+
+
+
+ Multiple Error Toasts - Top Left
+
+
+
+
+
+
+ Long Duration - No Animations
+
+
+
+
+
+
+ )
+}
+
+createRoot(document.getElementById("root")!).render(
+
+
+
+)
\ No newline at end of file
diff --git a/toast-notification/src/vite-env.d.ts b/toast-notification/src/vite-env.d.ts
new file mode 100644
index 0000000..151aa68
--- /dev/null
+++ b/toast-notification/src/vite-env.d.ts
@@ -0,0 +1 @@
+///
\ No newline at end of file
diff --git a/toast-notification/tsconfig.app.json b/toast-notification/tsconfig.app.json
new file mode 100644
index 0000000..d775f2a
--- /dev/null
+++ b/toast-notification/tsconfig.app.json
@@ -0,0 +1,27 @@
+{
+ "compilerOptions": {
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsBuildInfo",
+ "target": "ES2022",
+ "useDefineForClassFields": true,
+ "lib": [
+ "ES2022",
+ "DOM",
+ "DOM.Iterable"
+ ],
+ "module": "ESNext",
+ "skipLibCheck": true,
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "verbatimModuleSyntax": true,
+ "noEmit": true,
+ "jsx": "react-jsx",
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noFallthroughCasesInSwitch": true,
+ "noUncheckedSideEffectImports": true
+ },
+ "include": [
+ "src"
+ ]
+}
\ No newline at end of file
diff --git a/toast-notification/tsconfig.json b/toast-notification/tsconfig.json
new file mode 100644
index 0000000..65f670c
--- /dev/null
+++ b/toast-notification/tsconfig.json
@@ -0,0 +1,11 @@
+{
+ "files": [],
+ "references": [
+ {
+ "path": "./tsconfig.app.json"
+ },
+ {
+ "path": "./tsconfig.node.json"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/toast-notification/tsconfig.node.json b/toast-notification/tsconfig.node.json
new file mode 100644
index 0000000..c4a9a48
--- /dev/null
+++ b/toast-notification/tsconfig.node.json
@@ -0,0 +1,23 @@
+{
+ "compilerOptions": {
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsBuildInfo",
+ "target": "ES2023",
+ "lib": [
+ "ES2023"
+ ],
+ "module": "ESNext",
+ "skipLibCheck": true,
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "verbatimModuleSyntax": true,
+ "noEmit": true,
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noFallthroughCasesInSwitch": true,
+ "noUncheckedSideEffectImports": true
+ },
+ "include": [
+ "vite.config.ts"
+ ]
+}
\ No newline at end of file
diff --git a/toast-notification/vite.config.ts b/toast-notification/vite.config.ts
new file mode 100644
index 0000000..c7a4f78
--- /dev/null
+++ b/toast-notification/vite.config.ts
@@ -0,0 +1,6 @@
+import { defineConfig } from "vite";
+import react from "@vitejs/plugin-react";
+
+export default defineConfig({
+ plugins: [react()],
+});
\ No newline at end of file
diff --git a/toast-notification/webflow.json b/toast-notification/webflow.json
new file mode 100644
index 0000000..7429d5e
--- /dev/null
+++ b/toast-notification/webflow.json
@@ -0,0 +1,10 @@
+{
+ "library": {
+ "name": "ToastNotification",
+ "components": [
+ "./src/**/*.webflow.@(js|jsx|mjs|ts|tsx)"
+ ],
+ "description": "A toast notification system that displays temporary messages in a configurable screen corner (top-right, top-left, bottom-right, bottom-left). Each toast card features a colored left border and icon matching the variant (success with green checkmark, error with red X, warning with yellow exclamation, info with blue info icon), followed by a bold message title and optional lighter description text below. A close button (X) appears on the right. A progress bar animates along the bottom edge, depleting over the auto-dismiss duration. Toasts stack vertically with 12px gaps, slide in smoothly from their corner direction, and fade out when dismissed. Maximum 5 toasts visible simultaneously; oldest auto-dismiss when the limit is exceeded. Fully responsive with appropriate padding and max-width constraints.",
+ "id": "toast-notification"
+ }
+}
\ No newline at end of file