Skip to content

Conversation

@victorsanni
Copy link
Contributor

@victorsanni victorsanni commented May 21, 2024

This PR improves on the look and feel of CupertinoCheckbox to more closely match native iOS/macOS checkboxes. It also adds functionality to resolve the checkbox's fill color in different WidgetStates, configure a mouse cursor and a semantic label, all improving customizability.

This PR also adds examples and tests to CupertinoCheckbox.

Before After
nativefidelitybad-ezgif com-video-to-gif-converter ezgif com-video-to-gif-converter (2)
Native macOS Flutter Before Flutter After
native checkbox Screenshot 2024-06-27 at 10 23 18 AM Screenshot 2024-06-27 at 10 39 22 AM
Light mode Dark mode
light mode dark mode

Part of #148719.

Related PR exploring these changes: #147892

Pre-launch Checklist

If you need help, consider asking for advice on the #hackers-new channel on Discord.

@github-actions github-actions bot added framework flutter/packages/flutter repository. See also f: labels. f: material design flutter/packages/flutter/material repository. f: cupertino flutter/packages/flutter/cupertino repository d: api docs Issues with https://api.flutter.dev/ d: examples Sample code and demos labels May 21, 2024
@victorsanni victorsanni marked this pull request as ready for review May 21, 2024 21:34
Copy link
Contributor

@MitchellGoodwin MitchellGoodwin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. With one question about shadows.

],
);
final Paint gradientPaint = Paint()
..shader = topEdgeGradient.createShader(shadowRect);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we add a way to customize the shadow in someway? Either turn it off completely with a bool or let them provide their own shadow? It doesn't look like this shadow could be removed if wanted.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am exploring passing a LinearGradient as a parameter to CupertinoCheckbox to be used in place of topEdgeGradient. Is that a good idea, considering shadowRect is independent of topEdgeGradient (and used alongside it in drawing the shadow)? Is there a better way to do this (callbacks, etc) or should I just keep it simple and use a bool?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've been thinking about this more. I think we don't want to expose too complicated of a parameter, because it gets messy when if we think about the Material check box. It raises the question of whether we should add the equivalent to Material. But we don't provide shadow properties a lot because we generally encourage designing through composability. So we give them an easy way to remove the shadow, and if they want a different one, they wrap the widget with their own shadow. A bool could work, but maybe it would be more elegant to provide a shadowColor? And they could hide the shadow by making it transparent?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I have seen shadowColor in the material library. I think it is a pretty common pattern there 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On further inspection I've found that the shadow in native macOS checkboxes are even smaller and less-layered than previously thought. Considering its relatively minimal visual (and functional) effect, and the complexity of an additional parameter (without a Material equivalent, to boot), it might be worth it to consider sacrificing native fidelity for an easier to use, Material-compatible API in this instance. @MitchellGoodwin @Piinks

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm fine without a shadow. They can wrap them with a shadow if they want one.

@victorsanni victorsanni requested a review from justinmc May 22, 2024 20:14
Copy link
Contributor

@justinmc justinmc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One architecture idea: What if there was a RawCheckbox in the widgets library that accepted the painter as a parameter? Then Checkbox and CupertinoCheckbox just wrap that. That may also eliminate a bunch of duplicate code and tests.

One big adaptivity question: Should we be trying to make Cupertino widgets customizable in the same way that Material widgets are? Is this exposing us to more maintenance burden?

Like we talked about with @Piinks, I'd be interested to see a feature comparison between this approach and your original PR.

required this.onChanged,
this.mouseCursor,
this.activeColor,
this.inactiveColor,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checkbox has no inactiveColor. Does it do that with MaterialStateProperty? Anything we can do to align them?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, Checkbox does that with MaterialStateProperty. My guess is Checkbox and CupertinoCheckbox's API's were designed before MaterialStateProperty could configure fillColor in both active and inactive states, and so activeColor and inactiveColor aren't needed anymore in both Checkbox and CupertinoCheckbox. Both parameters could (and probably should) be removed, but wouldn't that break users?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It could be breaking, but we typically will deprecate and maintain backwards compatibility for a while so folks can take the time to migrate to the new API. Since CupertinoSwitch uses the same active/inactive parameters, I think this is OK. @MitchellGoodwin had some really good thoughts on how to evaluate when we do or don't use WSP here: #149465 (comment)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently inactiveColor only changes the border color when the checkbox is unselected. Which the changes to shape in this PR make that a little redundant. I think inactiveColor should be deprecated, because now it just doesn't do much. There's an argument to deprecate activeColor as well, but I think it's fine to keep it around for the simple cases.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Filed tracking issue #151252

@justinmc
Copy link
Contributor

To expand on what I mean about a "feature comparison" as I mentioned above in my review, I'm talking about answering questions like these:

  • Direct differences in the parameters list and capabilities.
  • How does Checkbox use Theme? Does CupertinoCheckbox use CupertinoTheme?
  • Checkbox makes use of the Material widget and CupertinoCheckbox does not. What is CupertinoCheckbox missing out on there?
  • If I've developed an Android app in Material first, and I've themed my Checkbox, what is the experience of building a similarly-themed iOS checkbox with this PR vs. with the approach in Make Checkbox adaptive without delegating to CupertinoCheckbox #147892? I imagine it might be easier to get an iOS checkbox with the same styles as the Material one if you're using 147892, but I wonder about the details.
  • Any other possible differences I'm not thinking of.

@QuncCccccc
Copy link
Contributor

QuncCccccc commented May 30, 2024

I can try to answer this question:)

I imagine it might be easier to get an iOS checkbox with the same styles as the Material one if you're using 147892, but I wonder about the details.

This Switch example shows how we can theme iOS Switch from Material Switch:

  1. Create a subclass of Adaptation<T> with SwitchThemeData type, like SwitchThemeAdaptation.
  2. Implement the adapt method in this class and provide SwitchThemeData based on different platforms.
    if we want a similar configuration for both iOS and Material, then probably just to provide the same or similar SwitchThemeData like:
SwitchThemeData adapt(ThemeData theme, SwitchThemeData defaultValue) {
  switch (theme.platform) {
    case TargetPlatform.fuchsia:
    case TargetPlatform.linux:
    case TargetPlatform.windows:
    case TargetPlatform.macOS:
      return defaultValue;
    case TargetPlatform.android:
    case TargetPlatform.iOS:
      return SwitchThemeData(
        // some customization that we want.
      );
  }
}
  1. the last step would be adding this SwitchThemeAdaptation to ThemeData.adaptations which takes a list of adaptation, so we can add as many adaptive widget theme as we want:)

To get the adaptive widget theme:

  1. Use Theme.of(context).getAdaptation<T>, like the switchAdaptation
  2. Get widget theme by calling Adaptation<T>.adapt() method, like here.

@victorsanni
Copy link
Contributor Author

victorsanni commented May 30, 2024

Direct differences in the parameters list and capabilities.

CupertinoCheckbox as in this PR only adds new extra parameters without modifying any previous parameters. The new parameters added are: mouseCursor, fillColor, isError, and semanticLabel, with the same capabilities as their material counterparts, and shadowColor which is specific to CupertinoCheckbox.

How does Checkbox use Theme? Does CupertinoCheckbox use CupertinoTheme?

As far as I see, Checkbox only uses Theme to:

  • Check the target platform
  • Check if Material 3 should be used.

However, Checkbox gets theme properties from CheckboxThemeData. When configuring the material checkbox’s properties, the order of precedence is:

      widget.property > CheckboxThemeData.property > defaults

CupertinoThemeData does not have component themes, so this order of precedence with CupertinoCheckbox is just

       widget.property > defaults

CupertinoCheckbox doesn't use CupertinoTheme, but CupertinoSwitch does, for example to set the track color to theme.primaryColor. CupertinoThemeData is very limited though.

Checkbox makes use of the Material widget and >CupertinoCheckbox does not. What is CupertinoCheckbox missing out on there?

I might be misunderstanding this question, but I think it more that Checkbox requires one of its ancestors to be a Material widget, not that it itself uses the Material widget. When I removed the line assert(debugCheckHasMaterial(context));
and ran a cupertino app with Checkbox having no material ancestor, I didn’t run into any errors/change in behavior.

If I've developed an Android app in Material first, and I've themed my Checkbox, what is the experience of building a similarly-themed iOS checkbox with this PR vs. with the approach in Make Checkbox adaptive without delegating to CupertinoCheckbox #147892? I imagine it might be easier to get an iOS checkbox with the same styles as the Material one if you're using 147892, but I wonder about the details.

Does theming the checkbox here mean:
a) creating an app-wide CheckboxTheme by setting CheckboxThemeData values, or
b) Individually configuring some checkbox by setting parameters?

For a), CupertinoCheckbox as in this PR doesn’t provide app-wide theming, but using Checkbox.adaptive as in #147892 does as Qun explained above.

For b), both CupertinoCheckbox as in this PR and Checkbox.adaptive as in #147892 have all the non-material-design-specific parameters as Checkbox, so the developer would only need to remove the non-material-design-specific parameters (hoverColor, overlayColor, splashRadius, materialTapTargetSize, and visualDensity).

Copy link
Contributor

@Piinks Piinks left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This LGTM to me as well modulo a doc nit :)

Some of the outstanding questions were around theming.. we talked offline about this a bit on Monday. Since CupertinoCheckbox does not currently use a theme, we won't be adding it here right now. It's ok, and probably best, for us to make these changes incrementally. This PR brings the checkbox up to date with full fidelity and some better alignment with material. After this PR, we could see if we want to incorporate CupertinoTheme in some way.

As far as cross library theming goes, we aren't diving too deeply into that yet. Having high fidelity native looking iOS widgets is our first priority, and in the meantime we are gathering more information from users to help inform how we can improve the adaptive angle. 👍

],
);
final Paint gradientPaint = Paint()
..shader = topEdgeGradient.createShader(shadowRect);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I have seen shadowColor in the material library. I think it is a pretty common pattern there 👍

required this.onChanged,
this.mouseCursor,
this.activeColor,
this.inactiveColor,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It could be breaking, but we typically will deprecate and maintain backwards compatibility for a while so folks can take the time to migrate to the new API. Since CupertinoSwitch uses the same active/inactive parameters, I think this is OK. @MitchellGoodwin had some really good thoughts on how to evaluate when we do or don't use WSP here: #149465 (comment)

@github-actions github-actions bot removed c: contributor-productivity Team-specific productivity, code health, technical debt. platform-ios iOS applications specifically tool Affects the "flutter" command-line tool. See also t: labels. engine flutter/engine related. See also e: labels. a: animation Animation APIs a: accessibility Accessibility, e.g. VoiceOver or TalkBack. (aka a11y) f: scrolling Viewports, list views, slivers, etc. f: routes Navigator, Router, and related APIs. f: gestures flutter/packages/flutter/gestures repository. a: desktop Running on desktop f: focus Focus traversal, gaining or losing focus f: integration_test The flutter/packages/integration_test plugin team-release d: docs/ flutter/flutter/docs, for contributors labels Jul 8, 2024
@victorsanni victorsanni removed the request for review from christopherfujino July 8, 2024 22:52
@github-actions github-actions bot removed the f: material design flutter/packages/flutter/material repository. label Jul 8, 2024
@victorsanni victorsanni marked this pull request as draft July 8, 2024 23:26
@flutter-dashboard
Copy link

This pull request has been changed to a draft. The currently pending flutter-gold status will not be able to resolve until a new commit is pushed or the change is marked ready for review again.

For more guidance, visit Writing a golden file test for package:flutter.

Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing.

@victorsanni
Copy link
Contributor Author

victorsanni commented Jul 9, 2024

Closing due to a bad merge leading to pollution with unrelated commits. New PR is #151441.

@victorsanni victorsanni closed this Jul 9, 2024
auto-submit bot pushed a commit that referenced this pull request Jul 12, 2024
Brings over the changes from `Switch.adaptive` into `CupertinoSwitch`.

This change adds the following `Switch` parameters to `CupertinoSwitch`:
`inactiveThumbColor,` `activeThumbImage`, `onActiveThumbImageError`, `inactiveThumbImage`, `onInactiveThumbImageError`, `trackOutlineColor`, `trackOutlineWidth`, `thumbIcon`, `mouseCursor`. 

The following `Switch` parameters are ignored:

* `activeTrackColor`: because `activeColor` has the same function.
* `inactiveTrackColor`: because `trackColor` has the same function.
* `materialTapTargetSize`: because it is only applicable in `Material`.
* `hoverColor`, `overlayColor`, `splashRadius`: because these parameters configure the radial reaction overlay in `Material`, so are not applicable here.

The following `CupertinoSwitch` parameters which are absent from `Switch.adaptive` are retained:

* `onLabelColor`, 
* `offLabelColor`, 
* `applyTheme`

`trackColor` and `thumbColor` are of type `WidgetStateProperty` in Material `Switch`, but are currently of type `Color` in `CupertinoSwitch`. For backwards compatibility, both parameters are kept as `Color`s, but can be resolved in different `WidgetState`s using `WidgetStateColor.resolve()`.

This PR does not apply any fidelity updates to `CupertinoSwitch`.

Part of #149275

Related PRs: #130425 #148804
@victorsanni victorsanni deleted the improve-cupertino-checkbox-fidelity branch July 13, 2024 00:15
victorsanni added a commit that referenced this pull request Jul 31, 2024
**NOTE: Previous [PR](#148804)
was closed because of a bad merge leading to pollution with unrelated
commits.**

This PR improves on the look and feel of `CupertinoCheckbox` to more
closely match native iOS/macOS checkboxes.

Adds the following updates from a native macOS checkbox:
* Fill color of an unchecked checkbox is a linear gradient that goes
from darker at the top to lighter at the bottom in dark mode
* Size of box reduced from 18.0 to 14.0
* Stroke width of check reduced from 2.5 to 2.0
* Border color changed from solid black to gray black in light mode and
a transparent gray in dark mode
* In light mode, checkbox darkens when pressed
* In dark mode, checkbox lightens when pressed
* Default blue color of a checked checkbox is darker in dark mode

### Light Mode

| Native macOS | Flutter Before | Flutter After |
| ----------- | ----------- | ----------- |
| <img width="63" alt="native checkbox"
src="https://github.com/flutter/flutter/assets/77553258/d57d4c78-2e67-49fb-9491-a5acee3782a7">
| <img width="66" alt="Screenshot 2024-06-27 at 10 23 18 AM"
src="https://github.com/flutter/flutter/assets/77553258/31c913ff-d36f-4eb5-b737-3a9117bd7eff">
| <img width="66" alt="Screenshot 2024-06-27 at 10 39 22 AM"
src="https://github.com/flutter/flutter/assets/77553258/ace8ef29-efae-4049-8f78-13fd39851947">
|

### Dark Mode - Checked

| Native macOS | Flutter Before | Flutter After |
| ----------- | ----------- | ----------- |
| <img width="22" alt="native light"
src="https://github.com/user-attachments/assets/fc52d5e1-7ab0-4a5d-b0fa-5b5bee3ed39d">
| <img width="22" alt="flutter before light"
src="https://github.com/user-attachments/assets/16e033a1-d2dd-4fb2-a5a5-f730c5f7cdc7">
| <img width="22" alt="flutter after light"
src="https://github.com/user-attachments/assets/8c0cff99-930e-4f5e-8540-e64294c1b4fa">
|

### Dark Mode - Unchecked
| Native macOS | Flutter Before | Flutter After |
| ----------- | ----------- | ----------- |
| <img width="22" alt="native dark mode"
src="https://github.com/user-attachments/assets/333280a0-85db-4464-9663-03ef7eafc270">
| <img width="22" alt="flutter before dark mode"
src="https://github.com/user-attachments/assets/a46e01ec-0d0b-4bb7-8d08-4b2723424a12">
| <img width="22" alt="flutter dark mode"
src="https://github.com/user-attachments/assets/a70ae4ad-f1ad-4441-a416-350cbdc32679">
|

### Light Mode - Disabled

| Native macOS | Flutter Before | Flutter After |
| --- | --- | --- |
| <img width="121" alt="native disabled checkbox"
src="https://github.com/user-attachments/assets/ed050d14-efec-49dd-82b6-1e7ed7fa99f9">
| <img width="136" alt="flutter b4 disabled checkbox"
src="https://github.com/user-attachments/assets/564918cf-f936-448d-b975-7bf9248bbf35">
| <img width="156" alt="flutter disabled checkbox"
src="https://github.com/user-attachments/assets/82f672a7-12e8-469c-99af-9f94c959df8f">
|

### Dark Mode - Disabled

| Native macOS | Flutter Before | Flutter After |
| --- | --- | --- |
| <img width="110" alt="disabled dark checkbox native"
src="https://github.com/user-attachments/assets/02a43b3f-5619-4b05-9066-2fd43a58c956">
| <img width="136" alt="disabled dark checkbox flutter b4"
src="https://github.com/user-attachments/assets/3a3db322-2002-4808-adc0-b10a7ab42381">
| <img width="140" alt="disabled dark checkbox flutter"
src="https://github.com/user-attachments/assets/cb91955a-8302-4dc7-8050-221fa2a7045f">

Fixes #148719.

Related PR exploring these changes: #147892

## 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] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [ ] 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
[Data Driven Fixes]:
https://github.com/flutter/flutter/wiki/Data-driven-Fixes

---------

Co-authored-by: Kate Lovett <[email protected]>
TytaniumDev pushed a commit to TytaniumDev/flutter that referenced this pull request Aug 7, 2024
**NOTE: Previous [PR](flutter#148804)
was closed because of a bad merge leading to pollution with unrelated
commits.**

This PR improves on the look and feel of `CupertinoCheckbox` to more
closely match native iOS/macOS checkboxes.

Adds the following updates from a native macOS checkbox:
* Fill color of an unchecked checkbox is a linear gradient that goes
from darker at the top to lighter at the bottom in dark mode
* Size of box reduced from 18.0 to 14.0
* Stroke width of check reduced from 2.5 to 2.0
* Border color changed from solid black to gray black in light mode and
a transparent gray in dark mode
* In light mode, checkbox darkens when pressed
* In dark mode, checkbox lightens when pressed
* Default blue color of a checked checkbox is darker in dark mode

### Light Mode

| Native macOS | Flutter Before | Flutter After |
| ----------- | ----------- | ----------- |
| <img width="63" alt="native checkbox"
src="https://github.com/flutter/flutter/assets/77553258/d57d4c78-2e67-49fb-9491-a5acee3782a7">
| <img width="66" alt="Screenshot 2024-06-27 at 10 23 18 AM"
src="https://github.com/flutter/flutter/assets/77553258/31c913ff-d36f-4eb5-b737-3a9117bd7eff">
| <img width="66" alt="Screenshot 2024-06-27 at 10 39 22 AM"
src="https://github.com/flutter/flutter/assets/77553258/ace8ef29-efae-4049-8f78-13fd39851947">
|

### Dark Mode - Checked

| Native macOS | Flutter Before | Flutter After |
| ----------- | ----------- | ----------- |
| <img width="22" alt="native light"
src="https://github.com/user-attachments/assets/fc52d5e1-7ab0-4a5d-b0fa-5b5bee3ed39d">
| <img width="22" alt="flutter before light"
src="https://github.com/user-attachments/assets/16e033a1-d2dd-4fb2-a5a5-f730c5f7cdc7">
| <img width="22" alt="flutter after light"
src="https://github.com/user-attachments/assets/8c0cff99-930e-4f5e-8540-e64294c1b4fa">
|

### Dark Mode - Unchecked
| Native macOS | Flutter Before | Flutter After |
| ----------- | ----------- | ----------- |
| <img width="22" alt="native dark mode"
src="https://github.com/user-attachments/assets/333280a0-85db-4464-9663-03ef7eafc270">
| <img width="22" alt="flutter before dark mode"
src="https://github.com/user-attachments/assets/a46e01ec-0d0b-4bb7-8d08-4b2723424a12">
| <img width="22" alt="flutter dark mode"
src="https://github.com/user-attachments/assets/a70ae4ad-f1ad-4441-a416-350cbdc32679">
|

### Light Mode - Disabled

| Native macOS | Flutter Before | Flutter After |
| --- | --- | --- |
| <img width="121" alt="native disabled checkbox"
src="https://github.com/user-attachments/assets/ed050d14-efec-49dd-82b6-1e7ed7fa99f9">
| <img width="136" alt="flutter b4 disabled checkbox"
src="https://github.com/user-attachments/assets/564918cf-f936-448d-b975-7bf9248bbf35">
| <img width="156" alt="flutter disabled checkbox"
src="https://github.com/user-attachments/assets/82f672a7-12e8-469c-99af-9f94c959df8f">
|

### Dark Mode - Disabled

| Native macOS | Flutter Before | Flutter After |
| --- | --- | --- |
| <img width="110" alt="disabled dark checkbox native"
src="https://github.com/user-attachments/assets/02a43b3f-5619-4b05-9066-2fd43a58c956">
| <img width="136" alt="disabled dark checkbox flutter b4"
src="https://github.com/user-attachments/assets/3a3db322-2002-4808-adc0-b10a7ab42381">
| <img width="140" alt="disabled dark checkbox flutter"
src="https://github.com/user-attachments/assets/cb91955a-8302-4dc7-8050-221fa2a7045f">

Fixes flutter#148719.

Related PR exploring these changes: flutter#147892

## 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] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [ ] 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
[Data Driven Fixes]:
https://github.com/flutter/flutter/wiki/Data-driven-Fixes

---------

Co-authored-by: Kate Lovett <[email protected]>
Buchimi pushed a commit to Buchimi/flutter that referenced this pull request Sep 2, 2024
**NOTE: Previous [PR](flutter#148804)
was closed because of a bad merge leading to pollution with unrelated
commits.**

This PR improves on the look and feel of `CupertinoCheckbox` to more
closely match native iOS/macOS checkboxes.

Adds the following updates from a native macOS checkbox:
* Fill color of an unchecked checkbox is a linear gradient that goes
from darker at the top to lighter at the bottom in dark mode
* Size of box reduced from 18.0 to 14.0
* Stroke width of check reduced from 2.5 to 2.0
* Border color changed from solid black to gray black in light mode and
a transparent gray in dark mode
* In light mode, checkbox darkens when pressed
* In dark mode, checkbox lightens when pressed
* Default blue color of a checked checkbox is darker in dark mode

### Light Mode

| Native macOS | Flutter Before | Flutter After |
| ----------- | ----------- | ----------- |
| <img width="63" alt="native checkbox"
src="https://github.com/flutter/flutter/assets/77553258/d57d4c78-2e67-49fb-9491-a5acee3782a7">
| <img width="66" alt="Screenshot 2024-06-27 at 10 23 18 AM"
src="https://github.com/flutter/flutter/assets/77553258/31c913ff-d36f-4eb5-b737-3a9117bd7eff">
| <img width="66" alt="Screenshot 2024-06-27 at 10 39 22 AM"
src="https://github.com/flutter/flutter/assets/77553258/ace8ef29-efae-4049-8f78-13fd39851947">
|

### Dark Mode - Checked

| Native macOS | Flutter Before | Flutter After |
| ----------- | ----------- | ----------- |
| <img width="22" alt="native light"
src="https://github.com/user-attachments/assets/fc52d5e1-7ab0-4a5d-b0fa-5b5bee3ed39d">
| <img width="22" alt="flutter before light"
src="https://github.com/user-attachments/assets/16e033a1-d2dd-4fb2-a5a5-f730c5f7cdc7">
| <img width="22" alt="flutter after light"
src="https://github.com/user-attachments/assets/8c0cff99-930e-4f5e-8540-e64294c1b4fa">
|

### Dark Mode - Unchecked
| Native macOS | Flutter Before | Flutter After |
| ----------- | ----------- | ----------- |
| <img width="22" alt="native dark mode"
src="https://github.com/user-attachments/assets/333280a0-85db-4464-9663-03ef7eafc270">
| <img width="22" alt="flutter before dark mode"
src="https://github.com/user-attachments/assets/a46e01ec-0d0b-4bb7-8d08-4b2723424a12">
| <img width="22" alt="flutter dark mode"
src="https://github.com/user-attachments/assets/a70ae4ad-f1ad-4441-a416-350cbdc32679">
|

### Light Mode - Disabled

| Native macOS | Flutter Before | Flutter After |
| --- | --- | --- |
| <img width="121" alt="native disabled checkbox"
src="https://github.com/user-attachments/assets/ed050d14-efec-49dd-82b6-1e7ed7fa99f9">
| <img width="136" alt="flutter b4 disabled checkbox"
src="https://github.com/user-attachments/assets/564918cf-f936-448d-b975-7bf9248bbf35">
| <img width="156" alt="flutter disabled checkbox"
src="https://github.com/user-attachments/assets/82f672a7-12e8-469c-99af-9f94c959df8f">
|

### Dark Mode - Disabled

| Native macOS | Flutter Before | Flutter After |
| --- | --- | --- |
| <img width="110" alt="disabled dark checkbox native"
src="https://github.com/user-attachments/assets/02a43b3f-5619-4b05-9066-2fd43a58c956">
| <img width="136" alt="disabled dark checkbox flutter b4"
src="https://github.com/user-attachments/assets/3a3db322-2002-4808-adc0-b10a7ab42381">
| <img width="140" alt="disabled dark checkbox flutter"
src="https://github.com/user-attachments/assets/cb91955a-8302-4dc7-8050-221fa2a7045f">

Fixes flutter#148719.

Related PR exploring these changes: flutter#147892

## 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] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [ ] 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
[Data Driven Fixes]:
https://github.com/flutter/flutter/wiki/Data-driven-Fixes

---------

Co-authored-by: Kate Lovett <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

d: api docs Issues with https://api.flutter.dev/ d: examples Sample code and demos f: cupertino flutter/packages/flutter/cupertino repository framework flutter/packages/flutter repository. See also f: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.