feat(ui): a question mark that keeps a section's explanation one tap away
HelpButton, beside a section's or a setting's title: the explanation opens in a small dialog, under its title where given, rather than standing in the everyday view (the developer's review of 3 Nov 2026). FieldInfoButton's tooltip stays for a field's short hint. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
abac248b76
commit
55fc245859
8 changed files with 85 additions and 3 deletions
|
|
@ -26,6 +26,7 @@ export 'src/widget/field_label.dart';
|
|||
export 'src/widget/floating_navigation_bar.dart';
|
||||
export 'src/widget/folding_tabs.dart';
|
||||
export 'src/widget/found_by_id.dart';
|
||||
export 'src/widget/help_button.dart';
|
||||
export 'src/widget/keyboard_back_on_resume.dart';
|
||||
export 'src/widget/launch_screen.dart';
|
||||
export 'src/widget/lift_while_dragged.dart';
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
{
|
||||
"@@locale": "de",
|
||||
|
||||
"brand": "Halkyon",
|
||||
"close": "Schließen",
|
||||
"cancel": "Abbrechen",
|
||||
|
|
@ -17,5 +16,6 @@
|
|||
"copiedToClipboard": "In die Zwischenablage kopiert",
|
||||
"copy": "Kopieren",
|
||||
"paletteColorName": "{name, select, carrot{Karotte} cerise{Kirschrot} cobalt{Kobalt} copper{Kupfer} enzian{Enzian} fern{Farn} forest{Wald} ocean{Ozean} olive{Olive} pacific{Pazifik} pickle{Essiggurke} pine{Kiefer} pink{Rosa} plum{Pflaume} purple{Lila} reef{Riff} sahara{Sahara} slateblue{Schieferblau} soil{Erde} strawberry{Erdbeere} other{{name}}}",
|
||||
"colorPickerLabel": "Farbe: {color}"
|
||||
"colorPickerLabel": "Farbe: {color}",
|
||||
"explain": "Was ist das?"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
{
|
||||
"@@locale": "en",
|
||||
|
||||
"brand": "Halkyon",
|
||||
"@brand": {
|
||||
"description": "The brand's word, above an app's own in its wordmark (\"Halkyon\" over \"Learn\")."
|
||||
|
|
@ -38,5 +37,9 @@
|
|||
"type": "String"
|
||||
}
|
||||
}
|
||||
},
|
||||
"explain": "What's this?",
|
||||
"@explain": {
|
||||
"description": "Tooltip of the question mark that opens a text explaining a section or setting (HelpButton)."
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -204,6 +204,12 @@ abstract class HalkyonUiLocalizations {
|
|||
/// In en, this message translates to:
|
||||
/// **'Colour: {color}'**
|
||||
String colorPickerLabel(String color);
|
||||
|
||||
/// Tooltip of the question mark that opens a text explaining a section or setting (HelpButton).
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'What\'s this?'**
|
||||
String get explain;
|
||||
}
|
||||
|
||||
class _HalkyonUiLocalizationsDelegate
|
||||
|
|
|
|||
|
|
@ -90,4 +90,7 @@ class HalkyonUiLocalizationsDe extends HalkyonUiLocalizations {
|
|||
String colorPickerLabel(String color) {
|
||||
return 'Farbe: $color';
|
||||
}
|
||||
|
||||
@override
|
||||
String get explain => 'Was ist das?';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,6 +90,9 @@ class HalkyonUiLocalizationsEn extends HalkyonUiLocalizations {
|
|||
String colorPickerLabel(String color) {
|
||||
return 'Colour: $color';
|
||||
}
|
||||
|
||||
@override
|
||||
String get explain => 'What\'s this?';
|
||||
}
|
||||
|
||||
/// The translations for English, as used in the United Kingdom (`en_GB`).
|
||||
|
|
|
|||
37
packages/halkyon_ui/lib/src/widget/help_button.dart
Normal file
37
packages/halkyon_ui/lib/src/widget/help_button.dart
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
import 'package:halkyon_ui/l10n/halkyon_ui_localizations.dart';
|
||||
import 'package:halkyon_ui/src/widget/field_label.dart';
|
||||
import 'package:lucide_icons_flutter/lucide_icons.dart';
|
||||
import 'package:material_ui/material_ui.dart';
|
||||
|
||||
/// A question mark beside a section's or a setting's title that keeps its
|
||||
/// explanation out of the everyday view: a tap opens [message] in a small
|
||||
/// dialog, under [title] where given (decided 3 Nov 2026: what explains,
|
||||
/// rather than what is the person's own, is one tap away). For a field's
|
||||
/// short hint, [FieldInfoButton]'s tooltip.
|
||||
class const HelpButton(
|
||||
final String message, {
|
||||
final String? title,
|
||||
super.key,
|
||||
}) extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) => IconButton(
|
||||
icon: const Icon(LucideIcons.circleQuestionMark, size: 20),
|
||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
visualDensity: VisualDensity.compact,
|
||||
tooltip: HalkyonUiLocalizations.of(context).explain,
|
||||
onPressed: () => showDialog<void>(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
icon: const Icon(LucideIcons.circleQuestionMark),
|
||||
title: title == null ? null : Text(title!),
|
||||
content: SingleChildScrollView(child: Text(message)),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: Text(MaterialLocalizations.of(context).okButtonLabel),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
29
packages/halkyon_ui/test/widget/help_button_test.dart
Normal file
29
packages/halkyon_ui/test/widget/help_button_test.dart
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:halkyon_ui/halkyon_ui.dart';
|
||||
import 'package:material_ui/material_ui.dart';
|
||||
|
||||
import '../support/test_app.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('the explanation stays hidden until the question mark is '
|
||||
'tapped, then shows under its title and closes again', (tester) async {
|
||||
await tester.pumpWidget(
|
||||
testApp(
|
||||
const Scaffold(
|
||||
body: HelpButton('How sources are cited.', title: 'Citation style'),
|
||||
),
|
||||
),
|
||||
);
|
||||
expect(find.text('How sources are cited.'), findsNothing);
|
||||
expect(find.byTooltip("What's this?"), findsOneWidget);
|
||||
|
||||
await tester.tap(find.byType(HelpButton));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('Citation style'), findsOneWidget);
|
||||
expect(find.text('How sources are cited.'), findsOneWidget);
|
||||
|
||||
await tester.tap(find.text('OK'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('How sources are cited.'), findsNothing);
|
||||
});
|
||||
}
|
||||
Loading…
Reference in a new issue