Plugins & Extensions

Create custom plugins to extend BismillahCSS with new utilities and components.

Creating a Basic Plugin

// tailwind.config.js
export default {
  plugins: [
    function({ addUtilities }) {
      const newUtilities = {
        '.skew-10deg': {
          transform: 'skewX(-10deg)',
        },
        '.skew-20deg': {
          transform: 'skewX(-20deg)',
        },
      };
      addUtilities(newUtilities);
    },
  ],
}

Plugin Types

Utilities Plugin

// Add custom utilities
function spinPlugin({ addUtilities }) {
  const utilities = {
    '.spin-slow': {
      animation: 'spin 3s linear infinite',
    },
    '.spin-fast': {
      animation: 'spin 0.5s linear infinite',
    },
  };
  
  addUtilities(utilities);
}

export default {
  plugins: [spinPlugin],
}

Component Plugin

// Add component classes
function buttonPlugin({ addComponents }) {
  const buttons = {
    '.btn': {
      padding: '0.5rem 1rem',
      borderRadius: '0.375rem',
      fontWeight: '500',
      cursor: 'pointer',
      transition: 'all 0.2s',
      '&:hover': {
        opacity: '0.9',
      },
    },
    '.btn-primary': {
      '@apply bg-blue-600 text-white': {},
    },
    '.btn-secondary': {
      '@apply bg-gray-200 text-gray-900': {},
    },
  };
  
  addComponents(buttons);
}

export default {
  plugins: [buttonPlugin],
}

Variants Plugin

// Add custom variants
function groupVariantPlugin({ addVariant, e }) {
  addVariant('group-hover', ({ modifySelectors }) => {
    modifySelectors(({ selector }) => {
      return selector.replace(/^./, '.group:hover .');
    });
  });
}

export default {
  plugins: [groupVariantPlugin],
}

Theme Plugin

// Extend theme
function customThemePlugin({ theme }) {
  return {
    theme: {
      extend: {
        colors: theme('colors', {}),
        spacing: {
          '128': '32rem',
          '144': '36rem',
        },
      },
    },
  };
}

export default {
  plugins: [customThemePlugin],
}

Advanced Plugin Features

Responsive Utilities Plugin

function responsiveUtilitiesPlugin({ addUtilities, e, theme }) {
  const utilities = {};
  const breakpoints = theme('screens');
  
  ['xs', 'sm', 'md', 'lg'].forEach((size) => {
    utilities['.container-' + size] = {
      maxWidth: theme('width.' + size),
    };
  });
  
  addUtilities(utilities, {
    variants: ['responsive', 'hover'],
  });
}

export default {
  plugins: [responsiveUtilitiesPlugin],
}

Dynamic Plugin with Options

function customPlugin(options = {}) {
  return function({ addUtilities, theme }) {
    const {
      variants = [],
      responsive = true,
    } = options;
    
    const utilities = {
      '.custom-utility': {
        color: theme('colors.primary', 'blue'),
      },
    };
    
    addUtilities(utilities, {
      variants: responsive ? ['responsive', ...variants] : variants,
    });
  };
}

export default {
  plugins: [
    customPlugin({
      variants: ['hover', 'focus'],
      responsive: true,
    }),
  ],
}

Multiple Variants Plugin

function multiVariantPlugin({ addVariant }) {
  // Custom state variant
  addVariant('aria-busy', '&[aria-busy="true"]');
  // Custom attribute variant
  addVariant('data-invalid', '&[data-invalid]');
  // Custom combination
  addVariant('group-aria-selected', ':merge(.group)[aria-selected] &');
}

export default {
  plugins: [multiVariantPlugin],
}

Complete Plugin Example

// Custom aspect-ratio plugin
function aspectRatioPlugin({ matchUtilities, theme }) {
  matchUtilities(
    {
      aspect: (value) => ({
        aspectRatio: value,
      }),
    },
    {
      values: theme('aspectRatio'),
    }
  );
}

export default {
  theme: {
    extend: {
      aspectRatio: {
        '4/3': '4 / 3',
        '16/9': '16 / 9',
        '21/9': '21 / 9',
      },
    },
  },
  plugins: [aspectRatioPlugin],
}

UI Component Plugin

// Create a comprehensive UI plugin
function uiComponentPlugin({ addComponents, theme }) {
  const components = {
    // Card component
    '.card': {
      backgroundColor: theme('colors.white'),
      borderRadius: theme('borderRadius.lg'),
      boxShadow: theme('boxShadow.md'),
      padding: theme('spacing.6'),
    },
    '.card-header': {
      borderBottomWidth: '1px',
      borderBottomColor: theme('colors.gray.200'),
      marginBottom: theme('spacing.4'),
      paddingBottom: theme('spacing.4'),
    },
    '.card-body': {
      paddingY: theme('spacing.4'),
    },
    '.card-footer': {
      borderTopWidth: '1px',
      borderTopColor: theme('colors.gray.200'),
      marginTop: theme('spacing.4'),
      paddingTop: theme('spacing.4'),
    },
    
    // Badge component
    '.badge': {
      display: 'inline-block',
      padding: theme('spacing.1') + ' ' + theme('spacing.2'),
      borderRadius: theme('borderRadius.full'),
      fontSize: theme('fontSize.xs'),
      fontWeight: theme('fontWeight.semibold'),
    },
    '.badge-outline': {
      borderWidth: '1px',
    },
    
    // Alert component
    '.alert': {
      padding: theme('spacing.4'),
      borderRadius: theme('borderRadius.md'),
      borderLeftWidth: '4px',
    },
    '.alert-success': {
      backgroundColor: theme('colors.green.50'),
      borderLeftColor: theme('colors.green.500'),
      color: theme('colors.green.900'),
    },
    '.alert-error': {
      backgroundColor: theme('colors.red.50'),
      borderLeftColor: theme('colors.red.500'),
      color: theme('colors.red.900'),
    },
  };
  
  addComponents(components);
}

export default {
  plugins: [uiComponentPlugin],
}

Publishing a Plugin

Package Structure

bismillah-plugin-custom/
├── package.json
├── index.js
├── README.md
└── examples/
    └── usage.html

Package JSON

{
  "name": "@bismillahcss/plugin-custom",
  "version": "1.0.0",
  "description": "Custom plugin for BismillahCSS",
  "main": "index.js",
  "keywords": ["bismillahcss", "plugin", "utilities"],
  "author": "Your Name",
  "license": "MIT",
  "peerDependencies": {
    "tailwindcss": "^3.0.0"
  },
  "repository": {
    "type": "git",
    "url": "https://github.com/yourname/bismillah-plugin-custom"
  }
}

Index File

// index.js
module.exports = function customPlugin(options = {}) {
  return function({ addUtilities, theme }) {
    const utilities = {
      '.custom-class': {
        /* styles */
      },
    };
    
    addUtilities(utilities);
  };
};

Install and Use

# Install from npm
npm install @bismillahcss/plugin-custom

# Use in config
export default {
  plugins: [require('@bismillahcss/plugin-custom')()],
}

Built-in Plugins to Use

Forms Plugin

npm install @tailwindcss/forms

Typography Plugin

npm install @tailwindcss/typography

Aspect Ratio Plugin

npm install @tailwindcss/aspect-ratio

Container Queries Plugin

npm install @tailwindcss/container-queries

Plugin Best Practices

  • Keep plugins focused on a single concern
  • Accept options for flexibility
  • Use theme values for consistency
  • Support responsive and state variants
  • Document usage with examples
  • Provide TypeScript definitions if using TS
  • Test on various Tailwind versions
  • Use semantic naming for utilities
  • Provide clear README documentation
  • Follow npm publishing best practices