suggestly_flutter 0.1.0
suggestly_flutter: ^0.1.0 copied to clipboard
Themeable dialogs in flutter for Suggestly feedback flows: feature requests, bug reports, and ratings.
suggestly_flutter #
Reusable, fully themeable Material 3 dialogs that capture text input, feature requests, bug reports (with environment + attachments), and star ratings. Every popup respects accessibility, null safety, and text scaling and can be themed globally or per instance.
Features #
TextInputPopup– simple text field dialog with validators and action callbacks.FeatureRequestPopup– reproduces the Suggestly feature form with priority + version inputs.BugReportPopup– matches the web bug report form including environment details and up to 5 validated image attachments.RatingPopup– star-based selector with optional comment and labels.- Shared action model, barrier configuration, autofocus, and semantic labels for all popups.
Getting started #
Add the dependency to your pubspec.yaml (path assumes the monorepo layout):
dependencies:
suggestly_flutter:
path: ../suggestly.packages/suggestly_input_popup
Then import the package:
import 'package:suggestly_flutter/suggestly_flutter.dart';
Usage #
Text input #
Future<void> promptForName(BuildContext context) async {
final result = await TextInputPopup.show(
context,
title: 'Rename list',
message: 'Enter a descriptive name so collaborators understand it.',
hintText: 'Team grocery list',
validator: (value) {
if (value == null || value.trim().isEmpty) {
return 'Please provide a name.';
}
return null;
},
primaryAction: const TextInputPopupAction(label: 'Save'),
);
if (result?.action == TextInputPopupActionType.primary) {
debugPrint('New name: ${result!.text}');
}
}
Feature requests #
final feature = await FeatureRequestPopup.show(
context,
title: 'Request a feature',
message: 'Share what would make Suggestly more helpful.',
primaryAction: const TextInputPopupAction(label: 'Submit request'),
);
if (feature?.action == TextInputPopupActionType.primary) {
debugPrint('Priority: ${feature!.data.priorityName}');
}
Bug reports (with attachments) #
final bug = await BugReportPopup.show(
context,
title: 'Report a bug',
message: 'Attachments are optional but recommended.',
onAddAttachments: (ctx, current) async {
// Delegate to your own file picker / camera flow.
return pickImagesFromGallery(limit: 5 - current.length);
},
primaryAction: const TextInputPopupAction(label: 'Send report'),
);
if (bug?.action == TextInputPopupActionType.primary) {
debugPrint('Attachments: ${bug!.data.attachments.length}');
}
Ratings #
final rating = await RatingPopup.show(
context,
title: 'Rate your experience',
message: 'Stars help us prioritise improvements.',
ratingLabelBuilder: (value) => '$value / 5',
primaryAction: const TextInputPopupAction(label: 'Submit rating'),
);
if (rating?.action == TextInputPopupActionType.primary) {
debugPrint('Rating: ${rating!.rating}');
debugPrint('Comment: ${rating.comment ?? '(none)'}');
}
Theming #
Wrap a subtree with TextInputPopupTheme to provide defaults, or supply overrides per call:
TextInputPopupTheme(
data: TextInputPopupThemeData(
backgroundColor: Theme.of(context).colorScheme.surfaceContainerHigh,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(24)),
contentPadding: const EdgeInsets.fromLTRB(28, 28, 28, 20),
inputDecoration: const InputDecoration(prefixIcon: Icon(Icons.person)),
primaryButtonStyle: FilledButton.styleFrom(minimumSize: const Size(120, 40)),
),
child: Builder(
builder: (context) => FilledButton(
onPressed: () {
RatingPopup.show(context, title: 'Rate Suggestly');
},
child: const Text('Give feedback'),
),
),
);
Additional information #
flutter analyzeandflutter testrun clean.BugReportPopupenforces the same limits as the Suggestly web app (image type, ≤5 files, ≤5 MB each). SupplyonAddAttachmentsto integrate your picker of choice.- Contributions, issues, and suggestions are welcome.