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.htmlPackage 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/formsTypography Plugin
npm install @tailwindcss/typographyAspect Ratio Plugin
npm install @tailwindcss/aspect-ratioContainer Queries Plugin
npm install @tailwindcss/container-queriesPlugin 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
