Skip to content

Commit 0919fb8

Browse files
authored
Improve handling of certain icons in RTL (#130979)
Fixes flutter/flutter#130978 ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/wiki/Tree-hygiene#overview [Tree Hygiene]: https://github.com/flutter/flutter/wiki/Tree-hygiene [test-exempt]: https://github.com/flutter/flutter/wiki/Tree-hygiene#tests [Flutter Style Guide]: https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo [Features we expect every widget to implement]: https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/wiki/Tree-hygiene#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/wiki/Chat
1 parent 9cfbf6b commit 0919fb8

3 files changed

Lines changed: 84 additions & 25 deletions

File tree

dev/tools/test/update_icons_test.dart

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,61 @@ void main() {
6161
'Icon(Icons.onetwothree_rounded),',
6262
);
6363
});
64+
65+
test('certain icons should be mirrored in RTL', () {
66+
// Exact match
67+
expect(
68+
Icon(const MapEntry<String, String>('help', '')).isMirroredInRTL,
69+
true,
70+
);
71+
// Variant
72+
expect(
73+
Icon(const MapEntry<String, String>('help_rounded', '')).isMirroredInRTL,
74+
true,
75+
);
76+
// Common suffixes
77+
expect(
78+
Icon(const MapEntry<String, String>('help_alt', '')).isMirroredInRTL,
79+
true,
80+
);
81+
expect(
82+
Icon(const MapEntry<String, String>('help_new', '')).isMirroredInRTL,
83+
true,
84+
);
85+
expect(
86+
Icon(const MapEntry<String, String>('help_off', '')).isMirroredInRTL,
87+
true,
88+
);
89+
expect(
90+
Icon(const MapEntry<String, String>('help_on', '')).isMirroredInRTL,
91+
true,
92+
);
93+
// Common suffixes + variant
94+
expect(
95+
Icon(const MapEntry<String, String>('help_alt_rounded', '')).isMirroredInRTL,
96+
true,
97+
);
98+
expect(
99+
Icon(const MapEntry<String, String>('help_new_rounded', '')).isMirroredInRTL,
100+
true,
101+
);
102+
expect(
103+
Icon(const MapEntry<String, String>('help_off_rounded', '')).isMirroredInRTL,
104+
true,
105+
);
106+
expect(
107+
Icon(const MapEntry<String, String>('help_on_rounded', '')).isMirroredInRTL,
108+
true,
109+
);
110+
// No match
111+
expect(
112+
Icon(const MapEntry<String, String>('help_center_rounded', '')).isMirroredInRTL,
113+
false,
114+
);
115+
// No match
116+
expect(
117+
Icon(const MapEntry<String, String>('arrow', '')).isMirroredInRTL,
118+
false,
119+
);
120+
});
64121
}

dev/tools/update_icons.dart

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ const Set<String> _iconsMirroredWhenRTL = <String>{
150150
'navigate_next',
151151
'next_week',
152152
'note',
153-
'open_in_new',
153+
'open_in',
154154
'playlist_add',
155155
'queue_music',
156156
'redo',
@@ -513,12 +513,14 @@ class Icon {
513513

514514
String get usage => 'Icon($className.$flutterId),';
515515

516-
String get mirroredInRTL => _iconsMirroredWhenRTL.contains(shortId)
517-
? ', matchTextDirection: true'
518-
: '';
516+
bool get isMirroredInRTL {
517+
// Remove common suffixes (e.g. "_new" or "_alt") from the shortId.
518+
final String normalizedShortId = shortId.replaceAll(RegExp(r'_(new|alt|off|on)$'), '');
519+
return _iconsMirroredWhenRTL.any((String shortIdMirroredWhenRTL) => normalizedShortId == shortIdMirroredWhenRTL);
520+
}
519521

520522
String get declaration =>
521-
"static const IconData $flutterId = IconData(0x$hexCodepoint, fontFamily: '$fontFamily'$mirroredInRTL);";
523+
"static const IconData $flutterId = IconData(0x$hexCodepoint, fontFamily: '$fontFamily'${isMirroredInRTL ? ', matchTextDirection: true' : ''});";
522524

523525
String get fullDeclaration => '''
524526

packages/flutter/lib/src/material/icons.dart

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2154,16 +2154,16 @@ abstract final class Icons {
21542154
static const IconData arrow_back_ios_outlined = IconData(0xee84, fontFamily: 'MaterialIcons', matchTextDirection: true);
21552155

21562156
/// <i class="material-icons md-36">arrow_back_ios_new</i> &#x2014; material icon named "arrow back ios new".
2157-
static const IconData arrow_back_ios_new = IconData(0xe094, fontFamily: 'MaterialIcons');
2157+
static const IconData arrow_back_ios_new = IconData(0xe094, fontFamily: 'MaterialIcons', matchTextDirection: true);
21582158

21592159
/// <i class="material-icons-sharp md-36">arrow_back_ios_new</i> &#x2014; material icon named "arrow back ios new" (sharp).
2160-
static const IconData arrow_back_ios_new_sharp = IconData(0xe791, fontFamily: 'MaterialIcons');
2160+
static const IconData arrow_back_ios_new_sharp = IconData(0xe791, fontFamily: 'MaterialIcons', matchTextDirection: true);
21612161

21622162
/// <i class="material-icons-round md-36">arrow_back_ios_new</i> &#x2014; material icon named "arrow back ios new" (round).
2163-
static const IconData arrow_back_ios_new_rounded = IconData(0xf570, fontFamily: 'MaterialIcons');
2163+
static const IconData arrow_back_ios_new_rounded = IconData(0xf570, fontFamily: 'MaterialIcons', matchTextDirection: true);
21642164

21652165
/// <i class="material-icons-outlined md-36">arrow_back_ios_new</i> &#x2014; material icon named "arrow back ios new" (outlined).
2166-
static const IconData arrow_back_ios_new_outlined = IconData(0xee83, fontFamily: 'MaterialIcons');
2166+
static const IconData arrow_back_ios_new_outlined = IconData(0xee83, fontFamily: 'MaterialIcons', matchTextDirection: true);
21672167

21682168
/// <i class="material-icons md-36">arrow_circle_down</i> &#x2014; material icon named "arrow circle down".
21692169
static const IconData arrow_circle_down = IconData(0xe095, fontFamily: 'MaterialIcons');
@@ -2322,16 +2322,16 @@ abstract final class Icons {
23222322
static const IconData arrow_right_outlined = IconData(0xee90, fontFamily: 'MaterialIcons', matchTextDirection: true);
23232323

23242324
/// <i class="material-icons md-36">arrow_right_alt</i> &#x2014; material icon named "arrow right alt".
2325-
static const IconData arrow_right_alt = IconData(0xe09f, fontFamily: 'MaterialIcons');
2325+
static const IconData arrow_right_alt = IconData(0xe09f, fontFamily: 'MaterialIcons', matchTextDirection: true);
23262326

23272327
/// <i class="material-icons-sharp md-36">arrow_right_alt</i> &#x2014; material icon named "arrow right alt" (sharp).
2328-
static const IconData arrow_right_alt_sharp = IconData(0xe79d, fontFamily: 'MaterialIcons');
2328+
static const IconData arrow_right_alt_sharp = IconData(0xe79d, fontFamily: 'MaterialIcons', matchTextDirection: true);
23292329

23302330
/// <i class="material-icons-round md-36">arrow_right_alt</i> &#x2014; material icon named "arrow right alt" (round).
2331-
static const IconData arrow_right_alt_rounded = IconData(0xf57c, fontFamily: 'MaterialIcons');
2331+
static const IconData arrow_right_alt_rounded = IconData(0xf57c, fontFamily: 'MaterialIcons', matchTextDirection: true);
23322332

23332333
/// <i class="material-icons-outlined md-36">arrow_right_alt</i> &#x2014; material icon named "arrow right alt" (outlined).
2334-
static const IconData arrow_right_alt_outlined = IconData(0xee8f, fontFamily: 'MaterialIcons');
2334+
static const IconData arrow_right_alt_outlined = IconData(0xee8f, fontFamily: 'MaterialIcons', matchTextDirection: true);
23352335

23362336
/// <i class="material-icons md-36">arrow_upward</i> &#x2014; material icon named "arrow upward".
23372337
static const IconData arrow_upward = IconData(0xe0a0, fontFamily: 'MaterialIcons');
@@ -12900,16 +12900,16 @@ abstract final class Icons {
1290012900
static const IconData label_important_outline_rounded = IconData(0xf839, fontFamily: 'MaterialIcons');
1290112901

1290212902
/// <i class="material-icons md-36">label_off</i> &#x2014; material icon named "label off".
12903-
static const IconData label_off = IconData(0xe363, fontFamily: 'MaterialIcons');
12903+
static const IconData label_off = IconData(0xe363, fontFamily: 'MaterialIcons', matchTextDirection: true);
1290412904

1290512905
/// <i class="material-icons-sharp md-36">label_off</i> &#x2014; material icon named "label off" (sharp).
12906-
static const IconData label_off_sharp = IconData(0xea5c, fontFamily: 'MaterialIcons');
12906+
static const IconData label_off_sharp = IconData(0xea5c, fontFamily: 'MaterialIcons', matchTextDirection: true);
1290712907

1290812908
/// <i class="material-icons-round md-36">label_off</i> &#x2014; material icon named "label off" (round).
12909-
static const IconData label_off_rounded = IconData(0xf83b, fontFamily: 'MaterialIcons');
12909+
static const IconData label_off_rounded = IconData(0xf83b, fontFamily: 'MaterialIcons', matchTextDirection: true);
1291012910

1291112911
/// <i class="material-icons-outlined md-36">label_off</i> &#x2014; material icon named "label off" (outlined).
12912-
static const IconData label_off_outlined = IconData(0xf14c, fontFamily: 'MaterialIcons');
12912+
static const IconData label_off_outlined = IconData(0xf14c, fontFamily: 'MaterialIcons', matchTextDirection: true);
1291312913

1291412914
/// <i class="material-icons md-36">label_outline</i> &#x2014; material icon named "label outline".
1291512915
static const IconData label_outline = IconData(0xe364, fontFamily: 'MaterialIcons', matchTextDirection: true);
@@ -13362,16 +13362,16 @@ abstract final class Icons {
1336213362
static const IconData list_outlined = IconData(0xf16d, fontFamily: 'MaterialIcons', matchTextDirection: true);
1336313363

1336413364
/// <i class="material-icons md-36">list_alt</i> &#x2014; material icon named "list alt".
13365-
static const IconData list_alt = IconData(0xe385, fontFamily: 'MaterialIcons');
13365+
static const IconData list_alt = IconData(0xe385, fontFamily: 'MaterialIcons', matchTextDirection: true);
1336613366

1336713367
/// <i class="material-icons-sharp md-36">list_alt</i> &#x2014; material icon named "list alt" (sharp).
13368-
static const IconData list_alt_sharp = IconData(0xea7e, fontFamily: 'MaterialIcons');
13368+
static const IconData list_alt_sharp = IconData(0xea7e, fontFamily: 'MaterialIcons', matchTextDirection: true);
1336913369

1337013370
/// <i class="material-icons-round md-36">list_alt</i> &#x2014; material icon named "list alt" (round).
13371-
static const IconData list_alt_rounded = IconData(0xf85d, fontFamily: 'MaterialIcons');
13371+
static const IconData list_alt_rounded = IconData(0xf85d, fontFamily: 'MaterialIcons', matchTextDirection: true);
1337213372

1337313373
/// <i class="material-icons-outlined md-36">list_alt</i> &#x2014; material icon named "list alt" (outlined).
13374-
static const IconData list_alt_outlined = IconData(0xf16c, fontFamily: 'MaterialIcons');
13374+
static const IconData list_alt_outlined = IconData(0xf16c, fontFamily: 'MaterialIcons', matchTextDirection: true);
1337513375

1337613376
/// <i class="material-icons md-36">live_help</i> &#x2014; material icon named "live help".
1337713377
static const IconData live_help = IconData(0xe386, fontFamily: 'MaterialIcons', matchTextDirection: true);
@@ -16224,16 +16224,16 @@ abstract final class Icons {
1622416224
static const IconData note_add_outlined = IconData(0xf22e, fontFamily: 'MaterialIcons');
1622516225

1622616226
/// <i class="material-icons md-36">note_alt</i> &#x2014; material icon named "note alt".
16227-
static const IconData note_alt = IconData(0xe44b, fontFamily: 'MaterialIcons');
16227+
static const IconData note_alt = IconData(0xe44b, fontFamily: 'MaterialIcons', matchTextDirection: true);
1622816228

1622916229
/// <i class="material-icons-sharp md-36">note_alt</i> &#x2014; material icon named "note alt" (sharp).
16230-
static const IconData note_alt_sharp = IconData(0xeb42, fontFamily: 'MaterialIcons');
16230+
static const IconData note_alt_sharp = IconData(0xeb42, fontFamily: 'MaterialIcons', matchTextDirection: true);
1623116231

1623216232
/// <i class="material-icons-round md-36">note_alt</i> &#x2014; material icon named "note alt" (round).
16233-
static const IconData note_alt_rounded = IconData(0xf0021, fontFamily: 'MaterialIcons');
16233+
static const IconData note_alt_rounded = IconData(0xf0021, fontFamily: 'MaterialIcons', matchTextDirection: true);
1623416234

1623516235
/// <i class="material-icons-outlined md-36">note_alt</i> &#x2014; material icon named "note alt" (outlined).
16236-
static const IconData note_alt_outlined = IconData(0xf22f, fontFamily: 'MaterialIcons');
16236+
static const IconData note_alt_outlined = IconData(0xf22f, fontFamily: 'MaterialIcons', matchTextDirection: true);
1623716237

1623816238
/// <i class="material-icons md-36">notes</i> &#x2014; material icon named "notes".
1623916239
static const IconData notes = IconData(0xe44c, fontFamily: 'MaterialIcons');

0 commit comments

Comments
 (0)