drawably_flutter 0.0.2
drawably_flutter: ^0.0.2 copied to clipboard
Animated hand-drawn Flutter controls and decorations with deterministic seeded sketches.
import 'package:drawably_flutter/drawably_flutter.dart';
import 'package:flutter/material.dart';
void main() => runApp(const ExampleApp());
class ExampleApp extends StatelessWidget {
const ExampleApp({super.key});
@override
Widget build(BuildContext context) => MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
scaffoldBackgroundColor: const Color(0xfffffbf4),
colorScheme: ColorScheme.fromSeed(
seedColor: const Color(0xff173f5f),
surface: const Color(0xfffffbf4),
),
textTheme: const TextTheme(bodyMedium: TextStyle(fontSize: 16)),
),
home: const Showcase(),
);
}
class Showcase extends StatefulWidget {
const Showcase({super.key});
@override
State<Showcase> createState() => _ShowcaseState();
}
class _ShowcaseState extends State<Showcase> {
bool checked = true;
bool toggled = false;
int selected = 1;
@override
Widget build(BuildContext context) => DrawablyTheme(
data: const DrawablyStyle(
strokeColor: Color(0xff173f5f),
fillColor: Color(0xffffd166),
),
child: Scaffold(
body: SafeArea(
child: ListView(
padding: const EdgeInsets.fromLTRB(24, 28, 24, 36),
children: [
const Text(
'Drawably Flutter',
style: TextStyle(
color: Color(0xff173f5f),
fontSize: 32,
fontWeight: FontWeight.w800,
letterSpacing: -.8,
),
),
const SizedBox(height: 6),
const Text(
'Playful, animated hand-drawn widgets.',
style: TextStyle(color: Color(0xff667785)),
),
const SizedBox(height: 26),
const _SectionLabel('BUTTONS'),
const SizedBox(height: 12),
Wrap(
spacing: 12,
runSpacing: 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'),
),
],
),
const SizedBox(height: 18),
const DrawablyDivider(),
const SizedBox(height: 16),
const _SectionLabel('CONTROLS'),
const SizedBox(height: 12),
Row(
children: [
DrawablyCheckbox(
value: checked,
semanticLabel: 'Remember me',
onChanged: (value) => setState(() => checked = value),
),
const SizedBox(width: 20),
DrawablyRadio(
value: 1,
groupValue: selected,
onChanged: (value) => setState(() => selected = value),
),
const SizedBox(width: 12),
DrawablyRadio(
value: 2,
groupValue: selected,
onChanged: (value) => setState(() => selected = value),
),
const Spacer(),
DrawablyToggle(
value: toggled,
semanticLabel: 'Notifications',
onChanged: (value) => setState(() => toggled = value),
),
],
),
const SizedBox(height: 24),
const _SectionLabel('CONTAINERS'),
const SizedBox(height: 12),
const DrawablyCard(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Sketch-friendly cards',
style: TextStyle(fontWeight: FontWeight.w700),
),
SizedBox(height: 6),
Text(
'Wrap any Flutter widget while keeping its layout intact.',
),
],
),
),
const SizedBox(height: 24),
const _SectionLabel('DECORATIONS'),
const SizedBox(height: 14),
const Wrap(
spacing: 18,
runSpacing: 18,
crossAxisAlignment: WrapCrossAlignment.center,
children: [
DrawablyBadge(child: Text('Outline badge')),
DrawablyBadge(
variant: DrawablyBadgeVariant.scribble,
child: Text('Scribbled'),
),
DrawablyUnderline(child: Text('Underlined')),
DrawablyHighlight(child: Text('Highlighted')),
DrawablyCircle(child: Text('Circled')),
],
),
],
),
),
),
);
}
class _SectionLabel extends StatelessWidget {
const _SectionLabel(this.text);
final String text;
@override
Widget build(BuildContext context) => Text(
text,
style: const TextStyle(
color: Color(0xff8b6f47),
fontSize: 12,
fontWeight: FontWeight.w700,
letterSpacing: 1.4,
),
);
}