Files
arcum42-ComfyUI_SageUtils/docs/BUTTON_COMPONENT_GUIDE.md
T

11 KiB

Button Component Quick Reference

Component: js/components/buttons.js
Status: ✅ Ready to Use
Updated: October 12, 2025


Import

import { 
    createButton, 
    createIconButton, 
    createButtonGroup,
    createConfigButton,
    BUTTON_VARIANTS, 
    BUTTON_SIZES,
    BUTTON_CONFIGS 
} from '../components/buttons.js';

Basic Usage

Simple Button

const button = createButton('Click Me');

Button with Variant

const saveBtn = createButton('Save', {
    variant: BUTTON_VARIANTS.SUCCESS
});

const deleteBtn = createButton('Delete', {
    variant: BUTTON_VARIANTS.DANGER
});

Button with Click Handler

const refreshBtn = createButton('Refresh', {
    variant: BUTTON_VARIANTS.INFO,
    onClick: () => {
        console.log('Refreshing...');
    }
});

Button with Icon

const saveBtn = createButton('Save', {
    variant: BUTTON_VARIANTS.SUCCESS,
    icon: '💾'
});
// Result: "💾 Save"

Button with Custom Color

const customBtn = createButton('Custom', {
    color: '#9C27B0'  // Overrides variant
});

Sizes

const smallBtn = createButton('Small', {
    size: BUTTON_SIZES.SMALL  // 11px font, 4px 8px padding
});

const mediumBtn = createButton('Medium', {
    size: BUTTON_SIZES.MEDIUM  // 12px font, 6px 12px padding (default)
});

const largeBtn = createButton('Large', {
    size: BUTTON_SIZES.LARGE  // 14px font, 8px 16px padding
});

Variants

const variants = {
    primary: createButton('Primary', { variant: BUTTON_VARIANTS.PRIMARY }),     // Blue #2196F3
    secondary: createButton('Secondary', { variant: BUTTON_VARIANTS.SECONDARY }), // Gray #757575
    success: createButton('Success', { variant: BUTTON_VARIANTS.SUCCESS }),     // Green #4CAF50
    warning: createButton('Warning', { variant: BUTTON_VARIANTS.WARNING }),     // Orange #FF9800
    danger: createButton('Danger', { variant: BUTTON_VARIANTS.DANGER }),       // Red #f44336
    info: createButton('Info', { variant: BUTTON_VARIANTS.INFO })             // Cyan #00BCD4
};

Pre-configured Buttons

Use createConfigButton() for common buttons:

const refreshBtn = createConfigButton('refresh');
const pullBtn = createConfigButton('pull');
const editBtn = createConfigButton('edit');
const scanBtn = createConfigButton('scan');
const reportBtn = createConfigButton('report');
const saveBtn = createConfigButton('save');
const deleteBtn = createConfigButton('delete');
const cancelBtn = createConfigButton('cancel');
const confirmBtn = createConfigButton('confirm');

Override Config Options

const saveBtn = createConfigButton('save', {
    onClick: () => saveFile(),
    disabled: true
});

Icon Buttons

Icon-only buttons (no text):

const editIcon = createIconButton('✏️', {
    variant: BUTTON_VARIANTS.WARNING,
    title: 'Edit item'
});

const deleteIcon = createIconButton('🗑️', {
    variant: BUTTON_VARIANTS.DANGER,
    title: 'Delete item'
});

Button Groups

Multiple buttons in a row:

const saveBtn = createButton('Save', { variant: BUTTON_VARIANTS.SUCCESS });
const cancelBtn = createButton('Cancel', { variant: BUTTON_VARIANTS.SECONDARY });
const deleteBtn = createButton('Delete', { variant: BUTTON_VARIANTS.DANGER });

const buttonGroup = createButtonGroup([saveBtn, cancelBtn, deleteBtn], {
    gap: '8px',
    marginTop: '16px',
    wrap: true
});

container.appendChild(buttonGroup);

Advanced Options

All Available Options

const button = createButton('Advanced', {
    // Appearance
    variant: BUTTON_VARIANTS.PRIMARY,  // Button variant
    size: BUTTON_SIZES.MEDIUM,         // Button size
    icon: '🚀',                        // Icon/emoji to prepend
    color: '#custom',                  // Custom color (overrides variant)
    
    // Behavior
    onClick: () => {},                 // Click handler
    disabled: false,                   // Disabled state
    
    // Attributes
    id: 'my-button-id',                // Element ID
    className: 'my-button',            // Additional CSS class
    title: 'Tooltip text',             // Tooltip
    
    // Styling
    hoverEffect: true,                 // Enable hover opacity (default: true)
    marginTop: '8px',                  // Top margin (default: '8px')
    
    // Custom overrides
    style: {                           // Any CSS style overrides
        fontWeight: 'bold',
        borderRadius: '8px'
    }
});

Button with ID

const searchBtn = createButton('Search', {
    id: 'search-button',
    variant: BUTTON_VARIANTS.SUCCESS
});
// Can now be found with: document.getElementById('search-button')

Disabled Button

const disabledBtn = createButton('Disabled', {
    disabled: true,
    variant: BUTTON_VARIANTS.SUCCESS
});
// Automatically: cursor: not-allowed, opacity: 0.6, click handler disabled

No Hover Effect

const staticBtn = createButton('Static', {
    hoverEffect: false
});

Custom Margin

const noMarginBtn = createButton('No Margin', {
    marginTop: '0'
});

Complete Examples

File Browser Action Buttons

const actions = document.createElement('div');
actions.style.cssText = 'display: flex; gap: 8px;';

if (allowCreate) {
    const createBtn = createButton('Create File', {
        variant: BUTTON_VARIANTS.SUCCESS,
        size: 'small',
        marginTop: '0',
        onClick: () => this.callbacks.onFileCreate()
    });
    actions.appendChild(createBtn);
}

const refreshBtn = createButton('Refresh', {
    variant: BUTTON_VARIANTS.WARNING,
    size: 'small',
    marginTop: '0',
    onClick: () => this.loadFiles()
});
actions.appendChild(refreshBtn);

File Editor Buttons

const saveBtn = createButton('Save', {
    variant: BUTTON_VARIANTS.SUCCESS,
    icon: '💾',
    disabled: true,
    onClick: () => this.saveFile()
});

const deleteBtn = createButton('Delete', {
    variant: BUTTON_VARIANTS.DANGER,
    icon: '🗑️',
    disabled: true,
    onClick: async () => {
        if (confirm('Delete this file?')) {
            await this.deleteFile();
        }
    }
});

// Enable when file is loaded
this.currentFile = file;
saveBtn.disabled = false;
deleteBtn.disabled = false;

Modal Dialog Buttons

const confirmBtn = createButton('Confirm', {
    variant: BUTTON_VARIANTS.PRIMARY,
    icon: '✓',
    onClick: () => {
        dialog.close();
        onConfirm();
    }
});

const cancelBtn = createButton('Cancel', {
    variant: BUTTON_VARIANTS.SECONDARY,
    icon: '✖',
    onClick: () => dialog.close()
});

const buttonGroup = createButtonGroup([confirmBtn, cancelBtn], {
    gap: '12px',
    marginTop: '20px'
});

dialog.appendChild(buttonGroup);

Migration from Old Patterns

From createStyledButton()

// OLD ❌
const btn = createStyledButton('Save', '#4CAF50', '💾');

// NEW ✅
const btn = createButton('Save', {
    variant: BUTTON_VARIANTS.SUCCESS,
    icon: '💾'
});

// OR use config ✅
const btn = createConfigButton('save');

From createActionButton()

// OLD ❌
const btn = this.createActionButton('Delete', '#f44336', () => {
    this.deleteFile();
});

// NEW ✅
const btn = createButton('Delete', {
    variant: BUTTON_VARIANTS.DANGER,
    size: 'small',
    onClick: () => this.deleteFile()
});

// OR use config ✅
const btn = createConfigButton('delete', {
    size: 'small',
    onClick: () => this.deleteFile()
});

From Manual Button Creation

// OLD ❌
const button = document.createElement('button');
button.textContent = 'Save';
button.style.cssText = `
    background: #4CAF50;
    color: white;
    border: none;
    padding: 6px 12px;
    border-radius: 4px;
    cursor: pointer;
`;
button.addEventListener('click', () => save());

// NEW ✅
const button = createButton('Save', {
    variant: BUTTON_VARIANTS.SUCCESS,
    onClick: () => save()
});

Style Customization

Override Individual Styles

const button = createButton('Custom', {
    variant: BUTTON_VARIANTS.PRIMARY,
    style: {
        borderRadius: '20px',
        fontWeight: 'bold',
        textTransform: 'uppercase',
        minWidth: '120px'
    }
});

Use Custom Colors with Variants

// Purple button with all variant features
const purpleBtn = createButton('Custom Purple', {
    color: '#9C27B0',
    size: BUTTON_SIZES.LARGE
});

Available Constants

BUTTON_VARIANTS

BUTTON_VARIANTS = {
    PRIMARY: 'primary',      // #2196F3
    SECONDARY: 'secondary',  // #757575
    SUCCESS: 'success',      // #4CAF50
    WARNING: 'warning',      // #FF9800
    DANGER: 'danger',        // #f44336
    INFO: 'info'            // #00BCD4
}

BUTTON_SIZES

BUTTON_SIZES = {
    SMALL: 'small',    // 11px, 4px 8px
    MEDIUM: 'medium',  // 12px, 6px 12px (default)
    LARGE: 'large'     // 14px, 8px 16px
}

BUTTON_CONFIGS

BUTTON_CONFIGS = {
    refresh: { text: 'Refresh', variant: BUTTON_VARIANTS.SUCCESS, icon: '↻' },
    pull: { text: 'Pull', variant: BUTTON_VARIANTS.INFO, icon: '⬇' },
    edit: { text: 'Edit', variant: BUTTON_VARIANTS.WARNING, icon: '✏' },
    scan: { text: 'Scan All', color: '#9C27B0', icon: '🔍' },
    report: { text: 'Generate Report', color: '#673AB7', icon: '📊' },
    save: { text: 'Save', variant: BUTTON_VARIANTS.SUCCESS, icon: '💾' },
    delete: { text: 'Delete', variant: BUTTON_VARIANTS.DANGER, icon: '🗑️' },
    cancel: { text: 'Cancel', variant: BUTTON_VARIANTS.SECONDARY, icon: '✖' },
    confirm: { text: 'Confirm', variant: BUTTON_VARIANTS.PRIMARY, icon: '✓' }
}

Best Practices

  1. Use Variants: Prefer variant over custom color for consistency
  2. Use Configs: Use createConfigButton() for common buttons
  3. Group Buttons: Use createButtonGroup() for multiple related buttons
  4. Set Titles: Add title for tooltips on icon buttons
  5. Disable Properly: Use disabled: true instead of manual opacity changes
  6. Reset Margins: Set marginTop: '0' when inside flex containers

Common Patterns

Conditional Button

const button = allowEdit
    ? createConfigButton('edit', { onClick: () => edit() })
    : createButton('View', { variant: BUTTON_VARIANTS.INFO });

Toggle Button State

function setModified(isModified) {
    saveBtn.disabled = !isModified;
    // Disabled state automatically handles opacity
}

Dynamic Button Group

const buttons = [];

if (allowSave) buttons.push(createConfigButton('save', { onClick: save }));
if (allowDelete) buttons.push(createConfigButton('delete', { onClick: del }));
buttons.push(createConfigButton('cancel', { onClick: cancel }));

const group = createButtonGroup(buttons);

Need Help? Check the main component documentation in components/buttons.js