drawably_flutter 0.0.2
drawably_flutter: ^0.0.2 copied to clipboard
Animated hand-drawn Flutter controls and decorations with deterministic seeded sketches.
Drawably Flutter #
Playful, animated hand-drawn controls and decorations for Flutter. Every widget is rendered with deterministic seeded randomness and can gently “boil” between three cached sketch frames.
Features #
- Outline, solid, and scribbled buttons
- Checkbox, radio, and toggle controls
- Cards, badges, and rough dividers
- Underline, highlight, and circle decorations
- Reproducible output using seeded randomness
- Shared styling through
DrawablyTheme - Keyboard navigation and semantic control states
- Automatic reduced-motion support
- No runtime dependency beyond Flutter
Installation #
flutter pub add drawably_flutter
Then import the package:
import 'package:drawably_flutter/drawably_flutter.dart';
Quick start #
DrawablyButton(
onPressed: () {
// Handle the press.
},
child: const Text('Create sketch'),
)
Buttons #
Choose from three visual variants and optional state/tone values:
Wrap(
spacing: 12,
children: [
DrawablyButton(
onPressed: () {},
child: const Text('Outline'),
),
DrawablyButton(
variant: DrawablyButtonVariant.solid,
onPressed: () {},
child: const Text('Solid'),
),
DrawablyButton(
variant: DrawablyButtonVariant.scribble,
onPressed: () {},
child: const Text('Scribble'),
),
],
)
For asynchronous actions, set state to loading, success, or error. Use tone for neutral and destructive actions.
DrawablyButton(
state: isSaving
? DrawablyButtonState.loading
: DrawablyButtonState.idle,
tone: DrawablyTone.primary,
onPressed: isSaving ? null : save,
child: const Text('Save'),
)
Selection controls #
Drawably controls use Flutter's familiar controlled-widget pattern. Your application owns the value and updates it in setState or your state-management solution.
DrawablyCheckbox(
value: checked,
semanticLabel: 'Accept terms',
onChanged: (value) => setState(() => checked = value),
)
DrawablyRadio<int>(
value: 1,
groupValue: selected,
onChanged: (value) => setState(() => selected = value),
)
DrawablyToggle(
value: notificationsEnabled,
semanticLabel: 'Notifications',
onChanged: (value) {
setState(() => notificationsEnabled = value);
},
)
Pass null to onChanged or onPressed to render a disabled control.
Containers and decorations #
Column(
children: [
const DrawablyCard(
child: Text('Any Flutter widget can go here.'),
),
const DrawablyDivider(),
const Wrap(
spacing: 16,
children: [
DrawablyBadge(child: Text('New')),
DrawablyUnderline(child: Text('Important')),
DrawablyHighlight(child: Text('Highlighted')),
DrawablyCircle(child: Text('Look here')),
],
),
],
)
Styling and themes #
Set a style on DrawablyTheme to configure every descendant. A style supplied directly to a widget overrides the inherited theme.
DrawablyTheme(
data: const DrawablyStyle(
seed: 42,
strokeColor: Color(0xff173f5f),
fillColor: Color(0xffffd166),
paperColor: Color(0xfffffbf4),
strokeWidth: 2,
roughness: 1.1,
boil: 0.3,
),
child: const MyAppContent(),
)
| Property | Default | Purpose |
|---|---|---|
seed |
random | Produces a reproducible sketch when provided |
roughness |
1.0 |
Controls the amount of hand-drawn wobble |
boil |
0.3 |
Controls frame-to-frame movement; use 0 for static paths |
strokeColor |
pen blue | Colors outlines and marks |
fillColor |
white | Colors solid and highlighted areas |
paperColor |
white | Colors paper-facing content in solid controls |
strokeWidth |
2.0 |
Sets line thickness |
Motion and accessibility #
Animated sketches cycle through three cached paths over 1.2 seconds. The paths are regenerated only when their size, seed, or visual configuration changes.
Drawably automatically freezes animation when Flutter reports that the user has requested reduced motion. Checkbox, radio, toggle, and button widgets expose semantic state and keyboard activation. Supply semanticLabel when the visible context does not already describe a control.
Low-level paths #
The rough geometry functions are public, so custom CustomPainter implementations can use the same visual language:
final path = roughRoundedRect(
RRect.fromRectAndRadius(
const Rect.fromLTWH(0, 0, 160, 48),
const Radius.circular(8),
),
const RoughOptions(seed: 42, roughness: 1.0),
);
Also available: roughLine, roughCircle, roughEllipse, roughCheckmark, and scribbleFill.
Example #
The complete showcase lives in example/lib/main.dart. Run it with:
cd example
flutter run
The package is still pre-1.0, so the public API may evolve between minor releases.
Attribution #
This is an independent Flutter port inspired by Daniel Belyi's MIT-licensed Drawably JavaScript library. It is not an official upstream package.
License #
MIT. The original Drawably copyright notice is preserved in LICENSE.
