Getting Started
Behavior-first, zero-styling Flutter components
The Naked UI library provides headless components that handle functionality, interaction, and accessibility without imposing any visual styling. This approach gives you full control over your design system while ensuring components work correctly and meet accessibility standards.
What is headless UI?
Headless components handle interaction behavior and accessibility without visual styling. They provide:
- Keyboard navigation (pressing Tab, Enter, arrow keys)
- Screen reader announcements
- Mouse interactions (hover, click, drag)
- Focus management
- Touch gestures
Headless components provide behavior and accessibility without visual styling.
Standard UI library approach
Most UI libraries give you components that look like this:
import 'package:flutter/material.dart';
import 'package:naked_ui/naked_ui.dart';
// Standard UI library approach
Widget example0(BuildContext context, FocusNode myFocusNode) {
return ElevatedButton(
onPressed: () {},
child: const Text('Click me'), // Fixed appearance
);
}Standard libraries limit customization to predefined themes and styles. Design flexibility is constrained.
The Naked UI approach
Naked UI provides custom styling through builders:
import 'package:flutter/material.dart';
import 'package:naked_ui/naked_ui.dart';
Widget example1(BuildContext context, FocusNode myFocusNode) {
return NakedButton(
onPressed: () {},
builder: (context, state, child) {
// Custom styling based on state
return Container(
decoration: BoxDecoration(
color: state.isPressed ? Colors.blue.shade700 : Colors.blue,
borderRadius: BorderRadius.circular(8),
// Customize any aspect of design
),
child: const Text('Click me'),
);
},
);
}Components handle behavior. Builders define appearance.
Key Features
- Zero-styling: behavior only - you own presentation
- Accessible: correct semantics and keyboard navigation
- Observable state: hover, focus, press, drag, select
- Composable: small, predictable APIs
Components
- NakedButton - button interactions (hover, press, focus)
- NakedCheckbox - toggle behavior and semantics
- NakedRadio - single-select radio with group management
- NakedSelect - dropdown/select with keyboard navigation
- NakedSlider - value slider with drag + keys
- NakedToggle - toggle button or switch behavior
- NakedTabs - tablist + roving focus
- NakedAccordion - expandable/collapsible sections
- NakedDisclosure - standalone show/hide button and panel
- NakedMenu - anchored overlay menu
- NakedDialog - modal dialog behavior + focus trap
- NakedLink - link semantics, activation, and observable interaction state
- NakedTooltip - anchored tooltip with lifecycle
- NakedPopover - anchored, dismissible popover overlay
- Switch (NakedToggle) - on/off control with switch semantics
- NakedTextField - native text editing with custom styling
Getting Started
Installation
dependencies:
naked_ui: ^1.5.0 # https://pub.dev/packages/naked_uiThen: flutter pub get
Import: import 'package:naked_ui/naked_ui.dart';
Basic implementation
Build a simple button:
import 'package:flutter/material.dart';
import 'package:naked_ui/naked_ui.dart';
Widget example2(BuildContext context, FocusNode myFocusNode) {
return NakedButton(
onPressed: () => print('Hello World!'),
builder: (context, state, child) {
return Container(
padding: const EdgeInsets.all(12),
color: state.isPressed ? Colors.blue : Colors.grey,
child: const Text('Submit'),
);
},
);
}This button includes:
- Press state color changes
- Automatic keyboard navigation
- Screen reader support
- Mouse and touch interaction
The color changes when pressed due to the state.isPressed condition.
Implementation details
NakedButtonmanages interaction behavior and accessibilitybuilderfunction defines visual appearance based on statestate.isPressedprovides current press state- Return any Widget for custom styling
Enhanced patterns
Multiple states: Use state.when() to handle pressed, hovered, and focused states
Animations: Wrap containers in AnimatedContainer for smooth transitions
Advanced styling: Add borders, shadows, gradients, or any visual elements
Check out our Button documentation for advanced examples and patterns.
Advanced state management
Common patterns for enhanced interactivity:
Multiple interaction states
Handle pressed, hovered, and focused states:
import 'package:flutter/material.dart';
import 'package:naked_ui/naked_ui.dart';
Widget example3(BuildContext context, FocusNode myFocusNode) {
return NakedButton(
onPressed: () {},
builder: (context, state, child) {
// Method 1: Check each state individually
Color buttonColor = Colors.grey;
if (state.isPressed) buttonColor = Colors.blue.shade800;
else if (state.isHovered) buttonColor = Colors.blue.shade600;
else if (state.isFocused) buttonColor = Colors.blue.shade400;
// Method 2: Use state.when() for cleaner code
final color = state.when(
pressed: Colors.blue.shade800, // Darkest when clicked
hovered: Colors.blue.shade600, // Medium when mouse over
focused: Colors.blue.shade400, // Light when keyboard focused
orElse: Colors.grey, // Default state
);
return Container(
padding: const EdgeInsets.all(12),
color: color,
child: const Text('Interactive button'),
);
},
);
}The state.when() method provides cleaner conditional logic.
Programmatic focus control
For precise focus management in forms or complex UIs:
import 'package:flutter/material.dart';
import 'package:naked_ui/naked_ui.dart';
Widget example4(BuildContext context, FocusNode myFocusNode) {
return NakedButton(
focusNode: myFocusNode, // Use your own focus node
autofocus: true, // Focus automatically when built
onPressed: () {
myFocusNode.requestFocus(); // Focus programmatically
},
builder: (context, state, child) => const Text('Continue'),
);
}Component selection guide
All components follow the same builder pattern. Choose based on interaction requirements:
For user actions
- Button - Any clickable action (submit, save, delete, etc.)
- Toggle - On/off switches (dark mode, notifications)
- Checkbox - Select multiple options from a list
- Radio - Pick one option from a group
For user input
- TextField - Text input (names, messages, search)
- Select - Choose from a dropdown list (countries, categories)
- Slider - Pick numeric values (volume, price range)
For organizing content
- Tabs - Switch between different content sections
- Accordion - Expandable sections (FAQ, settings groups)
- Disclosure - Independently show or hide one content section
- Dialog - Modal windows (confirmations, forms)
For helpful overlays
- Tooltip - Show help text on hover
- Popover - Show additional info or controls
- Menu - Context menus and dropdown actions
Getting started
Recommended approach: Begin with Button - the simplest component for learning the core patterns. Other components use the same builder-based approach.
Next steps: Review component-specific documentation for detailed implementation examples and API references.
More widgets
- NakedCombobox — Editable selection with filtered options.
- NakedMenubar — Horizontal menu navigation and nested actions.
- NakedScrollbar — State-aware scrollbar over Flutter RawScrollbar.
- NakedToggleGroup — Controlled single-selection toggle groups.
- NakedTextMagnifier — Adaptive touch magnification for editable text.