-
Notifications
You must be signed in to change notification settings - Fork 314
ui: Set letter spacing to 1% in buttons #635
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
03d16b8
to
562bd17
Compare
562bd17
to
3f822eb
Compare
(There were some tests failing, and I also caught a bug when resolving those; pushed fixes.) |
3f822eb
to
f7669ea
Compare
Do reaction chips count as buttons? We can give 1% letter spacing to their label text (which shows either a number or the reacting users' names); that wouldn't be hard. code--- lib/widgets/emoji_reaction.dart
+++ lib/widgets/emoji_reaction.dart
@@ -1,5 +1,6 @@
import 'package:flutter/foundation.dart';
+++ lib/widgets/emoji_reaction.dart
@@ -1,5 +1,6 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
+import 'package:zulip/widgets/theme.dart';
import '../api/model/model.dart';
import '../api/route/messages.dart';
@@ -153,6 +154,7 @@ class ReactionChip extends StatelessWidget {
// which we learn about especially late).
final maxLabelWidth = (maxRowWidth - 6) * 0.75; // 6 is padding
+ final labelScaler = _labelTextScalerClamped(context);
return Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
@@ -168,9 +170,13 @@ class ReactionChip extends StatelessWidget {
constraints: BoxConstraints(maxWidth: maxLabelWidth),
child: Text(
textWidthBasis: TextWidthBasis.longestLine,
- textScaler: _labelTextScalerClamped(context),
+ textScaler: labelScaler,
style: TextStyle(
fontSize: (14 * 0.90),
+ letterSpacing: proportionalLetterSpacing(context,
+ kButtonTextLetterSpacingProportion,
+ baseFontSize: (14 * 0.90),
+ textScaler: labelScaler),
height: 13 / (14 * 0.90),
color: labelColor,
).merge(weightVariableTextStyle(context, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @chrisbobbe! Comments below.
lib/widgets/app.dart
Outdated
theme: theme, | ||
theme: outerThemeData(context), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The commit message says:
theme [nfc]: Pull `outerThemeData` out from app.dart to new theme.dart file
but this makes another change too: it computes this ThemeData from within the builder callback for GlobalStoreWidget.child
. Is that intended?
If the method computing this theme data isn't going to be trying to use the store, then it's probably cleanest to keep the computation outside there, with e.g. final theme = outerThemeData(context);
at the top of the build method. That way it's clear we compute it once eagerly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed; thanks for noticing this!
lib/widgets/theme.dart
Outdated
elevatedButtonTheme: ElevatedButtonThemeData( style: _commonButtonStyle(context)), | ||
filledButtonTheme: FilledButtonThemeData( style: _commonButtonStyle(context)), | ||
iconButtonTheme: IconButtonThemeData( style: _commonButtonStyle(context)), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems cleanest to factor this common style out as a local — that way we only compute it once.
lib/widgets/theme.dart
Outdated
); | ||
} | ||
|
||
double kButtonTextLetterSpacingProportion = 0.01; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
double kButtonTextLetterSpacingProportion = 0.01; | |
const kButtonTextLetterSpacingProportion = 0.01; |
lib/widgets/theme.dart
Outdated
|
||
import 'text.dart'; | ||
|
||
ThemeData outerThemeData(BuildContext context) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a coherent description we can give for what the meaning of this "outer ThemeData" is?
It seems like it's basically an intermediate step in the calculation of the "inner ThemeData", which is the theme data we actually want to use in the app.
In that case, can we have one function that just computes the desired ThemeData start to finish, from a single BuildContext? I think that'd make it easier to reason about how the caller should use the function. That function could even have this intermediate step as a ThemeData local variable, if that's helpful.
test/widgets/autocomplete_test.dart
Outdated
child: MessageListPage( | ||
narrow: DmNarrow( | ||
allRecipientIds: [eg.selfUser.userId, eg.otherUser.userId], | ||
selfUserId: eg.selfUser.userId, | ||
)))))); | ||
await tester.pumpWidget(const ZulipApp()); | ||
await tester.pump(); | ||
final navigator = await ZulipApp.navigator; | ||
navigator.push(MessageListPage.buildRoute(accountId: eg.selfAccount.id, | ||
narrow: DmNarrow( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These rearrangements of existing tests are probably clearest as a separate prep commit.
test/widgets/autocomplete_test.dart
Outdated
))); | ||
|
||
// global store, per-account store, and message list get loaded | ||
await tester.pumpAndSettle(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment is no longer accurate. Perhaps just cut it:
))); | |
// global store, per-account store, and message list get loaded | |
await tester.pumpAndSettle(); | |
))); | |
await tester.pumpAndSettle(); |
And perhaps it can be reduced to just a pump
?
lib/widgets/message_list.dart
Outdated
// Restate [FilledButton]'s default… | ||
themeData.textTheme.labelLarge!.merge(filledButtonThemeTextStyle) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Huh.
Does this mean we could just set .textTheme.labelLarge
on our main ThemeData, and skip reaching into all the individual button styles? That seems like it'd be cleaner.
In principle that has a slightly broader effect than specified in #548, in that it affects any other Material widgets that use the labelLarge
text style. But fundamentally those are widgets that the Material designers intended to have a similar text style to that of buttons (even though they're not called "buttons"), so it's likely that that'll be the right answer anyway.
If we end up with such a widget where Vlad wants a different spacing, we can address that then… and I think it's fairly likely that in that case he'd want something that wasn't the Material widget in any event.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a good idea! Done.
@@ -109,37 +109,6 @@ class _ZulipAppState extends State<ZulipApp> with WidgetsBindingObserver { | |||
|
|||
@override | |||
Widget build(BuildContext context) { | |||
final theme = ThemeData( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool, good to get this pulled out of ZulipApp
.
f7669ea
to
71949f1
Compare
Thanks for the review! Revision pushed, with the simpler approach that you outlined in #635 (comment) and that we talked about in the office. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! This all looks good; just small comments below.
(I'll review #629 separately, but it also looks good modulo small comments.)
test/widgets/theme_test.dart
Outdated
return Builder(builder: (context) => | ||
buttonBuilder(context, buttonText)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return Builder(builder: (context) => | |
buttonBuilder(context, buttonText)); | |
return buttonBuilder(context, buttonText); |
This would have the same effect, right? It doesn't seem like this build context is effectively any different from its parent.
test/widgets/theme_test.dart
Outdated
double? expectedFontSize; | ||
double? expectedLetterSpacing; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can tighten up expectations here slightly:
double? expectedFontSize; | |
double? expectedLetterSpacing; | |
late final double expectedFontSize; | |
late final double expectedLetterSpacing; |
That way it's clear (and enforced) that these only get set once, and that they always get set before they're read.
test/widgets/theme_test.dart
Outdated
buttonBuilder: (context, text) => ElevatedButton(onPressed: () {}, | ||
child: Text(text))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems like none of these builders actually use the context. So they can be simplified to just widgets (by pulling up the buttonText
constant too):
buttonBuilder: (context, text) => ElevatedButton(onPressed: () {}, | |
child: Text(text))); | |
button: ElevatedButton(onPressed: () {}, child: const Text(buttonText))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah right, cool!
TextTheme.labelLarge is the default label style in all the various Material buttons; see: [ElevatedButton.defaultStyleOf], [FilledButton.defaultStyleOf], [MenuItemButton.defaultStyleOf], [MenuItemButton.defaultStyleOf], [OutlinedButton.defaultStyleOf], `defaults` in [SegmentedButton.build], [TextButton.defaultStyleOf] . Since our buttons are all Material buttons, changing this will effectively "set letter spacing to 1% in buttons", which is zulip#548. (...Actually, I guess there's one kind of button that's not a Material button: reaction chips in the message list. So, adjust those separately, also in this commit.) Greg mentioned, when suggesting this approach, > In principle that has a slightly broader effect than specified in > zulip#548, in that it affects any other Material widgets that use the > `labelLarge` text style. But fundamentally those are widgets that > the Material designers intended to have a similar text style to > that of buttons (even though they're not called "buttons"), so > it's likely that that'll be the right answer anyway. > If we end up with such a widget where Vlad wants a different > spacing, we can address that then… and I think it's fairly likely > that in that case he'd want something that wasn't the Material > widget in any event. Which makes sense and works for me. Fixes: zulip#548
71949f1
to
d882f50
Compare
Thanks! Revision pushed. |
Thanks! LGTM; merging. |
Stacked atop #629. Screenshots coming soon.
Fixes: #548