naked 0.0.1-dev.0
naked: ^0.0.1-dev.0 copied to clipboard
A library of behavior-first UI components for Flutter that separate state from presentation.
Naked #
A collection of behavior-first UI components for Flutter that separate state management and interaction logic from visual rendering.
Features #
- Complete separation of state from presentation
- Fully customizable appearance
- Consistent interaction patterns
- Built-in accessibility support
- Comprehensive testing
Installation #
Add this package to your pubspec.yaml:
dependencies:
naked: ^0.0.1-dev.0
Usage #
HeadlessButton #
A headless button component that manages interaction state while allowing complete visual customization.
import 'package:flutter/material.dart';
import 'package:naked/naked.dart';
class CustomButton extends StatelessWidget {
final String text;
final VoidCallback? onPressed;
final bool isLoading;
const CustomButton({
Key? key,
required this.text,
this.onPressed,
this.isLoading = false,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return HeadlessButton(
onPressed: onPressed,
isLoading: isLoading,
semanticLabel: text,
builder: (context, state) {
// Determine appearance based on state
Color backgroundColor;
double elevation;
switch (state) {
case HeadlessInteractiveState.disabled:
backgroundColor = Colors.grey.shade300;
elevation = 0;
break;
case HeadlessInteractiveState.pressed:
backgroundColor = Colors.blue.shade700;
elevation = 0;
break;
case HeadlessInteractiveState.hovered:
backgroundColor = Colors.blue.shade500;
elevation = 4;
break;
case HeadlessInteractiveState.focused:
backgroundColor = Colors.blue.shade600;
elevation = 2;
break;
}
// Use defaults for any future states
backgroundColor ??= Colors.blue.shade600;
elevation ??= 2;
return AnimatedContainer(
duration: Duration(milliseconds: 200),
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
decoration: BoxDecoration(
color: backgroundColor,
borderRadius: BorderRadius.circular(8),
boxShadow: elevation > 0
? [BoxShadow(color: Colors.black26, blurRadius: elevation)]
: null,
),
child: isLoading
? SizedBox(
width: 20,
height: 20,
child: CircularProgressIndicator(
strokeWidth: 2,
valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
),
)
: Text(
text,
style: TextStyle(
color: Colors.white,
fontWeight: state == HeadlessInteractiveState.pressed
? FontWeight.bold
: FontWeight.normal,
),
),
);
},
);
}
}
## Design Philosophy
The "naked" pattern is inspired by the "Blank Canvas" or "Headless UI" approaches, where widgets:
1. Manage their internal state and interaction logic
2. Expose state via builder functions
3. Delegate rendering entirely to the consumer
This approach allows for unlimited visual customization while maintaining consistent behavior and accessibility.
## Advanced Usage
### Using External State Controllers
For more advanced use cases, you can provide an external state controller to access all active states:
```dart
// Create a controller
final controller = HeadlessInteractiveStateController();
// Use it with a button
HeadlessButton(
stateController: controller,
onPressed: () {},
builder: (context, primaryState) {
// You can use the primary state for simple cases
// For advanced cases, access all active states
return AnimatedBuilder(
animation: controller,
builder: (context, _) {
final states = controller.states;
// Use the full set of states for complex UI decisions
// ...
},
);
},
)
License #
MIT