chore: highlight selected item in dropdowns (#2181)

This commit is contained in:
ggurdin 2025-03-19 15:34:38 -04:00 committed by GitHub
parent 1c1777bce4
commit af923d67bf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 174 additions and 80 deletions

View file

@ -15,6 +15,7 @@ import 'package:fluffychat/pangea/activity_planner/media_enum.dart';
import 'package:fluffychat/pangea/activity_planner/suggestion_form_field.dart';
import 'package:fluffychat/pangea/activity_planner/topic_list_repo.dart';
import 'package:fluffychat/pangea/chat_settings/widgets/language_level_dropdown.dart';
import 'package:fluffychat/pangea/common/widgets/dropdown_text_button.dart';
import 'package:fluffychat/pangea/instructions/instructions_enum.dart';
import 'package:fluffychat/pangea/instructions/instructions_inline_tooltip.dart';
import 'package:fluffychat/pangea/learning_settings/constants/language_constants.dart';
@ -256,23 +257,42 @@ class ActivityPlannerPageState extends State<ActivityPlannerPage> {
),
const SizedBox(height: 24),
DropdownButtonFormField2<MediaEnum>(
customButton: CustomDropdownTextButton(
text: _selectedMedia.toDisplayCopyUsingL10n(context),
),
menuItemStyleData: const MenuItemStyleData(
padding: EdgeInsets.zero, // Remove default padding
),
decoration: InputDecoration(labelText: l10n.mediaLabel),
isExpanded: true,
dropdownStyleData: DropdownStyleData(
decoration: BoxDecoration(
color: Theme.of(context)
.colorScheme
.surfaceContainerHigh,
),
),
items: MediaEnum.values
.map(
(e) => DropdownMenuItem(
value: e,
child: Text(e.toDisplayCopyUsingL10n(context)),
child: DropdownTextButton(
text: e.toDisplayCopyUsingL10n(context),
isSelected: _selectedMedia == e,
),
),
)
.toList(),
onChanged: (val) =>
_selectedMedia = val ?? MediaEnum.nan,
onChanged: (val) {
setState(() => _selectedMedia = val ?? MediaEnum.nan);
},
value: _selectedMedia,
),
const SizedBox(height: 24),
LanguageLevelDropdown(
initialLevel: _selectedCefrLevel,
onChanged: (val) => _selectedCefrLevel = val,
onChanged: (val) =>
setState(() => _selectedCefrLevel = val),
),
const SizedBox(height: 24),
PLanguageDropdown(

View file

@ -34,8 +34,6 @@ class ConversationBotModeDynamicZone extends StatelessWidget {
decoration: InputDecoration(
hintText: L10n.of(context)
.conversationBotDiscussionZone_discussionTopicPlaceholder,
contentPadding:
const EdgeInsets.symmetric(horizontal: 28.0, vertical: 12.0),
),
controller: discussionTopicController,
validator: (value) => enabled &&
@ -57,7 +55,6 @@ class ConversationBotModeDynamicZone extends StatelessWidget {
decoration: InputDecoration(
hintText: L10n.of(context)
.conversationBotDiscussionZone_discussionKeywordsPlaceholder,
contentPadding: const EdgeInsets.symmetric(horizontal: 28.0),
),
controller: discussionKeywordsController,
enabled: hasPermission && enabled,

View file

@ -4,6 +4,7 @@ import 'package:dropdown_button2/dropdown_button2.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:fluffychat/pangea/chat_settings/constants/bot_mode.dart';
import 'package:fluffychat/pangea/common/widgets/dropdown_text_button.dart';
class ConversationBotModeSelect extends StatelessWidget {
final String? initialMode;
@ -32,15 +33,28 @@ class ConversationBotModeSelect extends StatelessWidget {
};
return DropdownButtonFormField2(
customButton: initialMode != null && options.containsKey(initialMode)
? CustomDropdownTextButton(
text: options[initialMode]!,
)
: null,
menuItemStyleData: const MenuItemStyleData(
padding: EdgeInsets.zero, // Remove default padding
),
isExpanded: true,
dropdownStyleData: DropdownStyleData(
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surfaceContainerHigh,
),
),
hint: Text(L10n.of(context).selectBotChatMode),
items: [
for (final entry in options.entries)
DropdownMenuItem(
value: entry.key,
child: Text(
entry.value,
overflow: TextOverflow.clip,
textAlign: TextAlign.center,
child: DropdownTextButton(
text: entry.value,
isSelected: initialMode == entry.key,
),
),
],

View file

@ -1,6 +1,5 @@
import 'package:flutter/material.dart';
import 'package:dropdown_button2/dropdown_button2.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:fluffychat/pangea/chat_settings/models/bot_options_model.dart';
@ -9,6 +8,8 @@ import 'package:fluffychat/pangea/chat_settings/widgets/conversation_bot/convers
import 'package:fluffychat/pangea/chat_settings/widgets/conversation_bot/conversation_bot_no_permission_dialog.dart';
import 'package:fluffychat/pangea/chat_settings/widgets/language_level_dropdown.dart';
import 'package:fluffychat/pangea/learning_settings/enums/language_level_type_enum.dart';
import 'package:fluffychat/pangea/learning_settings/utils/p_language_store.dart';
import 'package:fluffychat/pangea/learning_settings/widgets/p_language_dropdown.dart';
import 'package:fluffychat/widgets/matrix.dart';
class ConversationBotSettingsForm extends StatelessWidget {
@ -48,44 +49,15 @@ class ConversationBotSettingsForm extends StatelessWidget {
children: [
InkWell(
onTap: hasPermission ? null : () => showNoPermissionDialog(context),
child: DropdownButtonFormField2(
dropdownStyleData: const DropdownStyleData(
padding: EdgeInsets.zero,
),
hint: Text(
L10n.of(context).selectBotLanguage,
overflow: TextOverflow.clip,
textAlign: TextAlign.center,
),
value: botOptions.targetLanguage,
isExpanded: true,
items: MatrixState.pangeaController.pLanguageStore.targetOptions
.map((language) {
return DropdownMenuItem(
value: language.langCode,
child: Text(
language.getDisplayName(context) ?? language.langCode,
overflow: TextOverflow.clip,
textAlign: TextAlign.center,
),
);
}).toList(),
onChanged: hasPermission && enabled ? onUpdateBotLanguage : null,
),
),
const SizedBox(height: 12),
InkWell(
onTap: hasPermission ? null : () => showNoPermissionDialog(context),
child: DropdownButtonFormField2<String>(
hint: Text(
L10n.of(context).chooseVoice,
overflow: TextOverflow.clip,
textAlign: TextAlign.center,
),
value: botOptions.targetVoice,
isExpanded: true,
items: const [],
onChanged: hasPermission && enabled ? onUpdateBotVoice : null,
child: PLanguageDropdown(
languages:
MatrixState.pangeaController.pLanguageStore.targetOptions,
onChange: (lang) => hasPermission && enabled
? onUpdateBotLanguage(lang.langCode)
: null,
initialLanguage: botOptions.targetLanguage != null
? PLanguageStore.byLangCode(botOptions.targetLanguage!)
: null,
),
),
const SizedBox(height: 12),

View file

@ -5,6 +5,7 @@ import 'package:dropdown_button2/dropdown_button2.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:fluffychat/pangea/chat_settings/utils/language_level_copy.dart';
import 'package:fluffychat/pangea/common/widgets/dropdown_text_button.dart';
import 'package:fluffychat/pangea/learning_settings/enums/language_level_type_enum.dart';
class LanguageLevelDropdown extends StatelessWidget {
@ -26,39 +27,47 @@ class LanguageLevelDropdown extends StatelessWidget {
@override
Widget build(BuildContext context) {
return DropdownButtonFormField2<LanguageLevelTypeEnum>(
decoration: InputDecoration(labelText: L10n.of(context).cefrLevelLabel),
hint: Text(
L10n.of(context).selectLanguageLevel,
overflow: TextOverflow.clip,
textAlign: TextAlign.center,
customButton: initialLevel != null &&
LanguageLevelTypeEnum.values.contains(initialLevel)
? CustomDropdownTextButton(
text: LanguageLevelTextPicker.languageLevelText(
context,
initialLevel!,
),
)
: null,
menuItemStyleData: const MenuItemStyleData(
padding: EdgeInsets.zero, // Remove default padding
),
decoration: InputDecoration(
labelText: L10n.of(context).cefrLevelLabel,
),
isExpanded: true,
dropdownStyleData: DropdownStyleData(
maxHeight: kIsWeb ? 500 : null,
decoration: BoxDecoration(
color: backgroundColor ??
Theme.of(context).colorScheme.surfaceContainerHigh,
),
),
value: initialLevel,
items:
LanguageLevelTypeEnum.values.map((LanguageLevelTypeEnum levelOption) {
return DropdownMenuItem(
value: levelOption,
child: Text(
LanguageLevelTextPicker.languageLevelText(
child: DropdownTextButton(
text: LanguageLevelTextPicker.languageLevelText(
context,
levelOption,
),
overflow: TextOverflow.clip,
textAlign: TextAlign.center,
isSelected: initialLevel == levelOption,
),
);
}).toList(),
onChanged: enabled
? (value) => onChanged?.call(value as LanguageLevelTypeEnum)
: null,
value: initialLevel,
validator: validator,
dropdownStyleData: DropdownStyleData(
maxHeight: kIsWeb ? 500 : null,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(14),
color: backgroundColor ??
Theme.of(context).colorScheme.surfaceContainerHigh,
),
),
);
}
}

View file

@ -0,0 +1,63 @@
import 'package:flutter/material.dart';
class DropdownTextButton extends StatelessWidget {
final bool isSelected;
final String text;
const DropdownTextButton({
required this.text,
this.isSelected = false,
super.key,
});
@override
Widget build(BuildContext context) {
return Container(
color: isSelected
? Theme.of(context)
.colorScheme
.primary
.withAlpha(20) // Highlight selected
: Colors.transparent,
padding: const EdgeInsets.symmetric(
vertical: 12,
horizontal: 12,
),
child: Row(
children: [
Text(
text,
overflow: TextOverflow.clip,
),
],
),
);
}
}
class CustomDropdownTextButton extends StatelessWidget {
final String text;
const CustomDropdownTextButton({
required this.text,
super.key,
});
@override
Widget build(BuildContext context) {
return Row(
children: [
Expanded(
child: Text(
text,
overflow: TextOverflow.clip,
),
),
Icon(
Icons.arrow_drop_down,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
],
);
}
}

View file

@ -43,6 +43,9 @@ class CountryPickerDropdownState extends State<CountryPickerDropdown> {
isDropdown: true,
)
: null,
menuItemStyleData: const MenuItemStyleData(
padding: EdgeInsets.zero,
),
isExpanded: true,
decoration: InputDecoration(
labelText: L10n.of(context).countryInformation,
@ -50,7 +53,7 @@ class CountryPickerDropdownState extends State<CountryPickerDropdown> {
dropdownStyleData: DropdownStyleData(
maxHeight: kIsWeb ? 500 : null,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(14),
// borderRadius: BorderRadius.circular(14),
color: Theme.of(context).colorScheme.surfaceContainerHigh,
),
),
@ -58,7 +61,16 @@ class CountryPickerDropdownState extends State<CountryPickerDropdown> {
...countries.map(
(country) => DropdownMenuItem(
value: country,
child: CountryPickerTile(country),
child: Container(
color: widget.learningController.country == country
? Theme.of(context).colorScheme.primary.withAlpha(20)
: Colors.transparent,
padding: const EdgeInsets.symmetric(
vertical: 8,
horizontal: 12,
),
child: CountryPickerTile(country),
),
),
),
],

View file

@ -16,7 +16,7 @@ class PLanguageDropdown extends StatefulWidget {
final Function(LanguageModel) onChange;
final bool showMultilingual;
final bool isL2List;
final String decorationText;
final String? decorationText;
final String? error;
final String? Function(LanguageModel?)? validator;
final Color? backgroundColor;
@ -28,7 +28,7 @@ class PLanguageDropdown extends StatefulWidget {
required this.onChange,
required this.initialLanguage,
this.showMultilingual = false,
required this.decorationText,
this.decorationText,
this.isL2List = false,
this.error,
this.validator,
@ -95,21 +95,19 @@ class PLanguageDropdownState extends State<PLanguageDropdown> {
isDropdown: true,
)
: null,
menuItemStyleData: const MenuItemStyleData(
padding: EdgeInsets.zero,
),
decoration: InputDecoration(
labelText: widget.decorationText,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(36.0),
),
enabledBorder: hasError
? OutlineInputBorder(
borderRadius: BorderRadius.circular(36.0),
borderSide:
BorderSide(color: Theme.of(context).colorScheme.error),
)
: null,
focusedBorder: hasError
? OutlineInputBorder(
borderRadius: BorderRadius.circular(36.0),
borderSide: BorderSide(
color: Theme.of(context).colorScheme.error,
width: 2,
@ -138,9 +136,18 @@ class PLanguageDropdownState extends State<PLanguageDropdown> {
...sortedLanguages.map(
(languageModel) => DropdownMenuItem(
value: languageModel,
child: LanguageDropDownEntry(
languageModel: languageModel,
isL2List: widget.isL2List,
child: Container(
color: widget.initialLanguage == languageModel
? Theme.of(context).colorScheme.primary.withAlpha(20)
: Colors.transparent,
padding: const EdgeInsets.symmetric(
vertical: 8,
horizontal: 12,
),
child: LanguageDropDownEntry(
languageModel: languageModel,
isL2List: widget.isL2List,
),
),
),
),