Documentation Index
Fetch the complete documentation index at: https://docs.thehuxdesign.com/llms.txt
Use this file to discover all available pages before exploring further.
Overview
Learn advanced customization techniques for modifying Hux UI components beyond the standard theming system. This guide covers component wrapping, style overrides, composition patterns, and creating custom variants.
Component Wrapping
Wrapping with Decorators
Wrap Hux components with additional styling or behavior:
// Add custom shadow and border
Container(
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.1),
blurRadius: 10,
offset: Offset(0, 4),
),
],
borderRadius: BorderRadius.circular(12),
),
child: HuxButton(
onPressed: () {},
child: Text('Wrapped Button'),
),
)
Custom Padding and Margins
Add custom spacing around components:
Padding(
padding: EdgeInsets.symmetric(horizontal: 24, vertical: 16),
child: HuxInput(
label: 'Email',
hint: 'Enter your email',
),
)
Style Overrides
Using Theme Extensions
Override component styles through theme extensions:
final customTheme = HuxTheme.lightTheme.copyWith(
elevatedButtonTheme: ElevatedButtonThemeData(
style: ElevatedButton.styleFrom(
padding: EdgeInsets.symmetric(horizontal: 32, vertical: 16),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
),
),
);
Custom Color Overrides
Override colors on individual components:
HuxButton(
onPressed: () {},
primaryColor: Colors.deepPurple,
child: Text('Custom Color'),
)
HuxBadge(
label: 'New',
variant: HuxBadgeVariant.primary,
// Custom styling through theme tokens
)
Composition Patterns
Building Custom Components
Create reusable components by composing Hux UI components:
class CustomActionButton extends StatelessWidget {
final String label;
final IconData icon;
final VoidCallback onPressed;
final bool isDestructive;
const CustomActionButton({
required this.label,
required this.icon,
required this.onPressed,
this.isDestructive = false,
});
@override
Widget build(BuildContext context) {
return HuxButton(
onPressed: onPressed,
variant: isDestructive
? HuxButtonVariant.outline
: HuxButtonVariant.primary,
icon: icon,
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(icon, size: 18),
SizedBox(width: 8),
Text(label),
],
),
);
}
}
Create specialized input components:
class EmailInput extends StatelessWidget {
final String? label;
final String? hint;
final ValueChanged<String>? onChanged;
final String? Function(String?)? validator;
const EmailInput({
this.label,
this.hint,
this.onChanged,
this.validator,
});
@override
Widget build(BuildContext context) {
return HuxInput(
label: label ?? 'Email',
hint: hint ?? 'Enter your email address',
prefixIcon: Icon(LucideIcons.mail),
keyboardType: TextInputType.emailAddress,
onChanged: onChanged,
validator: validator ?? (value) {
if (value == null || value.isEmpty) {
return 'Please enter your email';
}
if (!value.contains('@')) {
return 'Please enter a valid email';
}
return null;
},
);
}
}
Custom Variants
Extend button functionality with custom variants:
class CustomButton extends StatelessWidget {
final VoidCallback? onPressed;
final Widget child;
final bool isGradient;
const CustomButton({
required this.onPressed,
required this.child,
this.isGradient = false,
});
@override
Widget build(BuildContext context) {
if (isGradient) {
return Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.blue, Colors.purple],
),
borderRadius: BorderRadius.circular(8),
),
child: HuxButton(
onPressed: onPressed,
variant: HuxButtonVariant.ghost,
child: child,
),
);
}
return HuxButton(
onPressed: onPressed,
child: child,
);
}
}
Custom Card Variants
Create specialized card components:
class StatCard extends StatelessWidget {
final String title;
final String value;
final IconData icon;
final Color? color;
const StatCard({
required this.title,
required this.value,
required this.icon,
this.color,
});
@override
Widget build(BuildContext context) {
return HuxCard(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
title,
style: TextStyle(
color: HuxTokens.textSecondary(context),
fontSize: 14,
),
),
Icon(
icon,
color: color ?? HuxTokens.primary(context),
size: 20,
),
],
),
SizedBox(height: 8),
Text(
value,
style: TextStyle(
color: HuxTokens.textPrimary(context),
fontSize: 24,
fontWeight: FontWeight.bold,
),
),
],
),
);
}
}
Advanced Styling
Custom Animations
Add custom animations to components:
class AnimatedButton extends StatefulWidget {
final VoidCallback? onPressed;
final Widget child;
const AnimatedButton({
required this.onPressed,
required this.child,
});
@override
_AnimatedButtonState createState() => _AnimatedButtonState();
}
class _AnimatedButtonState extends State<AnimatedButton>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<double> _scale;
@override
void initState() {
super.initState();
_controller = AnimationController(
vsync: this,
duration: Duration(milliseconds: 100),
);
_scale = Tween<double>(begin: 1.0, end: 0.95).animate(_controller);
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTapDown: (_) => _controller.forward(),
onTapUp: (_) {
_controller.reverse();
widget.onPressed?.call();
},
onTapCancel: () => _controller.reverse(),
child: ScaleTransition(
scale: _scale,
child: HuxButton(
onPressed: widget.onPressed,
child: widget.child,
),
),
);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
}
Conditional Styling
Apply styles based on state or conditions:
HuxButton(
onPressed: () {},
variant: isActive
? HuxButtonVariant.primary
: HuxButtonVariant.outline,
primaryColor: isActive
? Colors.green
: null,
child: Text(isActive ? 'Active' : 'Inactive'),
)
Best Practices
Composition over Modification
Prefer wrapping and composing components rather than modifying their internals:// ✅ Good - Composition
Container(
decoration: BoxDecoration(...),
child: HuxButton(...),
)
// ❌ Avoid - Modifying internal implementation
Create reusable wrapper components for common patterns:// Create once, use everywhere
class PrimaryActionButton extends StatelessWidget {
// Custom implementation
}
Always use HuxTokens for colors to maintain theme consistency:// ✅ Good
color: HuxTokens.textPrimary(context)
// ❌ Avoid
color: Colors.black
Maintain accessibility when customizing:// Ensure proper contrast ratios
// Use semantic colors from HuxTokens
// Maintain keyboard navigation
Examples
Component Composition
See how to compose multiple Hux components
Custom Variants
Learn to create custom component variants
Theming Guide
Basic theming and design tokens
Advanced Theming
Deep dive into advanced theming