# ai-builder/2.7.10/assets/js/src/editor-blocks/snackbar/index.js

AI Builder – Generate pages, blocks, images &amp; translate with AI, version 2.7.10. 375 lines.

- Page: https://pluginprobe.com/plugins/ai-builder/2.7.10/code/assets/js/src/editor-blocks/snackbar/index.js
- Raw: https://pluginprobe.com/plugins/ai-builder/2.7.10/raw/assets/js/src/editor-blocks/snackbar/index.js
- Modified: 2025-09-24T10:00:52+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/ai-builder/2.7.10/code/assets/js/src/editor-blocks/snackbar/index.js#L10-L20`.

```javascript
const { registerBlockType } = wp.blocks;
const { __ } = wp.i18n;
const { PanelBody, TextControl, Button, Notice, ToggleControl, RangeControl } =
  wp.components;
const { InspectorControls, useBlockProps } = wp.blockEditor || wp.editor;

// Use HTML5 color input instead of WordPress ColorPicker to avoid compatibility issues
const SafeColorPicker = ({ color, onChange, disableAlpha }) => (
  <div style={{ position: "relative" }}>
    <input
      type="color"
      value={color || "#4f46e5"}
      onChange={(e) => onChange && onChange(e.target.value)}
      style={{
        width: "100%",
        height: "40px",
        border: "1px solid #ddd",
        borderRadius: "4px",
        cursor: "pointer",
      }}
    />
  </div>
);

registerBlockType("ai-builder/aibui-snackbar", {
  title: __("Snackbar (AI Builder)", "ai-builder"),
  icon: "info",
  category: "widgets",
  supports: { align: ["wide", "full"], html: false },
  attributes: {
    message: { type: "string", default: "This is a snackbar message" },
    buttons: {
      type: "array",
      default: [
        {
          id: "btn1",
          text: "Action",
          textColor: "#ffffff",
          backgroundColor: "#4f46e5",
          link: "",
          autoClose: true,
        },
      ],
    },
    globalAutoClose: { type: "boolean", default: true },
    globalCloseDelay: { type: "number", default: 5000 },
  },
  edit: (props) => {
    const { attributes, setAttributes } = props;
    const { message, buttons, globalAutoClose, globalCloseDelay } = attributes;
    const blockProps = useBlockProps({ className: "aibui-snackbar" });

    const addButton = () => {
      const newButton = {
        id: `btn${Date.now()}`,
        text: "New Button",
        textColor: "#ffffff",
        backgroundColor: "#4f46e5",
        link: "",
        autoClose: true,
      };
      setAttributes({
        buttons: [...buttons, newButton],
      });
    };

    const removeButton = (buttonId) => {
      setAttributes({
        buttons: buttons.filter((btn) => btn.id !== buttonId),
      });
    };

    const updateButton = (buttonId, field, value) => {
      setAttributes({
        buttons: buttons.map((btn) =>
          btn.id === buttonId ? { ...btn, [field]: value } : btn
        ),
      });
    };

    return (
      <div {...blockProps}>
        <InspectorControls>
          <PanelBody title={__("Snackbar Settings", "ai-builder")} initialOpen>
            <TextControl
              label={__("Message", "ai-builder")}
              value={message}
              onChange={(val) => setAttributes({ message: val || "" })}
            />

            <ToggleControl
              label={__("Global auto-close", "ai-builder")}
              checked={globalAutoClose}
              onChange={(val) => setAttributes({ globalAutoClose: !!val })}
              help={__(
                "When enabled, the snackbar will auto-hide after the specified delay",
                "ai-builder"
              )}
            />

            <TextControl
              label={__("Auto-hide delay (seconds)", "ai-builder")}
              value={Math.floor(globalCloseDelay / 1000)}
              onChange={(val) => {
                const numValue = parseInt(val) || 0;
                const clampedValue = Math.max(0, Math.min(60, numValue));
                setAttributes({ globalCloseDelay: clampedValue * 1000 });
              }}
              type="number"
              min="0"
              max="60"
              help={__("", "ai-builder")}
            />

            <div style={{ marginTop: "16px" }}>
              <h4>{__("Buttons", "ai-builder")}</h4>
              {buttons.map((button, index) => (
                <div
                  key={button.id}
                  style={{
                    border: "1px solid #e0e0e0",
                    borderRadius: "8px",
                    padding: "12px",
                    marginBottom: "12px",
                    backgroundColor: "#f9f9f9",
                  }}
                >
                  <div
                    style={{
                      display: "flex",
                      justifyContent: "space-between",
                      alignItems: "center",
                      marginBottom: "8px",
                    }}
                  >
                    <strong>
                      {__("Button", "ai-builder")} {index + 1}
                    </strong>
                    <Button
                      isDestructive
                      isSmall
                      onClick={() => removeButton(button.id)}
                    >
                      {__("Remove", "ai-builder")}
                    </Button>
                  </div>

                  <TextControl
                    label={__("Button Text", "ai-builder")}
                    value={button.text}
                    onChange={(val) =>
                      updateButton(button.id, "text", val || "")
                    }
                  />

                  <TextControl
                    label={__("Link (optional)", "ai-builder")}
                    value={button.link}
                    onChange={(val) =>
                      updateButton(button.id, "link", val || "")
                    }
                    help={__("Leave empty for no link", "ai-builder")}
                  />

                  <div style={{ marginTop: "12px" }}>
                    <p style={{ margin: "0 0 8px" }}>
                      {__("Text Color", "ai-builder")}
                    </p>
                    <SafeColorPicker
                      color={button.textColor}
                      onChange={(val) =>
                        updateButton(button.id, "textColor", val || "#ffffff")
                      }
                    />
                  </div>

                  <div style={{ marginTop: "12px" }}>
                    <p style={{ margin: "0 0 8px" }}>
                      {__("Background Color", "ai-builder")}
                    </p>
                    <SafeColorPicker
                      color={button.backgroundColor}
                      onChange={(val) =>
                        updateButton(
                          button.id,
                          "backgroundColor",
                          val || "#4f46e5"
                        )
                      }
                    />
                  </div>
                  <div style={{ marginTop: "12px" }}>
                    <ToggleControl
                      label={__("Auto-close on click", "ai-builder")}
                      checked={button.autoClose !== false}
                      onChange={(val) =>
                        updateButton(button.id, "autoClose", !!val)
                      }
                      style={{ marginTop: "8px" }}
                      help={__(
                        "When enabled, clicking this button will close the snackbar",
                        "ai-builder"
                      )}
                    />
                  </div>
                </div>
              ))}

              <Button isPrimary onClick={addButton}>
                {__("Add Button", "ai-builder")}
              </Button>
            </div>
          </PanelBody>
        </InspectorControls>

        <SnackbarPreview message={message} buttons={buttons} />
      </div>
    );
  },
  save: (props) => {
    const { attributes } = props;
    const { message, buttons, globalAutoClose, globalCloseDelay } = attributes;
    const blockProps = wp.blockEditor
      ? wp.blockEditor.useBlockProps.save({ className: "aibui-snackbar" })
      : {};

    return (
      <div {...blockProps}>
        <div
          className="aibui-snackbar-container"
          data-global-auto-close={globalAutoClose ? "1" : "0"}
          data-global-close-delay={globalCloseDelay}
          data-buttons={JSON.stringify(buttons)}
        >
          <div className="aibui-snackbar-content">
            <span className="aibui-snackbar-message">{message}</span>
            <div className="aibui-snackbar-buttons">
              {buttons.map((button) => {
                const buttonElement = (
                  <button
                    key={button.id}
                    className="aibui-snackbar-btn aibui-snackbar-action-btn"
                    style={{
                      color: button.textColor,
                      backgroundColor: button.backgroundColor,
                      border: "none",
                      borderRadius: "6px",
                      padding: "8px 16px",
                      marginLeft: "8px",
                      cursor: "pointer",
                      fontSize: "14px",
                      fontWeight: "500",
                      transition: "all 0.2s ease",
                    }}
                    onMouseEnter={(e) => {
                      e.target.style.opacity = "0.9";
                    }}
                    onMouseLeave={(e) => {
                      e.target.style.opacity = "1";
                    }}
                  >
                    {button.text}
                  </button>
                );

                return button.link ? (
                  <a
                    key={button.id}
                    href={button.link}
                    target="_blank"
                    rel="noopener noreferrer"
                    style={{ textDecoration: "none" }}
                  >
                    {buttonElement}
                  </a>
                ) : (
                  buttonElement
                );
              })}
            </div>
          </div>
        </div>
      </div>
    );
  },
});

function SnackbarPreview({ message, buttons }) {
  return (
    <div
      className="aibui-snackbar-container"
      style={{
        position: "fixed",
        bottom: "20px",
        left: "20px",
        right: "20px",
        maxWidth: "600px",
        margin: "0 auto",
        zIndex: 1000,
      }}
    >
      <div
        className="aibui-snackbar-content"
        style={{
          backgroundColor: "#333",
          color: "#fff",
          padding: "16px 20px",
          borderRadius: "8px",
          display: "flex",
          alignItems: "center",
          justifyContent: "space-between",
          boxShadow: "0 4px 12px rgba(0,0,0,0.3)",
          border: "1px solid rgba(255,255,255,0.1)",
        }}
      >
        <span
          className="aibui-snackbar-message"
          style={{
            flex: 1,
            fontSize: "14px",
            lineHeight: "1.4",
          }}
        >
          {message}
        </span>
        <div
          className="aibui-snackbar-buttons"
          style={{
            display: "flex",
            alignItems: "center",
            marginLeft: "16px",
          }}
        >
          {buttons.map((button) => {
            const buttonElement = (
              <button
                key={button.id}
                className="aibui-snackbar-btn"
                style={{
                  color: button.textColor,
                  backgroundColor: button.backgroundColor,
                  border: "none",
                  borderRadius: "6px",
                  padding: "8px 16px",
                  marginLeft: "8px",
                  cursor: "pointer",
                  fontSize: "14px",
                  fontWeight: "500",
                  transition: "all 0.2s ease",
                }}
              >
                {button.text}
              </button>
            );

            return button.link ? (
              <a
                key={button.id}
                href={button.link}
                target="_blank"
                rel="noopener noreferrer"
                style={{ textDecoration: "none" }}
              >
                {buttonElement}
              </a>
            ) : (
              buttonElement
            );
          })}
        </div>
      </div>
    </div>
  );
}

```
