Skip to content

Commit fc7f5f3

Browse files
committed
Merge branch 'main' into sync-develop-main-1.2.0
# Conflicts: # .github/workflows/build.yml # NOTICE.txt # README.md # app/CHANGELOG.md # app/lib/l10n/gen/ouds_flutter_app_localizations.dart # app/lib/l10n/gen/ouds_flutter_app_localizations_ar.dart # app/lib/l10n/gen/ouds_flutter_app_localizations_en.dart # app/lib/l10n/ouds_flutter_ar.arb # app/lib/l10n/ouds_flutter_en.arb # app/lib/main.dart # app/lib/main_app_bar.dart # app/lib/ui/about/about_screen.dart # app/lib/ui/about/detail/about_file_screen.dart # app/lib/ui/components/badge/badge_code_generator.dart # app/lib/ui/components/badge/badge_customization_utils.dart # app/lib/ui/components/badge/badge_demo_screen.dart # app/lib/ui/components/button/button_demo_screen.dart # app/lib/ui/components/checkbox/checkbox_demo_screen.dart # app/lib/ui/components/checkbox/checkbox_item_demo_screen.dart # app/lib/ui/components/chip/chip_filter_demo_sreen.dart # app/lib/ui/components/chip/chip_suggestion_demo_screen.dart # app/lib/ui/components/components.dart # app/lib/ui/components/components_screen.dart # app/lib/ui/components/divider/divider_demo_screen.dart # app/lib/ui/components/form_input/form_fields_customization.dart # app/lib/ui/components/form_input/password_input/password_input_demo_screen.dart # app/lib/ui/components/form_input/phone_number/phone_number_input_demo_screen.dart # app/lib/ui/components/form_input/text_input/text_input_demo_screen.dart # app/lib/ui/components/link/link_demo_screen.dart # app/lib/ui/components/navigation/navigation_bar_customization_utils.dart # app/lib/ui/components/navigation/navigation_bar_demo_screen.dart # app/lib/ui/components/pin_code_input/pin_code_input_customization.dart # app/lib/ui/components/pin_code_input/pin_code_input_demo_screen.dart # app/lib/ui/components/radio_button/radio_button_demo_screen.dart # app/lib/ui/components/radio_button/radio_button_item_demo_screen.dart # app/lib/ui/components/switch/switch_demo_screen.dart # app/lib/ui/components/switch/switch_item_demo_screen.dart # app/lib/ui/components/tag/input_tag_demo_screen.dart # app/lib/ui/components/tag/tag_code_generator.dart # app/lib/ui/components/tag/tag_customization.dart # app/lib/ui/components/tag/tag_customization_utils.dart # app/lib/ui/components/tag/tag_demo_screen.dart # app/lib/ui/theme/theme_controller.dart # app/lib/ui/theme/theme_selector.dart # app/lib/ui/tokens/border/border_screen.dart # app/lib/ui/tokens/token_screen.dart # app/lib/ui/tokens/tokens.dart # app/lib/ui/utilities/app_assets.dart # app/lib/ui/utilities/component_screen_header.dart # app/lib/ui/utilities/customizable/customizable_chips.dart # app/lib/ui/utilities/customizable/customizable_textfield.dart # app/lib/ui/utilities/customizable/customizable_widget_state.dart # app/lib/ui/utilities/reference_design_version_component.dart # app/lib/ui/utilities/sheets_bottom/ouds_sheets_bottom.dart # app/pubspec.yaml # ouds_core/CHANGELOG.md # ouds_core/README.md # ouds_core/lib/components/badge/internal/ouds_badge_status_modifier.dart # ouds_core/lib/components/badge/ouds_badge.dart # ouds_core/lib/components/button/ouds_button.dart # ouds_core/lib/components/checkbox/ouds_checkbox.dart # ouds_core/lib/components/checkbox/ouds_checkbox_item.dart # ouds_core/lib/components/chip/ouds_filter_chip.dart # ouds_core/lib/components/chip/ouds_suggestion_chip.dart # ouds_core/lib/components/divider/ouds_divider.dart # ouds_core/lib/components/form_input/ouds_phone_number_input.dart # ouds_core/lib/components/form_input/ouds_text_input.dart # ouds_core/lib/components/form_input/password_input/ouds_password_input.dart # ouds_core/lib/components/link/ouds_link.dart # ouds_core/lib/components/navigation/ouds_navigation_bar.dart # ouds_core/lib/components/navigation/ouds_navigation_bar_item.dart # ouds_core/lib/components/navigation/ouds_tab_bar.dart # ouds_core/lib/components/pin_code_input/ouds_pin_code_input.dart # ouds_core/lib/components/radio_button/ouds_radio_button.dart # ouds_core/lib/components/radio_button/ouds_radio_button_item.dart # ouds_core/lib/components/switch/ouds_switch.dart # ouds_core/lib/components/switch/ouds_switch_item.dart # ouds_core/lib/components/tag/internal/ouds_tag_border_modifier.dart # ouds_core/lib/components/tag/internal/ouds_tag_status_modifier.dart # ouds_core/lib/components/tag/internal/ouds_tag_text_style_modifier.dart # ouds_core/lib/components/tag/ouds_input_tag.dart # ouds_core/lib/components/tag/ouds_tag.dart # ouds_core/lib/components/utilities/app_assets.dart # ouds_core/lib/l10n/gen/ouds_localizations.dart # ouds_core/lib/l10n/gen/ouds_localizations_ar.dart # ouds_core/lib/l10n/gen/ouds_localizations_en.dart # ouds_core/lib/l10n/ouds_flutter_ar.arb # ouds_core/lib/l10n/ouds_flutter_en.arb # ouds_core/lib/theme/ouds_theme_tweak.dart # ouds_core/pubspec.yaml # ouds_global_raw_tokens/CHANGELOG.md # ouds_global_raw_tokens/README.md # ouds_global_raw_tokens/pubspec.yaml # ouds_theme_contract/CHANGELOG.md # ouds_theme_contract/README.md # ouds_theme_contract/lib/config/component/ouds_tag_config.dart # ouds_theme_contract/lib/config/ouds_theme_config_model.dart # ouds_theme_contract/pubspec.yaml # ouds_theme_orange/CHANGELOG.md # ouds_theme_orange/README.md # ouds_theme_orange/lib/orange_font_helper.dart # ouds_theme_orange/lib/orange_font_provider.dart # ouds_theme_orange/lib/orange_font_service.dart # ouds_theme_orange/lib/orange_theme.dart # ouds_theme_orange/pubspec.yaml # ouds_theme_orange_compact/CHANGELOG.md # ouds_theme_orange_compact/README.md # ouds_theme_orange_compact/lib/orange_compact_theme.dart # ouds_theme_orange_compact/pubspec.yaml # ouds_theme_sosh/CHANGELOG.md # ouds_theme_sosh/README.md # ouds_theme_sosh/pubspec.yaml # ouds_theme_wireframe/CHANGELOG.md # ouds_theme_wireframe/README.md # ouds_theme_wireframe/pubspec.yaml
2 parents f7c830c + 1a12f9a commit fc7f5f3

66 files changed

Lines changed: 996 additions & 1 deletion

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 3 additions & 0 deletions
Loading
Lines changed: 3 additions & 0 deletions
Loading
Lines changed: 3 additions & 0 deletions
Loading
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
/*
2+
* // Software Name: OUDS Flutter
3+
* // SPDX-FileCopyrightText: Copyright (c) Orange SA
4+
* // SPDX-License-Identifier: MIT
5+
* //
6+
* // This software is distributed under the MIT license,
7+
* // the text of which is available at https://opensource.org/license/MIT/
8+
* // or see the "LICENSE" file for more details.
9+
* //
10+
* // Software description: Flutter library of reusable graphical components
11+
* //
12+
*/
13+
import 'package:flutter/material.dart';
14+
import 'package:ouds_theme_contract/ouds_theme.dart';
15+
import 'package:ouds_theme_contract/ouds_theme_contract.dart';
16+
17+
/// A widget that applies a specific theme to its child using [OudsTheme].
18+
///
19+
/// This widget allows setting a theme mode (`ThemeMode`) and a theme contract
20+
/// (`OudsThemeContract`). It wraps its child inside a background colored by a [ColoredBox].
21+
class ThemeBox extends StatelessWidget {
22+
/// The widget to display inside the [ThemeBox].
23+
final Widget child;
24+
25+
/// The theme mode to apply (light, dark, or system).
26+
final ThemeMode themeMode;
27+
28+
/// The theme contract defining the theme's design tokens and styles.
29+
final OudsThemeContract themeContract;
30+
31+
/// Constructor for [ThemeBox].
32+
///
33+
/// Requires [child], [themeMode], and [themeContract].
34+
const ThemeBox({
35+
required this.child,
36+
required this.themeMode,
37+
required this.themeContract,
38+
super.key,
39+
});
40+
41+
@override
42+
Widget build(BuildContext context) {
43+
return OudsTheme(
44+
themeContract: themeContract,
45+
themeMode: themeMode,
46+
onColoredSurface: false,
47+
child: Builder(
48+
builder: (context) {
49+
return ColoredBox(
50+
color: ColoredBoxColor.backgroundPrimary,
51+
child: Column(
52+
children: [
53+
child,
54+
],
55+
),
56+
);
57+
},
58+
),
59+
);
60+
}
61+
}
62+
63+
/// A demo colored box widget used to showcase `DARK` and `LIGHT` modes.
64+
/// It displays a background with centered content and a minimum height.
65+
class ColoredBox extends StatelessWidget {
66+
/// The widget to display at the center of the box.
67+
final Widget child;
68+
69+
/// The background color of the box, optional.
70+
final ColoredBoxColor? color;
71+
72+
/// Constructor for [ColoredBox].
73+
///
74+
/// Requires [child], [color] is optional.
75+
const ColoredBox({
76+
required this.child,
77+
this.color,
78+
super.key,
79+
});
80+
81+
@override
82+
Widget build(BuildContext context) {
83+
return Container(
84+
constraints: BoxConstraints(
85+
minHeight: 80,
86+
),
87+
width: double.infinity,
88+
color: color?.getValue(context),
89+
child: Padding(
90+
padding: EdgeInsetsDirectional.symmetric(
91+
vertical: OudsTheme.of(context).spaceScheme(context).fixedMedium,
92+
horizontal: OudsTheme.of(context).spaceScheme(context).fixedNone,
93+
),
94+
child: Container(
95+
alignment: AlignmentDirectional.centerStart,
96+
child: child,
97+
),
98+
),
99+
);
100+
}
101+
}
102+
103+
/// Enumeration representing the possible background colors of a [ColoredBox].
104+
enum ColoredBoxColor {
105+
/// Primary background color.
106+
backgroundPrimary;
107+
108+
/// Retrieves the color value associated with this enum in the current context.
109+
Color getValue(BuildContext context) {
110+
final theme = OudsTheme.of(context);
111+
112+
switch (this) {
113+
case ColoredBoxColor.backgroundPrimary:
114+
return theme.colorScheme(context).bgPrimary;
115+
}
116+
}
117+
}
Lines changed: 3 additions & 0 deletions
Loading
Lines changed: 3 additions & 0 deletions
Loading
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
/*
2+
* // Software Name: OUDS Flutter
3+
* // SPDX-FileCopyrightText: Copyright (c) Orange SA
4+
* // SPDX-License-Identifier: MIT
5+
* //
6+
* // This software is distributed under the MIT license,
7+
* // the text of which is available at https://opensource.org/license/MIT/
8+
* // or see the "LICENSE" file for more details.
9+
* //
10+
* // Software description: Flutter library of reusable graphical components
11+
* //
12+
*/
13+
/// @nodoc
14+
library;
15+
16+
import 'package:flutter/material.dart';
17+
import 'package:ouds_theme_contract/ouds_theme.dart';
18+
19+
/// Controls how the focus ring stroke is positioned relative to the widget bounds.
20+
enum FocusAlignment {
21+
/// The stroke is fully inside the widget bounds.
22+
inside,
23+
24+
/// The stroke is centered on the widget bounds (half inside, half outside).
25+
center,
26+
27+
/// The stroke is fully outside the widget bounds.
28+
outside,
29+
}
30+
31+
/// A [CustomPainter] that draws a rounded-rectangle focus ring.
32+
///
33+
/// The ring is drawn using a stroke of [strokeWidth] and rounded corners
34+
/// defined by [borderRadius]. The ring position depends on [alignment]:
35+
/// - [FocusAlignment.inside] deflates the rect by half the stroke width.
36+
/// - [FocusAlignment.center] draws on the original rect.
37+
/// - [FocusAlignment.outside] inflates the rect by half the stroke width.
38+
class FocusContainerPainter extends CustomPainter {
39+
final Color color;
40+
final double strokeWidth;
41+
final double borderRadius;
42+
final FocusAlignment alignment;
43+
44+
FocusContainerPainter({
45+
required this.color,
46+
required this.strokeWidth,
47+
required this.borderRadius,
48+
this.alignment = FocusAlignment.center,
49+
});
50+
51+
@override
52+
void paint(Canvas canvas, Size size) {
53+
final paint = Paint()
54+
..style = PaintingStyle.stroke
55+
..strokeWidth = strokeWidth
56+
..color = color
57+
..isAntiAlias = true;
58+
59+
Rect baseRect = Offset.zero & size;
60+
RRect rrect = RRect.fromRectAndRadius(baseRect, Radius.circular(borderRadius));
61+
62+
final half = strokeWidth / 2;
63+
if (alignment == FocusAlignment.outside) {
64+
rrect = rrect.inflate(half);
65+
} else if (alignment == FocusAlignment.inside) {
66+
rrect = rrect.deflate(half);
67+
}
68+
canvas.drawRRect(rrect, paint);
69+
}
70+
71+
@override
72+
bool shouldRepaint(covariant FocusContainerPainter oldDelegate) {
73+
return oldDelegate.color != color || oldDelegate.strokeWidth != strokeWidth || oldDelegate.borderRadius != borderRadius || oldDelegate.alignment != alignment;
74+
}
75+
}
76+
77+
/// Wraps [child] with an optional focus ring and an optional inset border.
78+
///
79+
/// When [isFocused] is true, a focus ring is painted using [CustomPaint]
80+
/// inside a [Stack]. The ring uses theme tokens (focus border color/width)
81+
/// and can be visually aligned via [alignment].
82+
///
83+
/// This widget is designed to be used by interactive components to make
84+
/// keyboard focus visible (for example when navigating with Tab).
85+
class FocusContainer extends StatelessWidget {
86+
/// The content widget.
87+
final Widget child;
88+
89+
/// Optional ring color (defaults to transparent).
90+
///
91+
/// Note: the current implementation uses theme colors for the painted ring.
92+
final Color color;
93+
94+
/// The stroke width used for the focus ring.
95+
///
96+
/// Note: the current implementation uses theme tokens for the painted ring.
97+
final double strokeWidth;
98+
99+
/// Corner radius used for the focus ring and the inset border.
100+
final double borderRadius;
101+
102+
/// Focus ring alignment relative to the widget bounds.
103+
final FocusAlignment alignment;
104+
105+
/// Whether the focus ring should be visible.
106+
final bool isFocused;
107+
108+
const FocusContainer({
109+
super.key,
110+
required this.child,
111+
this.color = Colors.transparent,
112+
this.strokeWidth = 5,
113+
this.borderRadius = 8,
114+
this.alignment = FocusAlignment.center,
115+
this.isFocused = false,
116+
});
117+
118+
@override
119+
Widget build(BuildContext context) {
120+
final borderTokens = OudsTheme.of(context).borderTokens;
121+
122+
if (!isFocused) {
123+
// Pas de focus - retourner le child directement sans wrapper
124+
return child;
125+
}
126+
127+
// Avec focus - dessiner les borders par-dessus avec CustomPaint
128+
// Utiliser borderTokens au lieu des paramètres pour s'adapter au thème
129+
return CustomPaint(
130+
painter: FocusContainerPainter(
131+
color: color,
132+
strokeWidth: borderTokens.widthFocus,
133+
borderRadius: borderRadius,
134+
alignment: FocusAlignment.center,
135+
),
136+
foregroundPainter: FocusContainerPainter(
137+
color: OudsTheme.of(context).colorScheme(context).borderFocusInset,
138+
strokeWidth: borderTokens.widthFocusInset,
139+
borderRadius: borderRadius,
140+
alignment: FocusAlignment.inside,
141+
),
142+
child: child,
143+
);
144+
}
145+
}

ouds_theme_contract/lib/ouds_theme.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,4 +131,4 @@ class OudsTheme extends InheritedModel<OudsThemeAspect> {
131131
}
132132
return false;
133133
}
134-
}
134+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//
2+
// Software Name: OUDS Flutter
3+
// SPDX-FileCopyrightText: Copyright (c) Orange SA
4+
// SPDX-License-Identifier: MIT
5+
//
6+
// This software is distributed under the MIT license,
7+
// the text of which is available at https://opensource.org/license/MIT/
8+
// or see the "LICENSE" file for more details.
9+
//
10+
// Software description: Flutter library of reusable graphical components
11+
//
12+
13+
// Orange brand tokens version 1.5.0
14+
// Generated by Tokenator
15+
16+
import 'package:flutter/material.dart';
17+
18+
abstract class OudsTagInputTokens {
19+
late double borderWidthDefault;
20+
late double borderWidthDefaultInteraction;
21+
late Color colorBgEnabled;
22+
late Color colorBgFocus;
23+
late Color colorBgHover;
24+
late Color colorBgPressed;
25+
late Color colorBorderEnabled;
26+
late Color colorBorderFocus;
27+
late Color colorBorderHover;
28+
late Color colorBorderPressed;
29+
late Color colorContentEnabled;
30+
late Color colorContentFocus;
31+
late Color colorContentHover;
32+
late Color colorContentPressed;
33+
}
Lines changed: 3 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)