Untitled
unknown
plain_text
6 months ago
5.2 kB
3
Indexable
const { widget } = figma; const { useEffect, AutoLayout, Text } = widget; // Import required components import Accordion from "./components/Accordion"; import Button from "./components/Button"; import HintText from "./components/HintText"; import Status from "./components/Status"; // Toast types type ToastSeverity = 'success' | 'error' | 'warning' | 'info'; interface ToastProps { title: string; message: string; severity: ToastSeverity; action?: { label: string; onClick: () => void; }; } function ToastNotificationSystem() { useEffect(() => { const createComponent = async () => { try { // Sample notifications const notifications: ToastProps[] = [ { title: "Changes saved successfully", message: "All your changes have been saved to the cloud", severity: "success", action: { label: "View Changes", onClick: () => {} } }, { title: "Connection lost", message: "Please check your internet connection", severity: "error", action: { label: "Retry", onClick: () => {} } }, { title: "Update available", message: "A new version is available. Please update.", severity: "info" } ]; const node = await figma.createNodeFromJSXAsync( <AutoLayout direction="vertical" padding={{ right: 24, top: 24 }} spacing={12} width={360} horizontalAlignItems="end" > {notifications.map((toast, index) => ( <Accordion key={index} title={toast.title} description={toast.message} isOpen={true} icon={getStatusIcon(toast.severity)} state={getAccordionState(toast.severity)} > {toast.action && ( <AutoLayout padding={{ top: 8 }} spacing={8} horizontalAlignItems="end" > <Button label="Dismiss" style="ghost" theme="neutral" size="small" /> <Button label={toast.action.label} style="filled" theme={getButtonTheme(toast.severity)} size="small" /> </AutoLayout> )} </Accordion> ))} {/* Success Toast */} <HintText text="All notifications can be dismissed" state="default" /> </AutoLayout> ); figma.currentPage.appendChild(node); figma.viewport.scrollAndZoomIntoView([node]); } catch (error) { figma.notify(`Error creating toast system: ${error.message}`); } }; createComponent(); }); return <Text>Toast Notification System</Text>; } // Helper functions using component library styles function getStatusIcon(severity: ToastSeverity): string { const icons = { success: `<svg width="20" height="20" viewBox="0 0 20 20" fill="none"> <path d="M10 18C14.4183 18 18 14.4183 18 10C18 5.58172 14.4183 2 10 2C5.58172 2 2 5.58172 2 10C2 14.4183 5.58172 18 10 18Z" fill="#1FC16B"/> <path d="M14 8L8.5 13.5L6 11" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg>`, error: `<svg width="20" height="20" viewBox="0 0 20 20" fill="none"> <path d="M10 18C14.4183 18 18 14.4183 18 10C18 5.58172 14.4183 2 10 2C5.58172 2 2 5.58172 2 10C2 14.4183 5.58172 18 10 18Z" fill="#FB3748"/> <path d="M13 7L7 13M7 7L13 13" stroke="white" stroke-width="2" stroke-linecap="round"/> </svg>`, warning: `<svg width="20" height="20" viewBox="0 0 20 20" fill="none"> <path d="M10 18C14.4183 18 18 14.4183 18 10C18 5.58172 14.4183 2 10 2C5.58172 2 2 5.58172 2 10C2 14.4183 5.58172 18 10 18Z" fill="#F6B71E"/> <path d="M10 6V10M10 14H10.01" stroke="white" stroke-width="2" stroke-linecap="round"/> </svg>`, info: `<svg width="20" height="20" viewBox="0 0 20 20" fill="none"> <path d="M10 18C14.4183 18 18 14.4183 18 10C18 5.58172 14.4183 2 10 2C5.58172 2 2 5.58172 2 10C2 14.4183 5.58172 18 10 18Z" fill="#1D9BF0"/> <path d="M10 14V10M10 6H10.01" stroke="white" stroke-width="2" stroke-linecap="round"/> </svg>` }; return icons[severity]; } function getAccordionState(severity: ToastSeverity): 'default' | 'hover' | 'open' { const states = { success: 'default', error: 'open', warning: 'hover', info: 'default' }; return states[severity]; } function getButtonTheme(severity: ToastSeverity): 'primary' | 'error' | 'neutral' { const themes = { success: 'primary', error: 'error', warning: 'neutral', info: 'primary' }; return themes[severity]; } widget.register(ToastNotificationSystem);
Editor is loading...
Leave a Comment