Untitled
unknown
plain_text
a year ago
5.2 kB
5
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