Extending the Framework
Learn advanced techniques to extend and enhance BismillahCSS for your project needs.
Custom Utilities
Simple Custom Utilities
// tailwind.config.js
export default {
theme: {
extend: {
// Add custom utilities via theme
customUtilities: {
'frosted-glass': {
'backdrop-filter': 'blur(10px)',
'background-color': 'rgba(255, 255, 255, 0.1)',
},
'smooth-shadow': {
'box-shadow': '0 10px 40px rgba(0, 0, 0, 0.1)',
'transition': 'box-shadow 0.3s ease',
},
},
},
},
plugins: [
function({ matchUtilities, theme }) {
matchUtilities(
{
'frosted': (value) => ({
...value,
}),
},
{
values: theme('customUtilities'),
}
);
},
],
}Parameterized Utilities
// Create utilities with values
function customPlugin({ matchUtilities, theme }) {
matchUtilities(
{
// Create blur-[value] utilities
'blur': (value) => ({
'filter': `blur(${value})`,
}),
// Create hue-rotate-[value] utilities
'hue-rotate': (value) => ({
'filter': `hue-rotate(${value}deg)`,
}),
},
{
values: {
1: '1px',
5: '5px',
10: '10px',
20: '20px',
},
}
);
}
export default {
plugins: [customPlugin],
}Dynamic Utilities from Theme
function dynamicPlugin({ matchUtilities, theme }) {
matchUtilities(
{
'text': (value) => ({
color: value,
}),
},
{
values: theme('colors'),
}
);
}
export default {
plugins: [dynamicPlugin],
}Creating a Design System
Component Library Structure
my-design-system/
├── components/
│ ├── button.tsx
│ ├── card.tsx
│ ├── input.tsx
│ ├── modal.tsx
│ └── index.ts
├── tokens/
│ ├── colors.ts
│ ├── spacing.ts
│ ├── typography.ts
│ └── index.ts
├── styles/
│ ├── globals.css
│ └── components.css
├── tailwind.config.ts
└── package.jsonToken Definitions
// tokens/colors.ts
export const colors = {
primary: {
50: '#f0f9ff',
100: '#e0f2fe',
500: '#0ea5e9',
600: '#0284c7',
900: '#082f49',
},
semantic: {
success: '#10b981',
warning: '#f59e0b',
error: '#ef4444',
info: '#3b82f6',
},
};
// tokens/spacing.ts
export const spacing = {
xs: '0.25rem',
sm: '0.5rem',
md: '1rem',
lg: '1.5rem',
xl: '2rem',
'2xl': '3rem',
'3xl': '4rem',
};Sync Tokens to Config
// tailwind.config.ts
import { colors, spacing } from './tokens';
export default {
theme: {
extend: {
colors,
spacing,
},
},
}Component Variants
// components/button.tsx
import React from 'react';
interface ButtonProps {
variant?: 'primary' | 'secondary' | 'outline';
size?: 'sm' | 'md' | 'lg';
children: React.ReactNode;
}
const variantClasses = {
primary: 'bismillah-bg-primary-600 bismillah-text-white hover:bismillah-bg-primary-700',
secondary: 'bismillah-bg-gray-200 bismillah-text-gray-900 hover:bismillah-bg-gray-300',
outline: 'bismillah-border bismillah-border-gray-300 bismillah-text-gray-900',
};
const sizeClasses = {
sm: 'bismillah-px-3 bismillah-py-1 bismillah-text-sm',
md: 'bismillah-px-4 bismillah-py-2 bismillah-text-base',
lg: 'bismillah-px-6 bismillah-py-3 bismillah-text-lg',
};
export function Button({
variant = 'primary',
size = 'md',
children,
}: ButtonProps) {
return (
<button
className={`
bismillah-rounded-lg
bismillah-font-semibold
bismillah-transition
${variantClasses[variant]}
${sizeClasses[size]}
`}
>
{children}
</button>
);
}Integrating with Component Libraries
Headless UI Integration
// components/dropdown.tsx
import { Menu } from '@headlessui/react';
import { ChevronDownIcon } from '@heroicons/react/20/solid';
export function Dropdown() {
return (
<div class="bismillah-w-56 bismillah-text-right">
<Menu as="div" class="bismillah-relative bismillah-inline-block bismillah-text-left">
<Menu.Button class="bismillah-inline-flex bismillah-w-full bismillah-justify-center bismillah-rounded-md bismillah-bg-white bismillah-px-4 bismillah-py-2 bismillah-text-sm bismillah-font-medium bismillah-text-gray-700">
Options
<ChevronDownIcon />
</Menu.Button>
<Menu.Items class="bismillah-absolute bismillah-right-0 bismillah-z-10 bismillah-mt-2 bismillah-w-56 bismillah-origin-top-right bismillah-rounded-md bismillah-bg-white">
<Menu.Item>
{({ active }) => (
<a
href="#"
class={bismillah-block bismillah-px-4 bismillah-py-2 ${
active ? 'bismillah-bg-blue-500 bismillah-text-white' : 'bismillah-text-gray-700'
}}
>
Edit
</a>
)}
</Menu.Item>
</Menu.Items>
</Menu>
</div>
);
}Radix UI Integration
// components/select.tsx
import * as Select from '@radix-ui/react-select';
import { CheckIcon } from '@radix-ui/react-icons';
export function SelectComponent() {
return (
<Select.Root>
<Select.Trigger class="bismillah-inline-flex bismillah-items-center bismillah-justify-between bismillah-px-4 bismillah-py-2 bismillah-rounded-lg bismillah-border">
<Select.Value placeholder="Select..." />
</Select.Trigger>
<Select.Content class="bismillah-rounded-lg bismillah-shadow-lg">
<Select.Group>
<Select.Item value="option1" class="bismillah-px-4 bismillah-py-2">
<Select.ItemText>Option 1</Select.ItemText>
<Select.ItemIndicator>
<CheckIcon />
</Select.ItemIndicator>
</Select.Item>
</Select.Group>
</Select.Content>
</Select.Root>
);
}Advanced Responsive Patterns
Container Queries
<!-- Modern responsive pattern -->
<div class="@container">
<div class="@sm:bismillah-flex @md:bismillah-grid @md:bismillah-grid-cols-2">
<!-- Responds to container size, not viewport -->
</div>
</div>Aspect Ratio Patterns
<!-- Multiple aspect ratios -->
<div class="bismillah-aspect-video">
<!-- 16:9 aspect ratio -->
</div>
<div class="md:bismillah-aspect-square lg:bismillah-aspect-video">
<!-- Changes aspect ratio at different breakpoints -->
</div>Grid Responsive Patterns
<!-- Auto-responsive grid -->
<div class="bismillah-grid bismillah-grid-cols-1 sm:bismillah-grid-cols-2 md:bismillah-grid-cols-3 lg:bismillah-grid-cols-4 bismillah-gap-4">
<!-- Automatically adjusts columns based on viewport -->
</div>
<!-- Auto-fit pattern -->
<div class="bismillah-grid bismillah-grid-cols-[repeat(auto-fit,minmax(300px,1fr))] bismillah-gap-4">
<!-- Fills available space with cards minimum 300px wide -->
</div>Animation Extensions
// tailwind.config.js
export default {
theme: {
extend: {
keyframes: {
'fade-in': {
'0%': { opacity: '0' },
'100%': { opacity: '1' },
},
'slide-in': {
'0%': { transform: 'translateX(-100%)' },
'100%': { transform: 'translateX(0)' },
},
'bounce-alt': {
'0%, 100%': { transform: 'translateY(-25%)' },
'50%': { transform: 'none' },
},
},
animation: {
'fade-in': 'fade-in 0.3s ease-in',
'slide-in': 'slide-in 0.4s ease-out',
'bounce-alt': 'bounce-alt 1s infinite',
'pulse-slow': 'pulse 3s cubic-bezier(0.4, 0, 0.6, 1) infinite',
},
},
},
}CSS-in-JS Integration
// With Emotion
import { css } from '@emotion/react';
import styled from '@emotion/styled';
const CardStyles = styled.div`
@apply bismillah-bg-white bismillah-rounded-lg bismillah-shadow-md bismillah-p-6;
&:hover {
@apply bismillah-shadow-lg bismillah-transition;
}
`;
// With styled-components
import styled from 'styled-components';
const Button = styled.button`
@apply bismillah-px-4 bismillah-py-2 bismillah-rounded-lg bismillah-bg-blue-600 bismillah-text-white;
&:hover {
@apply bismillah-bg-blue-700;
}
`; Best Practices for Extensions
- Keep custom utilities focused and reusable
- Use theme values for consistency
- Document all custom extensions
- Maintain design system tokens separately
- Test responsive behavior across breakpoints
- Consider accessibility implications
- Use TypeScript for type safety
- Extract repeated patterns into components
- Monitor CSS file size growth
- Version control design system changes
Common Extension Patterns
Data Attribute Selectors
// Extend with data attribute utilities
export default {
plugins: [
function({ addVariant }) {
addVariant('data-active', '&[data-active]');
addVariant('data-disabled', '&[data-disabled]');
addVariant('data-state-open', '&[data-state="open"]');
},
],
}CSS Variables with Utilities
<!-- Use CSS variables with BismillahCSS utilities -->
<style>
:root {
--primary-color: #3b82f6;
--primary-dark: #1e40af;
}
</style>
<button class="bismillah-bg-[var(--primary-color)] hover:bismillah-bg-[var(--primary-dark)]">
Dynamic Color Button
</button>Performance Optimization
// Optimize by limiting scope
export default {
content: [
'./src/**/*.{js,ts,jsx,tsx}',
// Don't include node_modules
],
safelist: {
// Keep essential classes
pattern: /^(bismillah-)/,
variants: ['sm', 'md', 'lg', 'dark'],
},
}