NakedScrollbar
State-aware scrollbar over Flutter RawScrollbar
Pass the same ScrollController to NakedScrollbar and its scrollable. The wrapper retains RawScrollbar painting, fading, hit testing and thumb dragging. thumbColor, trackColor, trackBorderColor and thickness accept WidgetStateProperty values for hover and drag styling.
thumbVisibility, trackVisibility, interactive, radius, margins and fade durations control presentation. A visible track requires a visible thumb. Do not combine shape and radius; dispose controllers owned by your widget.
Basic implementation
import 'package:flutter/material.dart';
import 'package:naked_ui/naked_ui.dart';
import '../src/example_app.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const ExampleApp(child: Center(child: ScrollbarExample()));
}
}
class ScrollbarExample extends StatefulWidget {
const ScrollbarExample({super.key});
@override
State<ScrollbarExample> createState() => _ScrollbarExampleState();
}
class _ScrollbarExampleState extends State<ScrollbarExample> {
final _controller = ScrollController();
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return PrimaryScrollController(
controller: _controller,
child: SizedBox(
height: 240,
width: 280,
child: NakedScrollbar(
thumbVisibility: true,
thickness: const WidgetStatePropertyAll(8),
radius: const Radius.circular(8),
thumbColor: WidgetStateProperty.resolveWith((states) {
if (states.contains(WidgetState.dragged)) {
return Colors.blue.shade700;
}
if (states.contains(WidgetState.hovered)) return Colors.blue;
return Colors.blue.shade200;
}),
child: ListView.builder(
primary: true,
itemCount: 30,
itemBuilder: (context, index) => Padding(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
child: Text('Row $index'),
),
),
),
),
);
}
}Source and accessibility
See the package implementation for the complete API. Keep visible labels, focus indication and sufficient contrast in your presentation layer.