-
Notifications
You must be signed in to change notification settings - Fork 12
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
MediaQuery.V2 #1659
base: master
Are you sure you want to change the base?
MediaQuery.V2 #1659
Conversation
8a29a88
to
f3fcb5c
Compare
c0b8df8
to
27330e0
Compare
d9f840e
to
b15b534
Compare
@@ -641,56 +643,59 @@ css tooltipStyleOverrides = | |||
Attribute (\config -> { config | tooltipStyleOverrides = config.tooltipStyleOverrides ++ tooltipStyleOverrides }) | |||
|
|||
|
|||
{-| Set some conditional custom styles on the tooltip according to a media query. | |||
-} | |||
responsiveCss : MediaQuery properties -> Attribute msg |
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 chance Tooltip.V3 will behave different (in a bad way) after these changes? Do we need to add a Tooltip.V4?
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.
There are the same potential impacts with regards to ::before { content: "..." }"/
display: none`, but likely not being used anywhere. Still, not opposed to just versioning all of them as a matter of safety.
@@ -1223,115 +1221,103 @@ positionTooltip direction alignment = | |||
ltrPosition = | |||
case alignment of | |||
Start customOffset -> | |||
Css.left customOffset | |||
[ Css.left customOffset, Css.right Css.unset ] |
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.
Why we need to do things slightly different here?
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 change is related to this change, which was made because withViewport
was dropped.
As far as I could tell, that function is explicitly only being used as a workaround for the broken cascading. With that fixed, we can generate CSS for only the breakpoints we need, but we need to make sure that other properties up the cascade (that we aren't already overriding) are unset
.
I'd prefer to not bring withViewport
back, but if we didn't want to make these changes as drastic we could add another combinator to MediaQuery like MediaQuery.narrowMobile |> MediaQuery.and MediaQuery.not MediaQuery.mobile
to target a specific viewport in a more generalized way.
the previous way "not" media queries were handled (e.g. `notMobile` and `notNarrowMobile`, | ||
they were using the `not` keyword which caused a discrepancy between the device types | ||
affected. tl;dr: sometimes `content` and `display` rules affected screenreaders and printers, | ||
sometimes they didn't. In this version, media query rules are _strictly_ screen only). |
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 hints me to want to introduce new versions of all components that depends on MediaQuery.V2 since it's a change in behavior and it might be a blocker for upgrading in monolith if there is some regression.
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'm not opposed 👍🏼 . The differences only apply in specific scenarios like ::before { content: "..."; }
and display: none
, but they are technically UX breaking changes–and very subtle ones at that.
|
||
-} | ||
type MediaQuery properties | ||
= MediaQuery Target (Maybe (List Style)) (Maybe (List Style)) |
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.
= MediaQuery Target (Maybe (List Style)) (Maybe (List Style)) | |
= MediaQuery Target { whenSatisfied : Maybe (List Style), whenUnsatisfied : Maybe (List Style) } |
To reduce the changes of confusion of which is which
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.
good call I like this
|
||
{-| Set styles for users who prefer reduced motion | ||
|
||
Generally, you will want to wrap any use of animations/transitions with |
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.
Should we have a withAnimations = not prefersReducedMotion
for convenience?
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.
probably for this one specifically since that's almost always how it will be used
|
||
1. Use 2 independent calls to `MediaQuery.fromList`, one with your breakpoints and one with your user preferences. | ||
|
||
2. Use the pipeline-style API directly. |
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 benefit from one patter over the other? I would rather have a single api if possible
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.
Pipeline-style API is more flexible and lets us use phantom types for media query constructors–e.g. we can implement offset
and only allow it to be used with breakpoints, since we can't offset a user preference.
The problem arises if you have 2 MediaQuery attribute
with disparate attributes. Consider the following:
MediaQuery.init
|> MediaQuery.on MediaQuery.mobile []
|> MediaQuery.on MediaQuery.prefersReducedMotion []
|> MediaQuery.toStyle
This works, because on
interprets the type of the MediaQuery properties
, does the right thing for that media query type, and returns a normalized ResponsiveStyles
record. Since ResponsiveStyles
is unbound, we can repeat this operation with a bunch of media queries without caring about the phantom types.
Now, consider the List-style API:
MediaQuery.fromList
[ MediaQuery.mobile []
, MediaQuery.prefersReducedMotion []
]
What is the type? MediaQuery { offsettable : () }
? or MediaQuery {}
.
Trick question, the answer is compiler error.
For end-consumers in practice since user preferences and breakpoints can't conflict in the cascade, this doesn't really matter. It will throw a potentially confusing compiler error, but can be resolved by using
[ MediaQuery.fromList [MediaQuery.mobile []]
, MediaQuery.fromList [MediaQuery.prefersReducedMotion []]
It is however an actual problem for any libraries that want to implement this. Consider this line in Tooltip that defines the responsive types on the config.
type alias Tooltip msg =
{ responsiveTooltipStyleOverrides : MediaQuery.ResponsiveStyles }
If you have this implemented/exposed strictly as a list-style API, you're in the same issue as above where you're restricted to media queries that share the same phantom type.
Pros of the list-style API:
- It covers most cases for general consumers that are applying the results directly to some HTML, not making re-usable components.
- It's more consise.
- It better matches existing Nri.Ui behavior*
*I have thoughts about this, given all of the above about the implications for phantom types and using combinators instead of a ton of permutations of attributes, and think broader adoption of this style api may actually be a good thing.
🔧 Modifying a component
Context
This PR is a major refactor/re-architecture of the
MediaQuery
module to use a builder pattern instead of exposingCss.Media.MediaQuery
Motivation
mobile
/notMobile
styles with regards to screen readers and printers.Also:
Css.Media.MediaQuery
, they now acceptNri.Ui.MediaQuery.V2.MediaQuery
.hideTextForMobile
to Button (was pending TODO for next major Button release)doSomethingForMobile
/doSomethingForNotMobile
attributes to trackMediaQuery.ResponsiveStyles
and generate the media query at the last second to ensure auto-ordering benefits are realized.Component completion checklist
nriDescription