Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased](https://github.com/Orange-OpenSource/ouds-flutter/compare/1.3.1...develop)
### Added
### Changed
- [DemoApp][Library] update `alert message`, `switch`, `radio`, `checkbox`, `text input`, `pin code input`, `phone number input`, components to use rich text ([#782](https://github.com/Orange-OpenSource/ouds-flutter/issues/782))
- [Library] update `Phone number input` component to v1.3 ([#690](https://github.com/Orange-OpenSource/ouds-flutter/issues/690))
- [Library] update `tag` component to v1.5 ([#694](https://github.com/Orange-OpenSource/ouds-flutter/issues/694))
- [Library] update `input tag` component to v1.2 ([#695](https://github.com/Orange-OpenSource/ouds-flutter/issues/695))
Expand Down
12 changes: 6 additions & 6 deletions app/ios/Podfile.lock
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
PODS:
- app_settings (5.1.1):
- app_settings (6.1.2):
- Flutter
- Flutter (1.0.0)
- package_info_plus (0.4.5):
Expand Down Expand Up @@ -36,12 +36,12 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/webview_flutter_wkwebview/darwin"

SPEC CHECKSUMS:
app_settings: 58017cd26b604ae98c3e65acbdd8ba173703cc82
app_settings: 0341ec6daa4f0c50f5a421bf0ad7c36084db6e90
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4
path_provider_foundation: 0b743cbb62d8e47eab856f09262bb8c1ddcfe6ba
url_launcher_ios: bb13df5870e8c4234ca12609d04010a21be43dfa
webview_flutter_wkwebview: 29eb20d43355b48fe7d07113835b9128f84e3af4
package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499
path_provider_foundation: bb55f6dbba17d0dccd6737fe6f7f34fbd0376880
url_launcher_ios: 7a95fa5b60cc718a708b8f2966718e93db0cef1b
webview_flutter_wkwebview: 8ebf4fded22593026f7dbff1fbff31ea98573c8d

PODFILE CHECKSUM: 4f1c12611da7338d21589c0b2ecd6bd20b109694

Expand Down
4 changes: 4 additions & 0 deletions app/lib/ui/components/alert/alert_message_demo_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import 'package:ouds_flutter_demo/ui/utilities/sheets_bottom/ouds_sheets_bottom.
import 'package:ouds_theme_contract/ouds_component_version.dart';
import 'package:ouds_theme_contract/ouds_theme.dart';
import 'package:provider/provider.dart';
import 'package:url_launcher/url_launcher.dart';

/// Screen for the [OudsAlertMessage] component demo.
class AlertMessageDemoScreen extends StatefulWidget {
Expand Down Expand Up @@ -157,6 +158,9 @@ class _AlertMessageDemoState extends State<_AlertMessageDemo> {
),
),
onClose: customizationState.hasCloseButton ? () {} : null,
onDescriptionLinkTapped: (link) async {
await launchUrl(Uri.parse(link));
},
),
);
}
Expand Down
1 change: 1 addition & 0 deletions ouds_core/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased](https://github.com/Orange-OpenSource/ouds-flutter/compare/1.3.1...develop)
### Added
### Changed
- [Library] update `alert message`, `switch`, `radio`, `checkbox`, `text input`, `pin code input`, `phone number input`, components to use rich text ([#782](https://github.com/Orange-OpenSource/ouds-flutter/issues/782))
- [Library] update `Phone number input` component to v1.3 ([#690](https://github.com/Orange-OpenSource/ouds-flutter/issues/690))
- [Library] update `tag` component to v1.5 ([#694](https://github.com/Orange-OpenSource/ouds-flutter/issues/694))
- [Library] update `input tag` component to v1.2 ([#695](https://github.com/Orange-OpenSource/ouds-flutter/issues/695))
Expand Down
84 changes: 66 additions & 18 deletions ouds_core/lib/components/alert/ouds_alert_message.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import 'package:ouds_core/components/common/OudsBorder.dart';
import 'package:ouds_core/components/common/ouds_icon_status.dart';
import 'package:ouds_core/components/link/ouds_link.dart';
import 'package:ouds_core/components/utilities/app_assets.dart';
import 'package:ouds_core/components/utilities/markdown_span_builder.dart';
import 'package:ouds_core/l10n/gen/ouds_localizations.dart';
import 'package:ouds_theme_contract/ouds_theme.dart';

Expand Down Expand Up @@ -84,24 +85,43 @@ class OudsAlertMessageActionLayout {
/// - [label]: Label displayed in the alert message. Main message that should be short, clear, and readable at a glance.
/// - [status]: The status of the alert message. Its background color and its icon color are based on this status.
/// There are two types of statuses:
/// - Non-functional statuses [Neutral] or [Accent] used for informational or decorative alert messages. They
/// - Non-functional statuses [Neutral] or [Accent] used for informational or decorative alert messages. They
/// provide context or highlight content without implying a specific state, system event, or user action. These alerts are not tied to UX patterns such as
/// success, error, or warning, and may use contextual or brand-related icons to enhance recognition or storytelling.
/// - Functional statuses communicate specific system statuses, results, or user feedback: [Positive], [Warning],
/// - Functional statuses communicate specific system statuses, results, or user feedback: [Positive], [Warning],
/// [Negative], [Info].
/// Each variant conveys a clear semantic meaning and must always be paired with its dedicated functional icon to ensure clarity and accessibility.
/// Use functional alerts to inform user about state changes, confirmations, or issues that are directly connected to system logic or user actions. These
/// messages carry functional meaning and help guide user response or acknowledgment.
/// - [description]: Optional supplementary text in an alert message. Use only when additional detail or guidance is needed beyond the label. It should remain
/// short, clear and scannable, helping the user to understand what happened and what he can do next.
///
/// - [description]: Optional supplementary text displayed below the alert label. Use it only when additional context, guidance or next steps are needed.
/// The content should remain concise, clear and easy to scan.
/// Supports lightweight markdown rich text formatting:
/// - Strong text using `**bold**`,
/// - Underline bold text using `__**underline bold**__`,
/// - Hyperlinks using `[link](https://example.com)`
///
/// - [onDescriptionLinkTapped]: Callback invoked when a link in the description is tapped. The URL of the link is passed as an argument.
/// The caller is responsible for handling link opening behavior
/// (for example with `url_launcher` or an in-app WebView).
///
/// Example:
/// ```dart
/// onDescriptionLinkTapped: (link) async {
/// await launchUrl(Uri.parse(link));
/// },
/// ```
///
/// - [onClose]: Callback invoked when the close button is clicked. If `null`, the close button is not displayed and the alert message remains visible until
/// the context changes (e.g., the issue is resolved, the screen is refreshed). Otherwise, the alert message is dismissable and includes a close button,
/// allowing the user to dismiss it when he has acknowledged the message.
/// Some alerts must remain visible to ensure user is aware of important information; others can be closed to reduce visual clutter.
/// - [actionLayout]: An optional action link to be displayed in the alert message. It can be used to trigger an action.
/// - [bulletList]: An optional list of bullet points to be displayed in the alert message following the label or the optional [description].
/// Add this list when you need to highlight multiple points, such as service features, plan details, or next steps. Each bullet should be short and written
/// as a clear phrase or fragment — avoid long sentences or complex structures.
/// - [bulletList]: An optional list of bullet points displayed below the label or the optional [description].
/// Use this list to highlight multiple items such as service features, plan details or next steps.
/// Each bullet should remain short, clear and easy to scan. Avoid long sentences or complex structures.
/// Supports lightweight inline markdown formatting for text emphasis :
/// - Strong text `**bold**`.
///
/// ## Usage Example:
///
Expand All @@ -121,6 +141,7 @@ class OudsAlertMessage extends StatefulWidget {
required this.status,
this.description,
this.onClose,
this.onDescriptionLinkTapped,
this.actionLayout,
this.bulletList,
});
Expand All @@ -137,6 +158,19 @@ class OudsAlertMessage extends StatefulWidget {
/// A callback invoked when the close button is clicked. If `null`, the close button is not shown.
final VoidCallback? onClose;

/// A callback invoked when a link in the description is tapped.
///
/// The caller is responsible for handling link opening behavior
/// (for example with `url_launcher` or an in-app WebView).
///
/// Example:
/// ```dart
/// onDescriptionLinkTapped: (link) async {
/// await launchUrl(Uri.parse(link));
/// },
/// ```
final ValueChanged<String>? onDescriptionLinkTapped;

/// An optional clickable link to trigger an action.
final OudsAlertMessageActionLayout? actionLayout;

Expand Down Expand Up @@ -182,16 +216,7 @@ class _OudsAlertMessageState extends State<OudsAlertMessage> {
// Optional description text.
if (widget.description != null && widget.description!.isNotEmpty) ...[
SizedBox(height: alertTokens.spaceRowGap),
Text(
widget.description!,
style: theme.typographyTokens
.typeLabelDefaultMedium(context)
.copyWith(
color: alertMessageStatusModifier.getStatusTextColor(
widget.status,
),
),
),
_buildDescription(context),
],
// Optional bullet list. A gap is added only if the list is not empty.
if (widget.bulletList != null &&
Expand Down Expand Up @@ -376,6 +401,27 @@ class _OudsAlertMessageState extends State<OudsAlertMessage> {
);
}

/// Builds the description text with support for bold and hyperlinks.
Widget _buildDescription(BuildContext context) {
final theme = OudsTheme.of(context);
final alertMessageStatusModifier = OudsAlertStatusModifier(context);

final textStyle = theme.typographyTokens
.typeLabelDefaultMedium(context)
.copyWith(
color: alertMessageStatusModifier.getStatusTextColor(widget.status),
);

return Text.rich(
MarkdownSpanBuilder.buildRichText(
context,
widget.description ?? '',
baseStyle: textStyle,
onLinkTap: widget.onDescriptionLinkTapped,
),
);
}

/// Builds a single bullet list item for the alert message.
///
/// This widget creates a row containing a bullet icon and a text label,
Expand Down Expand Up @@ -436,7 +482,9 @@ class _OudsAlertMessageState extends State<OudsAlertMessage> {
Flexible(
child: ConstrainedBox(
constraints: BoxConstraints(maxWidth: maxTextWidth),
child: Text(label, style: textStyle),
child: Text.rich(
MarkdownSpanBuilder.buildBoldOnly(label, baseStyle: textStyle),
),
),
),
],
Expand Down
3 changes: 3 additions & 0 deletions ouds_core/lib/components/checkbox/ouds_checkbox_item.dart
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ import 'package:ouds_core/components/control/ouds_control_item.dart';
/// - [constrainedMaxWidth]: When `true`, the item width is constrained to a maximum value defined by the design system.
/// When `false`, no specific width constraint is applied, allowing the component to size itself or follow external modifiers.
/// Defaults to `false`.
/// - [errorText]: Text shown below the checkbox item indicating an error state. Supports only strong text formatting using `**bold**`.
/// Rich text is supported only for error messages.
///
///
/// ### You can use [OudsCheckboxItem] component in your project, customizing parameters as needed :
///
Expand Down
22 changes: 12 additions & 10 deletions ouds_core/lib/components/control/ouds_control_item.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@ import 'package:ouds_core/components/control/internal/modifier/ouds_control_back
import 'package:ouds_core/components/control/internal/modifier/ouds_control_border_modifier.dart';
import 'package:ouds_core/components/control/internal/modifier/ouds_control_indicator.dart';
import 'package:ouds_core/components/control/internal/modifier/ouds_control_text_modifier.dart';
import 'package:ouds_core/components/control/internal/modifier/ouds_control_tick_modifier.dart';
import 'package:ouds_core/components/control/internal/ouds_control_state.dart';
import 'package:ouds_core/components/divider/ouds_divider.dart';
import 'package:ouds_core/components/utilities/app_assets.dart';
import 'package:ouds_core/components/utilities/markdown_span_builder.dart';
import 'package:ouds_theme_contract/ouds_theme.dart';

import 'internal/modifier/ouds_control_tick_modifier.dart';

enum OudsControlItemType { switchButton, checkbox, radio }

/// Refactor of controls for [Checkbox], [Switch], and [RadioButton].
Expand Down Expand Up @@ -266,15 +266,17 @@ class OudsControlItemState extends State<OudsControlItem> {
top: controlItemTokens.spacePaddingBlockTopHelperText,
end: controlItemTokens.spacePaddingInline,
),
child: Text(
widget.errorText ?? '',
style: OudsTheme.of(context).typographyTokens
.typeLabelDefaultMedium(context)
.copyWith(
color: controlItemTextModifier.getErrorMessageTextColor(
controlItemState,
child: Text.rich(
MarkdownSpanBuilder.buildBoldOnly(
widget.errorText ?? '',
baseStyle: OudsTheme.of(context).typographyTokens
.typeLabelDefaultMedium(context)
.copyWith(
color: controlItemTextModifier.getErrorMessageTextColor(
controlItemState,
),
),
),
),
),
),
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
* // Software description: Flutter library of reusable graphical components
* //
*/
/// @nodoc
/// {@category Text input}
/// {@category Phone number input}
library;

import 'dart:ui';
Expand Down Expand Up @@ -43,7 +44,7 @@ class OudsInputDecoration extends OudsFormInputDecoration {
});
}

/// Configuration for decorating the [OudsformInput] widget.
/// Configuration for decorating the [OudsTextField] and [OudsPhoneNumberInput] widgets.
///
/// Provides properties to customize labels, hints, icons, helper and error texts,
/// loading states, and styling.
Expand All @@ -52,8 +53,9 @@ class OudsInputDecoration extends OudsFormInputDecoration {
///
/// - [labelText]: The main label text displayed above or inside the input field.
///
/// - [helperText]: Additional information displayed below the input,
/// often used to guide or assist the user.
/// - [helperText]: Additional information displayed below the input, often used to guide or assist the user.
/// Supports strong text formatting using `**bold**`.
/// Hyperlinks are not supported in helper text. Use the dedicated helper link component instead.
///
/// - [hintText]: A short placeholder or hint shown inside the input when empty,
/// describing the expected input.
Expand All @@ -72,6 +74,7 @@ class OudsInputDecoration extends OudsFormInputDecoration {
/// - [suffix]: A string displayed after the user's input, often used for units or context.
///
/// - [errorText]: Text shown below the input indicating an error state or invalid input.
/// Supports strong text formatting using `**bold**`.
///
/// - [loader]: When true, displays a loading indicator inside the input.
///
Expand Down
17 changes: 10 additions & 7 deletions ouds_core/lib/components/form_input/ouds_phone_number_input.dart
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import 'package:ouds_core/components/form_input/internal/modifier/ouds_form_inpu
import 'package:ouds_core/components/form_input/internal/ouds_form_input_control_state.dart';
import 'package:ouds_core/components/form_input/internal/ouds_form_input_decoration.dart';
import 'package:ouds_core/components/utilities/app_assets.dart';
import 'package:ouds_core/components/utilities/markdown_span_builder.dart';
import 'package:ouds_core/l10n/gen/ouds_localizations.dart';
import 'package:ouds_theme_contract/ouds_theme.dart';
import 'package:ouds_theme_contract/ouds_theme_contract.dart';
Expand Down Expand Up @@ -750,13 +751,15 @@ class _OudsPhoneNumberInputState extends State<OudsPhoneNumberInput> {
left: textInput.spacePaddingInlineDefault,
right: textInput.spacePaddingInlineDefault,
),
child: Text(
text,
style: theme.typographyTokens
.typeLabelDefaultMedium(context)
.copyWith(
color: inputTextTextModifier.getHelperTextColor(state, isError),
),
child: Text.rich(
MarkdownSpanBuilder.buildBoldOnly(
text,
baseStyle: theme.typographyTokens
.typeLabelDefaultMedium(context)
.copyWith(
color: inputTextTextModifier.getHelperTextColor(state, isError),
),
),
),
);
}
Expand Down
17 changes: 10 additions & 7 deletions ouds_core/lib/components/form_input/ouds_text_input.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import 'package:ouds_core/components/form_input/internal/ouds_form_input_decorat
import 'package:ouds_core/components/link/ouds_link.dart';
import 'package:ouds_core/components/utilities/app_assets.dart';
import 'package:ouds_core/components/utilities/input_utils.dart';
import 'package:ouds_core/components/utilities/markdown_span_builder.dart';
import 'package:ouds_core/l10n/gen/ouds_localizations.dart';
import 'package:ouds_theme_contract/ouds_theme.dart';
import 'package:ouds_theme_contract/ouds_theme_contract.dart';
Expand Down Expand Up @@ -660,13 +661,15 @@ class _OudsTextInputState extends State<OudsTextField> {
left: textInput.spacePaddingInlineDefault,
right: textInput.spacePaddingInlineDefault,
),
child: Text(
text,
style: theme.typographyTokens
.typeLabelDefaultMedium(context)
.copyWith(
color: inputTextTextModifier.getHelperTextColor(state, isError),
),
child: Text.rich(
MarkdownSpanBuilder.buildBoldOnly(
text,
baseStyle: theme.typographyTokens
.typeLabelDefaultMedium(context)
.copyWith(
color: inputTextTextModifier.getHelperTextColor(state, isError),
),
),
),
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import 'package:ouds_core/components/form_input/internal/ouds_form_input_control
import 'package:ouds_core/components/form_input/password_input/ouds_password_input_decoration.dart';
import 'package:ouds_core/components/utilities/app_assets.dart';
import 'package:ouds_core/components/utilities/input_utils.dart';
import 'package:ouds_core/components/utilities/markdown_span_builder.dart';
import 'package:ouds_core/l10n/gen/ouds_localizations.dart';
import 'package:ouds_theme_contract/ouds_theme.dart';
import 'package:ouds_theme_contract/ouds_theme_contract.dart';
Expand Down Expand Up @@ -524,13 +525,15 @@ class _OudsPasswordInputState extends State<OudsPasswordInput> {
left: textInput.spacePaddingInlineDefault,
right: textInput.spacePaddingInlineDefault,
),
child: Text(
text,
style: theme.typographyTokens
.typeLabelDefaultMedium(context)
.copyWith(
color: inputTextTextModifier.getHelperTextColor(state, isError),
),
child: Text.rich(
MarkdownSpanBuilder.buildBoldOnly(
text,
baseStyle: theme.typographyTokens
.typeLabelDefaultMedium(context)
.copyWith(
color: inputTextTextModifier.getHelperTextColor(state, isError),
),
),
),
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@
* //
*/

/// @nodoc
/// {@category Password input}
library;

/// Configuration for decorating the [OudsTextInput] widget.
/// Configuration for decorating the [OudsPasswordInput] widget.
///
/// Provides properties to customize labels, hints, icons, helper and error texts,
/// loading states, and styling.
Expand Down
Loading
Loading