-
Notifications
You must be signed in to change notification settings - Fork 259
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
Blurred Dots Background #4685
Blurred Dots Background #4685
Conversation
73f6f33
to
17ef344
Compare
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.
My feedback is a few fixups regarding theming configuration and mainly a concern about configurability for white-labels. I think we have the opportunity to consider infrastructure here to render different background components whether some complex SVG, a simple background image, or a gradient of some kind. All of these requirements can be handled in a custom component which may be "used" throughout the app and configured for each white-label configuration.
/** | ||
* We are simulating the blur using a radial gradient, | ||
* since it's cheaper and looks better. | ||
* | ||
* To do this, we slice a ring off the outside of each dot and | ||
* replace it with the gradient. The sliced-off ring has a width of blurR, | ||
* and the gradient ring has a width of 2 * blurR. | ||
* This means the circle radius will expand by blurR. | ||
* | ||
* If the circle is smaller than blurR, | ||
* then we can't slice off a big enough ring, | ||
* so we reduce the opacity towards 0 to compensate. | ||
*/ |
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.
I have a vague idea on how this works. Looking closely it does look like its the correct implementation for this description, but I have to double check math more to verify.
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.
To do a blur mathematically, imagine a circle of radius blurRadius
, which slides over the scene from left to right. The average color inside the circle becomes the new color for the pixel at the very center of the circle. This imaginary circle is called the "filter kernel" in signal processing lingo.
As it slides, the filter kernel first begins to intersect the background dot at a distance of blurRadius
away. As it continues to slide through, the ratio of dot color to background color increases, until the filter kernel is fully inside the background dot. This happens when the kernel is blurRadius
in. So, the total distance from 0% to 100% opacity is 2 * blurRadius
.
The "filter kernel" corresponds to the camera's iris in physical reality, where a single point on the film receives color from the entire circular lens. If the camera is out-of-focus, this circle will be projected out into space and perform the averaging operation I just described.
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 seems like something that could be better understood by a video. Though, thanks for clarifying as it does help me better understand blur algorithms.
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.
Also this shouldn't have been removed.
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.
Overall I see that the implementation works but I'm concerned that there was a lot of custom engineering work done for a specific design. A blurview on top of flat dots would have allowed more flexibility in the future should we ever want squares, triangles, or even images under the blurview. As is we'd have to write very specific code once again for other implementations.
// Settings for when using ScrollView | ||
keyboardShouldPersistTaps?: 'always' | 'never' | 'handled' | ||
// Adjusts the blurred dots background: | ||
accentColor?: string |
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.
Maybe this could be more general like a dotColorOverride: Array<string | undefined>
which can override any of the dot colors.
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.
Note the the design from @madpaiement has the bottom left dot removed completely and having the override array would allow this
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.
I did it by adding a property to the theme, since the app shouldn't care how many dots the theme wants or where they are positioned.
@@ -121,10 +121,16 @@ export const edgeDark: Theme = { | |||
loadingIcon: palette.edgeMint, | |||
|
|||
// Background | |||
// backgroundGradientColors: [palette.navyAqua, palette.navyAquaDarker], // For vertical gradient | |||
backgroundGradientColors: [palette.darkestNavy, palette.darkAqua], |
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.
We still need a backgroundGradient for the TxList Scene per design.
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.
I don't see the backgroundGradient reinstated from the fixup commits.
17ef344
to
5fb13ec
Compare
@@ -3,6 +3,9 @@ import { asNumber, asObject } from 'cleaners' | |||
export type ImageProp = { uri: string } | number | |||
|
|||
export interface ThemeDot { | |||
// We the dot color with the accent color, we want to keep the dot color, | |||
// or drop the dot: | |||
accent?: 'keep' | 'drop' |
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.
Hmm. I won't fight back hard on this but this is another bizarre api at is SO specific to our current design. I would have still preferred a simple accent array that allows any of the dots to be changed programmatically after the Theme is applied.
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.
I do agree, but for the sake of time let's roll with it. Also worth noting, the verbiage in the comment is a little word-jumbled.
@@ -249,6 +251,7 @@ function TransactionListComponent(props: Props) { | |||
<SceneWrapper accentColor={iconColor} hasNotifications hasTabs> | |||
{({ insetStyles }) => ( | |||
<> | |||
<LinearGradient colors={[backgroundGradientColor, '#00000000']} start={{ x: 0, y: 0 }} end={{ x: 0, y: 1 }} style={StyleSheet.absoluteFill} /> |
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.
Hard coding black in to the gradient will not allow us to do light mode or whitelabels with different colors. Due to time constraints, I won't push back on this today but I'll create a task to add the gradient color to the theme. Ideally something like
theme.txListBackgroundGradient
and theme.txDetailsBackgroundGradient
which would have the full gradient capabilities of arbitrary direction and colors.
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.
Agree that this color should be in the theme now that I think about it. I messed up on my PR prior and should have invented a new theme field for it. Good idea to create break away task.
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.
Oh, good catch! We should use theme.background.color
.
@samholmes I added my comments but nothing that needs fixing in the PR. I'll let you give it the final approval |
) | ||
} | ||
|
||
const Container = styled(View)({ | ||
const ViewContainer = styled(View)({ |
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.
I'd say it's actual name (Container) is a higher priority then the underlying component type it extends. The reasoning here is that unique names are quicker to read rather than all the JSX prefixed with very common prefixes (ViewFoo, ViewBar, TextBaz, TextInputBoz versus FooView, BarView, BazText, BozTextInput). I'll leave it up to you if you want to make any changes, so this is just optional feedback/thoughts and generally my opinion. Perhaps we can discuss a convention with the team for naming things (2nd hardest problem in CS).
@@ -249,6 +251,7 @@ function TransactionListComponent(props: Props) { | |||
<SceneWrapper accentColor={iconColor} hasNotifications hasTabs> | |||
{({ insetStyles }) => ( | |||
<> | |||
<LinearGradient colors={[backgroundGradientColor, '#00000000']} start={{ x: 0, y: 0 }} end={{ x: 0, y: 1 }} style={StyleSheet.absoluteFill} /> |
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.
Agree that this color should be in the theme now that I think about it. I messed up on my PR prior and should have invented a new theme field for it. Good idea to create break away task.
@@ -3,6 +3,9 @@ import { asNumber, asObject } from 'cleaners' | |||
export type ImageProp = { uri: string } | number | |||
|
|||
export interface ThemeDot { | |||
// We the dot color with the accent color, we want to keep the dot color, | |||
// or drop the dot: | |||
accent?: 'keep' | 'drop' |
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.
I do agree, but for the sake of time let's roll with it. Also worth noting, the verbiage in the comment is a little word-jumbled.
/** | ||
* We are simulating the blur using a radial gradient, | ||
* since it's cheaper and looks better. | ||
* | ||
* To do this, we slice a ring off the outside of each dot and | ||
* replace it with the gradient. The sliced-off ring has a width of blurR, | ||
* and the gradient ring has a width of 2 * blurR. | ||
* This means the circle radius will expand by blurR. | ||
* | ||
* If the circle is smaller than blurR, | ||
* then we can't slice off a big enough ring, | ||
* so we reduce the opacity towards 0 to compensate. | ||
*/ |
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 seems like something that could be better understood by a video. Though, thanks for clarifying as it does help me better understand blur algorithms.
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.
Approved with some optional feedback
438fc35
to
44fe524
Compare
/autosquash |
7c310a8
to
017d659
Compare
CHANGELOG
Does this branch warrant an entry to the CHANGELOG?
Dependencies
noneRequirements
If you have made any visual changes to the GUI. Make sure you have: