Skip to content
1 change: 1 addition & 0 deletions app/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased](https://github.com/Orange-OpenSource/ouds-flutter/compare/2.0.0...develop)
### Added
- [DemoApp][Library] Implementation of `Navigation Button` ([#417](https://github.com/Orange-OpenSource/ouds-flutter/issues/417))
### Changed
- [Library] update tokens 2.6.0 ([#842](https://github.com/Orange-OpenSource/ouds-flutter/issues/842))
### Fixed
Expand Down
30 changes: 30 additions & 0 deletions app/lib/l10n/gen/ouds_flutter_app_localizations.dart
Original file line number Diff line number Diff line change
Expand Up @@ -798,6 +798,36 @@ abstract class AppLocalizations {
/// **'Full width'**
String get app_components_button_fullWidth_label;

/// No description provided for @app_components_button_navigationButton_tech.
///
/// In en, this message translates to:
/// **'Navigation button'**
String get app_components_button_navigationButton_tech;

/// No description provided for @app_components_button_navigationButton_description_text.
///
/// In en, this message translates to:
/// **'A navigation button is a UI element that enables movement between different pages within a multi-page interface. The navigation button is typically arranged in a sequence to indicate the user’s current position and provide controls for accessing previous, next, or specific pages.'**
String get app_components_button_navigationButton_description_text;

/// No description provided for @app_components_button_navigationButton_chevron_tech.
///
/// In en, this message translates to:
/// **'Chevron'**
String get app_components_button_navigationButton_chevron_tech;

/// No description provided for @app_components_button_navigationButton_chevron_next_a11y.
///
/// In en, this message translates to:
/// **'Next page'**
String get app_components_button_navigationButton_chevron_next_a11y;

/// No description provided for @app_components_button_navigationButton_chevron_previous_a11y.
///
/// In en, this message translates to:
/// **'Previous page'**
String get app_components_button_navigationButton_chevron_previous_a11y;

/// No description provided for @app_components_checkbox_label.
///
/// In en, this message translates to:
Expand Down
18 changes: 18 additions & 0 deletions app/lib/l10n/gen/ouds_flutter_app_localizations_ar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,24 @@ class AppLocalizationsAr extends AppLocalizations {
@override
String get app_components_button_fullWidth_label => 'Full width';

@override
String get app_components_button_navigationButton_tech => 'Navigation button';

@override
String get app_components_button_navigationButton_description_text =>
' Navigation button هو عنصر واجهة مستخدم يتيح التنقل بين صفحات مختلفة داخل واجهة متعددة الصفحات. يتم عادةً ترتيب Navigation button ضمن تسلسل للإشارة إلى موضع المستخدم الحالي وتوفير عناصر تحكم للوصول إلى الصفحة السابقة أو التالية أو إلى صفحات محددة.';

@override
String get app_components_button_navigationButton_chevron_tech => 'Chevron';

@override
String get app_components_button_navigationButton_chevron_next_a11y =>
'الصفحة التالية';

@override
String get app_components_button_navigationButton_chevron_previous_a11y =>
'الصفحة السابقة';

@override
String get app_components_checkbox_label => 'Checkbox';

Expand Down
18 changes: 18 additions & 0 deletions app/lib/l10n/gen/ouds_flutter_app_localizations_en.dart
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,24 @@ class AppLocalizationsEn extends AppLocalizations {
@override
String get app_components_button_fullWidth_label => 'Full width';

@override
String get app_components_button_navigationButton_tech => 'Navigation button';

@override
String get app_components_button_navigationButton_description_text =>
'A navigation button is a UI element that enables movement between different pages within a multi-page interface. The navigation button is typically arranged in a sequence to indicate the user’s current position and provide controls for accessing previous, next, or specific pages.';

@override
String get app_components_button_navigationButton_chevron_tech => 'Chevron';

@override
String get app_components_button_navigationButton_chevron_next_a11y =>
'Next page';

@override
String get app_components_button_navigationButton_chevron_previous_a11y =>
'Previous page';

@override
String get app_components_checkbox_label => 'Checkbox';

Expand Down
18 changes: 18 additions & 0 deletions app/lib/l10n/gen/ouds_flutter_app_localizations_fr.dart
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,24 @@ class AppLocalizationsFr extends AppLocalizations {
@override
String get app_components_button_fullWidth_label => 'Full width';

@override
String get app_components_button_navigationButton_tech => 'Navigation button';

@override
String get app_components_button_navigationButton_description_text =>
'Un Navigation bouton (ou button de navigation) est un élément d’interface utilisateur qui permet de naviguer entre différentes pages au sein d’une interface multipage. Le Navigation button est généralement organisé dans une séquence afin d’indiquer la position actuelle de l’utilisateur et de fournir des contrôles permettant d’accéder à la page précédente, suivante ou à des pages spécifiques.';

@override
String get app_components_button_navigationButton_chevron_tech => 'Chevron';

@override
String get app_components_button_navigationButton_chevron_next_a11y =>
'Page suivante';

@override
String get app_components_button_navigationButton_chevron_previous_a11y =>
'Page précédente';

@override
String get app_components_checkbox_label => 'Checkbox';

Expand Down
3 changes: 3 additions & 0 deletions app/lib/l10n/ouds_flutter_ar.arb
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@

"@_components_button": {},
"app_components_button_description_text": "Button هو عنصر واجهة مستخدم يُستخدم لتحفيز إجراء أو حدث، ويستخدم لبدء المهام أو تأكيد إجراء معين.",
"app_components_button_navigationButton_description_text": " Navigation button هو عنصر واجهة مستخدم يتيح التنقل بين صفحات مختلفة داخل واجهة متعددة الصفحات. يتم عادةً ترتيب Navigation button ضمن تسلسل للإشارة إلى موضع المستخدم الحالي وتوفير عناصر تحكم للوصول إلى الصفحة السابقة أو التالية أو إلى صفحات محددة.",
"app_components_button_navigationButton_chevron_next_a11y":"الصفحة التالية",
"app_components_button_navigationButton_chevron_previous_a11y":"الصفحة السابقة",

"@_components_checkbox": {},
"app_components_checkbox_description_text": "Checkbox هو عنصر واجهة مستخدم يسمح باختيار خيارات متعددة من مجموعة من الخيارات غير الحصرية.",
Expand Down
5 changes: 5 additions & 0 deletions app/lib/l10n/ouds_flutter_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,11 @@
"app_components_button_label": "Button",
"app_components_button_description_text": "Button is a UI element that triggers an action or event, and is used to initiate tasks or confirming an action.",
"app_components_button_fullWidth_label": "Full width",
"app_components_button_navigationButton_tech": "Navigation button",
"app_components_button_navigationButton_description_text": "A navigation button is a UI element that enables movement between different pages within a multi-page interface. The navigation button is typically arranged in a sequence to indicate the user’s current position and provide controls for accessing previous, next, or specific pages.",
"app_components_button_navigationButton_chevron_tech":"Chevron",
"app_components_button_navigationButton_chevron_next_a11y":"Next page",
"app_components_button_navigationButton_chevron_previous_a11y":"Previous page",

"@_components_checkbox": {},
"app_components_checkbox_label": "Checkbox",
Expand Down
3 changes: 3 additions & 0 deletions app/lib/l10n/ouds_flutter_fr.arb
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@

"@_components_button": {},
"app_components_button_description_text": "Un Button (ou bouton) est un élément d'interface utilisateur qui déclenche une action ou un événement, et sert à lancer des tâches ou à confirmer une action.",
"app_components_button_navigationButton_description_text": "Un Navigation bouton (ou button de navigation) est un élément d’interface utilisateur qui permet de naviguer entre différentes pages au sein d’une interface multipage. Le Navigation button est généralement organisé dans une séquence afin d’indiquer la position actuelle de l’utilisateur et de fournir des contrôles permettant d’accéder à la page précédente, suivante ou à des pages spécifiques.",
"app_components_button_navigationButton_chevron_next_a11y":"Page suivante",
"app_components_button_navigationButton_chevron_previous_a11y":"Page précédente",

"@_components_checkbox": {},
"app_components_checkbox_description_text": "Une Checkbox (ou case à cocher) est un élément d'interface utilisateur qui permet de sélectionner plusieurs options parmi un ensemble de choix non exclusifs.",
Expand Down
89 changes: 82 additions & 7 deletions app/lib/ui/components/button/button_customization.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ class ButtonCustomizationState
late final LayoutState layoutState;
late final LoaderState loaderState;
late final FullWidthState fullWidthState;
late final ChevronState chevronState;
late final NavigationAppearanceState navigationAppearanceState;

@override
void initState() {
Expand All @@ -42,11 +44,19 @@ class ButtonCustomizationState
loaderState = LoaderState(setState, enabledState);
layoutState = LayoutState(setState);
fullWidthState = FullWidthState(setState);
chevronState = ChevronState(setState);
navigationAppearanceState = NavigationAppearanceState(
setState,
onColoredBoxState,
);
}

// Getter to determine if the 'OnColoredBox' should be disabled
bool get isOnColoredBoxDisabled {
return ButtonErrorCases.isOnColoredBoxDisabled(appearanceState.selected);
return ButtonErrorCases.isOnColoredBoxDisabled(appearanceState.selected) ||
ButtonErrorCases.isOnColoredBoxDisabled(
navigationAppearanceState.selected,
);
}

// Getter to determine if the 'Enabled' should be disabled
Expand All @@ -68,6 +78,15 @@ class ButtonCustomizationState
bool get hasFullWidth => fullWidthState.value;
set hasFullWidth(bool value) => fullWidthState.value = value;

NavigationButtonLayoutEnum get selectedChevron => chevronState.selected;
set selectedChevron(NavigationButtonLayoutEnum value) =>
chevronState.selected = value;

NavigationButtonEnumAppearance get selectedNavigationAppearance =>
navigationAppearanceState.selected;
set selectedNavigationAppearance(NavigationButtonEnumAppearance value) =>
navigationAppearanceState.selected = value;

@override
Widget build(BuildContext context) {
return _ButtonCustomization(data: this, child: widget.child);
Expand Down Expand Up @@ -166,21 +185,77 @@ class FullWidthState {
/// Error handling for specific button behavior
class ButtonErrorCases {
// OnColoredBox behavior: Disable if appearance is 'Negative'
static bool isOnColoredBoxDisabled(ButtonEnumAppearance appearance) {
static bool isOnColoredBoxDisabled(Object appearance) {
return appearance == ButtonEnumAppearance.negative ||
appearance == ButtonEnumAppearance.brand;
appearance == ButtonEnumAppearance.brand ||
appearance == NavigationButtonEnumAppearance.brand;
}

// OnColoredBox management: Disable when "Negative" appearance is selected
static bool shouldDisableOnColoredBox(
ButtonEnumAppearance selectedAppearance,
) {
static bool shouldDisableOnColoredBox(Object selectedAppearance) {
return selectedAppearance == ButtonEnumAppearance.negative ||
selectedAppearance == ButtonEnumAppearance.brand;
selectedAppearance == ButtonEnumAppearance.brand ||
selectedAppearance == NavigationButtonEnumAppearance.brand;
}

// Enabled behavior: Disable if Loader is not null
static bool isEnabledWhenLoading(bool hasEnabled) {
return hasEnabled;
}
}

/// Chevron State Management
class ChevronState {
ChevronState(this._setState);
final void Function(VoidCallback) _setState;

final List<NavigationButtonLayoutEnum> _chevron = [
NavigationButtonLayoutEnum.next,
NavigationButtonLayoutEnum.previous,
];

List<NavigationButtonLayoutEnum> get list => _chevron;

NavigationButtonLayoutEnum _selected = NavigationButtonLayoutEnum.next;
NavigationButtonLayoutEnum get selected => _selected;
set selected(NavigationButtonLayoutEnum newValue) {
_setState(() {
_selected = newValue;
});
}
}

/// Navigation Appearance State Management
class NavigationAppearanceState {
NavigationAppearanceState(this._setState, this.onColoredBoxState);

final void Function(void Function()) _setState;
final OnColoredBoxState onColoredBoxState;

List<NavigationButtonEnumAppearance> _navigationAppearance = [
NavigationButtonEnumAppearance.defaultAppearance,
NavigationButtonEnumAppearance.strong,
NavigationButtonEnumAppearance.brand,
NavigationButtonEnumAppearance.minimal,
];
NavigationButtonEnumAppearance _selectedAppearance =
NavigationButtonEnumAppearance.defaultAppearance;

List<NavigationButtonEnumAppearance> get list => _navigationAppearance;
set list(List<NavigationButtonEnumAppearance> newList) {
_setState(() {
_navigationAppearance = newList;
});
}

NavigationButtonEnumAppearance get selected => _selectedAppearance;
set selected(NavigationButtonEnumAppearance newValue) {
_setState(() {
_selectedAppearance = newValue;

if (ButtonErrorCases.shouldDisableOnColoredBox(newValue)) {
onColoredBoxState.value = false;
}
});
}
}
65 changes: 61 additions & 4 deletions app/lib/ui/components/button/button_customization_utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
// Software description: Flutter library of reusable graphical components
//

import 'package:flutter/cupertino.dart';
Comment thread
nouha06 marked this conversation as resolved.
Outdated
import 'package:ouds_core/components/button/ouds_button.dart';
import 'package:ouds_flutter_demo/l10n/app_localizations.dart';
import 'package:ouds_flutter_demo/ui/components/button/button_customization.dart';
import 'package:ouds_flutter_demo/ui/components/button/button_enum.dart';
import 'package:ouds_flutter_demo/ui/theme/theme_controller.dart';
Expand Down Expand Up @@ -63,18 +65,73 @@ class ButtonCustomizationUtils {
}

/// Determines the icon to display based on the selected layout.
static String? getIcon(ButtonCustomizationState? customizationState, ThemeController themeController) {
if (customizationState?.selectedLayout == ButtonEnumLayout.iconOnly || customizationState?.selectedLayout == ButtonEnumLayout.iconAndText) {
return AppAssets.icons.functionalSocialAndEngagementHeartEmpty(themeController);
static String? getIcon(
ButtonCustomizationState? customizationState,
ThemeController themeController,
) {
if (customizationState?.selectedLayout == ButtonEnumLayout.iconOnly ||
customizationState?.selectedLayout == ButtonEnumLayout.iconAndText) {
return AppAssets.icons.functionalSocialAndEngagementHeartEmpty(
themeController,
);
}
return null;
}

/// Determines the text to display based on the selected layout.
static String? getText(ButtonCustomizationState? customizationState) {
if (customizationState?.selectedLayout == ButtonEnumLayout.textOnly || customizationState?.selectedLayout == ButtonEnumLayout.iconAndText) {
if (customizationState?.selectedLayout == ButtonEnumLayout.textOnly ||
customizationState?.selectedLayout == ButtonEnumLayout.iconAndText) {
return customizationState?.textValue;
}
return null;
}

/// Maps the layout enum to `OudsNavigationButtonLayout`.
static OudsNavigationButtonLayout getNavigationLayout(
NavigationButtonLayoutEnum layout,
) {
switch (layout) {
case NavigationButtonLayoutEnum.next:
return OudsNavigationButtonLayout.next;
case NavigationButtonLayoutEnum.previous:
return OudsNavigationButtonLayout.previous;
}
}

/// Maps the appearance enum to `OudsNavigationButtonAppearance`.
static OudsNavigationButtonAppearance getNavigationAppearance(
Object appearance,
) {
switch (appearance) {
case NavigationButtonEnumAppearance.minimal:
return OudsNavigationButtonAppearance.minimal;
case NavigationButtonEnumAppearance.strong:
return OudsNavigationButtonAppearance.strong;
case NavigationButtonEnumAppearance.brand:
return OudsNavigationButtonAppearance.brand;
default:
return OudsNavigationButtonAppearance.defaultAppearance;
}
}

/// Determines the text to display based on the selected layout.
static String? getSemanticsLabel(
BuildContext context,
ButtonCustomizationState? customizationState,
) {
if (customizationState!.navigationTextValue.isEmpty) {
if (customizationState.selectedChevron ==
NavigationButtonLayoutEnum.next) {
return context
.l10n
.app_components_button_navigationButton_chevron_next_a11y;
} else {
return context
.l10n
.app_components_button_navigationButton_chevron_previous_a11y;
}
}
return null;
}
}
Loading
Loading