Untitled

 avatar
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